run code in ram

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I want to erase and program the flash and there for I want to run some code in ram, but when I call the ram the program crashes. It doesn't work from sdram and also from sram. Has anybody an idea what is going wrong? Here is the code:

DoOnStack:	
			mov		r0, lo(SpSubEnd)
			orh		r0, hi(SpSubEnd)
			mov		r1, lo(SpSub)
			orh		r1, hi(SpSub)
			mov		r2, lo(0x11000030)
			orh		r2, hi(0x11000030)
SpmoveLoop:
			ld.w	r3, --r0
			st.w	--r2, r3
			cp.w	r0, r1
			brhi	SpmoveLoop
			icall	r2
			retal	r12

			.balign	4
SpSub:		
			retal	r12
			.balign	4
SpSubEnd:
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, i think your approximation to this problem is wrong.
Simply copying the function to ram an call it _might_ work _if_ the compiler does not adress anything with absolute adresses. This is not the case sometimes.

Also be sure you copy more than the function only. At the end of the function the compiler places constants that are adressed with relative offset to PC. These constants must be copied too.

Make also sure, that the funcion you call has absolutely no references to stuff in flash. E.g. if you toggle an LED with an extra function you can get serious problems since this fuunction resides in flash.

The easiest solution is to tell the compiler that the funtion is places wiothing the .data section. This will automatically place the funtion into the heap that is initialized before main.

The next better thing is to look where and why it crashes. Use your jtag an follow the function call in instruction stepping mode. Look at the disassembler output if its matches with the original function...

