реклама на сайте
подробности

 
 
> FreeRtos проблемы с очередями, Иногда очередь "зависает"
yanvasiij
сообщение Apr 15 2014, 07:57
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041



Доброго времени суток!

Я не уверен, где конкретно ошибся, но возможно ошибка общего характера и кто-нибудь чего подскажет. Вообщем реализовал функцию, которая посылает запрос на модем и дожидается ответа некоторое время. Сделал это посредством очереди:
CODE
/**
* @brief Отправить строку и дождаться ответа от модема
*
* @param string строка, которую отправляем
* @param dataLen длинна отправляемой строки
* @param answer указатель на строку куда положить ответ
* @param answerLen длинна полученного ответа
* @param timeToWait Время в тиках, указывающее сколько времени ждать ответа от модуля
*/

void bgs2SendString (uint8_t *string, uint32_t dataLen, uint8_t *answer, uint32_t *answerLen, uint32_t timeToWait)
{
uint8_t ch;
*answerLen = 0;
uint32_t len=0;

/**
* Здесь отправляемая строка улетает на модем через уарт
*/
for (uint32_t i = 0; i < dataLen; i++)
{
bgs2Putchar (string[i]);
}
/**
* Здесь дожидаюсь ответа от модема. Если после последнего символа в течении timeToWait не пришел следующий символ,
* то принимаю решение, что строка с ответом полностью получена.
*/
while ( pdTRUE == xQueueReceive( uartRxData, &ch, timeToWait) )
{
putchar(ch);
answer[len] = ch;
len++;
}
/**
* На всякий случай сбрасываю очередь, на тот случай, если вдруг чего осталось в очереди. Хотя по идее такого произойти не должно.
*/
xQueueReset(uartRxData);
*answerLen = len;
}

/**
* @brief Обработчик прерываний, из которого данные попадают в очередь uartRxData
*/
void bgs2UartIrqHandler (void)
{
portBASE_TYPE xHigerPriorityTaskWoken;
#if UART_NUM==0
uint32_t interruptStatus = LPC_UART0->IIR & 0x0E;
#elif UART_NUM==1
uint32_t interruptStatus = LPC_UART1->IIR & 0x0E;
#endif
if (interruptStatus == 0x04)
{
#if UART_NUM==0
uint8_t ch = LPC_UART0->RBR;
#elif UART_NUM==1
uint8_t ch = LPC_UART1->RBR;
#endif

xQueueSendToBackFromISR ( uartRxData, &ch, &xHigerPriorityTaskWoken);

}

/** @brief инициализация железа и очереди */
void bgs2InitUartPort (void)
{
#if USE_FREERTOS==1
uartRxData = xQueueCreate (200, 1);
#endif
#if UART_NUM==0
/* Power Up the UART0 controller. */
LPC_SC->PCONP |= (1 << 3);
/* Configure UART0 pins */
LPC_IOCON->P0_2 = (1 << 9)| 1;
LPC_IOCON->P0_3 = (1 << 9)| 1;
/* Init UART0 */
LPC_UART0->LCR = 0x83;
LPC_UART0->DLL = 24;
LPC_UART0->DLM = 0;
LPC_UART0->FDR = 229;
LPC_UART0->LCR = 0x03;
LPC_UART0->IER |= (1<<0);
NVIC_EnableIRQ(UART0_IRQn);
NVIC_SetPriority(UART0_IRQn, 196);

#elif UART_NUM==1
/* Power Up the UART1 controller. */
LPC_SC->PCONP |= (1 << 4);
/* Configure UART1 pins */
LPC_IOCON->P0_15 = (1<<0)|(0<<1)|(0<<2);
LPC_IOCON->P0_16 = (1<<0)|(0<<1)|(0<<2);
/* Init UART1 */
LPC_UART1->LCR = 0x83;
LPC_UART1->DLL = 24;
LPC_UART1->DLM = 0;
LPC_UART1->FDR = 229;
LPC_UART1->LCR = 0x03;
LPC_UART1->IER |= (1<<0);
NVIC_EnableIRQ(UART1_IRQn);
NVIC_SetPriority(UART1_IRQn, 196);

#endif
}


Все работает, я наблюдаю оживленную беседу между модемом и микроконтроллером в том алгоритме, который и нужен. Но иногда, по непонятной для меня причине, задача (именно одна задача, все остальные задачи работают), занимающаяся "беседой" с модемом "застревает" навсегда на строчке while ( pdTRUE == xQueueReceive( uartRxData, &ch, timeToWait) ) (значение timeToWait = 200 - посмотрел в дебаге). Почему она там залипает мне совершенно непонятно, ведь период ожидания не равен portMAX_DELAY. Задача как будто блокируется, но при этом функция vTaskList показывает, что задача не блокирована (статус == READY) и стека у нее более чем достаточно. Конечно я мог ошибиться где то совсем в другом месте. Но если вдруг это что-то общее, буду признателен за помощь. Ну что это может быть, у меня уже просто нет никаких идей, хоть в петлю лезь! Нравоучения и критика на тему "индуский код" приветствуются sm.gif.

p.s.: Забыл упомянуть: приоритет у задачи занимающейся общением с модемом самый высокий, так что такого, что ее вытеснили быть не может.

Сообщение отредактировал yanvasiij - Apr 15 2014, 08:03
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Lagman
сообщение Apr 15 2014, 15:03
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Я писал как в примерах на сайте т.е. добавлял в конце прерывания переключение "portYIELD_FROM_ISR( xHigherPriorityTaskWoken );" после xQueueSendToBackFromISR, но у меня процессор другой и соответсвенно порт ОС. Вот тут есть информация http://microsin.ru/content/view/1306/44/ Еще можно проверить что в таких случая возвращает xQueueSendToBackFromISR, если errQUEUE_FULL - то данные не были отправлены в очередь, так как очередь уже полна.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st June 2025 - 07:01
Рейтинг@Mail.ru


Страница сгенерированна за 0.01393 секунд с 7
ELECTRONIX ©2004-2016