katapult/lib/pico-sdk/boot/picoboot.h
Kevin O'Connor c0014efc4a rp2040: Resynchronize with upstream Klipper code and support rp2350 chips
Synchronize with the latest Klipper code.  This pulls in the latest
lib/ files (needed to use the pico-sdk v2.0.0 version).  It updates to
latest can2040 code (needed for pico-sdk v2.0.0 support).  It
implements USB double buffering (as is now done in Klipper).  It adds
in support for additional UART pins (as is now done in Klipper).  It
adds support for rp2350 chips.

This replaces the execute in ram code previously implemented in
Katapult with the execute in ram code that is now standard in Klipper.

The CONFIG_RP2040_ADD_BOOT_SIGNATURE kconfig symbol was removed and
the build now always produces a katapult.withclear.uf2 file.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2024-12-17 19:27:43 -05:00

176 lines
4.7 KiB
C

/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _BOOT_PICOBOOT_H
#define _BOOT_PICOBOOT_H
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#ifndef NO_PICO_PLATFORM
#include "pico/platform.h"
#endif
/** \file picoboot.h
* \defgroup boot_picoboot_headers boot_picoboot_headers
*
* \brief Header file for the PICOBOOT USB interface exposed by an RP2xxx chip in BOOTSEL mode
*/
#include "picoboot_constants.h"
#define PICOBOOT_MAGIC 0x431fd10bu
// --------------------------------------------
// CONTROL REQUESTS FOR THE PICOBOOT INTERFACE
// --------------------------------------------
// size 0 OUT - un-stall EPs and reset
#define PICOBOOT_IF_RESET 0x41
// size 16 IN - return the status of the last command
#define PICOBOOT_IF_CMD_STATUS 0x42
// --------------------------------------------------
// COMMAND REQUESTS SENT TO THE PICOBOOT OUT ENDPOINT
// --------------------------------------------------
//
// picoboot_cmd structure of size 32 is sent to OUT endpoint
// transfer_length bytes are transferred via IN/OUT
// device responds on success with 0 length ACK packet set via OUT/IN
// device may stall the transferring endpoint in case of error
enum picoboot_cmd_id {
PC_EXCLUSIVE_ACCESS = 0x1,
PC_REBOOT = 0x2,
PC_FLASH_ERASE = 0x3,
PC_READ = 0x84, // either RAM or FLASH
PC_WRITE = 0x5, // either RAM or FLASH (does no erase)
PC_EXIT_XIP = 0x6,
PC_ENTER_CMD_XIP = 0x7,
PC_EXEC = 0x8,
PC_VECTORIZE_FLASH = 0x9,
// RP2350 only below here
PC_REBOOT2 = 0xa,
PC_GET_INFO = 0x8b,
PC_OTP_READ = 0x8c,
PC_OTP_WRITE = 0xd,
//PC_EXEC2 = 0xe, // currently unused
};
enum picoboot_status {
PICOBOOT_OK = 0,
PICOBOOT_UNKNOWN_CMD = 1,
PICOBOOT_INVALID_CMD_LENGTH = 2,
PICOBOOT_INVALID_TRANSFER_LENGTH = 3,
PICOBOOT_INVALID_ADDRESS = 4,
PICOBOOT_BAD_ALIGNMENT = 5,
PICOBOOT_INTERLEAVED_WRITE = 6,
PICOBOOT_REBOOTING = 7,
PICOBOOT_UNKNOWN_ERROR = 8,
PICOBOOT_INVALID_STATE = 9,
PICOBOOT_NOT_PERMITTED = 10,
PICOBOOT_INVALID_ARG = 11,
PICOBOOT_BUFFER_TOO_SMALL = 12,
PICOBOOT_PRECONDITION_NOT_MET = 13,
PICOBOOT_MODIFIED_DATA = 14,
PICOBOOT_INVALID_DATA = 15,
PICOBOOT_NOT_FOUND = 16,
PICOBOOT_UNSUPPORTED_MODIFICATION = 17,
};
struct __packed picoboot_reboot_cmd {
uint32_t dPC; // 0 means reset into regular boot path
uint32_t dSP;
uint32_t dDelayMS;
};
// note this (with pc_sp) union member has the same layout as picoboot_reboot_cmd except with extra dFlags
struct __packed picoboot_reboot2_cmd {
uint32_t dFlags;
uint32_t dDelayMS;
uint32_t dParam0;
uint32_t dParam1;
};
// used for EXEC, VECTORIZE_FLASH
struct __packed picoboot_address_only_cmd {
uint32_t dAddr;
};
// used for READ, WRITE, FLASH_ERASE
struct __packed picoboot_range_cmd {
uint32_t dAddr;
uint32_t dSize;
};
struct __packed picoboot_exec2_cmd {
uint32_t image_base;
uint32_t image_size;
uint32_t workarea_base;
uint32_t workarea_size;
};
enum picoboot_exclusive_type {
NOT_EXCLUSIVE = 0,
EXCLUSIVE,
EXCLUSIVE_AND_EJECT
};
struct __packed picoboot_exclusive_cmd {
uint8_t bExclusive;
};
struct __packed picoboot_otp_cmd {
uint16_t wRow; // OTP row
uint16_t wRowCount; // number of rows to transfer
uint8_t bEcc; // use error correction (16 bit per register vs 24 (stored as 32) bit raw)
};
struct __packed picoboot_get_info_cmd {
uint8_t bType;
uint8_t bParam;
uint16_t wParam;
uint32_t dParams[3];
};
// little endian
struct __packed __aligned(4) picoboot_cmd {
uint32_t dMagic;
uint32_t dToken; // an identifier for this token to correlate with a status response
uint8_t bCmdId; // top bit set for IN
uint8_t bCmdSize; // bytes of actual data in the arg part of this structure
uint16_t _unused;
uint32_t dTransferLength; // length of IN/OUT transfer (or 0) if none
union {
uint8_t args[16];
struct picoboot_reboot_cmd reboot_cmd;
struct picoboot_range_cmd range_cmd;
struct picoboot_address_only_cmd address_only_cmd;
struct picoboot_exclusive_cmd exclusive_cmd;
struct picoboot_reboot2_cmd reboot2_cmd;
struct picoboot_otp_cmd otp_cmd;
struct picoboot_get_info_cmd get_info_cmd;
struct picoboot_exec2_cmd exec2_cmd;
};
};
static_assert(32 == sizeof(struct picoboot_cmd), "picoboot_cmd must be 32 bytes big");
struct __packed __aligned(4) picoboot_cmd_status {
uint32_t dToken;
uint32_t dStatusCode;
uint8_t bCmdId;
uint8_t bInProgress;
uint8_t _pad[6];
};
static_assert(16 == sizeof(struct picoboot_cmd_status), "picoboot_cmd_status must be 16 bytes big");
#endif