10.2.3
hal_entry Function
When using an RTOS, the program starts thread scheduling from the main function; when not using an RTOS, the entry function of a C program, the main function, calls the hal_entry function. Since our newly created project does not use an RTOS, the user program starts execution from the hal_entry function. We directly open the “\src\hal_entry.c” file and write our code inside the hal_entry function.
The idea to achieve the blinking effect of the LED is very simple: first, initialize the LED pin configuration, then repeat this process in an infinite loop: turn on the LED, delay for 1 second, turn off the LED, delay for 1 second, and then turn the LED back on. By repeating this cycle, we can achieve the blinking effect of the LED.
First, we need to initialize the IOPORT module using the R_IOPORT_Open function. When calling the R_IOPORT_Open function, we need to pass the control block parameter g_ioport_ctrl and the configuration parameter g_ioport.p_cfg.
Swipe left to view the complete content
// Call R_IOPORT_Open function to initialize IOPORT module
R_IOPORT_Open (&g_ioport_ctrl, g_ioport.p_cfg);
Note
In fact, since the IOPORT module has already been opened in the R_BSP_WarmStart function, there is no need to open the IOPORT module again, although reopening it will not cause an error. The R_BSP_WarmStart function will be introduced in the later section “Detailed Explanation of FSP Library Startup Files,” so we can temporarily ignore it here.
After successfully opening the IOPORT module, it indicates that all IO pins have been initialized. Next, let the program continue to execute and enter the while(1) infinite loop. In the while(1) loop, we use the R_IOPORT_PinWrite and R_BSP_SoftwareDelay functions to implement the previously mentioned idea.
The R_IOPORT_PinWrite function can control the output high and low levels of the pins, thereby controlling the on and off states of the LED. Its first parameter requires passing the control block g_ioport_ctrl, the second parameter passes the IO port and pin number, and the third parameter passes the IO pin level.
Swipe left to view the complete content
fsp_err_t R_IOPORT_PinWrite(ioport_ctrl_t * const p_ctrl, bsp_io_port_pin_t pin, bsp_io_level_t level);
The R_BSP_SoftwareDelay function can be used for delays, and the duration for which the LED remains on and off is determined by this function. Its first parameter indicates the amount of delay, and the second parameter indicates the time unit.
Swipe left to view the complete content
void R_BSP_SoftwareDelay(uint32_t delay, bsp_delay_units_t units);
Available time unit parameters:
-
BSP_DELAY_UNITS_SECONDS, indicating seconds;
-
BSP_DELAY_UNITS_MILLISECONDS, indicating milliseconds;
-
BSP_DELAY_UNITS_MICROSECONDS, indicating microseconds.
Taking the Kizuna 6M5 development board as an example, the complete code is as follows: Code Listing 11_1
Listing 2: Code Listing 10-1: hal_entry Function
Swipe left to view the complete content
void hal_entry(void) {
/* TODO: add your own code here */
/* Initialize pin configuration (this is repeated initialization, can be commented out) */
R_IOPORT_Open (&g_ioport_ctrl, g_ioport.p_cfg);
while(1) {
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_00, BSP_IO_LEVEL_LOW); // LED1 ON
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_03, BSP_IO_LEVEL_LOW); // LED2 ON
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_LOW); // LED3 ON
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS); // Delay 1 second
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_00, BSP_IO_LEVEL_HIGH); // LED1 OFF
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_03, BSP_IO_LEVEL_HIGH); // LED2 OFF
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_HIGH); // LED3 OFF
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS); // Delay 1 second
}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
At this point, we have completely achieved the blinking effect of the LED. Readers can jump to the “Download Verification” section to verify its actual effect. According to the general requirements for writing drivers, we can separate the LED driver and encapsulate it in an independent source/header file. Next, we will introduce the general method of encapsulating the LED device driver.
10.2.4
Encapsulating the LED Device Driver
Let’s reorganize our project structure. Create a new folder named “led” in the src folder, and then create two files in that folder: “bsp_led.c” and “bsp_led.h,” as described in the previous “Create Project” section, and add them to our project. The contents of these two files are as follows.
Listing 3: Code Listing 10-2: led/bsp_led.h
Swipe left to view the complete content
#ifndef __BSP_LED_H
#define __BSP_LED_H
#include "hal_data.h"
/* Set LED pin to low level to turn on LED */
#define LED1_ON R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_00, BSP_IO_LEVEL_LOW)
#define LED2_ON R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_03, BSP_IO_LEVEL_LOW)
#define LED3_ON R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_LOW)
/* Set LED pin to high level to turn off LED */
#define LED1_OFF R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_00, BSP_IO_LEVEL_HIGH)
#define LED2_OFF R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_03, BSP_IO_LEVEL_HIGH)
#define LED3_OFF R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_HIGH)
/* Use registers to toggle LED */
#define LED1_TOGGLE R_PORT4->PODR ^= 1<<(BSP_IO_PORT_04_PIN_00 & 0xFF)
#define LED2_TOGGLE R_PORT4->PODR ^= 1<<(BSP_IO_PORT_04_PIN_03 & 0xFF)
#define LED3_TOGGLE R_PORT4->PODR ^= 1<<(BSP_IO_PORT_04_PIN_04 & 0xFF)
/* LED initialization function */
void LED_Init(void);
#endif
Listing 4: Code Listing 10-3: led/bsp_led.c
Swipe left to view the complete content
#include "bsp_led.h"
/* LED initialization function */
void LED_Init(void) {
/* Initialize pin configuration (this is repeated initialization, can be commented out) */
R_IOPORT_Open (&g_ioport_ctrl, g_ioport.p_cfg);
}
Add the inclusion of the header file “bsp_led.h” in the “hal_entry.c” file, and then modify the content of the hal_entry function as follows.
Listing 5: Code Listing 10-4: hal_entry Function
Swipe left to view the complete content
/* User header file inclusion */
#include "led/bsp_led.h"
void hal_entry(void) {
/* TODO: add your own code here */
LED_Init(); // LED initialization
while(1) {
LED1_ON; // LED1 ON
LED2_ON; // LED2 ON
LED3_ON; // LED3 ON
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS); // Delay 1 second
LED1_OFF; // LED1 OFF
LED2_OFF; // LED2 OFF
LED3_OFF; // LED3 OFF
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS); // Delay 1 second
}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
By encapsulating hardware drivers in this way, the program can appear simpler and clearer, and it will make our future development smoother.
10.3
Download Verification
After compiling and downloading the program to the development board, press the reset button to reset the development board. You can observe that the three LED lights on the development board, besides the power indicator, are slowly blinking simultaneously, changing their on and off states once per second.

Need Technical Support?
If you have any questions while using Renesas MCU/MPU products, you can scan the QR code below or copy the URL into your browser to access the Renesas Technical Forum for answers or to obtain online technical support.

https://community-ja.renesas.com/zh/forums-groups/mcu-mpu/
To be continued
Recommended Reading

GPIO Output – Renesas RA Series FSP Library Development Practical Guide (23)

Introduction to Renesas FSP Firmware Library – Renesas RA Series FSP Library Development Practical Guide (22)

Defining IO Initialization Structure – Renesas RA Series FSP Library Development Practical Guide (21)

