Reserving space in SRAM for SRAM decay experiment (C ; AVR atmega644p ; Atmel Studio 7) - c

I am looking to perform some experiments on an atmega644p looking at evaluating the amount of decay in SRAM between power cycles. My method is to set a number of bytes in SRAM to 0xFF, then when the mcu powers back up, count the number of remaining 1s in these bytes.
For this to work, I need to read and write the array of 1s to/from a known memory address in SRAM. So far I have code which writes the values to a specific address using a pointer set to 0x1000, and then on power up I begin reading the array from this address. However, I need a way of guaranteeing that this section of SRAM memory (say, 0x100 + 64 bytes) is not allocated to other variables/overwritten before it can be read.
I have looked online at the possibility of allocating memory segments - I don't know if this is a good solution in this case, and am not even too sure how to go about doing this. Can anyone suggest a neat way of approaching this?
Please ask any questions for clarification.
Thanks for your help.

If you're using AVR/GNU, then when C app starts it clears whole the memory and initializes global variables as required.
To avoid that, you can configure the linker to exclude all start files using options -nostartfiles -nodefaultlibs -nostdlib
If you're using Atmel Studio you can configure it like this:
After that you can mark your main for it to be called as initialization code:
int main(void) __attribute__((naked, section(".init9")));
Now you'll have the "naked" code, which does not perform ANY initialization.
That means you need at least to initialize the stack pointer and clear register r1 (which is assumed by avr-gcc to contain zero):
int main(void) {
asm volatile (
"clr r1\n" // load zero into r1
"cli" // clear I flag
);
SPL = (uint8_t)RAMEND;
SPH = (uint8_t)(RAMEND >> 8);
... // here goes your code
for(;;); // do not leave main()!
}
After this you'll have ALL global variables uninitialized. You can declare, for example a global array and check its content on startup.

You'll need to come up with a custom region in RAM by reserving space for it in your linker file. It is important that it is marked "no init" or similar, or otherwise .bss initialization and similar might happen on it before main() is called. How to do this is linker-specific.
However, writing software for this seems needlessly cumbersome. Simply use an in-circuit debugger:
Ensure that you are using a debugger which does not power the target.
Download a program which uses no RAM at all into flash. Confirm this by checking the map file.
Set the whole RAM to 0xFF through the debugger.
Remove power while keeping the in-circuit debugger connected.
Wait x time units.
Power up, hit MCU reset in the debugger, memory dump the whole RAM.
Any half-decent tool chain should be able to do this for you.

Related

I want to understand the syntax of '__attribute__((space(dma)));'

I have to write a Stub for:
extern ECAN1MSGBUF ecan1msgBuf __attribute__((space(dma)));
Can someone explain to me what makes this call, how it works and how I can write / use a stub for a test program? I have the hardware not at home and must write a test, but the XCode announces as a warning: unknown attributes space ignored. Otherwise I work on the MPLabX compiler / debugger with access to the hardware. There is not the problem, of course.
DMA space on dspics is dual ported RAM that can be accessed without competing for memory bandwidth with the ALU (the actual CPU).
However, in some dspicE's (*) , DMA space is beyond the 32kb mark which needs EDS addressing. If so, you might want to view the sample code I posted about dspice CAN at http://www.microchip.com/forums/m790729.aspx#792226
Note that you can also use non dma space memory, the dma space memory is just more optimal.
(*) the ones with 56k memory, which are generally the 512KB flash parts for the GP and MU series.

Big empty space in memory?

