Перейти к содержанию
    

Qic

Участник
  • Постов

    6
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные Qic


  1. Т.е. логика работы выглядит так?:

    DMA постоянно гонит данные в буфер, без остановки, когда у нас есть свободное время, мы начинаем анализировать этот самый FIFO буфер на совпадение.

    Звучит быстро и просто, проверяем 64 байта на совпадение и обрабатываем.

    А что будет если байт 200, или больше? Что если большой, как говорится, payload? А если система комманд исчисляется десятками? Проверять несколько раз буфер на все соответствия?

    Мне кажется это расточительно по ресурсам, хочется ловить из потока нужные данные, и тратить на это минимум времени просто проверяя заголовок сразу в известном месте - в начале буфера.

    Чисто логически FIFO правильное решение, но это очень много времени на проверку всего потока.

  2. Поменял битовое на логическое, спасибо, забыл как это делается. Про конструкции выражений тоже учту.

    Вот только все также в терминале наблюдается следующее:

    post-84881-1469090861_thumb.png

    Также идут проглатывания на отправке, и перестаёт работать видимо при использовании vTaskDelay, видимо особенности работы с FreeRTOS 6.4.0.

    Но в первую очередь интересно почему проглатывается.

     

    sKWO, Я посмотрел драйвер, но FIFO это кажется не совсем то что мне нужно. Насколько Я понимаю происходит постоянный сбор в буфер всего приемного и обработчик уже должен там самостоятельно выдёргивая по байту разбираться что это и куда. Я же хочу чтобы если что-то появлялось на входе в USART, то оно как правило будет иметь тишину, в частности позже хочу прикрутить туда modbus. Впринципе любые данные будут когда либо иметь конец и паузу, которую Я и ловлю, после чего всё что пришло анализирую.

    Насколько Я понимаю можно спокойно сделать и FIFO, не понадобится перезапускать приемный DMA и по IDLE ловить конец. Но хочется разобраться где у меня косяки в DMA что при передачи глотает байты.

     

    P.S. IgorKossak спасибо за форматирование.

  3. Доброго времени суток!

    Делаю на 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, перечитав даташит несколько раз всеравно не могу понять - может ли он корректно поймать тишину после байта? Но как видно - работает.

     

    Это мой первый опыт такого конфигурирования и в целом Я не очень хороший программист, возможно кто-нибудь свежим взглядом найдет ошибку и подскажет как сделать лучше.

    Надеюсь на вашу помощь.

  4. Вообще-то вместо "дичи" нужно выкладывать текст самой ошибки. Вот если Вы напишите кому-то насчет этой ошибки (разработчикам т.е.), то все как положено выложите/укажите. Я примерно знаю, что за ошибка (она возможно "кракозябрами" будет если ОС не английская), но все-таки. Ошибка наверно типа - "попытка обращения к несуществующему диску" или что-то такое. Ее возможные причины: 1) т.к. OpenOCD обменивается через сокеты с ИДЕ, то может-быть брандмаузер ОС запретил его работу в сети (проверить); 2) может быть у вас на портах, что рабочие у OpenOCD (см. в "Debug Configurations") кто-то уже сидит/работает - проверить. И еще, проверьте вначале на компе через нормальный обычный USB - так работает или нет?

     

    Да именно эта ошибка про диск. При подключении напрямую всё нормально видится, т.к. в системе определяется именно st-link с его vid/pid. Через usbip есть только виртуальный диск.

    Ничего не блочится и никто ничей порт не занимает, потому что Я сегодня его вручную запускал и openocd на шаге подключения(поиска) st-linka выдал что нет его.

     

    Попробую финт ушами с драйверами, не знал про отличия в openocd в версиях libusb, спасибо.

  5. OpenOCD стоит последний 0.9.0, драйверы на st-link с сайта ST "STSW-LINK009".

    Прям также у меня не видится он, точнее говоря всё еще запутаннее. В системе видится только виртуальный диск с ссылками. Но как не странно - остальной софт работает нормально.

    Даже st-link gdb server нормально отрабатывает. Видимо придется написать разрабам.

  6. Приветствую.

    Столкнулся с некоторой проблемой. Есть stm32vldiscovery которая подключена к роутеру с котого Я прокидываю её через USBIP на PC.

    Раньше Я пользовался CooCox и местный программатор/отладчик CoFlash замечательно всё видит и делает. Также всё замечательно видит и делает ST-Link utility.

    Вот только мне захотелось пересесть на System Workbench for STM32 и на OpenOCD в частности (и при прямом подключении мне всё понравилось).

    Однако OpenOCD не видит st-link через usbip при этом выдаёт какуюто дичь на счёт дисков. Его беспокоит "встроеный" mass storage в отладчике платы с рекламой?

    Как Я понимаю, проблема в том что USBIP не обрабатывает композитные девайсы как этот, но ведь всё кроме OpenOCD работает!

    Может мне кто поможет?

     

×
×
  • Создать...