├── .ccsproject ├── .cproject ├── .project ├── README.md ├── Release └── CSR_USB-SPI_TivaC_Launchpad.bin ├── csrspi.c ├── csrspi.h ├── main.c ├── startup_ccs.c ├── tm4c123gh6pm.cmd ├── usb_structs.c └── usb_structs.h /.ccsproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.cproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 33 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 124 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | CSR_USB-SPI_TivaC_Launchpad 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 15 | full,incremental, 16 | 17 | 18 | 19 | 20 | 21 | com.ti.ccstudio.core.ccsNature 22 | org.eclipse.cdt.core.cnature 23 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 24 | org.eclipse.cdt.core.ccnature 25 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 26 | 27 | 28 | 29 | utils/uartstdio.c 30 | 1 31 | SW_ROOT/utils/uartstdio.c 32 | 33 | 34 | utils/ustdlib.c 35 | 1 36 | SW_ROOT/utils/ustdlib.c 37 | 38 | 39 | 40 | 41 | ORIGINAL_PROJECT_ROOT 42 | file:/F:/devtools/tiva/Tivaware2/examples/boards/ek-tm4c123gxl/usb_dev_serial/ccs/ 43 | 44 | 45 | SW_ROOT 46 | $%7BPARENT-5-ORIGINAL_PROJECT_ROOT%7D 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CsrUsbSpiDevice-Tiva 2 | === 3 | Description 4 | --- 5 | This is a reverse engineered re-implementation of CSR's USB<->SPI Converter on a TI Stellaris Launchpad. It is compatible with CSR's own drivers and BlueSuite tools, and should work on any BlueCore chip that supports programming through SPI. 6 | 7 | Original version by Frans-Willem for original Stellaris Launchpad - https://github.com/Frans-Willem/CsrUsbSpiDeviceRE 8 | 9 | Minor tweaks to build under TivaWare Launchpad part # EK-TM4C123GXL by Richard Aplin, Dec2013 10 | Turbo mode (which may or may not work for you; YMMV) by Rich also. 11 | 12 | Disclaimer 13 | --- 14 | I make no guarantees about this code. For me it worked, but it might not for you. If you break your BlueCore module or anything else by using this software this is your own responsibility. 15 | 16 | How to use 17 | --- 18 | * Get a TI Tiva C Launchpad (EK-TM4C123GXL, $12 at time of writing) 19 | 20 | * Connect your BlueCore module. 3.3v -> 3.3v, GND -> GND, PC4 -> SPI_CSB, PC5 -> SPI_MOSI, PC6 -> SPI_MISO, PC7 -> SPI_CLK. (PC4 - PC7 are located on the second column from the right) 21 | 22 | EITHER Build from source: 23 | * Install from TI site: TivaWare, TI's Code Composer (free with the launchpad) 24 | * Import this project into Code composer as usual. 25 | * Ensure SW_ROOT is set to your TivaWare directory in *both* of these locations: 26 | * Project -> Properties -> Resource -> Linked Resources -> Path Variables -> SW_ROOT 27 | * Window -> Preferences -> C/C++ -> Build -> Environment -> SW_ROOT. 28 | * Build using Project -> Build Project 29 | * Connect your Tiva C Launchpad with the microUSB port at the top (next to power select), and set power select to DEBUG. 30 | * Debug using Run -> Debug 31 | * When paused on main, do Run -> Resume 32 | 33 | OR just flash the supplied binary using LM Flash Programmer: 34 | * Run LM Flash Programmer (in TI toolkit), plug in Launchpad 35 | * On "Configuration" tab select TM4C123G Launchpad 36 | * On "Program" tab select the bin file Release\CSR_USB-SPI_TivaC_Launchpad.bin (included in this project) 37 | * Hit Program, you're done. 38 | 39 | FINALLY 40 | * Plug in "device" microUSB port to a host computer with CSR BlueSuite (or Bluelab) installed. 41 | * Device should be recognized, Drivers can be found at csrsupport.com (needs registration), underBrowse category tree -> Bluetooth PC Software/Tools -> USB-SPI Converter. 42 | * Use any of the BlueSuite or BlueLabs tools to play with your bluecore module! (BlueSuite can be found on CSRSupport.com under Browser category tree -> Bluetooth PC Software/Tools -> Current BlueSuite Development Tools) 43 | * Green led will light up during reading, Red during writing, Blue when using BCCMD's. 44 | 45 | Optional Turbo mode 46 | --- 47 | This is a hack. If you hold down the LEFT button on the launchpad when booting (i.e. when you first plug it in to USB after programming, or when hitting reset button) the SPI interface will run without any delays for flash page read/writes. This makes it *much* faster - standard mode takes 65sec to read 8mbit, turbo mode takes 25 seconds. If you want to use this speedup, you should ensure it works reliably on your CSR device; use BlueFlash to "dump" whatever is in flash, then Erase the whole chip, then reprogram from the dump. 48 | Turbo mode works fine for me (on a BlueCore4-EXT) but YMMV. 49 | 50 | Notes 51 | --- 52 | * The SPI clock may not be accurate (certainly not in Turbo mode) 53 | * The code was written to match CSR's original firmware as closely as possible, it might not be the most efficient way to things on the Stellaris. 54 | * If something does or does not work, let me know (Frans-Willem) 55 | 56 | TODO 57 | --- 58 | * Clean up: The code works, but should still be cleaned up, and some bits aren't fully reverse engineered yet (e.g. the BCCMD timeout) 59 | * Refactor/rewrite: The code as it is now is as close to CSR's code as I could get, but it's not the most readable. I intend to refactor this at some point (maybe in a different project) to make it more readable and portable to other platforms. 60 | 61 | Original code - and all the hard work - by Frans-Willem Dec2012; minor hacks and porting to TivaWare by Richard Aplin, Dec2013 62 | -------------------------------------------------------------------------------- /Release/CSR_USB-SPI_TivaC_Launchpad.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raplin/CsrUsbSpiDeviceRE/b16d899565eee6a9a45f5a4c5c506ade42ca509c/Release/CSR_USB-SPI_TivaC_Launchpad.bin -------------------------------------------------------------------------------- /csrspi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * csrspi.c 3 | * 4 | * Created on: 2 jan. 2013 5 | * Author: Frans-Willem, 6 | * very small tweaks by Richard Aplin, Frans did all the hard work :-) 7 | */ 8 | #include 9 | #include 10 | #include "inc/hw_ints.h" 11 | #include "inc/hw_memmap.h" 12 | #include "inc/hw_types.h" 13 | #include "driverlib/sysctl.h" 14 | #include "driverlib/rom.h" 15 | #include "driverlib/gpio.h" 16 | 17 | #define PIN_CS GPIO_PIN_4 //Equivalent of pin 0x1 in CSR code 18 | #define PIN_MISO GPIO_PIN_6 //Equivalent of pin 0x2 in CSR code 19 | #define PIN_MOSI GPIO_PIN_5 //Equivalent of pin 0x4 in CSR code 20 | #define PIN_CLK GPIO_PIN_7 //Equivalent of pin 0x8 in CSR code 21 | #define PIN_UNK GPIO_PIN_3 //Equivalent to pin 0x10 in CSR code 22 | #define PIN_ALL_OUT PIN_CS|PIN_MOSI|PIN_CLK|PIN_UNK 23 | #define PIN_ALL_IN PIN_MISO 24 | #define PORT_BASE GPIO_PORTC_BASE 25 | 26 | #define SET_CS() GPIOPinWrite(PORT_BASE, PIN_CS, PIN_CS) 27 | #define CLR_CS() GPIOPinWrite(PORT_BASE, PIN_CS, 0) 28 | #define SET_CLK() GPIOPinWrite(PORT_BASE, PIN_CLK, PIN_CLK) 29 | #define CLR_CLK() GPIOPinWrite(PORT_BASE, PIN_CLK, 0) 30 | #define SET_MOSI() GPIOPinWrite(PORT_BASE, PIN_MOSI, PIN_MOSI) 31 | #define CLR_MOSI() GPIOPinWrite(PORT_BASE, PIN_MOSI, 0) 32 | #define GET_MISO() GPIOPinRead(PORT_BASE, PIN_MISO) 33 | 34 | 35 | unsigned short g_nSpeed = 393; 36 | unsigned short g_nReadBits = 0; 37 | unsigned short g_nWriteBits = 0; 38 | unsigned short g_nBcA = 0; 39 | unsigned short g_nBcB = 0; 40 | unsigned short g_nUseSpecialRead = 0; 41 | unsigned short g_nFastSpiMode=0; 42 | 43 | void CsrInit() { 44 | //Initialize Port B 45 | SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); 46 | GPIOPinTypeGPIOOutput(PORT_BASE, PIN_ALL_OUT); 47 | GPIOPadConfigSet(PORT_BASE, PIN_MISO, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); 48 | } 49 | 50 | void CsrSpiEnableFastMode(void) 51 | { 52 | //Richard Aplin tweak for super fast flashing (optional; test it with BlueFlash first!) 53 | //Enabled by holding down left button on Launchpad board when it's powered up 54 | //Without this, BlueFlash does about 2sectors/sec (65sec to dump 8mbits) 55 | //WITH this it does about 5/sec (26sec to dump 8mbit) 56 | //Works fine for me, but... 57 | //TEST ON YOUR OWN CHIP WITH BLUEFLASH DUMP/ERASE/VERIFY BEFORE REGULAR USE 58 | g_nFastSpiMode=1; 59 | } 60 | 61 | 62 | void CsrSpiDelay() { 63 | int kHz; 64 | 65 | if (g_nSpeed==4 && g_nFastSpiMode) return; //if usb host has specified 'fast' mode (Setspeed 0x0004) use practically no delay - works fine for me, but YMMV! 66 | 67 | kHz = 1000000 / (126 * g_nSpeed + 434); 68 | //Used to be 3000 69 | ROM_SysCtlDelay((SysCtlClockGet()/6000)/kHz); 70 | } 71 | 72 | //Equivalent of function at 022D 73 | void CsrSpiStart() { 74 | //022D 75 | //Unsets all outputs pins, sets unk and cs. 76 | GPIOPinWrite(PORT_BASE, PIN_ALL_OUT, PIN_UNK | PIN_CS); 77 | CsrSpiDelay(); 78 | //0239 79 | GPIOPinWrite(PORT_BASE, PIN_ALL_OUT, PIN_UNK | PIN_CS | PIN_CLK); 80 | CsrSpiDelay(); 81 | //023C 82 | GPIOPinWrite(PORT_BASE, PIN_ALL_OUT, PIN_UNK | PIN_CS); 83 | CsrSpiDelay(); 84 | //023F 85 | GPIOPinWrite(PORT_BASE, PIN_ALL_OUT, PIN_UNK | PIN_CS | PIN_CLK); 86 | CsrSpiDelay(); 87 | //0242 88 | GPIOPinWrite(PORT_BASE, PIN_ALL_OUT, PIN_UNK | PIN_CS); 89 | CsrSpiDelay(); 90 | //0245 91 | GPIOPinWrite(PORT_BASE, PIN_ALL_OUT, PIN_UNK); 92 | CsrSpiDelay(); 93 | //0247 94 | return; 95 | } 96 | 97 | //Equivalent of function at 0248 98 | void CsrSpiStop() { 99 | //Clears MOSI and CLK, sets CS and UNK 100 | GPIOPinWrite(PORT_BASE, PIN_ALL_OUT, PIN_UNK|PIN_CS); 101 | } 102 | 103 | //Equivalent of function at 0250 104 | //R10 is number of bits 105 | //R0 is what to send? 106 | //Normally R7 and R8 hold the first and second delay function, but I opted for a bool instead 107 | void CsrSpiSendBits(unsigned int nData, unsigned int nBits) { 108 | //CsrTransfer(nData, (1<<(nBits-1))); 109 | //return; 110 | unsigned char nClkLow = 0; //R2 111 | unsigned char nClkHigh = PIN_CLK; //R3 112 | nData <<= 24 - nBits; //Could've gone with 32, but hey, who cares 113 | while (nBits--) { 114 | GPIOPinWrite(PORT_BASE, PIN_CLK|PIN_MOSI|PIN_CS, nClkLow); 115 | if (nData & 0x800000) nClkHigh |= PIN_MOSI; 116 | nClkLow = nClkHigh - PIN_CLK; 117 | CsrSpiDelay(); 118 | GPIOPinWrite(PORT_BASE, PIN_MOSI|PIN_CS, nClkHigh); 119 | GPIOPinWrite(PORT_BASE, PIN_CLK|PIN_MOSI|PIN_CS, nClkHigh); 120 | CsrSpiDelay(); 121 | nClkHigh = PIN_CLK; 122 | nData <<= 1; 123 | } 124 | } 125 | 126 | //Equivalent of function at 0263 127 | //nBits = R10? 128 | unsigned int CsrSpiReadBits(unsigned int nBits) { 129 | //return CsrTransfer(0, (1<<(nBits-1))); 130 | unsigned int nRetval = 0; 131 | //CSR code disables interrupts here 132 | while (nBits--) { 133 | GPIOPinWrite(PORT_BASE, PIN_CLK, 0); 134 | CsrSpiDelay(); 135 | nRetval <<= 1; 136 | GPIOPinWrite(PORT_BASE, PIN_CLK, PIN_CLK); 137 | CsrSpiDelay(); 138 | if (GPIOPinRead(PORT_BASE, PIN_MISO)) 139 | nRetval |= 1; 140 | } 141 | //CSR code re-enables interrupts here 142 | return nRetval & 0xFFFF; 143 | } 144 | 145 | //Equivalent of function at 0279 146 | int CsrSpiReadBasic(unsigned short nAddress, unsigned short nLength, unsigned short *pnOutput) { 147 | nLength--; //Do one loop less, last word is read differently 148 | CsrSpiStart(); 149 | unsigned int nCommand = ((g_nReadBits | 3) << 16) | nAddress; 150 | unsigned int nControl; 151 | CsrSpiSendBits(nCommand, 24); 152 | /* 153 | * Inbetween these commands is an if-statement with some high-speed optimizations for if the spi delay = 0 154 | */ 155 | nControl = CsrSpiReadBits(16); 156 | if (nControl != ((nCommand >> 8) & 0xFFFF)) { 157 | //In CSR's code, this is at the bottom, 02B7 158 | CsrSpiStart(); //Not sure why we call this again 159 | CsrSpiStop(); 160 | return 0; 161 | } 162 | //Loop at 296 - 029B 163 | while (nLength--) { 164 | *(pnOutput++)=CsrSpiReadBits(16); 165 | } 166 | //From 19D to 2A2 some more speed optimized code that we don't need 167 | unsigned short nLast = CsrSpiReadBits(15); 168 | GPIOPinWrite(PORT_BASE, PIN_CLK, 0); 169 | CsrSpiDelay(); CsrSpiDelay(); CsrSpiDelay(); CsrSpiDelay(); 170 | nLast <<= 1; 171 | if (GPIOPinRead(PORT_BASE, PIN_MISO)) 172 | nLast |= 1; 173 | *(pnOutput++) = nLast; 174 | CsrSpiStart(); //Not sure why we call this again 175 | CsrSpiStop(); 176 | return 1; 177 | } 178 | 179 | //Equivalent of function at 02BB 180 | int CsrSpiRead(unsigned short nAddress, unsigned short nLength, unsigned short *pnOutput) { 181 | int nRet = 1; 182 | if (!g_nUseSpecialRead) 183 | return CsrSpiReadBasic(nAddress,nLength,pnOutput); 184 | nLength--; 185 | nRet &= CsrSpiReadBasic(nAddress, nLength, pnOutput); 186 | g_nReadBits |= 0x20; 187 | nRet &= CsrSpiReadBasic(nAddress + nLength, 1, &pnOutput[nLength]); 188 | g_nReadBits &= ~0x20; 189 | return nRet; 190 | } 191 | 192 | //Equivalent of 02CE 193 | void CsrSpiWrite(unsigned short nAddress, unsigned short nLength, unsigned short *pnInput) { 194 | CsrSpiStart(); 195 | // Some speed optimizing code from 02D2 to 02D8 196 | unsigned int nCommand = ((g_nWriteBits | 2) << 16) | nAddress; 197 | CsrSpiSendBits(nCommand, 24); 198 | while (nLength--) 199 | CsrSpiSendBits(*(pnInput++), 16); 200 | CsrSpiStart(); 201 | CsrSpiStop(); 202 | } 203 | 204 | int CsrSpiIsStopped() { 205 | unsigned short nOldSpeed = g_nSpeed; 206 | g_nSpeed += 32; 207 | CsrSpiStart(); 208 | g_nSpeed = nOldSpeed; 209 | unsigned char nRead = GPIOPinRead(PORT_BASE, PIN_MISO); 210 | CsrSpiStop(); 211 | if (nRead) return 1; 212 | return 0; 213 | } 214 | 215 | //0x47F 216 | //R1 seems to be used as return value 217 | int CsrSpiBcOperation(unsigned short nOperation /* R2 */) { 218 | unsigned short var0, var1 = 0; 219 | int i; 220 | CsrSpiRead(g_nBcA, 1, &var0); 221 | CsrSpiWrite(g_nBcB, 1, &nOperation); 222 | CsrSpiWrite(g_nBcA, 1, &var0); 223 | for (i=0; i<30; i++) { 224 | CsrSpiRead(g_nBcB, 1, &var1); 225 | if (nOperation != var1) 226 | return var1; 227 | } 228 | return var1; 229 | } 230 | 231 | int CsrSpiBcCmd(unsigned short nLength, unsigned short *pnData) { 232 | unsigned short var1,var2; 233 | int i; 234 | if (CsrSpiBcOperation(0x7) != 0) 235 | return 0; 236 | CsrSpiWrite(g_nBcB + 1, 1, &nLength); 237 | if (CsrSpiBcOperation(0x1) != 2) 238 | return 0; 239 | if (!CsrSpiRead(g_nBcB + 2, 1, &var1)) 240 | return 0; 241 | CsrSpiWrite(var1, nLength, pnData); 242 | CsrSpiBcOperation(0x4); 243 | for (i=0; i<30; i++) { 244 | if (CsrSpiRead(g_nBcB, 1, &var2) && var2 == 0x6) { 245 | CsrSpiRead(var1, nLength, pnData); 246 | CsrSpiBcOperation(0x7); 247 | return 1; 248 | } 249 | } 250 | return 0; 251 | } 252 | /* 253 | void CsrReset() { 254 | SET_CS(); CsrDelay(); 255 | SET_CLK(); CsrDelay(); 256 | CLR_CLK(); CsrDelay(); 257 | SET_CLK(); CsrDelay(); 258 | CLR_CLK(); CsrDelay(); 259 | } 260 | 261 | void CsrStart() { 262 | CsrReset(); 263 | CLR_CS(); CsrDelay(); 264 | } 265 | 266 | void CsrStop() { 267 | SET_CS(); 268 | } 269 | 270 | unsigned int CsrTransfer(unsigned int nInput, unsigned int msb) { 271 | unsigned int nOutput = 0; 272 | while (msb) { 273 | if (nInput & msb) SET_MOSI(); 274 | else CLR_MOSI(); 275 | msb >>= 1; 276 | CsrDelay(); 277 | SET_CLK(); 278 | CsrDelay(); 279 | nOutput <<= 1; 280 | if (GET_MISO()) nOutput |= 1; 281 | CLR_CLK(); 282 | } 283 | return nOutput; 284 | } 285 | 286 | int CsrRead(unsigned short nAddress, unsigned short nLength, unsigned short *pnOutput) { 287 | unsigned int nCommand; 288 | unsigned int nControl; 289 | nCommand = 3 | (g_nReadBits & ~3); 290 | CsrStart(); 291 | CsrTransfer(nCommand, 0x80); 292 | CsrTransfer(nAddress, 0x8000); 293 | nControl = CsrTransfer(0, 0x8000); 294 | unsigned int nExpected = ((nCommand & 0xFF) << 8) | ((nAddress >> 8) & 0xFF); 295 | //UARTprintf("Expected: %04X, Control: %04X\n",nExpected,nControl); 296 | if (nExpected != nControl) { 297 | CsrStop(); 298 | return 0; 299 | } 300 | while (nLength--) { 301 | *(pnOutput++) = CsrTransfer(0, 0x8000); 302 | } 303 | CsrStop(); 304 | return 1; 305 | } 306 | 307 | int CsrWrite(unsigned short nAddress, unsigned short nLength, unsigned short *pnInput) { 308 | unsigned int nCommand; 309 | nCommand = 2; 310 | CsrStart(); 311 | CsrTransfer(nCommand, 0x80); 312 | CsrTransfer(nAddress, 0x8000); 313 | while (nLength--) 314 | CsrTransfer(*(pnInput++), 0x8000); 315 | CsrStop(); 316 | return 1; 317 | } 318 | 319 | int CsrStopped() { 320 | unsigned int nControl, nCheck; 321 | CsrStart(); 322 | nCheck = CsrTransfer(3, 0x80); 323 | CsrTransfer(0xFF9A, 0x8000); 324 | nControl = CsrTransfer(0, 0x8000); 325 | if (nControl != 0x3FF) { 326 | return -1; 327 | } 328 | return (nCheck ? 1 : 0); 329 | }*/ 330 | -------------------------------------------------------------------------------- /csrspi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * csrspi.h 3 | * 4 | * Created on: 2 jan. 2013 5 | * Author: Frans-Willem 6 | */ 7 | 8 | #ifndef CSRSPI_H_ 9 | #define CSRSPI_H_ 10 | 11 | extern unsigned short g_nSpeed; 12 | extern unsigned short g_nReadBits; 13 | extern unsigned short g_nWriteBits; 14 | extern unsigned short g_nBcA; 15 | extern unsigned short g_nBcB; 16 | 17 | void CsrInit(); 18 | int CsrSpiRead(unsigned short nAddress, unsigned short nLength, unsigned short *pnOutput); 19 | void CsrSpiWrite(unsigned short nAddress, unsigned short nLength, unsigned short *pnInput); 20 | int CsrSpiIsStopped(); 21 | int CsrSpiBcOperation(unsigned short nOperation); 22 | int CsrSpiBcCmd(unsigned short nLength, unsigned short *pnData); 23 | void CsrSpiEnableFastMode(void); 24 | #endif /* CSRSPI_H_ */ 25 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Frans-Willem 3 | * Minor tweak for Tivaware compatibility by Richard Aplin, Dec2013 4 | * 5 | * This version runs on TI Tiva C series Launchpad - part # TM4C123G , costs USD$12 at time of writing, CSR dongle costs ~$250 6 | * 7 | * Connect: 8 | * 9 | * 10 | */ 11 | 12 | //two new includes for Tivaware types 13 | #include 14 | #include 15 | 16 | #include "inc/hw_ints.h" 17 | #include "inc/hw_memmap.h" 18 | #include "inc/hw_types.h" 19 | #include "driverlib/debug.h" 20 | #include "driverlib/fpu.h" 21 | #include "driverlib/gpio.h" 22 | #include "driverlib/interrupt.h" 23 | #include "driverlib/pin_map.h" 24 | #include "driverlib/sysctl.h" 25 | #include "driverlib/systick.h" 26 | #include "driverlib/timer.h" 27 | #include "driverlib/uart.h" 28 | #include "driverlib/rom.h" 29 | #include "usblib/usblib.h" 30 | #include "usblib/usb-ids.h" 31 | #include "usblib/device/usbdevice.h" 32 | #include "usblib/device/usbdbulk.h" 33 | #include "utils/uartstdio.h" 34 | #include "utils/ustdlib.h" 35 | #include "usb_structs.h" 36 | #include "csrspi.h" 37 | 38 | 39 | #define SYSCTL_PERIPH_LEDS SYSCTL_PERIPH_GPIOF 40 | #define GPIO_PORT_LEDS_BASE GPIO_PORTF_BASE 41 | #define GPIO_PIN_LED_R GPIO_PIN_1 42 | #define GPIO_PIN_LED_G GPIO_PIN_3 43 | #define GPIO_PIN_LED_B GPIO_PIN_2 44 | 45 | #define BUTTONS_GPIO_PERIPH SYSCTL_PERIPH_GPIOF 46 | #define BUTTONS_GPIO_BASE GPIO_PORTF_BASE 47 | #define NUM_BUTTONS 2 48 | #define LEFT_BUTTON GPIO_PIN_4 49 | #define RIGHT_BUTTON GPIO_PIN_0 50 | #define ALL_BUTTONS (LEFT_BUTTON | RIGHT_BUTTON) 51 | 52 | #define BUFFER_SIZE 1024 53 | 54 | #define CPU_CLOCK_100MHZ //else 80mhz, both work for me 55 | 56 | //#define PRINT_PROTOCOL 1 //debug info 57 | 58 | //typedef unsigned int size_t; //removed for tivaware 59 | 60 | unsigned char pReceiveBuffer[BUFFER_SIZE]; 61 | volatile size_t nReceiveLength; 62 | volatile int bReceiving = 1; 63 | 64 | unsigned char pTransmitBuffer[BUFFER_SIZE]; 65 | volatile size_t nTransmitLength; 66 | volatile size_t nTransmitOffset; 67 | volatile int bTransmitting = 0; 68 | 69 | #define MODE_SPI 0 70 | #define MODE_JTAG 0xFFFF; 71 | unsigned short g_nMode = MODE_SPI; 72 | 73 | #define CMD_READ 0x0100 74 | #define CMD_WRITE 0x0200 75 | #define CMD_SETSPEED 0x0300 76 | #define CMD_GETSTOPPED 0x0400 77 | #define CMD_GETSPEED 0x0500 78 | #define CMD_UPDATE 0x0600 79 | #define CMD_GETSERIAL 0x0700 80 | #define CMD_GETVERSION 0x0800 81 | #define CMD_SETMODE 0x0900 82 | #define CMD_SETBITS 0x0F00 83 | #define CMD_BCCMDINIT 0x4000 84 | #define CMD_BCCMD 0x4100 85 | 86 | void WriteWord(unsigned char *szOffset, unsigned short n) { 87 | szOffset[1] = n & 0xFF; 88 | szOffset[0] = (n >> 8) & 0xFF; 89 | } 90 | 91 | unsigned short ReadWord(unsigned char *szOffset) { 92 | return (szOffset[0] << 8) | szOffset[1]; 93 | } 94 | 95 | void TransmitWord(unsigned short n) { 96 | if (nTransmitLength + 2 < BUFFER_SIZE) { 97 | WriteWord(&pTransmitBuffer[nTransmitLength], n); 98 | nTransmitLength += 2; 99 | } 100 | } 101 | 102 | void TransmitDWord(unsigned int n) { 103 | TransmitWord((n >> 16) & 0xFFFF); 104 | TransmitWord(n & 0xFFFF); 105 | } 106 | 107 | int CmdRead(unsigned short nAddress, unsigned short nLength); 108 | int CmdWrite(unsigned short nAddress, unsigned short nLength, unsigned char *pData); 109 | int CmdSetSpeed(unsigned short nSpeed); 110 | int CmdGetStopped(); 111 | int CmdGetSpeed(); 112 | int CmdUpdate(); 113 | int CmdGetSerial(); 114 | int CmdGetVersion(); 115 | int CmdSetMode(unsigned short nMode); 116 | int CmdSetBits(unsigned short nWhich, unsigned short nValue); 117 | void CmdBcCmdInit(unsigned short nA, unsigned short nB); 118 | int CmdBcCmd(unsigned short nLength, unsigned char *pData); 119 | 120 | void TransmitCallback() { 121 | size_t nPacket; 122 | if (bTransmitting) { 123 | nPacket = nTransmitLength - nTransmitOffset; 124 | if (nPacket > 64) 125 | nPacket = 64; 126 | USBDBulkPacketWrite((void *)&g_sBulkDevice, &pTransmitBuffer[nTransmitOffset], nPacket, true); 127 | nTransmitOffset += nPacket; 128 | if (nPacket < 64) 129 | bTransmitting = 0; 130 | } 131 | } 132 | void StartTransmit() { 133 | nTransmitOffset = 0; 134 | bTransmitting = 1; 135 | if (USBDBulkTxPacketAvailable((void *)&g_sBulkDevice)) 136 | TransmitCallback(); 137 | } 138 | void WaitTransmit() { 139 | while (bTransmitting); 140 | nTransmitLength = nTransmitOffset = 0; 141 | } 142 | 143 | 144 | //***************************************************************************** 145 | // 146 | // Configure the UART and its pins. This must be called before UARTprintf(). 147 | // (Tivaware tweak) 148 | //***************************************************************************** 149 | void 150 | ConfigureUART(void) 151 | { 152 | // 153 | // Enable the GPIO Peripheral used by the UART. 154 | // 155 | ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); 156 | 157 | // 158 | // Enable UART0 159 | // 160 | ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); 161 | 162 | // 163 | // Configure GPIO Pins for UART mode. 164 | // 165 | ROM_GPIOPinConfigure(GPIO_PA0_U0RX); 166 | ROM_GPIOPinConfigure(GPIO_PA1_U0TX); 167 | ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); 168 | 169 | // 170 | // Use the internal 16MHz oscillator as the UART clock source. 171 | // 172 | UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC); 173 | 174 | // 175 | // Initialize the UART for console I/O. 176 | // 177 | UARTStdioConfig(0, 115200, 16000000); 178 | } 179 | 180 | void InitButtons(void) 181 | { 182 | // Set each of the button GPIO pins as an input with a pull-up. 183 | ROM_GPIODirModeSet(BUTTONS_GPIO_BASE, ALL_BUTTONS, GPIO_DIR_MODE_IN); 184 | ROM_GPIOPadConfigSet(BUTTONS_GPIO_BASE, ALL_BUTTONS, 185 | GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); 186 | } 187 | 188 | /* 189 | * main.c 190 | */ 191 | void main(void) { 192 | size_t nOffset; 193 | unsigned short nCommand, nArgs[4]; 194 | uint32_t buttons; 195 | 196 | #ifndef CPU_CLOCK_100MHZ 197 | //Set Clock at 80MHz 198 | ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); 199 | #else 200 | //Hey what the hell, let's run at 100Mhz, why not? 201 | ROM_SysCtlClockSet(SYSCTL_SYSDIV_2 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); 202 | #endif 203 | //Enable UART on Port A 204 | ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); 205 | GPIOPinConfigure(GPIO_PA0_U0RX); 206 | GPIOPinConfigure(GPIO_PA1_U0TX); 207 | ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); 208 | //Do some output! 209 | ConfigureUART(); //UARTStdioInit(0); tivaware tweak 210 | UARTprintf("CSR USB-SPI Emulator for Tiva Launchpad by Frans-Willem 2012,\n tweaked by Richard Aplin 2013\n"); 211 | 212 | UARTprintf("CPU Clock %dMhz\n",SysCtlClockGet()/1000000); 213 | 214 | //Csr SPI init 215 | CsrInit(); 216 | UARTprintf("CSR initialized\n"); 217 | 218 | //Status LEDs Init 219 | SysCtlPeripheralEnable(SYSCTL_PERIPH_LEDS); 220 | InitButtons(); 221 | GPIOPinTypeGPIOOutput(GPIO_PORT_LEDS_BASE, GPIO_PIN_LED_R|GPIO_PIN_LED_G|GPIO_PIN_LED_B); 222 | GPIOPinWrite(GPIO_PORT_LEDS_BASE, GPIO_PIN_LED_R|GPIO_PIN_LED_G|GPIO_PIN_LED_B, 0); 223 | UARTprintf("LEDs initialized\n"); 224 | 225 | //check for left button (NOT) being held down on boot for FAST mode 226 | buttons=ROM_GPIOPinRead(BUTTONS_GPIO_BASE, LEFT_BUTTON); 227 | if (!buttons){ 228 | UARTprintf("FAST SPI mode enabled - test reliability with BlueFlash before using!\n"); 229 | CsrSpiEnableFastMode(); 230 | }else{ 231 | UARTprintf("Regular (slow) SPI mode enabled\n"); 232 | } 233 | 234 | //USB init? 235 | ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); 236 | ROM_GPIOPinTypeUSBAnalog(GPIO_PORTD_BASE, GPIO_PIN_4 | GPIO_PIN_5); 237 | 238 | USBStackModeSet(0, eUSBModeForceDevice, 0); //tivaware tweak 239 | USBDBulkInit(0, (tUSBDBulkDevice *)&g_sBulkDevice); 240 | UARTprintf("Waiting for host...\n"); 241 | 242 | while (1) { 243 | while (bReceiving); //Wait until we're ready receiving data 244 | if (nReceiveLength == 0) { 245 | UARTprintf("Empty packet...\n"); 246 | } else { 247 | WaitTransmit(); 248 | if (pReceiveBuffer[0] != '\0') { 249 | UARTprintf("Invalid start byte\n"); 250 | } else { 251 | nOffset = 1; 252 | while (nReceiveLength >= nOffset + 2) { 253 | nCommand = ReadWord(&pReceiveBuffer[nOffset]); 254 | nOffset += 2; 255 | switch (nCommand) { 256 | case CMD_READ: 257 | if (nReceiveLength < nOffset + 4) { 258 | UARTprintf("Too few arguments to read\n"); 259 | } else { 260 | nArgs[0] = ReadWord(&pReceiveBuffer[nOffset]); 261 | nOffset += 2; 262 | nArgs[1] = ReadWord(&pReceiveBuffer[nOffset]); 263 | nOffset += 2; 264 | #if PRINT_PROTOCOL 265 | UARTprintf("CMD_READ %04x %04x\n",nArgs[0],nArgs[1]); 266 | #endif 267 | CmdRead(nArgs[0], nArgs[1]); 268 | } 269 | break; 270 | case CMD_WRITE: 271 | if (nReceiveLength < nOffset + 4) { 272 | UARTprintf("Too few arguments to write\n"); 273 | } else { 274 | nArgs[0] = ReadWord(&pReceiveBuffer[nOffset]); 275 | nOffset += 2; 276 | nArgs[1] = ReadWord(&pReceiveBuffer[nOffset]); 277 | nOffset += 2; 278 | if (nReceiveLength < nOffset + (nArgs[1] * 2)) { 279 | UARTprintf("Too few arguments to write\n"); 280 | } else { 281 | #if PRINT_PROTOCOL 282 | UARTprintf("CMD_WRITE %04x %04x\n",nArgs[0],nArgs[1]); 283 | #endif 284 | CmdWrite(nArgs[0], nArgs[1], &pReceiveBuffer[nOffset]); 285 | nOffset+=nArgs[1] * 2; 286 | } 287 | } 288 | break; 289 | case CMD_SETSPEED: 290 | if (nReceiveLength < nOffset + 2) { 291 | UARTprintf("Too few arguments to set speed\n"); 292 | } else { 293 | nArgs[0] = ReadWord(&pReceiveBuffer[nOffset]); 294 | nOffset += 2; 295 | #if PRINT_PROTOCOL 296 | UARTprintf("CMD_SETSPEED %04x\n",nArgs[0]); 297 | #endif 298 | CmdSetSpeed(nArgs[0]); 299 | } 300 | break; 301 | case CMD_GETSTOPPED: 302 | CmdGetStopped(); 303 | break; 304 | case CMD_GETSPEED: 305 | CmdGetSpeed(); 306 | break; 307 | case CMD_UPDATE: 308 | #if PRINT_PROTOCOL 309 | UARTprintf("CMD_UPDATE\n"); 310 | #endif 311 | CmdUpdate(); 312 | break; 313 | case CMD_GETSERIAL: 314 | CmdGetSerial(); 315 | break; 316 | case CMD_GETVERSION: 317 | CmdGetVersion(); 318 | break; 319 | case CMD_SETMODE: 320 | if (nReceiveLength < nOffset + 2) { 321 | UARTprintf("Too few arguments to set mode\n"); 322 | } else { 323 | nArgs[0] = ReadWord(&pReceiveBuffer[nOffset]); 324 | nOffset += 2; 325 | #if PRINT_PROTOCOL 326 | UARTprintf("CMD_SETMODE %04x\n",nArgs[0]); 327 | #endif 328 | CmdSetMode(nArgs[0]); 329 | } 330 | break; 331 | case CMD_SETBITS: 332 | if (nReceiveLength < nOffset + 4) { 333 | UARTprintf("Too few arguments to set bits\n"); 334 | } else { 335 | nArgs[0] = ReadWord(&pReceiveBuffer[nOffset]); 336 | nOffset += 2; 337 | nArgs[1] = ReadWord(&pReceiveBuffer[nOffset]); 338 | nOffset += 2; 339 | #if PRINT_PROTOCOL 340 | UARTprintf("CMD_SETBITS %04x %04x\n",nArgs[0],nArgs[1]); 341 | #endif 342 | CmdSetBits(nArgs[0], nArgs[1]); 343 | } 344 | break; 345 | case CMD_BCCMDINIT: 346 | if (nReceiveLength < nOffset + 4) { 347 | UARTprintf("Too few arguments to init bccmd\n"); 348 | } else { 349 | nArgs[0] = ReadWord(&pReceiveBuffer[nOffset]); 350 | nOffset += 2; 351 | nArgs[1] = ReadWord(&pReceiveBuffer[nOffset]); 352 | nOffset += 2; 353 | #if PRINT_PROTOCOL 354 | UARTprintf("CMD_BCCMDINIT %04x %04x\n",nArgs[0],nArgs[1]); 355 | #endif 356 | CmdBcCmdInit(nArgs[0], nArgs[1]); 357 | } 358 | break; 359 | case CMD_BCCMD: 360 | if (nReceiveLength < nOffset + 2) { 361 | UARTprintf("Too few arguments to bccmd\n"); 362 | } else { 363 | nArgs[0] = ReadWord(&pReceiveBuffer[nOffset]); 364 | nOffset += 2; 365 | if (nReceiveLength < nOffset + (nArgs[0] * 2)) { 366 | UARTprintf("Too few arguments to bccmd\n"); 367 | } else { 368 | #if PRINT_PROTOCOL 369 | UARTprintf("CMD_BCCMD %04x\n",nArgs[0]); 370 | #endif 371 | CmdBcCmd(nArgs[0], &pReceiveBuffer[nOffset]); 372 | nOffset+=nArgs[0] * 2; 373 | } 374 | } 375 | break; 376 | default: 377 | UARTprintf("Unknown command: %04X", nCommand); 378 | nOffset = nReceiveLength; 379 | continue; 380 | } 381 | nOffset += 2; //Read the two inbetween bytes 382 | } 383 | } 384 | if (nTransmitLength) 385 | StartTransmit(); 386 | } 387 | 388 | //Get ready for the next packet 389 | nReceiveLength = 0; 390 | bReceiving = 1; 391 | } 392 | } 393 | 394 | uint32_t TxHandler(void *pvi32CBData, uint32_t ulEvent, 395 | uint32_t ulMsgValue, void *pvMsgData) 396 | /*unsigned long 397 | TxHandler(void *pvCBData, unsigned long ulEvent, unsigned long ulMsgValue, 398 | void *pvMsgData)*/ 399 | { 400 | if(ulEvent == USB_EVENT_TX_COMPLETE) 401 | { 402 | TransmitCallback(); 403 | } 404 | return(0); 405 | } 406 | 407 | unsigned short pCsrBuffer[1024]; 408 | 409 | 410 | int CmdRead(unsigned short nAddress, unsigned short nLength) { 411 | unsigned short *pCurrent; 412 | GPIOPinWrite(GPIO_PORT_LEDS_BASE, GPIO_PIN_LED_G, GPIO_PIN_LED_G); 413 | if (g_nMode == MODE_SPI && nLength < 1024 && CsrSpiRead(nAddress,nLength,pCsrBuffer)) { 414 | GPIOPinWrite(GPIO_PORT_LEDS_BASE, GPIO_PIN_LED_G, 0); 415 | TransmitWord(CMD_READ); 416 | TransmitWord(nAddress); 417 | TransmitWord(nLength); 418 | pCurrent = pCsrBuffer; 419 | while (nLength--) { 420 | TransmitWord(*(pCurrent++)); 421 | } 422 | } else { 423 | GPIOPinWrite(GPIO_PORT_LEDS_BASE, GPIO_PIN_LED_G, 0); 424 | UARTprintf("Read Failed\n"); 425 | TransmitWord(CMD_READ + 1); 426 | TransmitWord(nAddress); 427 | TransmitWord(nLength); 428 | while (nLength--) 429 | TransmitWord(0); 430 | } 431 | return 1; 432 | } 433 | int CmdWrite(unsigned short nAddress, unsigned short nLength, unsigned char *pData) { 434 | if (nLength > 1024 || g_nMode != MODE_SPI) 435 | return 0; 436 | unsigned short i; 437 | for (i = 0; i < nLength; i++) { 438 | pCsrBuffer[i] = ReadWord(&pData[i * 2]); 439 | } 440 | GPIOPinWrite(GPIO_PORT_LEDS_BASE, GPIO_PIN_LED_R, GPIO_PIN_LED_R); 441 | CsrSpiWrite(nAddress, nLength, pCsrBuffer); 442 | GPIOPinWrite(GPIO_PORT_LEDS_BASE, GPIO_PIN_LED_R, 0); 443 | return 1; 444 | } 445 | int CmdSetSpeed(unsigned short nSpeed) { 446 | g_nSpeed = nSpeed; 447 | return 1; 448 | } 449 | int CmdGetStopped() { 450 | TransmitWord(CMD_GETSTOPPED); 451 | TransmitWord(g_nMode != MODE_SPI || CsrSpiIsStopped()); //TODO 452 | return 1; 453 | } 454 | int CmdGetSpeed() { 455 | TransmitWord(CMD_GETSPEED); 456 | TransmitWord(g_nSpeed); 457 | return 1; 458 | } 459 | int CmdUpdate() { 460 | return 1; 461 | } 462 | int CmdGetSerial() { 463 | TransmitWord(CMD_GETSERIAL); 464 | TransmitDWord(31337); 465 | return 1; 466 | } 467 | int CmdGetVersion() { 468 | TransmitWord(CMD_GETVERSION); 469 | TransmitWord(0x119); 470 | return 1; 471 | } 472 | int CmdSetMode(unsigned short nMode) { 473 | g_nMode = nMode; 474 | return 1; 475 | } 476 | int CmdSetBits(unsigned short nWhich, unsigned short nValue) { 477 | if (nWhich) g_nWriteBits = nValue; 478 | else g_nReadBits = nValue; 479 | return 1; 480 | } 481 | 482 | void CmdBcCmdInit(unsigned short nA, unsigned short nB) { 483 | UARTprintf("BCCMD Init: %04X %04X\n", nA, nB); 484 | g_nBcA = nA; 485 | g_nBcB = nB; 486 | } 487 | 488 | int CmdBcCmd(unsigned short nLength, unsigned char *pData) { 489 | unsigned short i; 490 | //UARTprintf("BCCMD input:\n"); 491 | for (i = 0; i < nLength; i++) { 492 | pCsrBuffer[i] = ReadWord(&pData[i*2]); 493 | } 494 | GPIOPinWrite(GPIO_PORT_LEDS_BASE, GPIO_PIN_LED_B, GPIO_PIN_LED_B); 495 | if (CsrSpiBcCmd(nLength, pCsrBuffer)) { 496 | TransmitWord(CMD_BCCMD); 497 | } else { 498 | TransmitWord(CMD_BCCMD + 1); 499 | } 500 | GPIOPinWrite(GPIO_PORT_LEDS_BASE, GPIO_PIN_LED_B, 0); 501 | TransmitWord(nLength); 502 | for (i=0; i BUFFER_SIZE) { 531 | UARTprintf("Buffer overflow\n"); 532 | return 0; 533 | } 534 | nReceiveLength += USBDBulkPacketRead((void *)&g_sBulkDevice, &pReceiveBuffer[nReceiveLength], ulMsgValue, true); 535 | if (ulMsgValue < 64) { 536 | bReceiving = 0; 537 | } 538 | return ulMsgValue; 539 | } 540 | return 0; 541 | } 542 | case USB_EVENT_SUSPEND: 543 | case USB_EVENT_RESUME: 544 | { 545 | break; 546 | } 547 | default: 548 | { 549 | break; 550 | } 551 | } 552 | 553 | return(0); 554 | } 555 | -------------------------------------------------------------------------------- /startup_ccs.c: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // 3 | // startup_ccs.c - Startup code for use with TI's Code Composer Studio. 4 | // 5 | // Copyright (c) 2012-2013 Texas Instruments Incorporated. All rights reserved. 6 | // Software License Agreement 7 | // 8 | // Texas Instruments (TI) is supplying this software for use solely and 9 | // exclusively on TI's microcontroller products. The software is owned by 10 | // TI and/or its suppliers, and is protected under applicable copyright 11 | // laws. You may not combine this software with "viral" open-source 12 | // software in order to form a larger program. 13 | // 14 | // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. 15 | // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT 16 | // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY 18 | // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL 19 | // DAMAGES, FOR ANY REASON WHATSOEVER. 20 | // 21 | // This is part of revision 1.0 of the EK-TM4C123GXL Firmware Package. 22 | // 23 | //***************************************************************************** 24 | 25 | #include 26 | #include "inc/hw_nvic.h" 27 | #include "inc/hw_types.h" 28 | 29 | //***************************************************************************** 30 | // 31 | // Forward declaration of the default fault handlers. 32 | // 33 | //***************************************************************************** 34 | void ResetISR(void); 35 | static void NmiSR(void); 36 | static void FaultISR(void); 37 | static void IntDefaultHandler(void); 38 | 39 | //***************************************************************************** 40 | // 41 | // External declaration for the reset handler that is to be called when the 42 | // processor is started 43 | // 44 | //***************************************************************************** 45 | extern void _c_int00(void); 46 | 47 | //***************************************************************************** 48 | // 49 | // Linker variable that marks the top of the stack. 50 | // 51 | //***************************************************************************** 52 | extern uint32_t __STACK_TOP; 53 | 54 | //***************************************************************************** 55 | // 56 | // External declarations for the interrupt handlers used by the application. 57 | // 58 | //***************************************************************************** 59 | extern void SysTickIntHandler(void); 60 | //extern void USBUARTIntHandler(void); 61 | extern void USB0DeviceIntHandler(void); 62 | 63 | extern void UARTStdioIntHandler(void); 64 | 65 | 66 | //***************************************************************************** 67 | // 68 | // The vector table. Note that the proper constructs must be placed on this to 69 | // ensure that it ends up at physical address 0x0000.0000 or at the start of 70 | // the program if located at a start address other than 0. 71 | // 72 | //***************************************************************************** 73 | #pragma DATA_SECTION(g_pfnVectors, ".intvecs") 74 | void (* const g_pfnVectors[])(void) = 75 | { 76 | (void (*)(void))((uint32_t)&__STACK_TOP), 77 | // The initial stack pointer 78 | ResetISR, // The reset handler 79 | NmiSR, // The NMI handler 80 | FaultISR, // The hard fault handler 81 | IntDefaultHandler, // The MPU fault handler 82 | IntDefaultHandler, // The bus fault handler 83 | IntDefaultHandler, // The usage fault handler 84 | 0, // Reserved 85 | 0, // Reserved 86 | 0, // Reserved 87 | 0, // Reserved 88 | IntDefaultHandler, // SVCall handler 89 | IntDefaultHandler, // Debug monitor handler 90 | 0, // Reserved 91 | IntDefaultHandler, // The PendSV handler 92 | IntDefaultHandler, // The SysTick handler 93 | IntDefaultHandler, // GPIO Port A 94 | IntDefaultHandler, // GPIO Port B 95 | IntDefaultHandler, // GPIO Port C 96 | IntDefaultHandler, // GPIO Port D 97 | IntDefaultHandler, // GPIO Port E 98 | UARTStdioIntHandler, // UART0 Rx and Tx 99 | IntDefaultHandler, // UART1 Rx and Tx 100 | IntDefaultHandler, // SSI0 Rx and Tx 101 | IntDefaultHandler, // I2C0 Master and Slave 102 | IntDefaultHandler, // PWM Fault 103 | IntDefaultHandler, // PWM Generator 0 104 | IntDefaultHandler, // PWM Generator 1 105 | IntDefaultHandler, // PWM Generator 2 106 | IntDefaultHandler, // Quadrature Encoder 0 107 | IntDefaultHandler, // ADC Sequence 0 108 | IntDefaultHandler, // ADC Sequence 1 109 | IntDefaultHandler, // ADC Sequence 2 110 | IntDefaultHandler, // ADC Sequence 3 111 | IntDefaultHandler, // Watchdog timer 112 | IntDefaultHandler, // Timer 0 subtimer A 113 | IntDefaultHandler, // Timer 0 subtimer B 114 | IntDefaultHandler, // Timer 1 subtimer A 115 | IntDefaultHandler, // Timer 1 subtimer B 116 | IntDefaultHandler, // Timer 2 subtimer A 117 | IntDefaultHandler, // Timer 2 subtimer B 118 | IntDefaultHandler, // Analog Comparator 0 119 | IntDefaultHandler, // Analog Comparator 1 120 | IntDefaultHandler, // Analog Comparator 2 121 | IntDefaultHandler, // System Control (PLL, OSC, BO) 122 | IntDefaultHandler, // FLASH Control 123 | IntDefaultHandler, // GPIO Port F 124 | IntDefaultHandler, // GPIO Port G 125 | IntDefaultHandler, // GPIO Port H 126 | IntDefaultHandler, // UART2 Rx and Tx 127 | IntDefaultHandler, // SSI1 Rx and Tx 128 | IntDefaultHandler, // Timer 3 subtimer A 129 | IntDefaultHandler, // Timer 3 subtimer B 130 | IntDefaultHandler, // I2C1 Master and Slave 131 | IntDefaultHandler, // Quadrature Encoder 1 132 | IntDefaultHandler, // CAN0 133 | IntDefaultHandler, // CAN1 134 | IntDefaultHandler, // CAN2 135 | 0, // Reserved 136 | IntDefaultHandler, // Hibernate 137 | USB0DeviceIntHandler, // USB0 138 | IntDefaultHandler, // PWM Generator 3 139 | IntDefaultHandler, // uDMA Software Transfer 140 | IntDefaultHandler, // uDMA Error 141 | IntDefaultHandler, // ADC1 Sequence 0 142 | IntDefaultHandler, // ADC1 Sequence 1 143 | IntDefaultHandler, // ADC1 Sequence 2 144 | IntDefaultHandler, // ADC1 Sequence 3 145 | 0, // Reserved 146 | 0, // Reserved 147 | IntDefaultHandler, // GPIO Port J 148 | IntDefaultHandler, // GPIO Port K 149 | IntDefaultHandler, // GPIO Port L 150 | IntDefaultHandler, // SSI2 Rx and Tx 151 | IntDefaultHandler, // SSI3 Rx and Tx 152 | IntDefaultHandler, // UART3 Rx and Tx 153 | IntDefaultHandler, // UART4 Rx and Tx 154 | IntDefaultHandler, // UART5 Rx and Tx 155 | IntDefaultHandler, // UART6 Rx and Tx 156 | IntDefaultHandler, // UART7 Rx and Tx 157 | 0, // Reserved 158 | 0, // Reserved 159 | 0, // Reserved 160 | 0, // Reserved 161 | IntDefaultHandler, // I2C2 Master and Slave 162 | IntDefaultHandler, // I2C3 Master and Slave 163 | IntDefaultHandler, // Timer 4 subtimer A 164 | IntDefaultHandler, // Timer 4 subtimer B 165 | 0, // Reserved 166 | 0, // Reserved 167 | 0, // Reserved 168 | 0, // Reserved 169 | 0, // Reserved 170 | 0, // Reserved 171 | 0, // Reserved 172 | 0, // Reserved 173 | 0, // Reserved 174 | 0, // Reserved 175 | 0, // Reserved 176 | 0, // Reserved 177 | 0, // Reserved 178 | 0, // Reserved 179 | 0, // Reserved 180 | 0, // Reserved 181 | 0, // Reserved 182 | 0, // Reserved 183 | 0, // Reserved 184 | 0, // Reserved 185 | IntDefaultHandler, // Timer 5 subtimer A 186 | IntDefaultHandler, // Timer 5 subtimer B 187 | IntDefaultHandler, // Wide Timer 0 subtimer A 188 | IntDefaultHandler, // Wide Timer 0 subtimer B 189 | IntDefaultHandler, // Wide Timer 1 subtimer A 190 | IntDefaultHandler, // Wide Timer 1 subtimer B 191 | IntDefaultHandler, // Wide Timer 2 subtimer A 192 | IntDefaultHandler, // Wide Timer 2 subtimer B 193 | IntDefaultHandler, // Wide Timer 3 subtimer A 194 | IntDefaultHandler, // Wide Timer 3 subtimer B 195 | IntDefaultHandler, // Wide Timer 4 subtimer A 196 | IntDefaultHandler, // Wide Timer 4 subtimer B 197 | IntDefaultHandler, // Wide Timer 5 subtimer A 198 | IntDefaultHandler, // Wide Timer 5 subtimer B 199 | IntDefaultHandler, // FPU 200 | 0, // Reserved 201 | 0, // Reserved 202 | IntDefaultHandler, // I2C4 Master and Slave 203 | IntDefaultHandler, // I2C5 Master and Slave 204 | IntDefaultHandler, // GPIO Port M 205 | IntDefaultHandler, // GPIO Port N 206 | IntDefaultHandler, // Quadrature Encoder 2 207 | 0, // Reserved 208 | 0, // Reserved 209 | IntDefaultHandler, // GPIO Port P (Summary or P0) 210 | IntDefaultHandler, // GPIO Port P1 211 | IntDefaultHandler, // GPIO Port P2 212 | IntDefaultHandler, // GPIO Port P3 213 | IntDefaultHandler, // GPIO Port P4 214 | IntDefaultHandler, // GPIO Port P5 215 | IntDefaultHandler, // GPIO Port P6 216 | IntDefaultHandler, // GPIO Port P7 217 | IntDefaultHandler, // GPIO Port Q (Summary or Q0) 218 | IntDefaultHandler, // GPIO Port Q1 219 | IntDefaultHandler, // GPIO Port Q2 220 | IntDefaultHandler, // GPIO Port Q3 221 | IntDefaultHandler, // GPIO Port Q4 222 | IntDefaultHandler, // GPIO Port Q5 223 | IntDefaultHandler, // GPIO Port Q6 224 | IntDefaultHandler, // GPIO Port Q7 225 | IntDefaultHandler, // GPIO Port R 226 | IntDefaultHandler, // GPIO Port S 227 | IntDefaultHandler, // PWM 1 Generator 0 228 | IntDefaultHandler, // PWM 1 Generator 1 229 | IntDefaultHandler, // PWM 1 Generator 2 230 | IntDefaultHandler, // PWM 1 Generator 3 231 | IntDefaultHandler // PWM 1 Fault 232 | }; 233 | 234 | //***************************************************************************** 235 | // 236 | // This is the code that gets called when the processor first starts execution 237 | // following a reset event. Only the absolutely necessary set is performed, 238 | // after which the application supplied entry() routine is called. Any fancy 239 | // actions (such as making decisions based on the reset cause register, and 240 | // resetting the bits in that register) are left solely in the hands of the 241 | // application. 242 | // 243 | //***************************************************************************** 244 | void 245 | ResetISR(void) 246 | { 247 | // 248 | // Jump to the CCS C initialization routine. This will enable the 249 | // floating-point unit as well, so that does not need to be done here. 250 | // 251 | __asm(" .global _c_int00\n" 252 | " b.w _c_int00"); 253 | } 254 | 255 | //***************************************************************************** 256 | // 257 | // This is the code that gets called when the processor receives a NMI. This 258 | // simply enters an infinite loop, preserving the system state for examination 259 | // by a debugger. 260 | // 261 | //***************************************************************************** 262 | static void 263 | NmiSR(void) 264 | { 265 | // 266 | // Enter an infinite loop. 267 | // 268 | while(1) 269 | { 270 | } 271 | } 272 | 273 | //***************************************************************************** 274 | // 275 | // This is the code that gets called when the processor receives a fault 276 | // interrupt. This simply enters an infinite loop, preserving the system state 277 | // for examination by a debugger. 278 | // 279 | //***************************************************************************** 280 | static void 281 | FaultISR(void) 282 | { 283 | // 284 | // Enter an infinite loop. 285 | // 286 | while(1) 287 | { 288 | } 289 | } 290 | 291 | //***************************************************************************** 292 | // 293 | // This is the code that gets called when the processor receives an unexpected 294 | // interrupt. This simply enters an infinite loop, preserving the system state 295 | // for examination by a debugger. 296 | // 297 | //***************************************************************************** 298 | static void 299 | IntDefaultHandler(void) 300 | { 301 | // 302 | // Go into an infinite loop. 303 | // 304 | while(1) 305 | { 306 | } 307 | } 308 | -------------------------------------------------------------------------------- /tm4c123gh6pm.cmd: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Default Linker Command file for the Texas Instruments TM4C123GH6PM 4 | * 5 | * This is derived from revision 10691 of the TivaWare Library. 6 | * 7 | *****************************************************************************/ 8 | 9 | --retain=g_pfnVectors 10 | 11 | MEMORY 12 | { 13 | FLASH (RX) : origin = 0x00000000, length = 0x00040000 14 | SRAM (RWX) : origin = 0x20000000, length = 0x00008000 15 | } 16 | 17 | /* The following command line options are set as part of the CCS project. */ 18 | /* If you are building using the command line, or for some reason want to */ 19 | /* define them here, you can uncomment and modify these lines as needed. */ 20 | /* If you are using CCS for building, it is probably better to make any such */ 21 | /* modifications in your CCS project and leave this file alone. */ 22 | /* */ 23 | /* --heap_size=0 */ 24 | /* --stack_size=256 */ 25 | /* --library=rtsv7M4_T_le_eabi.lib */ 26 | 27 | /* Section allocation in memory */ 28 | 29 | SECTIONS 30 | { 31 | .intvecs: > 0x00000000 32 | .text : > FLASH 33 | .const : > FLASH 34 | .cinit : > FLASH 35 | .pinit : > FLASH 36 | .init_array : > FLASH 37 | 38 | .vtable : > 0x20000000 39 | .data : > SRAM 40 | .bss : > SRAM 41 | .sysmem : > SRAM 42 | .stack : > SRAM 43 | } 44 | 45 | __STACK_TOP = __stack + 512; 46 | -------------------------------------------------------------------------------- /usb_structs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * usb_structs.c 3 | * 4 | * Created on: 31 dec. 2012 5 | * Author: Frans-Willem 6 | * Minor tweak for Tivaware compatibility by Richard Aplin, Dec2013 7 | */ 8 | #include //tivaware tweak 9 | #include 10 | 11 | #include "inc/hw_types.h" 12 | #include "driverlib/usb.h" 13 | #include "usblib/usblib.h" 14 | #include "usblib/usb-ids.h" 15 | #include "usblib/device/usbdevice.h" 16 | #include "usblib/device/usbdbulk.h" 17 | #include "usb_structs.h" 18 | 19 | const unsigned char g_pLangDescriptor[] = 20 | { 21 | 4, 22 | USB_DTYPE_STRING, 23 | USBShort(USB_LANG_EN_US) 24 | }; 25 | 26 | const unsigned char g_pManufacturerString[] = 27 | { 28 | (23 + 1) * 2, 29 | USB_DTYPE_STRING, 30 | 'C',0,'a',0,'m',0,'b',0,'r',0,'i',0,'d',0,'g',0,'e',0,' ',0,'S',0,'i',0,'l',0,'i',0,'c',0,'o',0,'n',0,' ',0,'R',0,'a',0,'d',0,'i',0,'o',0 31 | }; 32 | const unsigned char g_pProductString[] = 33 | { 34 | (14 + 1) * 2, 35 | USB_DTYPE_STRING, 36 | 'C',0,'S',0,'R',0,' ',0,'P',0,'r',0,'o',0,'g',0,'r',0,'a',0,'m',0,'m',0,'e',0,'r',0 37 | }; 38 | const unsigned char g_pSerialNumberString[] = 39 | { 40 | (8 + 1) * 2, 41 | USB_DTYPE_STRING, 42 | '1', 0, '2', 0, '3', 0, '4', 0, '5', 0, '6', 0, '7', 0, '8', 0 43 | }; 44 | const unsigned char g_pDataInterfaceString[] = 45 | { 46 | (19 + 1) * 2, 47 | USB_DTYPE_STRING, 48 | 'B', 0, 'u', 0, 'l', 0, 'k', 0, ' ', 0, 'D', 0, 'a', 0, 't', 0, 49 | 'a', 0, ' ', 0, 'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 50 | 'a', 0, 'c', 0, 'e', 0 51 | }; 52 | const unsigned char g_pConfigString[] = 53 | { 54 | (23 + 1) * 2, 55 | USB_DTYPE_STRING, 56 | 'B', 0, 'u', 0, 'l', 0, 'k', 0, ' ', 0, 'D', 0, 'a', 0, 't', 0, 57 | 'a', 0, ' ', 0, 'C', 0, 'o', 0, 'n', 0, 'f', 0, 'i', 0, 'g', 0, 58 | 'u', 0, 'r', 0, 'a', 0, 't', 0, 'i', 0, 'o', 0, 'n', 0 59 | }; 60 | const unsigned char * const g_pStringDescriptors[] = 61 | { 62 | g_pLangDescriptor, 63 | g_pManufacturerString, 64 | g_pProductString, 65 | g_pSerialNumberString, 66 | g_pDataInterfaceString, 67 | g_pConfigString 68 | }; 69 | 70 | #define NUM_STRING_DESCRIPTORS (sizeof(g_pStringDescriptors) / \ 71 | sizeof(unsigned char *)) 72 | 73 | //***************************************************************************** 74 | // 75 | // The bulk device initialization and customization structures. In this case, 76 | // we are using USBBuffers between the bulk device class driver and the 77 | // application code. The function pointers and callback data values are set 78 | // to insert a buffer in each of the data channels, transmit and receive. 79 | // 80 | // With the buffer in place, the bulk channel callback is set to the relevant 81 | // channel function and the callback data is set to point to the channel 82 | // instance data. The buffer, in turn, has its callback set to the application 83 | // function and the callback data set to our bulk instance structure. 84 | // 85 | //***************************************************************************** 86 | 87 | //Tivaware mods see http://www.ti.com/lit/an/spma050a/spma050a.pdf section 3.7.2 88 | //Don't need tBulkInstance 89 | //? tBulkInstance g_sBulkInstance; 90 | 91 | tUSBDBulkDevice g_sBulkDevice = 92 | { 93 | 0x0a12, //VID 94 | 0x0042, //PID 95 | 500, 96 | USB_CONF_ATTR_SELF_PWR, 97 | RxHandler, 98 | (void *)0, 99 | TxHandler, 100 | (void *)0, 101 | g_pStringDescriptors, 102 | NUM_STRING_DESCRIPTORS, 103 | // &g_sBulkInstance //removed for tivaware 104 | }; 105 | 106 | 107 | -------------------------------------------------------------------------------- /usb_structs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * usb_structs.h 3 | * 4 | * Created on: 31 dec. 2012 5 | * Author: Frans-Willem 6 | * Minor tweak for Tivaware compatibility by Richard Aplin, Dec2013 7 | */ 8 | 9 | #ifndef USB_STRUCTS_H_ 10 | #define USB_STRUCTS_H_ 11 | 12 | #define BULK_BUFFER_SIZE 256 13 | 14 | extern uint32_t RxHandler(void *pvCBData, uint32_t ui32Event, 15 | uint32_t ui32MsgValue, void *pvMsgData); 16 | extern uint32_t TxHandler(void *pvi32CBData, uint32_t ui32Event, 17 | uint32_t ui32MsgValue, void *pvMsgData); 18 | 19 | extern tUSBDBulkDevice g_sBulkDevice; 20 | 21 | 22 | #endif /* USB_STRUCTS_H_ */ 23 | --------------------------------------------------------------------------------