Is there any documentation that can help me get started with this? I tried searching but wasn't able to find much. I am trying to port code from a MC68HC908AB32 processor into this newer MC9S08AC128 processor.
Hi Jobber,
I attached some code for the AC128 for doing some simple EERPOM emulation. It does not require any modifications to the .prm file.
1. Create a new CW10.3 project, copy this main.c into the project, compile and run.
2. Open a hyper term, baud 38400, no hardware, no flow control.
The GUI will give the option to read, write and erase. This is a very simple program, but gets the idea on how to use the flash commands in the S08s.
Hope this helps-
Mike
Nice example, michaelsteffenfae. It will be very useful.
As far i could see, you aren't using external xtal? I'm correct?
Egidio
Yes. You are correct.
Michael Steffen
Cell 815-519-1567
Hello jobber.
In order to implement EEPROM emulation using Flash memory, it is required to have a Flash driver that allows erase and write the Flash. When these actions are performed, the Flash are inaccessible, thus, it is required to copy the flash routines from Flash to RAM and executing from RAM.
Some considerations for this implementation are that Flash clock must be from 150 to 200 KHz for correct erase/write operations, and that Flash memory can only be erased by pages, and MC9S08AC128 has 256 pages of 512 bytes each. I have uploaded an example project for MC9S08AC128 device and CodeWarrior v6.3; hope this will be useful for you.
Have a nice day.
Thank you Carlos for your response. I've used your sample code and made some modifications accordingly (I am using a 14.7 MHz clock). The settings in the .prm file I have used is similar to the sample. In my code, I am trying to save user data stored in RAM to the 0x78000 Flash address.
My issue seems to be that sometimes the Flash write works and sometimes it does not. Do you have an idea of what I may be setting up improperly?
I have tried stepping through the code, and the error flags do not trigger (FLASH_OK is always returned), so I am not sure what the issue is. When stepping through the u8Flash_Cmd() function, all the expected data and flags are there, but I do not see the Flash memory being set to the expected values in the Memory window of the debugger.
There are two likely causes which will yield similar behavior: either you have calculated the flash clock prescaler incorrectly, or you are running the flash programming algorithm from flash despite the advise made in this post.
I had checked the location of the flash programming function in the debugger, and it is correctly stored in RAM at 0x100. Here's a code snippet from the PRM file:
SEGMENTS /* Here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. */
Z_RAM = READ_WRITE 0x0080 TO 0x00FF;
RAM = READ_WRITE 0x0158 TO 0x17FF;
RAM1 = READ_WRITE 0x1870 TO 0x20EF;
/* unbanked FLASH ROM */
ROM = READ_ONLY 0x20F0 TO 0x7FFF;
ROM1 = READ_ONLY 0xC101 TO 0xFF9B;
/* INTVECTS = READ_ONLY 0xFF9C TO 0xFFFF; Reserved for Interrupt Vectors */
/* banked FLASH ROM */
PPAGE_0 = READ_ONLY 0x008000 TO 0x00A0EF; /* PAGE partially contained in ROM segment */
PPAGE_2 = READ_ONLY 0x028000 TO 0x02BFFF;
PPAGE_4 = READ_ONLY 0x048000 TO 0x04BFFF;
PPAGE_5 = READ_ONLY 0x058000 TO 0x05BFFF;
PPAGE_6 = READ_ONLY 0x068000 TO 0x06BFFF;
PPAGE_7 = READ_ONLY 0x078000 TO 0x07BFFF;
/* PPAGE_1 = READ_ONLY 0x018000 TO 0x01BFFF; PAGE already contained in segment at 0x4000-0x7FFF */
/* PPAGE_3 = READ_ONLY 0x038000 TO 0x03BFFF; PAGE already contained in segment at 0xC000-0xFFFF */
FLASH_TO_RAM = READ_ONLY 0xC000 TO 0xC100 RELOCATE_TO 0x100;
END
I've defined the flash clock as follows:
#define BUS_CLOCK 14745600
#if BUS_CLOCK > 12800000
#define FLASH_CLOCK (unsigned char)((BUS_CLOCK/1600000) + 0x40)
#else
#define FLASH_CLOCK (unsigned char)(BUS_CLOCK/200000)
#endif
The vfnFlashInit() routine that was provided by Carlos uses the FLASH_CLOCK to set the FCDIV. So it would appear I am setting these up correctly...
It seems like the problem now is that when I use the burst command to write to 0x78000 (during startup), the Flash data there is correctly erased and writes to the buffer there (but also unintentionally writes the same data to 0x8000 apparently). However, subsequent Flash burst commands only seem to update the data at 0x8000, but not at 0x78000. I need to store this data in 0x78000 which is in Banked Flash ROM so that on program reset, I will be able to retrieve it.
0x8000 is not only banked flash, but also PPAGE window. When you were programming 78000. you probably switched PPAGE to 7, and it made PPAGE 7 visible at 0x8000. After programming ant restore of PPAGE you should see old values at 0x8000.
Thanks Edward for that.
Yes, after I do a reset, the memory at 0x8000 gets cleared, but the memory at 0x78000 does not (which is what I intend). It looks like my remaining problem now is trying to read from 0x78000 and store into RAM.
I have this defined:
#define Flash_ReadSetup(FAddress) *(SetupData_t*)FAddress
#define FLASH_ADDRESS 0x78000
...
SetupData_t SetupData;
So the idea is to call the following to store the flash data into RAM:
SetupData = Flash_ReadSetup(FLASH_ADDRESS);
Unfortunately, it looks like this is reading from 0x8000 (which got cleared on a reset) instead of the intended 0x78000, so it doesn't work.
Unfortunately CW for S08 doesn't support banked data pointers, so you can't *(type*)address to access your data. Unless CW v10.3 has improved it, you either need to switch PPAGE and get data from PPAGE window, or use Linear Address Pointer hardware to access data without PPAGE switching.
1. PPAGE switching.
You can switch PPAGE only from routine in nonbanked memory. So your access routine shoud be made nonbaked. Also you need to restore PPAGE, else you will have problems returning to banked caller.
SetupData_t mysd; #pragma CODE_SEG __NEAR_SEG NON_BANKED void GetDataFrom78000(void) { char PPAGEbackup;
PPAGEbackup = PPAGE; PPAGE = 7; mysd = *(SetupData_t*)0x8000; PPAGE = PPAGEbackup; } #pragma CODE_SEG DEFAULT
2. LAP
There are 3 linear address pointer bytes LAP0-LAP2. You write address there, then read data from LB, LBP, or LWP registers.
Linear address is not the same like 78000, which is ppage*0x10000 + address in PPAGE window. Linear address is ppage*sizeof(page_window)+page_window_offset.
(Code insertion is broken, had to made new message)
#define BANKED_TO_LINEAR(x) (((x) / 0x10000) * 0x4000 + (x) % 0x4000)
int i; char *ptr;
LAP2 = BANKED_TO_LINEAR(0x78000) / 0x10000; LAP1 = BANKED_TO_LINEAR(0x78000) / 0x100; LAP0 = BANKED_TO_LINEAR(0x78000) / 0x1; ptr = &mysd; for(i = 0; i<sizeof(SetupData_t); i++) { *ptr++ = LBP; }
Jobber, sorry for the delay!
Here are a couple of documents that may be useful
Regards!