Перейти к содержанию
    

xSemaphoreTake() первый раз не получать

Собственно вопрос. Создал семафор при вызове задачи, вошёл в цикл и должен упереться в него пока семафор не будет отдан из прерывания или ещё откуда. Но первый вызов xSemaphoreTake() всегда pdTRUE независимо от того был он дан или нет. Есть ли правильный способ бороться с этим кроме "холостого" взятия семафора сразу после создания до входа в цикл или установкой флагов "первый раз" ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть ли правильный способ бороться с этим кроме "холостого" взятия семафора сразу после создания до входа в цикл или установкой флагов "первый раз" ?

Напишите свой макрос для создания закрытого семафора.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И что он будет делать? Захватывать свежесозданный семафор в первый? Я не уверен что это правильно, поэтому спрашиваю. Или Вы про что-то другое?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И что он будет делать? Захватывать свежесозданный семафор в первый?

Нет, разумеется. Он будет создавать семафор, но не будет затем вызывать xSemaphoreGive, в отличие от "родного" макроса.

#define    xSemaphoreCreateBinaryDisabled()    xQueueCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH )

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И получите в коде холостую последовательность xSemaphoreGive() - xSemaphoreTake(). Красиво?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И получите в коде холостую последовательность xSemaphoreGive() - xSemaphoreTake(). Красиво?

Я ничего не понял, столкнулся с той же проблемой что у автора, объясните поподробней плиз.

#include "stm32l1xx_gpio.h"

#include "stm32l1xx_rcc.h"

#include "stm32l1xx.h"

#include "stm32l1xx_exti.h"

#include "misc.h"

#include "FreeRTOS.h"

#include "task.h"

#include "queue.h"

#include "semphr.h"

#include "croutine.h"

 

xTaskHandle xp;

xTaskHandle xp1;

xSemaphoreHandle xBS;

xSemaphoreHandle xBS1;

static void prvLedBlink( void *pvParameters );

static void prvLedBlink2( void *pvParameters );

 

void vApplicationIdleHook( void ){}

void vApplicationMallocFailedHook( void ){ for( ;; );}

void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName )

{ ( void ) pcTaskName;

( void ) pxTask;

for( ;; );}

void vApplicationTickHook( void ){}

 

void RCC_Configuration(void)

{

SystemInit(); // Сброс по умолчанию

GPIO_DeInit(GPIOA);

GPIO_DeInit(GPIOB);

GPIO_DeInit(GPIOC);

GPIO_DeInit(GPIOD);

GPIO_DeInit(GPIOE);

 

RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB |

RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD |

RCC_AHBPeriph_GPIOE, ENABLE);

 

RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOAEN, ENABLE);

RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIODEN, ENABLE);

}

 

void init_led()

{

GPIO_InitTypeDef PORT;

PORT.GPIO_Pin = (GPIO_Pin_7 | GPIO_Pin_6);

PORT.GPIO_Mode = GPIO_Mode_OUT;

PORT.GPIO_Speed = GPIO_Speed_10MHz;

GPIO_Init( GPIOB , &PORT);

}

 

void init_but()

{

GPIO_InitTypeDef BUTA;

BUTA.GPIO_Pin = GPIO_Pin_0;

BUTA.GPIO_Mode = GPIO_Mode_IN;

BUTA.GPIO_Mode = GPIO_PuPd_NOPULL; // Хардварная кнопка и так подтянута

BUTA.GPIO_Speed = GPIO_Speed_10MHz;

GPIO_Init( GPIOA , &BUTA);

 

GPIO_InitTypeDef BUTD;

BUTD.GPIO_Pin = GPIO_Pin_2;

BUTD.GPIO_Mode = GPIO_Mode_IN;

BUTD.GPIO_Mode = GPIO_PuPd_UP;

BUTD.GPIO_Speed = GPIO_Speed_10MHz;

GPIO_Init( GPIOD , &BUTD);

}

void exiti()

