• Announcements

    • bluehash

      Forum Upgrade   03/11/2017

      Hello Everyone, Thanks for being patient while the forums were being fixed and upgraded. Please see details and report issues in this thread. Thanks!

DrOldies

Members
  • Content count

    17
  • Joined

  • Last visited

  1. I have found the Energia pin map pdf's are difficult to match with the (several) pin numbering systems so I created an Excel spreadsheet to combine all of these. It's in a spreadsheet so you can sort on any column. This makes it much easier to find the pins and their functions. The pin functional groups are color coded. Two sample images of the tables are included, one based on the Boosterpack pins (booster_pack), and the second on the breadboard pins (breadboard). Numbering lists include physical pins X6-X9, boosterpack pins A1- D2, GPIO pins PA-PQ, and digital pin-to-port numbers 1-95 TM4C1294 Board Pinouts_V3.zip
  2. (I started this [Energia Library] topic and copied my spiE library over to make it easier to find) I wanted to improve the compatibility of the SPI.h lm4f library to include functions of arduino user contributed SPI.h libraries. I found SPI2.h here: http://forum.stellar...two-spi-modules. This library added multi-module features but removed the 123 & 1294 compatibility. I have merged SPI2 and the core SPI libs into spiE.h and added several more function variations. spiE.h best features are: 1. Array transfer up to 255 bytes. This is 5x faster than single byte transfer. 2. SPI2's pinMode() and digitalWrire() functions are replaced with faster macros. 3. Support for __TM4C129XNCZAD__, __TM4C1294NCPDT__, BLIZZARD_RB1 (LM4F) boards 4. Up to 4 instances can be defined: SPI0, SPI1, SPI3, & SPI2 is instantiated by default as SPI for arduino code compatibility. 5. Multiple SlaveSelect pins can be used fir multiple devices on one data line. defaultSS, default +SS2, or SS1 + SS2, etc. I have tested this on the 129. If you have a need for it and can try it on the other boards before I upload it to github, be my guest. spiE.zip
  3. SOLVED! Using your advice I looked for an alternative to SSI_DMARX/TX. SSI_TXEOT (transfer buffer empty) gives the program control for updating the send array if used in SSI_Init., and the interrupt function. I also found that the interrupt frequency can also be set during initialization. void SSI_Init(uint32_t _freqHz_){ ROM_SSIIntEnable(SSI0_BASE, SSI_TXEOT); ROM_SSIConfigSetExpClk(SSI0_BASE, F_CPU, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, _freqHz_, 8); } void SSI0IntHandler(void) if (ui32Status == SSI_TXEOT) { //update send array } } Here is the code. //SpiDamInt_E.h #ifndef SPI_DMA_INT_H #define SPI_DMA_INT_H #include <Energia.h> #include <driverlib/ssi.h> #include <inc/hw_ssi.h> #include <driverlib/sysctl.h> #include <driverlib/udma.h> #include <driverlib/rom_map.h> #include <inc/hw_ints.h> // How do we want the DMA process to proceed? #define AUTO (1) //DMA will read from the program buffer every time its //transfer buffer is empty. It will send continuously. //#define SEMI (2) //DMA will read from the program buffer only when //_changedBuffer = true. It will send continuously. #define MANUAL (3) //DMA will read from the program buffer AND send only //when _changedBuffer = true #define STOP (0) //disable dma/spi transfers void ConfigureSSI0(uint32_t _freqHz_); void SSI_Init(uint32_t _freqHz_); void SSI0IntHandler(void); void CongifureuDMA(void); void SSIEnableTemp(uint32_t numBytes); void SSIEnable(void); // The count of SSI0 buffers filled static uint32_t g_ui32SSIRxCount = 0; static uint32_t g_ui32SSITxCount = 0; // The size of the memory transfer source //and destination buffers (in bytes) #define SSI_TX_BUFFER_SIZE (1024) #define SSI_RX_BUFFER_SIZE (1024) #endif //SPI_DMA_INT_H //SpiDamInt_E.cpp //SSI / uDMA Example TM4C1294XL #include "SpiDmaInt_E.h" template<class T> inline Print &operator <<(Print &obj, T arg) { obj.print(arg); return obj; } // The control table used by the uDMA controller. This table must be aligned // to a 1024 byte boundary. uint8_t pui8ControlTable[1024] __attribute__ ((aligned(1024))); //Gives the sketch control of the send buffer length. extern uint8_t g_ui8SSITxBuf[]; extern uint8_t g_ui8SSIRxBuf[]; //variables for class:private later uint32_t g_actualBufferSize; uint8_t g_dmaControl = AUTO; //the default - under program control // single buffer write/DMA read management bool g_writingBuffer = false; //Are we writing new data to the Buffer? bool g_changedBuffer = true; // Has the Buffer been changed? bool g_DMAreading = false; //If the DMA interrupt routine reading the Buffer? void led12(){ static bool ledon; if (ledon){ digitalWrite(82, LOW); digitalWrite(81, HIGH); ledon = 0; } else{ digitalWrite(81, LOW); digitalWrite(82, HIGH); ledon = 1; } } //---------------------SSI SPI Handler--------------------------------------- // SSI0 Interrupt Handler void SSI0IntHandler(void) { uint32_t ui32Status; uint32_t ui32Mode; //Int flag needs to be clear early in thid function ui32Status = ROM_SSIIntStatus(SSI0_BASE, 1); ROM_SSIIntClear(SSI0_BASE, ui32Status); // Interrupt due to TX FIFO empty so buffer is empty if (ui32Status == SSI_TXEOT) { //TRANSFER DONE, take SS HIGH ROM_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); led12(); //<<<<<<<<<<<<<<<< test if (g_dmaControl == MANUAL & !g_changedBuffer){ //do nothing return; } g_DMAreading = true; //I'm using the buffer while (g_writingBuffer); //wait until buffer is available SSIEnable(); //restart with current data and numbytes g_DMAreading = false; //done } } void SSIEnableTemp(uint32_t bufferSize){ //update buffer size g_actualBufferSize = bufferSize; SSIEnable(); } //---------------enable --------------------------- void SSIEnable(void){ //As soon as the channels are enabled, the peripheral will // issue a transfer request and the data transfers will begin. ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *)(SSI0_BASE + SSI_O_DR), g_ui8SSIRxBuf, g_actualBufferSize); ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, g_ui8SSITxBuf, (void *)(SSI0_BASE + SSI_O_DR), g_actualBufferSize); //start a new transfer take SS LOW ROM_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0); //The uDMA controller disables the channel at //the completion of a transfer. Restart here. ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0RX); ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0TX); } //----------------------initialize SSI --------------------------- void SSI_Init(uint32_t _freqHz_) { CongifureuDMA(); ConfigureSSI0(_freqHz_); //uDMA SSI0 RX (receive functionality not tested) ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0RX, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); ROM_uDMAChannelControlSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_4); //uDMA SSI0 TX ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0TX, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); ROM_uDMAChannelControlSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4); //Registers an interrupt handler for the synchronous serial interface. SSIIntRegister(SSI0_BASE, *SSI0IntHandler); ROM_SSIDMAEnable(SSI0_BASE, SSI_DMA_RX | SSI_DMA_TX); // Enable the SSI0 DMA TX/RX interrupts. //ROM_SSIIntEnable(SSI0_BASE, SSI_DMATX | SSI_DMARX); //95 ROM_SSIIntEnable(SSI0_BASE, SSI_TXEOT); //95 // Enable the SSI0 peripheral interrupts. ROM_IntEnable(INT_SSI0); } //-------------------SSI---------------------------- void ConfigureSSI0(uint32_t _freqHz_) { //uint32_t trashBin[1] = {0}; // Configure GPIO Pins for SSI0 mode. ROM_GPIOPinConfigure(GPIO_PA2_SSI0CLK); ROM_GPIOPinConfigure(GPIO_PA4_SSI0XDAT0); ROM_GPIOPinConfigure(GPIO_PA5_SSI0XDAT1); ROM_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_2); // Configure GPIOA_3 as the SSI Chip Select ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3); ROM_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); //HIGH // Enable the SSI0 Peripheral. ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); _freqHz_ = (_freqHz_ > 16000000) ? 16000000 : _freqHz_; _freqHz_ = (_freqHz_ < 1000) ? 1000 : _freqHz_; ROM_SSIConfigSetExpClk(SSI0_BASE, F_CPU, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, _freqHz_, 8); //1000 min - 16000000 maximum ROM_SSIEnable(SSI0_BASE); /* Clear SSI0 RX Buffer */ //while (ROM_SSIDataGetNonBlocking(SSI0_BASE, &trashBin[0])) {} } //-------------------uDMA---------------------------- void CongifureuDMA(void){ // Enable the uDMA controller at the system level. ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); // Enable the uDMA controller. ROM_uDMAEnable(); // Point at the control table to use for channel control structures. ROM_uDMAControlBaseSet(pui8ControlTable); //note: must BE LAST STATEMENT } I plan to convert this to an Energia compatible class with write and read functions. I'll post the link here when I add it to github.
  4. I obviously don't know what SysTick is supposed to do. Reviewing other code (very few examples are available) I gathered that it is a counter and when the SysTick value is reached it trips a DMA service interrupt. For the Arduino I would use a Timer interrupt. SysTick seems like a more efficient way to do this. Using SSI_DMARX/TX the interrupt occurs as soon as the array being transferred has been sent - the program has no control over the timing - so its not clear when I update that array. In my code these 3 line of code do nothing (I commented them out during testing). ROM_SysTickPeriodSet(period); ROM_SysTickIntEnable(); ROM_SysTickEnable(); I appreciate your comments.
  5. Sorry I was not clear in my last post. I'm learning that I cannot easily copy code from another MCU's program. The interrupt now works. It appears that the interrupt is based on the DMA Transmit completing (SSI_DMATX). The SysTickPeriod Set(period) has no effect and I can even comment out the 3 lines below in my CongifureuDMA() routine. What would I need to change to have the SysTick period control the interrupt timing? ROM_SysTickPeriodSet(100); ROM_SysTickIntEnable(); ROM_SysTickEnable(); BTW: The SSIIntEnable values are from ..\cores\lmf4\driverlib\ssi.h. They seemed like the best of the choices. #define SSI_TXEOT 0x00000040 // Transmit FIFO is empty #define SSI_DMATX 0x00000020 // DMA Transmit complete #define SSI_DMARX 0x00000010 // DMA Receive complete #define SSI_TXFF 0x00000008 // TX FIFO half full or less #define SSI_RXFF 0x00000004 // RX FIFO half full or more #define SSI_RXTO 0x00000002 // RX timeout #define SSI_RXOR 0x00000001 // RX overrun
  6. These maps are very useful but rather blurry. Can you make them available in a higher res format and downloadable like pdf? Thanks
  7. I registered the IntHandler and stripped out all the unnecessary calls as you suggested. I added LED toggles to the interrupt handler and the .ino sketch. It is functioning properly now, toweling 2 LEDs for each. However, ROM_SysTickPeriodSet(Period) seem to change the interrupt timing interval. I think that the uDMA may be triggering the interrupt every time the data send is completed (regardless of the tick period), but I can't see what I might have set incorrectly. I would like to be able to set the frequency from a few hertz to over 1 Mhz from the sketch. Here is the .cpp with the initialization and intHandler. The 2nd listing is the .ino sketch. uint8_t pui8ControlTable[1024] __attribute__ ((aligned(1024))); //---------------------SSI SPI Handler--------------------------------------- // SSI0 Interrupt Handler void SSI0IntHandler(void) { uint32_t ui32Status; uint32_t ui32Mode; static bool ledon; if (ledon){ digitalWrite(82, LOW); digitalWrite(81, HIGH); ledon = 0; } else{ digitalWrite(81, LOW); digitalWrite(82, HIGH); ledon = 1; } ui32Status = ROM_SSIIntStatus(SSI0_BASE, 1); ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT); if(ui32Mode == UDMA_MODE_STOP) { g_ui32SSIRxCount++; ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_MODE_AUTO, (void *)(SSI0_BASE + SSI_O_DR), g_ui8SSIRxBuf, sizeof(g_ui8SSIRxBuf)); ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0RX); } //AUTO or BASIC????? if(!ROM_uDMAChannelIsEnabled(UDMA_CHANNEL_SSI0TX)) { g_ui32SSITxCount++; ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT, UDMA_MODE_AUTO, g_ui8SSITxBuf, (void *)(SSI0_BASE + SSI_O_DR),sizeof(g_ui8SSITxBuf)); ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0TX); } ROM_SSIIntClear(SSI0_BASE, ui32Status); } void SSI_Init(void) { //uDMA SSI0 RX ROM_uDMAChannelControlSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_4); //uDMA SSI0 TX // Configure the control parameters for the SSI0 TX. ROM_uDMAChannelControlSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4); //Registers an interrupt handler for the synchronous serial interface. SSIIntRegister(SSI0_BASE, *SSI0IntHandler); //As soon as the channels are enabled, the peripheral will // issue a transfer request and the data transfers will begin. ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0RX); ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0TX); //no led 0n 43 if commented out ROM_SSIDMAEnable(SSI0_BASE, SSI_DMA_RX | SSI_DMA_TX); //33 // Enable the SSI0 DMA TX/RX interrupts. ROM_SSIIntEnable(SSI0_BASE, SSI_DMATX | SSI_DMARX); // Enable the SSI0 peripheral interrupts. ROM_IntEnable(INT_SSI0); //<<<<<<<<<<<<<< locks in this function } //-------------------SSI---------------------------- void ConfigureSSI0(void) { uint32_t trashBin[1] = {0}; // Enable the SSI0 Peripheral. ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); ROM_SSIConfigSetExpClk(SSI0_BASE, F_CPU, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 16000000, 8); //16000000 ROM_SSIEnable(SSI0_BASE); //ppd , SSI_DMA_TX ??? /* Clear SSI0 RX Buffer */ while (ROM_SSIDataGetNonBlocking(SSI0_BASE, &trashBin[0])) {} } //-------------------uDMA---------------------------- void CongifureuDMA(void){ // Configure SysTick to occur 100 times per second, to use as a time // reference. Enable SysTick to generate interrupts.- between 1 and 16, 777, 216, inclusive. ROM_SysTickPeriodSet(10000) ROM_SysTickIntEnable(); ROM_SysTickEnable(); // Enable the uDMA controller at the system level. ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); // Enable the uDMA controller. ROM_uDMAEnable(); // Point at the control table to use for channel control structures. ROM_uDMAControlBaseSet(pui8ControlTable); } #define LED1 (81) //Energia 4 led pins 81,82,83,84 #define LED2 (82) #define LED3 (83) #define LED4 (84) void setup(void) { // Serial.begin(9600); // delay(5000); // Serial.println ("start"); pinMode(LED1, OUTPUT); //these two are in the Interrupt handle routine pinMode(LED2, OUTPUT); pinMode(LED3, OUTPUT); //these two are in the .ino routine pinMode(LED4, OUTPUT); CongifureuDMA(); ConfigureSSI0(); //this was test data <<<<<<<<<<<<<<<<<<<<<<<<<<< // Fill the TX buffer with a simple data pattern. uint16_t dummy = 0b1101010101011101; for(uint_fast16_t ui16Idx = 0; ui16Idx < SSI_BUFFER_SIZE; ui16Idx++) { g_ui8SSITxBuf[ui16Idx] = dummy; //ui16Idx; } SSI_Init(); // Initialize the uDMA SPI transfers. } void loop(){ // Loop forever with the CPU not sleeping, so the debugger can connect. static bool led; if (led){ digitalWrite(84, LOW); digitalWrite(83, HIGH); led = 0; } else{ digitalWrite(83, LOW); digitalWrite(84, HIGH); led = 1; } }
  8. TM4C1294 PINOUT TABLE attachedTM4C1294 Board Pinouts.pdf I find the charts posted on Energia blurry and hard to read. I extracted the pinout table from one of the manuals and highlighted a few of the pin groupings (SSI, I2C, etc). Its much easier to read and its searchable.
  9. I am confused about the compatibility of BoosterPacks. According to the TM4C123 pub spmu296.pdf: * The TM4C123 is compatible with the "TIVA C Series LaunchPad BoosterPack XL" * The outer column of pins are also compatible with MSP430 "LaunchPad-Compatible BoosterPacks" In the TM4C129 pub spmu365a.pdf it describes the first and second BoosterPack XL. "‘A’ and ‘D’ make up the outer BoosterPack standard pins, ‘B’ and ‘C’ make up the inner BoosterPack XL standard pins." On examining the pinouts between the 123 and 1294 for these 2x10 pins, none of the pin functions match. How do I identify which boards a BoosterPack will be compatible with? Some BP descriptions say " for the MSP430." Most do not mention compatibility.
  10. This is a boosterpack/shield that is needed. Could you post back on this thread when you want to share the design or have the boards ready? That way I can get notified by following this tread. So many times good ideas like this are mentioned and then I never hear about them again.
  11. Good suggestions. I tried both and added print statements to the 3 error handlers included from the previous code: 1. The LED statement in SSI0IntHandler does NOT turn with ROM_IntEnable(INT_SSI0); enabled. 2. The code returns to main when IntEnabled is commented out. ( As expected, without the Interrupt enabled, nothing else happens) 3. None of the error traps below report an error. static void NmiSR(void) Serial.println ("processor received a NMI");//debug static void FaultISR(void) Serial.println ("received a fault interrupt");//debug static void IntDefaultHandler(void) Serial.println ("processor received an unexpected interrupt");//debug Since the code was taken from code for the TM4C129x, I have assumed all the setting in the other macros are set properly. The Peripherals Guide explanations are very limited on explaining the various setting options.
  12. I am trying to take the code from here: http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/367620.aspx and convert it to a Arduino/Energia library. The setup and initialization gets through the SSI configuration, and the uDMA configuration. However, at the last step to enable the interrupt it does not return from this call: // Enable the SSI0 peripheral interrupts. ROM_IntEnable(INT_SSI0); The original code was very well documented, but I'm including a version of my code with the comments removed for easier reading. There are so many steps to get SSI, DMA, and INT functions enabled, its hard too tell what might be wrong with this. SpiDmaInt_cpp.txt SpiDmaInt_Example_ino.txt
  13. I assume you mean as an additional library such as spiE.h, and not as an update to the core SPI.h? After its tested you are welcome to add it as SPI.h since 90% of the code is from it.
  14. I wanted to improve the compatibility of the SPI.h lm4f library to include functions of arduino user contributed SPI.h libraries. I found SPI2.h here: http://forum.stellarisiti.com/topic/620-two-spi-modules. This library added multi-module features but removed the 123 & 1294 compatibility. I have merged SPI2 and the core SPI libs into spiE.h and added several more function variations. spiE.h best features are: 1. Array transfer up to 255 bytes. This is 5x faster than single byte transfer. 2. SPI2's pinMode() and digitalWrire() functions are replaced with faster macros. 3. Support for __TM4C129XNCZAD__, __TM4C1294NCPDT__, BLIZZARD_RB1 (LM4F) boards 4. Up to 4 instances can be defined: SPI0, SPI1, SPI3, & SPI2 is instantiated by default as SPI for arduino code compatibility. 5. Multiple SlaveSelect pins can be used fir multiple devices on one data line. defaultSS, default +SS2, or SS1 + SS2, etc. I have tested this on the 129. If you have a need for it and can try it on the other boards before I upload it to github, be my guest. spiE.zip
  15. Looking thru the lm4f library's SPI.h it appears that while I can instantiate 3 SPI objects (SSI1, SSI2, and SSI3), on 3 sets of pins, I cannot use any slaveSelect pin other than the default slaveSelect pin. I would like to control 2 devices by using the default SS pin and a second SS2 pin. Some other boards' SPI libraries leave the SS pin control to the user, making this simple. Any suggestions?