why UART received data is not correct through GPDMA mode in FREERTOS?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

why UART received data is not correct through GPDMA mode in FREERTOS?

621 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by hilbertdavid on Sat Jan 03 05:57:13 MST 2015
my os is freertos 8.1.2.  i want to receive serial data through uart2 in dma mode,its priority is 16, and there is also an lwip task which prio is 9, and the lwip work correctly,while the uart2 received data is not correct, can anybody help me?
the schematic is listed here,the peri include a 7"lcd and 32M SDRAM.
the dma interrupt can intriggered normally,it's listed here:

#include "dma.h"
#include <LPC177x_8x.H>
#include <FREERTOS.h>
#include <lpc177x_8x_gpio.h>
#include "lpc177x_8x_pinsel.h"
#include "lpc177x_8x_uart.h"
#include "lpc177x_8x_gpdma.h"
#include "bsp.h"
#include <stdio.h>
#include "string.h"
#include "lpc177x_8x_clkpwr.h"
#include "lpc_debug.h"
#include "BUTTON.h"
#include "task.h"
extern __IO uint8_t rx_buff[256];
extern xSemaphoreHandle disp_sem,d2r_sem,rx485_sem;
uint32_t tmp = 0;
void DMA_IRQHandler (void)
{
//  portENTER_CRITICAL();

  static portBASE_TYPE xHigherPriorityTaskWoken;
  xHigherPriorityTaskWoken = pdFALSE;
    /* Scan interrupt pending */
  for (tmp = 0; tmp < 3; tmp++)
  {
    if (GPDMA_IntGetStatus(GPDMA_STAT_INT, tmp))
    {
      /* Check counter terminal status */
      if (GPDMA_IntGetStatus(GPDMA_STAT_INTTC, tmp))
      {
        /* Clear terminate counter Interrupt pending */
        GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, tmp);

        switch (tmp)
        {
          case 0:
            GPDMA_ChannelCmd(0, DISABLE);           
            break;
           
          case 1:
            GPDMA_ChannelCmd(1, DISABLE);
            xSemaphoreGiveFromISR(rx485_sem,&xHigherPriorityTaskWoken);
            break;
           
          case 2:
            GPDMA_ChannelCmd(2, DISABLE);           
            break;
           
          default:
            break;
        }
      }
      /* Check error terminal status */
      if (GPDMA_IntGetStatus(GPDMA_STAT_INTERR, tmp))
      {
        /* Clear error counter Interrupt pending */
        GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, tmp);
        switch (tmp)
        {
          case 0:
            GPDMA_ChannelCmd(0, DISABLE);
            break;
           
          case 1:
            GPDMA_ChannelCmd(1, DISABLE);
            break;
           
          case 2:
            GPDMA_ChannelCmd(2, DISABLE);
            break;
           
          default:
            break;
        }
      }
    }
  }
//  portEXIT_CRITICAL();
  portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}



void channel1setup(uint32_t DMARXSize,uint32_t rx_buf)
{
  GPDMA_Channel_CFG_Type GPDMACfg;
  /* Setup GPDMA channel --------------------------------*/
  /* channel 0 */
  GPDMACfg.ChannelNum = 1;
  /* Source memory - don't care */
  GPDMACfg.SrcMemAddr = 0;
  /* Destination memory */
  GPDMACfg.DstMemAddr = rx_buf;
  /* Transfer size */
  GPDMACfg.TransferSize = DMARXSize;
  /* Transfer width - don't care */
  GPDMACfg.TransferWidth = 0;
  /* Transfer type */
  GPDMACfg.TransferType = GPDMA_TRANSFERTYPE_P2M;
  /* Source connection */
  GPDMACfg.SrcConn = GPDMA_CONN_UART0_Rx;
  /* Destination connection - don't care */
  GPDMACfg.DstConn = 0;
  /* Linker List Item - unused */
  GPDMACfg.DMALLI = 0;
  GPDMA_Setup(&GPDMACfg); 
}


