rcbench
Servo and ESC test bench: panel, IOmcu and shared C
Loading...
Searching...
No Matches
link_update_dev.h File Reference

The IOmcu's half of the firmware update: the UPDATE_CTL and UPDATE_DATA pages (link_pages.h) and what they write. More...

#include <stdbool.h>
#include <stdint.h>
#include "link_pages.h"
#include "link_sha256.h"
#include "link_update_image.h"

Go to the source code of this file.

Data Structures

 The flash, gate, boot ROM and restart callbacks of the update. More...
 The state of the IOmcu's side of one update session. More...

Macros

#define LINK_UPD_HASH_STEP   1024u
 Bytes a link_update_dev_poll() hashes, at most: 1KiB, about 0.4ms of SHA-256 at 150MHz (not measured).
#define LINK_UPD_SILENCE_MS   5000u
 Time without a request to either update page that ends a session: longer than the panel's own 1000ms wait for an answer, so one lost frame costs a retry and not the session, and longer than the panel's LINK_UPH_LOST_MS, so the panel gives up first.
#define LINK_UPD_SWEEP_MS   1000u
 Time between two tries of an owed erase of the other slot's first sector: each one parks the loop for about 19ms.
#define LINK_UPD_RESTART_MS   20u
 Time from the ACTIVATE that wrote the first sector to the restart, so its acknowledgement is on the wire first.

Functions

void link_update_dev_init (link_update_dev_t *u, const link_update_io_t *io, const uint8_t *running, const uint8_t *target, uint32_t slot_bytes, uint16_t slot)
 Start idle. slot is LINK_UPD_SLOT as the boot ROM reports it: the running slot, LINK_UPD_SLOT_NONE without a partition table this build writes, and LINK_UPD_SLOT_TRIAL for an image that waits for its BUY. running and target may be NULL with LINK_UPD_SLOT_NONE.
void link_update_dev_read_ctl (link_update_dev_t *u, uint8_t offset, uint8_t count, uint16_t *out)
 The two pages' handlers, for the caller's link_page_t table.
uint8_t link_update_dev_write_ctl (link_update_dev_t *u, uint8_t offset, uint8_t count, const uint16_t *in)
 Write registers of the UPDATE_CTL page: one command and its arguments.
void link_update_dev_read_data (link_update_dev_t *u, uint8_t offset, uint8_t count, uint16_t *out)
 Read registers of the UPDATE_DATA page.
uint8_t link_update_dev_write_data (link_update_dev_t *u, uint8_t offset, uint8_t count, const uint16_t *in)
 Write registers of the UPDATE_DATA page: stage part of a block.
void link_update_dev_poll (link_update_dev_t *u, uint32_t now_ms)
 The work that does not fit a reply: LINK_UPD_HASH_STEP bytes of a hash, the restart LINK_UPD_RESTART_MS after ACTIVATE, an owed erase of the other slot's first sector, and the end of a session that has had no request to either update page for LINK_UPD_SILENCE_MS.
bool link_update_dev_holds_arm (const link_update_dev_t *u)
 True while ARM is refused: a session runs or an image waits for BUY.
bool link_update_dev_refuses_arm (const link_update_dev_t *u, uint8_t off, uint8_t n, const uint16_t *in)
 Whether a write of n CONTROL registers from off is refused for the update: it asks for a non-zero ARM while link_update_dev_holds_arm().

Detailed Description

The IOmcu's half of the firmware update: the UPDATE_CTL and UPDATE_DATA pages (link_pages.h) and what they write.

Pure C. The flash, the store's gate, the boot ROM's BUY and the restart are the caller's, handed in as callbacks, and both slots are read through plain pointers, so the host suite runs every path against a slot in RAM.

RAM: two 4KiB sector buffers – the slot's first sector, held until ACTIVATE writes it last, and the sector being filled.

SPDX-License-Identifier: MIT

Macro Definition Documentation

◆ LINK_UPD_SILENCE_MS

#define LINK_UPD_SILENCE_MS   5000u

Time without a request to either update page that ends a session: longer than the panel's own 1000ms wait for an answer, so one lost frame costs a retry and not the session, and longer than the panel's LINK_UPH_LOST_MS, so the panel gives up first.

