7.1. Linker Generated ECC

7.1.1. Linker Generated ECC Linker Command File Syntax

Beginning with release 5.1.0, the TI ARM C/C++ Compiler supports automatic generation of Error Correction Codes compatible with the Flash ECC on various TI microcontrollers (e.g. TMS570, RM4x). ECC can be generated during the final link step of compilation. The ECC data is included in the resulting object file, alongside code and data, as a data section located at the appropriate address. Therefore, no extra ECC generation step is required after compilation, and the ECC can be uploaded to the device along with everything else.

The Linker is configured to generate ECC using a new syntax in the linker command file. The command file will specify a separate memory range for the ECC inside the device`s memory map, and it will indicate which other memory range corresponds to the Flash data memory covered by the ECC. It will also specify the parameters by which the ECC will be calculated, which can vary somewhat between devices.

Please note, that CCS supports the automatic generation of the ECC code when downloading the binary to the target. This feature is enabled by default and could be configured in the Project Settings. It’s not possible to use both the CCS integrated ECC generation and Linker Generated ECC at the same time. The main difference between the two methods is, that with Linker Generated ECC the ECC code will be embedded in the binary (or ELF) file, whereas it’s generated on the fly by CCS. Let CCS handle the ECC is a grate usability improvement, however there are uses cases for Linker Generated ECC as, use of a gang programmer for production purpose, building a Firmware Update binary, or if you want to have the full control of all build steps.

Linker Command File Syntax The memory map for a device supporting Flash ECC may look something like this:

                VECTORS  : origin=0x00000000 length=0x000020
                FLASH0   : origin=0x00000020 length=0x17FFE0
                FLASH1   : origin=0x00180000 length=0x180000
                STACKS   : origin=0x08000000 length=0x000500
                RAM      : origin=0x08000500 length=0x03FB00
                ECC_VEC  : origin=0xf0400000 length=0x000004 ECC={ input_range=VECTORS }
                ECC_FLA0 : origin=0xf0400004 length=0x02FFFC ECC={ input_range=FLASH0  }
                ECC_FLA1 : origin=0xf0430000 length=0x030000 ECC={ input_range=FLASH1  }

The ECC specifier attached to the ECC memory ranges indicates the data memory range that the ECC range covers. The ECC specifier supports the following parameters:

input_range=<memory range>   The data memory range covered by the ECC
                        range; required.
input_page =<page number>    The page number of the input range; required
                        only if the input range's name is ambiguous.
algorithm  =<ECC algo. name> The name of an ECC algorithm defined later in
                        the command file; optional if only one
                        algorithm is defined. (see below)
fill       =<true/false>     Whether to generate ECC data for holes in the
                        initialized data of the input range; default
                        value is "true". Using fill=false will
                        produce behavior similar to the nowECC tool.

In addition to specifying the ECC memory ranges in the memory map, the command file must specify parameters for generating the ECC data. This is done with a new top level directive in the command file:

        algo_name : address_mask = 0x003ffff8
                                hamming_mask = FMC
                                parity_mask  = 0xfc
                                mirroring    = F021

This ECC algorithms directive accepts any number of definitions, which consist of an identifier, a colon, and some number of algorithm attributes. The following attributes are supported:

address_mask=<32-bit mask>  This mask determines what address bits are used
                       in the calculation of ECC.
hamming_mask=<FMC/R4>       This determines which data bits each ECC bit
                       encodes the parity for.
parity_mask =<8-bit mask>   This determines which ECC bits encode even
                       parity, and which bits encode odd parity.
mirroring   =<F021/F035>    This determines what pattern of duplication of
                       parity information is used in the ECC memory
                       for redundancy.

Each TI device supporting Flash ECC will have exactly one valid set of values for these parameters. The memory maps and ECC algorithm definitions for Flash ECC devices should be included in subsequent releases of Code Composer Studio. Users will not generally need to modify the preset values Error Injection

To enable users to test ECC error detection and handling, the compiler now supports two new command line options that inject bit errors into the linked executable. The compiler allows the user to specify an address where an error will appear and a bitmask that specifies which bits in the code/data at that address should be flipped. The address of the error can be specified absolutely, or as an offset from a symbol. When a data error is injected, the ECC for the data is calculated as if the error were not present. This is the syntax for the error injection options: .. code-block:: c

–ecc:data_error=(symbol+offset|address)[,page],bitmask –ecc:ecc_error=(symbol+offset|address)[,page],bitmask

The data_error version will inject errors into the load image at the specified location. The ecc_error version will inject errors into the ECC that corresponds to the specified location. Note that the ecc_error version can therefore only specify locations inside ECC input ranges, whereas the data_error version can also specify errors in the ECC output memory ranges.

For example, the following invocation of the compiler will flip the least significant bit in the byte at the address 0x100, making it inconsistent with the ECC for that byte:

armcl test.c --ecc:data_error=0x100,0x01 -z -o test.out

This invocation will flip two bits in the third byte of the code for main():

armcl test.c --ecc:data_error=main+2,0x42 -z -o test.out

This invocation will flip every bit in the ECC byte that contains the parity information for the byte at 0x200:

armcl test.c --ecc:ecc_error=0x200,0xff -z -o test.out

The compiler will disallow injecting errors into memory ranges that are neither an ECC range nor the input range for an ECC range. The compiler can only inject errors into initialized sections. VFILL Specifier

A small extension has been made to the fill value specifier for memory ranges in the linker command file. Normally, specifying a fill value for a memory range will create initialized data sections to cover any previously uninitialized areas of memory. To generate ECC for an entire memory range, the linker either needs to have initialized data for the entire range, or needs to know what value uninitialized memory areas will have at run time. To accommodate the case where the user wants to generate ECC for the entire memory range, but does not want to initialize the entire range by specifying a fill value, the new “vfill” specifier may be used instead of a “fill” specifier:

                FLASH : origin=0x0000  length=0x4000  vfill=0xffffffff

The vfill specifier is functionally equivalent to omitting a fill specifier, except that it allows ECC generation to occur for areas of the input memory range that remain uninitialized. This has the benefit of reducing the size of the resulting object file. The vfill specifier has no effect other than in ECC generation. It cannot be specified along with a fill specifier, since that would introduce ambiguity.

7.1.2. Settings for Hercules MCU’s TMS570LS20x/10x

ECC algorithm

                        algoR4F035 : address_mask = 0x003ffff8 /* Address Bits 21:3 */
        hamming_mask = R4         /* Use R4 build in Mask */
        parity_mask  = 0x0c       /* Set which ECC bits are Even and Odd parity */
        mirroring    = F035       /* TMS570LS20x/10x are build in F035 */

Example Memory Map for TMS570LS20x

#define FLASH_ECC_ORIGIN  (0x00400000)

        /* Flash Memory */
        /* Bank 0 */
        VECTORS (X)  : origin=0x00000000 length=0x00000020  fill=0xFFFFFFFF
        FLASH0  (RX) : origin=0x00000020 length=0x0007FFE0 vfill=0xFFFFFFFF
        /* Bank 1 */
        FLASH1  (RX) : origin=0x00080000 length=0x00080000 vfill=0xFFFFFFFF
        /* Bank 2 */
        FLASH2  (RX) : origin=0x00100000 length=0x00080000 vfill=0xFFFFFFFF
        /* Bank 3 */
        FLASH3  (RX) : origin=0x00180000 length=0x00080000 vfill=0xFFFFFFF
        /* Bank 0 ECC */
        ECC_VEC      : origin = (FLASH_ECC_ORIGIN+(start(VECTORS)>>1))
                                        length = (size(VECTORS)>>1)
                                        ECC    = {algorithm=algoR4F035, input_range=VECTORS}
        ECC_FLA0     : origin = (FLASH_ECC_ORIGIN+(start(FLASH0)>>1))
                                        length = (size(FLASH0)>>1)
                                        ECC    = {algorithm=algoR4F035, input_range=FLASH0}
        /* Bank 1 ECC */
        ECC_FLA1     : origin = (FLASH_ECC_ORIGIN+(start(FLASH1)>>1))
                                        length = (size(FLASH1)>>1)
                                        ECC    = {algorithm=algoR4F035, input_range=FLASH1}
        /* Bank 2 ECC */
        ECC_FLA2     : origin = (FLASH_ECC_ORIGIN+(start(FLASH2)>>1))
                                        length = (size(FLASH2)>>1)
                                        ECC    = {algorithm=algoR4F035, input_range=FLASH2}
        /* Bank 3 ECC */
        ECC_FLA3     : origin = (FLASH_ECC_ORIGIN+(start(FLASH3)>>1))
                                        length = (size(FLASH3)>>1)
                                        ECC    = {algorithm=algoR4F035, input_range=FLASH3}
        /* embedded SRAM */
        STACKS  (RW) : origin=0x08000000 length=0x00001500
        RAM     (RW) : origin=0x08001500 length=0x00026B00
} TMS570LS and RM4x

ECC algorithm

                                algoR4F021 : address_mask = 0x003ffff8 /* Address Bits 21:3 */
                                hamming_mask = R4         /* Use R4 build in Mask */
                                parity_mask  = 0x0c       /* Set which ECC bits are Even and Odd parity */
                                mirroring    = F021       /* RM4x and TMS570LSx are build in F021 */

example Memory Map for RM42L432 and TMS570LS0432

/* Bank 0 (384kB) */
VECTORS (X)  : origin=0x00000000
FLASH0  (RX) : origin=end(VECTORS)
                                length=(0x00060000 - size(VECTORS))
/* Bank 7 (FEE) */
FLASH7   (R) : origin=0xF0200000
/* Bank 0 ECC */
ECC_VEC  (R) : origin=(0xf0400000 + (start(VECTORS) >> 3))
                                length=(size(VECTORS) >> 3)
                                ECC={algorithm=algoR4F021, input_range=VECTORS}
ECC_FLA0 (R) : origin=(0xf0400000 + (start(FLASH0)  >> 3))
                                length=(size(FLASH0)  >> 3)
                                ECC={algorithm=algoR4F021, input_range=FLASH0 }
/* Bank 7 ECC */
ECC_FLA7 (R) : origin=0xF0100000
                                length=(size(FLASH7)  >> 3)
                                ECC={algorithm=algoR4F021, input_range=FLASH7 }
/* Embedded SRAM (32kB) */
STACKS  (RW) : origin=0x08000000
RAM     (RW) : origin=end(STACKS)
                                length=(0x00008000 - size(STACKS))

7.1.3. The_SECTIONS_Directive

Since the ECC on all current Hercuels devices is calculated on a 64 bit or 8 byte boundary all data and code sections which are placed in the on-chip flash should also be aligned to a 64 bit boundary. They furthermore should also end at 64 bit boundaries to ensure that the complete section will have a length of a multiple of 64 bits and is entirely be initialized. The easiest way to achieve this to use palign(8) on all output sections ind the Linker Command File which will be placed in the on-chip flash. In an LCF this could look like the following:

               .intvecs    : {} palign=8 > VECTORS

               .text       : {} palign=8 > FLASH0 | FLASH1 /* Executable code and constants */
               .const      : {} palign=8 > FLASH0 | FLASH1 /* Global and static const variables that are explicitly initialized */
               .cinit      : {} palign=8 > FLASH0 | FLASH1 /* Tables for explicitly initialized global and static variables */
       #ifdef __TI_EABI_SUPPORT__
               .init_array : {} palign=8 > FLASH0 | FLASH1 /* C++ global constructor addresses */
       #else /* TI_ARM9_ABI and TIABI */
               .pinit      : {} palign=8 > FLASH0 | FLASH1 /* C++ global constructor addresses */
               .stack      : {} > STACKS /* Stack */
               .bss        : {} > RAM    /* Uninitialized global and static variables */
               .data       : {} > RAM    /* Global and static non-const variables that are explicitly initialized. */
               .sysmem     : {} > RAM    /* Memory pool (heap) for dynamic memory allocation */

Description of palign() copied from SPNU118 Alignment With Padding As with align, you can tell the linker to place an output section at an address that falls on an n-byte boundary, where n is a power of 2, by using the palign keyword. In addition, palign ensures that the size of the section is a multiple of its placement alignment restrictions, padding the section size up to such a boundary, as needed.

7.2. LAUNCHXL2-570LC43-RM57L_LinkerECCRecommendation

7.2.1. Motivation

For the TMS570LC4357 and RM57L843 devices, ECC protection of Flash and SRAM memories is always enabled. This differs from Hercules devices in the TMS570LS and RM4 series where ECC is disabled after reset and remains disabled until enabled by software. Generally this is a good thing!

But it also means that it is a lot more likely that you will see the RED ERR LED go on during development. A common reason for this to occur is that erased flash is full of ECC errors! So if you erase the entire (4MByte) flash, then program a tiny “Hello World” into the part, most of the flash will still contain ECC errors. All it takes to trip the RED error LED is a read from an area of flash left with ECC errors. This can happen intentionally (say you run a CRC over the entire 4MBytes - even though you’re not using it) or it can happen unintentionally (the CPU performs speculative pre-fetches).

7.2.2. The Solution

The solution to frequent ECC related errors during development is avoid them by making sure all of the ECC data is programmed - in other words program correct ECC values even for the locations in the main flash array that are left unused. The easiest way to achieve this is to use the Linker to generate ECC data rather than the loader.

This can be accomplished by changing:

  1. The Linker Command File
  2. The Flash Loader Settings for your Project

7.2.3. Changes to the Linker Command File

If your linker command file has not already been updated (as of 5/28/2015 this includes the default linker command files shipped with HALCoGen). You will want to make the following changes.

  1. Add a vfill = 0xFFFFFFFF directive to the end of each line that maps to Flash in the Memory{} section of the command file.
  2. Add memory regions corresponding to the ECC area of the flash bank to the Memory{} section
  3. Add an ECC {} directive describing the algorithm that matches the device

The first change, the addition of the vfill, affects only the ECC generation. It instructs the ECC generator to treat the flash as if it were filled with the value 0xFFFFFFFF. It`s a virtual fill, because the loader doesn`t need to download 4MBytes - Your Program Size of 0xFFFFFFFF if it erases the flash first (since the erased state is 0xFFFFFFFF).The second change tells the linker how to create the data for the ECC area of flash. The ‘origin’ is the area of the device memory map where you can read and program the ECC values directly. The input range specifies the data over which ECC is calculated. Finally the ECC{} directive just has a description of the algorithm that the linker needs to use; different TI parts are designed with slightly different ECC equations. Here’s a modified linker command file that you can use in place of the one provided by HALCoGen. Actually it is the linker command file from HALCoGen, with the changes described above entered in the /* USER CODE */ blocks so that they will be preserved even if you regenerate your project.

  • HL_sys_link.cmd Modified file for HALCoGen Projects Using Linker ECC

7.2.4. Changes to CCS Flash Loader Settings

Once you make the changes to your linker command file so that the linker generates ECC for your project, it is necessary to change the loader settings so that the loader doesn’t also

try to generate ECC. Also verification during programming needs to be skipped because the data areas and ECC areas will now be programmed in separate steps.

You can access these settings in your project properties, under the Debug category. Select “Flash Settings” as shown below and make sure:

  • System Reset on Connect is checked
  • Auto ECC Generation is unchecked
  • Align program segments to 64-bit memory regions is checked
  • Flash Verification Settings should be ‘None’
  • Perform Blank Check before Program Load must be unchecked
  • Remember to Press “APPLY” or your changes will not be saved!

7.3. Hercules USB Device Driver and CDC Class

7.3.1. Introduction

The Hercules USB stack is an OS-independent USB solution that is migrated from the StellarisWare USB solution.

7.3.2. Features

  • Supports USB Device
  • Interrupt driver IO Transfers (DMA Transfers are not supported)
  • Support for CDC ACM

7.3.3. Limitations

  • DMA Transfers are not supported

7.3.4. Requirements Software

  • Requires CCS v10.1.0 with CGTools TI v20.2.1.LTS and later version
  • HALCoGen 4.07.01 Release Hardware

  • RM48L950 HDK

7.3.5. Software Architecture

The following diagram shows the architecture of the USB stack.

../../_images/HowTo_USB_CDC_Architecture.png Hardware Abstraction Layer

Hardware Abstraction Layer (HAL) is the lower most layer of the stack and is the only layer that directly communicates with the USB Device controller. This layer abstracts all the functionalities and services used by upper layers to configure and control the USB device controllers. The HAL is implemented in a single file (USB.C). Device Core Layer

The device core layer is responsible for device enumeration and handling all of the control transfers. Interrupt service routines are part of this layer. Typical tasks handled by device core layers are as follows:

  • Device Controller Initialization via HAL
  • USB Device Enumeration
  • Interrupt handling (EP0 & EPn)
  • Standard request handling & forwarding to class specific handlers
  • Terminate the device controller driver
The initialization APIs are called by the class driver in order to start the enumeration process. Once the enumeration has started, all of the standard request routines are called from the ISR in response to the appropriate interrupt event. For any class-specific request, the application or class driver must register the callback handler with the core so that the ISR can branch when necessary.
The device core layer is implemented by a single source file USBDENUM.C. USB Configuration Layer

This layer contains all of the parameters required to configure the USB device. These parameters include VID, PID, Descriptors, event handlers, buffers, and more. These parameters are specified by the application writer. Once all the information is fed in to this layer, the configuration layer can give a device instance structure to the other layers within the USB stack. This device instance contains all of the information regarding the device, and the required information is extracted when necessary.
This layer is considered to be part of application, and most of the data is specified by the application programmer. This layer is implemented by the source file USB_SERIAL_STRUCTS.C. The following parameters are configurable by the application programmer:
  • Global instance for the USB device structure
  • Rx and Tx Buffers
  • Vendor ID
  • Product ID
  • Power configuration parameters
  • Control event call backs
  • Application event call backs
  • String descriptors
  • Language descriptor

7.3.6. CDC Device Class


The USB Communication Device Class (CDC) class driver supports the CDC Abstract Control Model (ACM) variant and allows a client application to be seen as a virtual serial port to the USB host system. The driver provides two channels: one transmit and one receive. The channels may be used in conjunction with USB buffers to provide a simple read/write interface for data transfer to and from the host. Additional APIs and events are used to support serial link-specific operations such as notification of UART errors, sending break conditions, and setting communication line parameters. The data transmission capabilities of this device class driver are very similar to the generic bulk class, but (because this is a standard device class) the host operating system should be able to access the device without the need for any host-side drivers. On Windows, a simple INF file is all that is required to make the USB device appear as a COM port that can be accessed by any serial terminal application. This device class uses three endpoints in addition to endpoint zero. Two bulk endpoints carry data to and from the host and an interrupt IN endpoint is used to signal any serial errors such as break, framing error, or parity error detected by the device. Endpoint zero carries standard USB requests and also CDC-specific requests which translate to events passed to the application via the control channel callback. This layer is implemented in the source file USBDCDC.C. CDC Device Enumeration


The Application main must perform the following steps:

  • Configure the system interrupts
  • Register the interrupt handler (i.e. ISR)
  • Initialize the buffers
  • Call USBDCDCInit() with the device instance structure as a parameter

With this call, control is given to the CDC device class layer. The device class layer must perform the following steps:

  • Assign endpoints to the device instance structure
  • Apply the configuration descriptor to the device instance structure
  • Call USBDCDInit() and pass the device instance structure to the core

With this call, control is passed to the core layer. The core layer must perform the following steps in order to complete enumeration:

  • Reset the USB module
  • Switch on the USB PHY
  • Clear all pending interrupts
  • Enable the required interrupts
  • Set the configuration parameters
  • Disconnect the device
  • Reconnect the device

Now the device will start receiving interrupts from the host. The interrupt handler in the core layer will identify all of the EP0 interrupts and call the appropriate handler. If all the standard requests are serviced by the device, then enumeration is complete and the device is ready for communication. Now control return to the application and wait for data interrupts. CDC Application Data Flow

../../_images/HowTo_USB_CDC_Application_Data_Flow.png Data out Flow (From Host to Device)

When data arrives from the host, the device will receive an interrupt from the host. The interrupt handler must perform the following steps on reception:

  • Read the interrupt status register
  • Identify the interrupt
  • Call the appropriate handler (i.e. Read Data handler)
  • Read handler checks whether the RX Packet Ready bit is set
  • Check the number of byte available in the buffer
  • Read the data to buffer
  • Clear the RX Packet Ready bit
  • Give the read data to the application
../../_images/HowTo_USB_CDC_Data_Flow_Out.jpg Data in Flow (From Device to Host)

When the device side application needs to send data to the host, the device must follow the below steps.

  • Application calls the write data API and passes the data buffer to the CDC layer
  • Write data API checks the amount of data to be sent
  • Copy data the TX buffer
  • Set the TX Packet Ready bit
  • After the transmit operation completes, the host sends a TX completion interrupt
  • TX Packet Ready bit will be cleared automatically
  • After receiving the TX Complete Interrupt, the ISR sends an event to the application indicating the completion of data transfer

7.3.7. Creating a new CDC Device Application using HALCoGen

HALCoGen GUI can be used to create the required descriptors & configurations for USBD CDC Application. Following are details steps to create & configure a new CDC application using HALCoGen. Step 1: Enable USBD Drive

../../_images/HowTo_USB_CDC_New_App_1.png Step 2: Enable PINMUX for USBDevice peripheral

../../_images/HowTo_USB_CDC_New_App_2.jpg Step 3: Setup 48MHz clock on VCLKA3_S for USBD

Following screen shots demonstrate usage of PLL2 for VLCKA3 clock source (on PLL tab).

../../_images/HowTo_USB_CDC_New_App_3.png Step 4: Setup PLL2 as clock source for VCLKA3_S

../../_images/HowTo_USB_CDC_New_App_4.png Step 5: Update stack sizes

Since majority of the USBD stack executes in interrupt context, the stack size has to be increased as shown below

../../_images/HowTo_USB_CDC_New_App_5.jpg Step 6: Configure USB descriptors

Configure USB descriptors and other items specific to USBD CDC Stack. These options are available under the ‘USB’ tab.

Note: Since the string descriptors are in Unicode, one must manually convert the ASCII test to Unicode (Eg., ‘ABC’ should be entered as ‘A’,‘0’,’B’,‘0’,’C’,‘0’). The character count for each string must be manually updated for size of the Unicode string (eg., Size of A’,‘0’,’B’,‘0’,’C’,‘0’ shall be 4).

The manufacturer string (Texas Instruments): ‘T’, 0, ‘e’, 0, ‘x’, 0, ‘a’, 0, ‘s’, 0, ‘ ‘, 0, ‘I’, 0, ‘n’, 0, ‘s’, 0, ‘t’, 0, ‘r’, 0, ‘u’, 0, ‘m’, 0, ‘e’, 0, ‘n’, 0, ‘t’, 0, ‘s’, 0

The product string (Virtual COM Port): ‘V’, 0, ‘i’, 0, ‘r’, 0, ‘t’, 0, ‘u’, 0, ‘a’, 0, ‘l’, 0, ‘ ‘, 0, ‘C’, 0, ‘O’, 0, ‘M’, 0, ‘ ‘, 0, ‘P’, 0, ‘o’, 0, ‘r’, 0, ‘t’, 0

The serial number string (RM48L950): ‘R’, 0, ‘M’, 0, ‘4’, 0, ‘8’, 0, ‘L’, 0, ‘9’, 0, ‘5’, 0, ‘0’, 0

The control interface description string (ACM Control Interface): ‘A’, 0, ‘C’, 0, ‘M’, 0, ‘ ‘, 0, ‘C’, 0, ‘o’, 0, ‘n’, 0, ‘t’, 0, ‘r’, 0, ‘o’, 0, ‘l’, 0, ‘ ‘, 0, ‘I’, 0, ‘n’, 0, ‘t’, 0, ‘e’, 0, ‘r’, 0, ‘f’, 0, ‘a’, 0, ‘c’, 0, ‘e’, 0

The configuration description string (Self Powered Configuration): ‘S’, 0, ‘e’, 0, ‘l’, 0, ‘f’, 0, ‘ ‘, 0, ‘P’, 0, ‘o’, 0, ‘w’, 0, ‘e’, 0, ‘r’, 0, ‘e’, 0, ‘d’, 0, ‘ ‘, 0, ‘C’, 0, ‘O’, 0, ‘N’, 0, ‘F’, 0, ‘I’, 0, ‘G’, 0, ‘U’, 0, ‘R’, 0, ‘A’, 0, ‘T’, 0, ‘I’, 0, ‘O’, 0, ‘N’, 0

../../_images/HowTo_USB_CDC_New_App_6.png Step 7: Enable the USBD Interrupts on ‘VIM Channel 63-94’ tab

../../_images/HowTo_USB_CDC_New_App_7.png Step 8: Setup the interrupt service routines for USBD on ‘VIM RAM’ tab

../../_images/HowTo_USB_CDC_New_App_8.png Step 9: Generate the code Step 10: Integrating the CDC Example application

An example CDC application is provided HALCoGen release and is present in <install folder>examplesRM48xexample_usbd_cdcexample_usbd_cdc.c. This file needs to be copied & replaced in <code generation folderSourcesys_main.c

../../_images/HowTo_USB_CDC_New_App_10.png Step 11: Create a CCS Project

Following is a screenshot of the project settings used during creation. Note that USB device is available only on RM48xx devices (Little Endian).

../../_images/HowTo_USB_CDC_New_App_11.png Step 13: Compiler setting changes

USBD CDC Stack uses packed structures for the descriptors. Hence appropriate options should be enalbled in the compiler settings. Following two screenshots indicate the settings to be enabled.

../../_images/HowTo_USB_CDC_New_App_12.png Step 14: Update build settings

Update the project build settings to include the ‘include’ folder generated by HALCoGen. Step 15: Miscellaneous changes to project

Since the main() function is part of the example application, from Step# 10, delete the main.c that is generated during CCS project creation.

void main(void)
    /* USER CODE BEGIN (3) */
        uint8 ucBuffer[64];
        volatile uint32 ulDataWrote = 0,  ulTemp = 0;

        /* Enable the interrupts in CPSR register */
        /* Enable the SCI for console output */

        /* Dispaly welcome message */
        sciDisplayText(scilinREG, txtCRLF, sizeof(txtCRLF));
        sciDisplayText(scilinREG, txtTI, sizeof(txtTI));
        sciDisplayText(scilinREG, txtCRLF, sizeof(txtCRLF));
        sciDisplayText(scilinREG, txtTitle, sizeof(txtTitle));
        sciDisplayText(scilinREG, txtCRLF, sizeof(txtCRLF));

        #ifdef __little_endian__
            sciDisplayText(scilinREG, txtLittleEndian, sizeof(txtLittleEndian));
            sciDisplayText(scilinREG, txtCRLF, sizeof(txtCRLF));
            sciDisplayText(scilinREG, txtBigEndian, sizeof(txtBigEndian));
            sciDisplayText(scilinREG, txtCRLF, sizeof(txtCRLF));

        //Initialize the USB Rx and TX Buffers
        USBBufferInit((tUSBBuffer *)&g_sTxBuffer);
        USBBufferInit((tUSBBuffer *)&g_sRxBuffer);

        //Pass our device information to the USB library and place the device on the bus.
        USBDCDCInit(0, (tUSBDCDCDevice *)&g_sCDCDevice);

        // See if we have rcvd any data. Echo any rcvd data
        while(1) {
                if (USBBufferDataAvailable((tUSBBuffer *)&g_sRxBuffer) > 0) {
                        do {
                                ulTemp = USBBufferRead((tUSBBuffer *)&g_sRxBuffer, ucBuffer, 1);
                                if (ulTemp > 0) {
                                        USBBufferWrite((tUSBBuffer *)&g_sTxBuffer, ucBuffer, 1);
                        } while (ulTemp > 0);
} Step 16: Changes to HDK Jumper settings

Before executing the binary file ensure that the USBD switch is ON (HDK S2 Switch3 must be in ON position) DIP switches in S2 were OFF, OFF, ON, OFF (only USBD ON was on). Step 17: Build, Flash & Execute the binary Step 18: Windows (Win32) Drivers

Windows Driver INF file for Windows7 is present in examplesRM48xexample_usbd_cdc folder.

Make sure that your project is loaded on the HDK and *running* (not halted at a breakpoint) when you plug in the USB B cable.

Worked Example Files

Here is a project built with HalCoGen 10.01.00 and tested on an RM48 HDK. The usb cdc example is at: http://git.ti.com/hercules_examples/hercules_examples/trees/master/Application/