Initial version

Tested:
- UART debug output works at 115200 baud (pad S15)
- Jumps to bootloader on watchdog timeout
- Jumps to bootloader when Return is held while plugging in USB
- Jumps to bootloader when UTX/URX lines are shorted
- Measured max GPIO toggling speed is 3MHz
This commit is contained in:
Tobias Diedrich
2021-12-19 16:25:16 +01:00
parent 8378645f00
commit 0bf18ebf6f
3 changed files with 263 additions and 0 deletions
+1
View File
@@ -35,6 +35,7 @@
*.i*86
*.x86_64
*.hex
*.bin
# Debug files
*.dSYM/
+176
View File
@@ -0,0 +1,176 @@
CHIP SN8F2288
//{{SONIX_CODE_OPTION
; Options for Lenovo Compact Keyboard
.Code_Option Fcpu "Fosc/4"
.Code_Option Fslow "Flosc/2"
.Code_Option High_CLK "12M_X'tal"
.Code_Option LVD "LVD_M"
.Code_Option Reset_Pin "P07"
.Code_Option Rst_Length "No"
.Code_Option Security "Enable"
.Code_Option Watch_Dog "Enable"
//}}SONIX_CODE_OPTION
.DATA
_canary_check EQU 0x2880
_flasher EQU 0x2890
UTX EQU P0.6 ; S15
UTTXIRQ EQU INTRQ1.3
URX EQU P0.5 ; S10
S10 EQU P0.5
R6 EQU P1.5
.CODE
ORG 0x0 ; Reset vector
; Jump to bootloader, checks canary and continues execution at 0x10 if found
JMP _canary_check
ORG 0x8 ; Interrupt vector
JMP _flasher
ORG 0x10 ; Bootloader jumps here on successful canary check, start of payload execution
_start:
; Set stack pointer and disable interrupts
MOV A, #7
B0MOV STKP, A
MOV A, #0
B0MOV RBANK, A
; Jump into bootloader if watchdog triggered or undefined reset source
B0BTS1 FNT0
JMP _flasher ; NT0 == 0 => watchdog reset or undefined reason
; Light up the power LED (P5.3/PWM0)
B0BCLR P5.3 ; Set to low level to light up
B0BSET P5M.3 ; Set to output
; DS indicates watchdog may start running before CPU
; Tickle it once so we have a well-defined time left
MOV A, #0x5a
B0MOV WDTR, A
; Set up P0.6/UTX (UART TX)
B0BSET P0UR.6 ; Enable pull-up (UART idle is high)
B0BCLR P0M.6 ; Set to input (TXEN will override to output)
MOV A, #0x60 ; Baud 115200
B0MOV URBRC, A
MOV A, #0x90 ; 24MHz clock, TX enabled, 8n1, 1-byte mode
B0MOV URTX, A
; Send a message that we are alive
MOV A, #'H'
CALL _uart_tx
MOV A, #'i'
CALL _uart_tx
MOV A, #'!'
CALL _uart_tx
MOV A, #13
CALL _uart_tx
MOV A, #10
CALL _uart_tx
; Jump into bootloader if "Return" key (S10/R6) is held
B0BSET P0M.5 ; Set S10 to output
B0BCLR P1M.5 ; Set R6 to input
B0BSET P1UR.5 ; Enable pull-up on R6
B0BSET S10 ; Set S10 high
CALL _delayshort
B0BTS1 R6 ; Jump if R6 is low
JMP @F
B0BCLR S10 ; Set S10 low
CALL _delayshort
B0BTS1 R6 ; Jump if R6 is low
JMP _return_held
@@:
; Jump into bootloader if P0.5/P0.6 are shorted (URX/UTX)
B0BCLR 0xa9.4 ; Switch UTX back to GPIO
B0BSET P0M.6 ; Set UTX to output
B0BCLR P0M.5 ; Set URX to input
B0BSET P0UR.5 ; Enable pull-up on URX
B0BSET UTX ; Set P0.6/UTX high
CALL _delayshort
B0BTS1 URX ; Jump if P0.5/URX is low
JMP @F
B0BCLR UTX ; Set P0.6/UTX low
CALL _delayshort
B0BTS1 URX ; Jump if P0.5/URX is low
JMP _uart_shorted
@@:
B0BSET 0xa9.4 ; Switch UTX back to UART
; Reset either from undervoltage (power-on) or external reset
; Cold reset state per datasheet:
; - Clock is 12MHz PLL synced to external oscillator
; - IOs set to input
MOV A, #0
B0MOV Y, A
@@:
MOV A, Y
CALL _uart_hex
INCMS Y
NOP
JMP @B
JMP _flasher
_return_held:
MOV A, #'E'
CALL _uart_tx
MOV A, #'r'
CALL _uart_tx
JMP _flasher
_uart_shorted:
B0BSET 0xa9.4 ; Switch UTX back to UART
MOV A, #'E'
CALL _uart_tx
MOV A, #'s'
CALL _uart_tx
JMP _flasher
_uart_hex:
MOV R, A
SWAP R
CALL _uart_nibble
MOV A, R
; fall-through
_uart_nibble:
AND A, #0xf
ADD A, #0xf6 ; -0xa
B0BTS0 FC ; Skip next insn if carry unset
ADD A, #0x27 ; 'a' - '0' - 0xa
ADD A, #0x3a ; '0' + 0xa
; fall-through
_uart_tx:
B0MOV URTXD1, A
@@:
B0BTS1 FUTTXIRQ ; Check if TX is done
JMP @B
B0BCLR FUTTXIRQ
RET
_delayshort:
MOV A, #0
B0MOV R, A
@@:
DECMS R
JMP @B
RET
ORG 0x27ff
DW 0xaaaa ; canary
ORG _canary_check
JMP _start
ORG _flasher
JMP $
+86
View File
@@ -0,0 +1,86 @@
PIN1/P1.2: R2
PIN2/P1.1/SDA: R3
PIN3/P1.0/SCL: R0
PIN4/P0.0/INT0: ?NC?
PIN5/P0.1/INT1: ?NC?
PIN6/P0.2: ?NC?
[PIN7/VDD]
PIN8/P4.0/AIN0: S2
PIN9/P4.1/AIN1: S4
PIN10/P4.2/AIN2: S7
PIN11/P4.3/AIN3: S8
PIN12/P4.4/AIN4: S6
[corner]
PIN13/P4.5/AIN5: S3
PIN14/P4.6/AIN6: S12
PIN15/P4.7/AIN7: S13
[PIN16/VSS]
PIN17/P0.3: S14
PIN18/P0.4: S11
PIN19/P0.5/URX: S10/KSO10
PIN20/P0.6/UTX: S15/KSO15
PIN21/P0.7/RST
[PIN22/XIN]
[PIN23/XOUT]
[PIN24/VREG25]
[corner]
[PIN25/VSS]
[PIN26/D+]
[PIN27/D-]
[PIN28/VREG33]
[PIN29/VDD]
PIN30/P2.0/SCK: S1
PIN31/P2.1/SDO: S5
PIN32/P2.2/SDI: S0
PIN33/P2.3: S9
PIN34/P2.4: trackpoint SCL
PIN35/P2.5: trackpoint SDA
PIN36/P2.6: trackpoint IRQ
[corner]
PIN37/P2.7: ?NC?
PIN38/P5.0: ?NC?
PIN39/P5.1: ?NC?
PIN40/P5.2: ?NC?
PIN41/P5.3/PWM0: LED D1
PIN42/P5.4/PWM1 ?NC?
PIN43/P5.5/PWM2 ?NC?
PIN44/P1.7 R1
PIN45/P1.6 R7
PIN46/P1.5 R6
PIN47/P1.4: R4
PIN48/P1.3: R5
Keyboard connector (PCB labels):
R1 R6 R4 S0 R3 S1 S2 S7 S6 S12 S14 S10 MG MM
R7 S9 R5 R2 S5 R0 S4 S8 S3 S13 S11 S15 ML MR
Alternative names (S230U schematic):
KSI1 KSI6 KSI4 KSO0 KSI3 KSO1 KSO2 KSO7 KSO6 KSO12 KSO14 KSO10 GND IPD_MIDDLE
KSI7 KSO9 KSI5 KSI2 KSO5 KSI0 KSO4 KSO8 KSO3 KSO13 KSO11 KSO15 IPD_LEFT IPD_RIGHT
Pin1: KSI1
Pin2: KSI7
[...]
Pin27: IPD_MIDDLE
Pin28: IPD_RIGHT
Keyboard matrix (annotated ku1255_sim.py output):
P1.0 P1.1 P1.2 P1.3 P1.4 P1.5 P1.6 P1.7
R0 R3 R2 R5 R4 R6 R7 R1
UP (none) (none) END (none) PAUSE LEFT KP_MEMSTORE P0.3/S14
(none) HOME (none) F11 (none) (none) DOWN (none) P0.4/S11
F5 F9 INTERNATIONAL3 F10 BACKSLASH RETURN SPACE BACKSPACE P0.5/S10
(none) DELETE (none) INSERT PRINTSCREEN PAGEUP PAGEDOWN (none) P0.6/S15
F4 F2 E 3 D C (none) F3 P2.0/S1
H 6 U 7 J M N Y P2.1/S5
ESCAPE GRAVE Q 1 A Z INTERNATIONAL5 TAB P2.2/S0
(none) (none) (none) (none) (none) RSHIFT (none) LSHIFT P2.3/S9
NONUSBACKSLASH F1 W 2 S X (none) CAPSLOCK P4.0/S2
G 5 R 4 F V B T P4.1/S4
INTERNATIONAL4 F8 O 9 L PERIOD INTERNATIONAL2 F7 P4.2/S7
APOSTROPHE MINUS P 0 SEMICOLON NONUSHASH SLASH LEFTBRACKET P4.3/S8
F6 EQUALS I 8 K COMMA INTERNATIONAL1 RIGHTBRACKET P4.4/S6
(none) LCTRL (none) (none) (none) RCTRL (none) (none) P4.5/S3
LALT KP_MEMSUBTRACT (none) (none) (none) (none) RALT (none) P4.6/S12
(none) (none) KP_MEMCLEAR F12 (none) (none) RIGHT LGUI P4.7/S13