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.

Question about using interrupt to receive data on tms570ls1224

Other Parts Discussed in Thread: ADS1271, HALCOGEN

Hi

Im using the 1224 and the ADS1271. The 1271 drives a pin low when the data is ready and notifies the MCU to get that data. Im my board that pin is the pin 55 (it can generate an interrupt when driven low.)

Unfortunately for me, my only experience with interrupts is from PICs so...

The idea is that when the pin is driven low, the SPI starts receiving the data from ADC. 

So here are my questions: 

1) I have this: 

_enable_IRQ();
gioInit();
gioEnableNotification(gioPORTB,2);

but how do I know that the interrupt on channel 9 arrived so I can start getting the data? 

I mean: if(interrupt_on_channel_9==1)

get_data_from_spi

2) The SPI has a 16bits buffer but the ADS has a 24 buffer. I read on another post that I could have 2 transmissions from the ADS in order to get all the data. But how could I do that? 

3) I saw the example provided by Halcogen and saw this: 

spiDAT1_t dataconfig1_t;

dataconfig1_t.CS_HOLD = FALSE;
dataconfig1_t.WDEL = TRUE;
dataconfig1_t.DFSEL = SPI_FMT_0;
dataconfig1_t.CSNR = 0xFE;


/* Enable CPU Interrupt through CPSR */
_enable_IRQ();

/* Initialize SPI Module Based on GUI configuration
* SPI1 - Master ( SIMO, SOMI, CLK, CS0 )
* SPI2 - Slave ( SIMO, SOMI, CLK, CS0 )
* */
spiInit();

/* Initiate SPI2 Transmit and Receive through Interrupt Mode */
spiSendAndGetData(spiREG2, &dataconfig1_t, 16, TX_Data_Slave, RX_Data_Slave);

I don't understand why the first lines if I'm configuring that from HALCOGEN

and the last line I need to change it but I dont get what the dataconfig1_t is...

And, as you can see the on the line below, what is the destbuff?? that means I could have there the 24 bit buffer??

