Found unkown issue while parsing a usart fifo buffer

Discussion in 'Processors, Motherboards & Memory' started by Cadio, Dec 21, 2017.

  1. Cadio

    Cadio Newbie

    I have an STM32F429-disco(www.kynix.com/Parts/162854/STM32F429AGH6.html) configured for USART (Tx and Rx).Communicating with an asynchronous device. The receive data length is not known before hand. It generally varies from 2 bytes to 28 bytes. Hence i have configured the USART_IT_IDLE (idle line detection). DMA is responsible for performing the peripheral-to-memory transfer upon each USART_Rx request (which is per byte). I am not using internal usart fifo. IDLE line interrupt handler is responsible for disabling the dma and hence setting the DMA_FLAG_TCIFx flag. The DMA ISR then copies the data from thew usart buffer to another buffer where data processing is done.

    The device i communicate with expects a '\r' to be sent continuously until it acknowledges synchronization by sending a "OK" command. The job of the communication task is to parse the buffer and check if "OK" has been received. I am using freertos with stm32f4 standard peripheral library. Following is the code.

    Code:
        #define RXBUFFERSIZE  64
        #define PARSESIZE     128
    
        char aRxBuffer[RXBUFFERSIZE];
        char parsebuffer[PARSESIZE];
        volatile size_t writes,write_length;
    
        static int BufferCmp(char* pBuffer1,char* pBuffer2,size_t   pBufferLength)
        {
           while(pBufferLength--)
            {
              if(*pBuffer1 != *pBuffer2)
                 {
    
                    return -1;
                  }
              pBuffer1++;
              pBuffer2++;
             }
            return 0;
           }
    
    
        static void* BufferSearch(char* bf1,size_t size,char* bf2,size_t length)
          {
            const unsigned char* haystack=(const unsigned char*)bf1;
            const unsigned char* needle=(const unsigned char*)bf2;
    
            if(length==0)
               return 0;
            while(length <= size)
              {
                 if(!BufferCmp(haystack,needle,length))
                     return (void*) haystack;
                 haystack++;
                 size--;
               }
            return NULL;
          }
    
    
        void DMA1_Stream1_IRQHandler(void)
        {
          volatile size_t len,copyindex;
          uint8_t* ptr;
    
          if(DMA1->LISR & DMA_FLAG_TCIF1)
             DMA1->LIFCR = DMA_FLAG_TCIF1;
    
          len = (uint32_t)RXBUFFERSIZE - DMA1_Stream1->NDTR;
          copyindex=(uint32_t)PARSESIZE - writes;
    
          if(copyindex > len)
             copyindex=len;
          else if(copyindex < len)
          {
             writes=0;
             copyindex=len;
           }
    
           ptr=aRxBuffer;
           memcpy(&parsebuffer[writes],ptr,len);
    
           writes+=copyindex;
           write_length += len;
           len-=copyindex;
           ptr+=copyindex;
    
           BaseType_t xHigherPriorityTaskWoken;
    
           xHigherPriorityTaskWoken=pdFALSE;
    
           xSemaphoreGiveFromISR(parse,&xHigherPriorityTaskWoken);
    
           DMA1->LIFCR=DMA_FLAG_DMEIF1 | DMA_FLAG_FEIF1 | DMA_FLAG_TEIF1 | DMA_FLAG_TCIF1 | DMA_FLAG_HTIF1;
           DMA1_Stream1->M0AR=(uint32_t)aRxBuffer;
           DMA1_Stream1->NDTR=(uint32_t)RXBUFFERSIZE;
           DMA1_Stream1->CR |= DMA_SxCR_EN;
    
    
    
           portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
          }
    
        void vTask_parse(void* pvParameters)
          {
            const TickType_t MaxBlock =pdMS_TO_TICKS(20);
            char comm[2]={'O','K'};
            for(;;)
              {
                 //GPIOG->ODR ^= GPIO_Pin_13;
                if(xSemaphoreTake(parse,MaxBlock)==pdPASS)
                   {
    
                      if(!synced)
                         {
                           __disable_irq();
                        if(!BufferSearch(&parsebuffer[0],PARSESIZE,comm,2))
                           {
                             Putc_ax('\r');
                             //GPIOG->ODR ^= GPIO_Pin_13;
                            }
                           else
                            {
                              Puts_term("Synced\r\n"); //Message to the terminal USART
                              synced=1;
                              GPIOG->ODR ^= GPIO_Pin_13;
                             }
                           __enable_irq();
                          }
                       }
                    }
                }
    And following is the main code. vTask2 only prints the contents of the buffer to the terminal.
    I've checked the contents of the buffer by printing them and they do contain "OK". For some reason my code is unable to find the pattern. I've tried manually initialising the buffer with random values and placed "OK" at certain places. The BufferCmp and BufferSearch seems to do its job.

    Main:

    Code:
         int main()
         {
           parse=xSemaphoreCreateBinary();
           GPIO_Config();
           synced=0;
           USART6_Config(); //Initializes the Terminal usart
           USART3DMA_Config();
    
           xTaskCreate(vTask_parse,"parse",256,NULL,1,NULL);
           xTaskCreate(vTask2,"vTask2",100,NULL,1,NULL);
    
           vTaskStartScheduler();
    
           for(;;);
          }
    I dont understand what the issue is, DMA and USART seem to be working fine. I have even checked target devices bit pattern on a scope and found no issues. The BufferSearch function has an execution time of 44-46.8 usecs. And the USART baud is 9600 bps.There is no sign of data corruption as well. Since the printing task prints the correct data.

    Any suggestions or troubleshooting ideas would be greatly appreciated.

    P.S: The freertos works fine, no hardfaults or memmanage faults. The printing task gets scheduled regularly with no timing issues.
     

Share This Page