5.10 GPIO Guide
This chapter describes the file composition and the 22 public functions of the GPIO and AFIO drivers in the N32G41x standard peripheral library, together with the IORemap and LedBlink examples. Read the port structure, the alternate-function mapping and the pin locking sequence together with the “GPIO and AFIO” chapter of the user manual, and take the errata sheet as the authority on known chip issues.
5.10.1 Related files
| Relative path | Purpose |
|---|---|
firmware/n32g41x_std_periph_driver/inc/n32g41x_gpio.h |
Defines the GPIO_InitType structure and the macros for pins, modes, pull settings, slew rate, drive strength, alternate functions and EXTI line sources, and declares 22 public functions in the six sections reset and initialization, read, write, configuration, AFIO configuration and EXTI line configuration |
firmware/n32g41x_std_periph_driver/src/n32g41x_gpio.c |
Implements those 22 functions: port and pin reset, writing of the mode and alternate-function fields, port data reads and writes, the pin locking sequence, and AFIO and EXTI line configuration |
projects/n32g41x_EVAL/examples/GPIO/ |
Root directory of the GPIO examples, holding IORemap and LedBlink |
projects/n32g41x_EVAL/examples/GPIO/LedBlink/ |
Composition of one example directory: MDK-ARM/, EWARM/, inc/, src/ and readme.txt |
projects/n32g41x_EVAL/bsp/ |
Board support files shared by both examples: the board LED and key definitions, the log port initialization and the millisecond delay function |
5.10.2 API reference
The following 22 public functions are listed in the declaration order of n32g41x_gpio.h in 6 groups; each entry gives a summary and the original comment above the function in n32g41x_gpio.c.
Reset and initialization
GPIO_DeInit, GPIO_DeInitPin, GPIO_InitPeripheral, GPIO_InitStruct
Read
GPIO_ReadInputDataBit, GPIO_ReadInputData, GPIO_ReadOutputDataBit, GPIO_ReadOutputData
Write
GPIO_SetBits, GPIO_WritePBSC, GPIO_ResetBits, GPIO_WriteBit, GPIO_Write, GPIO_TogglePin
Configuration
GPIO_ConfigPinLock, GPIO_ConfigPinRemap
AFIO configuration
AFIO_ConfigSPINSSMode, AFIO_ConfigEXTIFlitEN, AFIO_ConfigIOFlitNum, AFIO_DIGEFTEnable
EXTI line configuration
GPIO_ConfigEXTILine, GPIO_ClearEXTILine
void GPIO_DeInit(void)Reset the GPIOx peripheral registers to their default reset values.
name GPIO_DeInit.
fun Reset the GPIOx peripheral registers to their default reset values.
param none
return none
void GPIO_DeInitPin(GPIO_Module *GPIOx, uint32_t Pin)Restores the selected GPIOx pins to their default reset values.
name GPIO_DeInitPin.
fun Restores the selected GPIOx pins to their default reset values.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
- GPIO_PIN_ALL
return none
void GPIO_InitPeripheral(GPIO_Module *GPIOx, const GPIO_InitType *GPIO_InitParam)Initialize the selected GPIOx pins with the value of the GPIO_InitType structure.
name GPIO_InitPeripheral.
fun Initialize the selected GPIOx pins with the value of the GPIO_InitType structure.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param GPIO_InitParam :
- Pin
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
- GPIO_PIN_ALL
- GPIO_Mode
- GPIO_MODE_INPUT
- GPIO_MODE_OUTPUT_PP
- GPIO_MODE_OUTPUT_OD
- GPIO_MODE_AF_PP
- GPIO_MODE_AF_OD
- GPIO_MODE_ANALOG
- GPIO_Pull
- GPIO_NO_PULL
- GPIO_PULL_UP
- GPIO_PULL_DOWN
- GPIO_Slew_Rate
note: only effective for pins PA0, PA1, PA2, PB5, PB6, PB7
- GPIO_SLEW_RATE_FAST
- GPIO_SLEW_RATE_SLOW
- GPIO_Current
- GPIO_DS_HIGH
- GPIO_DS_LOW
- GPIO_Alternate
- GPIO_AF0
- GPIO_AF1
- GPIO_AF2
- GPIO_AF3
- GPIO_AF4
- GPIO_AF5
- GPIO_AF6
- GPIO_AF7
- GPIO_AF8
- GPIO_AF9
- GPIO_AF10
- GPIO_AF11
- GPIO_AF12
- GPIO_AF13
- GPIO_AF14
- GPIO_NO_AF NO alternate Function mapping
return none
void GPIO_InitStruct(GPIO_InitType *GPIO_InitStructure)Assign default values to each GPIO_InitType member.
name GPIO_InitStruct.
fun Assign default values to each GPIO_InitType member.
param GPIO_InitStructure :
pointer to GPIO_InitType structure.
return none
uint8_t GPIO_ReadInputDataBit(const GPIO_Module *GPIOx, uint16_t Pin)Get the pin status on the specified input port.
name GPIO_ReadInputDataBit.
fun Get the pin status on the specified input port.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
return the pin state on the input port.
uint16_t GPIO_ReadInputData(const GPIO_Module *GPIOx)Get the input data on the designated GPIO port.
name GPIO_ReadInputData.
fun Get the input data on the designated GPIO port.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
return the data value on the GPIO input port.
uint8_t GPIO_ReadOutputDataBit(const GPIO_Module *GPIOx, uint16_t Pin)Get the pin status on the specified output port.
name GPIO_ReadOutputDataBit.
fun Get the pin status on the specified output port.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
return the pin state on the output port.
uint16_t GPIO_ReadOutputData(const GPIO_Module *GPIOx)Get the output data on the designated GPIO port.
name GPIO_ReadOutputData.
fun Get the output data on the designated GPIO port.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
return the data value on the GPIO output port.
void GPIO_SetBits(GPIO_Module *GPIOx, uint16_t Pin)Sets the selected data port bits.
name GPIO_SetBits.
fun Sets the selected data port bits.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
return none
Use note: The implementation writes Pin into GPIOx->PBSC; the bits written with 1 in PBSC are set and the bits written with 0 keep their value, so the operation completes in a single AHB write with no read-modify-write and no need to disable interrupts.
void GPIO_WritePBSC(GPIO_Module *GPIOx, uint16_t Pin, uint8_t bitstatus)Sets or clears the selected data port bits via GPIOx_PBSC.
name GPIO_WritePBSC.
fun Sets or clears the selected data port bits via GPIOx_PBSC.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
param bitstatus :
- Bit_SET
- Bit_RESET
return none
Use note: When bitstatus is Bit_SET the implementation writes GPIOx->PBSC = Pin to set the pins, and for any other value it writes GPIOx->PBSC = Pin << 16 to clear them, that is the upper 16 bits of PBSC are the clear bits.
void GPIO_ResetBits(GPIO_Module *GPIOx, uint16_t Pin)Reset the selected data port bits.
name GPIO_ResetBits.
fun Reset the selected data port bits.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
return none
Use note: The implementation writes Pin into GPIOx->PBC; the bits written with 1 are cleared and the bits written with 0 keep their value.
void GPIO_WriteBit(GPIO_Module *GPIOx, uint16_t Pin, Bit_OperateType BitCmd)Set or reset the selected data port bits.
name GPIO_WriteBit.
fun Set or reset the selected data port bits.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
param BitCmd :
- Bit_RESET
- Bit_SET
return none
Use note: When BitCmd is not Bit_RESET the function writes Pin into GPIOx->PBSC, and when it is Bit_RESET it writes Pin into GPIOx->PBC; neither form affects the pins outside Pin.
void GPIO_Write(GPIO_Module *GPIOx, uint16_t data_value)Write data on the designated GPIO data port.
name GPIO_Write.
fun Write data on the designated GPIO data port.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param data_value :
the value to be written to the port output data register.
- 0~0xFFFF
return none
Use note: The implementation writes data_value straight into the whole GPIOx->POD word; the value range is 0 to 0xFFFF and it overwrites the output level of all 16 pins of that port rather than operating bit by bit.
void GPIO_TogglePin(GPIO_Module *GPIOx, uint16_t Pin)Toggle the specified port pin level.
name GPIO_TogglePin.
fun Toggle the specified port pin level.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
return none
Use note: The implementation is GPIOx->POD ^= Pin, that is it reads the output data register back and writes the whole word again, unlike the single write of GPIO_SetBits and GPIO_ResetBits.
void GPIO_ConfigPinLock(GPIO_Module *GPIOx, uint16_t Pin)GPIO port lock register configuration.
name GPIO_ConfigPinLock.
fun GPIO port lock register configuration.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
return none
Use note: The implementation writes GPIO_PLOCK_PLOCKK | Pin and Pin alternately into GPIOx->PLOCK in the order w1 then w0 then w1 and then reads the register back twice, which is the w1 then w0 then w1 then r0 sequence required by the manual; PLOCK[15:0] must not change in the middle of the sequence.
void GPIO_ConfigPinRemap(uint8_t PortSource, uint32_t PinSource, uint32_t AlternateFunction)Pin remapping configuration.
name GPIO_ConfigPinRemap.
fun Pin remapping configuration.
param PortSource :
- GPIOA_PORT_SOURCE
- GPIOB_PORT_SOURCE
- GPIOC_PORT_SOURCE
- GPIOD_PORT_SOURCE
param PinSource :
- GPIO_PIN_SOURCE0
- GPIO_PIN_SOURCE1
- GPIO_PIN_SOURCE2
- GPIO_PIN_SOURCE3
- GPIO_PIN_SOURCE4
- GPIO_PIN_SOURCE5
- GPIO_PIN_SOURCE6
- GPIO_PIN_SOURCE7
- GPIO_PIN_SOURCE8
- GPIO_PIN_SOURCE9
- GPIO_PIN_SOURCE10
- GPIO_PIN_SOURCE11
- GPIO_PIN_SOURCE12
- GPIO_PIN_SOURCE13
- GPIO_PIN_SOURCE14
- GPIO_PIN_SOURCE15
param AlternateFunction :
- GPIO_AF0
- GPIO_AF1
- GPIO_AF2
- GPIO_AF3
- GPIO_AF4
- GPIO_AF5
- GPIO_AF6
- GPIO_AF7
- GPIO_AF8
- GPIO_AF9
- GPIO_AF10
- GPIO_AF11
- GPIO_AF12
- GPIO_AF13
- GPIO_AF14
- GPIO_NO_AF NO alternate Function mapping
return none
void AFIO_ConfigSPINSSMode(uint32_t AFIO_SPIx_NSS, uint32_t SpiNssMode)Configuring the idle state of the NSS signal when the SPIx NSS pin is set to push-pull alternate function mode..
name AFIO_ConfigSPINSSMode.
fun Selects the alternate function SPIx NSS mode.
param AFIO_SPIx_NSS :
choose which SPI configuration.
- AFIO_SPI1_NSS
- AFIO_SPI2_NSS
param SpiNssMode :
specifies the SPI_NSS mode to be configured.
- AFIO_SPI_NSS_HIGH_IMPEDANCE
- AFIO_SPI_NSS_HIGH_LEVEL
return none
void AFIO_ConfigEXTIFlitEN(FunctionalState Cmd)Configure EXTI filter enable.
name AFIO_ConfigEXTIFlitEN.
fun Configure EXTI filter enable.
param Cmd :
- ENABLE
- DISABLE
return none
void AFIO_ConfigIOFlitNum(uint32_t filter_clk)Configure the IO filter time in HCLK clock cycles.
name AFIO_ConfigIOFlitNum.
fun Configure the IO filter time in HCLK clock cycles.
param filter_clk
- GPIO_FILTER_BYPASS
- GPIO_FILTER_1_CLK
- GPIO_FILTER_2_CLK
- GPIO_FILTER_3_CLK
return none
void AFIO_DIGEFTEnable(const GPIO_Module *GPIOx, uint32_t Pin, FunctionalState Cmd)Enables or disables the digital glitch filter of port pins.
name AFIO_DIGEFTEnable.
fun Enables or disables the digital glitch filter of port pins.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
- GPIO_PIN_ALL
param Cmd :
- ENABLE
- DISABLE
return none
void GPIO_ConfigEXTILine(uint8_t PortSource, uint32_t PinSource)Selects the GPIO pin used as EXTI Line. A single EXTI line can only be configured with a single pin.
name GPIO_ConfigEXTILine.
fun Selects the GPIO pin used as EXTI Line. A single EXTI line can only be configured with a single pin.
param PortSource :
- GPIOA_PORT_SOURCE
- GPIOB_PORT_SOURCE
- GPIOC_PORT_SOURCE
- GPIOD_PORT_SOURCE
param PinSource :
- GPIO_PIN_SOURCE0
- GPIO_PIN_SOURCE1
- GPIO_PIN_SOURCE2
- GPIO_PIN_SOURCE3
- GPIO_PIN_SOURCE4
- GPIO_PIN_SOURCE5
- GPIO_PIN_SOURCE6
- GPIO_PIN_SOURCE7
- GPIO_PIN_SOURCE8
- GPIO_PIN_SOURCE9
- GPIO_PIN_SOURCE10
- GPIO_PIN_SOURCE11
- GPIO_PIN_SOURCE12
- GPIO_PIN_SOURCE13
- GPIO_PIN_SOURCE14
- GPIO_PIN_SOURCE15
return none
Use note: The implementation writes PortSource and PinSource together into the EXTI line configuration register of the AFIO; one pin source can only be bound to one port, and configuring it again overwrites the previous choice.
void GPIO_ClearEXTILine(uint8_t LineSource)Clear the GPIO pin used as EXTI Line.
name GPIO_ClearEXTILine.
fun Clear the GPIO pin used as EXTI Line.
param LineSource :
- GPIO_EXTILINE_SOURCE0
- GPIO_EXTILINE_SOURCE1
- GPIO_EXTILINE_SOURCE2
- GPIO_EXTILINE_SOURCE3
- GPIO_EXTILINE_SOURCE4
- GPIO_EXTILINE_SOURCE5
- GPIO_EXTILINE_SOURCE6
- GPIO_EXTILINE_SOURCE7
- GPIO_EXTILINE_SOURCE8
- GPIO_EXTILINE_SOURCE9
- GPIO_EXTILINE_SOURCE10
- GPIO_EXTILINE_SOURCE11
- GPIO_EXTILINE_SOURCE12
- GPIO_EXTILINE_SOURCE13
- GPIO_EXTILINE_SOURCE14
- GPIO_EXTILINE_SOURCE15
return none
Use note: The implementation clears the port selection bits of the matching EXTI line in the AFIO according to LineSource, so that the line is no longer driven by any GPIO pin.
5.10.3 Demo descriptions
This section describes the 2 GPIO examples: IORemap switches the SWD pins PA13 and PA14 between the debug function and plain outputs, and LedBlink drives the three board LEDs through push-pull outputs.
5.10.3.1 IORemap SWD pins reused as GPIO
Example directory: projects/n32g41x_EVAL/examples/GPIO/IORemap/
Initialize the log port→Configure PA1 and PA7 as push-pull outputs and PA4 as an input with pull-up→Poll the pressed state of KEY1→While pressed, release PA13 and PA14 as plain push-pull outputs and toggle them alternately every 50 ms→Restore the SWD function of both pins and light LED2 on release
| Item | Source analysis |
|---|---|
| Function | While KEY1 is held, the SWD pins PA13 (SWDIO) and PA14 (SWCLK) are released from the debug function and become push-pull outputs that toggle alternately; when KEY1 is released, both pins return to the SWD alternate function. LED1 on means the pins are plain outputs, and LED2 on means they are in SWD mode. |
| Source files | src/main.c: LED and key initialization, SWD_Function_Initialize, SWD_As_GPIO_Initialize, and the main loop;inc/main.h: the SWDIO_PORT/SWDIO_PIN and SWCLK_PORT/SWCLK_PIN macros and function declarations;src/n32g41x_it.c and inc/n32g41x_it.h: interrupt handlers;readme.txt: function, environment, and usage;MDK-ARM/ and EWARM/: Keil and IAR projects. |
| Key configuration | LED1 is PA1 and LED2 is PA7, both initialized as GPIO_MODE_OUTPUT_PP;KEY1 is PA4, initialized as GPIO_MODE_INPUT with BUTTON_KEY1_PULL, and its pressed level is BUTTON_KEY1_STATE. In SWD mode PA13 uses GPIO_MODE_AF_PP, GPIO_PULL_UP, and GPIO_AF0, and PA14 uses GPIO_MODE_AF_PP, GPIO_PULL_DOWN, and GPIO_AF0;as plain outputs PA13 and PA14 are initialized together as GPIO_MODE_OUTPUT_PP with GPIO_NO_AF. The system clock is HSI+PLL: 80 MHz on N32G412 and 96 MHz on N32G415. |
| Program and data path | main calls log_init, prints IO remaping demo!, initializes the LEDs and KEY1, and enters the loop: when KEY1 reads the pressed level, it turns LED1 on and LED2 off, calls SWD_As_GPIO_Initialize, then toggles PA13 and PA14 alternately with GPIO_TogglePin at 50 ms intervals until KEY1 is released;when KEY1 is not pressed, it calls SWD_Function_Initialize, turns LED2 on and LED1 off, and waits for KEY1 to be pressed again. |
| Main APIs | GPIO_InitStruct, GPIO_InitPeripheral, GPIO_ConfigPinRemap, GPIO_ReadInputDataBit, GPIO_TogglePin, GPIO_SetBits, GPIO_ResetBits |
| Verification | After reset the UART prints IO remaping demo!;with KEY1 released LED2 stays on; while KEY1 is held LED1 stays on, and an LED or oscilloscope on PA13 and PA14 shows the two pins toggling alternately every 50 ms. |
| Use note | N32G41x has no JTAG interface and supports SWD debugging only (PA13 is SWDIO, PA14 is SWCLK); after downloading, remove the SWDIO and SWCLK jumpers on J5 of the board. SWD is unavailable while KEY1 is held. Toolchains are KEIL MDK-ARM V5.34 and IAR EWARM 8.50.1; supported devices are N32G412x8L7, N32G412xBL7, N32G415x8L7, and N32G415xBL7. |
Core-code walkthrough and porting
The example lets the same pins take two roles in turn: pressing KEY1 releases the SWD pins as plain outputs, and releasing it restores the SWD alternate function.
Data path: KEY1 (PA4) level → GPIO_ReadInputDataBit → SWD_As_GPIO_Initialize or SWD_Function_Initialize rewrites the mode and alternate-function fields of PA13 and PA14 → GPIO_TogglePin toggles PA13 and PA14 → observed with an external LED or oscilloscope
1. Define the two SWD pins with macros. inc/main.h defines SWDIO as PA13 and SWCLK as PA14 and takes the port clock of both as RCC_AHB_PERIPH_GPIO, so all later configuration reaches the pins through this group of macros.
/* SWD pin defines */
#define SWDIO_PORT GPIOA
#define SWDIO_PIN GPIO_PIN_13
#define SWDIO_CLK RCC_AHB_PERIPH_GPIO
#define SWCLK_PORT GPIOA
#define SWCLK_PIN GPIO_PIN_14
#define SWCLK_CLK RCC_AHB_PERIPH_GPIO
When porting to another board the SWD pins are fixed by the chip, so usually only the LED and key definitions in bsp/inc/n32g41x_stb.h need to change.
2. The main loop switches roles according to KEY1. When KEY1 is pressed the loop lights LED1, turns LED2 off, and then calls the initialization function that releases the SWD pins; when KEY1 is not pressed the other branch restores SWD.
while(1)
{
if (GPIO_ReadInputDataBit(BUTTON_KEY1_PORT, BUTTON_KEY1_PIN) == BUTTON_KEY1_STATE)
{
/* Turn on Led1 */
LED_On(LED1_PORT, LED1_PIN);
The comparison level uses BUTTON_KEY1_STATE, which comes from bsp/inc/n32g41x_stb.h; change that macro together with the board or with the active level of the key.
3. The inner loop toggles the two pins alternately. After the pins are released, a nested while(1) toggles PA13 and PA14 alternately, each toggle followed by a 50 ms delay, and checks after every round whether KEY1 has been released.
/* Toggle SWDIO pin */
GPIO_TogglePin(SWDIO_PORT, SWDIO_PIN);
/* Toggle SWCLK pin */
GPIO_TogglePin(SWCLK_PORT, SWCLK_PIN);
The toggle interval comes from the two SysTick_Delay_Ms(50) calls; change both arguments to change the observed frequency.
4. Two configuration blocks release and restore the SWD pins. SWD_As_GPIO_Initialize first writes GPIO_NO_AF into the alternate-function fields of PA13 and PA14 and then initializes both pins together as push-pull outputs; SWD_Function_Initialize writes GPIO_AF0 back into those fields and initializes PA13 with a pull-up and PA14 with a pull-down.
/* Remap PA13 (SWDIO) and PA14 (SWCLK) to GPIO_NO_AF (release from SWD) */
GPIO_ConfigPinRemap(GPIOA_PORT_SOURCE, GPIO_PIN_SOURCE15, GPIO_NO_AF);
GPIO_ConfigPinRemap(GPIOA_PORT_SOURCE, GPIO_PIN_SOURCE14, GPIO_NO_AF);
/* Configure PA15 and PA14 as gpio output push-pull */
GPIO_InitStructure.Pin = SWDIO_PIN | SWCLK_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.GPIO_Alternate = GPIO_NO_AF;
GPIO_InitPeripheral(SWDIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.Pin = SWDIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
GPIO_InitStructure.GPIO_Alternate = GPIO_AF0;
GPIO_InitPeripheral(SWDIO_PORT, &GPIO_InitStructure);
In the sources the comment about releasing SWD says Remap PA13 (SWDIO) to AF0 and the output configuration comment says Configure PA15 and PA14, while the pin sources actually passed in are GPIO_PIN_SOURCE15 and GPIO_PIN_SOURCE14 and the value used is GPIO_NO_AF. When porting to a chip with a different alternate-function mapping, check the pin source numbers and the alternate-function numbers together.
Corresponding source files: inc/main.h, src/main.c
5.10.3.2 LedBlink LED blink
Example directory: projects/n32g41x_EVAL/examples/GPIO/LedBlink/
Enable the GPIO and board clocks→Configure PA1, PA7 and PB1 as push-pull outputs→Blink LED1 and LED3 4 times→Light LED1, LED2 and LED3 in turn in the main loop
| Item | Source analysis |
|---|---|
| Function | Drives the board LEDs LED1, LED2 and LED3 through push-pull outputs: first LED1 and LED3 blink together 4 times, then the three LEDs light up in turn in the order LED1, LED2, LED3 and the sequence repeats. |
| Source files | src/main.c: the four helper functions LED_Init, LED_On, LED_Off and LED_Blink together with the blink and light-in-turn flow of main;inc/main.h: the declarations of the four functions;src/n32g41x_it.c and inc/n32g41x_it.h: interrupt handlers;readme.txt: function, environment, and usage;MDK-ARM/ and EWARM/: Keil and IAR projects. |
| Key configuration | LED1 is PA1, LED2 is PA7 and LED3 is PB1;LED_Init configures all of them as GPIO_MODE_OUTPUT_PP, GPIO_NO_AF, GPIO_NO_PULL, GPIO_SLEW_RATE_FAST and GPIO_DS_HIGH, and calls RCC_EnableAHBPeriphClk to enable the matching port clock.The loop uses uint32_t i from 0 to 7, that is 8 toggles, each followed by SysTick_Delay_Ms(500). The system clock is HSI+PLL: 80 MHz on N32G412 and 96 MHz on N32G415. |
| Program and data path | main calls LED_Init three times to enable the clocks of PA1, PA7 and PB1 and configure them as push-pull outputs, then toggles LED1 and LED3 with LED_Blink and a 500 ms delay in a for loop 8 times;it then turns all three LEDs off with LED_Off, and finally lights them in the order LED1, LED2, LED3 in while (1), turning the previous LED off each time and delaying 500 ms. |
| Main APIs | GPIO_InitStruct, GPIO_InitPeripheral, GPIO_SetBits, GPIO_ResetBits, GPIO_TogglePin;RCC_EnableAHBPeriphClk for the clock and SysTick_Delay_Ms for the delay |
| Verification | After reset LED1 and LED3 blink together 4 times, then LED1, LED2 and LED3 light up in turn repeatedly; observing the 500 ms rhythm is enough to confirm that both the toggling and the light-in-turn sequence work. |
| Use note | Toolchains are KEIL MDK-ARM V5.34 and IAR EWARM 8.50.1; supported devices are N32G412x8L7, N32G412xBL7, N32G415x8L7, and N32G415xBL7. The LED-to-pin mapping comes from the board definitions, so it must be changed together with the board. |
Core-code walkthrough and porting
The example wraps pin configuration, lighting, turning off and toggling in three helper functions, so the main program only arranges the order of the blinking and the light-in-turn sequence.
Data path: main → LED_Init → RCC_EnableAHBPeriphClk enables the port clock and GPIO_InitPeripheral writes the output mode of PA1, PA7 and PB1 → LED_Blink/LED_On/LED_Off → GPIO_TogglePin/GPIO_SetBits/GPIO_ResetBits → pin levels → LED1 to LED3 turn on and off
1. Initialize the three LEDs one by one. At the start main calls LED_Init once for each LED, passing its own port, pin and clock macros.
/* LED port init */
LED_Init(LED1_PORT, LED1_PIN, LED1_CLOCK);
LED_Init(LED2_PORT, LED2_PIN, LED2_CLOCK);
LED_Init(LED3_PORT, LED3_PIN, LED3_CLOCK);
The three ports and pins come from bsp/inc/n32g41x_stb.h; on another board only that group of macros has to change, while the main program and the helper functions stay as they are.
2. Blink two LEDs 4 times first. The for loop runs from 0 to 7, that is 8 times, toggling LED1 and LED3 and delaying 500 ms on each pass, which shows as 4 blinks.
/* LED1 and LED3 blink 4 times */
for(i=0;i<8;i++)
{
LED_Blink(LED1_PORT, LED1_PIN);
LED_Blink(LED3_PORT, LED3_PIN);
SysTick_Delay_Ms(500);
}
The number of blinks follows from the loop bound 8 and the rhythm from SysTick_Delay_Ms(500); change both together when adjusting the observed effect.
3. The main loop lights the LEDs in turn. Entering while (1), the loop turns LED3 off and LED1 on, then turns the previous LED off and the next one on each round, delaying 500 ms every time.
/* Turn on LED1 and turn off LED3*/
LED_Off(LED3_PORT, LED3_PIN);
LED_On(LED1_PORT, LED1_PIN);
SysTick_Delay_Ms(500);
/* Turn on LED2 and turn off LED1*/
LED_Off(LED1_PORT, LED1_PIN);
LED_On(LED2_PORT, LED2_PIN);
SysTick_Delay_Ms(500);
/* Turn on LED3 and turn off LED2 */
LED_Off(LED2_PORT, LED2_PIN);
LED_On(LED3_PORT, LED3_PIN);
SysTick_Delay_Ms(500);
The light-in-turn order is simply the order of these three blocks; add or swap an LED by appending another block in the same way.
4. The initialization function fills a GPIO_InitType. LED_Init calls GPIO_InitStruct for the default values, then fills in the pin and the output parameters field by field, and finally hands the structure to GPIO_InitPeripheral to be written into the registers.
/* Init GPIO as output push-pull mode */
InitStruct.Pin = Pin;
InitStruct.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
InitStruct.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
InitStruct.GPIO_Alternate = GPIO_NO_AF;
InitStruct.GPIO_Pull = GPIO_NO_PULL;
InitStruct.GPIO_Current = GPIO_DS_HIGH;
The slew rate, drive strength and pull setting are all fixed here; change InitStruct.GPIO_Mode and InitStruct.GPIO_Pull for an open-drain output or a pull-up.
Corresponding source files: src/main.c, inc/main.h, projects/n32g41x_EVAL/bsp/inc/n32g41x_stb.h
5.10.4 Notes and troubleshooting
| Scenario | Check & action | Source |
|---|---|---|
| Access width of the I/O port registers | Every I/O port bit can be programmed freely, but the I/O port registers must be accessed as words (32 bits); 16-bit half-word and 8-bit byte accesses are not allowed. |
User manual |
| Changing single output bits without affecting the others | Writing 1 to the bits to be changed in the bit set/reset register GPIOx_PBSC and in the bit clear register GPIOx_PBC sets or clears those bits alone, the bits not written with 1 keep their value, the operation completes in a single AHB write, and the software does not have to disable interrupts. | User manual |
| The pin configuration is overwritten unexpectedly | After the locking sequence runs on a port bit, that pin configuration cannot be changed again until the next reset; PLOCKK is set only after the sequence w1 then w0 then w1 then r0, PLOCK[15:0] must not change during the sequence, and an interrupted sequence has to be repeated. |
User manual |
| An alternate function is selected but there is no output | When a port is configured in alternate-function mode, the port bit configuration registers GPIOx_AFL/GPIOx_AFH and the output type register GPIOx_POTYPE (push-pull or open-drain) must be programmed before use; whether the alternate function is an input or an output is decided by the peripheral. |
User manual |
| The slew rate bits do not exist on every port | The slew rate bits are not complete on every port: GPIOB has only SR5, SR6 and SR7, GPIOA has only SR0, SR1 and SR2, and GPIOC and GPIOD have none of these bits. | User manual |
| The SPI NSS pin in AFIO push-pull mode | The SPI1_NSS and SPI2_NSS bits in GPIOx_AFH must be configured to 0 when the matching SPI works as a slave, that is NSS is high-impedance when idle. | User manual |
| Clock source of the IO filter time | The IO filter time is counted in periods of the divided HCLK, whose divider is configured by GPIOFCLKDIV in the RCC; check that divider together with the filter setting. |
User manual |
The N32G412 and N32G415 series errata sheet V1.0.0 (2026.6.30) lists a single row for revision A chips with an empty errata link column, and gives no GPIO related entries.