Qic
-
Постов
6 -
Зарегистрирован
-
Посещение
Сообщения, опубликованные Qic
-
-
Поменял битовое на логическое, спасибо, забыл как это делается. Про конструкции выражений тоже учту.
Вот только все также в терминале наблюдается следующее:
Также идут проглатывания на отправке, и перестаёт работать видимо при использовании vTaskDelay, видимо особенности работы с FreeRTOS 6.4.0.
Но в первую очередь интересно почему проглатывается.
sKWO, Я посмотрел драйвер, но FIFO это кажется не совсем то что мне нужно. Насколько Я понимаю происходит постоянный сбор в буфер всего приемного и обработчик уже должен там самостоятельно выдёргивая по байту разбираться что это и куда. Я же хочу чтобы если что-то появлялось на входе в USART, то оно как правило будет иметь тишину, в частности позже хочу прикрутить туда modbus. Впринципе любые данные будут когда либо иметь конец и паузу, которую Я и ловлю, после чего всё что пришло анализирую.
Насколько Я понимаю можно спокойно сделать и FIFO, не понадобится перезапускать приемный DMA и по IDLE ловить конец. Но хочется разобраться где у меня косяки в DMA что при передачи глотает байты.
P.S. IgorKossak спасибо за форматирование.
-
Опубликовано · Изменено пользователем IgorKossak
[codebox] для длинного кода. [code]-для короткого!!! · ПожаловатьсяДоброго времени суток!
Делаю на stm32f103 приемопередающую часть с обработчиком произвольных команд для посылок произвольной длины.
Сейчас код выглядит так (самое важное):
volatile uint8_t usart1_rx_buff[255]; volatile int32_t usart1_rx_buff_lenght = 0; volatile int32_t usart1_rx_data_ready = 0; volatile uint8_t usart1_tx_buff[255]; volatile int32_t usart1_tx_buff_lenght = 0; void USART1_config (void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // Enable clk APB2 -> GPIOA GPIO_INIT_PIN(GPIOA,9,GPIO_MODE_OUTPUT50_ALT_PUSH_PULL); // USART1 PA9 TX GPIO_INIT_PIN(GPIOA,10,GPIO_MODE_INPUT_FLOATING); // USART1 PA10 RX USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd((RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO), ENABLE); //Разрешаем тактирование USART_InitStructure.USART_BaudRate = 115200;// скорость USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8 бит данных USART_InitStructure.USART_StopBits = USART_StopBits_1; //один стоп бит USART_InitStructure.USART_Parity = USART_Parity_No; //четность - нет USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // управлени потоком - нет USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // разрешаем прием и передачу USART_Init(USART1, &USART_InitStructure); //инизиализируем NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //канал NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //приоритет NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//приоритет субгруппы NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //включаем канал NVIC_Init(&NVIC_InitStructure); //инициализируем USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); USART_Cmd(USART1, ENABLE); } void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) // Receive Data register not empty interrupt { USART_ClearITPendingBit(USART1, USART_IT_RXNE); } if(USART_GetITStatus(USART1, USART_IT_TC) != RESET) // Transmission complete interrupt { USART_ClearITPendingBit(USART1, USART_IT_TC); } if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) // IDLE { USART_ClearITPendingBit(USART1, USART_IT_IDLE); // When DMA receiving get IDLE on UART USART_ITConfig(USART1, USART_IT_IDLE, DISABLE); // Выключаем прерывание т.к. мы схуято тутже висим постоянно usart1_rx_data_ready = 1; } } void DMA_for_USART1_TX_config_and_run (uint8_t buff_size) { // Config DMA : usart1_tx_buff -> USART1 for 255 bytes RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_InitTypeDef DMA_InitStruct; DMA_StructInit(&DMA_InitStruct); DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t) & (USART1->DR); DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t) usart1_tx_buff; DMA_InitStruct.DMA_BufferSize = buff_size; DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStruct.DMA_Mode = DMA_Mode_Normal; DMA_Init(DMA1_Channel4, &DMA_InitStruct); DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE); NVIC_EnableIRQ(DMA1_Channel4_IRQn); USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); DMA_Cmd(DMA1_Channel4, ENABLE); // RUN _delay_us(10); } void DMA_for_USART1_RX_config_and_run (void) { // Config DMA : USART1 -> usart1_rx_buff for 255 bytes RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_InitTypeDef DMA_InitStruct; DMA_StructInit(&DMA_InitStruct); DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t) & (USART1->DR); DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t) usart1_rx_buff; DMA_InitStruct.DMA_BufferSize = 255; DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStruct.DMA_Mode = DMA_Mode_Normal; DMA_Init(DMA1_Channel5, &DMA_InitStruct); NVIC_EnableIRQ(DMA1_Channel5_IRQn); USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); DMA_Cmd(DMA1_Channel5, ENABLE); // RUN } void DMA1_Channel4_IRQHandler(void) // USART1 TX // Now ONLY transfer complete { DMA_Cmd(DMA1_Channel4, DISABLE); USART_DMACmd(USART1, USART_DMAReq_Tx, DISABLE); if(DMA1->ISR & DMA_ISR_TCIF4) // Если обмен завершен { DMA_ClearITPendingBit(DMA1_IT_TC4); } if(DMA1->ISR & DMA_ISR_HTIF4) // Если передана половина буфера { DMA_ClearITPendingBit(DMA1_IT_HT4); } if(DMA1->ISR & DMA_ISR_TEIF4) // Если произошла ошибка при обмене { DMA_ClearITPendingBit(DMA1_IT_TE4); } if(DMA1->ISR & DMA_ISR_GIF4) // Если произошла ошибка при обмене { DMA_ClearITPendingBit(DMA_ISR_GIF4); } } void DMA1_Channel5_IRQHandler(void) // USART1 RX // Now ONLY transfer complete { DMA_Cmd(DMA1_Channel5, DISABLE); USART_DMACmd(USART1, USART_DMAReq_Rx, DISABLE); if(DMA1->ISR & DMA_ISR_TCIF5) // Если обмен завершен { DMA_ClearITPendingBit(DMA1_IT_TC5); } if(DMA1->ISR & DMA_ISR_HTIF5) // Если передана половина буфера { DMA_ClearITPendingBit(DMA1_IT_HT5); } if(DMA1->ISR & DMA_ISR_TEIF5) // Если произошла ошибка при обмене { DMA_ClearITPendingBit(DMA1_IT_TE5); } if(DMA1->ISR & DMA_ISR_GIF5) // Если произошла глобальная ошибка { DMA_ClearITPendingBit(DMA_ISR_GIF5); } } void Execute_Command (void) { if (usart1_rx_data_ready == 1) // { usart1_rx_data_ready = 0; DMA_Cmd(DMA1_Channel5, DISABLE); // Stop DMA usart1_rx_buff_lenght = 255 - DMA_GetCurrDataCounter(DMA1_Channel5); // Get REMAINING counter for work with usart1_rx_buff // Data in "usart1_rx_buff" & len of it "usart1_rx_buff_lenght" READY if (usart1_rx_buff_lenght != 0) { // Func FN01 "Echo" *************************************************************************** ************************* //if ((usart1_rx_buff[0]=='F')&(usart1_rx_buff[1]=='N')&(usart1_rx_buff[2]=='0')&(usart1_rx_buff[3]=='1')) //{ //GPIOB->BSRR = GPIO_BSRR_BS5; vTaskDelay(100); GPIOB->BSRR = GPIO_BSRR_BR5; vTaskDelay(100); // For DEBUG usart1_tx_buff_lenght = usart1_rx_buff_lenght; for (usart1_rx_buff_lenght; usart1_rx_buff_lenght>=0; usart1_rx_buff_lenght--) { usart1_tx_buff[usart1_rx_buff_lenght] = usart1_rx_buff[usart1_rx_buff_lenght]; }; DMA_for_USART1_TX_config_and_run(usart1_tx_buff_lenght); //} } // Remain of listening DMA_for_USART1_RX_config_and_run(); USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); } } int main(void) { System_RCC_config(); GPIO_config(); USART1_config(); DMA_for_USART1_RX_config_and_run(); TIM3_PWM_config_and_run(); xTaskCreate( default_task, ( signed char * ) "default_task", configMINIMAL_STACK_SIZE, NULL, 1, NULL ); __enable_irq (); vTaskStartScheduler(); while(1){} } void default_task ( void *pvParameters ) { for(;; ) { vTaskDelay(1); Execute_Command(); } vTaskDelete( NULL ); }
В таком виде конкретно функция Execute_Command которая умеет ЭХО делает всё быстро и замечательно. На все скорости ни затыков ничего такого.
Однако когда Я раскомментирую условие "if ((usart1_rx_buff[0]=='F')&(usart1_rx_buff[1]=='N')&(usart1_rx_buff[2]=='0')&(usart1_rx_buff[3]=='1'))" начинается дичь, а именно в случайном порядке пришедший ответ короче с конца на случайное число байт.
А когда Я раскомментирую мигание светодиодиком (for debug) через несколько срабатываний фукнция перестаёт вообще чтолибо делать, т.к. приемный счётчик DMA1_Channel4 возвращает 255.
Причем еще Я использую обработку IDLE флага от USART, перечитав даташит несколько раз всеравно не могу понять - может ли он корректно поймать тишину после байта? Но как видно - работает.
Это мой первый опыт такого конфигурирования и в целом Я не очень хороший программист, возможно кто-нибудь свежим взглядом найдет ошибку и подскажет как сделать лучше.
Надеюсь на вашу помощь.
-
Вообще-то вместо "дичи" нужно выкладывать текст самой ошибки. Вот если Вы напишите кому-то насчет этой ошибки (разработчикам т.е.), то все как положено выложите/укажите. Я примерно знаю, что за ошибка (она возможно "кракозябрами" будет если ОС не английская), но все-таки. Ошибка наверно типа - "попытка обращения к несуществующему диску" или что-то такое. Ее возможные причины: 1) т.к. OpenOCD обменивается через сокеты с ИДЕ, то может-быть брандмаузер ОС запретил его работу в сети (проверить); 2) может быть у вас на портах, что рабочие у OpenOCD (см. в "Debug Configurations") кто-то уже сидит/работает - проверить. И еще, проверьте вначале на компе через нормальный обычный USB - так работает или нет?
Да именно эта ошибка про диск. При подключении напрямую всё нормально видится, т.к. в системе определяется именно st-link с его vid/pid. Через usbip есть только виртуальный диск.
Ничего не блочится и никто ничей порт не занимает, потому что Я сегодня его вручную запускал и openocd на шаге подключения(поиска) st-linka выдал что нет его.
Попробую финт ушами с драйверами, не знал про отличия в openocd в версиях libusb, спасибо.
-
OpenOCD стоит последний 0.9.0, драйверы на st-link с сайта ST "STSW-LINK009".
Прям также у меня не видится он, точнее говоря всё еще запутаннее. В системе видится только виртуальный диск с ссылками. Но как не странно - остальной софт работает нормально.
Даже st-link gdb server нормально отрабатывает. Видимо придется написать разрабам.
-
Приветствую.
Столкнулся с некоторой проблемой. Есть stm32vldiscovery которая подключена к роутеру с котого Я прокидываю её через USBIP на PC.
Раньше Я пользовался CooCox и местный программатор/отладчик CoFlash замечательно всё видит и делает. Также всё замечательно видит и делает ST-Link utility.
Вот только мне захотелось пересесть на System Workbench for STM32 и на OpenOCD в частности (и при прямом подключении мне всё понравилось).
Однако OpenOCD не видит st-link через usbip при этом выдаёт какуюто дичь на счёт дисков. Его беспокоит "встроеный" mass storage в отладчике платы с рекламой?
Как Я понимаю, проблема в том что USBIP не обрабатывает композитные девайсы как этот, но ведь всё кроме OpenOCD работает!
Может мне кто поможет?
STM32F1 DMA USART Посылка произвольной длины
в STM
Опубликовано · Пожаловаться
Т.е. логика работы выглядит так?:
DMA постоянно гонит данные в буфер, без остановки, когда у нас есть свободное время, мы начинаем анализировать этот самый FIFO буфер на совпадение.
Звучит быстро и просто, проверяем 64 байта на совпадение и обрабатываем.
А что будет если байт 200, или больше? Что если большой, как говорится, payload? А если система комманд исчисляется десятками? Проверять несколько раз буфер на все соответствия?
Мне кажется это расточительно по ресурсам, хочется ловить из потока нужные данные, и тратить на это минимум времени просто проверяя заголовок сразу в известном месте - в начале буфера.
Чисто логически FIFO правильное решение, но это очень много времени на проверку всего потока.