I've been browsing the uVision/MDK-ARM manuals looking for a way to do something I did when using the Rowley CrossStudio tools, but I can't find what I'm looking for.
Basically, my app is too large to fit in the FLASH in my MCU (lots of graphics assets). With CrossStudio, I could set my project up so that the graphics assets were located in an external FLASH device that supported CFI (Common Flash Interface). Then when I built my app and used their JTAG tool it would write the parts of the app that belonged in the MCU to the MCU, and write the parts that belonged in the external FLASH to the external FLASH, such that my graphics assets were all available in the external FLASH device from the app code running in the MCU internal FLASH.
Is this possible with uVision/MDK-ARM, and if so, could someone please point me to where I can find the related documentation in the product manuals? Are there any KEIL app notes that describe the process? If they're there, I must be using the wrong search keywords, because I haven't been able to find them.
Thanks!
So... I'm going to assume (for now) that the lack of response to this post on this otherwise quite active forum means that there's no way to do this via the uVision IDE.
:-(
"If not, how is the IDE/JTAG tool supposed to know how to use the CFI algorithm in the loader app to actually get addresses & data onto the MCU's external address/data/control bus to talk to the FLASH chip...?"
Open the project options, and select page Utilities.
To the right of the selected JTAG interface, you have a 'Settings' button.
It pops up a dialog where you can add flash algorithms, and specifies which address ranges that requires this algorithm.
The JTAG interface doesn't know how to get addresses and data onto the MCU's external address/data/control bus.
The JTAG interface just knows how to get data into RAM, and how to get that downloaded flash algorithm to activate. The flash algorithm (that Keil supplies or that you have written yourself) knows how to pick up the data from RAM, and to drive the processor pins to write to the flash.
So in the end, the JTAG interface isn't involved in writing to your external flash. Just to hand over data to the flash algorithm.
In some situations, the flash algorithm have to play directly with processor pins or magic registers. In some situations, the flash algorithm might hand over the data to a boot loader IAP function already in existence in the processor and running code supplied by the chip vendor.
Thanks Per... your answer was very helpful.
I couldn't see how those flash loader samples could work, but now I do.
I took the CPU init code (just the I/O pin and external memory controller stuff) from my Segger JFlash script and pasted it into the init function in the (copied/edited) sample flash loader app for the NOR flash chip, and... it seems to be working perfectly now.
I am so grateful for your response... thanks again!!!
Sigh... so close... but not quite there...
I tested all this stuff by loading different large images into my external NOR FLASH and then displaying them. All was well for a while, but now I get the following error when I try to download:
Flash Timeout. Reset the target and try again. This happens during the ERASE part of the download process.
I tried increasing the timeout setting from 4 to 20 seconds in the flash loader app, and that did delay the above error message for 20 seconds, but didn't fix the problem so I put it back to 4 seconds.
Would you say then that the most likely cause is that the init code I copied into the flash loader's init function is close, but not quite correct? Meaning that the MCU can't access the flash chip at that place in the address map?
Bizzare... (meaning that I still don't understand what's happening)...
I went back to the app I used to create/test the minimal CPU code, to confirm that after it was done I could do a CFI query successfully; and it worked okay.
I went back to my board app and then the the download to the MCU and the NOR flash worked.
However, it's still flaky. Sometimes downloads to the MCU and NOR flash work, sometimes they don't. I think it must be that my init code is not quite right.
I tried by initialization app over and over again, and eventually it failed too (not loading into the board, but getting correct results from the CFI query).
Sigh...
Dave,
You need to add a load region to your scatter loading file. In that region, add at least one execution region and place in it the object files that need to be mapped to external flash. In addition, one of the blinky samples should show (at least, it did until 2010...) how to configure a NOR flash via uv4.
Thanks Tamir, but is using the scatter load file a requirement, or a preference?
For this exercise, is it sufficient to declare my image like this:
const uint8_t image[] __attribute__((at(0x80000000))) = // 800 x 480 image { ... all the image data goes here ... };
if the NOR flash base address is 0x80000000?
I ask because using the 'at' attribute appears to be enough to signal the tools that it needs to use a loader (different from the MCU loader), and the external flash loader does seem to be invoked as needed; it's just that it doesn't always product the desired result.
... doesn't always PRODUCE the desired result.
And... when my init app (that test's the EMC init code by doing a CFI query, but doesn't have anything that needs to be loaded into the external NOR flash) fails...
cycling power and restarting the debugger fixes it. Then I can load my other app (that does have stuff that needs to go into the external NOR flash) successfully.
More evidence that the init code is the most likely culprit...
I do appreciate all the responses... this has not been as easy as I'd hoped it would be, but it looks like I'm getting pretty close to a successful end.
2 more questions...
1) If my flash chip (Spansion S29GL064N90TFI010) has a uniform sector organization, made up of 64 KB blocks, does this look like correct info for the FlashDevice struct in FlashDev.c?
struct FlashDevice const FlashDevice = { FLASH_DRV_VERS, // Driver Version, do not modify! "S29GL064 Flash", // Device Name EXT16BIT, // Device Type 0x00000000, // Device Start Address 0x00800000, // Device Size in Bytes (8MB) 1024, // Programming Page Size 0, // Reserved, must be 0 0xFF, // Initial Content of Erased Memory 150, // Program Page Timeout 150 mSec 4000, // Erase Sector Timeout 4000 mSec // Specify Size and Address of Sectors 0x10000, 0x00000, // Uniform Sector Size 64kB SECTOR_END };
2) Sometimes, although not very often, I get the following error messages while trying to download my app (that uses the external NOR flash):
Erase Done. ***JLink Error: Can not read register 15 (R15) while CPU is running ***JLink Error: Can not read register 20 (CFBP) while CPU is running ***JLink Error: CPU is not halted ***JLink Error: Can not read register 15 (R15) while CPU is running Programming Failed!
What does this mean, and what's a likely cause?
After some tweaking of the external memory controller initialization code, the EraseSector feature of the flash loader app appears to be 100% reliable. However, the ProgramPage feature seems to be completely broken.
By using the Segger J-Flash app, I can confirm that the 16-bit wide data bus NOR flash chip is really being erased at the beginning of every program download attempt, and that no data is ever successfully written to the chip.
I wrote my own CFI flash functions (in my app, not the flash loader app); and they have no problem erasing, reading, or writing to the flash chip. This confirmed that the CFI functions work, and that the flash chip is working too.
I did notice a couple of questionable things in the template flash loader app.
1) There's no attempt to enter or exit the CFI Query mode. I must assume that the KEIL tools ensure that the only time they try to use the flash commands in the flash loader is while CFI Query mode is active.
2) There does not appear to be any attempt to handle the cases where the starting or ending address of a flash program operation straddles a 16-bit word boundary. So, if my application has arrays of bytes in const code space that's mapped to the NOR flash chip, what happens if the array starts or ends at an odd address? One might modify the ProgramPage function in the flash loader to handle these cases by looking at the starting address and doing something different if it's an odd address, or doing something different if there's less than 2 bytes left to write. Coincidentally, the data sheet for the Spansion chip I'm using notes that the *normal* programming process does not work if you ever try to program a word location that's not completely erased. In other words, incremental bit programming is not normally supported. The datasheet refers coders who want to do that to contact Spansion for special instructions that tell you how to implement incremental bit programming. So, again, not knowing how the KEIL tools call the functions in the flash loader app, I must assume that they never try to write a half word to a word location that's already got any bit programmed (or contact Spansion and get the special instructions, and handle that case, which I'm already trying to do).
But...
1) if my flash functions work the same as the ones in the flash loader app, and 2) I constrain my app to a single variable in the NOR flash address space, and 3) I confirm via the map file that it's located at a 32-bit address boundary (i.e., lower 2 bits are zero), and 4) my flash functions have no problem erasing, reading, or writing to the chip (confirmed by J-Flash and a JLink-Lite),
What could be a reason why the flash loader app can erase but not write to the NOR flash chip (during the program download process in the uVision IDE)?
Maybe there is clock timing differences between your program and the flash loader app.
That's possible. However, the init code that I put into the flash loader app (which does configure the clock tree) was copied from my app. So, if it's different, it's not because I made them different. Not knowing what the IDE's download process does though, could account for them being different, if they are.
Does your own application run from RAM or flash? Because flash execution is often slower than RAM execution.