Kogna RS485 and I2C

Moderators: TomKerekes, dynomotion

User avatar
TomKerekes
Posts: 2546
Joined: Mon Dec 04, 2017 1:49 am

Re: Kogna RS485 and I2C

Post by TomKerekes » Tue Mar 05, 2024 3:38 am

Hi Jim,

I think the problem is caused by L1 Data cache coherency. With this Processor cache coherency needs to be handled by software. If memory is cached and the DMA writes to the underlying memory, if the Processor reads the memory it may read the cached value rather than the value written by the DMA.

In this case we are writing 0xff to the read buffer bytes before the transfer so the read buffer is cached as 0xff. If the read buffer memory is then filled in by the DMA and the DSP reads the buffer to print it out it incorrectly prints the 0xffs from the cache.

I added a few lines of code to force the cache to do a write-back-and-invalidate just before the transfer is started. So the transmit data and 0xffs are written to memory and the cache is invalidated. The transmit data is therefore in physical memory for the DMA to send. And after the DMA changes the memory and the DSP reads it the cache will need to go and read the actual memory.

Code: Select all

    // writeback and invalidate cache so DMA reads from memory have correct data written by DSP
    // note cache lines are 64 bytes
	HWREG(SOC_CACHE_0_REGS + DSPCACHE_L1DWIBAR) = tx_buff;  // address to write back invalidate
	HWREG(SOC_CACHE_0_REGS + DSPCACHE_L1DWIWC) = nBytes >> 2;  // no of words

    // writeback and invalidate cache so DSP reads after DMA transfer come directly from memory
    // note cache lines are 64 bytes
	HWREG(SOC_CACHE_0_REGS + DSPCACHE_L1DWIBAR) = rx_buff;  // address to write back invalidate
	HWREG(SOC_CACHE_0_REGS + DSPCACHE_L1DWIWC) = nBytes >> 2;  // no of words
Cache issues can be complicated. Its not entirely clear to me why different transmit/read buffer locations didn't have similar problems. Local stack memory is in DSP Internal L2 memory but this is also cached by L1. Global Thread Memory is in external SDRAM. The gather_buffer is also in external SDRAM. The L1 Data cache works on 64 byte cache lines. So nearby memory accesses can have an effect. There was a bug defining the buffers in the gather buffer. The gather buffer is defined as doubles. So offsetting the buffers by 32 places them 256 bytes apart. So in different cache lines. Memory alignment can also make things fall into the same or different cache lines. If the code gets preempted activity in another thread might result in cache writebacks or invalidations.

I'm thinking there could still be a theoretical issue where during the DMA transfer some random code accesses nearby memory in the same cache line, causing the cache line to be read and validated. The only solution I can think of is to put 64 byte padding around the the buffer to assure nothing else is within the same cache line.

I've attached the modified file. One new header is required for the cache definitions which I've attached.

I suspect the I2C example should have a similar change.

Let us know if you find any further issues.
Attachments
hw_dspcache.h
(6.55 KiB) Downloaded 4 times
SPI_Tester.c
(13.17 KiB) Downloaded 4 times
Regards,

Tom Kerekes
Dynomotion, Inc.

jtremel
Posts: 39
Joined: Fri Jun 21, 2019 10:55 pm

Re: Kogna RS485 and I2C

Post by jtremel » Tue Mar 05, 2024 10:24 pm

Thanks Tom,

This one definitely had me stumped.

I'll rework my example (with your cache invalidation code implemented) into an endless looping "stress test" that continuously hammers the various memory locations... I'll let you now if any surprises come out.

I really appreciate your quick troubleshooting and help!

Post Reply