Im very new to embedded programming started yesterday actually and Ive noticed something I think is strange. I have a very simple program doing nothing but return 0.
int main() {
return 0;
}
When I run this in IAR Embedded Workbench I have a memory view showing me the programs memory. Ive noticed that in the memory there is some memory but then it is a big block of empty space and then there is memory again (I suck at explaining :P so here is an image of the memory)
Please help me understand this a little more than I do now. I dont really know what to search for because Im so new to this.
The first two lines are the 8 interrupt vectors, expressed as 32-bit instructions with the highest byte last. That is, read them in groups of 4 bytes, with the highest byte last, and then convert to an instruction via the usual method. The first few vectors, including the reset at memory location 0, turn out to be LDR instructions, which load an immediate address into the PC register. This causes the processor to jump to that address. (The reset vector is also the first instruction to run when the device is switched on.)
You can see the structure of an LDR instruction here, or at many other places via an internet search. If we write the reset vector 18 f0 95 e5 as e5 95 f0 18, then we see that the PC register is loaded with the address located at an offset of 0x20.
So the next two lines are memory locations referred to by instructions in the first two lines. The reset vector sends the PC to 0x00000080, which is where the C runtime of your program starts. (The other vectors send the PC to 0x00000170 near the end of your program. What this instruction is is left to the reader.)
Typically, the C runtime is code added to the front of your program that loads the global variables into RAM from flash, and sets the uninitialized RAM to 0. Your program starts after that.
Your original question was: why have such a big gap of unused flash? The answer is that flash memory is not really at a premium, so we can waste a little, and that having extra space there allows for forward-compatibility. If we need to increase the vector table size, then we don't need to move the code around. In fact, this interrupt model has been changed in the new ARM Cortex processors anyway.
Physical (not virtual) memory addresses map to physical circuits. The lowest addresses often map to registers, not RAM arrays. In the interest of consistency, a given address usually maps to the same functionality on different processors of the same family, and missing functionality appears as a small hole in the address mapping.
Furthermore, RAM is assigned to a contiguous address range, after all the I/O registers and housekeeping functions. This produces a big hole between all the registers and the RAM.
Alternately, as #Martin suggests, it may represent uninitialized and read-only Flash memory as -- bytes. Unlike truly unassigned addresses, access to this is unlikely to produce an exception, and you might even be able to make them "reappear" using appropriate Flash controller commands.
On a modern desktop-class machine, virtual memory hides all this from you, and even parts of the physical address map may be configurable. Many embedded-class processors allow configuration to the extent of specifying the location of the interrupt vector table.
UncleO is right but here is some additional information.
The project's linker command file (*.icf for IAR EW) determines where sections are located in memory. (Look under Project->Options->Linker->Config to identify your linker configuration file.) If you view the linker command file with a text editor you may be able to identify where it locates a section named .intvec (or similar) at address 0x00000000. And then it may locate another section (maybe .text) at address 0x00000080.
You can also see these memory sections identified in the .map file, along with their locations. (Ensure "Generate linker map file" is checked under Project->Options->Linker->List.) The map file is an output from the build, however, and it's the linker command file that determines the locations.
So that space in memory is there because the linker command file instructed it to be that way. I'm not sure whether that space is necessary but it's certainly not a problem. You might be able to experiment with the linker command file and move that second section around. But the exception table (a.k.a. interrupt vector table) must be located at 0x00000000. And you'll want to ensure that the reset vector points to the new location of the startup code if you move it.

Force Variable to be Stored in FLASH in C Using ARM Processor

I know I can force an array into FLASH in ARM by declaring it "const". But this is not truly an array of consts: I want to be able to write to it regularly. I have three large arrays that take up ~50k of the 128kB of SRAM I have available, but I have an order of magnitude more FLASH than I need. How can I force these three arrays into FLASH without declaring them const? Using IAR, BTW.
Tried using the __no_init keyword; according to the linker map files this had no effect.
To answer the original question, you can write a linker script to force any variable to reside in a predetermined area of memory (declaring them const does not force the compiler to put it in FLASH, it is merely a strong suggestion).
On the other hand, overabundance of FLASH is not in itself a good reason to keep a non-const array in flash. Among the reasons are: 1) depending on the chip, the access to FLASH memory can be much slower than RAM access (especially for writing) 2) FLASH can only be rewritten a limited number of times: it is not a problem for an occasional rewrite but if your code constantly rewrites FLASH memory, you can ruin it rather quicky. 3) There are special procedures to write to FLASH (ARM makes it easy but it is still not as simple as writing to RAM).
The C language, compilers, etc are not able to generate chip/board specific flash routines. If you wish to use flash pages to store read/write data you are going to have to have at least a page worth of ram and some read/write routines. You would need to have very many of these variables to overcome the cost of ram and execution time needed to keep the master copy in flash. In general every time you write the value to flash, you will need to read out the whole page, erase the page, then write back the whole page with the one item changed. Now if you know how your flash works (Generally it is erase to ones and write zeros) you could read the prior version, compare differences and if an erase is not needed then do a write of that one item.
if you dont have dozens of variables you wish to do this with then, dont bother. You would want to declare a const something offset for each variable in this flash and have a read/write routine
const unsigned int off_items=0x000;
const unsigned int off_dollars=0x004;
...
unsigned int flash_read_nv ( unsigned int offset );
void flash_write_nv ( unsigned int offset, unsigned int data);
so this code that uses .data:
items++;
dollars=items*5;
Using your desire to keep the variables in flash becomes:
unsigned int ra,rb;
ra= flash_read_nv(off_items);
rb= flash_read_nv(off_dollars);
ra++;
rb=ra*5;
flash_write_nv(off_items,ra);
flash_write_nv(off_dollars,ra);
And of course the flash writes take hundreds to thousands of clock cycles or more to execute. Plus require 64, 128, or 256 bytes of ram (or more) depending on the flash page size.
Believe it or not, this page is the best thing that pops up when looking how to store data in flash with the AVR ARM compiler.
On page 359 of the manual (the one that comes with v7.50 of the compiler), does show this as a way to put data in flash:
#define FLASH _Pragma("location=\"FLASH\"")
On page 332 of the manual, however, it says this:
"Static and global objects declared const are allocated in ROM."
I tested it and it seems the pragma is unnecessary with the IAR compiler, as specifying const puts it in flash already (as stated in the original question).
From the other answers, it seems like the OP didn't really want to use flash. If anyone like me comes to this page to figure out how to store data in flash with the AVR ARM compiler, however, I hope my answer saves them some time.
In IAR, you can declare your array as follows:
__root __no_init const uint8_t myVect[50000] #0x12345678
Where, of course, 0x12345678 is the address in FLASH.