int pos=0;
void data_recv_task(void)
{
  UBaseType_t x;
  UART_CFG_Type UARTConfigStruct;
  UART_FIFO_CFG_Type UARTFIFOConfigStruct;
 
  PINSEL_ConfigPin(0,2,1);
  PINSEL_ConfigPin(0,3,1);
//  PINSEL_ConfigPin(0,10,1);
//  PINSEL_ConfigPin(0,11,1);
//  PINSEL_ConfigPin(1,19,0);
//  GPIO_SetDir(1, (1<<19), GPIO_DIRECTION_OUTPUT);
//  GPIO_OutputValue(1,(1<<19), 0);
  UARTConfigStruct.Databits = UART_DATABIT_8;
  UARTConfigStruct.Parity = UART_PARITY_NONE;
  UARTConfigStruct.Stopbits = UART_STOPBIT_1;
  UARTConfigStruct.Baud_rate=230400;
  UART_Init(LPC_UART0, &UARTConfigStruct);
   
  UARTFIFOConfigStruct.FIFO_Level = UART_FIFO_TRGLEV0;
  UARTFIFOConfigStruct.FIFO_ResetRxBuf = ENABLE;
  UARTFIFOConfigStruct.FIFO_ResetTxBuf = ENABLE;
  UARTFIFOConfigStruct.FIFO_DMAMode = ENABLE;
  UART_FIFOConfig(LPC_UART0, &UARTFIFOConfigStruct);
   
  GPDMA_Init();  
  NVIC_DisableIRQ (DMA_IRQn);
  NVIC_SetPriority(DMA_IRQn,(0x01<<4)|0x00);
  NVIC_EnableIRQ (DMA_IRQn);

while(1)
{  
   channel1setup(201,(uint32_t)&rx_buff[0]); 
   GPDMA_ChannelCmd(1, ENABLE);
  
   xSemaphoreTake(rx485_sem,portMAX_DELAY);
   for(pos=0;pos<134;pos++)
     if((rx_buff[pos]==0xE7)&&(rx_buff[pos+1]==0x7E))
     {
       LPC_DEBUGF(LPC_DEBUG,("+++++++++++++"));
       xSemaphoreGive(disp_sem);
       xSemaphoreTake(d2r_sem,portMAX_DELAY);
       break;
     }
   else LPC_DEBUGF(LPC_DEBUG,("%d-%x\n",pos,rx_buff[pos]));
//   LPC_DEBUGF(LPC_DEBUG,("%d***%x***\n",pos,rx_buff[pos]));
   x=uxTaskGetStackHighWaterMark((xTaskHandle *)NULL);
   LPC_DEBUGF(LPC_DEBUG,("RECVDATA=%d;",x));
}  
}


/*********************************************************************************************************
**                            End Of File
*********************************************************************************************************/








Done!
i found it's the reason of the compiler ,when i changed the compiler from iar to keil.,it works correctly!!!!!!!!
Labels (1)
0 Kudos
3 Replies

498 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by hilbertdavid on Tue Jan 06 06:13:11 MST 2015
Done!
i found it's the reason of the compiler ,when i changed the compiler from iar to keil.,it works correctly!!!!!!!!
0 Kudos

498 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by hilbertdavid on Sun Jan 04 07:50:02 MST 2015
thanks very much for your answer, my question is my received data is always ff,fe,fc,fd and other like fx whenever i sent any data, the task code work correctly on uc os,but on uc os i only have one uart dma interrupt, no ethernet interruput,uart dma interrupt contains two dma interrupt, the other one is started before this one. i am thinking about whether it's because the ahb bus is busy in this project by lcd driver or by ethernet driver when dma is transmitting.
my configASSERT is defined in freertosconfig.h, and i have checked it's working right.
regards you
0 Kudos

498 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by www.FreeRTOS.org on Sun Jan 04 02:43:11 MST 2015
Not a direct answer as I cannot answer questions about the setup for specific chips, but some usage notes for you:

1) I see they are commented out in this code, but be careful not to use taskENTER_CRITICAL()/taskEXIT_CRITICAL() from an interrupt.  As always only use the ISR specific versions of functions and macros in an interrupt (for performance there is a separate ISR API).  It is rare that such a critical section would be necessary in an interrupt anyway (just in the task code that is accessing the same peripheral) but if you do need one then use portSET_INTERRUPT_MASK_FROM_ISR() and portCLEAR_INTERRUPT_MASK_FROM_ISR() instead.  If you search FreeRTOS/Source/queue.c for these macros you will see how to use them.  Also, assuming you are using an up-to-date version of FreeRTOS, then ensure configASSERT() is defined as calling taskENTER_CRITICAL() from an interrupt would generate an assert.   This page of the FAQ will help, and has a link to the configASSERT() documentation: http://www.freertos.org/FAQHelp.html

2) In FreeRTOS V8.2.0 you could replace the semaphore with a task notification.  It is faster and uses less RAM.  See:  http://www.freertos.org/RTOS_Task_Notification_As_Binary_Semaphore.html
0 Kudos