mirror of
https://github.com/mytechnotalent/Embedded-Hacking.git
synced 2026-04-06 11:22:26 +02:00
feat: add 0x0c_multicore_cbm bare-metal dual-core FIFO driver
This commit is contained in:
235
drivers/0x0c_multicore_cbm/Inc/rp2350.h
Normal file
235
drivers/0x0c_multicore_cbm/Inc/rp2350.h
Normal file
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350.h
|
||||
* @author Kevin Thomas
|
||||
* @brief RP2350 Device Peripheral Access Layer Header File.
|
||||
*
|
||||
* Memory-mapped register structures and peripheral base addresses
|
||||
* for the RP2350 microcontroller (Cortex-M33 dual-core). All
|
||||
* register offsets verified against the RP2350 datasheet
|
||||
* (RP-008373-DS-2).
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __RP2350_H
|
||||
#define __RP2350_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*!< Defines 'read / write' permissions */
|
||||
#define __IO volatile
|
||||
|
||||
/*!< Stack addresses */
|
||||
#define STACK_TOP 0x20082000UL
|
||||
#define STACK_LIMIT 0x2007A000UL
|
||||
|
||||
/*!< Memory map */
|
||||
#define XIP_BASE 0x10000000UL
|
||||
#define SRAM_BASE 0x20000000UL
|
||||
#define SIO_BASE 0xD0000000UL
|
||||
#define PPB_BASE 0xE0000000UL
|
||||
|
||||
/*!< APB peripherals */
|
||||
#define PSM_BASE 0x40018000UL
|
||||
#define CLOCKS_BASE 0x40010000UL
|
||||
#define RESETS_BASE 0x40020000UL
|
||||
#define IO_BANK0_BASE 0x40028000UL
|
||||
#define PADS_BANK0_BASE 0x40038000UL
|
||||
#define XOSC_BASE 0x40048000UL
|
||||
#define UART0_BASE 0x40070000UL
|
||||
|
||||
/*!< Atomic register alias offsets */
|
||||
#define ATOMIC_SET_OFFSET 0x2000UL
|
||||
#define ATOMIC_CLR_OFFSET 0x3000UL
|
||||
|
||||
/**
|
||||
* @brief XOSC (External Crystal Oscillator)
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t CTRL; // Control register Address offset: 0x00
|
||||
__IO uint32_t STATUS; // Status register Address offset: 0x04
|
||||
__IO uint32_t DORMANT; // Dormant mode Address offset: 0x08
|
||||
__IO uint32_t STARTUP; // Startup delay Address offset: 0x0C
|
||||
__IO uint32_t COUNT; // Frequency count Address offset: 0x10
|
||||
} XOSC_TypeDef;
|
||||
|
||||
/**
|
||||
* @brief CLOCKS
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t RESERVED0[12]; // GPOUT0..GPOUT3 registers Address offset: 0x00-0x2C
|
||||
__IO uint32_t CLK_REF_CTRL; // Reference clock control Address offset: 0x30
|
||||
__IO uint32_t RESERVED1[5]; // CLK_REF_DIV..CLK_SYS_SELECTED Address offset: 0x34-0x44
|
||||
__IO uint32_t CLK_PERI_CTRL; // Peripheral clock control Address offset: 0x48
|
||||
} CLOCKS_TypeDef;
|
||||
|
||||
/**
|
||||
* @brief RESETS
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t RESET; // Reset control Address offset: 0x00
|
||||
__IO uint32_t WDSEL; // Watchdog select Address offset: 0x04
|
||||
__IO uint32_t RESET_DONE; // Reset done status Address offset: 0x08
|
||||
} RESETS_TypeDef;
|
||||
|
||||
/**
|
||||
* @brief IO_BANK0 GPIO Control (one per GPIO)
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t STATUS; // GPIO status Address offset: 0x00
|
||||
__IO uint32_t CTRL; // GPIO control Address offset: 0x04
|
||||
} IO_BANK0_GPIO_TypeDef;
|
||||
|
||||
/**
|
||||
* @brief IO_BANK0
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
IO_BANK0_GPIO_TypeDef GPIO[30]; // GPIO 0-29 status/ctrl pairs Address offset: 0x000-0x0E8
|
||||
} IO_BANK0_TypeDef;
|
||||
|
||||
/**
|
||||
* @brief PADS_BANK0
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t VOLTAGE_SELECT; // Voltage select Address offset: 0x00
|
||||
__IO uint32_t GPIO[30]; // GPIO 0-29 pad control Address offset: 0x04-0x78
|
||||
} PADS_BANK0_TypeDef;
|
||||
|
||||
/**
|
||||
* @brief PSM (Power-on State Machine)
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t FRCE_ON; // Force block out of reset Address offset: 0x00
|
||||
__IO uint32_t FRCE_OFF; // Force block into reset Address offset: 0x04
|
||||
__IO uint32_t WDSEL; // Watchdog select Address offset: 0x08
|
||||
__IO uint32_t DONE; // Subsystem ready status Address offset: 0x0C
|
||||
} PSM_TypeDef;
|
||||
|
||||
/**
|
||||
* @brief Peripheral Definitions
|
||||
*/
|
||||
#define PSM ((PSM_TypeDef *) PSM_BASE)
|
||||
#define XOSC ((XOSC_TypeDef *) XOSC_BASE)
|
||||
#define CLOCKS ((CLOCKS_TypeDef *) CLOCKS_BASE)
|
||||
#define RESETS ((RESETS_TypeDef *) RESETS_BASE)
|
||||
#define IO_BANK0 ((IO_BANK0_TypeDef *) IO_BANK0_BASE)
|
||||
#define PADS_BANK0 ((PADS_BANK0_TypeDef *) PADS_BANK0_BASE)
|
||||
#define SIO ((volatile uint32_t *) SIO_BASE)
|
||||
#define CPACR ((volatile uint32_t *) (PPB_BASE + 0x0ED88UL))
|
||||
|
||||
/**
|
||||
* @brief XOSC bit definitions
|
||||
*/
|
||||
#define XOSC_STATUS_STABLE_SHIFT 31U
|
||||
|
||||
/**
|
||||
* @brief CPACR bit definitions
|
||||
*/
|
||||
#define CPACR_CP0_SHIFT 0U
|
||||
#define CPACR_CP1_SHIFT 1U
|
||||
|
||||
/**
|
||||
* @brief CLK_REF bit definitions
|
||||
*/
|
||||
#define CLK_REF_CTRL_SRC_XOSC 2U
|
||||
|
||||
/**
|
||||
* @brief CLOCKS bit definitions
|
||||
*/
|
||||
#define CLK_PERI_CTRL_ENABLE_SHIFT 11U
|
||||
#define CLK_PERI_CTRL_AUXSRC_SHIFT 5U
|
||||
#define CLK_PERI_CTRL_AUXSRC_MASK (0x07U << CLK_PERI_CTRL_AUXSRC_SHIFT)
|
||||
#define CLK_PERI_CTRL_AUXSRC_XOSC 4U
|
||||
|
||||
/**
|
||||
* @brief RESETS bit definitions
|
||||
*/
|
||||
#define RESETS_RESET_IO_BANK0_SHIFT 6U
|
||||
#define RESETS_RESET_PADS_BANK0_SHIFT 9U
|
||||
#define RESETS_RESET_UART0_SHIFT 26U
|
||||
|
||||
/**
|
||||
* @brief PSM bit definitions
|
||||
*/
|
||||
#define PSM_FRCE_OFF_PROC1_SHIFT 24U
|
||||
|
||||
/**
|
||||
* @brief IO_BANK0 bit definitions
|
||||
*/
|
||||
#define IO_BANK0_CTRL_FUNCSEL_MASK 0x1FU
|
||||
#define IO_BANK0_CTRL_FUNCSEL_UART 0x02U
|
||||
#define IO_BANK0_CTRL_FUNCSEL_SIO 0x05U
|
||||
#define IO_BANK0_CTRL_FUNCSEL_NULL 0x1FU
|
||||
|
||||
/**
|
||||
* @brief PADS_BANK0 bit definitions
|
||||
*/
|
||||
#define PADS_BANK0_OD_SHIFT 7U
|
||||
#define PADS_BANK0_IE_SHIFT 6U
|
||||
#define PADS_BANK0_ISO_SHIFT 8U
|
||||
#define PADS_BANK0_PUE_SHIFT 3U
|
||||
#define PADS_BANK0_PDE_SHIFT 2U
|
||||
|
||||
/**
|
||||
* @brief SIO GPIO register offsets (word indices from SIO_BASE)
|
||||
*/
|
||||
#define SIO_GPIO_OUT_SET_OFFSET (0x018U / 4U)
|
||||
#define SIO_GPIO_OUT_CLR_OFFSET (0x020U / 4U)
|
||||
#define SIO_GPIO_OE_SET_OFFSET (0x038U / 4U)
|
||||
|
||||
/**
|
||||
* @brief UART register offsets (word indices from UART0_BASE)
|
||||
*/
|
||||
#define UART_DR_OFFSET (0x000U / 4U)
|
||||
#define UART_FR_OFFSET (0x018U / 4U)
|
||||
#define UART_IBRD_OFFSET (0x024U / 4U)
|
||||
#define UART_FBRD_OFFSET (0x028U / 4U)
|
||||
#define UART_LCR_H_OFFSET (0x02CU / 4U)
|
||||
#define UART_CR_OFFSET (0x030U / 4U)
|
||||
|
||||
/**
|
||||
* @brief UART flag register bit definitions
|
||||
*/
|
||||
#define UART_FR_TXFF_MASK 32U
|
||||
#define UART_FR_RXFE_MASK 16U
|
||||
|
||||
/**
|
||||
* @brief UART line control and enable values
|
||||
*/
|
||||
#define UART_LCR_H_8N1_FIFO 0x70U
|
||||
#define UART_CR_ENABLE ((3U << 8) | 1U)
|
||||
|
||||
/**
|
||||
* @brief SIO FIFO register offsets (word indices from SIO_BASE)
|
||||
*/
|
||||
#define SIO_CPUID_OFFSET (0x000U / 4U)
|
||||
#define SIO_FIFO_ST_OFFSET (0x050U / 4U)
|
||||
#define SIO_FIFO_WR_OFFSET (0x054U / 4U)
|
||||
#define SIO_FIFO_RD_OFFSET (0x058U / 4U)
|
||||
|
||||
/**
|
||||
* @brief SIO FIFO status register bit definitions
|
||||
*/
|
||||
#define SIO_FIFO_ST_VLD_MASK (1U << 0)
|
||||
#define SIO_FIFO_ST_RDY_MASK (1U << 1)
|
||||
|
||||
#endif /* __RP2350_H */
|
||||
33
drivers/0x0c_multicore_cbm/Inc/rp2350_coprocessor.h
Normal file
33
drivers/0x0c_multicore_cbm/Inc/rp2350_coprocessor.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350_coprocessor.h
|
||||
* @author Kevin Thomas
|
||||
* @brief Coprocessor access control driver header for RP2350.
|
||||
*
|
||||
* Enables coprocessor access via the CPACR register.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __RP2350_COPROCESSOR_H
|
||||
#define __RP2350_COPROCESSOR_H
|
||||
|
||||
#include "rp2350.h"
|
||||
|
||||
/**
|
||||
* @brief Enable coprocessor access via CPACR with DSB/ISB barriers.
|
||||
* @retval None
|
||||
*/
|
||||
void coprocessor_enable(void);
|
||||
|
||||
#endif /* __RP2350_COPROCESSOR_H */
|
||||
42
drivers/0x0c_multicore_cbm/Inc/rp2350_delay.h
Normal file
42
drivers/0x0c_multicore_cbm/Inc/rp2350_delay.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350_delay.h
|
||||
* @author Kevin Thomas
|
||||
* @brief Delay driver header for RP2350.
|
||||
*
|
||||
* Millisecond and microsecond busy-wait delays calibrated for
|
||||
* a 12 MHz clock.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __RP2350_DELAY_H
|
||||
#define __RP2350_DELAY_H
|
||||
|
||||
#include "rp2350.h"
|
||||
|
||||
/**
|
||||
* @brief Delay for the specified number of milliseconds.
|
||||
* @param ms number of milliseconds to delay
|
||||
* @retval None
|
||||
*/
|
||||
void delay_ms(uint32_t ms);
|
||||
|
||||
/**
|
||||
* @brief Delay for the specified number of microseconds.
|
||||
* @param us number of microseconds to delay
|
||||
* @retval None
|
||||
*/
|
||||
void delay_us(uint32_t us);
|
||||
|
||||
#endif /* __RP2350_DELAY_H */
|
||||
62
drivers/0x0c_multicore_cbm/Inc/rp2350_multicore.h
Normal file
62
drivers/0x0c_multicore_cbm/Inc/rp2350_multicore.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350_multicore.h
|
||||
* @author Kevin Thomas
|
||||
* @brief Multicore driver header for RP2350.
|
||||
*
|
||||
* Bare-metal dual-core driver using the SIO inter-processor
|
||||
* FIFOs. Provides core 1 launch, blocking push, and blocking
|
||||
* pop operations for 32-bit mailbox messaging.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __RP2350_MULTICORE_H
|
||||
#define __RP2350_MULTICORE_H
|
||||
|
||||
#include "rp2350.h"
|
||||
|
||||
/**
|
||||
* @brief Launch a function on processor core 1.
|
||||
*
|
||||
* Resets core 1 via the PSM, then performs the FIFO handshake
|
||||
* protocol described in RP2350 datasheet Section 5.3 to pass
|
||||
* the vector table, stack pointer, and entry point.
|
||||
*
|
||||
* @param entry pointer to the void(void) function to run on core 1
|
||||
* @retval None
|
||||
*/
|
||||
void multicore_launch(void (*entry)(void));
|
||||
|
||||
/**
|
||||
* @brief Push a 32-bit value into the inter-core FIFO (blocking).
|
||||
*
|
||||
* Blocks until there is space in the TX FIFO, then writes the
|
||||
* value and signals the other core with SEV.
|
||||
*
|
||||
* @param data 32-bit value to send
|
||||
* @retval None
|
||||
*/
|
||||
void multicore_fifo_push(uint32_t data);
|
||||
|
||||
/**
|
||||
* @brief Pop a 32-bit value from the inter-core FIFO (blocking).
|
||||
*
|
||||
* Blocks with WFE until a value is available in the RX FIFO,
|
||||
* then returns it.
|
||||
*
|
||||
* @retval uint32_t value received from the other core
|
||||
*/
|
||||
uint32_t multicore_fifo_pop(void);
|
||||
|
||||
#endif /* __RP2350_MULTICORE_H */
|
||||
33
drivers/0x0c_multicore_cbm/Inc/rp2350_reset.h
Normal file
33
drivers/0x0c_multicore_cbm/Inc/rp2350_reset.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350_reset.h
|
||||
* @author Kevin Thomas
|
||||
* @brief Reset controller driver header for RP2350.
|
||||
*
|
||||
* Provides subsystem reset release for IO_BANK0.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __RP2350_RESET_H
|
||||
#define __RP2350_RESET_H
|
||||
|
||||
#include "rp2350.h"
|
||||
|
||||
/**
|
||||
* @brief Release IO_BANK0 from reset and wait until ready.
|
||||
* @retval None
|
||||
*/
|
||||
void reset_init_subsystem(void);
|
||||
|
||||
#endif /* __RP2350_RESET_H */
|
||||
33
drivers/0x0c_multicore_cbm/Inc/rp2350_reset_handler.h
Normal file
33
drivers/0x0c_multicore_cbm/Inc/rp2350_reset_handler.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350_reset_handler.h
|
||||
* @author Kevin Thomas
|
||||
* @brief Reset handler header for RP2350.
|
||||
*
|
||||
* Entry point after reset. Performs stack initialization, XOSC
|
||||
* setup, subsystem reset release, UART initialization,
|
||||
* coprocessor enable, and branches to main().
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __RP2350_RESET_HANDLER_H
|
||||
#define __RP2350_RESET_HANDLER_H
|
||||
|
||||
/**
|
||||
* @brief Reset handler entry point (naked, noreturn).
|
||||
* @retval None
|
||||
*/
|
||||
void Reset_Handler(void) __attribute__((noreturn));
|
||||
|
||||
#endif /* __RP2350_RESET_HANDLER_H */
|
||||
34
drivers/0x0c_multicore_cbm/Inc/rp2350_stack.h
Normal file
34
drivers/0x0c_multicore_cbm/Inc/rp2350_stack.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350_stack.h
|
||||
* @author Kevin Thomas
|
||||
* @brief Stack pointer initialization header for RP2350.
|
||||
*
|
||||
* Sets MSP, PSP, MSPLIM, and PSPLIM from the STACK_TOP and
|
||||
* STACK_LIMIT values defined in rp2350.h.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __RP2350_STACK_H
|
||||
#define __RP2350_STACK_H
|
||||
|
||||
#include "rp2350.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize MSP, PSP, MSPLIM, and PSPLIM stack pointers.
|
||||
* @retval None
|
||||
*/
|
||||
void stack_init(void);
|
||||
|
||||
#endif /* __RP2350_STACK_H */
|
||||
73
drivers/0x0c_multicore_cbm/Inc/rp2350_uart.h
Normal file
73
drivers/0x0c_multicore_cbm/Inc/rp2350_uart.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350_uart.h
|
||||
* @author Kevin Thomas
|
||||
* @brief UART0 driver header for RP2350.
|
||||
*
|
||||
* Bare-metal UART0 driver supporting TX/RX on GPIO 0/1 at
|
||||
* 115200 baud (12 MHz XOSC clock).
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __RP2350_UART_H
|
||||
#define __RP2350_UART_H
|
||||
|
||||
#include "rp2350.h"
|
||||
|
||||
/**
|
||||
* @brief Release UART0 from reset and wait until ready.
|
||||
* @retval None
|
||||
*/
|
||||
void uart_release_reset(void);
|
||||
|
||||
/**
|
||||
* @brief Initialize UART0 pins, baud rate, line control, and enable.
|
||||
* @retval None
|
||||
*/
|
||||
void uart_init(void);
|
||||
|
||||
/**
|
||||
* @brief Check whether a received byte is waiting in the UART FIFO.
|
||||
* @retval bool true if at least one byte is available
|
||||
*/
|
||||
bool uart_is_readable(void);
|
||||
|
||||
/**
|
||||
* @brief Read one character from UART0 (blocking).
|
||||
* @retval char the received character
|
||||
*/
|
||||
char uart_getchar(void);
|
||||
|
||||
/**
|
||||
* @brief Transmit one character over UART0 (blocking).
|
||||
* @param c character to transmit
|
||||
* @retval None
|
||||
*/
|
||||
void uart_putchar(char c);
|
||||
|
||||
/**
|
||||
* @brief Transmit a null-terminated string over UART0.
|
||||
* @param str pointer to the string to send
|
||||
* @retval None
|
||||
*/
|
||||
void uart_puts(const char *str);
|
||||
|
||||
/**
|
||||
* @brief Convert a lowercase ASCII character to uppercase.
|
||||
* @param c input character
|
||||
* @retval char uppercase equivalent or original character
|
||||
*/
|
||||
char uart_to_upper(char c);
|
||||
|
||||
#endif /* __RP2350_UART_H */
|
||||
46
drivers/0x0c_multicore_cbm/Inc/rp2350_xosc.h
Normal file
46
drivers/0x0c_multicore_cbm/Inc/rp2350_xosc.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350_xosc.h
|
||||
* @author Kevin Thomas
|
||||
* @brief XOSC driver header for RP2350.
|
||||
*
|
||||
* External crystal oscillator initialization and peripheral
|
||||
* clock enable using the XOSC registers.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __RP2350_XOSC_H
|
||||
#define __RP2350_XOSC_H
|
||||
|
||||
#include "rp2350.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize the external crystal oscillator and wait until stable.
|
||||
* @retval None
|
||||
*/
|
||||
void xosc_init(void);
|
||||
|
||||
/**
|
||||
* @brief Enable the XOSC peripheral clock via CLK_PERI_CTRL.
|
||||
* @retval None
|
||||
*/
|
||||
void xosc_enable_peri_clk(void);
|
||||
|
||||
/**
|
||||
* @brief Switch CLK_REF source to XOSC for a stable 12 MHz clk_sys.
|
||||
* @retval None
|
||||
*/
|
||||
void xosc_set_clk_ref(void);
|
||||
|
||||
#endif /* __RP2350_XOSC_H */
|
||||
79
drivers/0x0c_multicore_cbm/Makefile
Normal file
79
drivers/0x0c_multicore_cbm/Makefile
Normal file
@@ -0,0 +1,79 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# @file Makefile
|
||||
# @author Kevin Thomas
|
||||
# @brief Build script for RP2350 bare-metal C multicore FIFO driver.
|
||||
#
|
||||
# Compiles, links, and generates UF2 firmware for the RP2350.
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Toolchain
|
||||
CC = arm-none-eabi-gcc
|
||||
OBJCOPY = arm-none-eabi-objcopy
|
||||
SIZE = arm-none-eabi-size
|
||||
|
||||
# Target
|
||||
TARGET = multicore
|
||||
|
||||
# Directories
|
||||
SRC_DIR = Src
|
||||
INC_DIR = Inc
|
||||
BUILD_DIR = build
|
||||
|
||||
# CPU flags
|
||||
CPU_FLAGS = -mcpu=cortex-m33 -mthumb
|
||||
|
||||
# Compiler flags
|
||||
CFLAGS = $(CPU_FLAGS) -Og -g3 -Wall -Wextra \
|
||||
-ffunction-sections -fdata-sections \
|
||||
-I$(INC_DIR)
|
||||
|
||||
# Linker flags
|
||||
LDFLAGS = $(CPU_FLAGS) -T linker.ld -nostdlib -Wl,--gc-sections
|
||||
|
||||
# Source files
|
||||
SRCS = $(SRC_DIR)/vector_table.c \
|
||||
$(SRC_DIR)/rp2350_reset_handler.c \
|
||||
$(SRC_DIR)/rp2350_stack.c \
|
||||
$(SRC_DIR)/rp2350_xosc.c \
|
||||
$(SRC_DIR)/rp2350_reset.c \
|
||||
$(SRC_DIR)/rp2350_coprocessor.c \
|
||||
$(SRC_DIR)/rp2350_uart.c \
|
||||
$(SRC_DIR)/rp2350_multicore.c \
|
||||
$(SRC_DIR)/rp2350_delay.c \
|
||||
$(SRC_DIR)/main.c \
|
||||
$(SRC_DIR)/image_def.c
|
||||
|
||||
# Object files
|
||||
OBJS = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(SRCS))
|
||||
|
||||
# Rules
|
||||
.PHONY: all clean flash
|
||||
|
||||
all: $(BUILD_DIR)/$(TARGET).uf2
|
||||
@echo "==================================="
|
||||
@echo "SUCCESS! Created $(TARGET).bin and $(TARGET).uf2"
|
||||
@echo "==================================="
|
||||
|
||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/$(TARGET).elf: $(OBJS)
|
||||
$(CC) $(LDFLAGS) $(OBJS) -o $@
|
||||
$(SIZE) $@
|
||||
|
||||
$(BUILD_DIR)/$(TARGET).bin: $(BUILD_DIR)/$(TARGET).elf
|
||||
$(OBJCOPY) -O binary $< $@
|
||||
|
||||
$(BUILD_DIR)/$(TARGET).uf2: $(BUILD_DIR)/$(TARGET).bin
|
||||
python3 uf2conv.py -b 0x10000000 -f 0xe48bff59 -o $@ $<
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $(BUILD_DIR)
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
|
||||
flash: $(BUILD_DIR)/$(TARGET).elf
|
||||
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg \
|
||||
-c "adapter speed 5000" \
|
||||
-c "program $< verify reset exit"
|
||||
35
drivers/0x0c_multicore_cbm/Src/image_def.c
Normal file
35
drivers/0x0c_multicore_cbm/Src/image_def.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file image_def.c
|
||||
* @author Kevin Thomas
|
||||
* @brief RP2350 IMAGE_DEF block for boot ROM image recognition.
|
||||
*
|
||||
* Must appear within the first 4 KB of flash for the boot ROM
|
||||
* to accept the image.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief IMAGE_DEF block structure placed in flash
|
||||
*/
|
||||
__attribute__((section(".embedded_block"), used))
|
||||
const uint8_t picobin_block[] = {
|
||||
0xD3, 0xDE, 0xFF, 0xFF,
|
||||
0x42, 0x01, 0x21, 0x10,
|
||||
0xFF, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x79, 0x35, 0x12, 0xAB
|
||||
};
|
||||
144
drivers/0x0c_multicore_cbm/Src/main.c
Normal file
144
drivers/0x0c_multicore_cbm/Src/main.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file main.c
|
||||
* @author Kevin Thomas
|
||||
* @brief Multicore FIFO messaging demonstration.
|
||||
*
|
||||
* Core 0 launches core 1, then sends an incrementing counter
|
||||
* through the SIO inter-processor FIFO. Core 1 returns the
|
||||
* value plus one. Both values are printed over UART every
|
||||
* second.
|
||||
*
|
||||
* Wiring:
|
||||
* GPIO0 -> UART TX (USB-to-UART adapter RX)
|
||||
* GPIO1 -> UART RX (USB-to-UART adapter TX)
|
||||
* No external wiring required (dual-core on-chip)
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "rp2350_multicore.h"
|
||||
#include "rp2350_uart.h"
|
||||
#include "rp2350_delay.h"
|
||||
|
||||
/**
|
||||
* @brief Extract decimal digits from a value in reverse order.
|
||||
* @param value unsigned integer to convert
|
||||
* @param tmp output buffer for reversed digits (min 11 bytes)
|
||||
* @retval int number of digits written
|
||||
*/
|
||||
static int _extract_digits(uint32_t value, char *tmp)
|
||||
{
|
||||
int i = 0;
|
||||
if (value == 0)
|
||||
tmp[i++] = '0';
|
||||
while (value > 0) {
|
||||
tmp[i++] = '0' + (char)(value % 10);
|
||||
value /= 10;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reverse-copy a digit buffer into a null-terminated string.
|
||||
* @param tmp source buffer with reversed digits
|
||||
* @param len number of digits in source
|
||||
* @param buf destination buffer (must hold len + 1 bytes)
|
||||
* @retval None
|
||||
*/
|
||||
static void _reverse_copy(const char *tmp, int len, char *buf)
|
||||
{
|
||||
int j = 0;
|
||||
while (len > 0)
|
||||
buf[j++] = tmp[--len];
|
||||
buf[j] = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a uint32_t to a decimal null-terminated string.
|
||||
* @param value unsigned integer to convert
|
||||
* @param buf output buffer (min 12 bytes)
|
||||
* @retval None
|
||||
*/
|
||||
static void _uint_to_str(uint32_t value, char *buf)
|
||||
{
|
||||
char tmp[11];
|
||||
int len = _extract_digits(value, tmp);
|
||||
_reverse_copy(tmp, len, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Print a labelled decimal value over UART.
|
||||
* @param label text label to print before the value
|
||||
* @param value unsigned integer to print
|
||||
* @retval None
|
||||
*/
|
||||
static void _print_labeled_value(const char *label, uint32_t value)
|
||||
{
|
||||
char buf[12];
|
||||
uart_puts(label);
|
||||
_uint_to_str(value, buf);
|
||||
uart_puts(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Print a full sent/returned line over UART.
|
||||
* @param sent value sent by core 0
|
||||
* @param received value returned by core 1
|
||||
* @retval None
|
||||
*/
|
||||
static void _print_counter_line(uint32_t sent, uint32_t received)
|
||||
{
|
||||
_print_labeled_value("core0 sent: ", sent);
|
||||
_print_labeled_value(", core1 returned: ", received);
|
||||
uart_puts("\r\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Core 1 entry point: receive a value and return it plus one.
|
||||
* @retval None (does not return)
|
||||
*/
|
||||
static void _core1_main(void)
|
||||
{
|
||||
while (1) {
|
||||
uint32_t value = multicore_fifo_pop();
|
||||
multicore_fifo_push(value + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the counter to core 1, print the round-trip, delay.
|
||||
* @param counter pointer to the running counter (post-incremented)
|
||||
* @retval None
|
||||
*/
|
||||
static void _send_and_print(uint32_t *counter)
|
||||
{
|
||||
multicore_fifo_push(*counter);
|
||||
uint32_t response = multicore_fifo_pop();
|
||||
_print_counter_line(*counter, response);
|
||||
(*counter)++;
|
||||
delay_ms(1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Application entry point for the multicore FIFO demo.
|
||||
* @retval int does not return
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
uint32_t counter = 0;
|
||||
multicore_launch(_core1_main);
|
||||
uart_puts("Multicore FIFO demo initialized\r\n");
|
||||
while (1)
|
||||
_send_and_print(&counter);
|
||||
}
|
||||
34
drivers/0x0c_multicore_cbm/Src/rp2350_coprocessor.c
Normal file
34
drivers/0x0c_multicore_cbm/Src/rp2350_coprocessor.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350_coprocessor.c
|
||||
* @author Kevin Thomas
|
||||
* @brief Coprocessor access control driver implementation for RP2350.
|
||||
*
|
||||
* Grants access to coprocessors 0 and 1 by setting the
|
||||
* corresponding bits in CPACR with DSB/ISB barriers.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "rp2350_coprocessor.h"
|
||||
|
||||
void coprocessor_enable(void)
|
||||
{
|
||||
uint32_t value;
|
||||
value = *CPACR;
|
||||
value |= (1U << CPACR_CP1_SHIFT);
|
||||
value |= (1U << CPACR_CP0_SHIFT);
|
||||
*CPACR = value;
|
||||
__asm__ volatile ("dsb");
|
||||
__asm__ volatile ("isb");
|
||||
}
|
||||
55
drivers/0x0c_multicore_cbm/Src/rp2350_delay.c
Normal file
55
drivers/0x0c_multicore_cbm/Src/rp2350_delay.c
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350_delay.c
|
||||
* @author Kevin Thomas
|
||||
* @brief Delay driver implementation for RP2350.
|
||||
*
|
||||
* Busy-wait millisecond and microsecond delays calibrated for
|
||||
* a 12 MHz clock.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "rp2350_delay.h"
|
||||
|
||||
void delay_ms(uint32_t ms)
|
||||
{
|
||||
if (ms == 0)
|
||||
return;
|
||||
__asm__ volatile (
|
||||
"mov r4, #3600\n\t"
|
||||
"mul r5, %0, r4\n\t"
|
||||
"1:\n\t"
|
||||
"subs r5, #1\n\t"
|
||||
"bne 1b\n\t"
|
||||
:
|
||||
: "r" (ms)
|
||||
: "r4", "r5", "cc"
|
||||
);
|
||||
}
|
||||
|
||||
void delay_us(uint32_t us)
|
||||
{
|
||||
if (us == 0)
|
||||
return;
|
||||
__asm__ volatile (
|
||||
"mov r4, #4\n\t"
|
||||
"mul r5, %0, r4\n\t"
|
||||
"1:\n\t"
|
||||
"subs r5, #1\n\t"
|
||||
"bne 1b\n\t"
|
||||
:
|
||||
: "r" (us)
|
||||
: "r4", "r5", "cc"
|
||||
);
|
||||
}
|
||||
148
drivers/0x0c_multicore_cbm/Src/rp2350_multicore.c
Normal file
148
drivers/0x0c_multicore_cbm/Src/rp2350_multicore.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350_multicore.c
|
||||
* @author Kevin Thomas
|
||||
* @brief Multicore driver implementation for RP2350.
|
||||
*
|
||||
* Implements bare-metal core 1 launch via the PSM reset and
|
||||
* SIO FIFO handshake protocol (RP2350 datasheet Section 5.3).
|
||||
* Provides blocking push/pop for inter-core 32-bit messaging.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "rp2350_multicore.h"
|
||||
|
||||
/**
|
||||
* @brief Number of 32-bit words in the core 1 stack (4096 bytes).
|
||||
*/
|
||||
#define CORE1_STACK_WORDS 1024U
|
||||
|
||||
/**
|
||||
* @brief Core 1 stack array allocated in BSS.
|
||||
*/
|
||||
static uint32_t _core1_stack[CORE1_STACK_WORDS];
|
||||
|
||||
/**
|
||||
* @brief Drain all pending values from the RX FIFO.
|
||||
* @retval None
|
||||
*/
|
||||
static void _fifo_drain(void)
|
||||
{
|
||||
while (SIO[SIO_FIFO_ST_OFFSET] & SIO_FIFO_ST_VLD_MASK)
|
||||
(void)SIO[SIO_FIFO_RD_OFFSET];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Push one 32-bit word to the TX FIFO, blocking until ready.
|
||||
* @param data value to write
|
||||
* @retval None
|
||||
*/
|
||||
static void _fifo_push_blocking(uint32_t data)
|
||||
{
|
||||
while (!(SIO[SIO_FIFO_ST_OFFSET] & SIO_FIFO_ST_RDY_MASK)) {
|
||||
}
|
||||
SIO[SIO_FIFO_WR_OFFSET] = data;
|
||||
__asm__ volatile ("sev");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pop one 32-bit word from the RX FIFO, blocking until valid.
|
||||
* @retval uint32_t value read from the FIFO
|
||||
*/
|
||||
static uint32_t _fifo_pop_blocking(void)
|
||||
{
|
||||
while (!(SIO[SIO_FIFO_ST_OFFSET] & SIO_FIFO_ST_VLD_MASK)) {
|
||||
}
|
||||
return SIO[SIO_FIFO_RD_OFFSET];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Force core 1 into reset via PSM atomic set alias.
|
||||
* @retval None
|
||||
*/
|
||||
static void _set_frce_off_proc1(void)
|
||||
{
|
||||
volatile uint32_t *set = (volatile uint32_t *)((uintptr_t)&PSM->FRCE_OFF + ATOMIC_SET_OFFSET);
|
||||
*set = (1U << PSM_FRCE_OFF_PROC1_SHIFT);
|
||||
while (!(PSM->FRCE_OFF & (1U << PSM_FRCE_OFF_PROC1_SHIFT))) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release core 1 from reset via PSM atomic clear alias.
|
||||
* @retval None
|
||||
*/
|
||||
static void _clr_frce_off_proc1(void)
|
||||
{
|
||||
volatile uint32_t *clr = (volatile uint32_t *)((uintptr_t)&PSM->FRCE_OFF + ATOMIC_CLR_OFFSET);
|
||||
*clr = (1U << PSM_FRCE_OFF_PROC1_SHIFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset core 1 and wait for its boot FIFO acknowledgement.
|
||||
* @retval None
|
||||
*/
|
||||
static void _reset_core1(void)
|
||||
{
|
||||
_set_frce_off_proc1();
|
||||
_clr_frce_off_proc1();
|
||||
(void)_fifo_pop_blocking();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send one handshake word, draining the FIFO first for zeroes.
|
||||
* @param cmd the command word to send
|
||||
* @retval None
|
||||
*/
|
||||
static void _send_handshake_word(uint32_t cmd)
|
||||
{
|
||||
if (!cmd) {
|
||||
_fifo_drain();
|
||||
__asm__ volatile ("sev");
|
||||
}
|
||||
_fifo_push_blocking(cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform the six-word FIFO handshake to launch core 1.
|
||||
* @param entry pointer to the core 1 entry function
|
||||
* @retval None
|
||||
*/
|
||||
static void _launch_handshake(void (*entry)(void))
|
||||
{
|
||||
extern uint32_t __Vectors;
|
||||
uint32_t *sp = &_core1_stack[CORE1_STACK_WORDS];
|
||||
const uint32_t seq[] = {0, 0, 1, (uintptr_t)&__Vectors, (uintptr_t)sp, (uintptr_t)entry};
|
||||
uint32_t idx = 0;
|
||||
do {
|
||||
_send_handshake_word(seq[idx]);
|
||||
idx = (_fifo_pop_blocking() == seq[idx]) ? idx + 1 : 0;
|
||||
} while (idx < 6);
|
||||
}
|
||||
|
||||
void multicore_launch(void (*entry)(void))
|
||||
{
|
||||
_reset_core1();
|
||||
_launch_handshake(entry);
|
||||
}
|
||||
|
||||
void multicore_fifo_push(uint32_t data)
|
||||
{
|
||||
_fifo_push_blocking(data);
|
||||
}
|
||||
|
||||
uint32_t multicore_fifo_pop(void)
|
||||
{
|
||||
return _fifo_pop_blocking();
|
||||
}
|
||||
33
drivers/0x0c_multicore_cbm/Src/rp2350_reset.c
Normal file
33
drivers/0x0c_multicore_cbm/Src/rp2350_reset.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350_reset.c
|
||||
* @author Kevin Thomas
|
||||
* @brief Reset controller driver implementation for RP2350.
|
||||
*
|
||||
* Releases IO_BANK0 from reset and waits until the subsystem
|
||||
* is ready.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "rp2350_reset.h"
|
||||
|
||||
void reset_init_subsystem(void)
|
||||
{
|
||||
uint32_t value;
|
||||
value = RESETS->RESET;
|
||||
value &= ~(1U << RESETS_RESET_IO_BANK0_SHIFT);
|
||||
RESETS->RESET = value;
|
||||
while ((RESETS->RESET_DONE & (1U << RESETS_RESET_IO_BANK0_SHIFT)) == 0) {
|
||||
}
|
||||
}
|
||||
45
drivers/0x0c_multicore_cbm/Src/rp2350_reset_handler.c
Normal file
45
drivers/0x0c_multicore_cbm/Src/rp2350_reset_handler.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350_reset_handler.c
|
||||
* @author Kevin Thomas
|
||||
* @brief Reset handler implementation for RP2350.
|
||||
*
|
||||
* Entry point after power-on or system reset. Initializes the
|
||||
* stack, XOSC, subsystem resets, UART, coprocessor, then
|
||||
* branches to main().
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "rp2350_reset_handler.h"
|
||||
#include "rp2350_stack.h"
|
||||
#include "rp2350_xosc.h"
|
||||
#include "rp2350_reset.h"
|
||||
#include "rp2350_uart.h"
|
||||
#include "rp2350_coprocessor.h"
|
||||
|
||||
extern int main(void);
|
||||
|
||||
void __attribute__((naked, noreturn)) Reset_Handler(void)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"bl stack_init\n\t"
|
||||
"bl xosc_init\n\t"
|
||||
"bl xosc_enable_peri_clk\n\t"
|
||||
"bl reset_init_subsystem\n\t"
|
||||
"bl uart_release_reset\n\t"
|
||||
"bl uart_init\n\t"
|
||||
"bl coprocessor_enable\n\t"
|
||||
"b main\n\t"
|
||||
);
|
||||
}
|
||||
38
drivers/0x0c_multicore_cbm/Src/rp2350_stack.c
Normal file
38
drivers/0x0c_multicore_cbm/Src/rp2350_stack.c
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350_stack.c
|
||||
* @author Kevin Thomas
|
||||
* @brief Stack pointer initialization for RP2350.
|
||||
*
|
||||
* Sets MSP, PSP, MSPLIM, and PSPLIM using inline assembly.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "rp2350_stack.h"
|
||||
|
||||
void stack_init(void)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"ldr r0, =%0\n\t"
|
||||
"msr PSP, r0\n\t"
|
||||
"ldr r0, =%1\n\t"
|
||||
"msr MSPLIM, r0\n\t"
|
||||
"msr PSPLIM, r0\n\t"
|
||||
"ldr r0, =%0\n\t"
|
||||
"msr MSP, r0\n\t"
|
||||
:
|
||||
: "i" (STACK_TOP), "i" (STACK_LIMIT)
|
||||
: "r0"
|
||||
);
|
||||
}
|
||||
126
drivers/0x0c_multicore_cbm/Src/rp2350_uart.c
Normal file
126
drivers/0x0c_multicore_cbm/Src/rp2350_uart.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350_uart.c
|
||||
* @author Kevin Thomas
|
||||
* @brief UART0 driver implementation for RP2350.
|
||||
*
|
||||
* Configures UART0 on GPIO 0 (TX) and GPIO 1 (RX) at 115200
|
||||
* baud using the 12 MHz XOSC clock.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "rp2350_uart.h"
|
||||
|
||||
#define UART_BASE ((volatile uint32_t *) UART0_BASE)
|
||||
|
||||
/**
|
||||
* @brief Clear the UART0 reset bit in the reset controller.
|
||||
* @retval None
|
||||
*/
|
||||
static void _uart_clear_reset_bit(void)
|
||||
{
|
||||
uint32_t value;
|
||||
value = RESETS->RESET;
|
||||
value &= ~(1U << RESETS_RESET_UART0_SHIFT);
|
||||
RESETS->RESET = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait until the UART0 block is out of reset.
|
||||
* @retval None
|
||||
*/
|
||||
static void _uart_wait_reset_done(void)
|
||||
{
|
||||
while ((RESETS->RESET_DONE & (1U << RESETS_RESET_UART0_SHIFT)) == 0) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure GPIO pins 0 (TX) and 1 (RX) for UART function.
|
||||
* @retval None
|
||||
*/
|
||||
static void _uart_configure_pins(void)
|
||||
{
|
||||
IO_BANK0->GPIO[0].CTRL = IO_BANK0_CTRL_FUNCSEL_UART;
|
||||
IO_BANK0->GPIO[1].CTRL = IO_BANK0_CTRL_FUNCSEL_UART;
|
||||
PADS_BANK0->GPIO[0] = 0x04;
|
||||
PADS_BANK0->GPIO[1] = 0x40;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set UART0 baud rate divisors for 115200 at 12 MHz.
|
||||
* @retval None
|
||||
*/
|
||||
static void _uart_set_baud(void)
|
||||
{
|
||||
UART_BASE[UART_CR_OFFSET] = 0;
|
||||
UART_BASE[UART_IBRD_OFFSET] = 6;
|
||||
UART_BASE[UART_FBRD_OFFSET] = 33;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure line control and enable UART0.
|
||||
* @retval None
|
||||
*/
|
||||
static void _uart_enable(void)
|
||||
{
|
||||
UART_BASE[UART_LCR_H_OFFSET] = UART_LCR_H_8N1_FIFO;
|
||||
UART_BASE[UART_CR_OFFSET] = UART_CR_ENABLE;
|
||||
}
|
||||
|
||||
void uart_release_reset(void)
|
||||
{
|
||||
_uart_clear_reset_bit();
|
||||
_uart_wait_reset_done();
|
||||
}
|
||||
|
||||
void uart_init(void)
|
||||
{
|
||||
_uart_configure_pins();
|
||||
_uart_set_baud();
|
||||
_uart_enable();
|
||||
}
|
||||
|
||||
bool uart_is_readable(void)
|
||||
{
|
||||
return (UART_BASE[UART_FR_OFFSET] & UART_FR_RXFE_MASK) == 0;
|
||||
}
|
||||
|
||||
char uart_getchar(void)
|
||||
{
|
||||
while (UART_BASE[UART_FR_OFFSET] & UART_FR_RXFE_MASK) {
|
||||
}
|
||||
return (char)(UART_BASE[UART_DR_OFFSET] & 0xFF);
|
||||
}
|
||||
|
||||
void uart_putchar(char c)
|
||||
{
|
||||
while (UART_BASE[UART_FR_OFFSET] & UART_FR_TXFF_MASK) {
|
||||
}
|
||||
UART_BASE[UART_DR_OFFSET] = (uint32_t)c;
|
||||
}
|
||||
|
||||
void uart_puts(const char *str)
|
||||
{
|
||||
while (*str) {
|
||||
uart_putchar(*str++);
|
||||
}
|
||||
}
|
||||
|
||||
char uart_to_upper(char c)
|
||||
{
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return (char)(c - 32);
|
||||
return c;
|
||||
}
|
||||
46
drivers/0x0c_multicore_cbm/Src/rp2350_xosc.c
Normal file
46
drivers/0x0c_multicore_cbm/Src/rp2350_xosc.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rp2350_xosc.c
|
||||
* @author Kevin Thomas
|
||||
* @brief XOSC driver implementation for RP2350.
|
||||
*
|
||||
* Configures the external crystal oscillator and enables the
|
||||
* peripheral clock sourced from XOSC.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "rp2350_xosc.h"
|
||||
|
||||
void xosc_init(void)
|
||||
{
|
||||
XOSC->STARTUP = 0x00C4U;
|
||||
XOSC->CTRL = 0x00FABAA0U;
|
||||
while ((XOSC->STATUS & (1U << XOSC_STATUS_STABLE_SHIFT)) == 0) {
|
||||
}
|
||||
}
|
||||
|
||||
void xosc_enable_peri_clk(void)
|
||||
{
|
||||
uint32_t value;
|
||||
value = CLOCKS->CLK_PERI_CTRL;
|
||||
value &= ~CLK_PERI_CTRL_AUXSRC_MASK;
|
||||
value |= (1U << CLK_PERI_CTRL_ENABLE_SHIFT);
|
||||
value |= (CLK_PERI_CTRL_AUXSRC_XOSC << CLK_PERI_CTRL_AUXSRC_SHIFT);
|
||||
CLOCKS->CLK_PERI_CTRL = value;
|
||||
}
|
||||
|
||||
void xosc_set_clk_ref(void)
|
||||
{
|
||||
CLOCKS->CLK_REF_CTRL = CLK_REF_CTRL_SRC_XOSC;
|
||||
}
|
||||
38
drivers/0x0c_multicore_cbm/Src/vector_table.c
Normal file
38
drivers/0x0c_multicore_cbm/Src/vector_table.c
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file vector_table.c
|
||||
* @author Kevin Thomas
|
||||
* @brief Vector table with initial stack pointer and reset handler.
|
||||
*
|
||||
* Placed in the .vectors section at the start of flash.
|
||||
* The Thumb bit (bit 0 = 1) is automatically set by the
|
||||
* linker for function pointers in Thumb mode.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint32_t _stack_top;
|
||||
extern void Reset_Handler(void);
|
||||
|
||||
typedef void (*vector_func_t)(void);
|
||||
|
||||
/**
|
||||
* @brief Vector table placed in .vectors section
|
||||
*/
|
||||
__attribute__((section(".vectors"), used))
|
||||
const void *_vectors[2] = {
|
||||
&_stack_top,
|
||||
Reset_Handler
|
||||
};
|
||||
125
drivers/0x0c_multicore_cbm/linker.ld
Normal file
125
drivers/0x0c_multicore_cbm/linker.ld
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file linker.ld
|
||||
* @author Kevin Thomas
|
||||
* @brief Minimal linker script for bare-metal RP2350 development.
|
||||
*
|
||||
* Defines FLASH (XIP 32 MB) and RAM (520 kB SRAM) regions.
|
||||
* The vector table is placed at the start of flash (0x10000000).
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2026 Kevin Thomas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Entry point.
|
||||
*/
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
/**
|
||||
* Define memory regions.
|
||||
*/
|
||||
__XIP_BASE = 0x10000000;
|
||||
__XIP_SIZE = 32M;
|
||||
|
||||
__SRAM_BASE = 0x20000000;
|
||||
__SRAM_SIZE = 520K;
|
||||
__STACK_SIZE = 32K;
|
||||
|
||||
/**
|
||||
* Memory layout.
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
RAM (rwx) : ORIGIN = __SRAM_BASE, LENGTH = __SRAM_SIZE
|
||||
FLASH (rx) : ORIGIN = __XIP_BASE, LENGTH = __XIP_SIZE
|
||||
}
|
||||
|
||||
/**
|
||||
* Program headers.
|
||||
*/
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD FLAGS(5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Section placement.
|
||||
*/
|
||||
SECTIONS
|
||||
{
|
||||
. = ORIGIN(FLASH);
|
||||
|
||||
/**
|
||||
* Vector table MUST be first at 0x10000000.
|
||||
*/
|
||||
.vectors :
|
||||
{
|
||||
KEEP(*(.vectors))
|
||||
} > FLASH :text
|
||||
|
||||
/**
|
||||
* Verify vector table placement.
|
||||
*/
|
||||
ASSERT((ADDR(.vectors) == ORIGIN(FLASH)),
|
||||
"Vector table must be at start of flash (0x10000000)")
|
||||
|
||||
/**
|
||||
* Text and read-only data.
|
||||
*/
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.text*)
|
||||
*(.rodata*)
|
||||
KEEP(*(.init))
|
||||
KEEP(*(.fini))
|
||||
KEEP(*(.ARM.attributes))
|
||||
} > FLASH :text
|
||||
|
||||
/**
|
||||
* IMAGE_DEF block at end of code.
|
||||
*/
|
||||
.embedded_block :
|
||||
{
|
||||
KEEP(*(.embedded_block))
|
||||
} > FLASH :text
|
||||
|
||||
/**
|
||||
* Uninitialized data (BSS) in RAM.
|
||||
*/
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
} > RAM
|
||||
|
||||
/**
|
||||
* Non-secure stack symbols.
|
||||
*/
|
||||
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
|
||||
__StackLimit = __StackTop - __STACK_SIZE;
|
||||
__stack = __StackTop;
|
||||
_stack_top = __StackTop;
|
||||
|
||||
/**
|
||||
* Stack section (no load).
|
||||
*/
|
||||
.stack (NOLOAD) : { . = ALIGN(8); } > RAM
|
||||
|
||||
/**
|
||||
* Provide vector table symbol to startup code.
|
||||
*/
|
||||
PROVIDE(__Vectors = ADDR(.vectors));
|
||||
}
|
||||
438
drivers/0x0c_multicore_cbm/uf2conv.py
Normal file
438
drivers/0x0c_multicore_cbm/uf2conv.py
Normal file
@@ -0,0 +1,438 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import struct
|
||||
import subprocess
|
||||
import re
|
||||
import os
|
||||
import os.path
|
||||
import argparse
|
||||
import json
|
||||
from time import sleep
|
||||
|
||||
|
||||
UF2_MAGIC_START0 = 0x0A324655 # "UF2\n"
|
||||
UF2_MAGIC_START1 = 0x9E5D5157 # Randomly selected
|
||||
UF2_MAGIC_END = 0x0AB16F30 # Ditto
|
||||
|
||||
INFO_FILE = "/INFO_UF2.TXT"
|
||||
|
||||
appstartaddr = 0x2000
|
||||
familyid = 0x0
|
||||
|
||||
|
||||
def is_uf2(buf):
|
||||
w = struct.unpack("<II", buf[0:8])
|
||||
return w[0] == UF2_MAGIC_START0 and w[1] == UF2_MAGIC_START1
|
||||
|
||||
|
||||
def is_hex(buf):
|
||||
try:
|
||||
w = buf[0:30].decode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
return False
|
||||
if w[0] == ":" and re.match(rb"^[:0-9a-fA-F\r\n]+$", buf):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def convert_from_uf2(buf):
|
||||
global appstartaddr
|
||||
global familyid
|
||||
numblocks = len(buf) // 512
|
||||
curraddr = None
|
||||
currfamilyid = None
|
||||
families_found = {}
|
||||
prev_flag = None
|
||||
all_flags_same = True
|
||||
outp = []
|
||||
for blockno in range(numblocks):
|
||||
ptr = blockno * 512
|
||||
block = buf[ptr : ptr + 512]
|
||||
hd = struct.unpack(b"<IIIIIIII", block[0:32])
|
||||
if hd[0] != UF2_MAGIC_START0 or hd[1] != UF2_MAGIC_START1:
|
||||
print("Skipping block at " + ptr + "; bad magic")
|
||||
continue
|
||||
if hd[2] & 1:
|
||||
# NO-flash flag set; skip block
|
||||
continue
|
||||
datalen = hd[4]
|
||||
if datalen > 476:
|
||||
assert False, "Invalid UF2 data size at " + ptr
|
||||
newaddr = hd[3]
|
||||
if (hd[2] & 0x2000) and (currfamilyid == None):
|
||||
currfamilyid = hd[7]
|
||||
if curraddr == None or ((hd[2] & 0x2000) and hd[7] != currfamilyid):
|
||||
currfamilyid = hd[7]
|
||||
curraddr = newaddr
|
||||
if familyid == 0x0 or familyid == hd[7]:
|
||||
appstartaddr = newaddr
|
||||
padding = newaddr - curraddr
|
||||
if padding < 0:
|
||||
assert False, "Block out of order at " + ptr
|
||||
if padding > 10 * 1024 * 1024:
|
||||
assert False, "More than 10M of padding needed at " + ptr
|
||||
if padding % 4 != 0:
|
||||
assert False, "Non-word padding size at " + ptr
|
||||
while padding > 0:
|
||||
padding -= 4
|
||||
outp.append(b"\x00\x00\x00\x00")
|
||||
if familyid == 0x0 or ((hd[2] & 0x2000) and familyid == hd[7]):
|
||||
outp.append(block[32 : 32 + datalen])
|
||||
curraddr = newaddr + datalen
|
||||
if hd[2] & 0x2000:
|
||||
if hd[7] in families_found.keys():
|
||||
if families_found[hd[7]] > newaddr:
|
||||
families_found[hd[7]] = newaddr
|
||||
else:
|
||||
families_found[hd[7]] = newaddr
|
||||
if prev_flag == None:
|
||||
prev_flag = hd[2]
|
||||
if prev_flag != hd[2]:
|
||||
all_flags_same = False
|
||||
if blockno == (numblocks - 1):
|
||||
print("--- UF2 File Header Info ---")
|
||||
families = load_families()
|
||||
for family_hex in families_found.keys():
|
||||
family_short_name = ""
|
||||
for name, value in families.items():
|
||||
if value == family_hex:
|
||||
family_short_name = name
|
||||
print(
|
||||
"Family ID is {:s}, hex value is 0x{:08x}".format(
|
||||
family_short_name, family_hex
|
||||
)
|
||||
)
|
||||
print("Target Address is 0x{:08x}".format(families_found[family_hex]))
|
||||
if all_flags_same:
|
||||
print("All block flag values consistent, 0x{:04x}".format(hd[2]))
|
||||
else:
|
||||
print("Flags were not all the same")
|
||||
print("----------------------------")
|
||||
if len(families_found) > 1 and familyid == 0x0:
|
||||
outp = []
|
||||
appstartaddr = 0x0
|
||||
return b"".join(outp)
|
||||
|
||||
|
||||
def convert_to_carray(file_content):
|
||||
outp = "const unsigned long bindata_len = %d;\n" % len(file_content)
|
||||
outp += "const unsigned char bindata[] __attribute__((aligned(16))) = {"
|
||||
for i in range(len(file_content)):
|
||||
if i % 16 == 0:
|
||||
outp += "\n"
|
||||
outp += "0x%02x, " % file_content[i]
|
||||
outp += "\n};\n"
|
||||
return bytes(outp, "utf-8")
|
||||
|
||||
|
||||
def convert_to_uf2(file_content):
|
||||
global familyid
|
||||
datapadding = b""
|
||||
while len(datapadding) < 512 - 256 - 32 - 4:
|
||||
datapadding += b"\x00\x00\x00\x00"
|
||||
numblocks = (len(file_content) + 255) // 256
|
||||
outp = []
|
||||
for blockno in range(numblocks):
|
||||
ptr = 256 * blockno
|
||||
chunk = file_content[ptr : ptr + 256]
|
||||
flags = 0x0
|
||||
if familyid:
|
||||
flags |= 0x2000
|
||||
hd = struct.pack(
|
||||
b"<IIIIIIII",
|
||||
UF2_MAGIC_START0,
|
||||
UF2_MAGIC_START1,
|
||||
flags,
|
||||
ptr + appstartaddr,
|
||||
256,
|
||||
blockno,
|
||||
numblocks,
|
||||
familyid,
|
||||
)
|
||||
while len(chunk) < 256:
|
||||
chunk += b"\x00"
|
||||
block = hd + chunk + datapadding + struct.pack(b"<I", UF2_MAGIC_END)
|
||||
assert len(block) == 512
|
||||
outp.append(block)
|
||||
return b"".join(outp)
|
||||
|
||||
|
||||
class Block:
|
||||
def __init__(self, addr, default_data=0xFF):
|
||||
self.addr = addr
|
||||
self.bytes = bytearray([default_data] * 256)
|
||||
|
||||
def encode(self, blockno, numblocks):
|
||||
global familyid
|
||||
flags = 0x0
|
||||
if familyid:
|
||||
flags |= 0x2000
|
||||
hd = struct.pack(
|
||||
"<IIIIIIII",
|
||||
UF2_MAGIC_START0,
|
||||
UF2_MAGIC_START1,
|
||||
flags,
|
||||
self.addr,
|
||||
256,
|
||||
blockno,
|
||||
numblocks,
|
||||
familyid,
|
||||
)
|
||||
hd += self.bytes[0:256]
|
||||
while len(hd) < 512 - 4:
|
||||
hd += b"\x00"
|
||||
hd += struct.pack("<I", UF2_MAGIC_END)
|
||||
return hd
|
||||
|
||||
|
||||
def convert_from_hex_to_uf2(buf):
|
||||
global appstartaddr
|
||||
appstartaddr = None
|
||||
upper = 0
|
||||
currblock = None
|
||||
blocks = []
|
||||
for line in buf.split("\n"):
|
||||
if line[0] != ":":
|
||||
continue
|
||||
i = 1
|
||||
rec = []
|
||||
while i < len(line) - 1:
|
||||
rec.append(int(line[i : i + 2], 16))
|
||||
i += 2
|
||||
tp = rec[3]
|
||||
if tp == 4:
|
||||
upper = ((rec[4] << 8) | rec[5]) << 16
|
||||
elif tp == 2:
|
||||
upper = ((rec[4] << 8) | rec[5]) << 4
|
||||
elif tp == 1:
|
||||
break
|
||||
elif tp == 0:
|
||||
addr = upper + ((rec[1] << 8) | rec[2])
|
||||
if appstartaddr == None:
|
||||
appstartaddr = addr
|
||||
i = 4
|
||||
while i < len(rec) - 1:
|
||||
if not currblock or currblock.addr & ~0xFF != addr & ~0xFF:
|
||||
currblock = Block(addr & ~0xFF)
|
||||
blocks.append(currblock)
|
||||
currblock.bytes[addr & 0xFF] = rec[i]
|
||||
addr += 1
|
||||
i += 1
|
||||
numblocks = len(blocks)
|
||||
resfile = b""
|
||||
for i in range(0, numblocks):
|
||||
resfile += blocks[i].encode(i, numblocks)
|
||||
return resfile
|
||||
|
||||
|
||||
def to_str(b):
|
||||
return b.decode("utf-8")
|
||||
|
||||
|
||||
def get_drives():
|
||||
drives = []
|
||||
if sys.platform == "win32":
|
||||
r = subprocess.check_output(
|
||||
[
|
||||
"powershell",
|
||||
"-Command",
|
||||
"(Get-WmiObject Win32_LogicalDisk -Filter \"VolumeName='RPI-RP2'\").DeviceID",
|
||||
]
|
||||
)
|
||||
drive = to_str(r).strip()
|
||||
if drive:
|
||||
drives.append(drive)
|
||||
else:
|
||||
searchpaths = ["/mnt", "/media"]
|
||||
if sys.platform == "darwin":
|
||||
searchpaths = ["/Volumes"]
|
||||
elif sys.platform == "linux":
|
||||
searchpaths += [
|
||||
"/media/" + os.environ["USER"],
|
||||
"/run/media/" + os.environ["USER"],
|
||||
]
|
||||
if "SUDO_USER" in os.environ.keys():
|
||||
searchpaths += ["/media/" + os.environ["SUDO_USER"]]
|
||||
searchpaths += ["/run/media/" + os.environ["SUDO_USER"]]
|
||||
|
||||
for rootpath in searchpaths:
|
||||
if os.path.isdir(rootpath):
|
||||
for d in os.listdir(rootpath):
|
||||
if os.path.isdir(os.path.join(rootpath, d)):
|
||||
drives.append(os.path.join(rootpath, d))
|
||||
|
||||
def has_info(d):
|
||||
try:
|
||||
return os.path.isfile(d + INFO_FILE)
|
||||
except:
|
||||
return False
|
||||
|
||||
return list(filter(has_info, drives))
|
||||
|
||||
|
||||
def board_id(path):
|
||||
with open(path + INFO_FILE, mode="r") as file:
|
||||
file_content = file.read()
|
||||
return re.search(r"Board-ID: ([^\r\n]*)", file_content).group(1)
|
||||
|
||||
|
||||
def list_drives():
|
||||
for d in get_drives():
|
||||
print(d, board_id(d))
|
||||
|
||||
|
||||
def write_file(name, buf):
|
||||
with open(name, "wb") as f:
|
||||
f.write(buf)
|
||||
print("Wrote %d bytes to %s" % (len(buf), name))
|
||||
|
||||
|
||||
def load_families():
|
||||
# The expectation is that the `uf2families.json` file is in the same
|
||||
# directory as this script. Make a path that works using `__file__`
|
||||
# which contains the full path to this script.
|
||||
filename = "uf2families.json"
|
||||
pathname = os.path.join(os.path.dirname(os.path.abspath(__file__)), filename)
|
||||
with open(pathname) as f:
|
||||
raw_families = json.load(f)
|
||||
|
||||
families = {}
|
||||
for family in raw_families:
|
||||
families[family["short_name"]] = int(family["id"], 0)
|
||||
|
||||
return families
|
||||
|
||||
|
||||
def main():
|
||||
global appstartaddr, familyid
|
||||
|
||||
def error(msg):
|
||||
print(msg, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
parser = argparse.ArgumentParser(description="Convert to UF2 or flash directly.")
|
||||
parser.add_argument(
|
||||
"input",
|
||||
metavar="INPUT",
|
||||
type=str,
|
||||
nargs="?",
|
||||
help="input file (HEX, BIN or UF2)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-b",
|
||||
"--base",
|
||||
dest="base",
|
||||
type=str,
|
||||
default="0x2000",
|
||||
help="set base address of application for BIN format (default: 0x2000)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-f",
|
||||
"--family",
|
||||
dest="family",
|
||||
type=str,
|
||||
default="0x0",
|
||||
help="specify familyID - number or name (default: 0x0)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-o",
|
||||
"--output",
|
||||
metavar="FILE",
|
||||
dest="output",
|
||||
type=str,
|
||||
help='write output to named file; defaults to "flash.uf2" or "flash.bin" where sensible',
|
||||
)
|
||||
parser.add_argument(
|
||||
"-d", "--device", dest="device_path", help="select a device path to flash"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-l", "--list", action="store_true", help="list connected devices"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-c", "--convert", action="store_true", help="do not flash, just convert"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-D", "--deploy", action="store_true", help="just flash, do not convert"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-w", "--wait", action="store_true", help="wait for device to flash"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-C",
|
||||
"--carray",
|
||||
action="store_true",
|
||||
help="convert binary file to a C array, not UF2",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-i",
|
||||
"--info",
|
||||
action="store_true",
|
||||
help="display header information from UF2, do not convert",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
appstartaddr = int(args.base, 0)
|
||||
|
||||
families = load_families()
|
||||
|
||||
if args.family.upper() in families:
|
||||
familyid = families[args.family.upper()]
|
||||
else:
|
||||
try:
|
||||
familyid = int(args.family, 0)
|
||||
except ValueError:
|
||||
error(
|
||||
"Family ID needs to be a number or one of: "
|
||||
+ ", ".join(families.keys())
|
||||
)
|
||||
|
||||
if args.list:
|
||||
list_drives()
|
||||
else:
|
||||
if not args.input:
|
||||
error("Need input file")
|
||||
with open(args.input, mode="rb") as f:
|
||||
inpbuf = f.read()
|
||||
from_uf2 = is_uf2(inpbuf)
|
||||
ext = "uf2"
|
||||
if args.deploy:
|
||||
outbuf = inpbuf
|
||||
elif from_uf2 and not args.info:
|
||||
outbuf = convert_from_uf2(inpbuf)
|
||||
ext = "bin"
|
||||
elif from_uf2 and args.info:
|
||||
outbuf = ""
|
||||
convert_from_uf2(inpbuf)
|
||||
elif is_hex(inpbuf):
|
||||
outbuf = convert_from_hex_to_uf2(inpbuf.decode("utf-8"))
|
||||
elif args.carray:
|
||||
outbuf = convert_to_carray(inpbuf)
|
||||
ext = "h"
|
||||
else:
|
||||
outbuf = convert_to_uf2(inpbuf)
|
||||
if not args.deploy and not args.info:
|
||||
print(
|
||||
"Converted to %s, output size: %d, start address: 0x%x"
|
||||
% (ext, len(outbuf), appstartaddr)
|
||||
)
|
||||
if args.convert or ext != "uf2":
|
||||
if args.output == None:
|
||||
args.output = "flash." + ext
|
||||
if args.output:
|
||||
write_file(args.output, outbuf)
|
||||
if ext == "uf2" and not args.convert and not args.info:
|
||||
drives = get_drives()
|
||||
if len(drives) == 0:
|
||||
if args.wait:
|
||||
print("Waiting for drive to deploy...")
|
||||
while len(drives) == 0:
|
||||
sleep(0.1)
|
||||
drives = get_drives()
|
||||
elif not args.output:
|
||||
error("No drive to deploy.")
|
||||
for d in drives:
|
||||
print("Flashing %s (%s)" % (d, board_id(d)))
|
||||
write_file(d + "/NEW.UF2", outbuf)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
22
drivers/0x0c_multicore_cbm/uf2families.json
Normal file
22
drivers/0x0c_multicore_cbm/uf2families.json
Normal file
@@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"short_name": "RP2040",
|
||||
"id": "0xe48bff56",
|
||||
"description": "Raspberry Pi RP2040"
|
||||
},
|
||||
{
|
||||
"short_name": "RP2350-ARM-S",
|
||||
"id": "0xe48bff59",
|
||||
"description": "Raspberry Pi RP2350, ARM, Secure"
|
||||
},
|
||||
{
|
||||
"short_name": "RP2350-ARM-NS",
|
||||
"id": "0xe48bff5a",
|
||||
"description": "Raspberry Pi RP2350, ARM, Non-Secure"
|
||||
},
|
||||
{
|
||||
"short_name": "RP2350-RISCV",
|
||||
"id": "0xe48bff5b",
|
||||
"description": "Raspberry Pi RP2350, RISC-V"
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user