call stack unwinding in ARM cortex m3

I would like to create a debugging tool which will help me debug better my application.
I'm working bare-bones (without an OS). using IAR embedded workbench on Atmel's SAM3.
I have a Watchdog timer, which calls a specific IRQ in case of timeout (This will be replaced with a software reset on release).
In the IRQ handler, I want to print out (UART) the stack trace, of where exactly the Watchdog timeout occurred.
I looked in the web, and I didn't find any implementation of that functionality.
Anyone has an idea on how to approach this kind of thing ?
EDIT: OK, I managed to grab the return address from the stack, so I know exactly where the WDT timeout occurred.
Unwinding the whole stack is not simple as it first appears, because each function pushes different amount of local variables into the stack.
The code I end up with is this (for others, who may find it usefull)
void WDT_IrqHandler( void )
{
uint32_t * WDT_Address;
Wdt *pWdt = WDT ;
volatile uint32_t dummy ;
WDT_Address = (uint32_t *) __get_MSP() + 16 ;
LogFatal ("Watchdog Timer timeout,The Return Address is %#X", *WDT_Address);
/* Clear status bit to acknowledge interrupt */
dummy = pWdt->WDT_SR ;
}
ARM defines a pair of sections, .ARM.exidx and .ARM.extbl, that contain enough information to unwind the stack without debug symbols. These sections exist for exception handling but you can use them to perform a backtrace as well. Add -funwind-tables to force GCC to include these sections.
To do this with ARM, you will need to tell your compiler to generate stack frames. For instance with gcc, check the option -mapcs-frame. It may not be the one you need, but this will be a start.
If you do not have this, it will be nearly impossible to "unroll" the stack, because you will need for each function the exact stack usage depending on parameters and local variables.
If you are looking for some exemple code, you can check dump_stack() in Linux kernel sources, and find back the related piece of code executed for ARM.
It should be pretty straight forward to follow execution. Not programmatically in your isr...
We know from the ARM ARM that on a Cortex-M3 it pushes xPSR,
ReturnAddress, LR (R14), R12, R3, R2, R1, and R0 on the stack. mangles the lr so it can detect a return from interrupt then calls the entry point listed in the vector table. if you implement your isr in asm to control the stack, you can have a simple loop that disables the interrupt source (turns off the wdt, whatever, this is going to take some time) then goes into a loop to dump a portion of the stack.
From that dump you will see the lr/return address, the function/instruction that was interrupted, from a disassembly of your program you can then see what the compiler has placed on the stack for each function, subtract that off at each stage and go as far back as you like or as far back as you have printed the stack contents.
You could also make a copy of the stack in ram and dissect it later rather than doing such things in an isr (the copy still takes too much time but is less intrusive than waiting on the uart).
If all you are after is the address of the instruction that was interrupted, that is the most trivial task, just read that from the stack, it will be at a known place, and print it out.
Did I hear my name? :)
You will probably need a tiny bit of inline assembly. Just figure out the format of the stack frames, and which register holds the ordinary1 stack pointer, and transfer the relevant values into C variables from which you can format strings for output to the UART.
It shouldn't be too tricky, but of course (being rather low-level) you need to pay attention to the details.
1As in "non-exception"; not sure if the ARM has different stacks for ordinary code and exceptions, actually.
Your watchdog timer can fire at any point, even when the stack does not contain enough information to unwind (e.g. stack space has been allocated for register spill, but the registers not copied yet).
For properly optimized code, you need debug info, period. All you can do from a watchdog timer is a register and stack dump in a format that is machine readable enough to allow conversion into a core dump for gdb.

