Over a million developers have joined DZone.

USB CDC with the FRDM-K64F, finally!

· IoT Zone

Access the survey results 'State of Industrial Internet Application Development' to learn about latest challenges, trends and opportunities with Industrial IoT, brought to you in partnership with GE Digital.

Sometimes I think that a problem should be solvable in a few minutes, and then it turns out that it lingers around for months. Very, very frustrating! Such a thing is getting the USB 4.1.1 stack running on the FRDM-K64F board. I have that board since April 2014, and it took me 7 months to get the FSL USB stack running on it :-(.

FRDM-K64F Board

FRDM-K64F Board

I’m using the Freescale USB V4.1.1 stack and Processor Expert McuOnEclipse FSL_USB_Stack component successfully in many projects (ColdFire, S08 and Kinetis). But despite all my trials and debugging, the USB on the K64F failed to enumerate on the host.

:idea: Freescale discontinued the USB V4.1.1 stack, and newer Kinetis devices are only supported with the USB stack in the Kinetis SDK. That Kinetis SDK stack is very different from the V4.1.1 stack, and only supports newer Kinetis Devices. So using that SDK stack was not an option.

Of course I have not working on that problem full-time, but nearly every week-end I thought that this problem should be solvable. Usually to port the stack to another Kinetis device is very easy: make sure the USB peripheral gets clocked at 48 MHz, check the USB interrupt vector location, and it simply works. But not for the K64F on the FRDM-K64F Board :-(.

I was already close to give up on that topic, until I reader ‘Obi’ (thank you, thank you, thank you!) posted a tip in a previous blog post: The problem is that the K64F has a memory protection unit, and this needs to be disabled before using the USB!

disablingMemoryProtectionUnitForK64F

disablingMemoryProtectionUnitForK64F

The fix for K64F has been committed on GitHub, and will be available with the next release of the components on SourceForge.

To use USB with the FRDM-K64F, create a Processor Expert project, then add the FSL_USB_Stack component to the project:

FSL_USB_CDC Component

FSL_USB_CDC Component

Select the Init_USB_OTG_VAR0 (for Kinetis) and the USB CDC Device Class:

USB CDC Device

USB CDC Device

In the Init_USB_OTG component, have the clock gate enabled and make sure that you have a 48 MHz USB module clock:

USB Init Clock

USB Init Clock

:idea: The Clock divider input depends on how you have configured your CPU clock, see FRDM-K64F at Maximum Speed of 120 MHz.

The USB interrupts are disabled on startup, the interrupt will be enabled later in the USB stack initialization:

USB Init Interrupts

USB Init Interrupts

In the USB CDC component, I need to select my device:

USB CDC Device Selection

USB CDC Device Selection

The USB CDC device uses two ring buffers for the data:

USB CDC with RingBuffers

USB CDC with RingBuffers

Set both the Rx and Tx buffers to a reasonable size (I use 64 bytes):

USB CDC Ring Buffer Size

USB CDC Ring Buffer Size

With this I’m ready to use the USB CDC. Below is an example code using it:

static uint8_t cdc_buffer[USB1_DATA_BUFF_SIZE];
static uint8_t in_buffer[USB1_DATA_BUFF_SIZE];
 
static void CDC_Run(void) {
  int i, cnt = 0;
  uint32_t val = 0;
  unsigned char buf[16];
 
  for(;;) {
    while(CDC1_App_Task(cdc_buffer, sizeof(cdc_buffer))==ERR_BUSOFF) {
      /* device not enumerated */
      LED1_Neg(); LED2_Off();
      WAIT1_Waitms(10);
    }
    LED1_Off(); LED2_Neg();
    if (CDC1_GetCharsInRxBuf()!=0) {
      i = 0;
      while(   i<sizeof(in_buffer)-1
            && CDC1_GetChar(&in_buffer[i])==ERR_OK
           )
      {
        i++;
      }
      in_buffer[i] = '\0';
      (void)CDC1_SendString((unsigned char*)"echo: ");
      (void)CDC1_SendString(in_buffer);
      UTIL1_strcpy(buf, sizeof(buf), (unsigned char*)"val: ");
      UTIL1_strcatNum32u(buf, sizeof(buf), val);
      UTIL1_strcat(buf, sizeof(buf), (unsigned char*)"\r\n");
      (void)CDC1_SendString(buf);
      val++;
    } else {
      WAIT1_Waitms(10);
      cnt++;
      if ((cnt%1024)==0) { /* from time to time, write some text */
        (void)CDC1_SendString((unsigned char*)"Type some text and it will echo.\r\n");
        CDC1_SendBlock((unsigned char*)"hello?\r\n", sizeof("hello?\r\n")-1);
      }
    }
  }
}

With this, USB CDC enumerates and runs with the K64F :-).

Test Program for USB CDC on FRDM-K64F

Test Program for USB CDC on FRDM-K64F

Summary

Sometimes it takes a long time for a break through, as in this case. And as in this case, the right hint can come from somebody else. A big “thank you” to ‘Obi’!!!! I’m sure many other users of the FRDM-K64F board have waiting for that USB working.

An example project for KDS V1.1.1 is available on GitHub.

Happy USBing :-)

The IoT Zone is brought to you in partnership with GE Digital.  Discover how IoT developers are using Predix to disrupt traditional industrial development models.

Topics:

Published at DZone with permission of Erich Styger, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}