[pic32cz] Fix gpio and clock drivers. Implement blink example for pic32cz curiosity board#3
Conversation
…32cz curiosity board
There was a problem hiding this comment.
Pull request overview
This PR targets the PIC32CZ port by correcting low-level GPIO/clock register handling and adding a Curiosity Ultra “blink” example that uses SysTick as a millisecond timebase.
Changes:
- Fix PIC32CZ GPIO PMUX/PINCFG register addressing/masking to align with 32-bit APB access.
- Add clock-init status polling (PLL lock, divider ready, GCLK sync) in the PIC32CZ clock driver.
- Add a PIC32CZ Curiosity Ultra blink example wiring up SysTick via a new Cortex-M7 platform helper and updating the example Makefile.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| wolfHAL/platform/microchip/pic32cz.h | Includes Cortex-M7 platform header so PIC32CZ platform can reference SysTick device macro. |
| wolfHAL/platform/arm/cortex_m7.h | New Cortex-M7 SysTick device macro for timer configuration. |
| src/spi/stm32wb_spi.c | Whitespace/indentation adjustments in function signatures. |
| src/reg.c | Adds a trailing newline. |
| src/gpio/pic32cz_gpio.c | Reworks PMUX/PINCFG offsets and masks for word-aligned APB access; updates init logic accordingly. |
| src/clock/pic32cz_clock.c | Adds status/sync polling and adjusts some register definitions for clock bring-up. |
| examples/pic32cz/pic32cz_curiosity_ultra.h | Exposes a global SysTick-backed whal_Timer for the example. |
| examples/pic32cz/pic32cz_curiosity_ultra.c | Updates LED pin config and instantiates SysTick timer configuration. |
| examples/pic32cz/main.c | Implements SysTick handler + millisecond wait and blink loop using GPIO + timer. |
| examples/pic32cz/ivt.c | Moves reset handler after vector table and sets VTOR to the example’s vector table. |
| examples/pic32cz/Makefile | Switches CPU to Cortex-M7 and links in timer/systick sources for the example. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| volatile uint8_t g_waiting = 0; | ||
| volatile uint8_t g_tickOverflow = 0; | ||
|
|
||
| void SysTick_Handler() |
There was a problem hiding this comment.
SysTick_Handler() is defined with an empty parameter list, which is not a prototype in C and typically triggers -Wstrict-prototypes (and becomes an error with -Werror, which this Makefile enables). Define it with an explicit (void) parameter list to match the vector table declaration and avoid the warning.
| void SysTick_Handler() | |
| void SysTick_Handler(void) |
| 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; |
There was a problem hiding this comment.
WaitMs() uses extra shared flags (g_waiting/g_tickOverflow) and a non-atomic handshake that can miss an overflow if wrap happens between startCount = g_tick; and g_waiting = 1;, causing an immediate underflow in currentCount - startCount. You can simplify and make this wrap-safe by relying on unsigned wraparound: loop until (size_t)(g_tick - startCount) >= ms (also fixes the current off-by-one from using > instead of >=).
| 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; | |
| /* Increment the millisecond tick counter. Wraparound is handled in WaitMs. */ | |
| g_tick++; | |
| } | |
| void WaitMs(size_t ms) | |
| { | |
| size_t startCount = g_tick; | |
| /* Busy-wait until the requested number of milliseconds has elapsed. | |
| * This uses unsigned wraparound: the difference (g_tick - startCount) | |
| * is well-defined even if g_tick wraps between calls. */ | |
| while ((size_t)(g_tick - startCount) < ms) { | |
| /* spin */ | |
| } |
| @@ -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); | |||
| } | |||
There was a problem hiding this comment.
The busy-wait polling loops added for PLL lock / CKRDY / GCLK SYNCBUSY have no timeout or failure path, so a misconfiguration or hardware fault will hang the system inside whal_Pic32czClockPll_Init(). Consider adding a bounded retry counter (or time-based timeout if a timebase exists) and return an error (e.g., WHAL_ENOTREADY) when the status bit never reaches the expected state.
| #include <wolfHAL/wolfHAL.h> | ||
| #include "pic32cz_curiosity_ultra.h" | ||
|
|
||
| volatile size_t g_tick = 0; | ||
| volatile uint8_t g_waiting = 0; | ||
| volatile uint8_t g_tickOverflow = 0; | ||
|
|
There was a problem hiding this comment.
examples/pic32cz/main.c now uses uint8_t and SIZE_MAX, but the file doesn't include a header that defines them. This will fail to compile (or fail under -Werror) depending on the toolchain. Include the appropriate standard header(s) (e.g., <stdint.h> for uint8_t and SIZE_MAX).
No description provided.