You didnt give very much to work with.. no idea about your system and your tools. :-( Hope it helped anyway.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry, I forgot to announce my system. It is the NGW100.

The subroutine here is only the return-instruction (retal r12) which is copied to ram. I use the same technic with a freescale processor and it works there. I think, there must be something configured in the ap7000 to run code from ram, but I don't know what.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Caching issues? Do you use the internal RAM or external SDRAM? Did you setup the SDRAMC if you were using the external SDRAM?

Did you compile with PIC enabled (position independent code). Could you post the output from disassembling the produced firmware?

Hans-Christian

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It can have something to do with caching. I think I have to set up the mmu. In the compiler I used the -fpic flag. The sdram is working fine and also if I use the internal ram, it is not working. Here is the code from the disassembler:

000010ac :
    10ac:	e0 60 10 d4 	mov	r0,4308
    10b0:	ea 10 00 00 	orh	r0,0x0
    10b4:	e0 61 10 d0 	mov	r1,4304
    10b8:	ea 11 00 00 	orh	r1,0x0
    10bc:	33 02       	mov	r2,48
    10be:	ea 12 11 00 	orh	r2,0x1100

000010c2 :
    10c2:	01 43       	ld.w	r3,--r0
    10c4:	04 d3       	st.w	--r2,r3
    10c6:	02 30       	cp.w	r0,r1
    10c8:	fe 9b ff fd 	brhi	10c2 
    10cc:	5d 12       	icall	r2
    10ce:	5e fc       	retal	r12

000010d0 :
    10d0:	5e fc       	retal	r12

And this is the code for using the stack. It also doesn't work.

000010ac :
    10ac:	e0 60 10 d4 	mov	r0,4308
    10b0:	ea 10 00 00 	orh	r0,0x0
    10b4:	e0 61 10 d0 	mov	r1,4304
    10b8:	ea 11 00 00 	orh	r1,0x0

000010bc :
    10bc:	01 4a       	ld.w	r10,--r0
    10be:	d0 81       	pushm	r10
    10c0:	02 30       	cp.w	r0,r1
    10c2:	fe 9b ff fd 	brhi	10bc 
    10c6:	5d 1d       	icall	sp
    10c8:	30 4a       	mov	r10,4
    10ca:	14 0d       	add	sp,r10
    10cc:	5e fc       	retal	r12
	...

000010d0 :
    10d0:	5e fc       	retal	r12
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not so sure of the micro, though as I recall most 8 bit AVR's only run code in flash program space. You may copy executable code to Flash program space from ram and then execute it, say via bootstraping ect..
Anyone know more on this cpu?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Victor_Cole wrote:
Not so sure of the micro, though as I recall most 8 bit AVR's only run code in flash program space. You may copy executable code to Flash program space from ram and then execute it, say via bootstraping ect..
Anyone know more on this cpu?
Please disregard this information, 32-bit AVR has shared data and instruction bus, hence it can execute code from the entire address space. Also known as a Von Neumann architecture.

8-bit AVR are, as you state, only able to execute from flash, since the flash is wired to the instruction bus, while RAM is wired to the data bus. Also known as a Harvard architecture.

Hans-Christian

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
It can have something to do with caching. I think I have to set up the mmu. In the compiler I used the -fpic flag.
Useless. As said, its an caching issue. I can confirm this behavior. I have some self linking code running - you must clean the cache before calling anything.
use the "cache" asm instruction to do so. setting up the MMU will not solve the problem. (unless you mark the memory uncachable - bad idea: poor performance)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Indeed, it is not necessary to set up the mmu, the cache has to be cleared or set up. The avr32 architecture document is not very helpful. The description of the cache command is only "Control cache operation" and most of the "Semantic" of Op5 is "Implementation defined", but no definition can be found. I found an example and changed it for my program, but I don't really know what the cache command exactly does. The working code is now:

DoOnStack:	
			mov		r0, lo(SpSub)
			orh		r0, hi(SpSub)
			mov		r1, lo(SpSubEnd)
			orh		r1, hi(SpSubEnd)
			mov		r2, lo(0x11000000)
			orh		r2, hi(0x11000000)
SpmoveLoop:
			ld.w	r3, r0++
			st.w	r2++, r3
			cp.w	r1, r0
			cache	r2[-4], 0x0d	/* dcache clean/invalidate */
			cache	r2[-4], 0x01	/* icache invalidate */
			brhi	SpmoveLoop

			/* flush write buffer */
			sync	0

			mov		r2, lo(0x11000000)
			orh		r2, hi(0x11000000)
			icall	r2
			retal	r12


			.balign	4
SpSub:		
			mov		r1, lo(0x10000000)
			orh		r1, hi(0x10000000)
			mov		r0, sp
			st.w	r1++, r0
			mov		r0, lo(SpSubEnd)
			orh		r0, hi(SpSubEnd)
			st.w	r1++, r0
			retal	r12

			.balign	4
SpSubEnd:
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The implementation part is in the technical manual for the respective architecture (UC3 or AP7).

Hans-Christian

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Now I can run code in RAM, but I cannot write to the flash. A "Data Address (Write)" exception is generated. It seems, that the flash is write protected, but I cannot find where and how to enable writing to the flash. Does anybody know, how to do it?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Now I can write to the flash. The address has to be shifted. The interrupt comes from an unaligned address.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here is the code of the firmwareloader for the ngw100. It expects an S-record file written to the sdram at address 0x10000000. Unfortunately I could not use subroutines. It crashed, even if I saved the lr-register on the stack. I hope the program is useful for all, who want to reprogram the device in field.

			// begin-address of code to move in r0, end-address in r1
DoInRam:	
			mov		r2, lo(0x92000000)			// point to the end of ram
			orh		r2, hi(0x92000000)
			sub		r2, r1						// subtract the size of the program to move
			add		r2, r0
			andl	r2, lo(~0x7)				// make it an 8 byte boundary
			mov		r10, r2						// save the start address
SpmoveLoop:
			ld.w	r3, r0++
			st.w	r2++, r3
			cp.w	r1, r0
			cache	r2[-4], 0x0d				// dcache clean/invalidate
			cache	r2[-4], 0x01				// icache invalidate
			brhi	SpmoveLoop

			sync	0

			icall	r10
			retal	r12


// void WriteFirmware( void )

			.section	.text.WriteFirmware, "ax", @progbits
			.global		WriteFirmware
			.type		WriteFirmware, @function

WriteFirmware:
			pushm	r0-r10
			mov		r0, lo(irfw)
			orh		r0, hi(irfw)
			mov		r1, lo(irfwend)
			orh		r1, hi(irfwend)
			rcall	DoInRam
			popm	r0-r10
			retal	r12


			.balign	4

irfw:
			// flush unlock dcache
			mov		r0, 0
			cache	r0[5], 0x8
			sync	0


			// load the default addresses and values
			mov		r0, lo(0xA0000AAA)
			orh		r0, hi(0xA0000AAA)
			mov		r2, lo(0xA0001554)
			orh		r2, hi(0xA0001554)
			mov		r1, 0xAA
			mov		r3, 0x55
			
			// r6 hold the ram address, where S-records are stored
			mov		r6, lo(0x10000000)
			orh		r6, hi(0x10000000)
			
			// r8 holds the byte count
			mov		r8, 0
			orh		r8, 0
			
			// r9 holds the address of the sector in use
			mov		r9, lo(0x800000)
			orh		r9, hi(0x800000)
			
			// set the configuration register to 1
			st.h	r0[0], r1
			st.h	r2[0], r3
			mov		r4, 0xD0
			st.h	r0[0], r4
			mov		r4, 0x01
			st.h	r0[0], r4					// set the configuration reg. to 1

			bral	gnw0

fwmainloop:
			sub		r8, 2						// count down
			cp.w	r8, 0
			breq	gnw0						// no more words in this line
			sub		r10, -2						// increment the address by two
			bral	gnw2
gnw0:
			// begin to read a new line
			mov		r12, 100					// use it as a count
gnw1:
			sub		r12, 1
			cp.w	r12, 0
			breq	fwerror						// error, no 'S' found

			ld.ub	r11, r6++
			cp.w	r11, 'S'
			brne	gnw1
			
			// 'S' found, now get the type
			ld.ub	r11, r6++
			cp.w	r11, '0'
			breq	gnw0						// ignore the S0-record
			cp.w	r11, '5'
			breq	gnw0						// ignore the S5-record
			cp.w	r11, '7'
			brhs	fwfin						// end found
			cp.w	r11, '2'					// S2 means 3 byte address
			brne	fwerror						// no valid S-record found

			// S2-record found, get the byte-count
			mov		r11, 2

			mov		r5, 0
ghx1:
			ld.ub	r4, r6++
			sub		r4, '0'
			cp.w	r4, 10
			brlo	ghx2
			andl	r4, 0x1F, COH
			sub		r4, 7
ghx2:
			lsl		r5, 4
			or		r5, r4
			sub		r11, 1
			cp.w	r11, 0
			brne	ghx1


			mov		r8, r5
			sub		r8, 4						// adjust the count
			
			// get the address
			mov		r11, 6

			mov		r5, 0
ghx3:
			ld.ub	r4, r6++
			sub		r4, '0'
			cp.w	r4, 10
			brlo	ghx4
			andl	r4, 0x1F, COH
			sub		r4, 7
ghx4:
			lsl		r5, 4
			or		r5, r4
			sub		r11, 1
			cp.w	r11, 0
			brne	ghx3

			mov		r10, r5

			
			// get a word
gnw2:
			mov		r11, 4

			mov		r5, 0
ghx5:
			ld.ub	r4, r6++
			sub		r4, '0'
			cp.w	r4, 10
			brlo	ghx6
			andl	r4, 0x1F, COH
			sub		r4, 7
ghx6:
			lsl		r5, 4
			or		r5, r4
			sub		r11, 1
			cp.w	r11, 0
			brne	ghx5

			mov		r11, r5
			

			mov		r12, r10					// get the address

			// check, if we have to erase the sector
			cp.w	r12, 0x10000				// is it in a 64kb sector?
			brlo	fw1							// it is a 8kb sector
			andh	r12, 0xFFFF, COH			// make the address a sector beginning addr.
			bral	fw2
fw1:
			mov		r4, lo(0xFFFFE000)
			orh		r4, hi(0xFFFFE000)
			and		r12, r4						// make the address a sector beginning addr.
fw2:
			cp.w	r12, r9						// now we compare sectors
			breq	fwp							// the sector should be already erased

			mov		r9, r12						// store the address of the sector to erase

			mov		r12, r10					// get the address
			orh		r12, 0xA000					// make the address a P2 sector address


			// erase the sector
			st.h	r0[0x0], r1
			st.h	r2[0x0], r3
			mov		r4, 0x80
			st.h	r0[0x0], r4
			st.h	r0[0x0], r1
			st.h	r2[0x0], r3
			
			mov		r5, 0x30
			st.h	r12[0], r5
fw3:
			ld.uh	r5, r12[0x0]
			mov		r4, r5
			andl	r4, 0x80, COH
			breq	fw3
			andl	r5, 0x28, COH
			breq	fwp
			mov		r12, 1
			bral	fwfin


fwp:
			mov		r12, r10					// get the address
			orh		r12, 0xA000					// make the address a P2 sector address

			// program the word
			st.h	r0[0x0], r1
			st.h	r2[0x0], r3
			mov		r4, 0xA0
			st.h	r0[0x0], r4
			st.h	r12[0], r11					// program the word
			
			// wait until the word is written
fwloop:
			ld.uh	r5, r12[0x0]
			mov		r4, r5
			andl	r4, 0x80, COH
			breq	fwloop
			andl	r5, 0x28, COH
			breq	fwmainloop
			bral	fwerror

fwfin:
			// flag that we reprogrammed the flash
			mov		r0, lo(0x24007000)
			orh		r0, hi(0x24007000)
			mov		r2, lo(0x55555555)
			orh		r2, hi(0x55555555)
			st.w	r0[0], r2
			mov		r2, lo(0xAAAAAAAA)
			orh		r2, hi(0xAAAAAAAA)
			st.w	r0[4], r2

fwerror:
			// set the configuration register to 0
			st.h	r0[0], r1
			st.h	r2[0], r3
			mov		r4, 0xD0
			st.h	r0[0], r4
			mov		r4, 0
			st.h	r0[0], r4					// set the configuration reg. to 0

			// write the product id exit command
			st.h	r0[0x0], r1
			st.h	r2[0x0], r3
			mov		r4, 0xF0
			st.h	r0[0x0], r4

			// Flush the caches
			mov		r1, 0
			cache	r1[4], 8
			cache	r1[0], 0
			sync	0

			// restart the cpu
			mov		r1, lo(0xa0000000)
			orh		r1, hi(0xa0000000)
			mov		pc, r1
irfwend: