Self writing MCU in code memory for settings on 24FJ64GA004

Started by diebobo, Mar 10, 2023, 06:26 PM

Previous topic - Next topic

diebobo

Hi,

Has anyone got a sample code to store settings within the MCU itself ? The 24FJ64GA004 and family does not have Eprom on board, but since it can reprogram itself via a bootloader it should be able to store some variables in a unused code space right ?

trastikata

Hello,

the entire procedure is described step by step within chapter 4.6.1 at page 46 in the datasheet. 

diebobo

Ahh offcourse, that should have been my starting point..  I just wend for the ready to consume example code thingy :) Thanks..

diebobo

To whoever want to use this function, my code as a starting point for others :

Proc MCU_Code_Read ( Block_Nr As Byte, Offset As Word ), Word
   
    Dim Result_LowByte As Word
    Dim Result_HighByte As Word
   
    Dim Page As Word = 0 ' Alleen page 0 in 24FJ64GA004
    MCU_Code_Read_Offset = Offset + ( Block_Nr * 1024 )

    Asm
        ; Read program memory address 0x012340
        ; Create 24 bit EA for read by loading TBLPAG and W1
        Mov MCU_Code_Read_Page, W0 ; Load TBLPAG register with read address <23:16>
        Mov W0, TBLPAG
        Mov MCU_Code_Read_Offset, W1 ; Load W1 with read address <15:0>
        ; Read data from program memory into W registers
        TblrdL.B [W1++], w2 ; W2 contains low byte
        TblrdL.B [W1--], w3 ; W3 contains middle byte
        TblrdH.B [W1], w4 ; W4 contains high byte
        Mov w2, MCU_Code_Read_Result_LowByte
        Mov w3, MCU_Code_Read_Result_HighByte
    ;  Mov w4, w44 ; Je kan deze ook nog lezen voor byte extra, aangezien locatie 24 bits is ipv 16. Maar slechts 2 bytes uitlezen = word = makkelijker dan 24 bits opsplitsen. Toch ruimte zat.
    EndAsm

    Result.LowByte = Result_LowByte
    Result.HighByte = Result_HighByte
   
EndProc

Proc MCU_Code_Erase ( Block_Nr As Byte )

    Dim Page As Word = 0 ' Alleen page 0 in 24FJ64GA004
    Dim Offset As Word

    MCU_Code_Erase_Offset = Block_Nr * 1024 ' Erasen gaat per 8 rows van 64 instructies ? Komt uit op elke 1024 addressen

    Asm
        ; Set up NVMCON for block erase operation
        Mov #0x4042, W0 ;
        Mov W0, NVMCON ; Initialize NVMCON
        ; Init pointer to row to be ERASED
        Mov MCU_Code_Erase_Page, W0 ;
        Mov W0, TBLPAG ; Initialize PM Page Boundary SFR
        Mov MCU_Code_Erase_Offset, W0 ; Initialize in-page EA[15:0] pointer
        TblwtL W0, [W0] ; Set base address of erase block
        Disi #5 ; Block all interrupts with priority <7
        ; for next 5 instructions
        Mov #0x55, W0
        Mov W0, NVMKEY ; Write the 55 key
        Mov #0xAA, W1 ;
        Mov W1, NVMKEY ; Write the AA key
        Bset NVMCON, #15 ; Start the erase sequence
        Nop ; Insert two NOPs after the erase
        Nop ; command is asserted

    EndAsm
EndProc

Proc MCU_Code_Write ( Block_Nr As Byte, Offset As Word, Value As Word )
   
    Dim Page As Word = 0 ' Alleen page 0 in 24FJ64GA004
    MCU_Code_Write_Offset = Offset + ( Block_Nr * 1024 )
    Asm
        ; Setup a pointer to data Program Memory
        Mov MCU_Code_Write_Page, W0 ;
        Mov W0, TBLPAG ;Initialize PM Page Boundary SFR
        Mov MCU_Code_Write_Offset, W0 ;Initialize a register with program memory address
        Mov MCU_Code_Write_Value, W2 ;
        Mov #0, W3 ;
        TblwtL W2, [W0] ; Write PM low word into program latch
        TblwtH W3, [W0++] ; Write PM high byte into program latch
        ; Setup NVMCON for programming one word to data Program Memory
        Mov #0x4003, W0 ;
        Mov W0, NVMCON ; Set NVMOP bits to 0011
        Disi #5 ; Disable interrupts while the KEY sequence is written
        Mov #0x55, W0 ; Write the key sequence
        Mov W0, NVMKEY
        Mov #0xAA, W0
        Mov W0, NVMKEY
        Bset NVMCON, #15 ; Start the write cycle
        Nop ; 2 NOPs required after setting WR
        Nop ;
    EndAsm

EndProc   

- MCU_Code_Read, read a word value
- MCU_Code_Erase, erase a block . Required before a write action can be succesfull done.
- MCU_Code_Write, write word value on specifiek spot.

Remind, whenever you program your MCU with programmer any write actions done previously in code is undone since the programmer does prob. a full erase of device. So this is mostly ( for me ) usefull with reflashing with a bootloader. Since in my case tinybootloader isn't erasing block 40 when reflashing the MCU. So this is a spot that is persistant. Unless you create a program that required 95% + program space then it's gone also :)

Your millage may vary...