From 0bf18ebf6f6e73e3231899a87e1287dce6eff79a Mon Sep 17 00:00:00 2001 From: Tobias Diedrich Date: Sun, 19 Dec 2021 16:25:16 +0100 Subject: [PATCH] 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 --- .gitignore | 1 + main.s | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++++ pinout.txt | 86 ++++++++++++++++++++++++++ 3 files changed, 263 insertions(+) create mode 100644 main.s create mode 100644 pinout.txt diff --git a/.gitignore b/.gitignore index c6127b3..3a1ac20 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,7 @@ *.i*86 *.x86_64 *.hex +*.bin # Debug files *.dSYM/ diff --git a/main.s b/main.s new file mode 100644 index 0000000..4258a99 --- /dev/null +++ b/main.s @@ -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 $ diff --git a/pinout.txt b/pinout.txt new file mode 100644 index 0000000..d22eaad --- /dev/null +++ b/pinout.txt @@ -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