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.

CC3220: Documentation TI-Drivers for interrupt priority and SPI frequency

Part Number: CC3220

I have the CC3220MODASF12 Launchpad-XL and basically I have three questions about abstraction of TI drivers:

1) How does interrupt priority work on a CC3220 device? Is it possible to change the priority?
I know that the CC3220 uses an ARM Cortex M4 core, so it has a Nested Vector Interrupt Controller (NVIC).
In the old driverlib there were functions available such as " IntPrioritySet(unsigned long ulInterrupt, unsigned char ucPriority); ", however I can't find a equivalent function in TI-Drivers lib.
Only thing I could find was in documentation of GPIO:

"A device specific GPIOxxx_Config structure that tells the GPIO driver where the two aforementioned arrays are and the number of elements in each. The interrupt priority of all pins configured to generate interrupts is also specified here. Values for the interrupt priority are device-specific. You should be well-acquainted with the interrupt controller used in your device before setting this parameter to a non-default value. The sentinel value of (~0) (the default value) is used to indicate that the lowest possible priority should be used."

The abstractions in CMSIS library for NVIC is a lot closer to the real hardware , and would like to use this library if available for CC3220.

2) What is the real frequency of SPI CLK when setting spiParams.bitRate?
I want to control the SPI speed of the device, and switch between 3 MHz and 20 MHz. You can set spiParams.bitRate (=frequency in Hz) to any arbitrary value you like, however I know that in reality clock dividers will be used to approximate this frequency. The SPI slave has a maximum SPI frequency of 3 MHz in some device states, so I need to be careful about the used frequency.

3) How to manually set Chip Select port for SPI? I might want to use multiple SPI slave devices.
I assume that when using the ' SPI_transfer(SPI_Handle handle, SPI_Transaction *transaction) ' function, the driver automatically sets Chip select port to HIGH or LOW.
I expect that I can use it manually when changing the ".csPin" of SPICC32XXDMA_HWAttrsV1 to "SPICC32XXDMA_PIN_NO_CONFIG", and then use GPIO_write functions to set the right CS ports?

