📄 datapage.c
字号:
This does cause troubles for the unaware!
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
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.
*/
/*--------------------------- pointer conversion operations -------------------------------*/
/*--------------------------- _CONV_GLOBAL_TO_LOGICAL --------------------------------
Convert 24 bit logical to 24 bit global pointer
("char*__far" to "char*__gpage")
Arguments :
- B : page part of global address
- X : 16 offset part of global address
Postcondition :
- B == page of returned logical address
- X == offset of returned logical address
- Y remains unchanged
- A remains unchanged
*/
/*--------------------------- Convert 24 bit global to 24 bit logical pointer ----------------------------------*/
/* B:X = Logical(B:X) */
#ifdef __cplusplus
extern "C"
#endif
#pragma NO_FRAME
#pragma NO_ENTRY
#pragma NO_EXIT
void NEAR _CONV_GLOBAL_TO_LOGICAL(void) {
__asm {
CMPB #0x40 ;// flash (0x400000..0x7FFFFF) or not?
BLO Below400000
// from 0x400000 to 0x7FFFFF
CMPB #0x7F ;// check for Unpaged areas 0x7FC000..0x7FFFFF and 0x7F4000..0x7F7FFF
BNE PAGED_FLASH_AREA
BITX #0x4000
BEQ PAGED_FLASH_AREA
// from 0x7F4000 to 0x7F7FFF or 0x7FC000 to 0x7FFFFF
;// Note: offset in X is already OK.
CLRB ;// logical page == 0
RTS
PAGED_FLASH_AREA: ;// paged flash. Map to 0x8000..0xBFFF
// from 0x400000 to 0x7F3FFF or 0x7F8000 to 0x7FBFFF
LSLX ; // shift 24 bit address 2 bits to the left to get correct page in B
ROLB
LSLX
ROLB
LSRX ; // shift back to get offset from 0x8000 to 0xBFFF
SEC
RORX
RTS ;// done
Below400000:
// from 0x000000 to 0x3FFFFF
#if 0 /* How should we handle mapping to External Space. There is no logical equivalent. This is an error case! */
CMPB #0x14 ;// check if above 0x140000. If so, its in the external space
BLO Below140000
ERROR !!!! ;// this mapping is not possible! What should we do?
RTS
Below140000:
// from 0x000000 to 0x13FFFF
#endif
CMPB #0x10 ;// if >= 0x100000 it's EEPROM
BLO Below100000
// from 0x100000 to 0x13FFFF (or 0x3FFFFF)
CMPB #0x13 ;// check if its is in the non paged EEPROM area at 0x13FC00..0x13FFFF
BLO Below13FC00
CPX #0xFC00
BLO Below13FC00
// from 0x13FC00 to 0x13FFFF (or 0x3FFFFF)
LEAX 0x1000,X ;// same as SUBX #0xF000 // map from 0xFC00 to 0x0C00
CLRB
RTS
Below13FC00:
// from 0x100000 to 0x13FBFF
PSHA
TFR XH,A ;// calculate logical page
EXG A,B
LSRD
LSRD
PULA
ANDX #0x03FF
LEAX 0x0800,X ;// same as ORX #0x0800
RTS
Below100000:
// from 0x000000 to 0x0FFFFF
TSTB
BNE RAM_AREA
CPX #0x1000
BLO Below001000
RAM_AREA:
// from 0x001000 to 0x0FFFFF
CMPB #0x0F
BNE PagedRAM_AREA
CPX #0xE000
BLO PagedRAM_AREA
// from 0x0FE000 to 0x0FFFFF
SUBX #(0xE000-0x2000) ;// map 0xE000 to 0x2000
CLRB ;// Page is 0
RTS
PagedRAM_AREA:
// from 0x001000 to 0x0FDFFF
PSHA
TFR XH, A ;// calculate logical page
EXG A,B
LSRD
LSRD
LSRD
LSRD
PULA
ANDX #0x0FFF
LEAX 0x1000,X ;// same as ORX #0x1000
RTS
Below001000:
// from 0x000000 to 0x000FFF
#if 0
CMPA #0x08
BLO Below000800
// from 0x000800 to 0x000FFF
// ??? DMA Regs?
RTS
Below000800:
// from 0x000000 to 0x0007FF
#endif
CLRB
RTS
}
}
/*--------------------------- _CONV_GLOBAL_TO_NEAR --------------------------------
Convert 24 bit global to 16 bit logical pointer
("char*__far" to "char*")
Arguments :
- B : page part of global address
- X : 16 offset part of global address
Postcondition :
- B is undefined
- A remains unchanged
- X == offset of returned logical address
- Y remains unchanged
*/
/*--------------------------- Convert 24 bit global to 16 bit logical pointer ----------------------------------*/
/* X = Logical(B:X) */
#ifdef __cplusplus
extern "C"
#endif
#define _REUSE_CONV_GLOBAL_TO_LOGICAL 1
#pragma NO_FRAME
#pragma NO_ENTRY
#pragma NO_EXIT
void NEAR _CONV_GLOBAL_TO_NEAR(void){
#if _REUSE_CONV_GLOBAL_TO_LOGICAL /* do we want an optimized version? */
__asm JMP _CONV_GLOBAL_TO_LOGICAL; /* offset for NEAR is same as for LOGICAL. */
#else
__asm {
CMPB #0x40 ;// flash (0x400000..0x7FFFFF) or not?
BLO Below400000
// from 0x400000 to 0x7FFFFF
CMPB #0x7F ;// check for Unpaged areas 0x7FC000..0x7FFFFF and 0x7F4000..0x7F7FFF
BNE PAGED_FLASH_AREA
CPX #0x4000
BLS PAGED_FLASH_AREA
// from 0x7F4000 to 0x7FFFFF
;// note non PAGED flash areas or paged area 0x7F8000..0x7FBFFF which are mapping all correctly
RTS
PAGED_FLASH_AREA: ;// paged flash. Map to 0x8000..0xBFFF
// from 0x400000 to 0x7F3FFF
ANDX #0x3F00 ;// cut to 0.. 0x3FFF
LEAX 0x8000,X ;// same as ORX #0x8000 ;// move to 0x8000..0xBFFF
RTS ;// done
Below400000:
// from 0x000000 to 0x3FFFFF
#if 0 /* How should we handle mapping to External Space. There is no logical equivalent. This is an error case! */
CMPB #0x14 ;// check if above 0x140000. If so, its in the external space
BLO Below140000
ERROR !!!! ;// this mapping is not possible! What should we do?
RTS
Below140000:
// from 0x000000 to 0x13FFFF
#endif
CMPB #0x10 ;// if >= 0x100000 it's EEPROM
BLO Below100000
// from 0x100000 to 0x13FFFF (or 0x3FFFFF)
CMPB #0x13 ;// check if its is in the non paged EEPROM area at 0x13FC00..0x13FFFF
BNE Below13FC00
CPX #0xFC00
BLO Below13FC00
// from 0x13FC00 to 0x13FFFF (or 0x3FFFFF)
SUBX #0xF000 ;// map from 0xFC00 to 0x0C00
RTS
Below13FC00:
// from 0x100000 to 0x13FBFF
ANDX #0x03FF
LEAX 0x800,X ;// same as ORX #0x0800
RTS
Below100000:
// from 0x000000 to 0x0FFFFF
TBNE B,RAM_AREA
CPX #0x1000
BLO Below001000
RAM_AREA:
// from 0x001000 to 0x0FFFFF
CMPB #0x0F
BNE PagedRAM_AREA
CPX #0xE000
BLO PagedRAM_AREA
// from 0x0FE000 to 0x0FFFFF
SUBX #(0xE000-0x2000) ;// map 0xE000 to 0x2000
RTS
PagedRAM_AREA:
// from 0x001000 to 0x0FDFFF
ANDX #0x0FFF
LEAX 0x1000,X ;// same as ORX #0x1000
RTS
Below001000:
// from 0x000000 to 0x000FFF
#if 0
CMPA #0x08
BLO Below000800
// from 0x000800 to 0x000FFF
// ??? DMA Regs?
RTS
Below000800:
// from 0x000000 to 0x0007FF
#endif
RTS
}
#endif
}
/*--------------------------- _CONV_NEAR_TO_GLOBAL --------------------------------
Convert 16 bit logical to 24 bit global pointer
("char*__near" to "char*__far")
Arguments :
- X : 16 bit near pointer
Postcondition :
- B == page of returned global address
- X == offset of returned global address
- Y remains unchanged
- A is unspecified
*/
/*--------------------------- Convert 16 bit logical to 24 bit global pointer ----------------------------------*/
/* B:X = Global(X) */
#ifdef __cplusplus
extern "C"
#endif
#pragma NO_FRAME
#pragma NO_ENTRY
#pragma NO_EXIT
void NEAR _CONV_NEAR_TO_GLOBAL(void){
__asm {
// syntax:
// input 16 bit offset is bit15..bit0
// ppage values: ppage7..ppage0
// epage values: epage7..epage0
// dpage values: dpage7..dpage0
// rpage values: rpage7..rpage0
PSHX ;// D contains bit15..bit0
TFR X,D ;// D is cheaper to shift
LSLD ;// D contains 0 bit14..bit0, C contains bit15
BCC Below8000 ;// bit15 == 0?
// from 0x8000 to 0xFFFF
LSLD ;// D contains 00 bit13..bit0, C contains bit14
BCC BelowC000
LDAB #0x7F
PULX
RTS ;// returns 0b0111 1111 11 bit13...bit0
BelowC000: ;// from 0x8000 to 0xBFFF
TFR D,X
LDAB __PPAGE_ADR__
SEC
RORB
RORX
LSRB
RORX
LEAS 2,SP
RTS ;// returns 0b01 ppage7..ppage0 bit13...bit0
Below8000:
LSLD ;// D contains 00 bit13..bit0, C contains bit14
BCC Below4000
// from 0x4000 to 0x7FFF
LDAB #0x7F
PULX
RTS ;// returns 0b0111 1111 01 bit13...bit0
Below4000:
LSLD ;// D contains 000 bit12..bit0, C contains bit13
BCC Below2000
// from 0x2000 to 0x3FFF
PULX
ADDX #(0xE000-0x2000)
LDAB #0x0F
RTS ;// returns 0b0000 1111 111 bit12...bit0
Below2000:
LSLD ;// D contains 0000 bit11..bit0, C contains bit12
BCC Below1000
// from 0x1000 to 0x1FFF
LDAB __RPAGE_ADR__
LDAA #0x10
MUL
EORB 0,SP
EORB #0x10 ;// clear 1 bit
STAB 0,SP
TFR A,B
PULX
RTS
Below1000:
LSLD ;// D contains 0000 0 bit10..bit0, C contains bit11
BCC Below0800
// from 0x0800 to 0x0FFF
LSLD ;// D contains 0000 00 bit9..bit0, C contains bit10
BCC Below0C00
// from 0x0C00 to 0x0FFF
LDAB #0x13
PULX
ADDX #0xF000
RTS ;// returns 0b0001 0011 1111 11 bit9...bit0
Below0C00:
// from 0x0800 to 0x0BFF
LDAB __RPAGE_ADR__
LDAA #0x04
MUL
EORB 0,SP
EORB #0x08
STAB 0,SP
TFR A,B
ORAB #0b00010000
PULX
RTS
Below0800:
PULX
CLRB
RTS
}
}
/*--------------------------- _CONV_STACK_NEAR_TO_GLOBAL --------------------------------
Convert 16 bit logical of address on the stack 24 bit global pointer
("char*__near" to "char*__far")
Arguments :
- X : 16 bit near pointer
Postcondition :
- B == page of returned global address
- X == offset of returned global address
- Y remains unchanged
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -