//GLOBAL DECLARATAION:uint8 Flash_Command(UINT8 command, UINT16 address, UINT8 number); //function to erase/program flash // (command 40=erase page ; 20=prog byte)void high_voltage(void); //Critical high voltage flash erase/write function. must run from RAM.UINT8 high_voltage_in_RAM[50]; //this will be the place in RAM //where 'high_voltage' function will be copied. just an array.void (*function_pointer)(void); //points to address of function 'high voltage' //so we can copy it to RAM. (critical flash stuff must run from RAM) UINT8 *dummy_pointer; //just to point to byte units //instead of func units (generates indirection to diff types' warning but tha'ts ok)//////FUNCTIONS:///////////////////////////////////////////uint8 Flash_Command(UINT8 command, UINT16 address, UINT8 number) //(command 0x40=page erase ; 0x20= single byte write){//Note:just need page erase and single byte write in our Zigbee application //Note: flash seems to be unprotected by default at reset (FOPT=0xC2), which is good for us here! //NOTE: BE CAREFUL!! IF THIS FUNCTION ENDS UP BEING CALLED //FROM A LOOP OVER AND OVER, FLASH CAN BE DESTROYED!! (flash life=100,000 cycles only) UINT8 tries; UINT8 i; DisableInterrupts; //(_asm sei)During erasing or programming Flash, we must NOT be interrupted!!!tries=0;do{//try say, three times max.//(1)first copy high voltage function into RAM array //(critical flash steps must run from RAM since flash enters high voltage mode for erase/write)function_pointer= &high_voltage; //point to the address of high voltage function located in flashdummy_pointer = function_pointer; //point to bytes type at that addres //(when we increment we'll point to next byte instead of 'next function structure size')for(i=0;i<25;i++) {high_voltage_in_RAM[i] = *dummy_pointer;dummy_pointer++;}//copy the function to RAM arraydummy_pointer = (unsigned char*)&high_voltage_in_RAM; //NOW point to address of this RAM function. //(2)Prepare the flash registers here firstFSTAT |= 0x30; //clear acces error and page violation flags in case they're setFSTAT |= 0x30; //twice to ensureFCDIV = 0x27; //Set 8MHz/39=200Khz required flash clock //(in case it hasn't done before. if it has, this line won't affect it).//Now just mock-write the number in the address so flash controller latches //the target address and the number. _asm ldhx address //point to address //(for erase operations, the page (512 bytes) associated with //this address is the one to be erased)_asm lda number //put number in A (for erase operations, any number can go in here)_asm sta ,x //put A into address//Now put command into FCMD flash command register. FCMD = command; //(0x40=page erase ; 0x20= single byte write) //FCMD address=0x1826 on MC13214. //note: FCMD is non readable, so you can't see it 'change' from the debugger.//(3)Now call the Flash High Voltage handler function, which executes the flash command:asm{ ldhx dummy_pointer // load HighVoltage function address into X register jsr , x // finally call HighVoltage function //located in RAM (it should resume here when done) } //(4)now check for error flags in FSTAT (page violation flag bit5, access error flag bit4)tries++;}while(((FSTAT & 0x30) != 0x00)&& (tries <3));//try it again if errors found//(5)done!EnableInterrupts; //(_asm cli) ok, done with Flash, enable them againif ((FSTAT & 0x30) != 0x00){while(1){};return 0;}//if after three tries //it had still failed, return error. if ((FSTAT & 0x30) == 0x00){return 1;}//if it was succesful, return succes}///////////////////////////////////////////////////void high_voltage(void){//Just the critical Flash high voltage stuff is taken care of here.asm{//all in assembly here. this code will be copied into //a RAM array before being used (MUST RUN FROM RAM!!). ldhx #0x1825 //load FSTAT flash status register address (0x1825 on MC1321(hcs09gb60)) lda #0x80 //;A= 0x80 (command launch bit) sta ,x //;LAUNCH FLASH COMMAND!! //(put 0x80 on FSTAT) (Flash now goes into high voltage //operation till command completes) nop //wait at least four bus clock cycles before checking what happened nop nop nop //WAIT UNTIL COMMAND COMPLETE //(FSTAT->FCCF command complete flag=1) (byte program=45uS, page erase=20mS) lbl: //<<--just a label lda ,x //put FSTAT in A cmp #0xC0 //compare A with $C0 (command buffer empty and command complete flags)—– blo lbl //Keep checking if it's not the case yet (branch if lower) //AND RETURN rts //return to subroutine caller. (address automatically retrieved from stack) }//end asm //It is up to the caller of this function to check //for error flags on FSTAT and maybe call this again if necessary. //Note: opcodes for these instructions are: 45,18,25,A6,80,F7,//9D,9D,9D,9D,F6,A1,C0,25,FB,81. (taken from debugger)}
Message Edited by Alban on 2007-01-31 08:44 PM