How to use external memory on a microcontroller

In the past, I've worked a lot with 8 bit AVR's and MSP430's where both the RAM and flash were stored on the chip directly. When you compile and download your program, it sort of "just works" and you don't need to worry about where and how variables are actually stored.
Now I'm starting a project where I'd like to be able to add some external memory to a microcontroller (a TI Stellaris LM3S9D92 if that matters) but I'm not entirely sure how you get your code to use the external RAM. I can see how you configure the external bus pretty much like any other peripheral but what confuses me is how the processor keeps track of when to talk to the external memory and when to talk to the internal one.
From what I can tell, the external RAM is mapped to the same address space as the internal SRAM (internal starts at 0x20000000 and external starts at 0x60000000). Does that mean if I wrote something like this:
int* x= 0x20000000;
int* y= 0x60000000;
Would x and y would point to the first 4 bytes (assuming 32 bit ints) of internal and external RAM respectively? If so, what if I did something like this:
int x[999999999999]; //some super big array that uses all the internal ram
int y[999999999999]; //this would have to be in external ram or it wouldn't fit
I imagine that I'd need to tell something about the boundaries of where each type of memory is or do I have it all wrong and the hardware figures it out on its own? Do linker scripts deal with this? I know they have something to do with memory mapping but I don't know what exactly. After reading about how to set up an ARM cross compiler I get the feeling that something like winavr (avr-gcc) was doing a lot of stuff like this for me behind the scenes so I wouldn't have to deal with it.
Sorry for rambling a bit but I'd really appreciate it if someone could tell me if I'm on the right track with this stuff.
Update
For any future readers I found this after another few hours of googling http://www.bravegnu.org/gnu-eprog/index.html. Combined with answers here it helped me a lot.
Generally that is exactly how it works. You have to properly setup the hardware and/or the hardware may already have things hardcoded at fixed addresses.
You could ask the same question, how does the hardware know that when I write a byte to address 0x21000010 (I just made that up) that that is the uart transmit holding register and that write means I want to send a byte out the uart? The answer because it is hardcoded in the logic that way. Or the logic might have an offset, the uart might be able to move it might be at some other control register contents plus 0x10. change that control register (which itself has some hardcoded address) from 0x21000000, to 0x90000000 and then write to 0x90000010 and another byte goes out the uart.
I would have to look at that particular part, but if it does support external memory, then in theory that is all you have to do know what addresses in the processors address space are mapped to that external memory and reads and writes will cause external memory accesses.
Intel based computers, PC's, tend to like one big flat address space, use the lspci command on your Linux box (if you have one) or some other command if windows or a mac, and you will find that your video card has been given a chunk of address space. If you get through the protection of the cpu/operating system and were to write to an address in that space it will go right out the processor through the pcie controllers and into the video card, either causing havoc or maybe just changing the color of a pixel. You have already dealt with this with your avr and msp430s. Some addresses in the address space are flash, and some are ram, there is some logic outside the cpu core that looks at the cpu cores address bus and makes decisions on where to send that access. So far that flash bank and ram bank and logic are all self contained within the boundaries of the chip, this is not too far of a stretch beyond that the logic responds to an address, and from that creates an external memory cycle, when it is done or the result comes back on a read it completes the internal memory cycle and you go on to the next thing.
Does that make any sense or am I making it worse?
You can use the reserved word register to suggest to the compiler that it put that variable into an internal memory location:
register int iInside;
Use caution; the compiler knows how many bytes of register storage are available, and when all available space is gone it won't matter.
Use register variables only for things that are going to be used very, very frequently, such as counters.

Resources