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.

CC2650 SPI wakeup CS

Other Parts Discussed in Thread: CC2650

Hello,

i create a application and need a communication with other uC. The CC2650 is working as spi slave. And the communication working so far.

Because of energy reasons i want that the CC2650 is so much as possible in Sleep Mode. For the communication as slave i always need the "spi_transfer" function. So the callback of the Slave is always the next transfer.

Is it possible to wake up the CC2650 with the CS-Negative edge(chip select) and start the communication?

I try to set the CS as Wakeup and get the interrupt, but then the SPI-Comm dont work anymore.  Is there any tutorial how to do that?

Thank you very much!

   

  • Hi,

    You can configure an IO as a wake source from the PIN driver. The best example of a SPI slave is the NPI TL implementation in the HostTest project. You'll need to select the SPI project configuration in IAR. Refer to the npi_tl.c & npi_tl_spi.c files.

    Best wishes
  • Hi JXS,

    yeah i know that. In the simpleCentral or simplePeripheral i allready try it with Buttons. It works very well.


    But i want to start the transmission between the uC with the CS.

    Can i configure the CS as a wake source ?

    Pseudo Code:

    Board_SPI1_CSN     | PIN_GPIO_OUTPUT_DIS  | PIN_INPUT_EN  |  PIN_PULLUP

    PIN_setConfig(hKeyPins, PIN_BM_IRQ, Board_SPI1_CSN   | PIN_IRQ_NEGEDGE);

    PIN_setConfig(hKeyPins, PINCC26XX_BM_WAKEUP, Board_SPI1_CSN   | PINCC26XX_WAKEUP_NEGEDGE);

    CS_NE_EDGE_CALLBACK{

    SPI_transfer();

    }

    I try it, but if i set the CS as IRQ, the spi dont work anymore.

    Is threre any tutorial or examples how to do that?

    Best wishes,

    Roman

  • Roman,

    We are looking into adding full support for this in the SPI driver but for now we have not had time so you need to modify the driver manually.

    This is currently work in progress but you can try to include SPIDMACC26XX.c back into the project (it is exluded from build so pre-built version is linked in instead). Then, compile the project with the define SPICC26XXDMA_WAKEUP_ENABLED.

    Note that this is absolutely not guaranteed to work out of the box but can be a good starting point for you.

    Let us know if it works / doesn't work and if you see changes that are needed.

    .:svend
  • Hello svendbt,

    thank you very much for your help.

    I try the following:

    I detect the two most important functions in the driver:

    1)    Power_registerNotify(&object->spiPreObj, Power_ENTERING_STANDBY, (Fxn)spiPreNotify, (UInt32)handle, NULL );

    if the controller enter the standby state the interrupt for the negative edge for cs is set. So if a negative edge of the cs appear the controller wakeup.


    2) Power_registerNotify(&object->spiPostObj, Power_AWAKE_STANDBY, (Fxn)spiPostNotify, (UInt32)handle, NULL );

    if the controller wakeup from the standby state, here the "wakeupCallback" is called. 

    I want that if the negative edge is appear, the controller start to transmit data. If the controller only wakeup, i dont know why the controller wakeup and start then my callback where i start the transmission. it is not the answer for my problem.

    So i look in the driver for the csnCallback. There all Interrupts of the CS are appear:

    static void SPICC26XXDMA_csnCallback(PIN_Handle handle, PIN_Id pinId)
    {
        SPICC26XX_Object        *object;
        SPI_Handle              spiHandle;
        PIN_Config              csnConfig;
    
        /* Get the pointer to the SPI object */
        spiHandle = (SPI_Handle) PIN_getUserArg(handle);
        object    = spiHandle->object;
    
        /* Get current CSN config */
        csnConfig = PIN_getConfig(object->csnPin);
    
        
        /* Disable all interrupts */
       // PIN_setInterrupt(handle, object->csnPin);//Why deactivate the Interrupts, i want them
    
        /* Cancel transfer if POSEDGE interrupt */
        /* TODO: Consider doing this in a SWI */
        if ((csnConfig & PIN_IRQ_POSEDGE) == PIN_IRQ_POSEDGE) {
            /* Indicate why the transaction completed */
            object->currentTransaction->status = SPI_TRANSFER_CSN_DEASSERT;
    
            /* Cancel the current transaction */
            SPICC26XXDMA_transferCancel(spiHandle);
        }
    
        /*TEST TEST TEST*/
        if ((csnConfig & PIN_IRQ_NEGEDGE) == PIN_IRQ_NEGEDGE ) {
          /* Call user defined wake up callback */
          if (object->wakeupCallbackFxn) {
                object->wakeupCallbackFxn(spiHandle);
            }
        }   
    }

    so if the controller is wakeup, the interrupt is called to the callback. In the callback i can start my callback function, which transmits the data.

    Here the example of the wakeUpCallback:

    void myCSWakeUpCallback(SPI_Handle handle){
      counter++;
      uint8 transmitBuffer[8]      ={counter,42,42,42,42,42,42,counter};
      uint8 receiveBuffer[8];
      uint8 count  =8;
         /* we need to trigger the master to start a new SPI Comm.*/
      // Start another transfer
      spiTransaction.count=count;
      spiTransaction.txBuf=transmitBuffer;
      spiTransaction.rxBuf=receiveBuffer;
       
      /*send new Buffer to the Master. We can so receive the message from the master.*/
      SPI_transfer(handle, &spiTransaction); 
     
    }

    The problem is: the Callback calls without a stop. I deactivate the master and see that the csnCallback is called without a negative edge. I dont know why.

    maybe i understand the spi driver wrong. I search for the solution and check again everything.

    Roman

  • Hi Roman,

    it seems you are using the SPI module as a slave, is that correct? You need to set up the Board.c file for your module to assign a pin to the CSN input. The default in the board files is PIN_UNASSIGNED.

    Secondly, the callback is executed in a HW interrupt routine context. You should rather try to post a semaphore or event and handle the new transfer from your task instead.

    Regards,
    Svend
  • Hello Svend,

    Yes i use the SPI Module as slave! I allready set up the board.c and assign the last CS1 pin.

    The right way is ->SPICC26XXDMA_csnCallback->wakeUpCallback->Post Semaphore->Application Task->Start Spi transmission? right?

    I want to do that in that way:

    SPICC26XXDMA_csnCallback->wakeUpCallback->start spi Transmission->transferCallback->post semaphore->application task->workWithReceivedValues function.


    Is better to use your way?Or can i use my way?

    At the moment i try to resolve the current problem with the negative edge on the SPI. If i disconnect the other controller, then everything works fine. If the connected other controller, transmit over spi with a 1 second intervall, everything works(wakeupCallback is calling one time per one edge). Something is wrong with my connection to the other Controller.

    I write it here, if i know something new.

    Thanks

    Roman

  • Hi Roman,


    I have just found this old post from you.

    How did you finally solve the problem?

    If I understand correctly, since you use the SPI module in slave mode:

    spiPreNotify() simply sets an interrupt on CS negative edge before going into sleep mode. This interrupt will likely occur when the SPI master starts a transfer and deasserts CS.

    spiPostNotify() does a reinitialization of the SPI driver after awake from sleep mode.

    SPICC26XXDMA_csnCallback() is called when the SPI transfer has completed with a CS positive edge. This function is called only when SPICC26XXDMA_RETURN_PARTIAL_ENABLE is used.

    I have a very similar situation to yours.

    I have a cc2650 acting as SPI slave continuously waiting for SPI data from a SPI master.

    I want the SPI slave to be in sleep mode as much as possible.

    Regards,

    Pietro