{

__enable_irq ();

RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;

SYSCFG->EXTICR[0]|=SYSCFG_EXTICR1_EXTI0_PA; //линии конфирурируем

SYSCFG->EXTICR[0]|=SYSCFG_EXTICR1_EXTI2_PD;

EXTI->IMR|=EXTI_IMR_MR0; //разрешение прерывания всех Px0

EXTI->IMR|=EXTI_IMR_MR2; //разрешение прерывания всех Px2

EXTI->RTSR|=EXTI_RTSR_TR0; //фронт нарост

EXTI->RTSR|=EXTI_FTSR_TR2; //фронт спад

EXTI->RTSR|=EXTI_RTSR_TR2; //фронт нарост

EXTI->RTSR|=EXTI_FTSR_TR0; //фронт спад

NVIC_EnableIRQ (EXTI0_IRQn); // Разрешаем прерывания

NVIC_EnableIRQ (EXTI2_IRQn); // Разрешаем прерывания

NVIC_SetPriority(EXTI0_IRQn, 3);

NVIC_SetPriority(EXTI2_IRQn, 3);

 

}

void EXTI0_IRQHandler(void)

{

//GPIO_SetBits(GPIOB, GPIO_Pin_6);

EXTI->PR |= EXTI_PR_PR0;//сбросили бит прерывания

GPIO_SetBits(GPIOB, GPIO_Pin_7);

BaseType_t xHigherPriorityTaskWoken;

xHigherPriorityTaskWoken = pdFALSE;

xSemaphoreGiveFromISR(xBS, xHigherPriorityTaskWoken);

if( xHigherPriorityTaskWoken == pdFALSE )

{

portYIELD();

}

 

 

//taskYIELD();

}

void EXTI2_IRQHandler(void)

{

//GPIO_SetBits(GPIOB, GPIO_Pin_7);

portBASE_TYPE xHigherPriorityTaskWoken;

xHigherPriorityTaskWoken = pdFALSE;

xSemaphoreGiveFromISR(xBS, xHigherPriorityTaskWoken);

EXTI->PR |= EXTI_PR_PR2;//сбросили бит прерывания

taskYIELD();

}

void prvLedBlink( void *pvParameters )

{

while(1){

xSemaphoreTake( xBS, portMAX_DELAY );

GPIO_SetBits(GPIOB, GPIO_Pin_6);

 

taskYIELD();

}

 

}

void prvLedBlink2( void *pvParameters )

{

 

while(1){

xSemaphoreTake( xBS1, portMAX_DELAY );

GPIO_SetBits(GPIOB, GPIO_Pin_7);

taskYIELD();

}

}

int main(void)

{

RCC_Configuration();

init_led();

init_but();

exiti();

int i;

 

vSemaphoreCreateBinary(xBS);

vSemaphoreCreateBinary(xBS1);

 

if( xBS != NULL ) {

xTaskCreate(prvLedBlink,"LED",configMINIMAL_STACK_SIZE, NULL, 1, &xp);

}

if( xBS1!= NULL ){

xTaskCreate(prvLedBlink2,"LED2",configMINIMAL_STACK_SIZE, NULL, 1, &xp);

}

xTaskCreate(prvLedBlink2,"LED2",configMINIMAL_STACK_SIZE, NULL, 1, &xp1);

 

vTaskStartScheduler();

 

while(1)

{}

 

}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я ничего не понял, столкнулся с той же проблемой что у автора, объясните поподробней плиз

1) Я ничего не понял, объясните, что у вас за проблема?

2) Вы заметили, что ваше сообщение несколько отличается оформлением от предыдущих?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1) Я ничего не понял, объясните, что у вас за проблема?

2) Вы заметили, что ваше сообщение несколько отличается оформлением от предыдущих?

Проблема аналогична, создаю семафор, в прерывание даю его задаче которая зажигает светодиод, но задача сразу выпонялется, семафор есть без прерыания...

