Я не уверен, где конкретно ошибся, но возможно ошибка общего характера и кто-нибудь чего подскажет. Вообщем реализовал функцию, которая посылает запрос на модем и дожидается ответа некоторое время. Сделал это посредством очереди:
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
}
* @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) и стека у нее более чем достаточно. Конечно я мог ошибиться где то совсем в другом месте. Но если вдруг это что-то общее, буду признателен за помощь. Ну что это может быть, у меня уже просто нет никаких идей, хоть в петлю лезь! Нравоучения и критика на тему "индуский код" приветствуются .
p.s.: Забыл упомянуть: приоритет у задачи занимающейся общением с модемом самый высокий, так что такого, что ее вытеснили быть не может.