From d15bb37bd6f7579964759adafdb8acb9e2cf4d3f Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Wed, 11 Feb 2026 12:14:48 -0500 Subject: [PATCH] [pic32cz] Fix gpio and clock drivers. Implement blink example for pic32cz curiosity board --- examples/pic32cz/Makefile | 4 +- examples/pic32cz/ivt.c | 48 ++++++++++++---------- examples/pic32cz/main.c | 48 +++++++++++++++++++++- examples/pic32cz/pic32cz_curiosity_ultra.c | 14 ++++++- examples/pic32cz/pic32cz_curiosity_ultra.h | 1 + src/clock/pic32cz_clock.c | 35 +++++++++++++++- src/gpio/pic32cz_gpio.c | 48 +++++++++++++--------- src/reg.c | 1 + src/spi/stm32wb_spi.c | 6 +-- wolfHAL/platform/arm/cortex_m7.h | 13 ++++++ wolfHAL/platform/microchip/pic32cz.h | 1 + 11 files changed, 169 insertions(+), 50 deletions(-) create mode 100644 wolfHAL/platform/arm/cortex_m7.h diff --git a/examples/pic32cz/Makefile b/examples/pic32cz/Makefile index 654f71f..004e268 100644 --- a/examples/pic32cz/Makefile +++ b/examples/pic32cz/Makefile @@ -1,7 +1,7 @@ WHAL_DIR = $(PWD)/../../ INCLUDE = -I$(WHAL_DIR) CFLAGS = -Wall -Werror $(INCLUDE) -g3 \ - -ffreestanding -nostdlib -mcpu=cortex-m33 \ + -ffreestanding -nostdlib -mcpu=cortex-m7 \ -MMD -MF $(DEPDIR)/$*.d LDFLAGS = --omagic -static @@ -12,8 +12,10 @@ SOURCE += $(wildcard $(WHAL_DIR)/src/*.c) SOURCE += $(wildcard $(WHAL_DIR)/src/*/gpio.c) SOURCE += $(wildcard $(WHAL_DIR)/src/*/clock.c) +SOURCE += $(wildcard $(WHAL_DIR)/src/*/timer.c) SOURCE += $(wildcard $(WHAL_DIR)/src/*/supply.c) SOURCE += $(wildcard $(WHAL_DIR)/src/*/pic32cz_*.c) +SOURCE += $(wildcard $(WHAL_DIR)/src/*/systick.c) OBJECTS = $(patsubst %.c,%.o,$(SOURCE)) diff --git a/examples/pic32cz/ivt.c b/examples/pic32cz/ivt.c index 3af2764..69a622c 100644 --- a/examples/pic32cz/ivt.c +++ b/examples/pic32cz/ivt.c @@ -26,28 +26,6 @@ void Default_Handler(void) } } -void Reset_Handler(void) -{ - uint32_t* src = &_sidata; - uint32_t* dst = &_sdata; - - while (dst < &_edata) { - *dst++ = *src++; - } - - dst = &_sbss; - while (dst < &_ebss) { - *dst++ = 0; - } - - /* Call main */ - main(); - - /* Never return */ - while (1) { - } -} - /* Vector table */ __attribute__((section(".isr_vectors"))) const void* vector_table[] = { /* Stack pointer */ @@ -70,3 +48,29 @@ __attribute__((section(".isr_vectors"))) const void* vector_table[] = { PendSV_Handler, SysTick_Handler, }; + +void Reset_Handler(void) +{ + uint32_t* src = &_sidata; + uint32_t* dst = &_sdata; + + while (dst < &_edata) { + *dst++ = *src++; + } + + dst = &_sbss; + while (dst < &_ebss) { + *dst++ = 0; + } + + /* Point VTOR to our vector table (SCB->VTOR = 0xE000ED08) */ + *(volatile uint32_t *)0xE000ED08 = (uint32_t)vector_table; + + /* Call main */ + main(); + + /* Never return */ + while (1) { + } +} + diff --git a/examples/pic32cz/main.c b/examples/pic32cz/main.c index 492c2f2..99fb5ac 100644 --- a/examples/pic32cz/main.c +++ b/examples/pic32cz/main.c @@ -1,6 +1,38 @@ #include #include "pic32cz_curiosity_ultra.h" +volatile size_t g_tick = 0; +volatile uint8_t g_waiting = 0; +volatile uint8_t g_tickOverflow = 0; + +void SysTick_Handler() +{ + size_t tickBefore = g_tick++; + if (g_waiting) { + if (tickBefore > g_tick) + g_tickOverflow = 1; + } +} + +void WaitMs(size_t ms) +{ + size_t startCount = g_tick; + g_waiting = 1; + while (1) { + size_t currentCount = g_tick; + if (g_tickOverflow) { + if ((SIZE_MAX - startCount) + currentCount > ms) { + break; + } + } else if (currentCount - startCount > ms) { + break; + } + } + + g_waiting = 0; + g_tickOverflow = 0; +} + void main(void) { whal_Error err; @@ -15,7 +47,21 @@ void main(void) goto loop; } - whal_Gpio_Set(&gpio, 0, 1); + err = whal_Timer_Init(&g_whalTimer); + if (err) { + goto loop; + } + + whal_Timer_Start(&g_whalTimer); + + while (1) { + whal_Gpio_Set(&gpio, 0, 1); + + WaitMs(1000); + whal_Gpio_Set(&gpio, 0, 0); + WaitMs(1000); + } + loop: while (1); diff --git a/examples/pic32cz/pic32cz_curiosity_ultra.c b/examples/pic32cz/pic32cz_curiosity_ultra.c index ba516dd..0428168 100644 --- a/examples/pic32cz/pic32cz_curiosity_ultra.c +++ b/examples/pic32cz/pic32cz_curiosity_ultra.c @@ -46,8 +46,8 @@ whal_Gpio gpio = { .cfg = &(whal_Pic32czGpio_Cfg) { .pinCfgCount = 1, .pinCfg = &(whal_Pic32czGpio_PinCfg) { - .port = 0, - .pin = 0, + .port = 1, + .pin = 21, .dir = WHAL_PIC32CZ_DIR_OUTPUT, .out = 0, }, @@ -60,3 +60,13 @@ whal_Pic32czClock_Clk periphClock = { .mclkEnableInst = 0, .mclkEnableMask = 0, }; + +whal_Timer g_whalTimer = { + WHAL_CORTEX_M7_SYSTICK_DEVICE, + + .cfg = &(whal_SysTick_Cfg) { + .cyclesPerTick = 300000000 / 1000, + .clkSrc = WHAL_SYSTICK_CLKSRC_SYSCLK, + .tickInt = WHAL_SYSTICK_TICKINT_ENABLED, + }, +}; diff --git a/examples/pic32cz/pic32cz_curiosity_ultra.h b/examples/pic32cz/pic32cz_curiosity_ultra.h index 153132e..7b22621 100644 --- a/examples/pic32cz/pic32cz_curiosity_ultra.h +++ b/examples/pic32cz/pic32cz_curiosity_ultra.h @@ -7,5 +7,6 @@ extern whal_Supply supply; extern whal_Clock clock; extern whal_Gpio gpio; +extern whal_Timer g_whalTimer; #endif /* WHAL_PIC32CZ_CURIOSITY_ULTRA */ diff --git a/src/clock/pic32cz_clock.c b/src/clock/pic32cz_clock.c index 32e6d50..7a771f2 100644 --- a/src/clock/pic32cz_clock.c +++ b/src/clock/pic32cz_clock.c @@ -34,11 +34,15 @@ #define PIC32CZ_OSCCTRL_PLLxPOSTDIVA_POSTDIV0 WHAL_MASK_RANGE(5, 0) /* Output 0 divider */ #define PIC32CZ_OSCCTRL_PLLxPOSTDIVA_OUTEN0 WHAL_MASK(7) /* Output 0 enable */ +/* OSCCTRL Status Register - PLL lock and oscillator ready flags */ +#define PIC32CZ_OSCCTRL_STATUS_REG (PIC32CZ_OSCCTRL + 0x10) +#define PIC32CZ_OSCCTRL_STATUS_PLLxLOCK(pllInst) WHAL_MASK((24 + (pllInst))) + /* GCLK - Generic Clock Controller (base offset 0x10000) */ #define PIC32CZ_GCLK 0x10000 /* Generator Control Register - configures clock source and divider per generator */ -#define PIC32CZ_GCLK_GENCTRLx_REG(gclkInst) (PIC32CZ_GCLK + 0x20 + (gclkInst * 0x4)) +#define PIC32CZ_GCLK_GENCTRLx_REG(gclkInst) ((PIC32CZ_GCLK + 0x20 + (gclkInst * 0x4))) #define PIC32CZ_GCLK_GENCTRLx_SRC WHAL_MASK_RANGE(4, 0) /* Source selection */ #define PIC32CZ_GCLK_GENCTRLx_GENEN WHAL_MASK(8) /* Generator enable */ #define PIC32CZ_GCLK_GENCTRLx_DIV WHAL_MASK_RANGE(31, 16) /* Division factor */ @@ -48,11 +52,19 @@ #define PIC32CZ_GCLK_PCHCTRLx_GEN WHAL_MASK_RANGE(3, 0) /* Generator selection */ #define PIC32CZ_GCLK_PCHCTRLx_CHEN WHAL_MASK(6) /* Channel enable */ +/* GCLK Synchronization Busy Register - poll after writing GENCTRLx */ +#define PIC32CZ_GCLK_SYNCBUSY_REG (PIC32CZ_GCLK + 0x04) +#define PIC32CZ_GCLK_SYNCBUSY_GENCTRLx(gclkInst) WHAL_MASK((2 + (gclkInst))) + /* MCLK - Main Clock Controller (base offset 0x12000) */ #define PIC32CZ_MCLK 0x12000 +/* MCLK Interrupt Flag Register - clock ready status */ +#define PIC32CZ_MCLK_INTFLAG_REG (PIC32CZ_MCLK + 0x08) +#define PIC32CZ_MCLK_INTFLAG_CKRDY WHAL_MASK(0) /* Clock ready */ + /* CPU Clock Divider Register */ -#define PIC32CZ_MCLK_DIV1_REG (PIC32CZ_MCLK + 0x14) +#define PIC32CZ_MCLK_DIV1_REG (PIC32CZ_MCLK + 0x10) #define PIC32CZ_MCLK_DIV1 WHAL_MASK_RANGE(7, 0) /* CPU clock divider */ /* Peripheral Clock Mask Registers - enable/disable bus clocks to peripherals */ @@ -109,6 +121,7 @@ whal_Error whal_Pic32czClockPll_Init(whal_Clock *clkDev) size_t PLLxFBDIV_REG; size_t PLLxREFDIV_REG; size_t PLLxPOSTDIVA_REG; + size_t status; if (!clkDev) { return WHAL_EINVAL; @@ -151,10 +164,22 @@ whal_Error whal_Pic32czClockPll_Init(whal_Clock *clkDev) whal_SetBits(PIC32CZ_OSCCTRL_PLLxCTRL_REFSEL, oscCtrlCfg->refSel) | whal_SetBits(PIC32CZ_OSCCTRL_PLLxCTRL_BWSEL, oscCtrlCfg->bwSel)); + /* Wait for PLL to lock */ + do { + whal_Reg_Get(clkDev->regmap.base, PIC32CZ_OSCCTRL_STATUS_REG, + PIC32CZ_OSCCTRL_STATUS_PLLxLOCK(oscCtrlCfg->pllInst), &status); + } while (!status); + /* Configure CPU clock divider in MCLK */ whal_Reg_Update(clkDev->regmap.base, PIC32CZ_MCLK_DIV1_REG, PIC32CZ_MCLK_DIV1, whal_SetBits(PIC32CZ_MCLK_DIV1, mclkCfg->div)); + /* Wait for clock divider change to take effect */ + do { + whal_Reg_Get(clkDev->regmap.base, PIC32CZ_MCLK_INTFLAG_REG, + PIC32CZ_MCLK_INTFLAG_CKRDY, &status); + } while (!status); + /* Configure each GCLK generator with its source and divider */ for (uint8_t i = 0; i < cfg->gclkCfgCount; ++i) { whal_Pic32czClock_GclkCfg *gclkCfg = &cfg->gclkCfg[i]; @@ -163,6 +188,12 @@ whal_Error whal_Pic32czClockPll_Init(whal_Clock *clkDev) whal_SetBits(PIC32CZ_GCLK_GENCTRLx_SRC, gclkCfg->genSrc) | whal_SetBits(PIC32CZ_GCLK_GENCTRLx_GENEN, 1) | whal_SetBits(PIC32CZ_GCLK_GENCTRLx_DIV, gclkCfg->genDiv)); + + /* Wait for generator synchronization */ + do { + whal_Reg_Get(clkDev->regmap.base, PIC32CZ_GCLK_SYNCBUSY_REG, + PIC32CZ_GCLK_SYNCBUSY_GENCTRLx(gclkCfg->gen), &status); + } while (status); } return WHAL_SUCCESS; diff --git a/src/gpio/pic32cz_gpio.c b/src/gpio/pic32cz_gpio.c index 1dd3b66..f625aef 100644 --- a/src/gpio/pic32cz_gpio.c +++ b/src/gpio/pic32cz_gpio.c @@ -27,14 +27,23 @@ * Each byte contains two 4-bit PMUX fields: * - Lower nibble (bits 3:0): Even pin PMUX * - Upper nibble (bits 7:4): Odd pin PMUX + * + * The APB bridge only supports 32-bit access, so the offset is word-aligned + * and the shift positions the pin's nibble within the 32-bit word. */ -#define PIC32CZ_PMUXx_REG(port, pin) ((0x30 + ((pin) / 2)) + (port * 0x80)) +#define PIC32CZ_PMUXx_REG(port, pin) ((0x30 + (((pin) / 8) * 4)) + ((port) * 0x80)) +#define PIC32CZ_PMUXx_MASK(pin) (0xFul << (((pin) % 8) * 4)) -/* Pin configuration register - one byte per pin */ -#define PIC32CZ_PINCFGx_REG(port, pin) ((0x40 + (pin)) + (port * 0x80)) -#define PIC32CZ_PINCFGx_PMUXEN WHAL_MASK(0) /* Enable peripheral mux */ -#define PIC32CZ_PINCFGx_INEN WHAL_MASK(1) /* Enable input buffer */ -#define PIC32CZ_PINCFGx_PULLEN WHAL_MASK(2) /* Enable pull resistor */ +/* + * Pin configuration register - one byte per pin. + * + * Word-aligned for 32-bit access through the APB bridge. The pin argument + * positions each field's mask within the 32-bit word. + */ +#define PIC32CZ_PINCFGx_REG(port, pin) ((0x40 + ((pin) & ~3)) + ((port) * 0x80)) +#define PIC32CZ_PINCFGx_PMUXEN(pin) (WHAL_MASK(0) << (((pin) & 3) * 8)) +#define PIC32CZ_PINCFGx_INEN(pin) (WHAL_MASK(1) << (((pin) & 3) * 8)) +#define PIC32CZ_PINCFGx_PULLEN(pin) (WHAL_MASK(2) << (((pin) & 3) * 8)) whal_Error whal_Pic32czGpio_Init(whal_Gpio *gpioDev) { @@ -53,13 +62,9 @@ whal_Error whal_Pic32czGpio_Init(whal_Gpio *gpioDev) * Configure pin for peripheral function: * 1. Set the PMUX value to select the peripheral function * 2. Enable PMUXEN in PINCFG to route pin to peripheral - * - * PMUX register packs two 4-bit fields per byte: - * - Even pins use bits 3:0 - * - Odd pins use bits 7:4 */ - uint8_t maskBit = (pinCfg->pin & 1) * 4; - size_t pmuxMask = WHAL_MASK_RANGE(maskBit + 3, maskBit); + size_t pmuxMask = PIC32CZ_PMUXx_MASK(pinCfg->pin); + size_t pmuxenMask = PIC32CZ_PINCFGx_PMUXEN(pinCfg->pin); whal_Reg_Update(gpioDev->regmap.base, PIC32CZ_PMUXx_REG(pinCfg->port, pinCfg->pin), @@ -68,8 +73,8 @@ whal_Error whal_Pic32czGpio_Init(whal_Gpio *gpioDev) whal_Reg_Update(gpioDev->regmap.base, PIC32CZ_PINCFGx_REG(pinCfg->port, pinCfg->pin), - PIC32CZ_PINCFGx_PMUXEN, - whal_SetBits(PIC32CZ_PINCFGx_PMUXEN, 1)); + pmuxenMask, + whal_SetBits(pmuxenMask, 1)); continue; } @@ -92,11 +97,16 @@ whal_Error whal_Pic32czGpio_Init(whal_Gpio *gpioDev) whal_SetBits(pinMask, pinCfg->out)); /* Configure input buffer and pull resistor */ - whal_Reg_Update(gpioDev->regmap.base, - PIC32CZ_PINCFGx_REG(pinCfg->port, pinCfg->pin), - PIC32CZ_PINCFGx_INEN | PIC32CZ_PINCFGx_PULLEN, - whal_SetBits(PIC32CZ_PINCFGx_INEN, pinCfg->inEn) | - whal_SetBits(PIC32CZ_PINCFGx_PULLEN, pinCfg->pullEn)); + { + size_t inenMask = PIC32CZ_PINCFGx_INEN(pinCfg->pin); + size_t pullenMask = PIC32CZ_PINCFGx_PULLEN(pinCfg->pin); + + whal_Reg_Update(gpioDev->regmap.base, + PIC32CZ_PINCFGx_REG(pinCfg->port, pinCfg->pin), + inenMask | pullenMask, + whal_SetBits(inenMask, pinCfg->inEn) | + whal_SetBits(pullenMask, pinCfg->pullEn)); + } } return WHAL_SUCCESS; diff --git a/src/reg.c b/src/reg.c index b551f8a..8c6d044 100644 --- a/src/reg.c +++ b/src/reg.c @@ -18,3 +18,4 @@ void whal_Reg_Get(const size_t base, const size_t offset, const size_t mask, siz val = *(volatile size_t *)(base + offset); *value = whal_GetBits(mask, val); } + diff --git a/src/spi/stm32wb_spi.c b/src/spi/stm32wb_spi.c index 0a2706f..224dde7 100644 --- a/src/spi/stm32wb_spi.c +++ b/src/spi/stm32wb_spi.c @@ -22,7 +22,7 @@ whal_Error whal_Stm32wbSpi_Deinit(whal_Spi *spiDev) } whal_Error whal_Stm32wbSpi_SendRecv(whal_Spi *spiDev, void *spiComCfg, const uint8_t *tx, - size_t txLen, uint8_t *rx, size_t rxLen) + size_t txLen, uint8_t *rx, size_t rxLen) { (void)spiDev; (void)spiComCfg; @@ -34,7 +34,7 @@ whal_Error whal_Stm32wbSpi_SendRecv(whal_Spi *spiDev, void *spiComCfg, const uin } whal_Error whal_Stm32wbSpi_Send(whal_Spi *spiDev, void *spiComCfg, const uint8_t *data, - size_t dataSz) + size_t dataSz) { (void)spiDev; (void)spiComCfg; @@ -44,7 +44,7 @@ whal_Error whal_Stm32wbSpi_Send(whal_Spi *spiDev, void *spiComCfg, const uint8_t } whal_Error whal_Stm32wbSpi_Recv(whal_Spi *spiDev, void *spiComCfg, uint8_t *data, - size_t dataSz) + size_t dataSz) { (void)spiDev; (void)spiComCfg; diff --git a/wolfHAL/platform/arm/cortex_m7.h b/wolfHAL/platform/arm/cortex_m7.h new file mode 100644 index 0000000..4906015 --- /dev/null +++ b/wolfHAL/platform/arm/cortex_m7.h @@ -0,0 +1,13 @@ +#ifndef WHAL_CORTEX_M7_H +#define WHAL_CORTEX_M7_H + +#include + +#define WHAL_CORTEX_M7_SYSTICK_DEVICE \ + .regmap = { \ + .base = 0xE000E010, \ + .size = 0x400, \ + }, \ + .driver = &whal_SysTick_Driver + +#endif /* WHAL_CORTEX_M7_H */ diff --git a/wolfHAL/platform/microchip/pic32cz.h b/wolfHAL/platform/microchip/pic32cz.h index 4bb0a49..5867987 100644 --- a/wolfHAL/platform/microchip/pic32cz.h +++ b/wolfHAL/platform/microchip/pic32cz.h @@ -4,6 +4,7 @@ #include #include #include +#include #define WHAL_PIC32CZ_SUPPLY_DEVICE \ .regmap = { \