Friday, July 25, 2014

CC3200 LaunchPad with external debugger and ARM GCC in Eclipse

Hot stuff! I got the board and read most of the the documentation, examples and APIs. It's time for debugging now. Since I don't like bulky SDKs that come for each eval board I tend to extract what I need from them (installing to virtual machine) and use external debugger. Modifications to connect external debugger are depicted below. No HW changes are needed on this one. TI made it all configurable with jumpers. There are 2 changes made:
  • SOP pins are configured to enable SWD (Single Wire Debug).
  • Debug lines are disconnected from on board FTDI debugger. External debugger is connected to freed debug pins via 3 lines SWDIO(TMS), SWDTCK(TCK) and GND. Let's not get into why 3 lines are needed for Single Wire Debug :).
I stopped boot in endless loop after connecting to it. I made simple while(1) empty loop project. Downloaded it to beginning of the RAM (0x20000000) and it worked.
I'm still not sure about clock settings. It doesn't seem that any PLL needs initializing...
[UPDATE]
I did sample project without any PLL code and it worked.

Also I didn't get SWO (Single Wire Output) to generate any output from ITM (Instrumentation Trace Macrocell). I know ITM was configured properly because it worked on some other devices. That only leaves IO configuration which I did with enabling GPIO3CLKEN clock, configuring corresponding GPIO_PAD_CONFIG_24 and set pin as output by setting GPIOA3[0]. Scope didn't show anything on TDO pin when writing ITM stimulus registers. Did anyone manage to get trace output ?
[UPDATE]
I added following code to initialize SWO pin without success:
PRCMPeripheralClkEnable(PRCM_GPIOA3, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK | PRCM_DSLP_MODE_CLK);
PinModeSet(PIN_17, PIN_MODE_1);
PinConfigSet(PIN_17, PIN_STRENGTH_6MA, PIN_TYPE_STD);
PinDirModeSet(PIN_17, PIN_DIR_MODE_HW);
It works! Apparently TDO is not the pin to get SWO out. Pins 45, 53 and 50 are according to CC3200 forum. Anyway, connecting iTag to 53 and adding code below did the trick.
PinModeSet(PIN_53, PIN_MODE_13);


CC3200-LAUNCHXL + iTAG

[UPDATE]
Created Eclipse C projects for CC3200 libs are available in repository. Short note for building: download CC3200 SDK separately (or extract from CCS installation). Library folders contain RefreshFiles.bat script invoked with CC3200 path to copy needed files to project folder.

While playing with integrated HTTP server I got frustrated with constant terminal to Uniflash tool UART switching. I decided to use UART Tx pin multiplexed with JTAG, which was not used since I'm using SWD.
To utilize it I added FTDI MM232R USB to serial module. I only connected CC3200 Tx to MM232R Rx for printf() tracing. Unconnected pin on LAUNCHPAD debug pinhead (J11) could be used for sending serial data to CC3200.
Code for UART initialization:
#define PRCM_UART_TERM PRCM_UARTA1
#define PIN_TERM_TX PIN_16
#define PIN_TERM_TX_MODE PIN_MODE_2
#define PIN_TERM_RX PIN_17
#define PIN_TERM_RX_MODE PIN_MODE_2
#define UART_TERM UARTA1_BASE
#define PRCM_UART_TERM PRCM_UARTA1

