Flat Memory DDR3 Access on the ARM Cortex A8

I'm trying to kick out a simple (ha ha!) assembly language project in which I perform some simple DRAM tests on board based on the TI AM3352 using a 512 MB DRAM (256M x 16).

Ideally I'd like to just treat DRAM as a flat address space from

0x80000000 to 0x82000000.
  1. Can I just "turn off" the MMU?
  2. Should I keep data cache turned off as well?
  3. Are there any access sequence restrictions? E.g., can I just read/write each 16-bit value sequentially?
  4. Any other gotchas?

I believe I've got the EMIF/DDR3 controller initialized properly (I used the u-boot code for the beaglebone black), but I can't get the test code proper running. I'm getting DABORT exceptions on the _second_ time through the write loop in the following code.

Any help would be appreciated.

--Randy

#include "asm-defs/asm-defs.h" #include "asm-defs/prcm.h" #include "asm-defs/emif.h" #include "asm-defs/control.h" #include "asm-defs/cm.h"

.cpu cortex-a8 .text

//---------------------------------------- // Randy Yates // // entry: // ro = base of DRAM test. must be even since DRAM is 16-bit words // r2 = count of 16-bit words to test // r3 = value to write (lower 16-bits)

// routine usage // r1 = current offset into r0 (base of dram test) // r4 = value read back

// return: // r7 = result (boolean: test successful) // 0x01 = test passed // 0x00 = test failed //----------------------------------------

.fun ddr3_value_test push {lr}

mov r1, 0

// first write all values ddr3_value_test_write_loop: str.n r3, [r0, r1] //

Reply to
Randy Yates
Loading thread data ...

This is just a subroutine. Which is the environment it is run in (Linux)?

If there is an operating system, you have to negotiate the MMU setup with it.

It depends on the tolerance of the assembler used if the instruction 'mov r1,0' is accepted and interpreted as you seem to like. Please try 'mov r1,#0' instead.

There is actually no need to store the link register. If the system uses the EABI conventions, you should push and pop an even number of registers to maintain the 8 byte alignment of the stack pointer.

The standard ARM convention is to transfer first 4 arguments in registers r0 - r3, and the return value in r0. For the standard conventions, a subroutine is allowed to clobber r0 to r3 as it likes.

--

-TV
Reply to
Tauno Voipio

Hi Tauno,

Thank you for your resp> >> I'm trying to kick out a simple (ha ha!) assembly language project in

No, bare metal assembly. No operating system, no C, no C library. I perform my own startup and minimal system initialization in assembly, then do the DDR3/EMIF initialization, then the test code above.

Agreed that is sloppy syntax, but from the available mov instructions, I don't see how else it could be interpreted. I will fix the syntax.

In general I hate the following aspects of the gnu assembler:

  1. It permits sloppy syntax (as above). I want the assembler to complain for every wrong syntax. It is the assembly language programmer's job to input correct syntax and not the assembler's job to relax it's syntax checking.
  2. It auto-exports certain symbols. I want to explicitly specify which symbols are exported.
  3. It permits identical labels, e.g.,

l0: subs r1, #1 bne l0b subs r2, #1 bne l0f ... l0: ldr r2, SOME_VAR ....

  1. Special syntax like "=" destroys the one-to-one mapping of assembly instructions to machine language instructions.

Horrid.

As said, this is all my own assembly language code and I am perfectly free to implement things as I wish.

Ditto above.

--
Randy Yates, DSP/Embedded Firmware Developer 
Digital Signal Labs 
http://www.digitalsignallabs.com
Reply to
Randy Yates

Hello Randy,

Thank you. M> Hi Tauno,

The sloppy acceptance has come with the ARM unified syntax, as the Thumb and ARM syntaxes were combined.

Which one? Are you sure that they do not come from the included headers (which I do not have)?

These are called explicitly local labels, and the intention is to make simple throwaway labels for short loops etc. As far as I remember, they should be numeric.

AFAIK, they have been inherited from the PDP-11 assembler.

This is a service of the assembler to keep a supply of constants. It is called literal addressing, and it has been in various assemblers at least since the IBM S/360 era.

I beg to differ.

Here is GNU assembler output before declaring unified syntax:

dramtest.s: Assembler messages: dramtest.s:22: Error: unknown pseudo-op: `.fun' dramtest.s:25: Error: immediate expression requires a # prefix -- `mov r1,0' dramtest.s:29: Error: unexpected character `n' in type specifier dramtest.s:29: Error: bad instruction `str.n r3,[r0,r1]' dramtest.s:35: Error: immediate expression requires a # prefix -- `mov r1,0' dramtest.s:37: Error: unexpected character `n' in type specifier dramtest.s:37: Error: bad instruction `ldr.n r4,[r0,r1]' dramtest.s:46: Error: immediate expression requires a # prefix -- `mov r7,0x01' dramtest.s:51: Error: immediate expression requires a # prefix -- `mov r7,0' make: *** [all] Error 1

----

Here is your function without the #includes and twisted to be accepted by the assembler. I also changed the syntax a bit to avoid the pre-processor. I had to guess some, hope it is correct:

.syntax unified .thumb .cpu cortex-a8 .text

@---------------------------------------- @ Randy Yates @ @ entry: @ r0 = base of DRAM test. must be even since DRAM is 16-bit words @ r2 = count of 16-bit words to test @ r3 = value to write (lower 16-bits)

@ routine usage @ r1 = current offset into r0 (base of dram test) @ r4 = value read back

@ return: @ r7 = result (boolean: test successful) @ 0x01 = test passed @ 0x00 = test failed @----------------------------------------

@.fun ddr3_value_test

.globl ddr3_value_test ddr3_value_test: push {lr}

mov r1, 0

@ first write all values ddr3_value_test_write_loop: str.n r3, [r0, r1] @

Reply to
Tauno Voipio

Yes. You need system control coprocessor control register 1:

formatting link

For instance I think this will turn off the MMU: MRC p15, 0, r0, c1, c0, 0 BIC r0, #1 MCR p15, 0, r0, c1, c0, 0

Probably wise if you want to test DRAM. Clearing bit 2 should disable the D-cache.

That should work. However the memory controller may coalesce accesses - it will depend on how it is configured.

Initialising the DDR3 controller is probably the biggest gotcha, so if you've managed that it should be straightforward (probably).

I don't know what's going on in the code you supplied, since it depends on the MMU state and physical memory map.

Don't forget to turn off IRQs and FIQs, since whatever they're expecting is probably no longer there if you turned off the MMU.

Theo

Reply to
Theo Markettos

That was precisely the problem, Tauno! Thanks very much for your feedback! It is working now!

--
Randy Yates, DSP/Embedded Firmware Developer 
Digital Signal Labs 
http://www.digitalsignallabs.com
Reply to
Randy Yates

If you read closely enough, I think you will find that you actually cannot use the data cache on the A8 unless the MMU is enabled.

Simon.

--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP 
Microsoft: Bringing you 1980s technology to a 21st century world
Reply to
Simon Clubley

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.