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)
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.
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!
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!
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.
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?
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.
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.
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.