From the available documentation, I can't find proper answers to these questions. Can you tell me if there is any other place where I can find more explanation about the abstraction, or, if not available, explain to me how it works?

  • Hi MJ,

    1) When you're using the CC3220 with TI drivers, there is the CC3220SF_LAUNCHXL.c file where all of the peripherals are configured. For each peripheral there is a _config struct, which has the intPriority as one of its members. You would set the desired priority level of the interrupt by setting that intPriority to the ucPriority value you would pass into the old driverlib. That causes the RTOS to set the priority level of that peripheral's interrupt at _open() time just like how IntPrioritySet() would.

    2) In SPI Master mode, the real frequency of the SPI clock is whatever you specify in spiParams.bitRate. Keep in mind though that the SPI clock is generated by dividing the master 40MHz fast clock. The divider can be any integer up to 32768. This means 3MHz cannot be generated, since 40MHz cannot be evenly divided into 3MHz. You can probably use a lower frequency such as 2MHz for your slave devices which can only accept a max of 3MHz.

    3) If you want to use multiple slave devices and have a different CS line for each, your method of changing the .csPin to SPICC32XXDMA_PIN_NO_CONFIG works. You'll want to define GPIO CS pins for each slave in the GPIO section, and then do GPIO_write() calls around your SPI_transfer() calls to toggle the CS to the correct device.

    Let me know if you have any further questions, or need more help with the drivers.

    Regards,
    Michael
  • Dear Michael,

    Thank you for your reply. I have some follow-up questions:

    1) I'm not really familiar with the old driverlib, but the only documentation I found was here for the CC26xx.
    The standard priority is .intPriority = (~0), while the old driverlib used INT_PRI_LEVEL0 probably.
    Can I use the same macro's, or should I just replace the zero with the desired interrupt level (so INT_PRI_LEVEL1 becomes (~1) ) ?
    It seems to me (from the GPIO documentation sample I posted earlier) that .intPriority = (~0) is the lowest priority, while for the old driverlib INT_PRI_LEVEL0 is the highest priority
    It would be nice if you could link me to the documentation of this for the CC32xx devices.

    2) Where can I find that the maximum integer divider is 32768 and that the master CLK is 40 MHz? Especially for the master CLK, I would expect it to be equal to the processor speed (= 80 MHz) instead of 40 MHz (which is the crystal right?). If I assume 40 MHz as master CLK, I could set the SPI_CLK to 2.5 MHz, such that the divider would be 16 right? In that case I would have no rounding error.
    Again: it would be nice if these things would be in the documentation. If someone would specify 3 MHz for the bit-rate, it could actually be 3.077 MHz (divider = 13) or 2.857 MHz (divider= 14), which can mess up the application.

    3) Thanks for the clarification!

    And something that was still unanswered:

    The current TI drivers are nice to use for beginners (kind of Arduino-like), however I feel that documentation and/or API functions are sometimes too abstract (such as in the SPI bitrate case).
    Without detailed documentation about how it is implemented, I prefer to use more hardware-abstracted API functions (such as with CMSIS library as I mentioned in the earlier post), because it would give me more certainty that my code will work when I start testing.
    Does TI have something in the development pipeline that would improve these shortcomings?

  • Hi,

    1) Your idea of using the same macros as the CC26xx is correct. Thus, .intPriority 1 = 1<<5 = 0x20, .intPriority 2 = 2<<5 = 0x40, etc.. The .intPriority is supposed to be set according to the host platform's expected values for interrupt priority. For the CC3220, the way that the interrupt priority registers work is that the priority must be set in bit 7:5 of the specific PRI register for that interrupt. See page 90 of the TRM for an illustration of what I mean.

    2) The SPI clock is generated from the 40MHz crystal, and that is only really revealed through the implementation of the PRCMPeripheralClockGet() function of the driverlib. The maximum integer divider is 32768, but that's only using the power-of-two granularity mode. In single clock cycle granularity mode, the max is 4096. Thus, the divider can be set to 1-4096, 8192, 16384, and 32768. The TRM has some explanation of how this works, and the implementation of SPIConfigSetExpClk() shows how the SPI config registers are set for a given SPI clock. You are correct in your understanding in that you can only get 3.077MHz or 2.857MHz but not 3MHz exact using the CC3220's SPI interface.

    In terms of less-abstracted code, there are the lower-level driverlib APIs that you can use, which are much more transparent in terms of the registers and hardware features exercised. It's not presented to developers as the default to use since the higher-level TI drivers are more friendly to most users. In terms of what's in the development pipeline, there are some improvements that are coming that will hopefully make the configuration of the hardware peripherals more intuitive.

    Regards,
    Michael
  • Thanks for your answers again. I did some more research, and some things are still not completely clear.

    1) From the TRM and other NVIC tutorials, I get how the bit register should be now. However, it is still unclear to me what the right TI Driver syntax should be.
    So if I understand correctly the variable .intPriority that I put in,will be bit shifted by 5 to give 11100000b register value?
    How does this work with the current bitwise NOT operator: .intPriority = (~0) ? This would result in -1 (dec), and therefore be 11111....11111b two's complement?
    So is the correct syntax .intPriority = (~1) or .intPriority = 1?

    2) Thanks for the explanation. This would not have been easy to find out myself via the TRM and driverlib functions. I am still not so sure what the SPI clock would be if I won't set it to an realistic SPI speed.
    To be safe, I set the speed to 2.5 MHz (40/16 = 2.5 MHz). However, the other SPI speed was set to 18 MHz.  The options are 40MHz/ 2 = 20MHz or 40 MHz/3 = 13.333 MHz, but what would the TI driver do? Does it simply do a integer division and ignore everything behind all decimal places (so 40 MHz/18 MHz= 2.22 step = 2? )

    The driverlibs seem to be a better fit for what I am looking for, however I thought they were not going to be supported for the long-term and also that it wouldn't be possible to port your code easily later on to other devices. Could you clarify on that?

    - MJ

  • Hi,

    1) If you want an interrupt to be set to the default priority, then (~1) should be used. The -1 value signals to the RTOS that the default lowest priority should be used.

    2) The TI driver calls the driverlib SPIConfigSetExpClk() to get the SPI clock speed, and that driverlib function simply does an integer division to get the divisor from 40MHz/(target SPI clock), so 40MHz/18MHz --> clock divider of 2 being set and SPI clock of 20MHz generated.

    As for your concerns about driverlib, the driverlib on the CC3220 will be supported in the long term. It would be hard for us to remove support for it given that most of the driverlib is actually included on the ROM of the CC3220. Thus going forward to new firmware/software releases you will be able to continue using driverlib code that you write on the current CC3220 software platforms/SDK.
    Going forward to new parts, it is expected that there are differences between the driverlib of one device and that of another device seeing how the register mappings and the peripherals themselves can change. Going from the driverlib of the CC3220 to the driverlib of another TI part can be a bit of effort, especially if the peripherals are completely different. That is tradeoff between the higher-level hardware-abstracted TI drivers and the bare-metal device-specific driverlib.

    If you are willing to spend the time to completely understand the workings of the CC3220 hardware, then feel free to use driverlib instead of TI drivers. We do have some customers who feel that the ability to finely control all aspects of the CC3220 through driverlib outweighs the convenience of TI drivers, so while it's not something we encourage, it's also not something we won't support.

    Regards,
    Michael