Forum : ST7/STM8
Original Post
| Post Information | Post |
|---|---|
|
March 27, 2012 - 12:17am
|
Hello, I am trying to write the far code space on an STM8L151C8 (address 0x10000 and up). To do this, I have a flash program block routine that executes out of RAM, which programs a single 128 byte flash block at a time. The problem is that in order to write to far addresses, I have to use far pointers and 32-bit variables, which results in |
Hi,
Your post looks unfinished, but I got the idea: The far code access is very poor on the STM8. This is because there are not enough registers to hold both 24-bit source and destination addresses when performing object-to-object copies.
Here is an hidden treasure, an assembly subroutine that will help you a lot:
;----------------------------------------------------------------------------- ; Function: memcpyfar ;----------------------------------------------------------------------------- ; Purpose: Performs a memcpy with far pointers (24 bits). ; Works on STM8 only (ST7 not possible). ;----------------------------------------------------------------------------- ; C prototype: ; unsigned long memcpyfar(unsigned long dest, /* 32-bit address */ ; unsigned long src, /* 32-bit address */ ; unsigned short num); /* 16-bit length */ ;----------------------------------------------------------------------------- ; WARNING: The data must be INSECTION (cannot cross 64kB boundaries). ;----------------------------------------------------------------------------- $MODESTM8 ; Pseudo-registers declaration EXTRN DATA0(?BH, ?BL, ?CH, ?CL) PUBLIC ?memcpyfar ;----------------------------------------------------------------------------- ; User-defined macro that specifies the CALL/RET model. ;----------------------------------------------------------------------------- LARGE EQU 0 ; Use 1 in RCSTM8 LARGE mode ;----------------------------------------------------------------------------- ; Macros to adapt Library function calls to LARGE model ;----------------------------------------------------------------------------- $IF(LARGE==1) BIBRET MACRO RETF ENDM BIBCALL MACRO address CALLF address ENDM BIBJP MACRO address JPF address ENDM $ELSE BIBRET MACRO RET ENDM BIBCALL MACRO address CALL address ENDM BIBJP MACRO address JP address ENDM $ENDIF ;----------------------------------------------------------------------------- ; Equate definition for the Large model, with 1 byte stack offset (CALLF) ;----------------------------------------------------------------------------- $IF(LARGE==1) STKOFF EQU 1 $ELSE STKOFF EQU 0 $ENDIF ;----------------------------------------------------------------------------- ; This 24-bit storage area will hold the source pointer (high byte is ignored) ;----------------------------------------------------------------------------- CSTDLIB_REGISTERS SEGMENT DATA INPAGE0 RSEG CSTDLIB_REGISTERS ?SRC: DS 3 ;----------------------------------------------------------------------------- ; Actual fmemcpy function start ;----------------------------------------------------------------------------- MEMCPYFAR SEGMENT CODE INSECTION0 RSEG MEMCPYFAR ?memcpyfar: ; Copy source pointer into SRC LDW X, (8+STKOFF, SP) LDW ?SRC, X LD A, (10+STKOFF, SP) LD ?SRC+2, A ; Copy destination pointer into BX:CX LDW X, (3+STKOFF, SP) LDW ?BH, X LDW X, (5+STKOFF, SP) LDW ?CH, X ; Load the counter into X LDW X, (11+STKOFF, SP) _loop: DECW X CPLW X ; Check whether X is FFFFh JREQ _end CPLW X ; Restore X's actual value LDF A, ([?SRC.e], X) ; Loading source byte LDF ([?BL.e], X), A ; Copying the byte to destination JRA _loop _end: BIBRET ENDAdd this in a .asm file in your application, then you can call it as follows:
char mystring[] = "The string to copy"; extern unsigned long memcpyfar(unsigned long dest, /* 32-bit address */ unsigned long src, /* 32-bit address */ unsigned short num); /* 16-bit length */ void main( void ) { /* Copy the string to address 01:2345h. This will work ONLY if flash has been unlocked and if executing from RAM */ memcpyfar(0x00012345UL, (unsigned long)mystring, sizeof(mystring) + 1); while ( 1 ); }Using this you will have to copy this function to a specific address in RAM (refer to the RCSTM8 compiler documentation that describes this), then write your inram function that uses this as a helper for efficient copy of bytes to destination RAM.
Best Regards,
Hi Bruno,
Thanks for the response. The forum apparently chopped off half of my post, but I ended up figuring out how to resolve my issue through other posts on this forum.
I basically wrote a flash block program routine that assumes the hi 16-bits of the address stays constant, and the low 16-bits gets incremented to write all 128 bytes of the block. I could do this without invoking any 32-bit variable "helper" functions, and therefore not violating the "must not access flash while programming flash" rule.
Your code looks incredibly useful though. I may have another use for it.
Thank you!
Great job bcoons!