Обычно любую работу с UART в Keil RTX я разделяю на две части :
1) в прерывании я просто отправляю полученные данные в mailbox (да, несколько неэффективно по памяти).
Код
// указатель на mailbox для UART2 модуля
u32* uart2_mbx;
/* Обработчик прерывания UART2 */
void uart2_isr (void) __irq
{
if (isr_mbx_check(uart2_mbx) != 0) isr_mbx_send(uart2_mbx, (void *)U2RBR); // если uart2_mbx не переполнен послали в uart2_mbx принятый байт
VICVectAddr = 0; // завершили прерывание
}
2) делаю отдельную задачу для обработки принятых данных
CODE
/* Задача приема пакета wake */
__task void task_wake(void)
{
u32 data;
os_mbx_init(wake_mbx_byte, sizeof(wake_mbx_byte)); // инициализация mailbox для принятых байт
os_mbx_init(wake_mbx_pack, sizeof(wake_mbx_pack)); // инициализация mailbox для полученных пакетов
uart2_init(WAKE_BAUDRATE, (u32 *)wake_mbx_byte); // инициализация UART2
PINSEL4 &= ~((u32)3 << 26); // разрешили WAKE_DIR пин
FIO2DIR |= WAKE_DIR; // установили WAKE_DIR пин как выход
FIO2CLR |= WAKE_DIR; // установили направление - ПРИЕМ
pack.hdr = WAKE_FEND;
while (1)
{
/* Прием FEND */
os_mbx_wait(wake_mbx_byte, (void *)&data, 0xFFFF); // бесконечное ожидание FEND
if (data != WAKE_FEND) continue; // выход если пришел не FEND
/* Прием ADR */
if ((data = get_stuf()) == WAKE_ERROR) continue; // выход при ошибке приема ADR
pack.adr = data & 0x7F; // сохранили ADR
/* Прием CMD */
if ((data = get_stuf()) > 0x7F) continue; // выход при ошибке приема CMD
pack.cmd = data; // сохранили CMD
/* Прием NUM */
if ((data = get_stuf()) == WAKE_ERROR) continue; // выход при ошибке приема NUM
pack.num = data; // сохранили NUM
/* Прием DAT */
pack.tmp = 0; // сбросили счетчик принятых данных
while (pack.tmp < pack.num) // пока не приняты все данные
{
if ((data = get_stuf()) == WAKE_ERROR) break; // прекращаем прием данных при ошибке
pack.dat[pack.tmp++] = data; // сохранили принятые данные
}
if (pack.tmp != pack.num) continue; // выход если не все данные прияты
/* Прием CRC */
if ((data = get_stuf()) == WAKE_ERROR) continue; // выход при ошибке приема CRC
pack.dat[pack.num] = data; // сохранили CRC
/* Проверка целосности пакета */
pack.tmp = CRC8(0x18, 0xDE, &pack.hdr, pack.num + 4); // считаем CRC пакета
if (pack.dat[pack.num] == pack.tmp) // если расчетное CRC совпадает с принятым
{
if (os_mbx_check(wake_mbx_pack) != 0) os_mbx_send(wake_mbx_pack, (void *)&pack, 0);// если wake_mbx_pack не переполнен посылаем принятый пакет
#ifdef ERROR_HANDLING
else os_mbx_send(error_mbx, (void *)ERROR_WAKE_MBX_OVR, WAKE_TIMEOUT); // иначе отправляем ошибку переполнения wake_mbx_pack
#endif
}
}
}
Очень удобно и наглядно получается
P.S. Протокол WAKE я использую несколько модифицированный.