AnsweredAssumed Answered

High Baud Rate UART (6Mbaud) - K66F

Question asked by Eric Koski on Oct 5, 2016
Latest reply on Aug 6, 2017 by Akshay B

Hi, I just received my first NXP development board (FRDM-K66F).  I am trying to create a CDC device (ACM), and I am trying to get the UART communication working at a rate of 6Mbaud.

 

From what I can see from the documentation, my baud rate maximum will be  baud = clock / 16.  

 

I am using UART0, and I *think* I have correctly linked it to the system clock.  The documentation indicates that the system clock is running at 120Mhz, and stepping through the code confirms this value as I pass it to the UART_Init.  Based on this information and the baud calculation above, I should have no problems communicating at 7.5Mbaud.

 

I used the dev_cdc_vcom_freertos_frdmk66f example as a baseline.  This example creates the CDC device that I need, but it is set up as a loopback, so I needed to integrate pieces from the freertos_uart_frdmk66f for setting up my UART0.

 

The uart example is pretty basic, so I used the K66F Reference guide to try to set up the UART correctly (this may be my problem).  The original cdc_vcom code had the debug output also using UART0, so I have redirected that debug output to UART1.

 

The best data rate I can achieve is 1Mbaud.  If I try to go faster than that, I get garbage characters in my terminal.  I have confirmed that my terminal can handle the high 6Mbaud rates with my host device, so I do not have reason to believe that my terminal is the problem.

 

My code is still pretty basic, so I thought maybe someone would spot what I have done wrong.  Again, the base source is from the dev_cdc_vcom_freertos_frdmk66f example, so I will just post the portion that I have modified.

 

// -----------------
// In virtual_com.h
// -----------------
#define LINE_CODING_DTERATE (6000000)

// -----------------
// In virtual_com.c
// -----------------
#define UART_BASE UART0
#define UART_RX_TX_IRQn UART0_RX_TX_IRQn

/* UART configuration */
struct rtos_uart_config uart_config = {
.baudrate = LINE_CODING_DTERATE,
.parity = kUART_ParityDisabled,
.stopbits = kUART_OneStopBit,
.buffer = s_uartBackgroundBuffer,
.buffer_size = sizeof(s_uartBackgroundBuffer),
};

.
.
.
void CdcTask(void *handle)
{
   int error = kStatus_Fail;
   USB_DeviceApplicationInit();

   while (1)
   {
      if ((1 == s_cdcVcom.attach) && (1 == s_cdcVcom.startTransactions))
      {
         if (s_cdcRecvSize > 0)
         {
            error = UART_RTOS_Send(&s_uartHandle, s_cdcRecvBuf, s_cdcRecvSize);
            if (error != kStatus_Success)
            {
               /* Failure to send Data Handling code here */
               PRINTF("UART Send Error");
            }
            s_cdcRecvSize = 0;

            // Re-arm the receive handler.
            USB_DeviceCdcAcmRecv(s_cdcVcom.cdcAcmHandle,
                                 USB_CDC_VCOM_BULK_OUT_ENDPOINT,
                                 s_cdcRecvBuf,
                                 g_UsbDeviceCdcVcomDicEndpoints[0].maxPacketSize);
         }
      }
   }
}

void UartTask(void *pvParameters)
{
   uint8_t uartRxByte = 0;
   size_t rxCount;

   usb_status_t error = kStatus_USB_Error;

   uart_config.srcclk = CLOCK_GetFreq(kCLOCK_CoreSysClk);
   uart_config.base = UART_BASE;

   if (0 > UART_RTOS_Init(&s_uartHandle, &t_uartHandle, &uart_config))
   {
      PRINTF("Error during UART initialization.\r\n");
      vTaskSuspend(NULL);
   }

   while(1)
   {
      UART_RTOS_Receive(&s_uartHandle, &uartRxByte, sizeof(uartRxByte), &rxCount);

      if (rxCount > 0)
      {
         error = USB_DeviceCdcAcmSend(s_cdcVcom.cdcAcmHandle,
         USB_CDC_VCOM_BULK_IN_ENDPOINT, &uartRxByte, sizeof(uartRxByte));
         if (error != kStatus_USB_Success)
         {
            // Failure to send Data Handling code here
            PRINTF("CDC Send Error");
         }
         rxCount = 0;
      }
   }
}

int main(void)
{
   BOARD_InitPins();
   BOARD_BootClockRUN();
   BOARD_InitDebugConsole();
   NVIC_SetPriority(UART_RX_TX_IRQn, 5);

   if (xTaskCreate(CdcTask,                         // pointer to the task
                   s_cdcTaskName,            // task name for kernel awareness debugging
                   1000L / sizeof(portSTACK_TYPE),  // task stack size
                   &s_cdcVcom,                      // optional task startup argument
                   5,                               // initial priority
                   &s_cdcVcom.applicationTaskHandle // optional task handle to create
                   ) != pdPASS)
   {
      usb_echo("CDC task create failed!\r\n");
      return -1;
   }

   if (xTaskCreate(UartTask,                       // pointer to the task
                   s_uartTaskName,           // task name for kernel awareness debugging
                   1000L / sizeof(portSTACK_TYPE), // task stack size
                   NULL,                           // optional task startup argument
                   5,                              // initial priority
                   NULL                            // optional task handle to create
                   ) != pdPASS)
   {
      usb_echo("UART task create failed!\r\n");
      return -11;
   }

   vTaskStartScheduler();

   return 1;
}

 

A few more things to note... as I step through the UART_RTOS_Init (which leads to the UART_Init), I can see that the srcClock_Hz gets set to 120000000, I see that the sbr gets set to 1, the config->baudRate_Bps comes in as my defined 6000000, and the brfa is calculated as 8.  Based on the calculation that I found in the reference manual in section

59.5.3 Baud Rate Generation

UART baud rate = UART module clock / (16 × (SBR[12:0] + BRFD))

... plugging in the above values would give me the 6000000 that I want.  It just doesn't seem to communicate correctly.

 

Does anyone see something that I missed?  Thanks for your help!

Outcomes