ur4lvn 0 5 февраля, 2017 Опубликовано 5 февраля, 2017 · Жалоба Здравствуйте,All! Прошу помочь в разрешении следующей проблемы: нужно сопрячь 2 устройства, имеющих скорости по компорту отличающуюся в 30 раз (1М5 и 56К) тип информации - пакеты,разной длины,могут рваться на пол-дороги и приходить по 2 и более в пачке. Они имеют известный хидер, я их парсю без проблем на лету в обработчике прерывания,благо скорострельности камня хватает. Все это крутится под FreeRTOS на stm32f415. В обработчике прерывания кладу символ в кольцевой буфер и отдаю его парсеру(инлайн в обработчике). Если парсер собрал пакет - отдаю указатель на начало пакета и его длину через очередь гейткиперу сопряженного порта. Гейт копирует пакет в свой буфер передачи и разрешает передачу по порту. Все прекрасно работает до неопределенного момента - может зависнуть вся система,а может тупо перейти в вызовы задач каждую миллисекунду. Неопределенный момент может возникнуть как и через 10 сек после старта , так и через несколько часов. Ход процесса я смотрю с помощью SEGGER SYSVIEW,очень полезная вещь. Буду рад,если кто либо поможет мне разобраться,где же порылась собака. WBR, Sergey Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 5 февраля, 2017 Опубликовано 5 февраля, 2017 · Жалоба Ну что ж начнем сеанс спиритизма и телепатии. Переполненение буфера? Другие длинные обработчики прерываний? Слишком длинный пакет? Где-то бьётся память? ЗЫ Когда читаешь такой пост с описанием как-то подсознательно ождиаешь увидеть либо минмальный кусок кода на котором воспроизводится баг, либо попытки автора использовать data breakpoints в критичных для его алгоритма местах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ur4lvn 0 5 февраля, 2017 Опубликовано 5 февраля, 2017 (изменено) · Жалоба Ну что ж начнем сеанс спиритизма и телепатии. Переполненение буфера? Другие длинные обработчики прерываний? Слишком длинный пакет? Где-то бьётся память? ЗЫ Когда читаешь такой пост с описанием как-то подсознательно ождиаешь увидеть либо минмальный кусок кода на котором воспроизводится баг, либо попытки автора использовать data breakpoints в критичных для его алгоритма местах. Да,сорри. Буферы по 2К // Буфер приема сырых данных: uint8_t modem_buffer[MODEM_RX_BUFLEN]; __IO uint8_t* modem_buffer_head; __IO uint8_t* modem_buffer_tail; // Буфер передачи uint8_t modem_tx_buffer[MODEM_TX_BUFLEN]; __IO uint8_t* modem_tx_head; __IO uint8_t* modem_tx_tail; // Буфер приема сырых данных: uint8_t pilot_buffer[PILOT_RX_BUFLEN]; __IO uint8_t* pilot_buffer_head; __IO uint8_t* pilot_buffer_tail; // Буфер передачи uint8_t pilot_tx_buffer[PILOT_TX_BUFLEN]; __IO uint8_t* pilot_tx_head; __IO uint8_t* pilot_tx_tail; Инициализация портов HAL_UART_MspInit( &modem_port ); modem_port.Instance = USART2; modem_port.Init.BaudRate = MODEM_BAUDRATE; // 57600 modem_port.Init.WordLength = UART_WORDLENGTH_8B; modem_port.Init.StopBits = UART_STOPBITS_1; modem_port.Init.Parity = UART_PARITY_NONE; modem_port.Init.Mode = UART_MODE_TX_RX; modem_port.Init.HwFlowCtl = UART_HWCONTROL_NONE; modem_port.Init.OverSampling = UART_OVERSAMPLING_16; if( HAL_UART_Init( &modem_port ) != HAL_OK ) ErrorHandler(); HAL_NVIC_SetPriority( USART2_IRQn, 15, 0 ); HAL_NVIC_EnableIRQ( USART2_IRQn); HAL_UART_MspInit( &ptm_port ); ptm_port.Instance = USART6; ptm_port.Init.BaudRate = AP_TM1_BAUDRATE; //1M5 ptm_port.Init.WordLength = UART_WORDLENGTH_8B; ptm_port.Init.StopBits = UART_STOPBITS_1; ptm_port.Init.Parity = UART_PARITY_NONE; ptm_port.Init.Mode = UART_MODE_TX_RX; ptm_port.Init.HwFlowCtl = UART_HWCONTROL_NONE; ptm_port.Init.OverSampling = UART_OVERSAMPLING_16; if( HAL_UART_Init( &ptm_port ) != HAL_OK ) ErrorHandler(); HAL_NVIC_SetPriority( USART6_IRQn, 15, 0 ); HAL_NVIC_EnableIRQ( USART6_IRQn); Создание задач и очередей #define MAX_PENDING_PACKETS (32) #define configMINIMAL_STACK_SIZE ((portBASE_TYPE) 128) xTaskCreate ( pilotGateKeeper, "p gate", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, pilotGateKeeperHandle ); xTaskCreate ( modemGateKeeper, "modem gate", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, modemGateKeeperHandle ); pilotQueue = xQueueCreate ( MAX_PENDING_PACKETS, sizeof(packet_t) ); modemQueue = xQueueCreate ( MAX_PENDING_PACKETS, sizeof(packet_t) ); Гейткиперы почти одинаковы,вот один из них /* * Получив сообщение из очереди,берем оттуда адрес начала пакета в сыром буфере, * его длину, и дописываем в кольцевой буфер передачи порта.Оттуда он будет выдан в * прерывании передачи **/ void modemGateKeeper ( void* pvParameters ) { uint16_t len; uint16_t idx; uint8_t* src; packet_t packet; // Инициализация буферов modem_buffer_head = modem_buffer_tail = (uint8_t*)&modem_buffer; modem_tx_head = modem_tx_tail = (uint8_t*)&modem_tx_buffer; // Разрешаем прерывания приема символов,передатчик уже включен при инициализации порта modem_port.Instance->CR1 |= USART_CR1_RXNEIE; while(1) { xQueueReceive ( modemQueue, &packet, portMAX_DELAY ); { //SEGGER_SYSVIEW_PrintfHost("%d",packet.origin); //SEGGER_SYSVIEW_PrintfHost("MQ = %d",uxQueueMessagesWaiting(modemQueue) ); len = packet.len; src = packet.head; if(packet.origin == PILOT_CHANNEL ) { for(idx = 0; idx < len;idx++) { *modem_tx_tail = *src; modem_tx_tail++; if(modem_tx_tail == (uint8_t*)&modem_tx_buffer + MODEM_TX_BUFLEN) modem_tx_tail = (uint8_t*)&modem_tx_buffer; src++; if(src == (uint8_t*)&pilot_buffer + PILOT_RX_BUFLEN ) src = (uint8_t*)&pilot_buffer; } // разрешаем передачу modem_port.Instance->CR1 |= USART_CR1_TXEIE; } } } Обработчики прерываний - то же /* * Обработчик прерываний приема/передачи символов порта модема. ***/ void USART2_IRQHandler(void) { uint8_t current_symbol; packet_t packet; uint8_t* src; uint8_t* last_symbol; uint16_t idx; uint32_t state = modem_port.Instance->SR; portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; // Передача символа по указателю на голову буфера if( ( state & USART_SR_TXE ) && (modem_port.Instance->CR1 & USART_CR1_TXEIE) ) { modem_port.Instance->DR = *modem_tx_head++; if(modem_tx_head == (uint8_t*)&modem_tx_buffer + MODEM_TX_BUFLEN ) modem_tx_head = (uint8_t*)&modem_tx_buffer; if(modem_tx_head == modem_tx_tail) { modem_port.Instance->CR1 &= ~USART_CR1_TXEIE; SEGGER_SYSVIEW_PrintfHost("Mdone"); } } /* Указатели на голову и хвост приемника инициализированы на начало буфера при * старте таска модема **/ // Прием символа if( state & USART_SR_RXNE ) { // Проверка ошибок if( !( state & ( USART_SR_PE | USART_SR_ORE | USART_SR_NE | USART_SR_FE ) ) ) { GREEN_LED_TOGGLE; // принятый символ пишем в буфер *modem_buffer_tail = modem_port.Instance->DR; // и отдаем его на анализ if(parse_char(MODEM_CHANNEL, *modem_buffer_tail, &message[MODEM_CHANNEL],&status[MODEM_CHANNEL]) ) { // собран пакет,отдадим его длину в месседж packet.len = (uint16_t)message[MODEM_CHANNEL].len + MAVLINK_NUM_NON_PAYLOAD_BYTES; packet.msgid = message[MODEM_CHANNEL].msgid; packet.origin = MODEM_CHANNEL; // запомним указатель на последний символ пакета // и продвинем указатель хвоста на свободное место last_symbol = modem_buffer_tail++; if(modem_buffer_tail == (uint8_t*)&modem_buffer + MODEM_RX_BUFLEN) modem_buffer_tail = (uint8_t*)&modem_buffer; // найдем указатель на голову packet.head = ( (last_symbol > modem_buffer_head) ? (last_symbol - packet.len + 1 ) : (last_symbol + MODEM_RX_BUFLEN - packet.len + 1 ) ); packet.tail = last_symbol; modem_buffer_head = modem_buffer_tail; #ifdef USE_PILOT xQueueSendToBackFromISR(pilotQueue,&packet,&xHigherPriorityTaskWoken); #endif } // пакет еще не собран,подготовим место для следующего символа modem_buffer_tail++; if(modem_buffer_tail == (uint8_t*)&modem_buffer + MODEM_RX_BUFLEN) modem_buffer_tail = (uint8_t*)&modem_buffer; } else { char dummy = (char)modem_port.Instance->DR; } } if(xHigherPriorityTaskWoken) portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); } В мейне создаются таски и очереди,затем стартует шедулер. Порт принимает данные,парсит их и отдает гейткиперу другого порта для передачи. Другой порт делает то же самое,но в другом направлении,пакеты мелкие,2К буфера им с головой хватает,равно как и 32 пакета в очереди Забыл добавить: использую Eclipse Kepler + arm-none-eabi_5.4_2016q3 + FreeRTOS 9.0.0 Изменено 5 февраля, 2017 пользователем SergeyTT Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 26 14 марта, 2017 Опубликовано 14 марта, 2017 · Жалоба Симптомы похожи на "наезд" в RAM чего-то на что-то (так как слетает работа OS) Можно конечно анализировать правильность Вашего кода, но можно пойти другим путем. На один порт PC сделайте тест-запросчик, который будет выдавать на Ваш девайс случайные (или не случайные) наборы данных, которые параллельно пишутся в лог. На другой порт PC - приемник-анализатор работы Вашего девайса. Если удасться получить устойчивый влет в ошибку в приемлемое время - то найти причину будет делом техники. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться