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.

RTOS/TM4C1294NCPDT: SPI1: How to setup callback to operate via SWI

Part Number: TM4C1294NCPDT

Tool/software: TI-RTOS

Do you have reference material which details how to use SPI1 under SWI configuration?

I have it working but keep crashing. I tried HWI/SWI disabled but does not fix this.I also get this warning, how to fix this?

Description Resource Path Location Type
#515-D a value of type "void (*)(void)" cannot be assigned to an entity of type "SPI_CallbackFxn" TM4C_SPI_Master.c /RFDDAQ-1J/070_SPIBus line 142 C/C++ Problem

void TM4C_HWI_Timer4_Event(UArg instance)
{
    UInt Hkey;

    Hkey =  Hwi_disable();                      // to ensure atomic behaviour. Other HWI event is put to queue by TI-RTOS.
    GPIO_toggle(EK_PL5_EXP5_TIMINGPIN);
    Hwi_clearInterrupt(INT_TIMER4A_TM4C129);
    if(TimerIntStatus(TIMER4_BASE, false) != 0)
    {
        //--------------------------Increment DAC Pointer.
        DACPointer++;
        if (DACPointer>=16)
            DACPointer=0;
        //--------------------------
        TimerIntClear(TIMER4_BASE, 0x2FFF);     // Clear All Interrupt including TIMER_TIMA_TIMEOUT, etc
//        Swi_Params swiParams;
//        Swi_getAttrs(RFD_SWI_DAC12Update_handle, NULL, &swiParams); // Copy parameter from SWI module
//        swiParams.arg0 = DAC_SineTable[DACPointer];                  // Update DAC pointer
//        //swiParams.arg1 = 0;
//        Swi_setAttrs(RFD_SWI_DAC12Update_handle, NULL, &swiParams); // Save parameter back to SWI module
          Swi_post(RFD_SWI_DAC12Update_handle);                       // Post SWI (see below)
    }
    GPIO_toggle(EK_PL5_EXP5_TIMINGPIN);
    Hwi_restore(Hkey);
}
//==================================================================
//================================================================== RFD_DAC12Update_SWI_Fxn
// Purpose  : Process SPI operation to update DAC voltage level.
// Input    :
// Output   :
// Note     : The SPI cannot run by HWI so we use SWI.
//==================================================================
void RFD_DAC12Update_SWI_Fxn(UArg arg0, UArg arg1)
{
   UInt Skey;
    Skey = Swi_disable();
    GPIO_write(EK_PH0_DACTEST_CS, PINLOW);
    RFD_SPI1_DAQ12_16Bits((uINT16)(arg0 & 0x00000FFF));
    Swi_restore(Skey);
}

