mc: pic32cz: better state reset before boot

pull/850/head
Marco Oliverio 2026-08-04 09:50:01 +02:00 committed by Daniele Lacamera
parent c46c3278a4
commit 955b07cc0b
2 changed files with 64 additions and 8 deletions

View File

@ -27,6 +27,7 @@
#ifdef DEBUG_UART
#include "uart_drv.h"
void uart_deinit(void);
#endif
#if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT)
@ -60,6 +61,9 @@
#endif /* WOLFBOOT_ENABLE_WOLFHSM_CLIENT */
/* if the SUPC PLL regulator was already on at reset */
static int pic32_vreg_pll_was_enabled = 0;
#define SUPC_BASE (0x44020000U)
#define SUPC_VREGCTRL (*(volatile uint32_t *)(SUPC_BASE + 0x1CU))
#define SUPC_STATUS (*(volatile uint32_t *)(SUPC_BASE + 0x0CU))
@ -69,14 +73,34 @@
#define SUPC_STATUS_ADDVREGRDY_PLL (4)
#define SUPC_STATUS_ADDVREGRDY_SHIFT (8)
static void pic32_delay_cnt(uint32_t ticks)
{
uint32_t i = 0;
for (i = 0; i < ticks; i++) {
__asm__("nop");
}
}
#define PLL_VREG_SETTLE_TICKS (4000)
static void pic32_supc_vreg_pll_enable(void)
{
pic32_vreg_pll_was_enabled =
((SUPC_VREGCTRL >> SUPC_VREGCTRL_AVREGEN_SHIFT)
& SUPC_VREGCTRL_AVREGEN_PLLREG_EN) != 0;
if (pic32_vreg_pll_was_enabled) {
return;
}
SUPC_VREGCTRL |= SUPC_VREGCTRL_AVREGEN_PLLREG_EN
<< SUPC_VREGCTRL_AVREGEN_SHIFT;
/* wait for the vreg to be ready */
while (!(SUPC_STATUS &
(SUPC_STATUS_ADDVREGRDY_PLL << SUPC_STATUS_ADDVREGRDY_SHIFT))) {}
pic32_delay_cnt(PLL_VREG_SETTLE_TICKS);
}
#ifdef DUALBANK_SWAP
@ -106,14 +130,6 @@ int hal_flash_erase(uint32_t addr, int len)
return pic32_flash_erase(addr, len);
}
static void pic32_delay_cnt(uint32_t ticks)
{
uint32_t i = 0;
for (i = 0; i < ticks; i++) {
__asm__("nop");
}
}
void hal_init(void)
{
#if defined(TEST_CLOCK)
@ -144,7 +160,16 @@ void hal_init(void)
void hal_prepare_boot(void)
{
#ifdef WOLFBOOT_RESTORE_CLOCK
#ifdef DEBUG_UART
uart_deinit();
#endif
pic32_clock_reset();
if (!pic32_vreg_pll_was_enabled) {
SUPC_VREGCTRL &= ~((uint32_t)SUPC_VREGCTRL_AVREGEN_PLLREG_EN
<< SUPC_VREGCTRL_AVREGEN_SHIFT);
}
#endif
}

View File

@ -49,6 +49,7 @@
#define SERCOM_SYNCBUSY (*(volatile uint32_t*)(SERCOM1 + 0x1CU))
#define SERCOM_DATA (*(volatile uint32_t*)(SERCOM1 + 0x28U))
#define CTRLA_SWRST (0x1U << 0)
#define CTRLA_MODE_USART_INT (0x1U << 2) /* USART with internal clock */
#define CTRLA_ENABLE (0x1U << 1)
#define CTRLA_IBON (0x1U << 8)
@ -59,6 +60,7 @@
#define CTRLB_TXEN (0x1U << 16)
#define INTFLAG_DRE (0x1U << 0) /* Data Register Empty */
#define INTFLAG_TXC (0x1U << 1) /* Transmit Complete */
/* GCLK: generator 1 sources SERCOM1 */
#define GCLK_GENCTRL1 (*(volatile uint32_t*)(GCLK_BASE + 0x20U + (1 * 4)))
@ -139,6 +141,35 @@ int uart_init(uint32_t bitrate, uint8_t data, char parity, uint8_t stop)
return 0;
}
#define TXC_WAIT_MAX (200000U)
void uart_deinit(void)
{
uint32_t spin;
/* drain tx */
for (spin = 0U; spin < TXC_WAIT_MAX; spin++) {
if ((SERCOM_INTFLAG & INTFLAG_TXC) != 0U) {
break;
}
}
SERCOM_CTRLA &= ~(uint32_t)CTRLA_ENABLE;
while (SERCOM_SYNCBUSY != 0U) {
/* wait sync */
}
SERCOM_CTRLA = CTRLA_SWRST;
while (SERCOM_SYNCBUSY != 0U) {
/* wait sync */
}
PORTC_PMUX(2) = 0x0U;
PORTC_PMUX(3) = 0x0U;
PORTC_PINCFG(4) = 0x0U;
PORTC_PINCFG(7) = 0x0U;
}
int uart_tx(const uint8_t c)
{
while ((SERCOM_INTFLAG & INTFLAG_DRE) == 0U) {