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.

HalCoGen generated code SPI notification API

Expert 1550 points
Other Parts Discussed in Thread: HALCOGEN

I'm not quite at full grip with the design / API of the HAL  lower level code which HalCoGen automatically generates. The idea is,  or I had, is to use it as is with no / very little modification, yet I find it's not clear cut how to use the API best.

Example I have, is the notification calls from the SPI driver from HalCoGen layer.  Consider say "spiEndNotification(spiBASE_t* spi)" call .

The idea seems, great, I can provide my implementation of this handler, to get callback when either TX has run out or my RX buffer is full. Seems, great, but

One thing it just takes one parameter, and my handler cannot immediately check say what was reason /source of the callback, my code would have to access & re-examine the spi's registers to see what was the reason.  But this means accessing same registers that the lower code/HalCoGen code has already read - like flags for example - so seems I'm forced to do second (or more) same register access to read out again same info. And, that may not even be valid anymore : eg.  interrupt and interrupt flags regs may have already been modified by that code

And if your code wanted to check why spiEndNotification() was called, you seems left to guess about if that was  spi  HighLevel or LowLevel interrupt, you do not know which - INTVECT0 or INTVECT1 - you need to look into to see if that was full Rx or empty Tx.

Also once you have your spiEndNotification() handler code included, you cannot disable that specific call - it's not optional anymore. And, as sending will always enable the TX interrupt, your code will always get now this call, even when you don't care (because you already set all buffers with e.g. spiSendData).

I would think you could avoid then using this spiEndNotification() API part by using the other notification call  which should pass all flags : void spiNotification(spiBASE_t *spi, uint32 flags)

, but yet it's not clear how without changing the HalCoGen Code. The generated interrupt handlers code - mibspi1HighLevelInterrupt, mibspi1LowLevelInterrupt - only invoke this more 'generic' spiNotification callback for default switch case, i.e.  _excluding_ cases when RX full or TX empty.  So .. it seems you not meant to use these for the basic/normal case when you just want to send/receive data !

..And sendNotification does not either take the vector source as param either, so while not important, perhaps, You cannot check in your own handler, which interrupt source was this from..  (but... the HalCoGen code does read it, could have just passed it).

Further peculiar thing I see in the generated interrupt handler for example, is this (unsafe) code (snip):

    switch(vec)
    {

    case 0x24U: /* Receive Buffer Full Interrupt */
             {
                uint16 *destbuff;
                destbuff = g_spiPacket_t[0U].rxdata_ptr;

                *destbuff = (uint16)spiREG1->BUF;

So, err,  great, so if you did do a spiSendAndReceive(..) rather then just spiSendData(..) which doesnt' set RX and and you did not specifically disabled RX, you basically crash the system trying to write to null or invalid place.

I feel very limp mode with this API, I don't know if I understand the proper usage pattern of it , in flexible manner.  

Is there a proper example - beyond a 2 liner poll'ed spi send / receive? A more involved interrupt driven example exercising this HalCoGen API ?

  • Hello,

    And if your code wanted to check why spiEndNotification() was called, you seems left to guess about if that was  spi  HighLevel or LowLevel interrupt, you do not know which - INTVECT0 or INTVECT1 - you need to look into to see if that was full Rx or empty Tx.

    You can use the APIs to get the status of the SPI TX and RX data blocks: SpiTxStatus() and SpiRxStatus(), or you can check the status using g_spiPacket_t[x] directly. The tx_data_status = SPI_COMPLETED if it is TX interrupt, and  rx_data_status = SPI_COMPLETED if it is RX interrupt. 

    So, err,  great, so if you did do a spiSendAndReceive(..) rather then just spiSendData(..) which doesnt' set RX and and you did not specifically disabled RX, you basically crash the system trying to write to null or invalid place.

    If spiSendData(..) is used, theTX interrupt is enabled, but the RX interrupt should be disabled. 

  • hello

    You can use the APIs to get the status of the SPI TX and RX data blocks: SpiTxStatus() and SpiRxStatus(), or you can check the status using g_spiPacket_t[x] directly. The tx_data_status = SPI_COMPLETED if it is TX interrupt, and  rx_data_status = SPI_COMPLETED if it is RX interrupt. 

    Direct g_spiPacket_t[x] is a private member (static),  I would prefer only through API .   (Else, I may just access anything if I'm inside that code;  and change how I want).

    Yes, found SpiTX/RXStatus, handy. Looks like this is meant to be used for checking why endNotification was called.