Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: xSemaphoreTake() первый раз не получать
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > FreeRTOS
Cosmojam
Собственно вопрос. Создал семафор при вызове задачи, вошёл в цикл и должен упереться в него пока семафор не будет отдан из прерывания или ещё откуда. Но первый вызов xSemaphoreTake() всегда pdTRUE независимо от того был он дан или нет. Есть ли правильный способ бороться с этим кроме "холостого" взятия семафора сразу после создания до входа в цикл или установкой флагов "первый раз" ?
aaarrr
Цитата(Cosmojam @ Feb 10 2012, 17:25) *
Есть ли правильный способ бороться с этим кроме "холостого" взятия семафора сразу после создания до входа в цикл или установкой флагов "первый раз" ?

Напишите свой макрос для создания закрытого семафора.
Cosmojam
И что он будет делать? Захватывать свежесозданный семафор в первый? Я не уверен что это правильно, поэтому спрашиваю. Или Вы про что-то другое?
aaarrr
Цитата(Cosmojam @ Feb 10 2012, 21:36) *
И что он будет делать? Захватывать свежесозданный семафор в первый?

Нет, разумеется. Он будет создавать семафор, но не будет затем вызывать xSemaphoreGive, в отличие от "родного" макроса.
Код
#define    xSemaphoreCreateBinaryDisabled()    xQueueCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH )
Cosmojam
Всё, теперь понял, ларчик просто открывался sm.gif Спасибо
Bass
или просто сразу взять семафор после его создания
aaarrr
И получите в коде холостую последовательность xSemaphoreGive() - xSemaphoreTake(). Красиво?
Dele
Цитата(aaarrr @ Feb 11 2012, 15:24) *
И получите в коде холостую последовательность 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)
{}

}
Сергей Борщ
Цитата(Dele @ Apr 7 2014, 22:06) *
Я ничего не понял, столкнулся с той же проблемой что у автора, объясните поподробней плиз

1) Я ничего не понял, объясните, что у вас за проблема?
2) Вы заметили, что ваше сообщение несколько отличается оформлением от предыдущих?
Dele
Цитата(Сергей Борщ @ Apr 8 2014, 06:44) *
1) Я ничего не понял, объясните, что у вас за проблема?
2) Вы заметили, что ваше сообщение несколько отличается оформлением от предыдущих?

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

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

CODE

#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 ) ;
Ну явно это как то отходит от примеров в книгах...
aaarrr
Так создайте семафор приведенным выше макросом. Не будет лишнего Give-Take.
Dele
Цитата(aaarrr @ Apr 8 2014, 09:32) *
Так создайте семафор приведенным выше макросом. Не будет лишнего Give-Take.

Немного не понял, как создать таким образом семафор. В queue.h нету такого определения, Coocox выдает:
C:\CooCox\CoIDE\workspace\ledexitl/main.c:148: undefined reference to `SemaphoreCreateBinaryDisabled'
вы меня простите я учусь, ткните меня как это сделать пожалуйста)
aaarrr
Цитата(Dele @ Apr 8 2014, 14:39) *
Немного не понял, как создать таким образом семафор. В queue.h нету такого определения

Совершенно верно, его там нет. Поэтому добавьте упомянутый #define в любом удобном месте:
Код
#define    xSemaphoreCreateBinaryDisabled()    xQueueCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH )

xSemaphoreHandle S;

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

Лучше, конечно, в какой-нибудь заголовочный файл.
Dele
Цитата(aaarrr @ Apr 8 2014, 15:16) *
Совершенно верно, его там нет. Поэтому добавьте упомянутый #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)
Как то так...
aaarrr
Пардон, должно быть:
Код
S = xSemaphoreCreateBinaryDisabled();


CCCV иногда подводит.
Dele
Цитата(aaarrr @ Apr 8 2014, 20:37) *
Пардон, должно быть:
Код
S = xSemaphoreCreateBinaryDisabled();


CCCV иногда подводит.


Спасибо, заработало.
Но все равно не понятно почему так происходит и надо дополнительные макросы вводить, кто косяк?)
LightElf
QUOTE (Dele @ Apr 9 2014, 06:30) *
Но все равно не понятно почему так происходит и надо дополнительные макросы вводить, кто косяк?)

Блин, что непонятного-то? Семафор создается взведенным. Так решил автор FreeRTOS. В каких-то других кернелах семафор создается сброшенным. В каких-то третьих - можно в вызове указать, какое исходное состояние требуется.

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.