Requests to other pages do not count: a panel that polls and sends no update has left it.

Function Documentation

◆ link_update_dev_holds_arm()

bool link_update_dev_holds_arm ( const link_update_dev_t * u)

True while ARM is refused: a session runs or an image waits for BUY.

Parameters
uThe update state; NULL gives false.
Returns
true while a session runs, an ACTIVATE is pending, or an image waits for BUY.

◆ link_update_dev_init()

void link_update_dev_init ( link_update_dev_t * u,
const link_update_io_t * io,
const uint8_t * running,
const uint8_t * target,
uint32_t slot_bytes,
uint16_t slot )

Start idle. slot is LINK_UPD_SLOT as the boot ROM reports it: the running slot, LINK_UPD_SLOT_NONE without a partition table this build writes, and LINK_UPD_SLOT_TRIAL for an image that waits for its BUY. running and target may be NULL with LINK_UPD_SLOT_NONE.

A bought image that finds the other slot's first sector written owes its erase.

Parameters
uThe update state to set up.
ioThe callbacks; kept, not copied.
runningThe running slot's bytes.
targetThe other slot's bytes.
slot_bytesBytes in one slot, a multiple of the 4KiB sector.
slotLINK_UPD_SLOT as the boot ROM reports it.

◆ link_update_dev_poll()

void link_update_dev_poll ( link_update_dev_t * u,
uint32_t now_ms )

The work that does not fit a reply: LINK_UPD_HASH_STEP bytes of a hash, the restart LINK_UPD_RESTART_MS after ACTIVATE, an owed erase of the other slot's first sector, and the end of a session that has had no request to either update page for LINK_UPD_SILENCE_MS.

Once per pass of the caller's loop.

Parameters
uThe update state.
now_msThe current time, in ms.

◆ link_update_dev_read_ctl()

void link_update_dev_read_ctl ( link_update_dev_t * u,
uint8_t offset,
uint8_t count,
uint16_t * out )

The two pages' handlers, for the caller's link_page_t table.

Parameters
uThe update state.
offsetFirst register, 0 to LINK_UPD_COUNT - 1.
countNumber of registers to read.
outReceives the registers.

◆ link_update_dev_read_data()

void link_update_dev_read_data ( link_update_dev_t * u,
uint8_t offset,
uint8_t count,
uint16_t * out )

Read registers of the UPDATE_DATA page.

Parameters
uThe update state.
offsetFirst register of the staged block.
countNumber of registers to read.
outReceives the registers.

◆ link_update_dev_refuses_arm()

bool link_update_dev_refuses_arm ( const link_update_dev_t * u,
uint8_t off,
uint8_t n,
const uint16_t * in )

Whether a write of n CONTROL registers from off is refused for the update: it asks for a non-zero ARM while link_update_dev_holds_arm().

The caller answers it with LINK_NACK_NOT_ARMED before the page's own rules run, so nothing of the frame is stored. A disarm is always taken.

Parameters
uThe update state.
offFirst CONTROL register of the write.
nNumber of registers in the write.
inThe registers written.
Returns
true when the write must be refused.

◆ link_update_dev_write_ctl()

uint8_t link_update_dev_write_ctl ( link_update_dev_t * u,
uint8_t offset,
uint8_t count,
const uint16_t * in )

Write registers of the UPDATE_CTL page: one command and its arguments.

Parameters
uThe update state.
offsetFirst register; must be LINK_UPD_CMD.
countNumber of registers, 1 to 4.
inThe registers written.
Returns
0 when the command is taken, else the NACK reason.

◆ link_update_dev_write_data()

uint8_t link_update_dev_write_data ( link_update_dev_t * u,
uint8_t offset,
uint8_t count,
const uint16_t * in )

Write registers of the UPDATE_DATA page: stage part of a block.

Parameters
uThe update state.
offsetFirst register of the block, 0 to LINK_UPD_DATA_COUNT - 1.
countNumber of registers written.
inThe registers written.
Returns
0 when stored, LINK_NACK_BAD_RANGE when the window does not fit the block, or when the arguments are NULL.