This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

SPI Speed on ARM microprocessors (Tiva for example)

What speeds do the TI processors allow the SPI bus to run?  For example, if the processor is 220MHz, is SPI limites to 110MHz (divide by 2), 55MHz (divide by 4) or less?

Is there a general rule for TI micros speed vs SPI speed?

We are looking at using the SPI bus to oversample a slower (24MHz) signal on the bus and recreate it with firmware.  4x oversampling would be good, so I am wondering which MCU speed I would need.

Thanks,
Jeff 

  • SPI speed conforms to ARM standard (DDI0194G) - so minimum divisor factor is 4, same for other brand(s), not citing here. Tiva maximum clock speed is 80MHz.

    Petrei

  • While vendor indeed produces "Microprocessors" - and those may reach listed speed/beyond - you've landed on "MicroController" site - where 80MHz System Clock speed limit is enforced...  And this - divided prior to routing to SSI/SPI modules...

    These MCUs appear ill-suited for the high SPI speeds you list...

  • Thanks for your help guys, I wasn't aware of the /4 SPI ARM rule as well as the 80MHz split between controllers and processors!

  • Hey,

    Quick question.  I'm using SPI busses on a Tiva C TM4C123 part (80 Mhz MCLK) and the data sheet for this family says don't go beyond 25Mhz.  In developing I've tried 20-25 and I seem to get a lot of problems beyond 20.  So if 20 is the hard stop, max speed, for these chips why does the data sheet state 25?

    I've had some serious headaches because of this I think.

    Thanks,

    Rob

  • Hello Rob,

    There are multitude of timings involved with SSI Master mode which may make it tight for a Slave device. I have seen issues when the slave device is connected with wires v/s the same slave working absolutely fine when soldered down with good trace lengths match.

    Is there any specific slave device, that you are having problems with for >20MHz?

    Regards

    Amit

  • Amit Ashara said:
    I have seen issues...slave connected with wires...v/s the same slave working absolutely fine when soldered down with good trace lengths match.

    While not, "full-fledged, bought/paid for" apologist for this vendor - Amit's "spot-on" here.

    "Good trace length" may be clarified by stating, "Short, direct and balanced length" between the SPI signal lines.  Further note that while not "ideal" - such SPI speeds are aided by use of proper, high-speed cabling - not undisciplined (i.e. "handy") wires.  And - you should avoid operation of known, "noise sources" and SPI trace or cable routings in near proximity to other active, higher speed digital lines - when the high-speed SPI transaction is enabled.

    As always - your report rises in interest/value if your issue is noted to repeat - across multiple MCU and slave boards.  These are "short-range" signal buses - speed must be substantially "dialed down" when connection lengths exceed ~15 mm.  (we note this across multiple ARM MCUs - many vendors {we use 4}).

  • Hey Guys,


    I was just curious about the speed.  My yes or no question is ....is the max "usable" speed of the SPI ports in the Tiva 123 parts 20Mhz? or 25Mhz?  It sounds to me like the max speed is 20Mhz - 80Mhz CLK/4.

    I"m connecting the two ports to some Spansion flash parts.  the traces are only about 1 inch or less long, but not exactly matched like differential pairs usually are.


    My issue is that if I run my system (it takes ADC samples and sends blocks of them into the flash memory) at full speed and have no I2C configuration code it will run no problem.  This is with SPI set to 20Mhz which should be fine.  When I just "enable" the spi port my data being written into memory becomes skewed (it's wrong as in I get random samples out of place or dropped).  If I slow down my sampling rate so my system sends data into memory a little bit slower it is fine.  If I remove the I2C configuration instruction....actually it's just the I2C enable peripheral instruction everything is fine at max speed...no problems. 

    I've tried enabling all the I2C ports...like I would enable I2C0, run a test, bad data.  Enable I2C1 run a test bad data etc...for all 4 I2C ports.  I've literally got it down to enabling the peripheral affects my performance which makes no sense to me.  I've made sure I don't enable a peripheral or anything more than once.  This system is on a PCB so no wires or cables...just very short traces. 


    So, this is why I was wondering if I could reliably run the SPI ports at 25Mhz to maybe give me some more wiggle.

    My system takes a block of samples and pushes them out of SPI ports so I figured if I could get another 5Mhz out of the two SPI ports the data would get out of the ARM faster and maybe alleviate this problem.


    Didn't mean to jump on someone's thread with all this :(

  • Hi,

    Please check the following routine/file, where the SPI speed is set, overwriting any of your settings:

    Tiva/third_party/fatfs/port/mmc-dk-tm4c123g.c : void set_max_speed(void);

    Here any speed greather than 12.5MHz is replaced with this value.

    Petrei

  • You may be a bit too, "greedy" (and tempting fate) trying for that 25MHz - mais non?

    Curious if that same (unwanted) I2C effect occurs @ 20MHz SPI - might you advise?

    As an admitted "long shot" - might your 3V3 be, "at the edge" and the combination of high speed SPI and I2C peripheral being "powered/enabled" simply causes that 3V3 to randomly "dip?"  (we've seen this - when reg was improperly sized and/or powered...)

    (note that poster Petrei's 12.5MHz SPI max likely sprung from "old dayze" - when Stellaris ruled the earth - and speed limit was 50MHz.  20MHz SPI now "normal/customary" for left lane users - w/rebrand specials "under the hood.")

    (other ARM brands may top this 20MHz SPI - if you "really" live/die by that desire.  Do note that 20MHz (or higher) places you squarely in the HF radio band - and should you have "commercial hopes" expect that your, "Agency Approval tests" will almost surely "squawk" at that 20MHz (or higher) blasting their RF pick-up...  And - that 20MHz will likely impact any "unexpecting" low level pcb trace running nearby - especially parallel to your transmitter (i.e. 20 MHz SPI clock))

  • Hey guys great replies!  I'll double check my regulator to ensure I don't a have a power issue.  I'm still confused as on the 25Mhz.  Should it work or not?  Here is my configuration code for one of the SPI ports.

    	// ------------------------------
    	// Configure SSI0 module
    	// ------------------------------
    	GPIOPinConfigure(GPIO_PA2_SSI0CLK);					// Enable CLK pin
    	GPIOPinConfigure(GPIO_PA5_SSI0TX);					// Enable TX pin
    	GPIOPinConfigure(GPIO_PA4_SSI0RX);					// Enable RX pin
    	GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_2);		// Enable comm. pins for SSI module
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);									// Enable SSI0 peripheral
    	SSIConfigSetExpClk(SSI0_BASE, 80000000, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 20000000, 8);
    	SSIEnable(SSI0_BASE);								// Enalbe SSI0
    
    	// enable uDMA for SSI
    	SSIDMAEnable(SSI0_BASE, SSI_DMA_TX);				// Enable DMA for SSI0 TX
    	IntEnable(INT_SSI0);								// Enable interrupt for SSI (this is actually over ridden by the uDMA meaning when the entire DMA (512 byte) DMA tx is done the int. is triggered)
    	uDMAChannelControlSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_8);		// Configure channel control
    
    	// Enalbe CS pin for manual control
    	GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);		// Set PA3 as CS pin for SSI which is toggled manually
    	GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0x08);		// Initialize to a high - no bus activity
    
    	// Empty SSI receive buffer
    	uint32_t emptySSI;		// dummy integer
        while(SSIDataGetNonBlocking(SSI0_BASE, &emptySSI))
        {	// loop to empty bus
        }	// non-blocking
        IntPrioritySet(INT_SSI0,  0x20);	// Lower interrupt priority

    Per cb1's question:  At 20 Mhz with I2C peripheral enabled my data that I push into memory (I know if it's dropping bytes b/c I'm just pushing a 16 bit counter) is bad in places.  When I download the data to my computer it will drop 10-60 bytes on and off.  I should see 1-65535 repeated, but instead things get skipped and mixed up. 

    When I push the SPI busses to 25Mhz I can't run my system for a couple 100 miliseconds and it's good.  If I run for a couple seconds the SPI links drop out.  I verified this by toggling an LED every time push a 512 byte block to memory over these busses.  I can see on the scope it will run for a little bit (couple 100 miliseconds to couple seconds) but if I run for say 10-20 seconds it always drops out. 


    Its like I'm stuck in the middle here because 20Mhz works fine, but not at full speed (500ksps rate which pushes 1 megabyte/s to memory (pushing 16bit sample at 500ksps).  If I up the speed it will run correctly for a short duration, but the busses drop out. 

    I have to run out this afternoon, but I'll check out the function "void set_max_speed(void);" Petrie told me about. 

    Per EMI: This is for my own personal startup so all I care about now are working prototypes :)  I"ll deal with EMI etc....later :)

    As always, I really appreciate all of you taking the time here applying your experience/experties to my problem.  I'll get back with more info when I have time to delve in in more detail to some of you suggestions.

    Rob

  • Hello Rob,

    As per the API structure you would not be able to generate 25MHz from 80MHz, unless you have changed the clock speed (the code post does not suggest that)

    Regards

    Amit

  • Hey Guys,

    So I've made some progress using this code to configure I2C before I configure anything else.

        //
        // I2C1
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
        I2CMasterInitExpClk(I2C1_BASE, SysCtlClockGet(), false);
        GPIOPinConfigure(GPIO_PA6_I2C1SCL);
        GPIOPinConfigure(GPIO_PA7_I2C1SDA);
        //GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);
        //GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);

    So if I run that as is with the last two lines commented out it looks like my system is back up and running reliably.  After going back and re-reading the documentation I noticed that the two commented lines are required (from what I understand reading the comments in the function and the peripheral driver library) only when you have configurable pins that you can use to mux in different peripheral.  Since I'm using the TM4C123GE6PMI I don't have this capability. 

    For example, if I'm correct, my I2C1 port pins are hard wired to PA6 and PA7.  Does that mean I don't need the

        //GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);
        //GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);

    calls after all and they could be screwing me up?  Implementing (compiling) either one screws me up.  Does it make sense to not use these function calls in my case and just use

        //
        // I2C1
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
        I2CMasterInitExpClk(I2C1_BASE, SysCtlClockGet(), false);
        GPIOPinConfigure(GPIO_PA6_I2C1SCL);
        GPIOPinConfigure(GPIO_PA7_I2C1SDA);

    to configure I2C1?  I would then just apply this same idea to I2C0 and I'd be got to go.

    Also, I verified it is not a power/regulator problem, but that was actually a great idea!

  • Robbie Valentine said:

    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);

    I2CMasterInitExpClk(I2C1_BASE, SysCtlClockGet(), false);

    We're (sometimes) told that some delay should be inserted just post, "SysCtlPeripheralEnable()."  Code quoted reveals none.  Now past manuals suggested 5 clock cycles - then more recently that dropped to 3 clock cycles.  And - our small group has (like you) run (sometimes) successfully with no/zero delay.  Suggest you place some delay - see what's what.

    Recall that Amit advises 20MHz as top SPI speed - violation is unwise especially with MCU lot variations, operating temperatures/regulator accuracies, and slave device variations.  "Bending" the specs has been known to prove costly - "Risk-Reward" shouts against such!  20MHz (this vendor's MCUs @ SPI) - that's the law!

  • Hey CB, I'm definitely keeping the SPI speed at 20 MHz. Ill also throw some delays in between my peripheral enables for good measure. Any idea about the above mentioned code? Do you need those function calls to configure i2c?
  • Hello Robbie,

    The function calls mentioned are required to configure the I2C SCL and SDA. The one's before that configure the AFSEL and PCTL so that the PA6 and PA7 are connected to the I2C Instance. The other configure the registers of GPIO to set up I2C Open Drain.

    Regards

    Amit

  • Hi Amit,

    Believe that poster Robbie may be implying/suggesting that PA6/PA7 may "default" into I2C operation - thus the calls may be "unnecessary" or (worse still) disruptive.  (i.e. may some way/how contaminate the default operation of Port A)

    Have none of these parts on hand - earlier poster stated that operation was "ok" (until) those additional function calls were made - I'm further highlighting that comment here...

  • Hello cb1,

    By default the GPIO Pins will remain in Input Mode, so not having the call will not default it in I2C Mode. Since the I2C1 port is required by the application, configuring the same would be required. Just that it is hardwired is not sufficient.

    What would be good to see what the function call will do to Port A register settings when SSI port does not wotk v/s when it does work (w/o the settings)

    Regards

    Amit

  • Amit Ashara said:
    ...It would be good to see what the function call will do to Port A register settings when SSI port does not work!

    Indeed - I wasn't smart enough to suggest that. (your suggestion is ideal!)

    I know only a few of these TM4C parts - recall that many (and past LX4F) "default" Port A into UART, SPI, and I2C - if my memory serves...  (that was the basis of my earlier writing)

  • So I'm still working on this tonight, but I got some screen shots for you and a couple of things I noticed in doing this.  Attached are the screen shots the first one, "before.jpg", is the working version and "after.jpg" is where I add in those function calls and get a failure. 

    Failure induced:

    My PORTA is configure ad follows.  Pins 0, 1 are unused, pin2 is the SSI_CLK, pin3 is a chip select for the SSI Port, but I control this manually as a digital output because I have to do block writes so this is a plain old digital output.  Pin4 and 5 are SSI RX and TX respectively and 6 and 7 are SCL and SDA respectively.  Just so you have an idea of whats going on with the overall port.  One of the things I thought was odd is that there is only one pin being configure as open drain and that is pin7 in GPIO_ODR register.  The other thing I thought was strange is that GPIO_DEN (digital function enable) is enabled for all of the pins except pins0 and 1 which I'm not using. 

    Other than that the only change is the analog function select register (AFSEL) which (I think) makes sense because I'm not using anything on pins 0,1 and pin 3 is a digital output. 

  • Hello Rob,

    The configuration is correct. The use of I2C is not affecting the configuration of the SSI in anyways. So technically it should not cause an issue.

    The GPIODEN is fine since pin-0 and 1 are not being used. Could you check on a scope what is happening when the failure does occur? That would shed some light to the issue. A good idea would be to get the waveforms when it is working and when it fails.

    Regards

    Amit

  • Robbie Valentine said:

    So I've made some progress using this code to configure I2C before I configure anything else.

        //

        // I2C1

        //

        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

        SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);

        I2CMasterInitExpClk(I2C1_BASE, SysCtlClockGet(), false);

        GPIOPinConfigure(GPIO_PA6_I2C1SCL);

        GPIOPinConfigure(GPIO_PA7_I2C1SDA);

        //GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);

        //GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);

    Shouldn’t you configure all your pins before using ‘I2CMasterInitExpClk’?

  • Marc_rir,


    I've tried that as well as putting it in some other places and I didn't see a difference. 

    I did finally get up and running and it looks like I'm doing good.  I've done some 2 million sample runs and the data has been in tack.  I don't know if it was a code problem.  The code set that is up and running now is basically my original code with the two I2C configure blocks shown previously dropped in.  The thing that made the change was turning on optimizations in the compiler to level 2.  I had optimizing turned off during development over the pas year basically because I read somewhere that it was a good idea so the compiler doesn't do something you didn't intend. 

    After turning on optimizations my whole system looks like it is working fine now.  The code we've been discussing works fine.  I guess it was something about the code not being efficient enough to meet my timing or something.  My code size shrank a little and all seems to be good now. 

  • Good you got it working, would be interesting to see the difference of the assembler output, between the non-optimized code and the level 2 optimized code…

     

    On a side note, if you need more throughput, why not using a TM4C129X with Quad SPI(and 60MHz max SPI clock)?