|
STM32 Прерывание UART, Странное поведение |
|
|
|
Feb 20 2014, 10:37
|
Участник

Группа: Участник
Сообщений: 47
Регистрация: 9-03-11
Пользователь №: 63 481

|
Простой модуль чтения данных с GPS, из проекта выкинул все, кроме uart драйвера и парсера сообщений UBX. (Ublox gps protocol), STM415 стоит, но софт везде работает с ним как с 215 ( Это не влияет, я это ловил и на настоящих 215 ) Настройка порта: CODE case USART6_BASE:
#ifdef USE_IN_UART6_BUFFER UART6_InputBufWR = 0; UART6_InputBufRD = 0; #endif #ifdef USE_OUT_UART6_BUFFER UART6_OutputBufWR = 0; UART6_OutputBufRD = 0; #endif RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE); GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6); GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6); GPIO_Init_Struct.GPIO_Pin = GPIO_Pin_6; GPIO_Init_Struct.GPIO_Mode = GPIO_Mode_AF; GPIO_Init_Struct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init_Struct.GPIO_OType = GPIO_OType_PP; GPIO_Init_Struct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &GPIO_Init_Struct); GPIO_Init_Struct.GPIO_Pin = GPIO_Pin_7; GPIO_Init_Struct.GPIO_OType = GPIO_OType_OD; GPIO_Init_Struct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &GPIO_Init_Struct); #if defined (USE_IN_UART6_BUFFER) || defined (USE_OUT_UART6_BUFFER) NVIC_InitStructure.NVIC_IRQChannel = USART6_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = UART6_PreemptionPriority; NVIC_InitStructure.NVIC_IRQChannelSubPriority = UART6_SubPriority; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #endif #ifdef USE_IN_UART6_BUFFER USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE); //USART_ITConfig(USARTx, USART_IT_ORE, ENABLE); #endif break; } USART_Init_Struct.USART_BaudRate = Baudrate; USART_Init_Struct.USART_WordLength = USART_WordLength_8b; USART_Init_Struct.USART_StopBits = USART_StopBits_1; USART_Init_Struct.USART_Parity = USART_Parity_No; USART_Init_Struct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init_Struct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(USARTx, &USART_Init_Struct); USART_Cmd(USARTx,ENABLE); Прерывание: CODE void USART6_IRQHandler(void) { if(USART_GetITStatus(USART6, USART_IT_TXE) != RESET) { #ifdef USE_OUT_UART6_BUFFER if(UART6_out_counter != 0) { UART6_out_counter--; USART_SendData(USART6,(uint16_t) UART6_OutputBuf[UART6_OutputBufRD]); if(UART6_OutputBufRD >= (UART6_OutputBuf_size - 1)) { UART6_OutputBufRD = 0; } else { UART6_OutputBufRD++; } } else { USART_ITConfig(USART6, USART_IT_TXE, DISABLE); isTxDone6 = 1; #endif } } else if(USART_GetITStatus(USART6, USART_IT_RXNE) != RESET) { USART6->SR; #ifdef USE_IN_UART6_BUFFER uint8_t read_UART; read_UART = USART_ReceiveData(USART6); #ifdef FATFS_ON GPSLOGGER_PushByte( read_UART ); #endif
if(UART6_in_counter < UART6_InputBuf_size) { UART6_InputBuf[UART6_InputBufWR] = read_UART; if(UART6_InputBufWR == (UART6_InputBuf_size - 1)) { UART6_InputBufWR = 0; } else { UART6_InputBufWR++; } UART6_in_counter++; } #endif }else { USART6->SR; USART6->DR; } USART_ClearFlag( USART6, USART_FLAG_CTS | USART_FLAG_LBD | USART_FLAG_RXNE | USART_IT_TC ); } Ну тык вот, есть странности (скорость 200к). Самый главный вопрос, почему мы иногда попадаем в последний else, выполняя USART6->SR; USART6->DR; При этом, это должно было быть прерывание RX, НО RXNEIE = 0! Все остальные биты такие-же как и при нормальном прерывании. Еще странность что ORE почти всегда 1. В GPSLOGGER_PushByte есть глобальное разрешение и запрещение прерывания, но функция просто просто байт сохраняет: CODE inline void GPSLOGGER_PushByte( uint8_t b ){ __disable_irq(); if( sizebuf[curBuf] < LOGBUFSIZE ){ logbuf[ curBuf ][ sizebuf[curBuf] ] = b; } sizebuf[ curBuf ] ++; __enable_irq(); }
Сообщение отредактировал Vladimir Prokofiev - Feb 20 2014, 10:40
|
|
|
|
|
 |
