From 85ef93cd3c3c3895901029613f991ca08e346974 Mon Sep 17 00:00:00 2001 From: Daniel Lublin Date: Wed, 26 Oct 2022 11:38:58 +0200 Subject: [PATCH] Clarify switch_app reads and writes; add read test to testfw --- doc/system_description/software.md | 75 ++++++++++++++-------------- hw/application_fpga/fw/testfw/main.c | 12 +++++ 2 files changed, 50 insertions(+), 37 deletions(-) diff --git a/doc/system_description/software.md b/doc/system_description/software.md index 0b90d46..9e92ddf 100644 --- a/doc/system_description/software.md +++ b/doc/system_description/software.md @@ -165,9 +165,9 @@ Procedure: 1. The host sends `FW_CMD_RUN_APP` to the device. 2. The firmware responds with `FW_RSP_RUN_APP` - 3. The firmware writes a non-zero to `SWITCH_APP`, and executes - assembler code that writes zeros to stack and data of the - firmware, then jumps to what's in APP_ADDR. + 3. The firmware writes to `SWITCH_APP`, and executes assembler code + that writes zeros to stack and data of the firmware, then jumps + to what's in APP_ADDR. 4. The device is now in application mode and is executing the application. @@ -324,39 +324,40 @@ Assigned core prefixes: *Nota bene*: MMIO accesses should be 32 bit wide, e.g use `lw` and `sw`. Exceptions are `FW_RAM` and `QEMU_DEBUG`. -| *name* | *fw* | *app | *size* | *type* | *content* | *description* | -|-------------------|-------|------------|--------|----------|-----------|-----------------------------------------------------------------------| -| `TRNG_STATUS` | r | r | | | | TRNG_STATUS_READY_BIT is 1 when an entropy word is available. | -| `TRNG_ENTROPY` | r | r | 4B | u32 | | Entropy word. Reading a word will clear status. | -| `TIMER_CTRL` | r/w | r/w | | | | If TIMER_STATUS_READY_BIT in TIMER_STATUS is 1 then writing here | -| | | | | | | starts the timer. If the same bit is 0 then writing stops the timer. | -| `TIMER_STATUS` | r | r | | | | TIMER_STATUS_READY_BIT is 1 when timer is ready to start running. | -| `TIMER_PRESCALER` | r/w | r/w | 4B | | | Prescaler init value. Write blocked when running. | -| `TIMER_TIMER` | r/w | r/w | 4B | | | Timer init or current value while running. Write blocked when running.| -| `UDS_FIRST` | r[^3] | invisible | 4B | u8[32] | | First word of Unique Device Secret key. | -| `UDS_LAST` | | invisible | | | | The last word of the UDS | -| `UART_BITRATE` | r/w | | | | | TBD | -| `UART_DATABITS` | r/w | | | | | TBD | -| `UART_STOPBITS` | r/w | | | | | TBD | -| `UART_RX_STATUS` | r | r | 1B | u8 | | Non-zero when there is data to read | -| `UART_RX_DATA` | r | r | 1B | u8 | | Data to read. Only LSB contains data | -| `UART_TX_STATUS` | r | r | 1B | u8 | | Non-zero when it's OK to write data | -| `UART_TX_DATA` | w | w | 1B | u8 | | Data to send. Only LSB contains data | -| `TOUCH_STATUS` | r/w | r/w | | | | TOUCH_STATUS_EVENT_BIT is 1 when touched. After detecting a touch | -| | | | | | | event (reading a 1), write anything here to acknowledge it. | -| `FW_RAM` | r/w | invisible | 1 kiB | u8[1024] | | Firmware-only RAM. | -| `UDA` | r | invisible | 16B | u8[16] | | Unique Device Authentication key. | -| `UDI` | r | r | 8B | u64 | | Unique Device ID (UDI). | -| `QEMU_DEBUG` | w | w | | u8 | | Debug console (only in QEMU) | -| `NAME0` | r | r | 4B | char[4] | "tk1 " | ID of core/stick | -| `NAME1` | r | r | 4B | char[4] | "mkdf" | ID of core/stick | -| `VERSION` | r | r | 4B | u32 | 1 | Current version. | -| `SWITCH_APP` | w | invisible? | 1B | u8 | | Switch to application mode. Write non-zero to trigger. | -| `LED` | w | w | 1B | u8 | | | -| `GPIO` | | | | | | | -| `APP_ADDR` | r/w | r | 4B | u32 | | Application address (0x4000_0000) | -| `APP_SIZE` | r/w | r | 4B | u32 | | Application size | -| `CDI_FIRST` | r/w | r | 32B | u8[32] | | Compound Device Identifier (CDI). UDS+measurement... | -| `CDI_LAST` | | r | | | | Last word of CDI | +| *name* | *fw* | *app* | *size* | *type* | *content* | *description* | +|-------------------|-------|-----------|--------|----------|-----------|------------------------------------------------------------------------| +| `TRNG_STATUS` | r | r | | | | TRNG_STATUS_READY_BIT is 1 when an entropy word is available. | +| `TRNG_ENTROPY` | r | r | 4B | u32 | | Entropy word. Reading a word will clear status. | +| `TIMER_CTRL` | r/w | r/w | | | | If TIMER_STATUS_READY_BIT in TIMER_STATUS is 1, writing anything here | +| | | | | | | starts the timer. If the same bit is 0 then writing stops the timer. | +| `TIMER_STATUS` | r | r | | | | TIMER_STATUS_READY_BIT is 1 when timer is ready to start running. | +| `TIMER_PRESCALER` | r/w | r/w | 4B | | | Prescaler init value. Write blocked when running. | +| `TIMER_TIMER` | r/w | r/w | 4B | | | Timer init or current value while running. Write blocked when running. | +| `UDS_FIRST` | r[^3] | invisible | 4B | u8[32] | | First word of Unique Device Secret key. | +| `UDS_LAST` | | invisible | | | | The last word of the UDS | +| `UART_BITRATE` | r/w | | | | | TBD | +| `UART_DATABITS` | r/w | | | | | TBD | +| `UART_STOPBITS` | r/w | | | | | TBD | +| `UART_RX_STATUS` | r | r | 1B | u8 | | Non-zero when there is data to read | +| `UART_RX_DATA` | r | r | 1B | u8 | | Data to read. Only LSB contains data | +| `UART_TX_STATUS` | r | r | 1B | u8 | | Non-zero when it's OK to write data | +| `UART_TX_DATA` | w | w | 1B | u8 | | Data to send. Only LSB contains data | +| `TOUCH_STATUS` | r/w | r/w | | | | TOUCH_STATUS_EVENT_BIT is 1 when touched. After detecting a touch | +| | | | | | | event (reading a 1), write anything here to acknowledge it. | +| `FW_RAM` | r/w | invisible | 1 kiB | u8[1024] | | Firmware-only RAM. | +| `UDA` | r | invisible | 16B | u8[16] | | Unique Device Authentication key. | +| `UDI` | r | r | 8B | u64 | | Unique Device ID (UDI). | +| `QEMU_DEBUG` | w | w | | u8 | | Debug console (only in QEMU) | +| `NAME0` | r | r | 4B | char[4] | "tk1 " | ID of core/stick | +| `NAME1` | r | r | 4B | char[4] | "mkdf" | ID of core/stick | +| `VERSION` | r | r | 4B | u32 | 1 | Current version. | +| `SWITCH_APP` | r/w | r | 1B | u8 | | Write anything here to trigger the switch to application mode. Reading | +| | | | | | | returns 0 if device is in firmware mode, 0xffffffff if in app mode. | +| `LED` | w | w | 1B | u8 | | | +| `GPIO` | | | | | | | +| `APP_ADDR` | r/w | r | 4B | u32 | | Application address (0x4000_0000) | +| `APP_SIZE` | r/w | r | 4B | u32 | | Application size | +| `CDI_FIRST` | r/w | r | 32B | u8[32] | | Compound Device Identifier (CDI). UDS+measurement... | +| `CDI_LAST` | | r | | | | Last word of CDI | [^3]: The UDS can only be read *once* per power-cycle. diff --git a/hw/application_fpga/fw/testfw/main.c b/hw/application_fpga/fw/testfw/main.c index 71208dc..2a8e18c 100644 --- a/hw/application_fpga/fw/testfw/main.c +++ b/hw/application_fpga/fw/testfw/main.c @@ -151,10 +151,22 @@ int main() anyfailed = 1; } + uint32_t sw = *switch_app; + if (sw != 0) { + test_puts("FAIL: switch_app is not 0 in fw mode\r\n"); + anyfailed = 1; + } + // Turn on application mode. // ------------------------- *switch_app = 1; + sw = *switch_app; + if (sw != 0xffffffff) { + test_puts("FAIL: switch_app is not 0xffffffff in app mode\r\n"); + anyfailed = 1; + } + // Should NOT be able to read from UDS in app-mode. wordcpy(uds_local, (void *)uds, 8); if (!memeq(uds_local, uds_zeros, 8 * 4)) {