0xFFFF |=====================
|XXXXXXXXXXXXXXXXXXXXX
| not addressable
0x8200 |XXXXXXXXXXXXXXXXXXXXX
|=====================
0x81FF |
|
| boot loader
|
0x8000 |
|=====================
0x7FFF |XXXXXXXXXXXXXXXXXXXXX
| not addressable
0x1000 |XXXXXXXXXXXXXXXXXXXXX
4kBytes |=====================
0x0FFF | \
| |
| 3.75 kBytes |
| |
0x0100 | |
256bytes|===================== |
0x00ff | || | ERAM,
| IRAM || SFR |== program/data mem
| || | accessible w/
| indirect|| direct | movc, movx
| adressin|| addressing |
| only || only |
0x0080 | || |
128bytes|===================== |
0x007F | | \
| | |
| variable allocation | |
| | |== direct and indirect
| --stack-after-data | | addressing
| (sdcc) | |
0x0030 | | |
|===================== | |
0x002F | | |
| | |
| bit addressable | |
| space | |
| (bit addresses | |
| 0x00-0x7F) | |
0x0020 | | |
|===================== | |
0x001F | R7 | |
| - register bank 3 | |
0x0018 | R0 | |
|--------------------- | |
0x0017 | R7 | |
| - register bank 2 | |
0x0010 | R0 | |
|--------------------- | |
0x000F | R7 | |
| - register bank 1 | |
0x0008 | R0 | |
|--------------------- | |
0x0007 | R7 | |
| - register bank 0 | |
0x0000 | R0 | |
|===================== / /
mov a, #0x20 ; a = x20direct addressing
mov a, 0x20 ; a = contents of x20indirect addressing
mov a, @R1 ; a = contents of address in R1external direct addressing
movx a, @DPTR ; a = contents of 16bit address pointed by DPTR movx @DPTR, a ; contents of 16bit address pointed by DPTR = a e.g.: read 0x0FED: mov DPTR, #0x0FED movx a, @DPTRexternal indirect addressing
movx a, @R1 ; read indirect R1 address movx @R1, a ; write to indirect R1 addresscode indirect addressing
movc a, @A+DPTR movc a, @A+PC
the stackpointer SP has a resetvalue of 0x07, that means the first push
command will write to 0x08, the R0 register of bank1, the second push
will wirte to 0x09.
To be safe the SP should be initializes by SW to 0x2F (or the highest
used bit-addressable register).
;--------------------------------------------------------
.area area_address0 (DATA)
mov SP, #0x2F; stack grows after bit area
ljmp start
;--------------------------------------------------------
; our main code lies from 0x0100 on
;--------------------------------------------------------
.area area_0x0100 (REL,CON,CODE)
;--------------------------------------------------------
start:
...
all InterruptServiceRoutines MUST push and pop PSW ! This is the statusword and it is unlikely that the statusword remains the same during interrupt processing. IE 0xA8 interrupt enable register IP 0xB8 interrupt priority register
... | |
... | |
... | |
N+1: | Second byte of user program, |
| goes into ERAM at 0x0001 |
N: | First byte of user program, |
| goes into ERAM at 0x0000 |
... | |
... | |
... | ignored data |
... | |
... | |
2: | Nr of 256 byte blocks in user program | -> 0x10 -> 4kB
| (includes block 0 that is not full) |
1: | offset to start of user program (N) | -> 0x03
0: | 0 | 0 | 0 | 0 | SPEED | XO_FREQ[2..0] | -> 0x04 -> 20 MHz
SPEED: EEPROM max. speed
0 : 1 MHz
1 : 0.5 MHz
XO_FREQ: crystal oscillator frequency
000 = 4MHz
001 = 8MHz
010 = 12MHz
011 = 16MHz
100 = 20MHz
| 0x80 | P0 |
SP | DPL0 | DPH0 | DPL1 | DPH1 | DPS | PCON | 0x87 |
| 0x88 | TCON TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 |
TMOD | TL0 | TL1 | TH0 | TH1 | CKCON | SPC_FNC | 0x8F |
| 0x90 | P1 - - - - P1_3 P1_2 P1_1 P1_0 |
EXIF | MPAGE | P0_DRV | P0_DIR | P0_ALT | P1_DIR | P1_ALT | 0x97 |
| 0x98 | SCON SM0 SM1 SM2 REN TB8 RB8 TI RI |
SBUF | 0x9F | ||||||
| 0xA0 | P2 AM CD DR/TRC_CE CE EOC/TX_EN RACSN SBMISO SBMOSI SBSCK |
0xA7 | |||||||
| 0xA8 | IE EA 0 ET2 ES ET1 EX1 ET0 EX0 |
PWMCON | PWMDUTY | REGX_MSB | REGX_LSB | REGX_CTRL | 0xAF | ||
| 0xB0 | RSTREAS | SPI_DATA | SPI_CTRL | SPICLK | TICK_DV | CK_CTRL | 0xB7 | ||
| 0xB8 | IP 1 0 PT2 PS PT1 PX1 PT0 PX0 |
CKLFCON | 0xBF | ||||||
| 0xC0 | 0xC7 | ||||||||
| 0xC8 | T2CON TF2 EXF2 RCLK TCLK EXEN2 TR2 C/T2 CP/RL2 |
RCAP2L | RCAP2H | TL2 | TH2 | 0xCF | |||
| 0xD0 | PSW CY AC F0 RS1 RS0 OV F1 P |
0xD7 | |||||||
| 0xD8 | EICON - 1 0 0 WDTI 0 0 0 |
0xDF | |||||||
| 0xE0 | ACC |
0xE7 | |||||||
| 0xE8 | EIE 1 1 1 EWDI EX5 EX4 EX3 EX2 |
0xEF | |||||||
| 0xF0 | B |
0xF7 | |||||||
| 0xF8 | EIP 1 1 1 PWDI PX5 PX4 PX3 PX2 |
HWREV | 0xFF |
| I/O port SFRs |
| control SFRs |
| other SFRs |
| bit addressable SFRs all SFRs dividable by 8 are bit adressable |
Register Addr Reset Description ACC 0xE0 0x00 Accumulator register B 0xF0 0x00 B-register CK_CTRL 0xB6 0x00 Table 51, page 58 CKCON 0x8E 0x01 Table 67, page 78 CKLFCON 0xBF 0x27 Table 43 on page 51 DPH0 0x83 0x00 ch.18.5, page 68 DPH1 0x85 0x00 ch.18.5, page 68 DPL0 0x82 0x00 ch.18.5, page 68 DPL1 0x84 0x00 ch.18.5, page 68 DPS 0x86 0x00 ch.18.5, page 68 EICON 0xD8 0x40 Table 40, page 47 EIE 0xE8 0xE0 Table 41, page 47 EIP 0xF8 0xE0 Table 42, page 48 EXIF 0x91 0x08 Table 39, page 47 HWREV 0xFE 0x00 read only hardware revision no IE 0xA8 0x00 interrupt enable Table 37, page 46 IP 0xB8 0x80 interrupt priority Table 38, page 46 MPAGE 0x92 0x00 do not use P0 0x80 0xFF Table 10, page 15 P0_ALT 0x95 0x00 Table 10, page 15 P0_DIR 0x94 0xFF Table 10, page 15 P0_DRV 0x93 0x00 Table 10, page 15 P1 0x90 0xFF Table 12, page 16 P1_ALT 0x97 0x00 Table 12, page 16 P1_DIR 0x96 0xF4 Table 12, page 16 P2 0xA0 0x08 Table 15, page 19 PCON 0x87 0x30 Table 49, page 57 PSW 0xD0 0x00 Table 63, page 72 PWMCON 0xA9 0x00 Table 35, page 44 PWMDUTY 0xAA 0x00 Table 35, page 44 RCAP2H 0xCB 0x00 ch.18.8.3.3, page 80 RCAP2L 0xCA 0x00 ch.18.8.3.3, page 80 REGX_CTRL 0xAD 0x00 Table 45, page 54 REGX_LSB 0xAC 0x00 Table 45, page 54 REGX_MSB 0xAB 0x00 Table 45, page 54 RSTREAS 0xB1 0x02 Table 48, page 56 SBUF 0x99 0x00 ch.18.9, page 81 SCON 0x98 0x00 Table 71, page 82 SP 0x81 0x07 Stack pointer SPC_FNC 0x8F 0x00 do not use SPI_CTRL 0xB3 0x00 Table 33, page 43 SPI_DATA 0xB2 0x00 Table 33, page 43 SPICLK 0xB4 0x00 Table 33, page 43 T2CON 0xC8 0x00 Table 68, page 79 TCON 0x88 0x00 Table 66, page 75 TH0 0x8C 0x00 ch.18.8, page 74 TH1 0x8D 0x00 ch.18.8, page 74 TH2 0xCD 0x00 ch.18.8, page 74 TICK_DV 0xB5 0x1D Table 43, page 51 TL0 0x8A 0x00 ch.18.8, page 74 TL1 0x8B 0x00 ch.18.8, page 74 TL2 0xCC 0x00 ch.18.8, page 74 TMOD 0x89 0x00 Table 65, page 74
The SPI interface is made up by 7 registers: STATUS RO ADC_CONFIG RW ADC_DATA RO RF_CONFIG RW TX_ADDR RW TX_DATA RW RX_DATA RO behind most of these registers lies a sequence of up to 32 bytes to be read or written via SPI. What I found missing in the docs is that for full clock speed one needs not only to set XO_DIRECT in CKLFCON: mov CKLFCON,#0xe4 ; - - XOF[5..3] XO_DIRECT UP_CLK_FREQ[1..0] but also configure RF_CONFIG via SPI (byte 9 after RF_CONFIG). Since the documentation somewhat shaky says that the SPI register and CKLFCON should be same, I also set the two MSBs in CKLFCON ... The registers seem to be different, I am not sure if setting CKLFCON has any effect at all.
nRF9E5rev1_1.pdf: In Table 21 the LSB SCON.0 bit is missing, it is the "ring indicator" RI bit, which is set high once a valid byte is received. Must be cleared by SW. nRF9E5rev1_2.pdf nordic found some formerly undocumented bits and docu bugs: - SPEED bit in the EEPROM was messd up - UP_CLK_EN is now known as XO_DIRECT
Note: all ISRs need to push + pop PSW !
Note: SP should be initialzed to 0x2F by SW to be safe
Note: to switch between DPL0/DPH0 and DPL1/DPH1 as active DPTR
use the DPS register bit0 (all other DPS bits have no function)
Note: to use the UART you need to configure SCON,
and timer1 in TCON, and TMOD
Note: MOV A,#20h ; requires 2 instruction cycles
MOV 0xE0,#20h ; requires 3 instruction cycles
Note:
PC cannot be written, but LJMP 0x0123 does the trick,
PC cannot be read, but there's a trick to reveal its value: FIXME