Ответов
|
Apr 29 2014, 09:19
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(Vladimir Prokofiev @ Feb 20 2014, 11:37)  ...странное... Прежде, чем начинать новую тему, поискал, не было ли чего похожего. Оказался здесь. Мой пост есть не столько ответ к ТС сколько нарытая информация к UART STM32F10x. Предыстория раскопок. Применяю, естессно, UART широко и с размахом. Возникла тема подключить WiFi-модуль к STM32F103 через UART. Сделал, заработало. Более тщательные тесты обнаружили спорадическую потерю байтов при приеме от WiFi-модуля. Ну, скажем, один байт на каждые полмега. Прием построен по принципу FIFO в виде аппаратно-независимого драйвера. Полный код приводить не буду, но процедура обработки прерывания в части приема выглядит так: CODE /******************************************************************************/ // // IRQ Handler // void bufio_IRQHandler(bufio_FIFO *FIFO) { bufio_DRIVER* h = FIFO->HD; // to shorten the script if (h && h->RI) { while (h->RI()) { // If no more place in the input buffer, no char read out // from the data register follows, and RI flag stays ON. // The interrupt will be disabled. As soon as it is reenabled // in the ReadChar, the interrupt shoots again. if (bufio_RXBufferReady() && !FIFO->RX.flag) bufio_StoreChar(FIFO, h->Get()); else { h->RIE(0); // disable RX interrupt w/o getting the char break; // from the device; it should keep the RI flag on. } } } .... h->RI() - это, по сути, чтение SR на предмет RXNE. Ну а h->Get() - чтение DR. Вроде все согласно логике и докам. Обработчик - это еще не вектор прерывания: тот инкапсулирует вызов обработчика как: CODE /******************************************************************************/ // // USART IRQ Handler // /******************************************************************************/ void STDIO_IRQHandler(void) { bufio_IRQHandler(&FIFO); } Когда я натолкнулся на потерю байтов, я, естественно, начал подозревать переполнение буфера UART, хотя при 115200 бод и 72MHz проца такого быть бы не должно (приоритет прерывания для UART установлен неслабенький). Для поимки жука я выставил ловушку: CODE /******************************************************************************/ // // USART IRQ Handler // /******************************************************************************/ void STDIO_IRQHandler(void) { if (STDIO_DEVICE->SR & USART_SR_ORE) __NOP(); bufio_IRQHandler(&FIFO); } После чего в ловушку никто не попал, а потери байтов, похоже, прекратились... Чисто феноменологически, а также из опыта продирания сквозь дебри I2C этого проца, я сделал вывод, что, похоже, прерывание возникает раньше, чем биты, его вызвавшие, появляются в SR. Это, возможно, приводит к тому, что без задержки по причине if() вверху нарушается логика работы основного обработчика. Чтение же (явно лишнее) SR просто так перед дальнейшими действиями приводит UART в чувство после пинка прерывания. Где-то напортачили с синхронизацией регистров и шин. Даже осмелюсь высказать крамольную гипотезу, что обновления SR происходят не от основной частоты, а синхронизируются с baud-частотой. В общем, оставил я тупое предчтение SR пока. Не люблю я таких work around... А что делать? И кто виноват?
Сообщение отредактировал KnightIgor - Apr 29 2014, 09:33
|
|
|
|
|
Apr 29 2014, 10:03
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(KnightIgor @ Apr 29 2014, 13:19)  Чисто феноменологически, а также из опыта продирания сквозь дебри I2C этого проца, я сделал вывод, что, похоже, прерывание возникает раньше, чем биты, его вызвавшие, появляются в SR. Это, возможно, приводит к тому, что без задержки по причине if() вверху нарушается логика работы основного обработчика. Чтение же (явно лишнее) SR просто так перед дальнейшими действиями приводит UART в чувство после пинка прерывания. Где-то напортачили с синхронизацией регистров и шин. Даже осмелюсь высказать крамольную гипотезу, что обновления SR происходят не от основной частоты, а синхронизируются с baud-частотой. В общем, оставил я тупое предчтение SR пока. Не люблю я таких work around... А что делать? И кто виноват? Недавно тоже боролся с потерей байтов в USART у STM32, но проблема была в... компиляторе - при записи в регистр USART->DR вставлялось фиктивное его чтение (древняя сборка kgp, в последней все нормально). Нигде в Интернете жалоб на пропажу байт не нашел, эррата тоже пуста. Если бы прерывание выставлялось раньше флага, то у Вас просто были бы повторные вхождения в прерывание. Флаг же очищается только чтением из USART->DR.
|
|
|
|
Сообщений в этой теме
Vladimir Prokofiev STM32 Прерывание UART Feb 20 2014, 10:37 AHTOXA У STM-ок это довольно часто бывает - "ложное... Feb 20 2014, 18:06 demiurg_spb А зачем этот участок кода? Ведь по приходу нового ... Apr 30 2014, 06:55  KnightIgor Цитата(demiurg_spb @ Apr 30 2014, 07:55) ... Apr 30 2014, 08:57   AHTOXA Да, эта часть бесполезна. Видимо, наследие какого-... Apr 30 2014, 09:31 KnightIgor Цитата(Vladimir Prokofiev @ Feb 20 2014, 11... Feb 24 2014, 08:24 Vladimir Prokofiev Цитата(KnightIgor @ Feb 24 2014, 12:24) К... Feb 26 2014, 09:47 demiurg_spb Цитата(KnightIgor @ Apr 29 2014, 13:19) М... Apr 29 2014, 10:48  KnightIgor Цитата(demiurg_spb @ Apr 29 2014, 11:48) ... Apr 29 2014, 12:07   adnega Цитата(KnightIgor @ Apr 29 2014, 16:07) П... Apr 29 2014, 13:22    KnightIgor Цитата(adnega @ Apr 29 2014, 14:22) Что з... Apr 29 2014, 13:56     adnega Цитата(KnightIgor @ Apr 29 2014, 17:56) Д... Apr 29 2014, 17:25      KnightIgor Цитата(adnega @ Apr 29 2014, 18:25) Собра... Apr 29 2014, 18:38 adnega С USART_SR_RXNE Вы правы - он у меня определен как... Apr 29 2014, 21:40 KnightIgor Цитата(adnega @ Apr 29 2014, 22:40) С USA... Apr 30 2014, 07:51  adnega Цитата(KnightIgor @ Apr 30 2014, 11:51) И... Apr 30 2014, 09:38   KnightIgor Цитата(adnega @ Apr 30 2014, 10:38) Насче... Apr 30 2014, 10:11    adnega Цитата(KnightIgor @ Apr 30 2014, 14:11) Ж... Apr 30 2014, 10:34 Golikov A. Да библиотеки производителя все (ну большинство то... Apr 30 2014, 11:03 KnightIgor Цитата(Golikov A. @ Apr 30 2014, 12:03) Д... Apr 30 2014, 16:54
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|