По программе: 2 семафора, 2 прерывания, 2 разных обработчика и задачи но по сути они зеракально копируют друг друга просто зажигают разные светодиоды...

 

ПС. простите за оформление... Я только начал приобщаться к форуму)

 

#include "stm32l1xx_gpio.h"
#include "stm32l1xx_rcc.h"
#include "stm32l1xx.h"
#include "stm32l1xx_exti.h"
#include "misc.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "croutine.h"

xTaskHandle xp;
xTaskHandle xp1;
xSemaphoreHandle xBS;
xSemaphoreHandle xBS1;
static void prvLedBlink( void *pvParameters );
static void prvLedBlink2( void *pvParameters );

void vApplicationIdleHook( void ){}
void vApplicationMallocFailedHook( void ){ for( ;; );}
void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName )
{   ( void ) pcTaskName;
   ( void ) pxTask;
   for( ;; );}
void vApplicationTickHook( void ){}

void RCC_Configuration(void)
{
 SystemInit(); // Сброс по умолчанию
 GPIO_DeInit(GPIOA);
 GPIO_DeInit(GPIOB);
 GPIO_DeInit(GPIOC);
 GPIO_DeInit(GPIOD);
 GPIO_DeInit(GPIOE);

 RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB |
                        RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD |
                        RCC_AHBPeriph_GPIOE, ENABLE);

 RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOAEN, ENABLE);
 RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIODEN, ENABLE);
}

void init_led()
{
GPIO_InitTypeDef PORT;
PORT.GPIO_Pin = (GPIO_Pin_7 | GPIO_Pin_6);
PORT.GPIO_Mode = GPIO_Mode_OUT;
PORT.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init( GPIOB , &PORT);
}

void init_but()
{
GPIO_InitTypeDef BUTA;
BUTA.GPIO_Pin = GPIO_Pin_0;
BUTA.GPIO_Mode = GPIO_Mode_IN;
BUTA.GPIO_Mode = GPIO_PuPd_NOPULL; // Хардварная кнопка и так подтянута
BUTA.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init( GPIOA , &BUTA);

GPIO_InitTypeDef BUTD;
BUTD.GPIO_Pin = GPIO_Pin_2;
BUTD.GPIO_Mode = GPIO_Mode_IN;
BUTD.GPIO_Mode = GPIO_PuPd_UP;
BUTD.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init( GPIOD , &BUTD);
}
void exiti()
{
__enable_irq ();
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
SYSCFG->EXTICR[0]|=SYSCFG_EXTICR1_EXTI0_PA; //линии конфирурируем
SYSCFG->EXTICR[0]|=SYSCFG_EXTICR1_EXTI2_PD;
   EXTI->IMR|=EXTI_IMR_MR0; //разрешение прерывания всех Px0
   EXTI->IMR|=EXTI_IMR_MR2; //разрешение прерывания всех Px2
   EXTI->RTSR|=EXTI_RTSR_TR0; //фронт нарост
   EXTI->RTSR|=EXTI_FTSR_TR2; //фронт спад
   EXTI->RTSR|=EXTI_RTSR_TR2; //фронт нарост
   EXTI->RTSR|=EXTI_FTSR_TR0; //фронт спад
   NVIC_EnableIRQ (EXTI0_IRQn); // Разрешаем прерывания
   NVIC_EnableIRQ (EXTI2_IRQn); // Разрешаем прерывания
   NVIC_SetPriority(EXTI0_IRQn, 3);
   NVIC_SetPriority(EXTI2_IRQn, 3);

}
void EXTI0_IRQHandler(void)
{
//GPIO_SetBits(GPIOB, GPIO_Pin_6);
EXTI->PR |= EXTI_PR_PR0;//сбросили бит прерывания
GPIO_SetBits(GPIOB, GPIO_Pin_7); // Green для проверки произошло ли прерывание
BaseType_t xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(xBS, xHigherPriorityTaskWoken);
if( xHigherPriorityTaskWoken == pdTRUE )
{
	portYIELD();
}


 //taskYIELD();
}
void EXTI2_IRQHandler(void)
{
//GPIO_SetBits(GPIOB, GPIO_Pin_7);
portBASE_TYPE xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
	xSemaphoreGiveFromISR(xBS, xHigherPriorityTaskWoken);
 EXTI->PR |= EXTI_PR_PR2;//сбросили бит прерывания
 taskYIELD();
}
void prvLedBlink( void *pvParameters )
{
portBASE_TYPE xStatus;
while(1){
	xStatus=xSemaphoreTake( xBS, portMAX_DELAY );
	 if (xStatus == pdPASS)
	    {
GPIO_SetBits(GPIOB, GPIO_Pin_6);
	    }
  EXTI->PR |= EXTI_PR_PR0;//сбросили бит прерывания
   taskYIELD();
         }

}
void prvLedBlink2( void *pvParameters )
{

while(1){
	xSemaphoreTake( xBS1, portMAX_DELAY );
	GPIO_SetBits(GPIOB, GPIO_Pin_7);
    taskYIELD();
}
}
int main(void)
{
RCC_Configuration();
init_led();
init_but();
exiti();
int i;

vSemaphoreCreateBinary(xBS);
vSemaphoreCreateBinary(xBS1);

if( xBS != NULL ) {
xTaskCreate(prvLedBlink,"LED",configMINIMAL_STACK_SIZE, NULL, 0, &xp);
                  }

//if( xBS1!= NULL ){
	//xTaskCreate(prvLedBlink2,"LED2",configMINIMAL_STACK_SIZE, NULL, 1, &xp);
      //             }
//xTaskCreate(prvLedBlink2,"LED2",configMINIMAL_STACK_SIZE, NULL, 1, &xp1);

vTaskStartScheduler();

while(1)
{}

}

 

 

 

