9 Replies Latest reply on Mar 4, 2015 4:19 PM by user_78878863

    Dueling ISRs in UART component

    user_385543602

       Hi,

         

      I am still at work on a project using the DMX RS485 protocol used for lighting systems.  Basically what this application does is receive the data (512 bytes) in, shift it over depending on the address requested by two capsense buttons, and send it back out starting at that address.

         

      The problem I am having is that the data streams need to be continuous, at least for all 512 bytes plus some start of stream indication.  The two ISRs are constantly firing for each byte because it takes to long either to read it all in, and then to write it all out at once and causes jerky reaction from the lights.

         

      My question is if there is a way to have the receiving ISR go until its buffer is full, then turn off, and turn on the transmit ISR.  The transmit ISR would then transmit it's 512 bytes, and turn off, turning back on the receive ISR.

         

      I may be going about this in a very convoluted way, please let me know if that is the case as well.

         

      Thank you, see attached project.

         

      Tom

        • 1. Re: Dueling ISRs in UART component
          user_78878863

          Without looking at the project: you are using the component-internal ISRs? They are doing byte-wise transfer into a buffer, right.

             

          What you could do:

             
                
          • skip the ISRs, use DMA to transfer data in and out and only do something when a buffer is ready
          •     
          • write your own ISR, which then could handle the full 512 bytes in one go (but that could mean that during sending you get a receiver buffer overrun)
          •     
          • use the ISRs, define the buffers large enough to hold e.g. 600 bytes, and then do anything outside of them (in your main loop) - wait until 512 bytes are received, copy them to the transmit buffer, wait again
          •    
             

          (I would suggest #1 first, then #3)

          • 2. Re: Dueling ISRs in UART component
            user_1377889

            With looking at the project ;-) I would suggest to increase the buffer sizes for Rx and Tx to 600. This will enable an internal interrupt for the handling and - as a consequence - disable your interrupts for Rx Byte Received and Tx On FIFO Empty which you are using right now. Do not use them in this configuration! You can get notified when the transmission of your 512 bytes is done and when there is an Rx break. Additionally you may check the number of bytes received so far. Transmission and recept is done by the UART component "in the Background" which is truly interrupt driven in both directions.

               

            When a buffer is received you may read it and move the result to the Tx-buffer using the blocking functions which usually will not block due to the large buffer size.

               

             

               

            Bob

            • 3. Re: Dueling ISRs in UART component
              user_1377889

              Ah, and looking into your code: The reason for any strange behaving of the interrupts may be caused by violating rule #! for handlers:

                 

              #1 Never (ever) use a delay within an interrupt handler, neither directly nor indirectly!

                 

               

                 

              Bob

              • 4. Re: Dueling ISRs in UART component
                user_385543602

                 Hi,

                   

                Thanks for all the tips!  I have a few questions and comments:

                   
                      
                • Is the 600 bytes special somehow?  Why would that trigger an interrupt?  How do I access this interrupt?  Do you mean the serial buffer, or the DMXbuffer software buffer?  How would it fill in the background?
                •     
                • I moved the delays to the main method, and it seems to be working a lot better.  I also had to set the DMX_OUT to priority 1.
                •     
                • The capsense is not reading very well due to the amount of interrupts going on.  How can I 'pause' to check for this?  This is probably linked to what you were talking about with the 600 byte trigger, allowing me to do other things while the buffer filled up.  When I move the capsense interrupt up, it messes with the data transfer.
                •     
                • I know nothing about DMA, and will have to read up some more about it.  Any examples of using DMA with serial out there?
                •    
                   

                Thank you for your help!

                   

                Tom

                • 5. Re: Dueling ISRs in UART component
                  user_1377889

                  You will not learn much about DMA, since PSoC4 hasn't got DMA (yet).

                     

                  When increasing the buffer of the UART you will see that the "internal" interrupt switches on. There is no need (and you should not) use this internal interrupt. It just cares that your Rx buffer gets filled and your Tx buffer gets transmitted without any action of yours. In main() you may check for progress with the APIs GetRxBufferSize() which does not return the size of the buffer, but the number of characters in the buffer. Same for GetTxBufferSize() which returns 0 (zero) when all required bytes have been sent.

                     

                  There is a function to send a break and a status bit telling a break was received.

                     

                   I took 600 bytes buffer size because it is fairly larger than your 512 bytes stream length.

                     

                   

                     

                  Bob

                  • 6. Re: Dueling ISRs in UART component
                    user_385543602

                     Hi,

                       

                    Is there a way to mass copy the RX buffer to a software buffer to tweak and then send back out?  For transmitting, can I just use a mass transmit such as PutArray?

                       

                    Thank you,
                    Tom

                    • 7. Re: Dueling ISRs in UART component
                      user_78878863

                      Sorry about the DMA reference, I did not regocnize the question was about PSoC4. (DMA will only be in the upcoming PSoC4M).

                         

                      Regarding the internal interrupt: it will be enabled as soon as the receiver or transmit buffers are larger than 8 bytes (for the SCB UART) or 4 bytes (for the UDB based UART). But be careful with the buffer sizes, the PSoC4 has not that much memory...

                         

                      If you have interrupt problem, maybe you can set the Capsense interrupt priority higher to ensure it gets handled faster.

                      • 8. Re: Dueling ISRs in UART component
                        user_1377889

                        @Tom

                           

                        No, you have to kling to the API-pattern of the component and read the buffer byte-wise. You may think about directly after the read performing the operation with the data and concurrently send the new values out when you are in a hurry.

                           

                         

                           

                        Bob

                        • 9. Re: Dueling ISRs in UART component
                          user_78878863

                          When you enable the internal interrupt, you can look at the generated source code for the UART component. The internal ISR should show you where the internal buffer is exactly, sou you could access it directly.

                             

                          Its probably a circular buffer, so it won't be a simple memcpy operation. You also will bind yourself to the implementation - if it changes, you need to change your code.