- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
What would be the issue with SPI setup because there is a big gap/delay between data while I would like to send it continuously?
The source code is simple:
void send_packet(void) {
uint8_t i;
for(i=0; i<82; i++) {
SPI_IR_WriteTxData(0xAAAA);
}
}
As on the attached picture it is sending two 16 bit data continuously and then there is a 2.6ms delay before the next group of data.
Thanks!
Solved! Go to Solution.
- Labels:
-
PSOC5 LP MCU
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
zoli,
moto is correct. Use of SPI_IR_PutArray(const uint8/uint16 buffer[], uint8 byteCount) would be much better for your needs.
uint16 data_ary[82] = {0xAAAA, 0xAAAA, ... };
void send_packet(void)
{
SPI_IR_PutArray(data_ary, sizeof(data_ary));
}
The use of SPI_IR_WriteTxData() implied you are sending on element at a time via CPU intervention which could take some time between sending more elements from your array.
Using SPI_IR_PutArray() tries to find the most efficient (time and/or CPU) method of sending the elements.
In your configuration, you allocated 82 16-bit elements for your Tx buffer. Since the component only has a 4-byte deep FIFO, it allocates RAM scratchpad of 82*2 bytes. The SPI_IR_PutArray() will copy the data from the array you pass to this RAM scratchpad.
It then allocates and initializes an internal interrupt to efficiently manage the RAM scratchpad buffer.
Additionally it enables the "Tx FIFO Not Full" interrupt to cause the Tx interrupt.
When this interrupt occurs, it checks that the Tx FIFO status is "Not Full" and then moves data from the RAM scratchpad to the Tx FIFO until it is full.
The Tx interrupt will again trigger when the next data is transferred to the serial buffer which makes the "TX FIFO Not Full". This pattern will repeat until all the data is transferred.
As long as there is data in the FIFO and in the serial output buffer, the transmission of SPI data should be continuous without breaks and the /CS line should be low for the entire transmission.
Additional Note:
Since you allocated 82 elements as the SPI TX buffer, when you execute the SPI_IR_PutArray() API call with same number of bytes as your RAM scratchpad, it will copy all the bytes from your data array in the arguments to the RAM scratchpad and then exit the call immediately. In this case, it is a non-blocking call. All transferring will occur at interrupt-level.
If you want to allow the SPI_IR_PutArray() API call as a blocking call, you could allocate only the 4-byte FIFO in the TX buffer. It will not allocate a RAM scratchpad or enable the Tx interrupt.
In this case, when executing the SPI_IR_PutArray() API call, your code will fill the FIFO and start the transmission and wait in the API call. It will poll the TX FIFO status and place data in the FIFO when it becomes "Not Full" until ALL the data is transferred
"Engineering is an Art. The Art of Compromise."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I wonder if you can try
void SPI_IR_PutArray(const uint8/uint16 buffer[], uint8 byteCount)
Or you might need to consider using DMA
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
zoli,
moto is correct. Use of SPI_IR_PutArray(const uint8/uint16 buffer[], uint8 byteCount) would be much better for your needs.
uint16 data_ary[82] = {0xAAAA, 0xAAAA, ... };
void send_packet(void)
{
SPI_IR_PutArray(data_ary, sizeof(data_ary));
}
The use of SPI_IR_WriteTxData() implied you are sending on element at a time via CPU intervention which could take some time between sending more elements from your array.
Using SPI_IR_PutArray() tries to find the most efficient (time and/or CPU) method of sending the elements.
In your configuration, you allocated 82 16-bit elements for your Tx buffer. Since the component only has a 4-byte deep FIFO, it allocates RAM scratchpad of 82*2 bytes. The SPI_IR_PutArray() will copy the data from the array you pass to this RAM scratchpad.
It then allocates and initializes an internal interrupt to efficiently manage the RAM scratchpad buffer.
Additionally it enables the "Tx FIFO Not Full" interrupt to cause the Tx interrupt.
When this interrupt occurs, it checks that the Tx FIFO status is "Not Full" and then moves data from the RAM scratchpad to the Tx FIFO until it is full.
The Tx interrupt will again trigger when the next data is transferred to the serial buffer which makes the "TX FIFO Not Full". This pattern will repeat until all the data is transferred.
As long as there is data in the FIFO and in the serial output buffer, the transmission of SPI data should be continuous without breaks and the /CS line should be low for the entire transmission.
Additional Note:
Since you allocated 82 elements as the SPI TX buffer, when you execute the SPI_IR_PutArray() API call with same number of bytes as your RAM scratchpad, it will copy all the bytes from your data array in the arguments to the RAM scratchpad and then exit the call immediately. In this case, it is a non-blocking call. All transferring will occur at interrupt-level.
If you want to allow the SPI_IR_PutArray() API call as a blocking call, you could allocate only the 4-byte FIFO in the TX buffer. It will not allocate a RAM scratchpad or enable the Tx interrupt.
In this case, when executing the SPI_IR_PutArray() API call, your code will fill the FIFO and start the transmission and wait in the API call. It will poll the TX FIFO status and place data in the FIFO when it becomes "Not Full" until ALL the data is transferred
"Engineering is an Art. The Art of Compromise."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the answers.
The reason I didn't consider SPI_IR_PutArray() is it is calling the same SPI_IR_WriteTxData() function kind a similar way as I did. So I can't see a reason why it would be any faster, but I will try it now.
void SPI_IR_PutArray(const uint16 buffer[], uint8 byteCount) {
uint8 bufIndex;
bufIndex = 0u;
while(byteCount > 0u) {
SPI_IR_WriteTxData(buffer[bufIndex]);
bufIndex++;
byteCount--;
}
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
zoli,
Interesting ...
Question: Why are you creating your own SPI_IR_PutArray() function call since this API function already exists?
I've created a VERY simple project to dump 82 16bit elements through the SPI Master.
I used a SPI Master component with 82 16-bit words.
I ran the code with your original send_packet() function listed in the first post.
Here's a scope pic of the results:
No issue. No data gaps between Tx data transmissions.
I changed your send_packet() function to the SPI_IR_PuttArray() API call that comes with the component. I get the EXACT SAME results. No issue. No gaps.
I've attached my program I used for your review.
"Engineering is an Art. The Art of Compromise."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Len,
"Question: Why are you creating your own SPI_IR_PutArray()...?"
No, I didn't created a new one. I just copied the generated code to show it is using the same function in a loop.
I really appreciate your detailed answers, and as you mentioned 82*2 bytes FIFO is a software resource so I tested with the 4 words long FIFO. And it is solved the issue.
So if I'm using only the hardware (4*2 bytes) FIFO there is no gap between data anymore.
It is also means I have to read out RX register after every data sending, and I can't get data in one packet at the end, but it is not a drawback.
void read_packet(void) {
uint8_t i;
for(i=0; i<82; i++) {
SPI_IR_WriteTxData(0xAAAA);
packet_buffer[i] = SPI_IR_ReadRxData();
}
}
I have checked your project also and the only difference is the SPI speed.
I'm using 20 MHz and you have used 1 MHz. Maybe in 1 MHz SPI the software FIFO speed limitation is not an issue.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So SPI_IR_PutArray() is even slower to send 82 times 16 bit data.
On pictures the SPI_IR_PutArray() vs my for loop.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Surprisingly you are right!
I have confirmed same result with my CY8CKIT-059.
So I'm sorry, I was wrong. m(_ _)m
BTW, by writing "slow", how fast do you need to send these 82 x 16 bits?
Or is/are the gap between the data problem for your application?
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Moto,
Thanks for your help! The solution was so simple, just use 4 words long FIFO (see above).
The fast speed is important, because I'm on to read out thermal image sensor, and there is a big amount of data coming often.