Проблему решил но считаю что что-то все равно не так как должно быть, я после создания семафора сразу беру его

vSemaphoreCreateBinary(xBS);

vSemaphoreCreateBinary(xBS1);

xSemaphoreTake(xBS, pdFALSE ) ;

xSemaphoreTake(xBS1, pdFALSE ) ;

Ну явно это как то отходит от примеров в книгах...

Изменено пользователем Dele

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так создайте семафор приведенным выше макросом. Не будет лишнего Give-Take.

Немного не понял, как создать таким образом семафор. В queue.h нету такого определения, Coocox выдает:

C:\CooCox\CoIDE\workspace\ledexitl/main.c:148: undefined reference to `SemaphoreCreateBinaryDisabled'

вы меня простите я учусь, ткните меня как это сделать пожалуйста)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Немного не понял, как создать таким образом семафор. В queue.h нету такого определения

Совершенно верно, его там нет. Поэтому добавьте упомянутый #define в любом удобном месте:

#define    xSemaphoreCreateBinaryDisabled()    xQueueCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH )

xSemaphoreHandle S;

int main(void)
{
    S = xSemaphoreCreateBinaryDisabled();
}

Лучше, конечно, в какой-нибудь заголовочный файл.

Изменено пользователем aaarrr

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Совершенно верно, его там нет. Поэтому добавьте упомянутый #define в любом удобном месте:

#define    xSemaphoreCreateBinaryDisabled()    xQueueCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH )

xSemaphoreHandle S;

int main(void)
{
    xSemaphoreCreateBinaryDisabled(S)
}

Лучше, конечно, в какой-нибудь заголовочный файл.

 

Добавил строчку в queue.h

в итоге:

[cc] C:\CooCox\CoIDE\workspace\ledexitl\main.c:148:37: error: macro "xSemaphoreCreateBinaryDisabled" passed 1 arguments, but takes just 0

[cc] xSemaphoreCreateBinaryDisabled(xBS1);

[cc] ^

[cc] C:\CooCox\CoIDE\workspace\ledexitl\main.c:148:2: error: 'xSemaphoreCreateBinaryDisabled' undeclared (first use in this function)

Как то так...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...