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/MSP432-RTOS: Problem with SPI Module

Part Number: MSP432-RTOS


Tool/software: TI-RTOS

Hello.

I'm trying to communicate my MSP432 with a module using the RTOS SPI module, I have been looking at the documentation about the module and using the spiloopback as a reference, but for some reason, the module does not send anything when I told it to. I have been looking at the configuration of my module and comparing it to the loopback example in order to find some parameter i may have ignored, but I didn't find anything.

My question is, aside from initializing the bus, creating the SPI_Params and SPI_transfer structs, modify them and open the bus, am I leaving something that I'm not noticing?

Thanks in advance

  • Hi C H,

    You’ve looked at the spiloopback example, have you also run it successfully?  

    Are you using the MSP432 Launchpad or a custom board?

    And have you double checked the wiring of the SPI master port to your SPI module?  Are you able to look at the signals with a logic or bus analyzer to see if there is bus activity?

    And what version of TI-RTOS are you using?

    If this is still not working, can you post or attach your code so I can look at it?

    Thanks,
    Scott

  • Hi Scott, thanks for your answer.

    I haven't tested the spiloopback example, might as well test it.

    I am working with the MSP432 Launchpad, and with RTOS version 2.16.0.08.

    I checked the wiring previously by using a non-RTOS model of my program using driverlib. In this model, I communicate perfectly with the module, but not with the RTOS program.

    I can watch the SPI signal on a scope if I use a low transfer speed (eg, 2MHz), this test works on the driverlib program, but not with the RTOS version, meaning the board doesn't send the data, instead of sending it but not capturing the response.

    Here's my .c code, in case you need it, in this test program I'm trying to read the value of a register of the module, the SPI parameters and transfer structs are declared inside a custom library I made ("SPIlibRTOS.h"), but the configuration takes place in the main function. Also the ReadReg function of the task is also located in this library. The function loads the parameters of the "ReadReg" command and the direction of the register in the TX buffer wich will be sent to the module in a 8 bit window, and calls the SPI_transfer function. The CE and CS pins are GPIO's which I have included in the pin matrix of the MSP432 file and checked they work:

    #include <stdio.h>
    #include <xdc/std.h>
    #include <xdc/runtime/System.h>
    #include <xdc/cfg/global.h>
    
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    
    /* TI-RTOS Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/sysbios/knl/Swi.h>
    #include <ti/drivers/SPI.h>
    #include <ti/sysbios/knl/Semaphore.h>
    
    /* Board Header file */
    #include "Board.h"
    
    #include "SPIlibRTOS.h"//Custom library, the SPI params and transfer structs are declared here
    
    
    void isr_pushbutton(UArg arg0){//ISR function for BUTTON1, will call the SWI, which will call the SPIReadtest task
    	Swi_post(swi0);
    	GPIO_clearInt(Board_BUTTON1);
    }
    
    
    Void SPIReadtest(UArg arg0, UArg arg1){
    		Semaphore_pend(semaph,2000); //Take the semaphore, wait a max of 2 ms as timeout
    		System_printf("Intiating test\n");
    		System_flush();
    		uint8_t result = ReadReg(REG0); //Reading the value of the register (1 byte length)
    		System_printf("The value of the register is: %ld",result);
    		System_flush();
    		Semaphore_post(semaph); //Give the semaphore.
    
    }
    
    
    
    
    /*
     *  ======== main ========
     */
    int main(void)
    {
        //Task_Params taskParams;
    
        /* Call board init functions */
        Board_initGeneral();
        Board_initGPIO();
        Board_initSPI();
    
        SPI_Params_init(&SPIparams); //SPI configuration, Master mode, blocking mode, 2MHz clock, 8 bit window per transfer
        SPIparams.transferMode = SPI_MODE_BLOCKING;
        SPIparams.transferCallbackFxn = NULL;
        SPIparams.mode = SPI_MASTER;
        SPIparams.bitRate = 2000000;
        SPIparams.dataSize = 8;
        SPIparams.frameFormat = SPI_POL0_PHA0;
    
        SPI_MODULE = SPI_open(Board_SPI0, &SPIparams);
    
        SPItransaction.count = 2; //Transaction configuration, linking of the buffers and make a 2 window transaction, this number may change depending of the function.
        SPItransaction.txBuf = (Ptr)SPITxBuf; 
        SPItransaction.rxBuf = (Ptr)SPIRxBuf;
    
        GPIO_setCallback(Board_BUTTON1, isr_pushbutton);
        GPIO_enableInt(Board_BUTTON1); //Setting Interrupt for BUTTON 1
        GPIO_write(CSPIN, 1); //Put the CS and CE pins of the SPI module on high
        GPIO_write(CEPIN, 1);
        printf("General init finished \n");
        System_flush();
        Semaphore_post(semaph); //Gives the semaphore, so the task can start after the BIOS started
        /* Start BIOS */
        BIOS_start();
        return (0);
    }
    

    Thanks

    C

  • Hi C H,

    Thanks for the additional information.  

    The comment “ISR function for BUTTON1, will call the SWI, which will call the SPIReadtest task”  If the Swi function is calling SPIReadTest() then the Semaphore_pend() and the SPI_transfer() will be called in software interrupt context, which is not allowed for either of these functions.  What I expected was that the button ISR posted the semaphore.  So after the button ISR completes, the read task would unblock, and would then do the SPI_transfer().

    Also, if SPIReadtest() is a task, it will run only once because it is not a loop.  Is that intentional?  And there is no need for the Semaphore_post() at the end of this function.  You should look at the BIOS User’s Guide and kernel examples to see typical usage of Tasks and Semaphores.

    Also, in main() there is no need to initially post a semaphore to get a task to run.  Normally tasks that are created at startup will be in the ready state and will start automatically as part of app start up.  And there is a call to "printf()", which I think you want to be "System_printf()" since you are using that elsewhere.

    And can you please attach your application .cfg file?  I’d like see the Task, Swi, and Hwi creation parameters.

    Thanks,
    Scott

  • Hello Scott.

    What you suggest about the semaphore beign posted through the ISR seems better than my version, I'll test it and see what happens.

    And yes, it was intentional to execute the task ony once, since it is a test code to see if the Launchpad and the module communicate together.

    Now that you say the SPI functions aren't meant to work on a SWI level, I think I know where my mistake is: For what I understood, I called the Task from the SWI configuration on the cfg so the chain continues (HWI -> SWI -> Task), but that's where the error is, since I'll be calling the SWI function to execute (in a SWI context), instead of going directly to the Task as I though. I'll get rid of the SWI, since I don't really need it, and just use the HWI and the task itself. I'll fix the code and add the changes to the semaphore and see if that's where my mistake was.

    Here's the cfg file anyway, in case you can find more mistakes. In this case, I'm using the GPIO callback function as a HWI, since I understand that the function executes in the context of an interruption, maybe that's something I need to change for an HWI instance.

    Thanks for the help so far.

    C

    Edit: I managed to solve the problem and communicate with the module. The error was in using the task as the function the SWI calls when activated, since the function is executed in a SWI context instead of a task context, in which the SPI functions won't work. Thank you for your help.

    Edit2: Now that I'm capable of using the SPI module, I'm having a weird problem: Sometimes the bus gives me the correct value of the register, but sometimes it shifts the result of the first byte by n bits to the left (beign n mostly 1 bit, but sometimes 2 and even 3) and nullifies the other bits of the Rx vector, I double checked the wiring and reduced the bus speed, but it keeps happening. I'm using the correct clock phase and polarization, which is proven by the correct transfers. Do you know why is this happening?

    1348.empty.cfg

  • Hi C,

    I looked at your .cfg file and was going to reply that I didn’t see any further issues, and then I saw you’d updated your last response, and that you’ve updated your app and can now communicate with the device.  This is good to hear!   

    Regarding your edit #2, I don’t know what is causing this.  I searched the forums for “SPI bit shift” and saw many hits, for various devices and for a variety of reasons, from bad grounding, peripheral-specific timing requirements not being met, CPU or peripheral errata, loss of sync and inability to reset bit counter without an additional handshake signal, etc.  If you are able to look at the SPI signals with a scope it will likely help a lot to narrow down what is going on with this bit shifting.  Have you done that yet?   

    Since this thread is closed, if you are still seeing a problem with shifting I think it would be best to open a new thread for this new question…

    Regards,
    Scott