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!
... 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.
It runs from MCU internal flash. The clock tree should be the same though. Perhaps the flash loader app is running faster and violating the timing of the external NOR flash? I thought that might be the case, so I set all the timing parameters in the external memory controller to their slowest settings, but that didn't make a difference.
"Thanks Tamir, but is using the scatter load file a requirement, or a preference?"
I am not sure it is required in this particular instance but it certainly makes your code more readable and maintainable.
Did you verify the timing of the different control signals going to the NOR? If remember correctly, there is a series of settings in Keil startup files to configure parameters of EMC slots. A BBR once gave us hell !
I'll see if I can't get some flying leads added to the board so that I can compare the timing as the different apps are running.
Now that I think about it... the timing for my flash functions running from MCU internal flash shouldn't be an issue, because those functions work. It's the flash loader app functions that don't work. I'm assuming that those functions (in the flash loader app) must be running from RAM. So... maybe they're executing too fast when running from RAM and thereby violating timing?
So... I adjusted the timing via the init code in the flash loader app to make the system clock run slower, and guess what...? The flash loader app and the download process started working!
So... when running from RAM, the code executed so much faster that the CFI functions violated the timing constraints, and that's why it wouldn't work!
That must be it, because the download process is working quite reliably now. My tech is out till mid next week, so I'll have to wait to get the flying leads added to my board to confirm this all in an easily quantifiable way using an o-scope. In the meantime I'll see if I can't do the math and see if that confirms my hypothesis.
Thanks again for all the hints!