Camilo Cruz

ZIGBEE: For those of you struggling to save your Net ID in flash !

Discussion created by Camilo Cruz on Jan 31, 2007
Latest reply on Nov 2, 2007 by Pavendhan Yadav
Well, After almost drowning in a sea of #ifndefined and #defines (good grief!!) and after almost getting lost in a forest of NV_ram structres, function pointers and header files...the  'Update_NV RAM' functions from appnote 2770  **DID NOT WORK**  to save my  updated MAC network address in flash.  
I tried then the 'Flash bean' from Processor Expert, but faced a mountain of conflicts with the .prm files and other things of the sort. so that had to be abandoned as well.
-BUT FINALLY HERE IT IS,  I wrote these two small funtions that will let you save the few bytes of your network ID in flash (cause that's all you need in a Zigbee application!!).
The trick to this is to copy the critical flash instructions to RAM and execute them from there, because the flash enters a high voltage mode when erasing or programming bytes, so no code can run from there simoultaneously. So the function  "Flash_Command" here just copies the "high voltage" function into a little RAM  array and jumps to execute from it, where the actual flash command is triggered, and then we exit when the high voltage operation is finally over. is that easy or what?
All YOU have to do, is copy and paste this code into you program, there's no nasty file or memory allocation dependencies with this :smileyhappy: , just make sure the globally declared things are placed on top of your  program, where all global stuff goes of course.
How to use it then:
//Erase the desired page   -in the 13213, 13214  there is free flash between $1080 to $1200, use that:
Flash_Command(0x40, 1080, 0);  //this erases that page
//Now program a byte (0x55 for example)  into address 1082 for example:
Flash_Command(0x20, 1082, 0x55); //this puts 0x55 in $1082
//repeat for any other bytes that make your network ID.
NOTE: of course don't program the same byte address more than once without erasing the page first!!
Any questions, let me know...
//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)}
Search Keywords:   zigbee , flash , program , nv , nv_ram , nvram , mac , mac_address , address , network , volatile , save , store  
Alban edited for word wrapping.

Message Edited by Alban on 2007-01-31 08:44 PM