11 Replies Latest reply on Nov 7, 2019 8:06 AM by BragadeeshV_41

    SPI Interrupt

    SaGh_4441651

      I have a SCB component that I have configured as SPI master. I need to enable/disable 2 types of interrupts. 1st is to generate an interrupt when TX fifo is empty and 2nd is to generate an interrupt when the SPI is font transmitting.

       

      My questions are -

       

      1) Do I need to enable Internal Interrupts in the PSOC Creator when configuring the SCB component for SPI? What happens if I dont enable Internal Interrupt

      2) Can I enable and disable these interrupt sources individually?

      3) I do not need any additional code in the predefined ISR - so I can just enable these 2 interrupts in the PSOC creator and use the ISR's as it is?

        • 1. Re: SPI Interrupt
          LePo_1062026

          SaGh,

           

          Using external interrupts:

          1) You can see "Interrupt On Tx FIFO Empty" for one of your requested interrupts and "Interrupt On SPI Done" or "Interrupt On SPI Idle" for the other.

          2) Each of the above HW Tx interrupts can be Enabled (or Disabled) with the SW API SPIM_SetTxInterruptMode(uint8 intSrc).  Where intSrc are bit settings for each HW Tx interrupt that will be passed on to the tx_interrupt pin of the component.  If you what to disable a HW Tx interrupt type, make sure that bit is cleared in intSrc before issuing the SPIM_SetTxInterruptMode(uint8 intSrc) API call.  Setting intSrc = 0 diables ALL HW Tx interrupts.

          Also if you use the external HW Tx interrupt sources, you need to install an external ISR.  With this ISR, you need to configure it and you can enable or disable it separately from the SPI_M component calls.

          3)  With external interrupts, you need to supply the ISR code.

           

          Using the internal interrupts:

          1) The "Enable Tx Internal Interrupt" allows the user to create their own code to process the application intent.  See 3) below.

          It was intended to handle Tx data buffers larger than the 4 in the FIFO.  When you change "Tx Buffer Size" to a value larger than 4, the "Enable Tx Internal Interrupt" is enabled.

          2) To enable/disable the internal Tx interrupt, there are SPIM_EnableTxInt(void) and SPIM_DisableTxInt(void).

          3) The Tx internal interrupt has code to handle Tx data transfer when the buffer is larger than the FIFO.  You can chose either entry or exit callbacks to create your own code to handle your application-intent interrupt conditions.

           

          I've implemented internal types on some projects and external on others.  If you use the internal interrupt, set the other desired Tx interrupt types you want to process otherwise you may not interrupt on anything but "Interrupt On Tx FIFO Buffer Not Full".

           

          Len

          • 2. Re: SPI Interrupt
            SaGh_4441651

            Len,

             

            Thank you for your response. I understand that using Internal Interrupts would be best in my case, since I dont want to write the ISR code.

             

            So what I tried to do is -

             

            1) In the PSOC Creator, I enabled the Internal Interrupt and selected Interrupt on SPI Done and Interrupt On TX FIFO Empty.

            2) I defined SPI_1_SCB_IRQ_INTERRUPT_INTERRUPT_CALLBACK and SPI_1_SCB_IRQ_Interrupt_InterruptCallback() in cyapicallbacks.h

            3) In the SPI_1_SCB_IRQ_Interrupt_InterruptCallback() I do something lie this -

             

            void SPI_1_SCB_IRQ_Interrupt_InterruptCallback(void)

            {

              if( 0u != (SPI_1_GetTxInterruptSource() & SPI_1_INTR_TX_EMPTY ))

              {

                 //api function call here

                 SPI_1_ClearTxInterruptSource( SPI_1_INTR_TX_EMPTY );  //Clear the interrupt

              }

              if( 0u != (SPI_1_GetMasterInterruptSource() & SPI_1_INTR_MASTER_SPI_DONE ))

              {

                 //api function call here

                 SPI_1_ClearMasterInterruptSource( SPI_1_INTR_MASTER_SPI_DONE );  //Clear the interrupt

              }

            }

             

            Is this the right way of doing it or am I missing something?


            How do I enable/disable interrupts individually. Like I want to just disable Interrupt on SPI Done? Also, I dont have SPIM_EnableTxInt(void) or SPIM_EnableRxInt(void) functions, since I am not using the SPI Master block, but instead configuring hte SCB bloack as SPI master. Does it make a difference?

             

            Also, when you said this in your response - "If you use the internal interrupt, set the other desired Tx interrupt types you want to process otherwise you may not interrupt on anything but "Interrupt On Tx FIFO Buffer Not Full" - What do I need to do here? What do you mean when you say set the other desired TX interrupt types? I see in my code right now that a SPI interrupt is constantly occurring (The function is going into this function CY_ISR(SPI_1_SPI_UART_ISR)), but how do I figure out what is the cause of that interrupt?

             

            UPDATE:

             

            I used the function SPI_1_SPI_UART_ISR_EntryCallback() to get the source of interrupt. And looks like the interrupt is caused by SPI_1_INTR_TX_EMPTY. Why is this interrupt occurring? How do I stop it from occurring? I also read that " This Interrupt source is not cleared when transmitter FIFO is empty.", so how do I clear this interrupt?

            • 3. Re: SPI Interrupt
              LePo_1062026

              SaGh,

               

              I'm not sure I can address all your questions without having your current state of your project.  If you can send me the project, I'll take a look at it.

               

              Either way, you can alter the sources that cause interrupts by making the API call for Tx ints:

              void SPIM_SetTxInterruptMode(uint8 intSrc);

              or API call for Rx ints:

              void SPIM_SetRxInterruptMode(uint8 intSrc);

               

              This will allow you to enable or disable interrupt sources in your application at runtime.

               

              Len

              • 4. Re: SPI Interrupt
                SaGh_4441651

                Len,

                 

                I am unable to share my project here. Could you answer a few basic but confusing questions for me?

                 

                1) Can I enable or disable particular interrupts in the SBI mode? Can I enable/disable all TX interrupts for the SPI master? If yes, how do I do that?

                 

                2) What is the difference between SPI_1_GetTxInterruptSource() and SPI_1_GetMasterInterruptSource()? Why do these 2 functions refer to different interrupt flags?

                • 5. Re: SPI Interrupt
                  SaGh_4441651

                  When I enable the TX FIFO empty flag in the PSOC Creator, I am getting constantly interrupted by this condition. What am I missing here?

                  • 6. Re: SPI Interrupt
                    LePo_1062026

                    SaGh,

                     

                    I'm not sure what SBI mode is but I'll try to answer your questions.

                    1) The configuration page for the SPI Master component is a compile-time configuration.  You can alter these setting in your code at run-time.

                    You can enable and disable interrupts at run-time.  You can do this inside an interrupt or outside an interrupt using SPIM_SetTxInterruptMode(uint8 intSrc);

                     

                    2) In the "Serial Peripheral Interface (SPI) Master V2.50"  There is no mention of SPI_1_GetTxInterruptSource() and SPI_1_GetMasterInterruptSource() as API calls.  What component are you using?

                     

                    I think I see the issue of my not understanding certain aspects of your question.  It appears you are using the SPI (SCB) PDL component.  I've never used it so I'm a bit at a loss to answer you properly.

                     

                    What PSoC are you using for this project?

                     

                    Len

                    • 7. Re: SPI Interrupt
                      BragadeeshV_41

                      Hi SaGh_4441651,

                       

                      If you want to dynamically enable and disable an interrupt you can use the following APIs.

                      1.  Use the API SPIM_SetTxInterruptMode to write to the SCBx_INTR_TX_MASK register that will say if the corresponding bit will be able to generate an interrupt or not.

                      If you don't want a condition to generate an interrupt, you can clear the corresponding bit in the interrupt mask register.

                       

                      2. When I enable the TX FIFO empty flag in the PSOC Creator, I am getting constantly interrupted by this condition. What am I missing here?

                      --> This is expected. TX FIFO empty flag indicates that there is no data in the TX FIFO and will keep triggering an interrupt until there is some data. If you don't want to generate this interrupt, use point#1 of this post.

                       

                      3. What is the difference between SPI_1_GetTxInterruptSource() and SPI_1_GetMasterInterruptSource()? Why do these 2 functions refer to different interrupt flags?

                      --> SPI_1_GetTxInterruptSource() : This API will return SCBx_INTR_TX register that will return the current status of the interrupt request register. For your case, TX_EMPTY interrupt is available in this register.

                      -->SPI_1_GetMasterInterruptSource(): This API will return SCBx_INTR_M register which is Master interrupt request register. For your case SPI_DONE interrupt is available in this register.

                       

                      4. Internal ISR is specifically used in case you want to a software buffer management. For your case the ideal way of doing this is to register a interrupt callback function using the API SCB_SetCustomInterruptHandler(). This function is called whenever an interrupt that is set in the Interrupt mask register is called. For example:

                       

                      SCB_Start();

                      SCB_SetCustomInterruptHandler(My_ISR);

                      SCB_SetTxInterruptMode(SCB_INTR_TX_EMPTY);

                      SCB_SetMasterInterruptMode(SCB_INTR_MASTER_SPI_DONE);

                       

                      void My_ISr()

                      {

                           // To detect SPI_DONE

                           if((SCB_GetMasterInterruptSourceMasked() & SCB_INTR_MASTER_SPI_DONE) !=0)

                           {

                                //SPI done interrupt occurred

                                SCB_ClearMasterInterruptSource(SCB_INTR_MASTER_SPI_DONE);

                           }

                           if((SCB_GetTxInterruptSourceMasked() & SCB_INTR_TX_EMPTY) != 0)

                           {

                                //TX FIFO is empty . Load something to send

                                SCB_ClearTxInterruptSource(SCB_INTR_TX_EMPTY);

                       

                           }

                      }

                       

                      I think you are using unconfigured SCB in your case. The above APIs are common SCB APIs and doesn't require a SPI master configuration.

                       

                      Regards,

                      Bragadeesh

                       

                       

                      • 8. Re: SPI Interrupt
                        SaGh_4441651

                        Hey Bragadeesh,

                         

                        Thank you for your response. I have one question - what is the difference between clearing an interrupt and disabling an interrupt? How do I do each of these - Clear an interrupt that has occurred and disable the interrupt at run time and enable when I want?

                        • 9. Re: SPI Interrupt
                          LePo_1062026

                          SaGh,

                           

                          Maybe I can help here.

                           

                          There is an interrupt pending flag in a register associated with the component's interrupt.  This is a flag that gets set when the interrupt conditions are satisfied.  This flag is connected to the HW to generate the desired interrupt if this specific interrupt is enabled. This flag can be set even if the interrupt is disabled.

                           

                          When you enable an interrupt in SW, if the flag is already set, you immediately go to the interrupt ISR to service it.  Depending on your application, you may want to Clear the interrupt pending flag first before enabling the interrupt.  This can prevent a potential false trigger of the ISR.

                           

                          The Clear interrupt clears this pending flag in a way needed for that specific component.

                           

                          Enabling and Disabling the interrupt controls if the interrupt pending flag causes the CPU to perform the ISR.  You will NOT jump to the ISR if the interrupt is disabled.

                           

                          I hope this helped.

                           

                          Len

                          • 10. Re: SPI Interrupt
                            SaGh_4441651

                            LePo,

                             

                            Thank you for your response. What are the specific api calls to clear an interrupt vs disable an interrupt. I am unable to distinguish between these api calls.

                            • 11. Re: SPI Interrupt
                              BragadeeshV_41

                              Hi SaGh_4441651,

                               

                              SCB_ClearMasterInterruptSource will clear the interrupt.

                              We do not have apis to disable a particular interrupt source rather you can disable all the interrupts associated with the block. Eg SCB_DisableInt().

                              To disable a particular interrupt, you can clear the corresponding bit in the interrupt mask register by writing appropriate mask to SCB_SetTxInterruptMode or by directly clearing the bit by direct register write to SCBx_INTR_TX_MASK  register. Use CY_SET_REG32(address, value).

                               

                              We highly recommend you to refer to the device register TRM for more details and clear explanation on each of the registers.

                              https://www.cypress.com/documentation/technical-reference-manuals/psocr-4100s-plus-psoc-4-registers-technical-reference

                               

                              Regards,

                              Bragadeesh