void spiGetData(spiBASE_t *spi, spiDAT1_t *dataconfig_t, uint32 blocksize, uint16 * destbuff);

  • Hi,

     1)  I'm not too clear on your question how do you know if the interrupt has arrived on channel 9. When the GIO detects a low, it will generate an interrupt to the VIM module on its channel 9. Think of the VIM as a funnel that will eventually generate an IRQ to the CPU. When the CPU is interrupted it will fetch the interrupt vector for GIO provided by the VIM module. You can place a breakpoint in gioHighLevelInterrupt() in gio.c. If CPU is interrupted, the CPU wlll branch to gioHighLevelInterrupt(). I'm assuming that you have configured for GIO High Level interrupt in HalCoGen since you said you wanted the GIO interrupt at channel 9. Note that there is also the GIO Low Level interrupt mapped to channel 23. By default, the HalCoGen map the GIO interrupts to the low priority.

     Here is one example project for your reference to generate GIO interrupt. 1563.Push_Button_Low.zip

    2) For ADS1271 you will need to consult with the Precision Data Converter Forum.

    3) dataconfig1_t is just a structure that contains the control information pertaining to the SPI transfer. 

  • 1) so... I if understand correctly, I could place if(gioHighLevelInterrupt()==1), then start receiving the data?

    2) The question is not precisely about the ADS. Is more on how can I make that the SPI gets two packages of 12 bits each and then place them into a bus of 24 bits

    3) ok ok... that structure is defined from halcogen? of is defined by me?

    thanks!!

  • Hi,

     The gioHighLevelInterrupt() is a function of void. Please see below. You can find in gio.c. You can place your code to receive data from SPI in the gioNotification(). When the CPU gets an interrupt it will branch to the ISR vector at gioHighLevelInterrupt(). It is up to your application what you want to do in the ISR. In your case, you want to trigger the SPI to receive data. 

    void gioHighLevelInterrupt(void)
    {
        uint32 offset = gioREG->OFF1;
    
    /* USER CODE BEGIN (14) */
    /* USER CODE END */
    	
    	if (offset != 0U)
    	{
    		offset = offset - 1U;
    		if (offset >= 8U)
    		{
    			gioNotification(gioPORTB, offset - 8U);
    		}
    		else
    		{
    			gioNotification(gioPORTA, offset);
    		}
    	}
    /* USER CODE BEGIN (15) */
    /* USER CODE END */
    
    }

    On #2, again you need to read the ADS datasheet on how to do it. From the MCU side you can configure to for the char length of 12 bits so that you can receive 2 12-bit characters. Whether or not  the ADS can be read in two 12bits you ned to read the datasheet. 

  • 1)so I could just use:
    gioNotification(gioPORTB, offset - 8U);
    spi_get_data(.....)
    right?? And I could control the SPI by disabling the interrupts on the GIOB

    2) ok. i will check the data sheet of the ADS to see how to do that

    thanks!!!
  • Hi Charles

    I hope you are doing great. I was checking the codes generated by halcogen and some post and was wondering on something...

    If I have an interrupt from the ADS on GIOB[2] pin, I could then use the polling method, which is more complete than the other (In terms of information)

    so watching a post, I made this:

    while((spi->FLG & 0x00000100U) != 0x00000100U)

           {

           } /* Wait */

           /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */

           *destbuff = (uint16)spi->BUF;

           data1=spi->BUF;

           data2=spi->BUF;

           data3=spi->BUF;

           data4=data1<<16U|data2<<8U|data3;

           //llenar arreglo 1

           /*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */

           destbuff++;

           blocksize--;

    I did this so the buffer empty the information on the data1, then the second word on data 2 and the third on data 3....

    I havent been able to test it but was wondering if ir would work...

    Also, I was thinking on calling the "spiReceiveData" function (polling one) from the

    if (offset >= 8U)
    		{
    			gioNotification(gioPORTB, offset - 8U);
    spiReceiveData(............);
    }
    does it make any sense??
    and last question: what is the difference from polling method and interrupt method?? on this module


    thanks!!!
  • Hi Miguel,
    Thank you. I'm doing well.

    Your code will not work. I'm not sure what you are trying to do. You seem to configure SPI for 8-bit char length and try to concatenate four 8 bit together to form a 24-bit data. It does not work that way. Reading the spi->BUF 4 times will read the same data 4 times. Reading spi->BUF does not trigger a new transmission with the ADS. I think what you want to try is the spiTransmitAndReceiveData() function. Your MCU is a master who will be generating SPICLK to the ADS. It needs to initiate a transmission to the ADS and at the same time receive the conversion data back. You are also making assumption you can read from the ADS in 8-bit char length and read 4 times to read out the entire 24 bits. Have you confirmed what type of SPI interface you have? If the ADS can only be read in 24 bits then there is a problem with the MCU. The MCU can only transmit/receive at max of 16-bits in one frame. I'm not sure if there is a solution for it. Perhaps you can configure the SPI for 12-bit mode and receive two 12-bit data. The CPU can concatenate them after two 12-bit data are received. In any case, you need to use the spiTransmitAndReceiveData() for this, not simply reading spi->BUF multiple times.
  • Im trying to receive 8 bits, transfer them to a variable and receive the other 8 bits and so on and then concatenate them on data4

    I cannot use that function. The SIMO pin is not connected.

    Charles Tsai said:
    Perhaps you can configure the SPI for 12-bit mode and receive two 12-bit data. The CPU can concatenate them after two 12-bit data are received.

    how could I accomplish that???

    Charles Tsai said:
    In any case, you need to use the spiTransmitAndReceiveData() for this, not simply reading spi->BUF multiple times.

    ok ok. but I need to use spiGetData or spiReceiveData

    best regards

  • I don't think the spiGetData or spiReceiveData will work. These are used when the MCU is a slave device. However, the MCU will the master generating clock. So you need to look at spiTransmitAndReceiveData. You can leave the SIMO unconnected if the ADS does not need it. But you need to generate the SPICLK to your slave device whether it is ADS or anything else.

    Configure for 2 12-bit is just an idea. I don't know if it will work. You configure the char length to 12 bit and makes two frames of transfer. The MCU will generate 12 SPICLK for the first frame followed by another 12 SPICLK for the second frame. Since these are two different frames so there will be idle period between the frames. From the slave device point of view, it will see 24 SPICLK but note that the 24 SPICLK are separated into two different frames with each having 12 SPICLK. You need to check the ADS to see if this will meet its timing requirement. If timing cannot be met then this solution will not work. Can your application use 16-bit or less ADC?
  • Mmmmm okok

    Ok. If i get ir right,  could i just use like

    (pin interrupt)

    Spigetdata(...)

    Spigetdata2(....)??? Something like that?

  • The spiGetData is used if the MCU is a slave. For example, if the MCU is a slave then it will wait for an external SPICLK. As a slave device it does not generate the SPICLK. Once the external master generates the clock the slave starts to receive the master data and transmit the slave data out. When the master data is received into the spi->BUF it generates an interrupt. The spiGetData is only used if you are in interrupt mode and if the MCU is a slave device. As I said, in your case the MCU is a master and it needs to generate SPICLK to the external slave device. So spiGetData will not work.
  • yeah, but then I should just repeat the spiGetAndTransmitData twice? and send the data from the buffer to an arrangement?
    like
    gio_interrupt{
    spiGetAndTransmitData(....)--->polling mode
    pass the buffer data to an arrange (data=spibuf[i])
    spiGetAndTransmitData(....)--->polling mode
    pass the buffer data to an arrange (data=spibuf[i])<<16
    }
    something like this?

    what would be the best method? because I will be inside the giob interrupt... I think polling could be a good idea...

    thanks Charles!!
  • I think you can just the spiTransmitAndReceiveData once and pass 2 for the blocksize argument to the function.
  • I already checked with the ADS forum and they told me that as long as the full trasfer occurs on less time than the conversion time, I should not have any problem. 

    So I can do 2 12bits transfers. 

    ammmm How could I pass 2 for the block size??

    spiTransmitAndReceiveData(spiREG1, &dataconfig1_t, 24, TX_Data_Master, RX_Data_Master); ?

    and havingRX_Data_Master be uint16 RX_Data_Master[24] = { 0 }; ??

    thanks!!

  • You are not calling the function correctly. You don't pass 24, you pass 2 as the blocksize.

    You need to configure the charlen to 12 like below in HalCoGen. Or you can write to the CHARLEN field in the SPIFMTx register. Please refer to the TRM for detail. 

  • ok. The Charlen is already in 12. So I just write 2 instead of 24, and the RX_Data_Master is an arrangement of 24 bits right??

    thanks!!!
  • Look at the function prototype.
    uint32 spiTransmitAndReceiveData(spiBASE_t *spi, spiDAT1_t *dataconfig_t, uint32 blocksize, uint16 * srcbuff, uint16 * destbuff)

    The destbuff is a pointer to a 16-bit unsigned integer. The first 16-bit element in the array will receive the upper 12bits from the ADS and the second 16-bit element will receive the lower 12 bits from the ADS. You will typecast the first element to 32 and left shift the first element by 12 bits and then add to the second element to form a 24-bit value.
  • thanks for the response Charles

    ammmm ok ok I have the Charlen on 12. Then the next step is to make two arrangements of 16 bits, lets say Data_Master_1 and Data_Master_2
    on the blocksize, seeing the examples from halcogen, they used 16 but you told me to use 2.
    My question here is:
    the prototype function has ONE uint16 * destbuff, so I dont understand how to put both "Data_Master_1 and Data_Master_2" inside there... Because I could save the data in both and then concatenate them. But how I tell the SPI to save the data from the fisrt 12 in one arrangement and the second 12 bit transfer on the second arrangement??

    best regards
  • The destbuf is a pointer. The pointer is pointing to the beginning of the array. The Data_Master_1 is pointed to by destbuf initally. You do desbuf++ to move the pointer to the next element which will be Data_Master_2. Check the code inside the function and I think you will become familiar with how it works.

    uint32 spiTransmitAndReceiveData(spiBASE_t *spi, spiDAT1_t *dataconfig_t, uint32 blocksize, uint16 * srcbuff, uint16 * destbuff)
    {

      // snip

       while(blocksize != 0U)
        {
    
            // snip the transmit for simplicity 
    
            while((spi->FLG & 0x00000100U) != 0x00000100U)
            {
            } /* Wait */
            /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
            *destbuff = (uint16)spi->BUF;
            /*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */
            destbuff++;
    
            blocksize--;
        }

    /* USER CODE BEGIN (15) */
    /* USER CODE END */

    return (spi->FLG & 0xFFU);
    }

  • Hi Charles

    Sorry for the late response

    So... after checking what you said, is this:

    unint32 RX_Data_Master[2]={0};

    if(pin_interrupt)

    spiTransmitAndReceiveData(spiREG1, &dataconfig1_t, 2, TX_Data_Master, RX_Data_Master);

    having a charlen of 12. 

    Just to clarify something... the charlen is the size of the package to be received right?? so if Im receiving 24 bits, then is 3 bytes right??

    I think I might get confused with the example because there they have the blocksize on 16 and the destbuff is an arrangement of 16...

    so I guess I was thinking the code was talking on bits and not bytes or packages

    Am I right??

    thanks!!

  • Think of the blocksize in terms of number of frames or in your definition the number of packages. So you need two frames with each frame the size of 12bits. After you receive 2 frames you have receive two 12-bits of data.
  • so If I wanted to receive 8 packages, I should use '16' ans then concatenate 1-2,3-4,5-6,7-8,9-10,11-12,13-14,15-16 ans having that way 8 different data right?
  • If your definition of one package is one 24-bit data then the blocksize to pass to the function is 16. You will then concatenate 1-2,3-4,5-6,7-8,9-10,11-12,13-14,15-16.
  • ammmm my definition here of one package would be 12-bit, so I can receive 2 packages to form one of 24bit, but yeah... I think I get it

    thanks Charles!!
  • I think I already have it ready. But... I tried today to see the SCLK and saw nothing...
    I was looking at the example on halcogen and got some question

    spiDAT1_t dataconfig1_t;

    dataconfig1_t.CS_HOLD = FALSE;
    dataconfig1_t.WDEL = TRUE;
    dataconfig1_t.DFSEL = SPI_FMT_0;
    dataconfig1_t.CSNR = 0xFE;

    this is the initialization from the example. The first 3 I understand them but the last one... that is the chip select... If I don't have chip select (the ADS doesnt have it) what sould I use?

    And where is the clock started? because I already checked the different functions and none have a SCLK Start or something...


    best regards
  • If you don't need chip select then the CSNR is a don't care. Which SPI do you use? There are five SPI in the device. How did you initiate the transmit? Do you have oscilloscope to probe the SPICLK?
  • ooh okok
    Im using SPI5. Im just writing the function look:
    uint16 RX_Data_Master[16] = { 0 };
    uint16 TX_Data_Master[16] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 };

    main
    spiInit()

    spiDAT1_t dataconfig1_t;
    //Check spi.h lines 116 and 56
    dataconfig1_t.CS_HOLD = FALSE;
    dataconfig1_t.WDEL = 0;
    dataconfig1_t.DFSEL = SPI_FMT_0;
    dataconfig1_t.CSNR = SPI_CS_NONE;



    spiTransmitAndReceiveData(spiREG1, &dataconfig1_t, 16, TX_Data_Master, RX_Data_Master);
  • If you are using SPI5 then you should pass spiREG5, not spiREG1.
  • ow.... hahahha I Already correct that and test it but still no clock...
  • I checked the variable, the spiDAT1 and this is what the debugger showed me...

    souldnt I see some numbers on it?

  • Hi Charles

    Somehow the clock started to work. But.... ammm Im not sure I can call it a clock...

    shouldnt it be a perfectly square signal?? why it looks like a sawtooth???

  • what frequency did you configure for the SPICLK?
  • ammmm its working on... 5.333MHz
  • What board do you use?

    5.3MHz should not be a problem of the I/O pin.
  • This is what I have. Each frame is 12 bits. 

  • Is one I developed. I think is because of the frequency. But its working =)
  • Hi Charles

    I was reading something on the data sheet and found this:

    does this means that when Im using the debugger (XDS100v2) Im not reaching the external interrupt?

    thanks

  • When you are in debug mode the CPU is halted during which time an external interrupt via the GIO will have no effect. Did you try to let it just free run?
  • Hi Charles

    The thing is that I used a break point on gio notification and went there everythime when usin gioa pin for a test... so this confuse me a little. Why was I entering to gio notification and to gio low level interrupt??

  • I don't understand your question. If you place a breakpoint in the gio notification and the CPU will halt and enter debug mode when it hits the breakpoint. Didn't you set the GIO for interrupt mode? You can setup GIO interrupt based on rising edge or falling edge on the GIO pin to cause an interrupt. The first time the GIO detects the specified edge on the pin it will generate an interrupt. Once the CPU enters the ISR it hits the breakpoint. During this time the CPU is halted and the device is in debug state. If you have further edges on the GIO pin then it will not cause new interrupts since the device is still on halted/debug state.
  • It was a problem on the configuration. Halcogen has a bug or something and the pin was taking the configuration of MIBSPI3_SCS[0] but I already solve it by replacing a line on pin mux and configuring ADEVNT as input and also the MIBSPI3_SCS[0] as input and everything worked