📄 datapage.c
字号:
BRA done
L_NOPAGE:
MOVW 0,SP, 0,Y ;// store the value passed in X (high word)
STD 2,Y ;// store the value passed in D (low word)
done:
PULX ;// restore X register
MOVW 0,SP, 1,+SP ;// move return address
RTS
}
#else /* USE_SEVERAL_PAGES */
__asm {
PSHD ;// save D register
LDAA PAGE_ADDR ;// save page register
LDAB 4,SP ;// load page part of address
STAB PAGE_ADDR ;// set page register
STX 0,Y ;// store the value passed in X
MOVW 0,SP, 2,Y ;// store the value passed in D (low word)
STAA PAGE_ADDR ;// restore page register
PULD ;// restore D register
MOVW 0,SP, 1,+SP ;// move return address
RTS
}
#endif /* USE_SEVERAL_PAGES */
}
/*--------------------------- _FAR_COPY_RC --------------------------------
This runtime routine is used to access paged memory via a runtime function.
It may also be used if the compiler option -Cp is not used with the runtime argument.
Arguments :
- offset part of the source int the X register
- page part of the source in the A register
- offset part of the dest int the Y register
- page part of the dest in the B register
- number of bytes to be copied is defined by the next 2 bytes after the return address.
Result :
- memory area copied
- no registers are saved, i.e. all registers may be destroyed
- all page register still contain the same value as before the call
- the function returns after the constant defining the number of bytes to be copied
stack-structure at the loop-label:
0,SP : destination offset
2,SP : source page
3,SP : destination page
4,SP : source offset
6,SP : points to length to be copied. This function returns after the size
A usual call to this function looks like:
struct Huge src, dest;
; ...
LDX #src
LDAA #PAGE(src)
LDY #dest
LDAB #PAGE(dest)
JSR _FAR_COPY_RC
DC.W sizeof(struct Huge)
; ...
--------------------------- _FAR_COPY_RC ----------------------------------*/
#ifdef __cplusplus
extern "C"
#endif
#pragma NO_ENTRY
#pragma NO_EXIT
#pragma NO_FRAME
void NEAR _FAR_COPY_RC(void) {
#if USE_SEVERAL_PAGES
__asm {
DEX ;// source addr-=1, because loop counter ends at 1
PSHX ;// save source offset
PSHD ;// save both pages
DEY ;// destination addr-=1, because loop counter ends at 1
PSHY ;// save destination offset
LDY 6,SP ;// Load Return address
LDX 2,Y+ ;// Load Size to copy
STY 6,SP ;// Store adjusted return address
loop:
LDD 4,SP ;// load source offset
LEAY D,X ;// calculate actual source address
LDAB 2,SP ;// load source page
__PIC_JSR(_LOAD_FAR_8) ;// load 1 source byte
PSHB ;// save value
LDD 0+1,SP ;// load destination offset
LEAY D,X ;// calculate actual destination address
PULA ;// restore value
LDAB 3,SP ;// load destination page
__PIC_JSR(_STORE_FAR_8) ;// store one byte
DEX
BNE loop
LEAS 6,SP ;// release stack
_SRET ;// debug info only: This is the last instr of a function with a special return
RTS ;// return
}
#else
__asm {
PSHD ;// store page registers
TFR X,D
PSHY ;// temporary space
LDY 4,SP ;// load return address
ADDD 2,Y+ ;// calculate source end address. Increment return address
STY 4,SP
PULY
PSHD ;// store src end address
LDAB 2,SP ;// reload source page
LDAA PAGE_ADDR ;// save page register
PSHA
loop:
STAB PAGE_ADDR ;// set source page
LDAA 1,X+ ;// load value
MOVB 4,SP, PAGE_ADDR ;// set destination page
STAA 1,Y+
CPX 1,SP
BNE loop
LDAA 5,SP+ ;// restore old page value and release stack
STAA PAGE_ADDR ;// store it into page register
_SRET ;// debug info only: This is the last instr of a function with a special return
RTS
}
#endif
}
/*--------------------------- _FAR_COPY --------------------------------
The _FAR_COPY runtime routine was used to copied large memory blocks in previous compiler releases.
However this release now does use _FAR_COPY_RC instead. The only difference is how the size of
the area to be copied is passed into the function. For _FAR_COPY the size is passed on the stack just
above the return address. _FAR_COPY_RC does expect the return address just after the JSR _FAR_COPY_RC call
in the code of the caller. This allows for denser code calling _FAR_COPY_RC but does also need a slightly
larger runtime routine and it is slightly slower.
The _FAR_COPY routine is here now mainly for compatibility with previous releases.
The current compiler does not use it.
--------------------------- _FAR_COPY ----------------------------------*/
#ifdef __cplusplus
extern "C"
#endif
#pragma NO_ENTRY
#pragma NO_EXIT
#pragma NO_FRAME
void NEAR _FAR_COPY(void) {
#if USE_SEVERAL_PAGES
__asm {
DEX ;// source addr-=1, because loop counter ends at 1
PSHX ;// save source offset
PSHD ;// save both pages
DEY ;// destination addr-=1, because loop counter ends at 1
PSHY ;// save destination offset
LDX 8,SP ;// load counter, assuming counter > 0
loop:
LDD 4,SP ;// load source offset
LEAY D,X ;// calculate actual source address
LDAB 2,SP ;// load source page
__PIC_JSR(_LOAD_FAR_8) ;// load 1 source byte
PSHB ;// save value
LDD 0+1,SP ;// load destination offset
LEAY D,X ;// calculate actual destination address
PULA ;// restore value
LDAB 3,SP ;// load destination page
__PIC_JSR(_STORE_FAR_8) ;// store one byte
DEX
BNE loop
LDX 6,SP ;// load return address
LEAS 10,SP ;// release stack
JMP 0,X ;// return
}
#else
__asm {
PSHD ;// store page registers
TFR X,D
ADDD 4,SP ;// calculate source end address
STD 4,SP
PULB ;// reload source page
LDAA PAGE_ADDR ;// save page register
PSHA
loop:
STAB PAGE_ADDR ;// set source page
LDAA 1,X+ ;// load value
MOVB 1,SP, PAGE_ADDR ;// set destination page
STAA 1,Y+
CPX 4,SP
BNE loop
LDAA 2,SP+ ;// restore old page value and release stack
STAA PAGE_ADDR ;// store it into page register
LDX 4,SP+ ;// release stack and load return address
JMP 0,X ;// return
}
#endif
}
#else /* __HCS12X__ */
/*
The HCS12X knows two different kind of addresses:
- Logical addresses. E.g.
MOVB #page(var),RPAGE
INC var
- Global addresses E.g.
MOVB #page(var),GPAGE
GLDAA var
INCA
GSTAA var
Global addresses are used with G-Load's and G-Store's, logical addresses are used for all the other instructions
and occasions. As HC12's or HCS12's do not have the G-Load and G-Store instructions,
global addresses are not used with these processor families.
They are only used with HCS12X chips (and maybe future ones deriving from a HCS12X).
Logical and Global addresses can point to the same object, however the global and logical address of an object
are different for most objects (actually for all except the registers from 0 to 0x7FF).
Therefore the compiler needs to transform in between them.
HCS12X Pointer types:
The following are logical addresses:
- all 16 bit pointers
- "char* __near": always.
- "char *" in the small and banked memory model
- 24 bit dpage, epage, ppage or rpage pointers (*1) (note: the first HCS12X compilers may not support these pointer types)
- "char *__dpage": Note this type only exists for
orthogonality with the HC12 A4 chip which has a DPAGE reg.
It does not apply to the HCS12X.
- "char *__epage": 24 bit pointer using the EPAGE register
- "char *__ppage": 24 bit pointer using the PPAGE register.
As the PPAGE is also used for BANKED code,
using this pointer type is only legal from non banked code.
- "char *__rpage": 24 bit pointer using the RPAGE register
The following are global addresses:
"char*": in the large memory model (only HCS12X)
"char* __far": always for HCS12X.
(*1): For the HC12 and HCS12 "char* __far" and "char*" in the large memory model are also logical.
Some notes for the HC12/HCS12 programmers.
The address of a far object for a HC12 and for a HCS12X is different, even if they are at the same place in the memory map.
For the HC12, a far address is using the logical addresses, for the HCS12X however, far addresses are using global addresses.
This does cause troubles for the unaware!
The conversion routines implemented in this file support the special HCS12XE RAM mapping (when RAMHM is set).
To enable this mapping compile this file with the "-MapRAM" compiler option.
HCS12X Logical Memory map
Logical Addresses Used for shadowed at page register Global Address
0x000000 .. 0x0007FF Peripheral Registers Not Paged 0x000000
0x??0800 .. 0x??0BFF Paged EEPROM EPAGE (@0x17) 0x100000+EPAGE*0x0400
0x000C00 .. 0x000FFF Non Paged EEPROM 0xFF0800..0xFF0FFF Not Paged 0x13FC00
0x??1000 .. 0x??1FFF Paged RAM RPAGE (@0x16) 0x000000+RPAGE*0x1000
0x002000 .. 0x003FFF Non Paged RAM 0xFE1000..0xFF1FFF Not Paged 0x0FE000
0x004000 .. 0x007FFF Non Paged FLASH 0xFC8000..0xFCBFFF Not Paged 0x7F4000
0x??8000 .. 0x00BFFF Paged FLASH PPAGE (@0x30) 0x400000+PPAGE*0x4000
0x00C000 .. 0x00FFFF Non Paged FLASH 0xFF8000..0xFFBFFF Not Paged 0x7FC000
NA: Not Applicable
HCS12X Global Memory map
Global Addresses Used for Logical mapped at
0x000000 .. 0x0007FF Peripheral Registers 0x000000 .. 0x0007FF
0x000800 .. 0x000FFF DMA registers Not mapped
0x001000 .. 0x0FFFFF RAM 0x??1000 .. 0x??1FFF
0x0FE000 .. 0x0FFFFF RAM, Log non paged 0x002000 .. 0x003FFF
0x100000 .. 0x13FFFF EEPROM 0x??0800 .. 0x??0BFF
0x13FC00 .. 0x13FFFF EEPROM non paged 0x000C00 .. 0x000FFF
0x140000 .. 0x3FFFFF External Space Not mapped
0x400000 .. 0x7FFFFF FLASH 0x??8000 .. 0x??BFFF
0x7F4000 .. 0x7F7FFF FLASH, Log non paged 0x004000 .. 0x007FFF
0x7FC000 .. 0x7FFFFF FLASH, Log non paged 0x00C000 .. 0x00FFFF
HCS12X Logical Memory map (RAM mapped)
Logical Addresses Used for shadowed at page register Global Address
0x000000 .. 0x0007FF Peripheral Registers Not Paged 0x000000
0x??0800 .. 0x??0BFF Paged EEPROM EPAGE (@0x17) 0x100000+EPAGE*0x0400
0x000C00 .. 0x000FFF Non Paged EEPROM 0xFF0800..0xFF0FFF Not Paged 0x13FC00
0x??1000 .. 0x??1FFF Paged RAM RPAGE (@0x16) 0x000000+RPAGE*0x1000
0x002000 .. 0x003FFF Non Paged RAM 0xFE1000..0xFF1FFF Not Paged 0x0FE000
0x004000 .. 0x007FFF Non Paged RAM 0xFA1000..0xFD1FFF Not Paged 0FC000
0x??8000 .. 0x00BFFF Paged FLASH PPAGE (@0x30) 0x400000+PPAGE*0x4000
0x00C000 .. 0x00FFFF Non Paged FLASH 0xFF8000..0xFFBFFF Not Paged 0x7FC000
NA: Not Applicable
HCS12X Global Memory map
Global Addresses Used for Logical mapped at
0x000000 .. 0x0007FF Peripheral Registers 0x000000 .. 0x0007FF
0x000800 .. 0x000FFF DMA registers Not mapped
0x001000 .. 0x0FFFFF RAM 0x??1000 .. 0x??1FFF
0x0FA000 .. 0x0FFFFF RAM, Log non paged 0x002000 .. 0x007FFF
0x100000 .. 0x13FFFF EEPROM 0x??0800 .. 0x??0BFF
0x13FC00 .. 0x13FFFF EEPROM non paged 0x000C00 .. 0x000FFF
0x140000 .. 0x3FFFFF External Space Not mapped
0x400000 .. 0x7FFFFF FLASH 0x??8000 .. 0x??BFFF
0x7F4000 .. 0x7F7FFF FLASH, Log non paged Not mapped
0x7FC000 .. 0x7FFFFF FLASH, Log non paged 0x00C000 .. 0x00FFFF
How to read this table:
For logical addresses, the lower 16 bits of the address do determine in which area the address is,
if this address is paged, then this entry also controls and which of the EPAGE, PPAGE or RPAGE
page register is controlling the bits 16 to 23 of the address.
For global addresses, the bits 16 to 23 have to be in the GPAGE register and the lower 16 bits
have to be used with the special G load or store instructions (e.g. GLDAA).
As example the logical address 0x123456 is invalid. Because its lower bits 0x3456 are in a
non paged area, so the page 0x12 does not exist.
The address 0xFE1020 however does exist. Do access it, the RPAGE has to contain 0xFE and the
offset 0x1020 has to be used.
ORG $7000
MOVB #0xFE, 0x16 ; RPAGE
LDAA 0x1020 ; reads at the logical address 0xFE1020
Because the last two RAM pages are also accessible directly from 0x2000 to 0x3FFF, the
following shorter code does read the same memory location:
ORG $7000
LDAA 0x2020 ; reads at the logical address 0x2020
; which maps to the same memory as 0xFE1020
This memory location now also has a global address. For logical 0xFE1020 the global address is 0x0FE020.
So the following code does once more access the same memory location:
ORG $7000
MOVB #0x0F, 0x10 ; GPAGE
LDAA 0xE020 ; reads at the global address 0x0FE020
; which maps to the same memory as the logical addr. 0xFE1020
Therefore every memory location for the HCS12X has up to 3 different addresses.
Up to two logical and one global.
Notes.
- Not every address has a logical equivalent. The external space is only available in the global address space.
The DMA Registers are also only addressable with global addresses.
- The PPAGE can only be set if the code is outside of the 0x8000 to 0xBFFF range.
If not, the next code fetch will be from the new wrong PPAGE value.
- Inside of the paged area, the highest pages are allocated first. So all HCS12X's do have the FF pages
(if they have this memory type at all).
- For RPAGE, the value 0 is illegal. Otherwise the global addresses would overlap with the registers.
This has the implication that the logical address 0x001000 is strictly seen not valid.
*/
#if __OPTION_ACTIVE__("-MapRAM")
#define __HCS12XE_RAMHM_SET__
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -