Ok, so this was quite interesting. I made a quick ('n dirty) test program
using an STM32F405 MCU connected to an external 16-bit SRAM IC. The MCU is
running at 168 MHz (6 ns CPU cycle). The SRAM has 55 ns access time.
The FSMC (memory controller) is configured like this:
1 BUSTURN delay after read
6 DATAST data-phase duration
0 ADDHLD address-hold phase duration
3 ADDSET address setup phase duration
That is something like 10 CPU cycles per FSMC transaction (60 ns to match
the 55 ns access time), plus any overhead. The exact timing would need to be
determined for the requirements of your specific peripherals, of course.
I tested single and burst read, single and burst write, read followed by
write, and GPIO read + SRAM read + SRAM write + GPIO write (this last one to
resemble your DMA code). For example:
do
{
(void)*gpio_read_ptr;
(void)*sram_ptr;
*sram_ptr = some_value;
*gpio_set_ptr = gpio_set_val;
-- i;
} while (i != 0);
The results show that an external SRAM read or write takes 12 CPU cycles, or
72 ns, in all the cases basically. I see no penalty for changing direction
on the bus. In fact, the overhead of adding the GPIO read/write is exactly
zero cycles! I believe this is because the FSMC has a CPU cycle or two of
delay between transactions, which can be overlapped with the GPIO accesses.
Put another way, I am getting 14 MByte/second bandwidth copying external ram
to external ram on the STM32F405, with this particular SRAM IC.
So basically, the ST's Cortex M4 in my tests seem to be able to communicate
on the external bus at the full configured speed. Just note that the M4
usually takes 2 CPU cycles (12 ns) to do a store or a load (plus any wait
states), which sometimes can go to a single cycle if load and stores are
scheduled optimally in the code.
But I noticed that the at91Sam9XE you are using seems to be a full ARM
application processor with MMU and such? The STM32F405 is a Cortex M4
microcontroller, it does not have MMU or caches or other such things...
These ARM chips are designed specifically with a mind to get fast and
predictable timing for things like peripheral access and interupts and such,
which might explain the difference...
If you are interested, you can find my test code on my github (note the
non-default branch 'eevblog', I hacked an old test program I had):
https://github.com/knielsen/stm32f4_sram_memtest/tree/eevblogHope this helps,
- Kristian.