diff --git a/arch.mk b/arch.mk index 4036d6bf69..6838b57ae0 100644 --- a/arch.mk +++ b/arch.mk @@ -288,10 +288,7 @@ ifeq ($(ARCH),ARM) OBJS+=hal/pic32c.o ifeq ($(WOLFHSM_CLIENT),1) - ifeq ($(WOLFHSM_MICROCHIP_PIC32CZ),) - $(error WOLFHSM_MICROCHIP_PIC32CZ is not set: point it at the wolfHSM \ - PIC32CZ client port directory (the one containing port/)) - endif + WOLFHSM_MICROCHIP_PIC32CZ ?= .. CFLAGS+=-I$(WOLFHSM_MICROCHIP_PIC32CZ) \ -DWOLFHSM_CFG_NO_SYS_TIME \ diff --git a/hal/pic32cz.c b/hal/pic32cz.c index 32424011d5..cdbf2af685 100644 --- a/hal/pic32cz.c +++ b/hal/pic32cz.c @@ -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__ __volatile__("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) @@ -143,8 +159,17 @@ void hal_init(void) void hal_prepare_boot(void) { +#ifdef DEBUG_UART + uart_deinit(); +#endif + #ifdef WOLFBOOT_RESTORE_CLOCK pic32_clock_reset(); + + if (!pic32_vreg_pll_was_enabled) { + SUPC_VREGCTRL &= ~((uint32_t)SUPC_VREGCTRL_AVREGEN_PLLREG_EN + << SUPC_VREGCTRL_AVREGEN_SHIFT); + } #endif } diff --git a/hal/uart/uart_drv_pic32cz.c b/hal/uart/uart_drv_pic32cz.c index f1ee49c40f..550bbd25d6 100644 --- a/hal/uart/uart_drv_pic32cz.c +++ b/hal/uart/uart_drv_pic32cz.c @@ -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) {