Ernie Firmware: Difference between revisions
(Created page with "= References = * 78K0R/KH3 Reference Manual * RL78 ISA Manual * [https://github.com/fail0verflow/rl78-ida-proc IDA...") |
CelesteBlue (talk | contribs) |
||
(11 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
= References = | = References = | ||
== Manuals == | |||
* [[File:78K0R_User_Manual.pdf|78K0R/KH3 Reference Manual]] | * [[File:78K0R_User_Manual.pdf|78K0R/KH3 Reference Manual]] | ||
* [[File:RL78_ISA_Manual.pdf|RL78 ISA Manual]] | * [[File:RL78_ISA_Manual.pdf|RL78 ISA Manual]] | ||
* [https://github.com/fail0verflow/rl78-ida-proc IDA | * [[File:RL78_G13_User_Manual_Hardware.pdf|RL78 G13 User Manual Hardware]] | ||
== Tools == | |||
* [https://github.com/fail0verflow/rl78-ida-proc IDA PRO RL78 Processor module] | |||
* [https://github.com/astrelsky/RL78_sleigh Ghidra RL78 disassembler and decompiler] | |||
== Unofficial documentation == | |||
* [https://fail0verflow.com/blog/2018/ps4-syscon/ fail0verflow PS4 Syscon (RL78 G13) hack and RE writeup] | |||
= Architecture = | = Architecture = | ||
Line 39: | Line 50: | ||
== Startup == | == Startup == | ||
Reset vector sets up environment and calls into the Worker Loop | Reset vector sets up environment and calls into the Worker Loop. | ||
== Worker Loop == | == Worker Loop == | ||
Line 53: | Line 64: | ||
== Main Function == | == Main Function == | ||
The Main Function is the starting point for most of | The Main Function is the starting point for most of Syscon's tasks. It looks at the current state (a global variable) and the target state (its only argument) to determine what to do. If the task is successful, the target state will be written to the current state variable and the function call returns to the Worker Loop. | ||
== Command Handler == | == Command Handler == | ||
Line 61: | Line 72: | ||
== Asynchronous Handler == | == Asynchronous Handler == | ||
A timer (<code>TMR00</code>) is set up at the start of the Worker Loop to count in <code>0x7D00</code> cycle intervals. Oddly, the timer interrupt is not configured but <code>INTCSI01</code> is configured. Possibly the reference manual is not correct | A timer (<code>TMR00</code>) is set up at the start of the Worker Loop to count in <code>0x7D00</code> cycle intervals. Oddly, the timer interrupt is not configured but <code>INTCSI01</code> is configured. Possibly the reference manual is not correct with reference to Ernie because the interrupt handler for <code>INTCSI01</code> does not appear to reference the serial interface at all. We will assume this interrupt is the timer's interrupt. | ||
A table of software handlers are initialized to 0 at the start of the Worker Loop. Functions can register handlers in this table. Functions can also flag a handler to run at the next timer interrupt. During each timer interrupt, (with interrupt disabled) the firmware will iterate through the handlers and run any function that is flagged (and unflag it). | A table of software handlers are initialized to 0 at the start of the Worker Loop. Functions can register handlers in this table. Functions can also flag a handler to run at the next timer interrupt. During each timer interrupt, (with interrupt disabled) the firmware will iterate through the handlers and run any function that is flagged (and unflag it). | ||
== | == Jig Handler == | ||
When [[Syscon UART RPC]] is initialized, commands can be sent through a UART interface by an external agent. A UART RX interrupt will flag asynchronous handler <code>0xB</code>. This handler is registered at the start of the Worker Loop to set flag <code>0x32</code> and return. In the Worker Loop, flag <code>0x32</code> can be handled by states 1, 3, 8, 9. In any of these states, the Jig Handler is called. | |||
= | == Jig Initialization == | ||
# At startup, the timer for the [[#Asynchronous_Handler]] is set up. When the interrupt is triggered at least 8 times, every time it is triggered, flag <code>0x79</code> is set. | |||
# At startup, the timer for the [[ | |||
# In states 0, 1, 3, 8, or 9, flag <code>0x79</code> is handled. | # In states 0, 1, 3, 8, or 9, flag <code>0x79</code> is handled. | ||
# The ADC is called on channel ANI6 (port P26). The voltage is passed to a lookup table that converts different voltage ranges to different ids. For example 1.562V - 1.622V corresponds to id 0. | # The ADC is called on channel ANI6 (port P26). The voltage is passed to a lookup table that converts different voltage ranges to different ids. For example 1.562V - 1.622V corresponds to id 0. | ||
# Repeat 1-3 and if the id value did not change, then we set a global variable to that value and set flag <code>0x7A</code>. | # Repeat 1-3 and if the id value did not change, then we set a global variable to that value and set flag <code>0x7A</code>. | ||
# In states 0, 1, 3, 8, or 9, flag <code>0x7A</code> is handled. | # In states 0, 1, 3, 8, or 9, flag <code>0x7A</code> is handled. | ||
# If the id from #3 is | # If the id from #3 is 4 (P26 is held at 1.017V - 1.140V for at least 32000 clock cycles), then UART serial controller is configured. If bit 3 is set in [[KBL_Param#Hardware_Info]] then a hello packet is printed to UART: <code>0x55 0x55 0x55</code> ("UUU"). | ||
=== Voltage Table === | === Jig Initialization Voltage Table === | ||
The conversion is done using the equation on 11.4.2 of the manual with Vref=1.8V. | The conversion is done using the equation on 11.4.2 of the Syscon manual with Vref=1.8V. | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 145: | Line 148: | ||
|} | |} | ||
[[Category:Syscon]] | [[Category:Syscon]] | ||
[[Category:Devices]] | [[Category:Devices]] |
Latest revision as of 21:22, 6 January 2024
References
Manuals
Tools
Unofficial documentation
Architecture
Read the reference manual for full information. Below are the most important facts.
Memory Space
The memory is laid out into 0x800
sized blocks. The bottom X blocks are flash memory that can be programmed. Some blocks are not programmable on Ernie. Most keys reside on the non-programmable blocks.
Registers and Devices
Registers are 8-bits and adjacent registers can be addressed as 16-bits (example: register AX can be addressed as A (top 8 bits) and X (bottom 8 bits)).
Additional registers are located near the top of the memory map. They are addressed like any other memory. Ernie uses 0xFFED4-0xFFEDF
as extra scratch registers.
Device registers (documented in the reference manual) are located at 0xFFF00-0xFFFFF
(SFR) and 0xF0000-0xF07FF
(SFR2).
The UART serial controller used by Ernie is not documented in the reference manual but the register definitions are the same as the serial controllers that are documented. There appears to be a few other registers and interrupt vectors that differ from the documentation.
Memory access is done through segmented addressing on a 20-bit address space. CS contains the top 4 bits for code access. ES contains the top 4 bits for data access.
Calling Convention
Functions with one argument: AX
Functions with one pointer argument: AX = pointer, C = segment
Functions with multiple arguments: first argument same as above, then rest are in stack using PUSH instruction. Stack pointer moves downwards.
Often, at the start of a function, the AX and BC registers are PUSH onto the stack before the frame pointer is allocated. Then the arguments are referenced by addressing the bottom of the frame pointer.
Firmware Basics
Startup
Reset vector sets up environment and calls into the Worker Loop.
Worker Loop
The Worker Loop is a FSM with 10 states (0-9). In each state, the Main function is called with the current state and the target state depending on flags that are set.
The starting state is either 0 or 7 depending on a global value derived earlier.
Flags are global variables in memory set by various sources: asynchronous interrupts, synchronous work in the current state, command handlers, etc. Not all states will handle all flags. Some flags can be handled in all states and some flags can be handled in only some states. Each flag is cleared after it is read. When multiple flags are set, the Main function will be called multiple times synchronously in a set order (certain flags have higher priority).
In states 3 and 4, after the Main Function is called (potentially multiple times depending on the flags set), the Command Handler is called.
Main Function
The Main Function is the starting point for most of Syscon's tasks. It looks at the current state (a global variable) and the target state (its only argument) to determine what to do. If the task is successful, the target state will be written to the current state variable and the function call returns to the Worker Loop.
Command Handler
Two bytes are read from SDR00. This is the command header. If the header & 0x80 == 0, then there is no data payload in the command and the command handler is invoked. One more byte is read. If there is no payload, this is the checksum. If there is a payload, the rest of the packet is read and handled in a different command table. Finally, the checksum is checked.
Asynchronous Handler
A timer (TMR00
) is set up at the start of the Worker Loop to count in 0x7D00
cycle intervals. Oddly, the timer interrupt is not configured but INTCSI01
is configured. Possibly the reference manual is not correct with reference to Ernie because the interrupt handler for INTCSI01
does not appear to reference the serial interface at all. We will assume this interrupt is the timer's interrupt.
A table of software handlers are initialized to 0 at the start of the Worker Loop. Functions can register handlers in this table. Functions can also flag a handler to run at the next timer interrupt. During each timer interrupt, (with interrupt disabled) the firmware will iterate through the handlers and run any function that is flagged (and unflag it).
Jig Handler
When Syscon UART RPC is initialized, commands can be sent through a UART interface by an external agent. A UART RX interrupt will flag asynchronous handler 0xB
. This handler is registered at the start of the Worker Loop to set flag 0x32
and return. In the Worker Loop, flag 0x32
can be handled by states 1, 3, 8, 9. In any of these states, the Jig Handler is called.
Jig Initialization
- At startup, the timer for the #Asynchronous_Handler is set up. When the interrupt is triggered at least 8 times, every time it is triggered, flag
0x79
is set. - In states 0, 1, 3, 8, or 9, flag
0x79
is handled. - The ADC is called on channel ANI6 (port P26). The voltage is passed to a lookup table that converts different voltage ranges to different ids. For example 1.562V - 1.622V corresponds to id 0.
- Repeat 1-3 and if the id value did not change, then we set a global variable to that value and set flag
0x7A
. - In states 0, 1, 3, 8, or 9, flag
0x7A
is handled. - If the id from #3 is 4 (P26 is held at 1.017V - 1.140V for at least 32000 clock cycles), then UART serial controller is configured. If bit 3 is set in KBL_Param#Hardware_Info then a hello packet is printed to UART:
0x55 0x55 0x55
("UUU").
Jig Initialization Voltage Table
The conversion is done using the equation on 11.4.2 of the Syscon manual with Vref=1.8V.
ID | ADC Value | Min Voltage |
---|---|---|
0 | 59072 | 1.622 |
1 | 56896 | 1.562 |
255 | 52608 | 1.444 |
2 | 50240 | 1.379 |
3 | 46656 | 1.281 |
255 | 41536 | 1.140 |
4 | 37056 | 1.017 |
255 | 34752 | 0.954 |
5 | 31488 | 0.864 |
255 | 1408 | 0.038 |
6 | 320 | 0.008 |
7 | 0 | 0 |