Hello fellow engineers,
I'm trying to implement a USB soundcard on the Tiva Launchpad (123gxl) to test if the Cortex-M4 is fast enough to do various signal processing related processing. As I'm fairly new to USB in general and therefore also to the USB stack from TI I struggle a bit with the implementation of the USB driver to get the audio data in the microcontroller. As this may be useful for somebode else, I want to ask a bit more extensive.
To achieve what I wanted I followed the instructions in the following manual (Tivaware USB Library User Manual, chapter 2.3) : http://www.ti.com.cn/cn/lit/ug/spmu297/spmu297.pdf
I included the following header files from the usblib which gave me the first error:
#include "driverlib/usb.h" #include "usblib/usblib.h" #include "usblib/device/usbdevice.h" #include "usblib/device/usbdaudio.h"
The error stated that the compiler "expected a type identifier". It turned out that Code Composer Studio does not enable the GCC extensions of the ARM compiler by default. This has do be done manually in the Project Properties. Go to Build and open the ARM Compiler dropdown. There you will find the Advanced Options. Check the "Enable support for GCC extensions". Click OK and the compiler will recognize the pragma.
Next up: The prototypes and the tUSBAudioDevice struct to configure everything:
//The Callback function uint32_t HandleUSBMessages(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgParam, void *pvMsgData); //We do not need the instance but the driver does static tAudioInstance g_sAudioInstance; //Handle for the device void *pvDevice; // The languages supported by this device. const uint8_t g_pui8LangDescriptor[] = {4, USB_DTYPE_STRING, USBShort(USB_LANG_EN_US) }; // The manufacturer string. const uint8_t g_pui8ManufacturerString[] = { (17 + 1) * 2, USB_DTYPE_STRING, '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. const uint8_t g_pui8ProductString[] = { (13 + 1) * 2, USB_DTYPE_STRING, 'A', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0, ' ', 0, 'E', 0, 'x', 0, 'a', 0, 'm', 0, 'p', 0, 'l', 0, 'e', 0 }; // The serial number string. const uint8_t g_pui8SerialNumberString[] = { (8 + 1) * 2, USB_DTYPE_STRING, '1', 0, '2', 0, '3', 0, '4', 0, '5', 0, '6', 0, '7', 0, '8', 0 }; // The interface description string. const uint8_t g_pui8HIDInterfaceString[] = { (15 + 1) * 2, USB_DTYPE_STRING, 'A', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0, ' ', 0, 'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0 }; // The configuration description string. const uint8_t g_pui8ConfigString[] = { (20 + 1) * 2, USB_DTYPE_STRING, 'A', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0, ' ', 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 }; // The descriptor string table. const uint8_t * const g_ppui8StringDescriptors[] = { g_pui8LangDescriptor, g_pui8ManufacturerString, g_pui8ProductString, g_pui8SerialNumberString, g_pui8HIDInterfaceString, g_pui8ConfigString }; #define NUM_STRING_DESCRIPTORS (sizeof(g_ppui8StringDescriptors) / \ sizeof(uint8_t *)) /******************************************************************************************************************/ tUSBDAudioDevice g_sAudioDevice = { 0xFFFF, // The Vendor ID - Not important for personal use 0xFFFF, // The product ID - Not important for personal use "TI ", // The vendor string for your device (8 chars). "Audio Device ", // The product string for your device (16 chars). "1.00", // The revision string for your device (4 chars BCD). 500, // The power consumption of your device in milliamps. USB_CONF_ATTR_SELF_PWR, // The value to be passed to the host in the USB configuration descriptor's bmAttributes field. HandleUSBMessages, // A pointer to your control callback event handler. g_ppui8StringDescriptors, // A pointer to your string table. NUM_STRING_DESCRIPTORS, // The number of entries in your string table. 0xFF00, // Maximum volume setting expressed as and 8.8 signed fixed point number. 0x0000, // Minimum volume setting expressed as and 8.8 signed fixed point number. 0x0014 // Minimum volume step expressed as and 8.8 signed fixed point number. };
Please note that the so called "Instance data" described in the manual will be added by the USB audio Device Init function so we do not have to set it here!
Now we need to configure the pins and enable the clock inside main():
ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
ROM_GPIOPinTypeUSBAnalog(GPIO_PORTD_BASE, GPIO_PIN_4 | GPIO_PIN_5); pvDevice = USBDAudioInit(0, &g_sAudioDevice);
while(1){ };
This is where I get stuck. When I run the code to see if the device works properly I run into the FaultISR(). the callback function returns 0 and nothing is configured to transmit or receive audio date yet. Still - after the USBDAudioInit() it should enumerate and configure the device to the host (computer) even if the interrupts are still disabled.
The NVIC registers say that it is a bus fault with valid registers happening somewhere inside of USBAudioInit().
Inside this function there's another function called USBDAudioCompositeInit() (usbaudio.c).
Inside of USBDAudioCompositeInit() is another function called USBLibDMAInit() which in turn has a function called USBControllerVersion(). This is, where the bus fault occurs. This is the function as I have it in my version of the TivaWare (most recent):
uint32_t USBControllerVersion(uint32_t ui32Base) { // // Return the type field of the peripheral properties. This returns // zero for all parts that did not have a peripheral property. // return(HWREG(ui32Base + USB_O_PP) & USB_PP_TYPE_M); }
This is where my knowledge ends. I simply can't see why there is a fault occuring? Did I forget to enable a clock to a peripheral somewhere?
I will continue to post here until the code runs and does something fancy like modulating a LED to the volume of the sound or using the DAC/ PWM to provide a simple 10bit playback. Maybe we can provide another example for the Tivaware. I missed a usb_dev_audio example :)