PRCMPeripheralClkEnable(PRCM_UART_TERM, PRCM_RUN_MODE_CLK);
PinTypeUART(PIN_TERM_TX, PIN_TERM_TX_MODE);
UARTConfigSetExpClk(UART_TERM,
                    MAP_PRCMPeripheralClockGet(PRCM_UART_TERM),
                    115200,
                    (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

and code for sending single character:
UARTCharPut(UART_TERM, ch);

CC3200-LAUNCHXL + iTAG + MM232R

CC3200-LAUNCHXL to MM232R closeup

Soon after I realized I can capture serial data with iTAG debugger since SWD leaves pins for capturing SWO and iTAG can be configured to dump UART data from that pin to terminal window.
CC3200-LAUNCHXL + iTAG with UART capturing

CC3200-LAUNCHXL + iTAG with UART capturing (iTAG closeup)

CC3200-LAUNCHXL + iTAG with UART capturing (LAUNCHPAD closeup)

Programming SPI flash without Uniflash through debug port

With setup above updating the SPI flash content still requires disconnecting the debug session, switching SOP jumper to 'FLASH' position and resetting the board to program files with TI Uniflash tool.

For development purposes I wrote small monitor application to run on CC3200 and Python script controlling the execution of the monitor through debugger to write files to SPI flash, e.g. write file data to CC3200 RAM and trigger function calling SimpleLink lib to write the data to file. Scripting is supported by winIDEA, IDE used with iTAG debugger and iSYSTEM.Connect API. My intention was to first format the flash and then program all files in specified folder. It turned out that formatting is not supported by library (only Uniflash tool). As workaround first SPI flash must be erased on low (SPI) level, then formatted with Uniflash tool and all data from flash read to be later used as "empty" image. This is done once. SPI access is provided in the script. Later on every update of the files the script erases the flash, programs "empty" image to it and then calls SimpleLink lib to create and write files. See script for more details.

Recording ITM printf() messages on SWO

Tested on pin 53 as mentioned in update above. Don't get confused by the photo below. I'm using white wire for SWO. SWO is configured by debugger to output at 4Mbits/second. CPU speed and SWO prescaler settings in winIDEA must be configured for this. Following equation applies: BAUD = CPUclk/(SWOprcs + 1) -> 80MHz/(19 + 1) = 4MHz.

White wire connected from pin 53 configured as SWO to TDO input on iTag

4M BAUD configured in winIDEA



Monday, July 21, 2014

Communication with embedded devices

It is always a hassle to communicate with embedded device. I do manage one time solution e.g. through USB to UART converter but it is always too much interleaved with application code to later switch to integrated USB peripheral.

Sometimes in the past I got requests to provide new or additional way of communication for device. Another use case I wrote this library for is when I found myself repeating writing same code. I had point to point serial communication implemented on some project. On another project I used serial bus approach (with CAN physical drivers - not important) and the communication was identical with addition of the byte header for destination address at the beginning of each packet. Repetition also happened on client and host side.

In short, Comm library offers a way to make communication entities modular thus easily replaceable. It also makes them stackable to make the whole through communication extending easy. First library implementation is in C [Google Code repository].

Communication is meant to be of  query - response from master (client) to slave (host). The use of library enforces a way of transmission and reception but the same design can be used on both sides of communication channel. This means that layer can have same implementation on client and host  side if both running on the same hardware platform.


From library point of view the communication entity is self sufficient communication layer implementing a set of predefined functions i.e. implementing an interface. As it turned out layers are of two types. In one stack there are more data formatting layers and single physical layer.

Physical layers are in charge of data storage and thus having communication buffer. Example of a layer on top of physical would be an encryption layer. Application interacts with Comm library functions when transferring data. Library then calls Comm layer implementation as needed. All functions have C++ style “this” pointer parameter. In the application accessible library functions this is a predefined Comm stack type holding a pointer to array of another predefined type instances each describing single Comm layer implementation. Comm layer instance is used as the "this" pointer in layer implementation functions and in library functions used for data transfer between layers. Comm layer instance has 5 pointers:
  • vague void pointer member to store reference to a custom type object for specific implementation
  • pointer to predefined type object holding function pointers of layer implementation
  • pointers to upper and lower layer if any
  • pointer to Comm stack to which layer belongs.

Instance custom pointer and pointer to functions are initialized in extra initialization function call which is custom for each specific layer implementation and additionally exposed to the application together with a custom instance type. This initialization function is not to be mistaken with layer implementation initialization function.
Pointers to surrounding layers and pointer to parent stack are initialized in library initialization call which should result in established connection after return.
Or everything again in objective language words: main communication stack object has methods for communication and holds references to layer objects each implementing the defined interface and custom init method which is only method called by application directly.
Below is a general sequence and internal states of the objects after each initialization step:

Initial state.

After first layer custom initialization call.

After last layer custom initialization call.

After Comm library initialization call.
Next to custom and implementation initialization method a Comm layer implements data transfer, event notification, and process methods.

Data transfer methods:

  • Send
    To send data in direction from application towards physical layer. Layer can optionally implement this method to transform data or add data to sent data. Additional data must be then in same fashion removed on receiving side in OnData call.

  • Store
    To save data in comm buffer. Called from OnData call back from upper layer. Usually only implemented in lowest, physical layer.

  • OnData
    To optionally unpack received data. Called from lower layer ReceiveProcess when new data received. Here is a chance to undo the changes to data made in Send and in PacketStart and in PacketEnd on transmitting side. If implemented it must forward remaining data with chained OnData call to upper layer or call Store if there is no upper layer like library does.

Event notifications:

  • PacketStart
    First call from application when sending a packet. Lower layers get this call first, upper last. Each layer can already put own header to transmitted packet with call to Send. This call gives layers a chance to clean up from previous application packet transfer. Send call(s) will follow.

  • PacketEnd
    Last call from application when sending a packet. Upper layers get this call first to append custom data to the packet with call to Send if needed. Physical layer can start actual transmission in this call.

  • OnNewPacket
    Call originates in physical layer ReceiveProcess method when start of new packet is detected. Here is a chance for layers to prepare for new packet. OnData call(s) will follow.

  • OnPacketEnd
    Called from physical layer ReceiveProcess  after complete packet was received.

Process methods:

  • TransmitProcess
    Called repeatedly from application after PacketEnd. Usually only implemented in physical layer. Returns Active status while data is being sent to medium and returns Idle status after all data is sent.

  • ReceiveProcess
    Called repeatedly from application to receive a packet. Usually only implemented in physical layer. Returns Idle status while there is no incoming data, optionally returns Active status while data is being received and returns NewPacket status after whole packet is received. Together with NewPacket status it returns the size of the packet and pointer to received data.

Flow of calls to send and receive the data with Comm library is as depicted below.

First call in client to send a packet to client; first call on host to send response.
PacketEnd behaves identically. Physical layer can start sending data in PacketEnd call.

Multiple calls to send data on client and host.

Multiple calls while transmitting data on client and host.

Repeatedly called on client while expecting a response from host; repeatedly called on host while waiting for new packet. OnPacketEnd behaves identically.

Repeatedly called on client while expecting a response from host; repeatedly called on host while waiting for new packet.
For test implementation I did a pair of embedded STM32F4 project and Windows client application communicating over USB. Windows side uses WinUSB library for communication and firmware reports a OS USB descriptor associating device with WinUSB driver so drivers or .inf files are not needed. Firmware code is in C and Windows client application uses C++ in Windows only code.

WinUSB communication with STM32 round 2 (Part 2: Client)


Previous client application is linked against WinUSB and SetupAPI libraries. This was a bit of a bother with WDK and project settings. They are loaded dynamically in new client test application. Two thin wrappers load the libraries and provide needed function calls with same prototypes as original library functions. SetupAPI is needed at low level for enumeration and when creating connection. WinUSB is further wrapped in an object representing USB device. And later wrapped in Comm interface explained in another post.
USB device object uses two USB pipes to transfer data which takes two USB endpoints in bulk mode at device side. One for sending data to device and other to receive it. Messaging control is done through USB control endpoint. Transfer sequence is optimized from previous implementation. Sending a complete application packet consists of sending a control message with the 32 bits length of the packet and then writing the packet data to bulk pipe. Receiving a packet is done with reading the return size through the control endpoint util nonzero length is returned and then reading the packet data from second endpoint. Application packet is meant to be a complete data set needed for single operation on device and can be larger than endpoint buffer.
Comm wrapper mentioned earlier is an implementation of the layer interface as specified by Comm library. Comm library core utilizes this interface to make transferring of data easier to application. WinUSB Comm layer is written to be the last layer in stack, also referred to as "physical" layer as is the closest to the physical medium on the master (client) side - Windows PC.
Application is written to test the connection and speed. Device is expected to return same data as sent by application. Speed is calculated from time it takes to send and receive back the packet.

Application uses Comm library methods to transfer the data. It is just that the Comm library object is initialized with comm layer using USB. It could instead be some other communication type, e.g. serial port or TCP/IP.

[Source files]

This is the second post in this series (of total 2 posts). See 1.

Thursday, May 8, 2014

ARMv7 coprocessor access

Macros below generate little endian ARM (not THUMB) instructions for access to coprocessor. This for when instructions can't be compiled but rather stored in table as data.

// MCR<c> <coproc>, <opc1>, <rt>, <crn>, <crm>{, <opc2>}
// Read coprocessor register (no condition)
#define A_MRC(coproc, opc1, Rt, CRn, CRm, op2)  (0xEE100010 | (((opc1) & 0x7) << 21 ) | (((CRn) & 0xF) << 16 ) | (((Rt) & 0xF) << 12 ) | (((coproc) & 0xF) << 8) | (((op2) & 0x7) << 5)) | ((CRm) & 0xF)
// Write coprocessor register (no condition)
#define A_MCR(coproc, opc1, Rt, CRn, CRm, op2)  (0xEE000010 | (((opc1) & 0x7) << 21 ) | (((CRn) & 0xF) << 16 ) | (((Rt) & 0xF) << 12 ) | (((coproc) & 0xF) << 8) | (((op2) & 0x7) << 5)) | ((CRm) & 0xF)


Saturday, May 3, 2014

WinUSB communication with STM32 round 2 (Part 1: Firmware)

Introduction


I did another WinUsb device. This time I've used STM32F4. Project in Google Code repository is for STM32F4DISCOVERY board featuring STM32F407VGT6.
I wanted to make it so that it wouldn't need Windows side driver information in a form of .inf file. I did it with Windows OS USB descriptors. They are described in subsection on MS "Dev Center - Hardware" Drivers page (links at the end of post). 



Result of device providing these descriptors is Windows loading one of MS provided drivers and associating the device with it as instructed in descriptor gotten from device when plugged in USB port.
"MS provided drivers" are not to be mistaken with "USB device class drivers included in Windows" which are drivers for external HDDs, webcams, HIDs...
WinUSB is one of MS provided drivers providing raw communication with device, e.g. WriteBuffer/ReadBuffer. This means that PC side application and firmware in device must follow some defined communication protocol. These are well defined for standard class USB devices like mouse and keyboard or external HDD but with WinUSB custom protocol can/must be defined. It can be quite simple like adding 4 byte header to transferred buffer holding the length of buffer.

[Update] Windows enumeration

While preparing PC side demo application to demonstrate communication I found out that categorization differs for single interface devices and composite multiple interface devices. Image above shows 2 devices in  device manager each plugged in own USB port and each with single USB interface associated with WinUSB driver. So does the image below with additional Properties window.
Single device with single WinUSB driver associated interface. 

But notice how composite device (having multiple USB interfaces) is shown on next image. Two WinUSB  associated interfaces were reported in descriptors by device:
Single device with two WinUSB driver associated interfaces.
Three devices are shown in Device Manager. One Composite device and two WinUSB devices - one for each interface. WinUSB devices have Composite device set as parent. Note how "Bus reported device description" differs for single interface device from dual interface device.
To test both configuration un/comment WINUSBCOMM_DUAL_INTERFACE_TEST macro in usbd_WinUSBComm.h file.

Windows OS USB descriptors


Text below refers to 'interfaces'. Term is used for a set of endpoints/pipes used in a group. Interfaces have own descriptors.

MS OS String Descriptor


When device is plugged in USB port for the first time on a Windows machine it also receives a standard USB string descriptor request requesting the string descriptor with index 0xEE among other requests during enumeration. For first few indices device responds with standard string descriptors which are Manufacturer, Product and Serial strings (also Language IDs for index 0). Device can ignore 0xEE string descriptor request or respond with data predefined by MS. If so Windows will then query for additional MS specific descriptors:
  • Extended Compat ID OS Descriptor
  • Extended Properties OS Descriptor
  • others not relevant here
The content of MS OS String Descriptor must be:

Value Field Size in Bytes Description
0x12,
bLength
1
Length of the descriptor
0x03,
bDescriptorType
1
Descriptor type - string
0x4D, 0x00,
0x53, 0x00,
0x46, 0x00,
0x54, 0x00,
0x31, 0x00,
0x30, 0x00,
0x30, 0x00,
qwSignature
14
MSFT100” Signature field
MS_VendorCode,
bMS_VendorCode
1
Vendor-specific Vendor code
0x00
bPad
1
Pad field

MS_VendorCode is a value (defined as custom macro in project) which Windows will use to form requests for other descriptors. This gives device developer some leeway to add OS descriptors functionality without clashing with other custom USB requests which device might already support. For new and simple USB devices supporting only single WinUSB interface the vendor code is not that much relevant. Just make it non zero so that it won't cause problems on USB 3 hosts (see specification for more).
Note that Windows queries this descriptor only once. It can be a hassle during development. Information that OS descriptors have been queried for some device is stored in registry under
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\usbflags\VVVVPPPPRRRR
(VVVV - vendor ID; PPPP - product ID; RRRR - revision).
Delete VVVVPPPPRRRR key and also uninstall the device with utility like USDDeview to always get fresh device plug in behavior.

Extended Compat ID OS Descriptor


After device responds with proper 'MS OS String Descriptor' Windows sends a setup packet with request for 'Compat ID OS Descriptor'. Format of request is as follows:

Setup request field Value
bmRequestType b11000000 (device to host transfer direction; vendor type request; recipient is device)
bRequest
MS_VendorCode
wValue 0x0000
wIndex
0x0004 (request for an extended compat ID OS descriptor)
wLength
0x0010 or full length of descriptor

This a chance for device to inform Windows which driver should be loaded. Content below shows WinUSB driver association:

Value Field Size in Bytes Description
0x28, 0x00, 0x00, 0x00,
dwLength
4
The length, in bytes, of the complete extended compat ID descriptor
0x00, 0x01,
bcdVersion
2
The descriptor’s version number, in binary coded decimal (BCD) format
0x04, 0x00,
wIndex
2
An index that identifies the particular OS feature descriptor
0x01,
bCount
1
The number of custom property sections
0, 0, 0, 0, 0, 0, 0,
RESERVED
7
Reserved
0,
bFirstInterfaceNumber
1
The interface or function number
0,
RESERVED
1
Reserved
0x57, 0x49, 0x4E, 0x55, 0x53, 0x42, 0x00, 0x00,
compatibleID
8
The function’s compatible ID ("WINUSB")
0, 0, 0, 0, 0, 0, 0, 0,
subCompatibleID
8
The function’s subcompatible ID (none)
0, 0, 0, 0, 0, 0,
RESERVED
6
Reserved

Descriptor is queried twice. First with only header length (0x10) in wLength field. Then, after full length is known to Windows (from dwLength field) with full length in wLength field.
Each interface in device can have own association. Multiple sections follow the header (in yellow) in case of more interfaces. Descriptor is queried on device level and all associations must be listed in single descriptor. bFirstInterfaceNumber denotes the index of associated interface in each section.

Extended Properties OS Descriptor


After associating the driver with device Windows queries for interface properties. These are meant to provide information which is usually provided in .inf files of drivers, e.g.:

[USB_Install.HW]
AddReg=Dev_AddReg

[Dev_AddReg]
HKR,,DeviceInterfaceGUIDs,0x10000,"{EA0BD5C3-50F3-4888-84B4-74E50E1649DB}"

Properties Descriptor request is also issued twice (or more for descriptors larger than 64kByte). First with wLength set to 0x0A to only retrieve the header and later with wLength set to full length gotten from dwLength.
Following is the layout of USB Setup request:

Setup request field Value
bmRequestType b11000001 (device to host transfer direction; vendor type request; recipient is interface)
bRequest
MS_VendorCode
wValue 0xppii (pp – PageNumber for descriptors larger than 64kB; ii – interface index)
wIndex
0x0005 (request is for an extended properties OS descriptor)
wLength
0x000A or full length of descriptor

Note that properties are queried per interface. So if your device has multiple interfaces the request is send at least twice for each interface (BTW the number of interfaces is known from standard USB configuration descriptor). Following descriptors defines two properties:

  • DeviceInterfaceGUID
    This identifies interface with GUID which is used later in Windows application when querying the OS for devices with SetupDiGetClassDevs
  • Label
    This should be a friendly name displayed for device in Device manager. But apparently it only works form Windows 8 on

Value Field Size in Bytes Description
0xCC, 0x00, 0x00, 0x00,
dwLength
4
The length, in bytes, of the complete extended properties descriptor
0x00, 0x01,
bcdVersion
2
The descriptor’s version number, in binary coded decimal (BCD) format
0x05, 0x00,
wIndex
2
The index for extended properties OS descriptors
0x02, 0x00,
wCount
2
The number of custom property sections that follow the header section
0x84, 0x00, 0x00, 0x00,
dwSize
4
The size of this custom properties section
0x01, 0x00, 0x00, 0x00,
dwPropertyDataType
4
Property data format
0x28, 0x00,
wPropertyNameLength
2
Property name length (PNL)
'D',0, 'e',0, 'v',0, 'i',0, 'c',0, 'e',0, 'I',0, 'n',0, 't',0, 'e',0, 'r',0, 'f',0, 'a',0, 'c',0, 'e',0, 'G',0, 'U',0, 'I',0, 'D',0, 0, 0,
bPropertyName
PNL
The property name (DeviceInterfaceGUID)
0x4E, 0x00, 0x00, 0x00,
dwPropertyDataLength
4
Length of the buffer holding the property data (PDL)
'{',0, 'E',0, 'A',0, '0',0, 'B',0, 'D',0, '5',0, 'C',0, '3',0, '-',0, '5',0, '0',0, 'F',0, '3',0, '-',0, '4',0, '8',0, '8',0, '8',0, '-',0, '8',0, '4',0, 'B',0, '4',0,
'-',0, '7',0, '4',0, 'E',0, '5',0, '0',0, 'E',0, '1',0, '6',0, '4',0, '9',0, 'D',0, 'B',0, '}',0, 0, 0,
bPropertyData
PDL
PDL Format-dependent Property data ({EA0BD5C3-50F3-4888-84B4-74E50E1649DB})
0x3E, 0x00, 0x00, 0x00,
dwSize
4
The size of this custom properties section
0x01, 0x00, 0x00, 0x00,
dwPropertyDataType
4
Property data format
0x0C, 0x00,
wPropertyNameLength
2
Property name length (PNL)
'L',0, 'a',0, 'b',0, 'e',0, 'l',0, 0, 0,
bPropertyName
PNL
The property name (Label)
0x24, 0x00, 0x00, 0x00,
dwPropertyDataLength
4
Length of the buffer holding the property data (PDL)
'W',0, 'i',0, 'n',0, 'U',0, 'S',0, 'B',0, 'C',0, 'o',0, 'm',0, 'm',0, ' ',0, 'd',0, 'e',0, 'v',0, 'i',0, 'c',0, 'e',0, 0, 0

bPropertyData
PDL
PDL Format-dependent Property data (WinUSBComm Device)
These properties are stored in Windows registry at:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_xxxx&PID_xxxx\sssssssss\Device Parameters
Use USDDeview or similar utility to uninstall device and delete this entry while developing.

HW Info


To supply the board from OTG USB micro AB connector you need to connect PA9 pin to 5V pin. This is possible because VBUS is (strangely) connected directly to PA9 VBUS sensing input.

[Update] Comm library

Communication is implemented by implementing Comm layer so that it can be used with Comm library explained separately.

This is first post in this series (of total 2 posts). See 2.

Reference


Links tree below is for my future reference. You probably want to see descriptor specification (in bold).