Hi, Alban -
You wrote:
We are getting there. I can feel it
Well, it seems we are there. I think I have finally figured this thing out. In case anyone else is having the same problem writing to Flash I am including the code that works for me. The dereferenced variables MyValue1 and MyValue2 are displayed with the correct values in the debugger using the P&E Multilink. Still, I haven't figured out how to store negative values. I guess I would just have to split the value into two words.
Sorry the listing is somewhat long for a forum msg. Also note that in my app I don't need Flash_Write_block or Flash_Erase_Block so they have been dropped from flash.c. Finally, I have used the variable name far_address but it is not cast as far.
Dan
The code (most of it):
/* main.c */
#include <hidef.h> /* common defines and macros */
#include <mc9s12c32.h> /* derivative information */
#include "flash.h" /* defines for the FLASHEE routines */
#define PAGE 0x3E0000
#pragma CODE_SEG DEFAULT
#pragma LINK_INFO DERIVATIVE "mc9s12c32"
#pragma MESSAGE DISABLE C1860 //Pointer conversion: Possible loss of data
void main(void) {
// EnableInterrupts;
volatile signed char rval1, rval2, rval3, rval4;
volatile unsigned int myvalue1, myvalue2;
Flash_Init(8000);
rval1=Flash_Erase_Sector((unsigned int *)0x4000);
rval2=Flash_Write_Word((unsigned int *)0x4000,0xABCD);
myvalue1 = (*(volatile unsigned int*)0x4000);
rval3=Flash_Write_Word((unsigned int *)0x4002,0x4321);
myvalue2 = (*(volatile unsigned int*)0x4002);
rval4=Flash_Erase_Sector((unsigned int *)0x4000);
for( ; ; ) {} /* wait forever */
}
#pragma MESSAGE DEFAULT C1860 // Pointer conversion: Possible loss of data
/*******************************************************************
* Freescale
*
* DESCRIPTION: Header file for S12 single array Flash routines
* SOURCE: flash.h
* COPYRIGHT: © 04/2004 Made in the USA
* AUTHOR: rat579
* REV. HISTORY: (none)
*
*******************************************************************/
#ifndef FLASH_H /* Prevent duplicated includes */
#define FLASH_H
/* Functions from flash.c */
void Flash_Init(unsigned long oscclk);
signed char Flash_Write_Word(unsigned int *address, unsigned int data);
signed char Flash_Erase_Sector(unsigned int *far_address);
signed char Flash_Write_Block(unsigned int *address_source,\
unsigned int *far_address_destination,\
unsigned int count);
signed char Flash_Erase_Block(unsigned int *start_address,\
unsigned int *end_address);
/* Error codes */
#define Flash_Odd_Access -1
#define Flash_Not_Erased -2
#define Access_Error -3
#define Protection_Error -4
#define Not_StartofSector_Error -5
#endif /*FLASH_H*/
/*******************************************************************
*
* DESCRIPTION: S12 single array Flash routines
* SOURCE: flash.c
*
*******************************************************************/
#include "flash.h"
#include <hidef.h> /* common defines and macros */
#include <mc9s12c32.h> /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12c32"
#define Flash_Sector_Size 0x200 /* must be modified for particular device */
extern DoOnStack(unsigned int* address);
#pragma MESSAGE DISABLE C1860 //Pointer conversion: Possible loss of data
//*****************************************************************************
//* Function Name : Flash_Init
//* Description : Initialize Flash NVM for HC9S12 by programming
//* FCLKDIV based on passed oscillator frequency, then
//* uprotect the array, and finally ensure PVIOL and
//* ACCERR are cleared by writing to them.
//*
//*****************************************************************************
void Flash_Init(unsigned long oscclk)
{
unsigned char fclk_val;
/* Next, initialize FCLKDIV register to ensure we can program/erase */
if (oscclk >= 12000) {
fclk_val = oscclk/8/200 - 1; /* FDIV8 set since above 12MHz clock */
FCLKDIV |= fclk_val | FCLKDIV_PRDIV8_MASK;
}
else
{
fclk_val = oscclk/180 - 1;
FCLKDIV |= fclk_val;
}
// FPROT = 0xFF; /* Disable all protection (only in special modes)*/
FPROT = 0x18; /* Disable protection for 0x4000 - 0x4FFF (only in special modes)*/
FSTAT |= (FSTAT_PVIOL|FSTAT_ACCERR);/* Clear any errors */
}
//*****************************************************************************
//* Function Name : Flash_Write_Word
//* Description : Program a given Flash location using address and data
//* passed from calling function.
//*
//*****************************************************************************
signed char Flash_Write_Word(unsigned int *far_address,unsigned int data)
{
unsigned int *address;
address = (unsigned int *)far_address; // strip page off
FSTAT = FSTAT_ACCERR | FSTAT_PVIOL;
if((unsigned int)address & 0x0001) {return Flash_Odd_Access;} // Aligned word?
if(*far_address != 0xFFFF) {return Flash_Not_Erased;} // Is it erased?
// FCNFG = 0x00;
(*far_address) = data; // Store desired data to address being programmed
FCMD = 0x20; // Store programming command in FCMD
(void)DoOnStack(far_address);
if (FSTAT_ACCERR) {return Access_Error;}
if (FSTAT_PVIOL) {return Protection_Error;}
return 1;
}
//*****************************************************************************
//* Function Name : Flash_Erase_Sector
//* Description : Erases a given Flash sector using address
//* passed from calling function.
//*
//*****************************************************************************
signed char Flash_Erase_Sector(unsigned int *far_address)
{
unsigned int *address;
address = (unsigned int *)far_address; // strip page off
if((unsigned int)address & 0x0001) {return Flash_Odd_Access;} // Aligned word?
if((unsigned int)address % Flash_Sector_Size !=0) {return Not_StartofSector_Error;}
FCNFG = 0x00;
FSTAT = (FSTAT_ACCERR | FSTAT_PVIOL); // clear errors
(*far_address) = 0xFFFF; /* Dummy store to page to be erased */
FCMD=0x40;
(void)DoOnStack(far_address);
if (FSTAT_ACCERR) {return Access_Error;}
if (FSTAT_PVIOL) {return Protection_Error;}
return 1;
}
#pragma MESSAGE DEFAULT C1860 // Pointer conversion: Possible loss of data
;*******************************************************************
;*
;* DESCRIPTION: S12 Flash Asm Routines
;* SOURCE: Do_On_Stack.asm
;*
;*******************************************************************/
;*****************************************************************************
; Local defines
;*****************************************************************************
CBEIF EQU $80
FSTAT EQU $105
FCMD EQU $106
CCIF EQU $40
PAGE_ADDR EQU $30
xdef DoOnStack
;*********************************************************************
;* DoOnStack - copy SpSub onto stack and call it (see also SpSub)
;* De-allocates the stack space used by SpSub after returning from it.
;* Allows final steps in a flash prog/erase command to execute out
;* of RAM (on stack) while flash is out of the memory map
;* This routine can be used for flash word-program or erase commands
;*
;* Calling Convention:
;* jsr DoOnStack
;*
;********************************************************************
DoOnStack:
pshx ;save IX
ldx #SpSubEnd-2 ;point at last word to move to stack
SpmoveLoop: ldd 2,x- ;read from flash
pshd ;move onto stack
cpx #SpSub-2 ;past end?
bne SpmoveLoop ;loop till whole sub on stack
tfr sp,x ;point to sub on stack
ldaa #CBEIF ;preload mask to register command
;call 0,x,00 ;execute the sub on the stack
jsr ,x ;execute the sub on the stack
leas SpSubEnd-SpSub,sp ;de-allocate space used by sub
ldaa FSTAT ;get result of operation
anda #$30 ;and mask all but PVIOL or ACCERR
pulx ;restore IX
rts ;to flash where DoOnStack was called
;*********************************************************************
;* SpSub - register flash command and wait for Flash CCIF
;* this subroutine is copied onto the stack before executing
;* because you can't execute out of flash while a flash command is
;* in progress (see DoOnStack to see how this is used)
;*
;* Note: must be even # of bytes!
;*
;*********************************************************************
EVEN ;Make code start word aliened
SpSub:
tfr ccr,b ;get copy of ccr
orcc #$10 ;disable interrupts
staa FSTAT ;[PwO] register command
nop ;[O] wait min 4~ from w cycle to r
nop ;[O]
nop ;[O]
brclr FSTAT,CCIF,* ;[rfPPP] wait for queued commands to finish
tfr b,ccr ;restore ccr and int condition
rts ;back into DoOnStack in flash
SpSubEnd: