Dueling ISRs in UART component

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
ToVa_285016
Level 5
Level 5
100 replies posted 50 replies posted 50 questions asked

 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

0 Likes
9 Replies
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

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)

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

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

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

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

0 Likes
ToVa_285016
Level 5
Level 5
100 replies posted 50 replies posted 50 questions asked

 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

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

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

0 Likes
ToVa_285016
Level 5
Level 5
100 replies posted 50 replies posted 50 questions asked

 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

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

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.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

@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

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

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.

0 Likes