void RFD_DAC12Update_test_Fxn(void)
{
    GPIO_write(EK_PH0_DACTEST_CS, PINHIGH);
}

  • I mean "crashes" where SPI stop working after few minutes.
  • Hi Richard,

     We don't have any specific examples for SPI using SWI. I think you might have already tried the TI-RTOS SPI example which is using TASK , not SWI. For SWI usage you can refer to the section 3.5 Software Interrupt in the TI-RTOS Kernel user's guide for details. 

    http://www.ti.com/lit/ug/spruex3t/spruex3t.pdf

     It is not clear to me what you meant that the SPI stops working after a while.  Did the SWI still get called after you think the SPI stops working? Try to place a breakpoint in your SPI function to see if it is getting called.

     I'm not a TI-RTOS expert but I don't think it is necessary to disable the SWI if you can setup the correct priority such that your RFD_DAC12Update_SWI_Fxn will not be preempted by other SWIs. Same can be done for the HWI.

     Looking at your code, it does not seem that you are using the TI-RTOS provides drivers for SPI but rather you are using the TivaWare drivers for SPI. Is this correct? From a high level I don't see an issue with your usage of the Swi_post() within the HWI ISR. Below is an example code of using the SWI which is similar to what you have.

    //----------------------------------------
    // BIOS header files
    //----------------------------------------
    #include <xdc/std.h>  						//mandatory - have to include first, for BIOS types
    #include <ti/sysbios/BIOS.h> 				//mandatory - if you call APIs like BIOS_start()
    #include <xdc/runtime/Log.h>				//needed for any Log_info() call
    #include <xdc/cfg/global.h> 				//header file for statically defined objects/handles
    #include <xdc/runtime/System.h>
    #include <xdc/runtime/Error.h>
    #include <ti/sysbios/hal/Hwi.h>
    
    
    //------------------------------------------
    // TivaWare Header Files
    //------------------------------------------
    #include <stdint.h>
    #include <stdbool.h>
    
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/gpio.h"
    #include "inc/hw_ints.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/timer.h"
    
    
    //----------------------------------------
    // Prototypes
    //----------------------------------------
    void hardware_init(void);
    void ledToggle(void);
    void Timer_ISR(void);
    
    
    //---------------------------------------
    // Globals
    //---------------------------------------
    volatile int16_t i16ToggleCount = 0;
    
    
    //---------------------------------------------------------------------------
    // main()
    //---------------------------------------------------------------------------
    void main(void)
    {
        Hwi_Params hwiParams;
        Hwi_Handle myHwi;
        Error_Block eb;
        /* Initialize error block and hwiParams to default values */
        Error_init(&eb);
        Hwi_Params_init(&hwiParams);
        hwiParams.enableInt = FALSE;
        /* Create Hwi on vector 51 which is the TIMER3A */
        myHwi = Hwi_create(51, (Hwi_FuncPtr)Timer_ISR, &hwiParams, &eb);
        if (myHwi == NULL) {
        System_abort("Hwi create failed");
        }
        Hwi_enableInterrupt(51);
    
    
        Swi_Params swiParams;
         Swi_Handle LEDSwi;
         Error_Block eb2;
         /* Initialize error block and hwiParams to default values */
         Error_init(&eb2);
         Swi_Params_init(&swiParams);
         LEDSwi = Swi_create((Swi_FuncPtr)ledToggle, &swiParams, &eb2);
         if (LEDSwi == NULL) {
         System_abort("Swi create failed");
         }
    
    
       hardware_init();							// init hardware via Xware
    
       BIOS_start();
    
    }
    
    
    //---------------------------------------------------------------------------
    // hardware_init()
    //
    // inits GPIO pins for toggling the LED
    //---------------------------------------------------------------------------
    void hardware_init(void)
    {
    	uint32_t ui32Period;
    
    	//Set CPU Clock to 40MHz. 400MHz PLL/2 = 200 DIV 5 = 40MHz
    	SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    
    	// ADD Tiva-C GPIO setup - enables port, sets pins 1-3 (RGB) pins for output
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    	GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
    
    	// Turn on the LED
    	GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 4);
    
    	// Timer 2 setup code
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER3);			// enable Timer 3 periph clks
    	TimerConfigure(TIMER3_BASE, TIMER_CFG_PERIODIC);		// cfg Timer 3 mode - periodic
    
    	ui32Period = (SysCtlClockGet() /2);						// period = CPU clk div 2 (500ms)
    	TimerLoadSet(TIMER3_BASE, TIMER_A, ui32Period);			// set Timer 3 period
    
    	TimerIntEnable(TIMER3_BASE, TIMER_TIMA_TIMEOUT);		// enables Timer 3 to interrupt CPU
    
    	TimerEnable(TIMER3_BASE, TIMER_A);						// enable Timer 3
    
    }
    
    
    //---------------------------------------------------------------------------
    // ledToggle()
    //
    // toggles LED on Tiva-C LaunchPad
    //---------------------------------------------------------------------------
    void ledToggle(void)
    {
    	// LED values - 2=RED, 4=BLUE, 8=GREEN
    	if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2))
    	{
    		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0);
    	}
    	else
    	{
    		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 4);
    	}
    
    	i16ToggleCount += 1;									// keep track of #toggles
    
    	Log_info1("LED TOGGLED [%u] TIMES",i16ToggleCount);		// send toggle count to UIA
    
    }
    
    
    //---------------------------------------------------------------------------
    // Timer ISR - called by BIOS Hwi (see app.cfg)
    //
    // Posts Swi (or later a Semaphore) to toggle the LED
    //---------------------------------------------------------------------------
    void Timer_ISR(void)
    {
        TimerIntClear(TIMER3_BASE, TIMER_TIMA_TIMEOUT);			// must clear timer flag FROM timer
    
    	Swi_post(LEDSwi);										// post LEDSwi
    }
    

     So the problem can be either SPI specific or related to how the SPI is used in the Ti-RTOS context which will need more investigation from your side. Do you have many other HWIs/SWIs going on? What if for debugging purpose, you disable/remove these non SPI SWIs? Will it make a difference?

  • Hi Richard,
    Is this issue resolved? I will close the thread for now. If you still have question you can reopen the thread.
  • I closing this due to a sidetracked project and will review this discussion in few week time.