diff --git a/bsp/renesas/libraries/HAL_Drivers/SConscript b/bsp/renesas/libraries/HAL_Drivers/SConscript index b789c6ed49..c0db499f86 100644 --- a/bsp/renesas/libraries/HAL_Drivers/SConscript +++ b/bsp/renesas/libraries/HAL_Drivers/SConscript @@ -26,7 +26,7 @@ if GetDepend(['BSP_USING_ONCHIP_RTC']): src += ['drv_rtc.c'] if GetDepend(['BSP_USING_I2C', 'RT_USING_I2C_BITOPS']): - if GetDepend('BSP_USING_I2C0') or GetDepend('BSP_USING_I2C1'): + if GetDepend('BSP_USING_I2C0') or GetDepend('BSP_USING_I2C1') or GetDepend('BSP_USING_I2C2'): src += ['drv_soft_i2c.c'] if GetDepend(['BSP_USING_I2C', 'BSP_USING_HW_I2C']): diff --git a/bsp/renesas/libraries/HAL_Drivers/drv_adc.c b/bsp/renesas/libraries/HAL_Drivers/drv_adc.c index 9fd734d922..ebe7eed9b8 100644 --- a/bsp/renesas/libraries/HAL_Drivers/drv_adc.c +++ b/bsp/renesas/libraries/HAL_Drivers/drv_adc.c @@ -41,7 +41,7 @@ struct rt_adc_device adc1_device; struct ra_dev _ra_adc1_device = {.ra_adc_device_t = &adc1_device, .ra_adc_dev = &ra_adc[1]}; #endif -static rt_err_t ra_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled) +static rt_err_t ra_adc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled) { RT_ASSERT(device != RT_NULL); struct ra_adc_map *adc = (struct ra_adc_map *)device->parent.user_data; @@ -78,7 +78,7 @@ rt_err_t ra_adc_close(struct rt_adc_device *device) return RT_EOK; } -static rt_err_t ra_get_adc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value) +static rt_err_t ra_get_adc_value(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value) { RT_ASSERT(device != RT_NULL); struct ra_adc_map *adc = (struct ra_adc_map *)device->parent.user_data; diff --git a/bsp/renesas/libraries/HAL_Drivers/drv_soft_i2c.c b/bsp/renesas/libraries/HAL_Drivers/drv_soft_i2c.c index 57aa02e9e2..ac2ea26284 100644 --- a/bsp/renesas/libraries/HAL_Drivers/drv_soft_i2c.c +++ b/bsp/renesas/libraries/HAL_Drivers/drv_soft_i2c.c @@ -21,7 +21,7 @@ #define DBG_LVL DBG_INFO #endif /* DRV_DEBUG */ -#if !defined(BSP_USING_I2C0) && !defined(BSP_USING_I2C1) +#if !defined(BSP_USING_I2C0) && !defined(BSP_USING_I2C1) && !defined(BSP_USING_I2C2) #error "Please define at least one BSP_USING_I2Cx" /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */ #endif @@ -34,6 +34,9 @@ static const struct ra_soft_i2c_config soft_i2c_config[] = #ifdef BSP_USING_I2C1 I2C1_BUS_CONFIG, #endif +#ifdef BSP_USING_I2C2 + I2C2_BUS_CONFIG, +#endif }; static struct ra_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_config[0])]; diff --git a/bsp/renesas/libraries/HAL_Drivers/drv_soft_i2c.h b/bsp/renesas/libraries/HAL_Drivers/drv_soft_i2c.h index 098810b433..24881cd25b 100644 --- a/bsp/renesas/libraries/HAL_Drivers/drv_soft_i2c.h +++ b/bsp/renesas/libraries/HAL_Drivers/drv_soft_i2c.h @@ -30,6 +30,15 @@ struct ra_i2c struct rt_i2c_bus_device i2c2_bus; }; +#ifdef BSP_USING_I2C0 +#define I2C0_BUS_CONFIG \ + { \ + .scl = BSP_I2C0_SCL_PIN, \ + .sda = BSP_I2C0_SDA_PIN, \ + .bus_name = "i2c0", \ + } +#endif + #ifdef BSP_USING_I2C1 #define I2C1_BUS_CONFIG \ { \ diff --git a/bsp/renesas/ra6m3-hmi-board/.settings/standalone.prefs b/bsp/renesas/ra6m3-hmi-board/.settings/standalone.prefs index 691ce137f0..1394e92dba 100644 --- a/bsp/renesas/ra6m3-hmi-board/.settings/standalone.prefs +++ b/bsp/renesas/ra6m3-hmi-board/.settings/standalone.prefs @@ -1,19 +1,24 @@ -#Tue Apr 18 17:25:03 CST 2023 +#Tue Oct 31 10:46:22 CST 2023 com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#Common\#\#all\#\#fsp_common\#\#\#\#3.5.0/libraries= com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#BSP\#\#ra6m3\#\#fsp\#\#\#\#3.5.0/libraries= com.renesas.cdt.ddsc.content/com.renesas.cdt.ddsc.content.defaultlinkerscript=script/fsp.scat -com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#BSP\#\#ra6m3\#\#fsp\#\#\#\#3.5.0/all=3427620923,ra/fsp/src/bsp/mcu/ra6m3/bsp_mcu_info.h|143358381,ra/fsp/src/bsp/mcu/ra6m3/bsp_elc.h|2743353138,ra/fsp/src/bsp/mcu/ra6m3/bsp_feature.h +com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#BSP\#\#ra6m3\#\#fsp\#\#\#\#3.5.0/all=143358381,ra/fsp/src/bsp/mcu/ra6m3/bsp_elc.h|3427620923,ra/fsp/src/bsp/mcu/ra6m3/bsp_mcu_info.h|2743353138,ra/fsp/src/bsp/mcu/ra6m3/bsp_feature.h +com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#HAL\ Drivers\#\#all\#\#r_adc\#\#\#\#3.5.0/libraries= com.renesas.cdt.ddsc.threads.configurator/collapse/module.driver.uart_on_sci_uart.552817864=false -com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#Common\#\#all\#\#fsp_common\#\#\#\#3.5.0/all=731782070,ra/fsp/src/bsp/mcu/all/bsp_irq.h|3492513568,ra/fsp/src/bsp/mcu/all/bsp_register_protection.c|1630997354,ra/fsp/src/bsp/mcu/all/bsp_irq.c|400573940,ra/fsp/src/bsp/mcu/all/bsp_register_protection.h|1904866635,ra/fsp/src/bsp/mcu/all/bsp_clocks.h|1728953905,ra/fsp/inc/fsp_features.h|3549961311,ra/fsp/src/bsp/mcu/all/bsp_tfu.h|4222527282,ra/fsp/src/bsp/mcu/all/bsp_module_stop.h|1939984091,ra/fsp/inc/api/r_ioport_api.h|3606266210,ra/fsp/src/bsp/mcu/all/bsp_rom_registers.c|3753300083,ra/fsp/src/bsp/mcu/all/bsp_arm_exceptions.h|2208590403,ra/fsp/inc/instances/r_ioport.h|470601830,ra/fsp/src/bsp/mcu/all/bsp_clocks.c|3297195641,ra/fsp/inc/fsp_version.h|521902797,ra/fsp/src/bsp/mcu/all/bsp_security.h|2847966430,ra/fsp/src/bsp/mcu/all/bsp_security.c|460577388,ra/fsp/src/bsp/mcu/all/bsp_io.h|1353647784,ra/fsp/src/bsp/mcu/all/bsp_delay.c|2906400,ra/fsp/src/bsp/mcu/all/bsp_common.c|2308894280,ra/fsp/src/bsp/cmsis/Device/RENESAS/Include/system.h|3255765648,ra/fsp/src/bsp/cmsis/Device/RENESAS/Source/system.c|4051445857,ra/fsp/src/bsp/mcu/all/bsp_common.h|2386285210,ra/fsp/src/bsp/cmsis/Device/RENESAS/Include/renesas.h|1615019982,ra/fsp/src/bsp/mcu/all/bsp_sbrk.c|2425160085,ra/fsp/inc/api/bsp_api.h|3983299396,ra/fsp/src/bsp/mcu/all/bsp_delay.h|1499520276,ra/fsp/src/bsp/mcu/all/bsp_group_irq.c|3984836408,ra/fsp/src/bsp/mcu/all/bsp_group_irq.h|2920829723,ra/fsp/src/bsp/mcu/all/bsp_guard.c|568600546,ra/fsp/src/bsp/cmsis/Device/RENESAS/Source/startup.c|1552630912,ra/fsp/src/bsp/mcu/all/bsp_guard.h|1236602439,ra/fsp/src/bsp/mcu/all/bsp_io.c|1992062042,ra/fsp/src/bsp/mcu/all/bsp_compiler_support.h|546480625,ra/fsp/inc/fsp_common_api.h|3998046333,ra/fsp/src/bsp/cmsis/Device/RENESAS/Include/base_addresses.h|2977689308,ra/fsp/src/bsp/mcu/all/bsp_mcu_api.h +com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#Common\#\#all\#\#fsp_common\#\#\#\#3.5.0/all=546480625,ra/fsp/inc/fsp_common_api.h|400573940,ra/fsp/src/bsp/mcu/all/bsp_register_protection.h|2977689308,ra/fsp/src/bsp/mcu/all/bsp_mcu_api.h|2386285210,ra/fsp/src/bsp/cmsis/Device/RENESAS/Include/renesas.h|2425160085,ra/fsp/inc/api/bsp_api.h|3998046333,ra/fsp/src/bsp/cmsis/Device/RENESAS/Include/base_addresses.h|460577388,ra/fsp/src/bsp/mcu/all/bsp_io.h|3492513568,ra/fsp/src/bsp/mcu/all/bsp_register_protection.c|3753300083,ra/fsp/src/bsp/mcu/all/bsp_arm_exceptions.h|568600546,ra/fsp/src/bsp/cmsis/Device/RENESAS/Source/startup.c|3297195641,ra/fsp/inc/fsp_version.h|3606266210,ra/fsp/src/bsp/mcu/all/bsp_rom_registers.c|470601830,ra/fsp/src/bsp/mcu/all/bsp_clocks.c|3255765648,ra/fsp/src/bsp/cmsis/Device/RENESAS/Source/system.c|2208590403,ra/fsp/inc/instances/r_ioport.h|1630997354,ra/fsp/src/bsp/mcu/all/bsp_irq.c|3984836408,ra/fsp/src/bsp/mcu/all/bsp_group_irq.h|4222527282,ra/fsp/src/bsp/mcu/all/bsp_module_stop.h|1499520276,ra/fsp/src/bsp/mcu/all/bsp_group_irq.c|731782070,ra/fsp/src/bsp/mcu/all/bsp_irq.h|1904866635,ra/fsp/src/bsp/mcu/all/bsp_clocks.h|1615019982,ra/fsp/src/bsp/mcu/all/bsp_sbrk.c|2308894280,ra/fsp/src/bsp/cmsis/Device/RENESAS/Include/system.h|3549961311,ra/fsp/src/bsp/mcu/all/bsp_tfu.h|521902797,ra/fsp/src/bsp/mcu/all/bsp_security.h|2847966430,ra/fsp/src/bsp/mcu/all/bsp_security.c|1236602439,ra/fsp/src/bsp/mcu/all/bsp_io.c|1552630912,ra/fsp/src/bsp/mcu/all/bsp_guard.h|4051445857,ra/fsp/src/bsp/mcu/all/bsp_common.h|1353647784,ra/fsp/src/bsp/mcu/all/bsp_delay.c|2906400,ra/fsp/src/bsp/mcu/all/bsp_common.c|2920829723,ra/fsp/src/bsp/mcu/all/bsp_guard.c|3983299396,ra/fsp/src/bsp/mcu/all/bsp_delay.h|1992062042,ra/fsp/src/bsp/mcu/all/bsp_compiler_support.h|1728953905,ra/fsp/inc/fsp_features.h|1939984091,ra/fsp/inc/api/r_ioport_api.h com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#BSP\#\#ra6m3\#\#device\#\#R7FA6M3AH3CFB\#\#3.5.0/libraries= com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#HAL\ Drivers\#\#all\#\#r_sci_uart\#\#\#\#3.5.0/libraries= +com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#HAL\ Drivers\#\#all\#\#r_gpt\#\#\#\#3.5.0/libraries= com.renesas.cdt.ddsc.settingseditor/com.renesas.cdt.ddsc.settingseditor.active_page=SWPConfigurator -com.renesas.cdt.ddsc.packs.componentfiles/Arm\#\#CMSIS\#\#CMSIS5\#\#CoreM\#\#\#\#5.8.0+renesas.0.fsp.3.5.0/all=1441545198,ra/arm/CMSIS_5/LICENSE.txt|2718020009,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm33.h|3898569239,ra/arm/CMSIS_5/CMSIS/Core/Include/cmsis_armclang.h|3007265674,ra/arm/CMSIS_5/CMSIS/Core/Include/core_armv8mbl.h|1168186370,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm55.h|3127123217,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm35p.h|3163610011,ra/arm/CMSIS_5/CMSIS/Core/Include/pmu_armv8.h|2851112248,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm1.h|3358993753,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm4.h|2333906976,ra/arm/CMSIS_5/CMSIS/Core/Include/cmsis_version.h|304461792,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm3.h|965562395,ra/arm/CMSIS_5/CMSIS/Core/Include/cmsis_gcc.h|364344841,ra/arm/CMSIS_5/CMSIS/Core/Include/core_sc300.h|1564341101,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm7.h|1577199483,ra/arm/CMSIS_5/CMSIS/Core/Include/cmsis_iccarm.h|2701379970,ra/arm/CMSIS_5/CMSIS/Core/Include/mpu_armv8.h|2635219934,ra/arm/CMSIS_5/CMSIS/Core/Include/tz_context.h|1017116116,ra/arm/CMSIS_5/CMSIS/Core/Include/cmsis_compiler.h|1044777225,ra/arm/CMSIS_5/CMSIS/Core/Include/cmsis_armcc.h|1745843273,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm0.h|1494441116,ra/arm/CMSIS_5/CMSIS/Core/Include/mpu_armv7.h|4290386133,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm0plus.h|1372010515,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm23.h|3911746910,ra/arm/CMSIS_5/CMSIS/Core/Include/cmsis_armclang_ltm.h|2327633156,ra/arm/CMSIS_5/CMSIS/Core/Include/core_sc000.h|2381390623,ra/arm/CMSIS_5/CMSIS/Core/Include/core_armv8mml.h|302860276,ra/arm/CMSIS_5/CMSIS/Core/Include/cachel1_armv7.h|3552689244,ra/arm/CMSIS_5/CMSIS/Core/Include/core_armv81mml.h +com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#HAL\ Drivers\#\#all\#\#r_gpt\#\#\#\#3.5.0/all=1958999550,ra/fsp/src/r_gpt/r_gpt.c|232390045,ra/fsp/inc/api/r_timer_api.h|2886639616,ra/fsp/inc/instances/r_gpt.h +com.renesas.cdt.ddsc.packs.componentfiles/Arm\#\#CMSIS\#\#CMSIS5\#\#CoreM\#\#\#\#5.8.0+renesas.0.fsp.3.5.0/all=1441545198,ra/arm/CMSIS_5/LICENSE.txt|3898569239,ra/arm/CMSIS_5/CMSIS/Core/Include/cmsis_armclang.h|2327633156,ra/arm/CMSIS_5/CMSIS/Core/Include/core_sc000.h|1372010515,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm23.h|3552689244,ra/arm/CMSIS_5/CMSIS/Core/Include/core_armv81mml.h|2381390623,ra/arm/CMSIS_5/CMSIS/Core/Include/core_armv8mml.h|1044777225,ra/arm/CMSIS_5/CMSIS/Core/Include/cmsis_armcc.h|965562395,ra/arm/CMSIS_5/CMSIS/Core/Include/cmsis_gcc.h|2333906976,ra/arm/CMSIS_5/CMSIS/Core/Include/cmsis_version.h|2701379970,ra/arm/CMSIS_5/CMSIS/Core/Include/mpu_armv8.h|3911746910,ra/arm/CMSIS_5/CMSIS/Core/Include/cmsis_armclang_ltm.h|1494441116,ra/arm/CMSIS_5/CMSIS/Core/Include/mpu_armv7.h|2635219934,ra/arm/CMSIS_5/CMSIS/Core/Include/tz_context.h|1168186370,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm55.h|4290386133,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm0plus.h|302860276,ra/arm/CMSIS_5/CMSIS/Core/Include/cachel1_armv7.h|3163610011,ra/arm/CMSIS_5/CMSIS/Core/Include/pmu_armv8.h|2718020009,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm33.h|364344841,ra/arm/CMSIS_5/CMSIS/Core/Include/core_sc300.h|3007265674,ra/arm/CMSIS_5/CMSIS/Core/Include/core_armv8mbl.h|1745843273,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm0.h|3127123217,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm35p.h|1564341101,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm7.h|1577199483,ra/arm/CMSIS_5/CMSIS/Core/Include/cmsis_iccarm.h|304461792,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm3.h|3358993753,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm4.h|1017116116,ra/arm/CMSIS_5/CMSIS/Core/Include/cmsis_compiler.h|2851112248,ra/arm/CMSIS_5/CMSIS/Core/Include/core_cm1.h com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#BSP\#\#ra6m3\#\#device\#\#\#\#3.5.0/all=2308894280,ra/fsp/src/bsp/cmsis/Device/RENESAS/Include/system.h com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#BSP\#\#Board\#\#custom\#\#\#\#3.5.0/all= -com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#HAL\ Drivers\#\#all\#\#r_ioport\#\#\#\#3.5.0/all=2208590403,ra/fsp/inc/instances/r_ioport.h|3254285722,ra/fsp/src/r_ioport/r_ioport.c|1939984091,ra/fsp/inc/api/r_ioport_api.h +com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#HAL\ Drivers\#\#all\#\#r_adc\#\#\#\#3.5.0/all=4250819551,ra/fsp/inc/instances/r_adc.h|1515334001,ra/fsp/inc/api/r_elc_api.h|1610456547,ra/fsp/inc/api/r_transfer_api.h|1675086128,ra/fsp/inc/api/r_adc_api.h|377989633,ra/fsp/src/r_adc/r_adc.c +com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#HAL\ Drivers\#\#all\#\#r_ioport\#\#\#\#3.5.0/all=3254285722,ra/fsp/src/r_ioport/r_ioport.c|1939984091,ra/fsp/inc/api/r_ioport_api.h|2208590403,ra/fsp/inc/instances/r_ioport.h com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#BSP\#\#ra6m3\#\#device\#\#\#\#3.5.0/libraries= -com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#HAL\ Drivers\#\#all\#\#r_sci_uart\#\#\#\#3.5.0/all=3916852077,ra/fsp/inc/api/r_uart_api.h|3094200246,ra/fsp/src/r_sci_uart/r_sci_uart.c|1610456547,ra/fsp/inc/api/r_transfer_api.h|1889256766,ra/fsp/inc/instances/r_sci_uart.h +com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#HAL\ Drivers\#\#all\#\#r_sci_uart\#\#\#\#3.5.0/all=1889256766,ra/fsp/inc/instances/r_sci_uart.h|1610456547,ra/fsp/inc/api/r_transfer_api.h|3916852077,ra/fsp/inc/api/r_uart_api.h|3094200246,ra/fsp/src/r_sci_uart/r_sci_uart.c +com.renesas.cdt.ddsc.threads.configurator/collapse/module.driver.uart_on_sci_uart.606654632=false com.renesas.cdt.ddsc.packs.componentfiles/Arm\#\#CMSIS\#\#CMSIS5\#\#CoreM\#\#\#\#5.8.0+renesas.0.fsp.3.5.0/libraries= com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#BSP\#\#Board\#\#custom\#\#\#\#3.5.0/libraries= com.renesas.cdt.ddsc.packs.componentfiles/Renesas\#\#HAL\ Drivers\#\#all\#\#r_ioport\#\#\#\#3.5.0/libraries= diff --git a/bsp/renesas/ra6m3-hmi-board/board/Kconfig b/bsp/renesas/ra6m3-hmi-board/board/Kconfig index 91938682c4..788422d916 100644 --- a/bsp/renesas/ra6m3-hmi-board/board/Kconfig +++ b/bsp/renesas/ra6m3-hmi-board/board/Kconfig @@ -8,7 +8,25 @@ menu "Hardware Drivers Config" default y menu "Onboard Peripheral Drivers" - + + config BSP_USING_ARDUINO + bool "Compatible with Arduino Ecosystem (RTduino)" + select PKG_USING_RTDUINO + select BSP_USING_UART4 + select BSP_USING_GPIO + select BSP_USING_TIM + select BSP_USING_TIM2 + select BSP_USING_ADC + select BSP_USING_ADC0 + select BSP_USING_PWM + select BSP_USING_PWM2 + select BSP_USING_PWM2_CH2 + select BSP_USING_I2C + select BSP_USING_I2C2 + imply RTDUINO_USING_SERVO + imply RTDUINO_USING_WIRE + default n + endmenu menu "On-chip Peripheral Drivers" @@ -445,6 +463,65 @@ menu "Hardware Drivers Config" default n endif + menuconfig BSP_USING_I2C + bool "Enable software I2C bus" + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + default n + + if BSP_USING_I2C + config BSP_USING_I2C + menuconfig BSP_USING_I2C0 + bool "Enable I2C0 Bus (software simulation)" + default n + if BSP_USING_I2C0 + comment "Please select your i2c analog pin, e.g. 'P512': BSP_IO_PORT_05_PIN_12" + config BSP_I2C0_SCL_PIN + string "i2c0 scl pin number (Pxxx)" + default "pxxx" + config BSP_I2C0_SDA_PIN + string "i2c0 sda pin number (Pxxx)" + default "pxxx" + endif + + menuconfig BSP_USING_I2C1 + bool "Enable I2C1 Bus (software simulation)" + default n + if BSP_USING_I2C1 + comment "Please select your i2c analog pin, e.g. 'P512': BSP_IO_PORT_05_PIN_12" + config BSP_I2C1_SCL_PIN + string "i2c1 scl pin number (Pxxx)" + default "pxxx" + config BSP_I2C1_SDA_PIN + string "i2c1 sda pin number (Pxxx)" + default "pxxx" + endif + + menuconfig BSP_USING_I2C2 + bool "Enable I2C2 Bus (software simulation)" + default n + if BSP_USING_I2C2 + comment "Please select your i2c analog pin, e.g. 'P512': BSP_IO_PORT_05_PIN_12" + config BSP_I2C2_SCL_PIN + string "i2c2 scl pin number (P512)" + default "BSP_IO_PORT_05_PIN_12" + config BSP_I2C2_SDA_PIN + string "i2c2 sda pin number (P511)" + default "BSP_IO_PORT_05_PIN_11" + endif + endif + + menuconfig BSP_USING_ADC + bool "Enable ADC" + default n + select RT_USING_ADC + if BSP_USING_ADC + config BSP_USING_ADC0 + bool "Enable ADC0" + default n + endif + menuconfig BSP_USING_FS bool "Enable filesystem" default n @@ -481,11 +558,22 @@ menu "Hardware Drivers Config" default n select RT_USING_PWM if BSP_USING_PWM - config BSP_USING_PWM12 - bool "Enable GPT12 (16-Bits) output PWM" - default n + config BSP_USING_PWM12 + bool "Enable GPT12 (16-Bits) output PWM" + default n + + menuconfig BSP_USING_PWM2 + bool "Enable timer2 output PWM" + default n + if BSP_USING_PWM2 + config BSP_USING_PWM2_CH2 + bool "Enable PWM2 channel2" + default n + endif + endif + menuconfig BSP_USING_CAN bool "Enable CAN" default n diff --git a/bsp/renesas/ra6m3-hmi-board/board/rtduino/SConscript b/bsp/renesas/ra6m3-hmi-board/board/rtduino/SConscript new file mode 100644 index 0000000000..0196c0b781 --- /dev/null +++ b/bsp/renesas/ra6m3-hmi-board/board/rtduino/SConscript @@ -0,0 +1,19 @@ +from building import * +import os + +cwd = GetCurrentDir() +src = [] +group = [] +CPPPATH = [cwd] + + +if GetDepend(['PKG_USING_RTDUINO']) and not GetDepend(['RTDUINO_NO_SETUP_LOOP']): + src += Glob('arduino_main.cpp') + +list = os.listdir(cwd) +for item in list: + if os.path.isfile(os.path.join(cwd, item, 'SConscript')): + group = group + SConscript(os.path.join(item, 'SConscript')) + +group = group + DefineGroup('rtduino-port', src, depend = ['PKG_USING_RTDUINO'], CPPPATH = CPPPATH) +Return('group') \ No newline at end of file diff --git a/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_main.cpp b/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_main.cpp new file mode 100644 index 0000000000..0a1a5650d3 --- /dev/null +++ b/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_main.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-10-28 Wangyuqiang first version + */ + +#include + +void setup(void) +{ + /* put your setup code here, to run once: */ + Serial.begin(); +} + +void loop(void) +{ + /* put your main code here, to run repeatedly: */ + Serial.println("Hello Arduino!"); + delay(800); +} diff --git a/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/README.md b/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/README.md new file mode 100644 index 0000000000..16846da661 --- /dev/null +++ b/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/README.md @@ -0,0 +1,50 @@ +# ra6m3-hmi-board Arduino Eco-compatibility Guide + +**[中文](README_zh.md)** | **English** + +## 1 RTduino - Arduino Eco-compatibility Layer for RT-Thread + +The ra6m3-hmi-board development board has been fully adapted to the [RTduino software package](https://github.com/RTduino/RTduino), which is an Arduino eco-compatibility layer for RT-Thread. Users can program this BSP in accordance with Arduino coding conventions and can utilize a wide range of libraries from the Arduino community, significantly enhancing the RT-Thread ecosystem. For more information, please refer to the [RTduino software package documentation](https://github.com/RTduino/RTduino). + +### 1.1 Enabling the Arduino Eco-compatibility Layer for this BSP + +In the Env tool, enter the "menuconfig" command, or in the RT-Thread Studio IDE, select "RT-Thread Settings": + +```Kconfig +Hardware Drivers Config ---> + Onboard Peripheral Drivers ---> + [*] Compatible with Arduino Ecosystem (RTduino) +``` + +## 2 Arduino Pin Layout + +For more information about pin layout, please see [pins_arduino.c](pins_arduino.c) and [pins_arduino.h](pins_arduino.h). + +![ra6m3-hmi-board-pinout-figure](ra6m3-hmi-board-pinout-figure.jpg) + +| Arduino Pin Number | STM32 Pin Number | 5V Tolerance | Remarks | +| ------------------- | --------- | ---- | ------------------------------------------------------------------------- | +| 0 (D0) | P206 | Yes | Serial4-RX, managed by RT-Thread's UART device framework uart4 by default | +| 1 (D1) | P205 | Yes | Serial4-TX, managed by RT-Thread's UART device framework uart4 by default | +| 2 (D2) | P008 | Yes | | +| 3 (D3) | P506 | Yes | | +| 4 (D4) | P603 | Yes | | +| 5 (D5) | P604 | Yes | | +| 6 (D6) | P605 | Yes | | +| 7 (D7) | P208 | Yes | | +| 8 (D8) | P207 | Yes | | +| 9 (D9) | P009 | Yes | | +| 10 (D10) | P712 | Yes | PWM2-CH2, managed by RT-Thread's PWM device framework pwm2's channel2 by default | +| 11 (D11) | P512 | Yes | I2C2-SCL, managed by RT-Thread's I2C device framework i2c2 by default | +| 12 (D12) | P511 | Yes | I2C2-SDA, managed by RT-Thread's I2C device framework i2c2 by default | +| 13 (D13) | P204 | Yes | | +| 14 (D14) | P203 | Yes | | +| 15 (D15) | P202 | Yes | | +| 16 (A0) | P000 | Yes | ADC1-CH0-EXTVOL (external voltage), managed by RT-Thread's ADC device framework adc0's channel0 by default | +| 17 (A1) | P001 | Yes | ADC1-CH1-EXTVOL (external voltage), managed by RT-Thread's ADC device framework adc0's channel1 by default | +| 18 (A2) | P002 | Yes | ADC1-CH2-EXTVOL (external voltage), managed by RT-Thread's ADC device framework adc0's channel2 by default | +| 19 (A3) | P003 | Yes | ADC1-CH7-EXTVOL (external voltage), managed by RT-Thread's ADC device framework adc0's channel7 by default | +| 20 (A4) | P508 | Yes | ADC1-CH19-EXTVOL (external voltage), managed by RT-Thread's ADC device framework adc0's channel20 by default | +| 21 (A5) | P014 | Yes | ADC1-CH5-EXTVOL (external voltage), managed by RT-Thread's ADC device framework adc0's channel5 by default | + +> Note: RTduino does not currently support MDK. It is recommended to use the GNU GCC toolchain for compilation. \ No newline at end of file diff --git a/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/README_zh.md b/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/README_zh.md new file mode 100644 index 0000000000..38715e6944 --- /dev/null +++ b/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/README_zh.md @@ -0,0 +1,50 @@ +# ra6m3-hmi-board 开发板的Arduino生态兼容说明 + +**[English](README.md)** | **中文** + +## 1 RTduino - RT-Thread的Arduino生态兼容层 + +ra6m3-hmi-board 开发板已经完整适配了[RTduino软件包](https://github.com/RTduino/RTduino),即RT-Thread的Arduino生态兼容层。用户可以按照Arduino的编程习惯来操作该BSP,并且可以使用大量Arduino社区丰富的库,是对RT-Thread生态的极大增强。更多信息,请参见[RTduino软件包说明文档](https://github.com/RTduino/RTduino)。 + +### 1.1 如何开启针对本BSP的Arduino生态兼容层 + +Env 工具下敲入 menuconfig 命令,或者 RT-Thread Studio IDE 下选择 RT-Thread Settings: + +```Kconfig +Hardware Drivers Config ---> + Onboard Peripheral Drivers ---> + [*] Compatible with Arduino Ecosystem (RTduino) +``` + +## 2 Arduino引脚排布 + +更多引脚布局相关信息参见 [pins_arduino.c](pins_arduino.c) 和 [pins_arduino.h](pins_arduino.h)。 + +![ra6m3-hmi-board-pinout-figure](ra6m3-hmi-board-pinout-figure.jpg) + +| Arduino引脚编号 | STM32引脚编号 | 5V容忍 | 备注 | +| ------------------- | --------- | ---- | ------------------------------------------------------------------------- | +| 0 (D0) | P206 | 是 | Serial4-RX,默认被RT-Thread的UART设备框架uart4接管 | +| 1 (D1) | P205 | 是 | Serial4-TX,默认被RT-Thread的UART设备框架uart4接管 | +| 2 (D2) | P008 | 是 | | +| 3 (D3) | P506 | 是 | | +| 4 (D4) | P603 | 是 | | +| 5 (D5) | P604 | 是 | | +| 6 (D6) | P605 | 是 | | +| 7 (D7) | P208 | 是 | | +| 8 (D8) | P207 | 是 | | +| 9 (D9) | P009 | 是 | | +| 10 (D10) | P712 | 是 | PWM2-CH2,默认被RT-Thread的PWM设备框架pwm2的channel2接管 | +| 11 (D11) | P512 | 是 | I2C2-SCL,默认被RT-Thread的I2C设备框架i2c2接管 | +| 12 (D12) | P511 | 是 | I2C2-SDA,默认被RT-Thread的I2C设备框架i2c2接管 | +| 13 (D13) | P204 | 是 | | +| 14 (D14) | P203 | 是 | | +| 15 (D15) | P202 | 是 | | +| 16 (A0) | P000 | 是 | ADC1-CH0-EXTVOL(外部电压),默认被RT-Thread的ADC设备框架adc0的channel0接管 | +| 17 (A1) | P001 | 是 | ADC1-CH1-EXTVOL(外部电压),默认被RT-Thread的ADC设备框架adc0的channel1接管 | +| 18 (A2) | P002 | 是 | ADC1-CH2-EXTVOL(外部电压),默认被RT-Thread的ADC设备框架adc0的channel2接管 | +| 19 (A3) | P003 | 是 | ADC1-CH7-EXTVOL(外部电压),默认被RT-Thread的ADC设备框架adc0的channel7接管 | +| 20 (A4) | P508 | 是 | ADC1-CH19-EXTVOL(外部电压),默认被RT-Thread的ADC设备框架adc0的channel20接管 | +| 21 (A5) | P014 | 是 | ADC1-CH5-EXTVOL(外部电压),默认被RT-Thread的ADC设备框架adc0的channel5接管 | + +> 注意:RTduino暂时不对MDK支持,建议使用GNU GCC工具链编译 diff --git a/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/SConscript b/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/SConscript new file mode 100644 index 0000000000..aa01ea933e --- /dev/null +++ b/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/SConscript @@ -0,0 +1,16 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') +group = [] +inc = [cwd] + +list = os.listdir(cwd) +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + group = group + SConscript(os.path.join(d, 'SConscript')) + +group = group + DefineGroup('RTduino', src, depend = ['PKG_USING_RTDUINO'], CPPPATH = inc) + +Return('group') \ No newline at end of file diff --git a/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/pins_arduino.c b/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/pins_arduino.c new file mode 100644 index 0000000000..ebd3d581d2 --- /dev/null +++ b/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/pins_arduino.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-10-28 Wangyuqiang first version + */ + +#include +#include "pins_arduino.h" + +#include +#include "hal_data.h" +#include + +/* + * {Arduino Pin, RT-Thread Pin [, Device Name, Channel]} + * [] means optional + * Digital pins must NOT give the device name and channel. + * Analog pins MUST give the device name and channel(ADC, PWM or DAC). + * Arduino Pin must keep in sequence. + */ +const pin_map_t pin_map_table[]= +{ + {D0, BSP_IO_PORT_02_PIN_06, "uart4"}, /* Serial4-RX */ + {D1, BSP_IO_PORT_02_PIN_05, "uart4"}, /* Serial4-TX */ + {D2, BSP_IO_PORT_00_PIN_08}, + {D3, BSP_IO_PORT_05_PIN_06}, + {D4, BSP_IO_PORT_06_PIN_03}, + {D5, BSP_IO_PORT_06_PIN_04}, + {D6, BSP_IO_PORT_06_PIN_05}, + {D7, BSP_IO_PORT_02_PIN_08}, + {D8, BSP_IO_PORT_02_PIN_07}, + {D9, BSP_IO_PORT_00_PIN_09}, /* SPI-SS */ + {D10, BSP_IO_PORT_07_PIN_12, "pwm2", 2}, /* PWM */ + {D11, BSP_IO_PORT_05_PIN_12, "i2c2"}, /* I2C-SCL (Wire) */ + {D12, BSP_IO_PORT_05_PIN_11, "i2c2"}, /* I2C-SDA (Wire) */ + {D13, BSP_IO_PORT_02_PIN_04}, + {D14, BSP_IO_PORT_02_PIN_03}, + {D15, BSP_IO_PORT_02_PIN_02}, + {A0, BSP_IO_PORT_00_PIN_00, "adc0", 0}, /* ADC */ + {A1, BSP_IO_PORT_00_PIN_01, "adc0", 1}, /* ADC */ + {A2, BSP_IO_PORT_00_PIN_02, "adc0", 2}, /* ADC */ + {A3, BSP_IO_PORT_00_PIN_03, "adc0", 7}, /* ADC */ + {A4, BSP_IO_PORT_05_PIN_08, "adc0", 20}, /* ADC */ + {A5, BSP_IO_PORT_00_PIN_14, "adc0", 5} /* ADC */ +}; \ No newline at end of file diff --git a/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/pins_arduino.h b/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/pins_arduino.h new file mode 100644 index 0000000000..2cf8b744e7 --- /dev/null +++ b/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/pins_arduino.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-10-28 Wangyuqiang first version + */ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +/* pins alias. Must keep in sequence */ +#define D0 (0) +#define D1 (1) +#define D2 (2) +#define D3 (3) +#define D4 (4) +#define D5 (5) +#define D6 (6) +#define D7 (7) +#define D8 (8) +#define D9 (9) +#define D10 (10) +#define D11 (11) +#define D12 (12) +#define D13 (13) +#define D14 (14) +#define D15 (15) +#define A0 (16) +#define A1 (17) +#define A2 (18) +#define A3 (19) +#define A4 (20) +#define A5 (21) + +#define RTDUINO_PIN_MAX_LIMIT A5 /* pin number max limit check */ + +#define F_CPU 120000000L /* CPU:120MHz */ + +/* i2c2 : PD10-SDA PD10-SCL */ +#define RTDUINO_DEFAULT_IIC_BUS_NAME "i2c2" + +/* Serial4(uart4) : P205-TX P206-RX */ +#define RTDUINO_SERIAL2_DEVICE_NAME "uart4" + +#define RTDUINO_DEFAULT_HWTIMER_DEVICE_NAME "timer2" + +#endif /* Pins_Arduino_h */ diff --git a/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/ra6m3-hmi-board-pinout-figure.jpg b/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/ra6m3-hmi-board-pinout-figure.jpg new file mode 100644 index 0000000000..157cdb4bab Binary files /dev/null and b/bsp/renesas/ra6m3-hmi-board/board/rtduino/arduino_pinout/ra6m3-hmi-board-pinout-figure.jpg differ diff --git a/bsp/renesas/ra6m3-hmi-board/buildinfo.gpdsc b/bsp/renesas/ra6m3-hmi-board/buildinfo.gpdsc index 971a3d223d..55be25e21d 100644 --- a/bsp/renesas/ra6m3-hmi-board/buildinfo.gpdsc +++ b/bsp/renesas/ra6m3-hmi-board/buildinfo.gpdsc @@ -57,65 +57,57 @@ + + + + + - - - - - - - - - - - - - + + - - @@ -129,6 +121,8 @@ + + diff --git a/bsp/renesas/ra6m3-hmi-board/configuration.xml b/bsp/renesas/ra6m3-hmi-board/configuration.xml index 6f4dd28f74..3337f216f3 100644 --- a/bsp/renesas/ra6m3-hmi-board/configuration.xml +++ b/bsp/renesas/ra6m3-hmi-board/configuration.xml @@ -165,6 +165,14 @@ SCI UART Renesas.RA.3.5.0.pack + + A/D Converter + Renesas.RA.3.5.0.pack + + + General PWM Timer + Renesas.RA.3.5.0.pack + @@ -203,33 +211,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bsp/renesas/ra6m3-hmi-board/ra/fsp/inc/api/r_adc_api.h b/bsp/renesas/ra6m3-hmi-board/ra/fsp/inc/api/r_adc_api.h new file mode 100644 index 0000000000..d22d1ef4b4 --- /dev/null +++ b/bsp/renesas/ra6m3-hmi-board/ra/fsp/inc/api/r_adc_api.h @@ -0,0 +1,410 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics America Inc. and may only be used with products + * of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. Renesas products are + * sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for the selection and use + * of Renesas products and Renesas assumes no liability. No license, express or implied, to any intellectual property + * right is granted by Renesas. This software is protected under all applicable laws, including copyright laws. Renesas + * reserves the right to change or discontinue this software and/or this documentation. THE SOFTWARE AND DOCUMENTATION + * IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND TO THE FULLEST EXTENT + * PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, INCLUDING WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE SOFTWARE OR + * DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. TO THE MAXIMUM + * EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR DOCUMENTATION + * (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, INCLUDING, + * WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY LOST PROFITS, + * OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE POSSIBILITY + * OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ + +#ifndef R_ADC_API_H +#define R_ADC_API_H + +/*******************************************************************************************************************//** + * @ingroup RENESAS_INTERFACES + * @defgroup ADC_API ADC Interface + * @brief Interface for A/D Converters. + * + * @section ADC_API_SUMMARY Summary + * The ADC interface provides standard ADC functionality including one-shot mode (single scan), continuous scan and + * group scan. It also allows configuration of hardware and software triggers for starting scans. After each conversion + * an interrupt can be triggered, and if a callback function is provided, the call back is invoked with the + * appropriate event information. + * + * Implemented by: + * @ref ADC + * + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ + +/* Includes board and MCU related header files. */ +#include "bsp_api.h" +#include "r_elc_api.h" +#include "r_transfer_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/***************************************************************************** + * Typedef definitions + ******************************************************************************/ + +/** ADC operation mode definitions */ +typedef enum e_adc_mode +{ + ADC_MODE_SINGLE_SCAN = 0, ///< Single scan - one or more channels + ADC_MODE_GROUP_SCAN = 1, ///< Two trigger sources to trigger scan for two groups which contain one or more channels + ADC_MODE_CONTINUOUS_SCAN = 2, ///< Continuous scan - one or more channels +} adc_mode_t; + +/** ADC data resolution definitions */ +typedef enum e_adc_resolution +{ + ADC_RESOLUTION_12_BIT = 0, ///< 12 bit resolution + ADC_RESOLUTION_10_BIT = 1, ///< 10 bit resolution + ADC_RESOLUTION_8_BIT = 2, ///< 8 bit resolution + ADC_RESOLUTION_14_BIT = 3, ///< 14 bit resolution + ADC_RESOLUTION_16_BIT = 4, ///< 16 bit resolution + ADC_RESOLUTION_24_BIT = 5, ///< 24 bit resolution +} adc_resolution_t; + +/** ADC data alignment definitions */ +typedef enum e_adc_alignment +{ + ADC_ALIGNMENT_RIGHT = 0, ///< Data alignment right + ADC_ALIGNMENT_LEFT = 1 ///< Data alignment left +} adc_alignment_t; + +/** ADC trigger mode definitions */ +typedef enum e_adc_trigger +{ + ADC_TRIGGER_SOFTWARE = 0, ///< Software trigger; not for group modes + ADC_TRIGGER_SYNC_ELC = 2, ///< Synchronous trigger via ELC + ADC_TRIGGER_ASYNC_EXTERNAL = 3, ///< External asynchronous trigger; not for group modes +} adc_trigger_t; + +/** ADC callback event definitions */ +typedef enum e_adc_event +{ + ADC_EVENT_SCAN_COMPLETE, ///< Normal/Group A scan complete + ADC_EVENT_SCAN_COMPLETE_GROUP_B, ///< Group B scan complete + ADC_EVENT_CALIBRATION_COMPLETE, ///< Calibration complete + ADC_EVENT_CONVERSION_COMPLETE, ///< Conversion complete + ADC_EVENT_CALIBRATION_REQUEST, ///< Calibration requested + ADC_EVENT_CONVERSION_ERROR, ///< Scan error + ADC_EVENT_OVERFLOW, ///< Overflow occurred + ADC_EVENT_LIMIT_CLIP, ///< Limiter clipping occurred + ADC_EVENT_FIFO_READ_REQUEST, ///< FIFO read requested + ADC_EVENT_FIFO_OVERFLOW, ///< FIFO overflow occurred + ADC_EVENT_WINDOW_COMPARE_A, ///< Window A comparison condition met + ADC_EVENT_WINDOW_COMPARE_B, ///< Window B comparison condition met +} adc_event_t; + +#ifndef BSP_OVERRIDE_ADC_CHANNEL_T + +/** ADC channels */ +typedef enum e_adc_channel +{ + ADC_CHANNEL_0 = 0, ///< ADC channel 0 + ADC_CHANNEL_1 = 1, ///< ADC channel 1 + ADC_CHANNEL_2 = 2, ///< ADC channel 2 + ADC_CHANNEL_3 = 3, ///< ADC channel 3 + ADC_CHANNEL_4 = 4, ///< ADC channel 4 + ADC_CHANNEL_5 = 5, ///< ADC channel 5 + ADC_CHANNEL_6 = 6, ///< ADC channel 6 + ADC_CHANNEL_7 = 7, ///< ADC channel 7 + ADC_CHANNEL_8 = 8, ///< ADC channel 8 + ADC_CHANNEL_9 = 9, ///< ADC channel 9 + ADC_CHANNEL_10 = 10, ///< ADC channel 10 + ADC_CHANNEL_11 = 11, ///< ADC channel 11 + ADC_CHANNEL_12 = 12, ///< ADC channel 12 + ADC_CHANNEL_13 = 13, ///< ADC channel 13 + ADC_CHANNEL_14 = 14, ///< ADC channel 14 + ADC_CHANNEL_15 = 15, ///< ADC channel 15 + ADC_CHANNEL_16 = 16, ///< ADC channel 16 + ADC_CHANNEL_17 = 17, ///< ADC channel 17 + ADC_CHANNEL_18 = 18, ///< ADC channel 18 + ADC_CHANNEL_19 = 19, ///< ADC channel 19 + ADC_CHANNEL_20 = 20, ///< ADC channel 20 + ADC_CHANNEL_21 = 21, ///< ADC channel 21 + ADC_CHANNEL_22 = 22, ///< ADC channel 22 + ADC_CHANNEL_23 = 23, ///< ADC channel 23 + ADC_CHANNEL_24 = 24, ///< ADC channel 24 + ADC_CHANNEL_25 = 25, ///< ADC channel 25 + ADC_CHANNEL_26 = 26, ///< ADC channel 26 + ADC_CHANNEL_27 = 27, ///< ADC channel 27 + ADC_CHANNEL_28 = 28, ///< ADC channel 28 + ADC_CHANNEL_DUPLEX_A = 50, ///< Data duplexing register A + ADC_CHANNEL_DUPLEX_B = 51, ///< Data duplexing register B + ADC_CHANNEL_DUPLEX = -4, ///< Data duplexing register + ADC_CHANNEL_TEMPERATURE = -3, ///< Temperature sensor output + ADC_CHANNEL_VOLT = -2, ///< Internal reference voltage +} adc_channel_t; + +#endif + +typedef enum e_adc_group_id +{ + ADC_GROUP_ID_0 = 0, ///< Group ID 0 + ADC_GROUP_ID_1 = 1, ///< Group ID 1 + ADC_GROUP_ID_2 = 2, ///< Group ID 2 + ADC_GROUP_ID_3 = 3, ///< Group ID 3 + ADC_GROUP_ID_4 = 4, ///< Group ID 4 + ADC_GROUP_ID_5 = 5, ///< Group ID 5 + ADC_GROUP_ID_6 = 6, ///< Group ID 6 + ADC_GROUP_ID_7 = 7, ///< Group ID 7 + ADC_GROUP_ID_8 = 8, ///< Group ID 8 +} adc_group_id_t; + +typedef enum e_adc_group_mask +{ + ADC_GROUP_MASK_NONE = 0x000, ///< Group Mask Unknown or None + ADC_GROUP_MASK_0 = 0x001, ///< Group Mask 0 + ADC_GROUP_MASK_1 = 0x002, ///< Group Mask 1 + ADC_GROUP_MASK_2 = 0x004, ///< Group Mask 2 + ADC_GROUP_MASK_3 = 0x008, ///< Group Mask 3 + ADC_GROUP_MASK_4 = 0x010, ///< Group Mask 4 + ADC_GROUP_MASK_5 = 0x020, ///< Group Mask 5 + ADC_GROUP_MASK_6 = 0x040, ///< Group Mask 6 + ADC_GROUP_MASK_7 = 0x080, ///< Group Mask 7 + ADC_GROUP_MASK_8 = 0x100, ///< Group Mask 8 + ADC_GROUP_MASK_ALL = 0x1FF, ///< All Groups +} adc_group_mask_t; + +/** ADC states. */ +typedef enum e_adc_state +{ + ADC_STATE_IDLE = 0, ///< ADC is idle + ADC_STATE_SCAN_IN_PROGRESS = 1, ///< ADC scan in progress +} adc_state_t; + +/** ADC status. */ +typedef struct st_adc_status +{ + adc_state_t state; ///< Current state +} adc_status_t; + +/** ADC callback arguments definitions */ +typedef struct st_adc_callback_args +{ + uint16_t unit; ///< ADC device in use + adc_event_t event; ///< ADC callback event + void const * p_context; ///< Placeholder for user data + adc_channel_t channel; ///< Channel of conversion result. Only valid for r_adc ADC_EVENT_CONVERSION_COMPLETE + uint64_t channel_mask; ///< Channel mask for conversion result. Only valid for r_adc_b + adc_group_mask_t group_mask; ///< Group Mask +} adc_callback_args_t; + +/** ADC Information Structure for Transfer Interface */ +typedef struct st_adc_info +{ + __I void * p_address; ///< The address to start reading the data from + uint32_t length; ///< The total number of transfers to read + + transfer_size_t transfer_size; ///< The size of each transfer + elc_peripheral_t elc_peripheral; ///< Name of the peripheral in the ELC list + elc_event_t elc_event; ///< Name of the ELC event for the peripheral + uint32_t calibration_data; ///< Temperature sensor calibration data (0xFFFFFFFF if unsupported) for reference voltage + int16_t slope_microvolts; ///< Temperature sensor slope in microvolts/degrees C + bool calibration_ongoing; ///< Calibration is in progress. +} adc_info_t; + +/** ADC general configuration */ +typedef struct st_adc_cfg +{ + uint16_t unit; ///< ADC unit to be used + adc_mode_t mode; ///< ADC operation mode + adc_resolution_t resolution; ///< ADC resolution + adc_alignment_t alignment; ///< Specify left or right alignment; ignored if addition used + adc_trigger_t trigger; ///< Default and Group A trigger source + IRQn_Type scan_end_irq; ///< Scan end IRQ number + IRQn_Type scan_end_b_irq; ///< Scan end group B IRQ number + uint8_t scan_end_ipl; ///< Scan end interrupt priority + uint8_t scan_end_b_ipl; ///< Scan end group B interrupt priority + void (* p_callback)(adc_callback_args_t * p_args); ///< Callback function; set to NULL for none + void const * p_context; ///< Placeholder for user data. Passed to the user callback in @ref adc_callback_args_t. + void const * p_extend; ///< Extension parameter for hardware specific settings +} adc_cfg_t; + +/** ADC control block. Allocate using driver instance control structure from driver instance header file. */ +typedef void adc_ctrl_t; + +/** ADC functions implemented at the HAL layer will follow this API. */ +typedef struct st_adc_api +{ + /** Initialize ADC Unit; apply power, set the operational mode, trigger sources, interrupt priority, + * and configurations common to all channels and sensors. + * @par Implemented as + * - @ref R_ADC_Open() + * - @ref R_ADC_B_Open() + * - @ref R_SDADC_Open() + * + * @pre Configure peripheral clocks, ADC pins and IRQs prior to calling this function. + * @param[in] p_ctrl Pointer to control handle structure + * @param[in] p_cfg Pointer to configuration structure + */ + fsp_err_t (* open)(adc_ctrl_t * const p_ctrl, adc_cfg_t const * const p_cfg); + + /** Configure the scan including the channels, groups, and scan triggers to be used for the unit that + * was initialized in the open call. Some configurations are not supported for all implementations. + * See implementation for details. + * @par Implemented as + * - @ref R_ADC_ScanCfg() + * - @ref R_ADC_B_ScanCfg() + * - @ref R_SDADC_ScanCfg() + * + * @param[in] p_ctrl Pointer to control handle structure + * @param[in] p_extend See implementation for details + */ + fsp_err_t (* scanCfg)(adc_ctrl_t * const p_ctrl, void const * const p_extend); + + /** Start the scan (in case of a software trigger), or enable the hardware trigger. + * @par Implemented as + * - @ref R_ADC_ScanStart() + * - @ref R_SDADC_ScanStart() + * + * @param[in] p_ctrl Pointer to control handle structure + */ + fsp_err_t (* scanStart)(adc_ctrl_t * const p_ctrl); + + /** Start the scan group (in case of a software trigger), or enable the hardware trigger. + * @par Implemented as + * - @ref R_ADC_B_ScanGroupStart() + * + * @param[in] p_ctrl Pointer to control handle structure + * @param[in] group_mask Mask of groups to start + */ + fsp_err_t (* scanGroupStart)(adc_ctrl_t * p_ctrl, adc_group_mask_t group_mask); + + /** Stop the ADC scan (in case of a software trigger), or disable the hardware trigger. + * @par Implemented as + * - @ref R_ADC_ScanStop() + * - @ref R_SDADC_ScanStop() + * + * @param[in] p_ctrl Pointer to control handle structure + */ + fsp_err_t (* scanStop)(adc_ctrl_t * const p_ctrl); + + /** Check scan status. + * @par Implemented as + * - @ref R_ADC_StatusGet() + * - @ref R_ADC_B_StatusGet() + * - @ref R_SDADC_StatusGet() + * + * @param[in] p_ctrl Pointer to control handle structure + * @param[out] p_status Pointer to store current status in + */ + fsp_err_t (* scanStatusGet)(adc_ctrl_t * const p_ctrl, adc_status_t * p_status); + + /** Read ADC conversion result. + * @par Implemented as + * - @ref R_ADC_Read() + * - @ref R_ADC_B_Read() + * - @ref R_SDADC_Read() + * + * @param[in] p_ctrl Pointer to control handle structure + * @param[in] reg_id ADC channel to read (see enumeration adc_channel_t) + * @param[in] p_data Pointer to variable to load value into. + */ + fsp_err_t (* read)(adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, uint16_t * const p_data); + + /** Read ADC conversion result into a 32-bit word. + * @par Implemented as + * - @ref R_ADC_Read32() + * - @ref R_ADC_B_Read32() + * - @ref R_SDADC_Read32() + * + * @param[in] p_ctrl Pointer to control handle structure + * @param[in] reg_id ADC channel to read (see enumeration adc_channel_t) + * @param[in] p_data Pointer to variable to load value into. + */ + fsp_err_t (* read32)(adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, uint32_t * const p_data); + + /** Calibrate ADC or associated PGA (programmable gain amplifier). The driver may require implementation specific + * arguments to the p_extend input. Not supported for all implementations. See implementation for details. + * @par Implemented as + * - @ref R_ADC_Calibrate() + * - @ref R_ADC_B_Calibrate() + * - @ref R_SDADC_Calibrate() + * + * @param[in] p_ctrl Pointer to control handle structure + * @param[in] p_extend Pointer to implementation specific arguments + */ + fsp_err_t (* calibrate)(adc_ctrl_t * const p_ctrl, void const * p_extend); + + /** Set offset for input PGA configured for differential input. Not supported for all implementations. + * See implementation for details. + * @par Implemented as + * - @ref R_SDADC_OffsetSet() + * + * @param[in] p_ctrl Pointer to control handle structure + * @param[in] reg_id ADC channel to read (see enumeration adc_channel_t) + * @param[in] offset See implementation for details. + */ + fsp_err_t (* offsetSet)(adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, int32_t const offset); + + /** + * Specify callback function and optional context pointer and working memory pointer. + * @par Implemented as + * - @ref R_ADC_CallbackSet() + * - @ref R_ADC_B_CallbackSet() + * + * @param[in] p_ctrl Pointer to the ADC control block. + * @param[in] p_callback Callback function + * @param[in] p_context Pointer to send to callback function + * @param[in] p_working_memory Pointer to volatile memory where callback structure can be allocated. + * Callback arguments allocated here are only valid during the callback. + */ + fsp_err_t (* callbackSet)(adc_ctrl_t * const p_api_ctrl, void (* p_callback)(adc_callback_args_t *), + void const * const p_context, adc_callback_args_t * const p_callback_memory); + + /** Close the specified ADC unit by ending any scan in progress, disabling interrupts, and removing power to the + * specified A/D unit. + * @par Implemented as + * - @ref R_ADC_Close() + * - @ref R_ADC_B_Close() + * - @ref R_SDADC_Close() + * + * @param[in] p_ctrl Pointer to control handle structure + */ + fsp_err_t (* close)(adc_ctrl_t * const p_ctrl); + + /** Return the ADC data register address of the first (lowest number) channel and the total number of bytes + * to be read in order for the DTC/DMAC to read the conversion results of all configured channels. + * Return the temperature sensor calibration and slope data. + * @par Implemented as + * - @ref R_ADC_InfoGet() + * - @ref R_ADC_B_InfoGet() + * - @ref R_SDADC_InfoGet() + * + * @param[in] p_ctrl Pointer to control handle structure + * @param[out] p_adc_info Pointer to ADC information structure + */ + fsp_err_t (* infoGet)(adc_ctrl_t * const p_ctrl, adc_info_t * const p_adc_info); +} adc_api_t; + +/** This structure encompasses everything that is needed to use an instance of this interface. */ +typedef struct st_adc_instance +{ + adc_ctrl_t * p_ctrl; ///< Pointer to the control structure for this instance + adc_cfg_t const * p_cfg; ///< Pointer to the configuration structure for this instance + void const * p_channel_cfg; ///< Pointer to the channel configuration structure for this instance + adc_api_t const * p_api; ///< Pointer to the API structure for this instance +} adc_instance_t; + +/*******************************************************************************************************************//** + * @} (end defgroup ADC_API) + **********************************************************************************************************************/ + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER +#endif diff --git a/bsp/renesas/ra6m3-hmi-board/ra/fsp/inc/api/r_elc_api.h b/bsp/renesas/ra6m3-hmi-board/ra/fsp/inc/api/r_elc_api.h new file mode 100644 index 0000000000..89861e49da --- /dev/null +++ b/bsp/renesas/ra6m3-hmi-board/ra/fsp/inc/api/r_elc_api.h @@ -0,0 +1,185 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics America Inc. and may only be used with products + * of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. Renesas products are + * sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for the selection and use + * of Renesas products and Renesas assumes no liability. No license, express or implied, to any intellectual property + * right is granted by Renesas. This software is protected under all applicable laws, including copyright laws. Renesas + * reserves the right to change or discontinue this software and/or this documentation. THE SOFTWARE AND DOCUMENTATION + * IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND TO THE FULLEST EXTENT + * PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, INCLUDING WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE SOFTWARE OR + * DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. TO THE MAXIMUM + * EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR DOCUMENTATION + * (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, INCLUDING, + * WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY LOST PROFITS, + * OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE POSSIBILITY + * OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * @ingroup RENESAS_INTERFACES + * @defgroup ELC_API ELC Interface + * @brief Interface for the Event Link Controller. + * + * + * + * @{ + **********************************************************************************************************************/ + +#ifndef R_ELC_API_H +#define R_ELC_API_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ + +/* Register definitions, common services and error codes. */ +#include "bsp_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ +#ifndef ELC_PERIPHERAL_NUM + #define ELC_PERIPHERAL_NUM (23U) +#endif + +/********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +#ifndef BSP_OVERRIDE_ELC_PERIPHERAL_T + +/** Possible peripherals to be linked to event signals (not all available on all MCUs) */ +typedef enum e_elc_peripheral +{ + ELC_PERIPHERAL_GPT_A = (0), + ELC_PERIPHERAL_GPT_B = (1), + ELC_PERIPHERAL_GPT_C = (2), + ELC_PERIPHERAL_GPT_D = (3), + ELC_PERIPHERAL_GPT_E = (4), + ELC_PERIPHERAL_GPT_F = (5), + ELC_PERIPHERAL_GPT_G = (6), + ELC_PERIPHERAL_GPT_H = (7), + ELC_PERIPHERAL_ADC0 = (8), + ELC_PERIPHERAL_ADC0_B = (9), + ELC_PERIPHERAL_ADC1 = (10), + ELC_PERIPHERAL_ADC1_B = (11), + ELC_PERIPHERAL_DAC0 = (12), + ELC_PERIPHERAL_DAC1 = (13), + ELC_PERIPHERAL_IOPORT1 = (14), + ELC_PERIPHERAL_IOPORT2 = (15), + ELC_PERIPHERAL_IOPORT3 = (16), + ELC_PERIPHERAL_IOPORT4 = (17), + ELC_PERIPHERAL_CTSU = (18), + ELC_PERIPHERAL_DA8_0 = (19), + ELC_PERIPHERAL_DA8_1 = (20), + ELC_PERIPHERAL_SDADC0 = (22), +} elc_peripheral_t; + +#endif + +/** ELC control block. Allocate an instance specific control block to pass into the ELC API calls. + * @par Implemented as + * - elc_instance_ctrl_t + */ +typedef void elc_ctrl_t; + +/** Main configuration structure for the Event Link Controller */ +typedef struct st_elc_cfg +{ + elc_event_t const link[ELC_PERIPHERAL_NUM]; ///< Event link register (ELSR) settings +} elc_cfg_t; + +/** Software event number */ +typedef enum e_elc_software_event +{ + ELC_SOFTWARE_EVENT_0, ///< Software event 0 + ELC_SOFTWARE_EVENT_1, ///< Software event 1 +} elc_software_event_t; + +/** ELC driver structure. General ELC functions implemented at the HAL layer follow this API. */ +typedef struct st_elc_api +{ + /** Initialize all links in the Event Link Controller. + * @par Implemented as + * - @ref R_ELC_Open() + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] p_cfg Pointer to configuration structure. + **/ + fsp_err_t (* open)(elc_ctrl_t * const p_ctrl, elc_cfg_t const * const p_cfg); + + /** Disable all links in the Event Link Controller and close the API. + * @par Implemented as + * - @ref R_ELC_Close() + * + * @param[in] p_ctrl Pointer to control structure. + **/ + fsp_err_t (* close)(elc_ctrl_t * const p_ctrl); + + /** Generate a software event in the Event Link Controller. + * @par Implemented as + * - @ref R_ELC_SoftwareEventGenerate() + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] eventNum Software event number to be generated. + **/ + fsp_err_t (* softwareEventGenerate)(elc_ctrl_t * const p_ctrl, elc_software_event_t event_num); + + /** Create a single event link. + * @par Implemented as + * - @ref R_ELC_LinkSet() + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] peripheral The peripheral block that will receive the event signal. + * @param[in] signal The event signal. + **/ + fsp_err_t (* linkSet)(elc_ctrl_t * const p_ctrl, elc_peripheral_t peripheral, elc_event_t signal); + + /** Break an event link. + * @par Implemented as + * - @ref R_ELC_LinkBreak() + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] peripheral The peripheral that should no longer be linked. + **/ + fsp_err_t (* linkBreak)(elc_ctrl_t * const p_ctrl, elc_peripheral_t peripheral); + + /** Enable the operation of the Event Link Controller. + * @par Implemented as + * - @ref R_ELC_Enable() + * + * @param[in] p_ctrl Pointer to control structure. + **/ + fsp_err_t (* enable)(elc_ctrl_t * const p_ctrl); + + /** Disable the operation of the Event Link Controller. + * @par Implemented as + * - @ref R_ELC_Disable() + * + * @param[in] p_ctrl Pointer to control structure. + **/ + fsp_err_t (* disable)(elc_ctrl_t * const p_ctrl); +} elc_api_t; + +/** This structure encompasses everything that is needed to use an instance of this interface. */ +typedef struct st_elc_instance +{ + elc_ctrl_t * p_ctrl; ///< Pointer to the control structure for this instance + elc_cfg_t const * p_cfg; ///< Pointer to the configuration structure for this instance + elc_api_t const * p_api; ///< Pointer to the API structure for this instance +} elc_instance_t; + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif + +/*******************************************************************************************************************//** + * @} (end addtogroup ELC_API) + **********************************************************************************************************************/ diff --git a/bsp/renesas/ra6m3-hmi-board/ra/fsp/inc/api/r_timer_api.h b/bsp/renesas/ra6m3-hmi-board/ra/fsp/inc/api/r_timer_api.h new file mode 100644 index 0000000000..2cbd3b4860 --- /dev/null +++ b/bsp/renesas/ra6m3-hmi-board/ra/fsp/inc/api/r_timer_api.h @@ -0,0 +1,332 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics America Inc. and may only be used with products + * of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. Renesas products are + * sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for the selection and use + * of Renesas products and Renesas assumes no liability. No license, express or implied, to any intellectual property + * right is granted by Renesas. This software is protected under all applicable laws, including copyright laws. Renesas + * reserves the right to change or discontinue this software and/or this documentation. THE SOFTWARE AND DOCUMENTATION + * IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND TO THE FULLEST EXTENT + * PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, INCLUDING WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE SOFTWARE OR + * DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. TO THE MAXIMUM + * EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR DOCUMENTATION + * (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, INCLUDING, + * WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY LOST PROFITS, + * OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE POSSIBILITY + * OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ + +#ifndef R_TIMER_API_H +#define R_TIMER_API_H + +/*******************************************************************************************************************//** + * @defgroup TIMER_API Timer Interface + * @ingroup RENESAS_INTERFACES + * @brief Interface for timer functions. + * + * @section TIMER_API_SUMMARY Summary + * The general timer interface provides standard timer functionality including periodic mode, one-shot mode, PWM output, + * and free-running timer mode. After each timer cycle (overflow or underflow), an interrupt can be triggered. + * + * If an instance supports output compare mode, it is provided in the extension configuration + * timer_on__cfg_t defined in r_.h. + * + * Implemented by: + * - @ref GPT + * - @ref AGT + * + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ + +/* Includes board and MCU related header files. */ +#include "bsp_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/* Leading zeroes removed to avoid coding standard violation. */ + +/********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** Events that can trigger a callback function */ +typedef enum e_timer_event +{ + TIMER_EVENT_CYCLE_END, ///< Requested timer delay has expired or timer has wrapped around + TIMER_EVENT_CREST = TIMER_EVENT_CYCLE_END, ///< Timer crest event (counter is at a maximum, triangle-wave PWM only) + TIMER_EVENT_CAPTURE_A, ///< A capture has occurred on signal A + TIMER_EVENT_CAPTURE_B, ///< A capture has occurred on signal B + TIMER_EVENT_TROUGH, ///< Timer trough event (counter is 0, triangle-wave PWM only +} timer_event_t; + +/** Timer variant types. */ +typedef enum e_timer_variant +{ + TIMER_VARIANT_32_BIT, ///< 32-bit timer + TIMER_VARIANT_16_BIT ///< 16-bit timer +} timer_variant_t; + +/** Callback function parameter data */ +typedef struct st_timer_callback_args +{ + /** Placeholder for user data. Set in @ref timer_api_t::open function in @ref timer_cfg_t. */ + void const * p_context; + timer_event_t event; ///< The event can be used to identify what caused the callback. + + /** Most recent capture, only valid if event is TIMER_EVENT_CAPTURE_A or TIMER_EVENT_CAPTURE_B. */ + uint32_t capture; +} timer_callback_args_t; + +/** Timer control block. Allocate an instance specific control block to pass into the timer API calls. + * @par Implemented as + * - gpt_instance_ctrl_t + * - agt_instance_ctrl_t + */ +typedef void timer_ctrl_t; + +/** Possible status values returned by @ref timer_api_t::statusGet. */ +typedef enum e_timer_state +{ + TIMER_STATE_STOPPED = 0, ///< Timer is stopped + TIMER_STATE_COUNTING = 1, ///< Timer is running +} timer_state_t; + +/** Timer operational modes */ +typedef enum e_timer_mode +{ + TIMER_MODE_PERIODIC, ///< Timer restarts after period elapses. + TIMER_MODE_ONE_SHOT, ///< Timer stops after period elapses. + TIMER_MODE_PWM, ///< Timer generates saw-wave PWM output. + TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM = 4U, ///< Timer generates symmetric triangle-wave PWM output. + TIMER_MODE_TRIANGLE_WAVE_ASYMMETRIC_PWM = 5U, ///< Timer generates asymmetric triangle-wave PWM output. + + /** + * Timer generates Asymmetric Triangle-wave PWM output. In PWM mode 3, the duty cycle does + * not need to be updated at each tough/crest interrupt. Instead, the trough and crest duty cycle values can be + * set once and only need to be updated when the application needs to change the duty cycle. + */ + TIMER_MODE_TRIANGLE_WAVE_ASYMMETRIC_PWM_MODE3 = 6U, +} timer_mode_t; + +/** Direction of timer count */ +typedef enum e_timer_direction +{ + TIMER_DIRECTION_DOWN = 0, ///< Timer count goes up + TIMER_DIRECTION_UP = 1 ///< Timer count goes down +} timer_direction_t; + +/** PCLK divisors */ +typedef enum e_timer_source_div +{ + TIMER_SOURCE_DIV_1 = 0, ///< Timer clock source divided by 1 + TIMER_SOURCE_DIV_2 = 1, ///< Timer clock source divided by 2 + TIMER_SOURCE_DIV_4 = 2, ///< Timer clock source divided by 4 + TIMER_SOURCE_DIV_8 = 3, ///< Timer clock source divided by 8 + TIMER_SOURCE_DIV_16 = 4, ///< Timer clock source divided by 16 + TIMER_SOURCE_DIV_32 = 5, ///< Timer clock source divided by 32 + TIMER_SOURCE_DIV_64 = 6, ///< Timer clock source divided by 64 + TIMER_SOURCE_DIV_128 = 7, ///< Timer clock source divided by 128 + TIMER_SOURCE_DIV_256 = 8, ///< Timer clock source divided by 256 + TIMER_SOURCE_DIV_512 = 9, ///< Timer clock source divided by 512 + TIMER_SOURCE_DIV_1024 = 10, ///< Timer clock source divided by 1024 +} timer_source_div_t; + +/** Timer information structure to store various information for a timer resource */ +typedef struct st_timer_info +{ + timer_direction_t count_direction; ///< Clock counting direction of the timer. + uint32_t clock_frequency; ///< Clock frequency of the timer counter. + + /** Period in raw timer counts. + * @note For triangle wave PWM modes, the full period is double this value. + */ + uint32_t period_counts; +} timer_info_t; + +/** Current timer status. */ +typedef struct st_timer_status +{ + uint32_t counter; ///< Current counter value + timer_state_t state; ///< Current timer state (running or stopped) +} timer_status_t; + +/** User configuration structure, used in open function */ +typedef struct st_timer_cfg +{ + timer_mode_t mode; ///< Select enumerated value from @ref timer_mode_t + + /* Period in raw timer counts. + * @note For triangle wave PWM modes, enter the period of half the triangle wave, or half the desired period. + */ + uint32_t period_counts; ///< Period in raw timer counts + timer_source_div_t source_div; ///< Source clock divider + uint32_t duty_cycle_counts; ///< Duty cycle in counts + + /** Select a channel corresponding to the channel number of the hardware. */ + uint8_t channel; + uint8_t cycle_end_ipl; ///< Cycle end interrupt priority + IRQn_Type cycle_end_irq; ///< Cycle end interrupt + + /** Callback provided when a timer ISR occurs. Set to NULL for no CPU interrupt. */ + void (* p_callback)(timer_callback_args_t * p_args); + + /** Placeholder for user data. Passed to the user callback in @ref timer_callback_args_t. */ + void const * p_context; + void const * p_extend; ///< Extension parameter for hardware specific settings. +} timer_cfg_t; + +/** Timer API structure. General timer functions implemented at the HAL layer follow this API. */ +typedef struct st_timer_api +{ + /** Initial configuration. + * @par Implemented as + * - @ref R_GPT_Open() + * - @ref R_AGT_Open() + * + * @param[in] p_ctrl Pointer to control block. Must be declared by user. Elements set here. + * @param[in] p_cfg Pointer to configuration structure. All elements of this structure must be set by user. + */ + fsp_err_t (* open)(timer_ctrl_t * const p_ctrl, timer_cfg_t const * const p_cfg); + + /** Start the counter. + * @par Implemented as + * - @ref R_GPT_Start() + * - @ref R_AGT_Start() + * + * @param[in] p_ctrl Control block set in @ref timer_api_t::open call for this timer. + */ + fsp_err_t (* start)(timer_ctrl_t * const p_ctrl); + + /** Stop the counter. + * @par Implemented as + * - @ref R_GPT_Stop() + * - @ref R_AGT_Stop() + * + * @param[in] p_ctrl Control block set in @ref timer_api_t::open call for this timer. + */ + fsp_err_t (* stop)(timer_ctrl_t * const p_ctrl); + + /** Reset the counter to the initial value. + * @par Implemented as + * - @ref R_GPT_Reset() + * - @ref R_AGT_Reset() + * + * @param[in] p_ctrl Control block set in @ref timer_api_t::open call for this timer. + */ + fsp_err_t (* reset)(timer_ctrl_t * const p_ctrl); + + /** Enables input capture. + * @par Implemented as + * - @ref R_GPT_Enable() + * - @ref R_AGT_Enable() + * + * @param[in] p_ctrl Control block set in @ref timer_api_t::open call for this timer. + */ + fsp_err_t (* enable)(timer_ctrl_t * const p_ctrl); + + /** Disables input capture. + * @par Implemented as + * - @ref R_GPT_Disable() + * - @ref R_AGT_Disable() + * + * @param[in] p_ctrl Control block set in @ref timer_api_t::open call for this timer. + */ + fsp_err_t (* disable)(timer_ctrl_t * const p_ctrl); + + /** Set the time until the timer expires. See implementation for details of period update timing. + * + * @par Implemented as + * - @ref R_GPT_PeriodSet() + * - @ref R_AGT_PeriodSet() + * + * @note Timer expiration may or may not generate a CPU interrupt based on how the timer is configured in + * @ref timer_api_t::open. + * @param[in] p_ctrl Control block set in @ref timer_api_t::open call for this timer. + * @param[in] p_period Time until timer should expire. + */ + fsp_err_t (* periodSet)(timer_ctrl_t * const p_ctrl, uint32_t const period); + + /** Sets the number of counts for the pin level to be high. If the timer is counting, the updated duty cycle is + * reflected after the next timer expiration. + * + * @par Implemented as + * - @ref R_GPT_DutyCycleSet() + * - @ref R_AGT_DutyCycleSet() + * + * @param[in] p_ctrl Control block set in @ref timer_api_t::open call for this timer. + * @param[in] duty_cycle_counts Time until duty cycle should expire. + * @param[in] pin Which output pin to update. See implementation for details. + */ + fsp_err_t (* dutyCycleSet)(timer_ctrl_t * const p_ctrl, uint32_t const duty_cycle_counts, uint32_t const pin); + + /** Stores timer information in p_info. + * @par Implemented as + * - @ref R_GPT_InfoGet() + * - @ref R_AGT_InfoGet() + * + * @param[in] p_ctrl Control block set in @ref timer_api_t::open call for this timer. + * @param[out] p_info Collection of information for this timer. + */ + fsp_err_t (* infoGet)(timer_ctrl_t * const p_ctrl, timer_info_t * const p_info); + + /** Get the current counter value and timer state and store it in p_status. + * @par Implemented as + * - @ref R_GPT_StatusGet() + * - @ref R_AGT_StatusGet() + * + * @param[in] p_ctrl Control block set in @ref timer_api_t::open call for this timer. + * @param[out] p_status Current status of this timer. + */ + fsp_err_t (* statusGet)(timer_ctrl_t * const p_ctrl, timer_status_t * const p_status); + + /** Specify callback function and optional context pointer and working memory pointer. + * @par Implemented as + * - @ref R_GPT_CallbackSet() + * - @ref R_AGT_CallbackSet() + * + * @param[in] p_ctrl Control block set in @ref timer_api_t::open call for this timer. + * @param[in] p_callback Callback function to register + * @param[in] p_context Pointer to send to callback function + * @param[in] p_working_memory Pointer to volatile memory where callback structure can be allocated. + * Callback arguments allocated here are only valid during the callback. + */ + fsp_err_t (* callbackSet)(timer_ctrl_t * const p_api_ctrl, void (* p_callback)(timer_callback_args_t *), + void const * const p_context, timer_callback_args_t * const p_callback_memory); + + /** Allows driver to be reconfigured and may reduce power consumption. + * @par Implemented as + * - @ref R_GPT_Close() + * - @ref R_AGT_Close() + * + * @param[in] p_ctrl Control block set in @ref timer_api_t::open call for this timer. + */ + fsp_err_t (* close)(timer_ctrl_t * const p_ctrl); +} timer_api_t; + +/** This structure encompasses everything that is needed to use an instance of this interface. */ +typedef struct st_timer_instance +{ + timer_ctrl_t * p_ctrl; ///< Pointer to the control structure for this instance + timer_cfg_t const * p_cfg; ///< Pointer to the configuration structure for this instance + timer_api_t const * p_api; ///< Pointer to the API structure for this instance +} timer_instance_t; + +/*******************************************************************************************************************//** + * @} (end defgroup TIMER_API) + **********************************************************************************************************************/ + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif diff --git a/bsp/renesas/ra6m3-hmi-board/ra/fsp/inc/instances/r_adc.h b/bsp/renesas/ra6m3-hmi-board/ra/fsp/inc/instances/r_adc.h new file mode 100644 index 0000000000..7b56107cee --- /dev/null +++ b/bsp/renesas/ra6m3-hmi-board/ra/fsp/inc/instances/r_adc.h @@ -0,0 +1,359 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics America Inc. and may only be used with products + * of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. Renesas products are + * sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for the selection and use + * of Renesas products and Renesas assumes no liability. No license, express or implied, to any intellectual property + * right is granted by Renesas. This software is protected under all applicable laws, including copyright laws. Renesas + * reserves the right to change or discontinue this software and/or this documentation. THE SOFTWARE AND DOCUMENTATION + * IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND TO THE FULLEST EXTENT + * PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, INCLUDING WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE SOFTWARE OR + * DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. TO THE MAXIMUM + * EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR DOCUMENTATION + * (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, INCLUDING, + * WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY LOST PROFITS, + * OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE POSSIBILITY + * OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ + +#ifndef R_ADC_H +#define R_ADC_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include + +/* Fixed width integer support. */ +#include + +/* bool support */ +#include +#include "bsp_api.h" +#include "r_adc_cfg.h" +#include "r_adc_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*******************************************************************************************************************//** + * @addtogroup ADC + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/* Typical values that can be used to modify the sample states. + * The minimum sample state count value is either 6 or 7 depending on the clock ratios. + * It is fixed to 7 based on the fact that at the lowest ADC conversion clock supported (1 MHz) + * this extra state will lead to at worst a "1 microsecond" increase in conversion time. + * At 60 MHz the extra sample state will add 16.7 ns to the conversion time. + */ +#define ADC_SAMPLE_STATE_COUNT_MIN (7U) +#define ADC_SAMPLE_STATE_COUNT_MAX (255U) + +/* Typical values that can be used for the sample and hold counts for the channels 0-2*/ +/* Minimum sample and hold states */ +#define ADC_SAMPLE_STATE_HOLD_COUNT_MIN (4U) + +/* Default sample and hold states */ +#define ADC_SAMPLE_STATE_HOLD_COUNT_DEFAULT (24U) + +/** For ADC Scan configuration adc_channel_cfg_t::scan_mask, adc_channel_cfg_t::scan_mask_group_b, + * adc_channel_cfg_t::add_mask and adc_channel_cfg_t::sample_hold_mask. + * Use bitwise OR to combine these masks for desired channels and sensors. */ +typedef enum e_adc_mask +{ + ADC_MASK_OFF = (0U), ///< No channels selected + ADC_MASK_CHANNEL_0 = (1U << 0U), ///< Channel 0 mask + ADC_MASK_CHANNEL_1 = (1U << 1U), ///< Channel 1 mask + ADC_MASK_CHANNEL_2 = (1U << 2U), ///< Channel 2 mask + ADC_MASK_CHANNEL_3 = (1U << 3U), ///< Channel 3 mask + ADC_MASK_CHANNEL_4 = (1U << 4U), ///< Channel 4 mask + ADC_MASK_CHANNEL_5 = (1U << 5U), ///< Channel 5 mask + ADC_MASK_CHANNEL_6 = (1U << 6U), ///< Channel 6 mask + ADC_MASK_CHANNEL_7 = (1U << 7U), ///< Channel 7 mask + ADC_MASK_CHANNEL_8 = (1U << 8U), ///< Channel 8 mask + ADC_MASK_CHANNEL_9 = (1U << 9U), ///< Channel 9 mask + ADC_MASK_CHANNEL_10 = (1U << 10U), ///< Channel 10 mask + ADC_MASK_CHANNEL_11 = (1U << 11U), ///< Channel 11 mask + ADC_MASK_CHANNEL_12 = (1U << 12U), ///< Channel 12 mask + ADC_MASK_CHANNEL_13 = (1U << 13U), ///< Channel 13 mask + ADC_MASK_CHANNEL_14 = (1U << 14U), ///< Channel 14 mask + ADC_MASK_CHANNEL_15 = (1U << 15U), ///< Channel 15 mask + ADC_MASK_CHANNEL_16 = (1U << 16U), ///< Channel 16 mask + ADC_MASK_CHANNEL_17 = (1U << 17U), ///< Channel 17 mask + ADC_MASK_CHANNEL_18 = (1U << 18U), ///< Channel 18 mask + ADC_MASK_CHANNEL_19 = (1U << 19U), ///< Channel 19 mask + ADC_MASK_CHANNEL_20 = (1U << 20U), ///< Channel 20 mask + ADC_MASK_CHANNEL_21 = (1U << 21U), ///< Channel 21 mask + ADC_MASK_CHANNEL_22 = (1U << 22U), ///< Channel 22 mask + ADC_MASK_CHANNEL_23 = (1U << 23U), ///< Channel 23 mask + ADC_MASK_CHANNEL_24 = (1U << 24U), ///< Channel 24 mask + ADC_MASK_CHANNEL_25 = (1U << 25U), ///< Channel 25 mask + ADC_MASK_CHANNEL_26 = (1U << 26U), ///< Channel 26 mask + ADC_MASK_CHANNEL_27 = (1U << 27U), ///< Channel 27 mask + ADC_MASK_TEMPERATURE = (1U << 28UL), ///< Temperature sensor channel mask + ADC_MASK_VOLT = (1U << 29UL), ///< Voltage reference channel mask + ADC_MASK_SENSORS = (ADC_MASK_TEMPERATURE | ADC_MASK_VOLT), ///< All sensor channel mask +} adc_mask_t; + +/** ADC data sample addition and averaging options */ +typedef enum e_adc_add +{ + ADC_ADD_OFF = 0, ///< Addition turned off for channels/sensors + ADC_ADD_TWO = 1, ///< Add two samples + ADC_ADD_THREE = 2, ///< Add three samples + ADC_ADD_FOUR = 3, ///< Add four samples + ADC_ADD_SIXTEEN = 5, ///< Add sixteen samples + ADC_ADD_AVERAGE_TWO = 0x81, ///< Average two samples + ADC_ADD_AVERAGE_FOUR = 0x83, ///< Average four samples + ADC_ADD_AVERAGE_EIGHT = 0x84, ///< Average eight samples + ADC_ADD_AVERAGE_SIXTEEN = 0x85, ///< Add sixteen samples +} adc_add_t; + +/** ADC clear after read definitions */ +typedef enum e_adc_clear +{ + ADC_CLEAR_AFTER_READ_OFF = 0, ///< Clear after read off + ADC_CLEAR_AFTER_READ_ON = 1 ///< Clear after read on +} adc_clear_t; + +/* VREF configuration options, not all options are available on all MCUs. If the MCU does not have VREFAMPCNT or + * ADHVREFCNT. */ +typedef enum e_adc_vref_control +{ + /* Available selections on MCUs with VREFAMPCNT. + * Reference Table 32.12 "VREFADC output voltage control list" in the RA2A1 manual R01UH0888EJ0100.*/ + + ADC_VREF_CONTROL_VREFH = 0, ///< VREFAMPCNT reset value. VREFADC Output voltage is Hi-Z + ADC_VREF_CONTROL_1_5V_OUTPUT = 25, ///< BGR turn ON. VREFADC Output voltage is 1.5 V + ADC_VREF_CONTROL_2_0V_OUTPUT = 29, ///< BGR turn ON. VREFADC Output voltage is 2.0 V + ADC_VREF_CONTROL_2_5V_OUTPUT = 31, ///< BGR turn ON. VREFADC Output voltage is 2.5 V + + /* Available selections on MCUs with ADHVREFCNT. + * Reference Section 35.2.31 "A/D High-Potential/Low-Potential Reference Voltage Control Register (ADHVREFCNT)" + * in the RA4M1 manual R01UH0887EJ0100.*/ + + ADC_VREF_CONTROL_AVCC0_AVSS0 = 0x0, ///< High potential is AVCC0, low potential is AVSS0 + ADC_VREF_CONTROL_VREFH0_AVSS0 = 0x1, ///< High potential is VREFH0, low potential is AVSS0 + + /** High potential is internal reference voltage, low potential is AVSS0. When the high potential is set to the + * internal reference voltage, wait 5 us after R_ADC_Open() to start an ADC measurement. */ + ADC_VREF_CONTROL_IVREF_AVSS0 = 0x2, + ADC_VREF_CONTROL_AVCC0_VREFL0 = 0x10, ///< High potential is AVCC0, low potential is VREFL0 + ADC_VREF_CONTROL_VREFH0_VREFL0 = 0x11, ///< High potential is VREFH0, low potential is VREFL0 + + /** High potential is internal reference voltage, low potential is VREFL0. When the high potential is set to the + * internal reference voltage, wait 5 us after R_ADC_Open() to start an ADC measurement. */ + ADC_VREF_CONTROL_IVREF_VREFL0 = 0x12, +} adc_vref_control_t; + +/** ADC sample state registers */ +typedef enum e_adc_sample_state_reg +{ + ADC_SAMPLE_STATE_CHANNEL_0 = 0, ///< Sample state register channel 0 + ADC_SAMPLE_STATE_CHANNEL_1, ///< Sample state register channel 1 + ADC_SAMPLE_STATE_CHANNEL_2, ///< Sample state register channel 2 + ADC_SAMPLE_STATE_CHANNEL_3, ///< Sample state register channel 3 + ADC_SAMPLE_STATE_CHANNEL_4, ///< Sample state register channel 4 + ADC_SAMPLE_STATE_CHANNEL_5, ///< Sample state register channel 5 + ADC_SAMPLE_STATE_CHANNEL_6, ///< Sample state register channel 6 + ADC_SAMPLE_STATE_CHANNEL_7, ///< Sample state register channel 7 + ADC_SAMPLE_STATE_CHANNEL_8, ///< Sample state register channel 8 + ADC_SAMPLE_STATE_CHANNEL_9, ///< Sample state register channel 9 + ADC_SAMPLE_STATE_CHANNEL_10, ///< Sample state register channel 10 + ADC_SAMPLE_STATE_CHANNEL_11, ///< Sample state register channel 11 + ADC_SAMPLE_STATE_CHANNEL_12, ///< Sample state register channel 12 + ADC_SAMPLE_STATE_CHANNEL_13, ///< Sample state register channel 13 + ADC_SAMPLE_STATE_CHANNEL_14, ///< Sample state register channel 14 + ADC_SAMPLE_STATE_CHANNEL_15, ///< Sample state register channel 15 + ADC_SAMPLE_STATE_CHANNEL_16_TO_31 = -3, ///< Sample state register channel 16 to 31 +} adc_sample_state_reg_t; + +/** ADC comparison settings */ +typedef enum e_adc_compare_cfg +{ + ADC_COMPARE_CFG_EVENT_OUTPUT_OR = 0, + ADC_COMPARE_CFG_EVENT_OUTPUT_XOR = 1, + ADC_COMPARE_CFG_EVENT_OUTPUT_AND = 2, + ADC_COMPARE_CFG_A_ENABLE = R_ADC0_ADCMPCR_CMPAE_Msk | R_ADC0_ADCMPCR_CMPAIE_Msk, + ADC_COMPARE_CFG_B_ENABLE = R_ADC0_ADCMPCR_CMPBE_Msk | R_ADC0_ADCMPCR_CMPBIE_Msk, + ADC_COMPARE_CFG_WINDOW_ENABLE = R_ADC0_ADCMPCR_WCMPE_Msk, +} adc_compare_cfg_t; + +/** ADC Window B channel */ +typedef enum e_adc_window_b_channel +{ + ADC_WINDOW_B_CHANNEL_0 = 0, + ADC_WINDOW_B_CHANNEL_1, + ADC_WINDOW_B_CHANNEL_2, + ADC_WINDOW_B_CHANNEL_3, + ADC_WINDOW_B_CHANNEL_4, + ADC_WINDOW_B_CHANNEL_5, + ADC_WINDOW_B_CHANNEL_6, + ADC_WINDOW_B_CHANNEL_7, + ADC_WINDOW_B_CHANNEL_8, + ADC_WINDOW_B_CHANNEL_9, + ADC_WINDOW_B_CHANNEL_10, + ADC_WINDOW_B_CHANNEL_11, + ADC_WINDOW_B_CHANNEL_12, + ADC_WINDOW_B_CHANNEL_13, + ADC_WINDOW_B_CHANNEL_14, + ADC_WINDOW_B_CHANNEL_15, + ADC_WINDOW_B_CHANNEL_16, + ADC_WINDOW_B_CHANNEL_17, + ADC_WINDOW_B_CHANNEL_18, + ADC_WINDOW_B_CHANNEL_19, + ADC_WINDOW_B_CHANNEL_20, + ADC_WINDOW_B_CHANNEL_21, + ADC_WINDOW_B_CHANNEL_22, + ADC_WINDOW_B_CHANNEL_23, + ADC_WINDOW_B_CHANNEL_24, + ADC_WINDOW_B_CHANNEL_25, + ADC_WINDOW_B_CHANNEL_26, + ADC_WINDOW_B_CHANNEL_27, + ADC_WINDOW_B_CHANNEL_TEMPERATURE = 32, + ADC_WINDOW_B_CHANNEL_VOLT = 33, +} adc_window_b_channel_t; + +/** ADC Window B comparison mode */ +typedef enum e_adc_window_b_mode +{ + ADC_WINDOW_B_MODE_LESS_THAN_OR_OUTSIDE = 0, + ADC_WINDOW_B_MODE_GREATER_THAN_OR_INSIDE = R_ADC0_ADCMPBNSR_CMPLB_Msk, +} adc_window_b_mode_t; + +/** ADC action for group A interrupts group B scan. + * This enumeration is used to specify the priority between Group A and B in group mode. */ +typedef enum e_adc_group_a +{ + ADC_GROUP_A_PRIORITY_OFF = 0, ///< Group A ignored and does not interrupt ongoing group B scan + ADC_GROUP_A_GROUP_B_WAIT_FOR_TRIGGER = 1, ///< Group A interrupts Group B(single scan) which restarts at next Group B trigger + ADC_GROUP_A_GROUP_B_RESTART_SCAN = 3, ///< Group A interrupts Group B(single scan) which restarts immediately after Group A scan is complete + ADC_GROUP_A_GROUP_B_CONTINUOUS_SCAN = 0x8001, ///< Group A interrupts Group B(continuous scan) which continues scanning without a new Group B trigger +} adc_group_a_t; + +/** ADC double-trigger mode definitions */ +typedef enum e_adc_double_trigger +{ + ADC_DOUBLE_TRIGGER_DISABLED = 0, ///< Double-triggering disabled + ADC_DOUBLE_TRIGGER_ENABLED = 1, ///< Double-triggering enabled + ADC_DOUBLE_TRIGGER_ENABLED_EXTENDED = 2, ///< Double-triggering enabled on both ADC ELC events +} adc_double_trigger_t; + +/** ADC sample state configuration */ +typedef struct st_adc_sample_state +{ + adc_sample_state_reg_t reg_id; ///< Sample state register ID + uint8_t num_states; ///< Number of sampling states for conversion. Ch16-20/21 use the same value. +} adc_sample_state_t; + +/** ADC Window Compare configuration */ +typedef struct st_adc_window_cfg +{ + uint32_t compare_mask; ///< Channel mask to compare with Window A + uint32_t compare_mode_mask; ///< Per-channel condition mask for Window A + adc_compare_cfg_t compare_cfg; ///< Window Compare configuration + uint16_t compare_ref_low; ///< Window A lower reference value + uint16_t compare_ref_high; ///< Window A upper reference value + uint16_t compare_b_ref_low; ///< Window B lower reference value + uint16_t compare_b_ref_high; ///< Window A upper reference value + adc_window_b_channel_t compare_b_channel; ///< Window B channel + adc_window_b_mode_t compare_b_mode; ///< Window B condition setting +} adc_window_cfg_t; + +/** Extended configuration structure for ADC. */ +typedef struct st_adc_extended_cfg +{ + adc_add_t add_average_count; ///< Add or average samples + adc_clear_t clearing; ///< Clear after read + adc_trigger_t trigger_group_b; ///< Group B trigger source; valid only for group mode + adc_double_trigger_t double_trigger_mode; ///< Double-trigger mode setting + adc_vref_control_t adc_vref_control; ///< VREFADC output voltage control + uint8_t enable_adbuf; ///< Enable ADC Ring Buffer, Valid only to use along with DMAC transfer + IRQn_Type window_a_irq; ///< IRQ number for Window Compare A interrupts + IRQn_Type window_b_irq; ///< IRQ number for Window Compare B interrupts + uint8_t window_a_ipl; ///< Priority for Window Compare A interrupts + uint8_t window_b_ipl; ///< Priority for Window Compare B interrupts +} adc_extended_cfg_t; + +/** ADC channel(s) configuration */ +typedef struct st_adc_channel_cfg +{ + uint32_t scan_mask; ///< Channels/bits: bit 0 is ch0; bit 15 is ch15. + uint32_t scan_mask_group_b; ///< Valid for group modes. + uint32_t add_mask; ///< Valid if add enabled in Open(). + adc_window_cfg_t * p_window_cfg; ///< Pointer to Window Compare configuration + adc_group_a_t priority_group_a; ///< Valid for group modes. + uint8_t sample_hold_mask; ///< Channels/bits 0-2. + uint8_t sample_hold_states; ///< Number of states to be used for sample and hold. Affects channels 0-2. +} adc_channel_cfg_t; + +/* Sample and hold Channel mask. Sample and hold is only available for channel 0,1,2*/ +#define ADC_SAMPLE_HOLD_CHANNELS (0x07U) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** ADC instance control block. DO NOT INITIALIZE. Initialized in @ref adc_api_t::open(). */ +typedef struct +{ + R_ADC0_Type * p_reg; // Base register for this unit + adc_cfg_t const * p_cfg; + uint32_t opened; // Boolean to verify that the Unit has been initialized + uint32_t initialized; // Initialized status of ADC + uint32_t scan_mask; // Scan mask used for Normal scan + uint16_t scan_start_adcsr; + + void (* p_callback)(adc_callback_args_t *); // Pointer to callback that is called when an adc_event_t occurs. + adc_callback_args_t * p_callback_memory; // Pointer to non-secure memory that can be used to pass arguments to a callback in non-secure memory. + + /* Pointer to context to be passed into callback function */ + void const * p_context; +} adc_instance_ctrl_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Interface Structure for user access */ +extern const adc_api_t g_adc_on_adc; + +/** @endcond */ + +/*********************************************************************************************************************** + * Public APIs + **********************************************************************************************************************/ +fsp_err_t R_ADC_Open(adc_ctrl_t * p_ctrl, adc_cfg_t const * const p_cfg); +fsp_err_t R_ADC_ScanCfg(adc_ctrl_t * p_ctrl, void const * const p_channel_cfg); +fsp_err_t R_ADC_InfoGet(adc_ctrl_t * p_ctrl, adc_info_t * p_adc_info); +fsp_err_t R_ADC_ScanStart(adc_ctrl_t * p_ctrl); +fsp_err_t R_ADC_ScanGroupStart(adc_ctrl_t * p_ctrl, adc_group_mask_t group_id); +fsp_err_t R_ADC_ScanStop(adc_ctrl_t * p_ctrl); +fsp_err_t R_ADC_StatusGet(adc_ctrl_t * p_ctrl, adc_status_t * p_status); +fsp_err_t R_ADC_Read(adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint16_t * const p_data); +fsp_err_t R_ADC_Read32(adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint32_t * const p_data); +fsp_err_t R_ADC_SampleStateCountSet(adc_ctrl_t * p_ctrl, adc_sample_state_t * p_sample); +fsp_err_t R_ADC_Close(adc_ctrl_t * p_ctrl); +fsp_err_t R_ADC_OffsetSet(adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, int32_t offset); +fsp_err_t R_ADC_Calibrate(adc_ctrl_t * const p_ctrl, void const * p_extend); +fsp_err_t R_ADC_CallbackSet(adc_ctrl_t * const p_api_ctrl, + void ( * p_callback)(adc_callback_args_t *), + void const * const p_context, + adc_callback_args_t * const p_callback_memory); + +/*******************************************************************************************************************//** + * @} (end defgroup ADC) + **********************************************************************************************************************/ + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif diff --git a/bsp/renesas/ra6m3-hmi-board/ra/fsp/inc/instances/r_gpt.h b/bsp/renesas/ra6m3-hmi-board/ra/fsp/inc/instances/r_gpt.h new file mode 100644 index 0000000000..46816c8a72 --- /dev/null +++ b/bsp/renesas/ra6m3-hmi-board/ra/fsp/inc/instances/r_gpt.h @@ -0,0 +1,438 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics America Inc. and may only be used with products + * of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. Renesas products are + * sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for the selection and use + * of Renesas products and Renesas assumes no liability. No license, express or implied, to any intellectual property + * right is granted by Renesas. This software is protected under all applicable laws, including copyright laws. Renesas + * reserves the right to change or discontinue this software and/or this documentation. THE SOFTWARE AND DOCUMENTATION + * IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND TO THE FULLEST EXTENT + * PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, INCLUDING WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE SOFTWARE OR + * DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. TO THE MAXIMUM + * EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR DOCUMENTATION + * (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, INCLUDING, + * WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY LOST PROFITS, + * OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE POSSIBILITY + * OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ + +#ifndef R_GPT_H +#define R_GPT_H + +/*******************************************************************************************************************//** + * @addtogroup GPT + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "bsp_api.h" +#include "r_timer_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** Input/Output pins, used to select which duty cycle to update in R_GPT_DutyCycleSet(). */ +typedef enum e_gpt_io_pin +{ + GPT_IO_PIN_GTIOCA = 0, ///< GTIOCA + GPT_IO_PIN_GTIOCB = 1, ///< GTIOCB + GPT_IO_PIN_GTIOCA_AND_GTIOCB = 2, ///< GTIOCA and GTIOCB + GPT_IO_PIN_TROUGH = 4, ///< Used in @ref R_GPT_DutyCycleSet when Triangle-wave PWM Mode 3 is selected. + GPT_IO_PIN_CREST = 8, ///< Used in @ref R_GPT_DutyCycleSet when Triangle-wave PWM Mode 3 is selected. +} gpt_io_pin_t; + +/** Level of GPT pin */ +typedef enum e_gpt_pin_level +{ + GPT_PIN_LEVEL_LOW = 0, ///< Pin level low + GPT_PIN_LEVEL_HIGH = 1, ///< Pin level high +} gpt_pin_level_t; + +/** Sources can be used to start the timer, stop the timer, count up, or count down. These enumerations represent + * a bitmask. Multiple sources can be ORed together. */ +typedef enum e_gpt_source +{ + /** No active event sources. */ + GPT_SOURCE_NONE = 0U, + + /** Action performed on GTETRGA rising edge. **/ + GPT_SOURCE_GTETRGA_RISING = (1U << 0), + + /** Action performed on GTETRGA falling edge. **/ + GPT_SOURCE_GTETRGA_FALLING = (1U << 1), + + /** Action performed on GTETRGB rising edge. **/ + GPT_SOURCE_GTETRGB_RISING = (1U << 2), + + /** Action performed on GTETRGB falling edge. **/ + GPT_SOURCE_GTETRGB_FALLING = (1U << 3), + + /** Action performed on GTETRGC rising edge. **/ + GPT_SOURCE_GTETRGC_RISING = (1U << 4), + + /** Action performed on GTETRGC falling edge. **/ + GPT_SOURCE_GTETRGC_FALLING = (1U << 5), + + /** Action performed on GTETRGB rising edge. **/ + GPT_SOURCE_GTETRGD_RISING = (1U << 6), + + /** Action performed on GTETRGB falling edge. **/ + GPT_SOURCE_GTETRGD_FALLING = (1U << 7), + + /** Action performed when GTIOCA input rises while GTIOCB is low. **/ + GPT_SOURCE_GTIOCA_RISING_WHILE_GTIOCB_LOW = (1U << 8), + + /** Action performed when GTIOCA input rises while GTIOCB is high. **/ + GPT_SOURCE_GTIOCA_RISING_WHILE_GTIOCB_HIGH = (1U << 9), + + /** Action performed when GTIOCA input falls while GTIOCB is low. **/ + GPT_SOURCE_GTIOCA_FALLING_WHILE_GTIOCB_LOW = (1U << 10), + + /** Action performed when GTIOCA input falls while GTIOCB is high. **/ + GPT_SOURCE_GTIOCA_FALLING_WHILE_GTIOCB_HIGH = (1U << 11), + + /** Action performed when GTIOCB input rises while GTIOCA is low. **/ + GPT_SOURCE_GTIOCB_RISING_WHILE_GTIOCA_LOW = (1U << 12), + + /** Action performed when GTIOCB input rises while GTIOCA is high. **/ + GPT_SOURCE_GTIOCB_RISING_WHILE_GTIOCA_HIGH = (1U << 13), + + /** Action performed when GTIOCB input falls while GTIOCA is low. **/ + GPT_SOURCE_GTIOCB_FALLING_WHILE_GTIOCA_LOW = (1U << 14), + + /** Action performed when GTIOCB input falls while GTIOCA is high. **/ + GPT_SOURCE_GTIOCB_FALLING_WHILE_GTIOCA_HIGH = (1U << 15), + + /** Action performed on ELC GPTA event. **/ + GPT_SOURCE_GPT_A = (1U << 16), + + /** Action performed on ELC GPTB event. **/ + GPT_SOURCE_GPT_B = (1U << 17), + + /** Action performed on ELC GPTC event. **/ + GPT_SOURCE_GPT_C = (1U << 18), + + /** Action performed on ELC GPTD event. **/ + GPT_SOURCE_GPT_D = (1U << 19), + + /** Action performed on ELC GPTE event. **/ + GPT_SOURCE_GPT_E = (1U << 20), + + /** Action performed on ELC GPTF event. **/ + GPT_SOURCE_GPT_F = (1U << 21), + + /** Action performed on ELC GPTG event. **/ + GPT_SOURCE_GPT_G = (1U << 22), + + /** Action performed on ELC GPTH event. **/ + GPT_SOURCE_GPT_H = (1U << 23), +} gpt_source_t; + +/** Configurations for output pins. */ +typedef struct s_gpt_output_pin +{ + bool output_enabled; ///< Set to true to enable output, false to disable output + gpt_pin_level_t stop_level; ///< Select a stop level from ::gpt_pin_level_t +} gpt_output_pin_t; + +/** Custom GTIOR settings used for configuring GTIOCxA and GTIOCxB pins. */ +typedef struct s_gpt_gtior_setting +{ + union + { + uint32_t gtior; + struct + { + /* Settings for GTIOCxA pin. */ + uint32_t gtioa : 5; ///< GTIOCA Pin Function Select. + uint32_t : 1; // Reserved + uint32_t oadflt : 1; ///< GTIOCA Pin Output Value Setting at the Count Stop. + uint32_t oahld : 1; ///< GTIOCA Pin Output Setting at the Start/Stop Count. + uint32_t oae : 1; ///< GTIOCA Pin Output Enable + uint32_t oadf : 2; ///< GTIOCA Pin Disable Value Setting. + uint32_t : 2; /// Reserved + uint32_t nfaen : 1; /// Noise Filter A Enable. + uint32_t nfcsa : 2; /// Noise Filter A Sampling Clock Select. + + /* Settings for GTIOCxB pin. */ + uint32_t gtiob : 5; ///< GTIOCB Pin Function Select. + uint32_t : 1; // Reserved + uint32_t obdflt : 1; ///< GTIOCB Pin Output Value Setting at the Count Stop. + uint32_t obhld : 1; ///< GTIOCB Pin Output Setting at the Start/Stop Count. + uint32_t obe : 1; ///< GTIOCB Pin Output Enable + uint32_t obdf : 2; ///< GTIOCB Pin Disable Value Setting. + uint32_t : 2; /// Reserved + uint32_t nfben : 1; /// Noise Filter B Enable. + uint32_t nfcsb : 2; /// Noise Filter B Sampling Clock Select. + } gtior_b; + }; +} gpt_gtior_setting_t; + +/** Input capture signal noise filter (debounce) setting. Only available for input signals GTIOCxA and GTIOCxB. + * The noise filter samples the external signal at intervals of the PCLK divided by one of the values. + * When 3 consecutive samples are at the same level (high or low), then that level is passed on as + * the observed state of the signal. See "Noise Filter Function" in the hardware manual, GPT section. + */ +typedef enum e_gpt_capture_filter +{ + GPT_CAPTURE_FILTER_NONE = 0U, ///< None - no filtering + GPT_CAPTURE_FILTER_PCLKD_DIV_1 = 1U, ///< PCLK/1 - fast sampling + GPT_CAPTURE_FILTER_PCLKD_DIV_4 = 3U, ///< PCLK/4 + GPT_CAPTURE_FILTER_PCLKD_DIV_16 = 5U, ///< PCLK/16 + GPT_CAPTURE_FILTER_PCLKD_DIV_64 = 7U, ///< PCLK/64 - slow sampling +} gpt_capture_filter_t; + +/** Trigger options to start A/D conversion. */ +typedef enum e_gpt_adc_trigger +{ + GPT_ADC_TRIGGER_NONE = 0U, ///< None - no output disable request + GPT_ADC_TRIGGER_UP_COUNT_START_ADC_A = 1U << 0, ///< Request A/D conversion from ADC unit 0 at up counting compare match of @ref gpt_extended_pwm_cfg_t::adc_a_compare_match + GPT_ADC_TRIGGER_DOWN_COUNT_START_ADC_A = 1U << 1, ///< Request A/D conversion from ADC unit 0 at down counting compare match of @ref gpt_extended_pwm_cfg_t::adc_a_compare_match + GPT_ADC_TRIGGER_UP_COUNT_START_ADC_B = 1U << 2, ///< Request A/D conversion from ADC unit 1 at up counting compare match of @ref gpt_extended_pwm_cfg_t::adc_b_compare_match + GPT_ADC_TRIGGER_DOWN_COUNT_START_ADC_B = 1U << 3, ///< Request A/D conversion from ADC unit 1 at down counting compare match of @ref gpt_extended_pwm_cfg_t::adc_b_compare_match +} gpt_adc_trigger_t; + +/** POEG channel to link to this channel. */ +typedef enum e_gpt_poeg_link +{ + GPT_POEG_LINK_POEG0 = 0U, ///< Link this GPT channel to POEG channel 0 (GTETRGA) + GPT_POEG_LINK_POEG1 = 1U, ///< Link this GPT channel to POEG channel 1 (GTETRGB) + GPT_POEG_LINK_POEG2 = 2U, ///< Link this GPT channel to POEG channel 2 (GTETRGC) + GPT_POEG_LINK_POEG3 = 3U, ///< Link this GPT channel to POEG channel 3 (GTETRGD) +} gpt_poeg_link_t; + +/** Select trigger to send output disable request to POEG. */ +typedef enum e_gpt_output_disable +{ + GPT_OUTPUT_DISABLE_NONE = 0U, ///< None - no output disable request + GPT_OUTPUT_DISABLE_DEAD_TIME_ERROR = 1U << 0, ///< Request output disable if a dead time error occurs + GPT_OUTPUT_DISABLE_GTIOCA_GTIOCB_HIGH = 1U << 1, ///< Request output disable if GTIOCA and GTIOCB are high at the same time + GPT_OUTPUT_DISABLE_GTIOCA_GTIOCB_LOW = 1U << 2, ///< Request output disable if GTIOCA and GTIOCB are low at the same time +} gpt_output_disable_t; + +/** Disable level options for GTIOC pins. */ +typedef enum e_gpt_gtioc_disable +{ + GPT_GTIOC_DISABLE_PROHIBITED = 0U, ///< Do not allow output disable + GPT_GTIOC_DISABLE_SET_HI_Z = 1U, ///< Set GTIOC to high impedance when output is disabled + GPT_GTIOC_DISABLE_LEVEL_LOW = 2U, ///< Set GTIOC level low when output is disabled + GPT_GTIOC_DISABLE_LEVEL_HIGH = 3U, ///< Set GTIOC level high when output is disabled +} gpt_gtioc_disable_t; + +/** Trigger options to start A/D conversion. */ +typedef enum e_gpt_adc_compare_match +{ + GPT_ADC_COMPARE_MATCH_ADC_A = 0U, ///< Set A/D conversion start request value for GPT A/D converter start request A + GPT_ADC_COMPARE_MATCH_ADC_B = 3U, ///< Set A/D conversion start request value for GPT A/D converter start request B +} gpt_adc_compare_match_t; + +/** Interrupt skipping modes */ +typedef enum e_gpt_interrupt_skip_source +{ + GPT_INTERRUPT_SKIP_SOURCE_NONE = 0U, ///< Do not skip interrupts + GPT_INTERRUPT_SKIP_SOURCE_OVERFLOW_UNDERFLOW = 1U, ///< Count and skip overflow and underflow interrupts + + /** Count crest interrupts for interrupt skipping. Skip the number of crest and trough interrupts configured in + * @ref gpt_interrupt_skip_count_t. When the interrupt does fire, the trough interrupt fires before the crest + * interrupt. */ + GPT_INTERRUPT_SKIP_SOURCE_CREST = 1U, + + /** Count trough interrupts for interrupt skipping. Skip the number of crest and trough interrupts configured in + * @ref gpt_interrupt_skip_count_t. When the interrupt does fire, the crest interrupt fires before the trough + * interrupt. */ + GPT_INTERRUPT_SKIP_SOURCE_TROUGH = 2U, +} gpt_interrupt_skip_source_t; + +/** Number of interrupts to skip between events */ +typedef enum e_gpt_interrupt_skip_count +{ + GPT_INTERRUPT_SKIP_COUNT_0 = 0U, ///< Do not skip interrupts + GPT_INTERRUPT_SKIP_COUNT_1, ///< Skip one interrupt + GPT_INTERRUPT_SKIP_COUNT_2, ///< Skip two interrupts + GPT_INTERRUPT_SKIP_COUNT_3, ///< Skip three interrupts + GPT_INTERRUPT_SKIP_COUNT_4, ///< Skip four interrupts + GPT_INTERRUPT_SKIP_COUNT_5, ///< Skip five interrupts + GPT_INTERRUPT_SKIP_COUNT_6, ///< Skip six interrupts + GPT_INTERRUPT_SKIP_COUNT_7, ///< Skip seven interrupts +} gpt_interrupt_skip_count_t; + +/** ADC events to skip during interrupt skipping */ +typedef enum e_gpt_interrupt_skip_adc +{ + GPT_INTERRUPT_SKIP_ADC_NONE = 0U, ///< Do not skip ADC events + GPT_INTERRUPT_SKIP_ADC_A = 1U, ///< Skip ADC A events + GPT_INTERRUPT_SKIP_ADC_B = 4U, ///< Skip ADC B events + GPT_INTERRUPT_SKIP_ADC_A_AND_B = 5U, ///< Skip ADC A and B events +} gpt_interrupt_skip_adc_t; + +/** Delay setting for the PWM Delay Generation Circuit (PDG). */ +typedef enum e_gpt_pwm_output_delay_setting +{ + GPT_PWM_OUTPUT_DELAY_SETTING_0_32, ///< Delay is not applied. + GPT_PWM_OUTPUT_DELAY_SETTING_1_32, ///< Delay of 1 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_2_32, ///< Delay of 2 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_3_32, ///< Delay of 3 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_4_32, ///< Delay of 4 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_5_32, ///< Delay of 5 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_6_32, ///< Delay of 6 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_7_32, ///< Delay of 7 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_8_32, ///< Delay of 8 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_9_32, ///< Delay of 9 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_10_32, ///< Delay of 10 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_11_32, ///< Delay of 11 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_12_32, ///< Delay of 12 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_13_32, ///< Delay of 13 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_14_32, ///< Delay of 14 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_15_32, ///< Delay of 15 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_16_32, ///< Delay of 16 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_17_32, ///< Delay of 17 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_18_32, ///< Delay of 18 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_19_32, ///< Delay of 19 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_20_32, ///< Delay of 20 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_21_32, ///< Delay of 21 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_22_32, ///< Delay of 22 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_23_32, ///< Delay of 23 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_24_32, ///< Delay of 24 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_25_32, ///< Delay of 25 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_26_32, ///< Delay of 26 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_27_32, ///< Delay of 27 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_28_32, ///< Delay of 28 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_29_32, ///< Delay of 29 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_30_32, ///< Delay of 30 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_31_32, ///< Delay of 31 / 32 GTCLK period applied. + GPT_PWM_OUTPUT_DELAY_SETTING_BYPASS, ///< Bypass the PWM Output Delay Circuit. +} gpt_pwm_output_delay_setting_t; + +/** Select which PWM Output Delay setting to apply. */ +typedef enum e_gpt_pwm_output_delay_edge +{ + GPT_PWM_OUTPUT_DELAY_EDGE_RISING, ///< Configure the PWM Output Delay setting for rising edge. + GPT_PWM_OUTPUT_DELAY_EDGE_FALLING, ///< Configure the PWM Output Delay setting for falling edge. +} gpt_pwm_output_delay_edge_t; + +/** Channel control block. DO NOT INITIALIZE. Initialization occurs when @ref timer_api_t::open is called. */ +typedef struct st_gpt_instance_ctrl +{ + uint32_t open; // Whether or not channel is open + const timer_cfg_t * p_cfg; // Pointer to initial configurations + R_GPT0_Type * p_reg; // Base register for this channel + uint32_t channel_mask; // Channel bitmask + timer_variant_t variant; // Timer variant + + void (* p_callback)(timer_callback_args_t *); // Pointer to callback + timer_callback_args_t * p_callback_memory; // Pointer to optional callback argument memory + void const * p_context; // Pointer to context to be passed into callback function +} gpt_instance_ctrl_t; + +/** GPT extension for advanced PWM features. */ +typedef struct st_gpt_extended_pwm_cfg +{ + uint8_t trough_ipl; ///< Trough interrupt priority + IRQn_Type trough_irq; ///< Trough interrupt + gpt_poeg_link_t poeg_link; ///< Select which POEG channel controls output disable for this GPT channel + gpt_output_disable_t output_disable; ///< Select which trigger sources request output disable from POEG + gpt_adc_trigger_t adc_trigger; ///< Select trigger sources to start A/D conversion + uint32_t dead_time_count_up; ///< Set a dead time value for counting up + uint32_t dead_time_count_down; ///< Set a dead time value for counting down (available on GPT32E and GPT32EH only) + uint32_t adc_a_compare_match; ///< Select the compare match value used to trigger an A/D conversion start request using ELC_EVENT_GPT_AD_TRIG_A + uint32_t adc_b_compare_match; ///< Select the compare match value used to trigger an A/D conversion start request using ELC_EVENT_GPT_AD_TRIG_B + gpt_interrupt_skip_source_t interrupt_skip_source; ///< Interrupt source to count for interrupt skipping + gpt_interrupt_skip_count_t interrupt_skip_count; ///< Number of interrupts to skip between events + gpt_interrupt_skip_adc_t interrupt_skip_adc; ///< ADC events to skip when interrupt skipping is enabled + gpt_gtioc_disable_t gtioca_disable_setting; ///< DEPRECATED - Select how to configure GTIOCA when output is disabled + gpt_gtioc_disable_t gtiocb_disable_setting; ///< DEPRECATED - Select how to configure GTIOCB when output is disabled +} gpt_extended_pwm_cfg_t; + +/** GPT extension configures the output pins for GPT. */ +typedef struct st_gpt_extended_cfg +{ + gpt_output_pin_t gtioca; ///< DEPRECATED - Configuration for GPT I/O pin A + gpt_output_pin_t gtiocb; ///< DEPRECATED - Configuration for GPT I/O pin B + gpt_source_t start_source; ///< Event sources that trigger the timer to start + gpt_source_t stop_source; ///< Event sources that trigger the timer to stop + gpt_source_t clear_source; ///< Event sources that trigger the timer to clear + gpt_source_t capture_a_source; ///< Event sources that trigger capture of GTIOCA + gpt_source_t capture_b_source; ///< Event sources that trigger capture of GTIOCB + + /** Event sources that trigger a single up count. If GPT_SOURCE_NONE is selected for both count_up_source + * and count_down_source, then the timer count source is PCLK. */ + gpt_source_t count_up_source; + + /** Event sources that trigger a single down count. If GPT_SOURCE_NONE is selected for both count_up_source + * and count_down_source, then the timer count source is PCLK. */ + gpt_source_t count_down_source; + + /* Debounce filter for GTIOCxA input signal pin (DEPRECATED). */ + gpt_capture_filter_t capture_filter_gtioca; + + /* Debounce filter for GTIOCxB input signal pin (DEPRECATED). */ + gpt_capture_filter_t capture_filter_gtiocb; + + uint8_t capture_a_ipl; ///< Capture A interrupt priority + uint8_t capture_b_ipl; ///< Capture B interrupt priority + IRQn_Type capture_a_irq; ///< Capture A interrupt + IRQn_Type capture_b_irq; ///< Capture B interrupt + gpt_extended_pwm_cfg_t const * p_pwm_cfg; ///< Advanced PWM features, optional + gpt_gtior_setting_t gtior_setting; ///< Custom GTIOR settings used for configuring GTIOCxA and GTIOCxB pins. +} gpt_extended_cfg_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Filled in Interface API structure for this Instance. */ +extern const timer_api_t g_timer_on_gpt; + +/** @endcond */ + +/*********************************************************************************************************************** + * Public APIs + **********************************************************************************************************************/ +fsp_err_t R_GPT_Open(timer_ctrl_t * const p_ctrl, timer_cfg_t const * const p_cfg); +fsp_err_t R_GPT_Stop(timer_ctrl_t * const p_ctrl); +fsp_err_t R_GPT_Start(timer_ctrl_t * const p_ctrl); +fsp_err_t R_GPT_Reset(timer_ctrl_t * const p_ctrl); +fsp_err_t R_GPT_Enable(timer_ctrl_t * const p_ctrl); +fsp_err_t R_GPT_Disable(timer_ctrl_t * const p_ctrl); +fsp_err_t R_GPT_PeriodSet(timer_ctrl_t * const p_ctrl, uint32_t const period_counts); +fsp_err_t R_GPT_DutyCycleSet(timer_ctrl_t * const p_ctrl, uint32_t const duty_cycle_counts, uint32_t const pin); +fsp_err_t R_GPT_InfoGet(timer_ctrl_t * const p_ctrl, timer_info_t * const p_info); +fsp_err_t R_GPT_StatusGet(timer_ctrl_t * const p_ctrl, timer_status_t * const p_status); +fsp_err_t R_GPT_CounterSet(timer_ctrl_t * const p_ctrl, uint32_t counter); +fsp_err_t R_GPT_OutputEnable(timer_ctrl_t * const p_ctrl, gpt_io_pin_t pin); +fsp_err_t R_GPT_OutputDisable(timer_ctrl_t * const p_ctrl, gpt_io_pin_t pin); +fsp_err_t R_GPT_AdcTriggerSet(timer_ctrl_t * const p_ctrl, + gpt_adc_compare_match_t which_compare_match, + uint32_t compare_match_value); +fsp_err_t R_GPT_PwmOutputDelaySet(timer_ctrl_t * const p_ctrl, + gpt_pwm_output_delay_edge_t edge, + gpt_pwm_output_delay_setting_t delay_setting, + uint32_t const pin); +fsp_err_t R_GPT_CallbackSet(timer_ctrl_t * const p_api_ctrl, + void ( * p_callback)(timer_callback_args_t *), + void const * const p_context, + timer_callback_args_t * const p_callback_memory); +fsp_err_t R_GPT_Close(timer_ctrl_t * const p_ctrl); +fsp_err_t R_GPT_PwmOutputDelayInitialize(); + +/*******************************************************************************************************************//** + * @} (end defgroup GPT) + **********************************************************************************************************************/ + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif diff --git a/bsp/renesas/ra6m3-hmi-board/ra/fsp/src/r_adc/r_adc.c b/bsp/renesas/ra6m3-hmi-board/ra/fsp/src/r_adc/r_adc.c new file mode 100644 index 0000000000..f4ad098fc8 --- /dev/null +++ b/bsp/renesas/ra6m3-hmi-board/ra/fsp/src/r_adc/r_adc.c @@ -0,0 +1,1802 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics America Inc. and may only be used with products + * of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. Renesas products are + * sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for the selection and use + * of Renesas products and Renesas assumes no liability. No license, express or implied, to any intellectual property + * right is granted by Renesas. This software is protected under all applicable laws, including copyright laws. Renesas + * reserves the right to change or discontinue this software and/or this documentation. THE SOFTWARE AND DOCUMENTATION + * IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND TO THE FULLEST EXTENT + * PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, INCLUDING WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE SOFTWARE OR + * DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. TO THE MAXIMUM + * EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR DOCUMENTATION + * (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, INCLUDING, + * WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY LOST PROFITS, + * OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE POSSIBILITY + * OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Includes , "Project Includes" + **********************************************************************************************************************/ + +#include "bsp_api.h" + +/* Configuration for this package. */ +#include "r_adc_cfg.h" + +/* Private header file for this package. */ +#include "r_adc.h" + +/********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +#define ADC_PRV_USEC_PER_SEC (1000000U) +#define ADC_PRV_MIN_ADCLK_HZ (1000000U) +#define ADC_MAX_CALIBRATION_CLOCKS_MILLISECS (780U) + +#define ADC_PRV_HZ_PER_KHZ (1000U) + +#define ADC_SHIFT_LEFT_ALIGNED_32_BIT (16U) + +#define ADC_OPEN (0x52414443U) + +#define ADC_ADADC_AVEE_BIT (0x80U) + +/* Sample and hold bypass applies to these channels. */ +#define ADC_MASK_SAMPLE_HOLD_BYPASS_CHANNELS (0x7U) + +/* Sample and hold bypass starts at bit 8. */ +#define ADC_MASK_SAMPLE_HOLD_BYPASS_SHIFT (8U) + +/* Value for ADPGADCR0 to disable PGA */ +#define ADC_ADPGADCR0_DISABLE_PGA (0x0000) + +/* Value for ADPGACR to disable PGA */ +#define ADC_ADPGACR_DISABLE_PGA (0x9999) + +/* Position of ADCALEXE to start calibration-CALEXE bit */ +#define ADC_ADCALEXE_SET_CALEXE (0x80U) + +/* Position of ADCALEXE calibration-CALMON bit */ +#define ADC_ADCALEXE_CALIBRATION_STATUS (0x40U) + +/* Value of ADICR with interrupt at end of calibration */ +#define ADC_ADICR_CALIBRATION_INTERRUPT_ENABLED (0x03U) + +/* Value of ADICR with no interrupt at end of calibration */ +#define ADC_ADICR_CALIBRATION_INTERRUPT_DISABLED (0x00U) + +/* Stabilization time when BGR is enabled */ +#define ADC_BGR_STABILIZATION_DELAY_US (150U) + +/* Bit set in adc_vref_control if the internal voltage reference is used for VREFH. */ +#define ADC_PRV_ADHVREFCNT_VREF_INTERNAL_BIT_1 (1U << 1) + +#define ADC_PRV_ADCSR_ADST_TRGE_MASK (R_ADC0_ADCSR_ADST_Msk | R_ADC0_ADCSR_TRGE_Msk) +#define ADC_PRV_ADCSR_CLEAR_ADST_TRGE (~ADC_PRV_ADCSR_ADST_TRGE_MASK) + +#define ADC_PRV_TSCR_TSN_ENABLE (R_TSN_CTRL_TSCR_TSEN_Msk | R_TSN_CTRL_TSCR_TSOE_Msk) + +#define ADC_PRV_ADBUF_ENABLED (1U) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** Defines the registers settings for the ADC synchronous ELC trigger. */ +typedef enum e_adc_elc_trigger +{ + ADC_ELC_TRIGGER_EXTERNAL = (0x00U), + ADC_ELC_TRIGGER = (0x09U), + ADC_ELC_TRIGGER_GROUP_B = (0x0AU), + ADC_ELC_TRIGGER_BOTH = (0x0BU), + ADC_ELC_TRIGGER_DISABLED = (0x3FU) +} adc_elc_trigger_t; + +#if defined(__ARMCC_VERSION) || defined(__ICCARM__) +typedef void (BSP_CMSE_NONSECURE_CALL * adc_prv_ns_callback)(adc_callback_args_t * p_args); +#elif defined(__GNUC__) +typedef BSP_CMSE_NONSECURE_CALL void (*volatile adc_prv_ns_callback)(adc_callback_args_t * p_args); +#endif + +/*********************************************************************************************************************** + * Private global variables and functions + **********************************************************************************************************************/ +#if ADC_CFG_PARAM_CHECKING_ENABLE +static fsp_err_t r_adc_open_cfg_check(adc_cfg_t const * const p_cfg); +static fsp_err_t r_adc_open_cfg_resolution_check(adc_cfg_t const * const p_cfg); +static fsp_err_t r_adc_sample_state_cfg_check(adc_instance_ctrl_t * p_instance_ctrl, adc_sample_state_t * p_sample); + +static fsp_err_t r_adc_scan_cfg_check_sample_hold(adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg); + +static fsp_err_t r_adc_scan_cfg_check_sensors(adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg); + +#endif + +static void r_adc_open_sub(adc_instance_ctrl_t * const p_instance_ctrl, adc_cfg_t const * const p_cfg); + +static void r_adc_sensor_cfg(adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg); + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +static fsp_err_t r_adc_scan_cfg_check(adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg); + +#endif + +static void r_adc_scan_cfg(adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg); +static void r_adc_sensor_sample_state_calculation(uint32_t * const p_sample_states); +void adc_scan_end_b_isr(void); +void adc_scan_end_isr(void); +void adc_window_compare_isr(void); +static void r_adc_irq_enable(IRQn_Type irq, uint8_t ipl, void * p_context); +static void r_adc_irq_disable(IRQn_Type irq); +static int32_t r_adc_lowest_channel_get(uint32_t adc_mask); +static void r_adc_scan_end_common_isr(adc_event_t event); + +/** Look-up table for ADSTRGR values */ +static const uint32_t adc_elc_trigger_lut[] = +{ + [ADC_DOUBLE_TRIGGER_DISABLED] = (ADC_ELC_TRIGGER << R_ADC0_ADSTRGR_TRSA_Pos) + ADC_ELC_TRIGGER_GROUP_B, + [ADC_DOUBLE_TRIGGER_ENABLED] = (ADC_ELC_TRIGGER << R_ADC0_ADSTRGR_TRSA_Pos) + ADC_ELC_TRIGGER_GROUP_B, + [ADC_DOUBLE_TRIGGER_ENABLED_EXTENDED] = (ADC_ELC_TRIGGER_BOTH << R_ADC0_ADSTRGR_TRSA_Pos) + + ADC_ELC_TRIGGER_DISABLED, +}; + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/** Mask of valid channels on this MCU. */ +static const uint32_t g_adc_valid_channels[] = +{ + BSP_FEATURE_ADC_UNIT_0_CHANNELS, + #if BSP_FEATURE_ADC_UNIT_1_CHANNELS + BSP_FEATURE_ADC_UNIT_1_CHANNELS + #endif +}; +#endif + +/*********************************************************************************************************************** + * Global Variables + **********************************************************************************************************************/ + +/** ADC Implementation of ADC. */ +const adc_api_t g_adc_on_adc = +{ + .open = R_ADC_Open, + .scanCfg = R_ADC_ScanCfg, + .infoGet = R_ADC_InfoGet, + .scanStart = R_ADC_ScanStart, + .scanGroupStart = R_ADC_ScanGroupStart, + .scanStop = R_ADC_ScanStop, + .scanStatusGet = R_ADC_StatusGet, + .read = R_ADC_Read, + .read32 = R_ADC_Read32, + .close = R_ADC_Close, + .calibrate = R_ADC_Calibrate, + .offsetSet = R_ADC_OffsetSet, + .callbackSet = R_ADC_CallbackSet, +}; + +/*******************************************************************************************************************//** + * @addtogroup ADC + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Sets the operational mode, trigger sources, interrupt priority, and configurations for the peripheral as a whole. + * If interrupt is enabled, the function registers a callback function pointer for notifying the user whenever a scan + * has completed. + * + * @retval FSP_SUCCESS Module is ready for use. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_ALREADY_OPEN The instance control structure has already been opened. + * @retval FSP_ERR_IRQ_BSP_DISABLED A callback is provided, but the interrupt is not enabled. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The requested unit does not exist on this MCU. + * @retval FSP_ERR_INVALID_HW_CONDITION The ADC clock must be at least 1 MHz + **********************************************************************************************************************/ +fsp_err_t R_ADC_Open (adc_ctrl_t * p_ctrl, adc_cfg_t const * const p_cfg) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking */ +#if ADC_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + + /* Verify the configuration parameters are valid */ + fsp_err_t err = r_adc_open_cfg_check(p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Check for valid argument values for options that are unique to the IP */ + err = r_adc_open_cfg_resolution_check(p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Verify this unit has not already been initialized */ + FSP_ERROR_RETURN(ADC_OPEN != p_instance_ctrl->opened, FSP_ERR_ALREADY_OPEN); + + /* If a callback is used, then make sure an interrupt is enabled */ + adc_extended_cfg_t const * p_extend = (adc_extended_cfg_t const *) p_cfg->p_extend; + if (NULL != p_cfg->p_callback) + { + FSP_ERROR_RETURN((p_cfg->scan_end_irq >= 0) || (p_extend->window_a_irq >= 0) || (p_extend->window_b_irq >= 0), + FSP_ERR_IRQ_BSP_DISABLED); + + /* Group B interrupts are never required since group B can be configured in continuous scan mode when group A + * has priority over group B. */ + } + +#else + adc_extended_cfg_t const * p_extend = (adc_extended_cfg_t const *) p_cfg->p_extend; +#endif + + /* Save configurations. */ + p_instance_ctrl->p_cfg = p_cfg; + p_instance_ctrl->p_callback = p_cfg->p_callback; + p_instance_ctrl->p_context = p_cfg->p_context; + p_instance_ctrl->p_callback_memory = NULL; + + /* Calculate the register base address. */ + uint32_t address_gap = (uint32_t) R_ADC1 - (uint32_t) R_ADC0; + p_instance_ctrl->p_reg = (R_ADC0_Type *) ((uint32_t) R_ADC0 + (address_gap * p_cfg->unit)); + + /* Initialize the hardware based on the configuration. */ + r_adc_open_sub(p_instance_ctrl, p_cfg); + + /* Enable interrupts */ + r_adc_irq_enable(p_cfg->scan_end_irq, p_cfg->scan_end_ipl, p_instance_ctrl); + r_adc_irq_enable(p_cfg->scan_end_b_irq, p_cfg->scan_end_b_ipl, p_instance_ctrl); + r_adc_irq_enable(p_extend->window_a_irq, p_extend->window_a_ipl, p_instance_ctrl); + r_adc_irq_enable(p_extend->window_b_irq, p_extend->window_b_ipl, p_instance_ctrl); + + /* Invalid scan mask (initialized for later). */ + p_instance_ctrl->scan_mask = 0U; + + /* Mark driver as opened by initializing it to "RADC" in its ASCII equivalent for this unit. */ + p_instance_ctrl->opened = ADC_OPEN; + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Configures the ADC scan parameters. Channel specific settings are set in this function. Pass a pointer to + * @ref adc_channel_cfg_t to p_channel_cfg. + * + * @note This starts group B scans if adc_channel_cfg_t::priority_group_a is set to ADC_GROUP_A_GROUP_B_CONTINUOUS_SCAN. + * + * @retval FSP_SUCCESS Channel specific settings applied. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_ScanCfg (adc_ctrl_t * p_ctrl, void const * const p_channel_cfg) +{ + adc_channel_cfg_t const * p_adc_channel_cfg = (adc_channel_cfg_t const *) p_channel_cfg; + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + fsp_err_t err = FSP_SUCCESS; + +#if ADC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_adc_channel_cfg); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + + err = r_adc_scan_cfg_check(p_instance_ctrl, p_adc_channel_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + /* Configure the hardware based on the configuration */ + r_adc_scan_cfg(p_instance_ctrl, p_adc_channel_cfg); + + /* Save the scan mask locally; this is required for the infoGet function. */ + p_instance_ctrl->scan_mask = p_adc_channel_cfg->scan_mask; + + /* Return the error code */ + return err; +} + +/*******************************************************************************************************************//** + * Updates the user callback and has option of providing memory for callback structure. + * Implements adc_api_t::callbackSet + * + * @retval FSP_SUCCESS Callback updated successfully. + * @retval FSP_ERR_ASSERTION A required pointer is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + * @retval FSP_ERR_NO_CALLBACK_MEMORY p_callback is non-secure and p_callback_memory is either secure or NULL. + **********************************************************************************************************************/ +fsp_err_t R_ADC_CallbackSet (adc_ctrl_t * const p_api_ctrl, + void ( * p_callback)(adc_callback_args_t *), + void const * const p_context, + adc_callback_args_t * const p_callback_memory) +{ + adc_instance_ctrl_t * p_ctrl = (adc_instance_ctrl_t *) p_api_ctrl; + +#if (ADC_CFG_PARAM_CHECKING_ENABLE) + FSP_ASSERT(p_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(ADC_OPEN == p_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Store callback and context */ + +#if BSP_TZ_SECURE_BUILD + + /* Get security state of p_callback */ + bool callback_is_secure = + (NULL == cmse_check_address_range((void *) p_callback, sizeof(void *), CMSE_AU_NONSECURE)); + + #if ADC_CFG_PARAM_CHECKING_ENABLE + + /* In secure projects, p_callback_memory must be provided in non-secure space if p_callback is non-secure */ + adc_callback_args_t * const p_callback_memory_checked = cmse_check_pointed_object(p_callback_memory, + CMSE_AU_NONSECURE); + FSP_ERROR_RETURN(callback_is_secure || (NULL != p_callback_memory_checked), FSP_ERR_NO_CALLBACK_MEMORY); + #endif + + p_ctrl->p_callback = callback_is_secure ? p_callback : + (void (*)(adc_callback_args_t *))cmse_nsfptr_create(p_callback); +#else + p_ctrl->p_callback = p_callback; +#endif + + p_ctrl->p_context = p_context; + p_ctrl->p_callback_memory = p_callback_memory; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Starts a software scan or enables the hardware trigger for a scan depending on how the triggers were configured in + * the R_ADC_Open call. If the unit was configured for ELC or external hardware triggering, then this function allows + * the trigger signal to get to the ADC unit. The function is not able to control the generation of the trigger itself. + * If the unit was configured for software triggering, then this function starts the software triggered scan. + * + * @pre Call R_ADC_ScanCfg after R_ADC_Open before starting a scan. + * + * @pre On MCUs that support calibration, call R_ADC_Calibrate and wait for calibration to complete before starting + * a scan. + * + * @retval FSP_SUCCESS Scan started (software trigger) or hardware triggers enabled. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized. + * @retval FSP_ERR_IN_USE Another scan is still in progress (software trigger). + **********************************************************************************************************************/ +fsp_err_t R_ADC_ScanStart (adc_ctrl_t * p_ctrl) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking */ +#if ADC_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->initialized, FSP_ERR_NOT_INITIALIZED); + if (ADC_GROUP_A_GROUP_B_CONTINUOUS_SCAN != p_instance_ctrl->p_reg->ADGSPCR) + { + FSP_ERROR_RETURN(0U == p_instance_ctrl->p_reg->ADCSR_b.ADST, FSP_ERR_IN_USE); + } +#endif + + /* Enable hardware trigger or start software scan depending on mode. */ + p_instance_ctrl->p_reg->ADCSR = p_instance_ctrl->scan_start_adcsr; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @ref adc_api_t::scanStart is not supported on the ADCH. Use scanStart instead. + * + * @retval FSP_ERR_UNSUPPORTED Function not supported in this implementation. + **********************************************************************************************************************/ +fsp_err_t R_ADC_ScanGroupStart (adc_ctrl_t * p_ctrl, adc_group_mask_t group_id) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(group_id); + + /* Return the unsupported error. */ + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * Stops the software scan or disables the unit from being triggered by the hardware trigger (ELC or external) based on + * what type of trigger the unit was configured for in the R_ADC_Open function. Stopping a hardware triggered scan via + * this function does not abort an ongoing scan, but prevents the next scan from occurring. Stopping a software + * triggered scan aborts an ongoing scan. + * + * @retval FSP_SUCCESS Scan stopped (software trigger) or hardware triggers disabled. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_ADC_ScanStop (adc_ctrl_t * p_ctrl) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking */ +#if ADC_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->initialized, FSP_ERR_NOT_INITIALIZED); +#endif + + /* Disable hardware trigger or stop software scan depending on mode. */ + p_instance_ctrl->p_reg->ADCSR = 0U; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Provides the status of any scan process that was started, including scans started by ELC or external triggers and + * calibration scans on MCUs that support calibration. + * + * @retval FSP_SUCCESS Module status stored in the provided pointer p_status + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_StatusGet (adc_ctrl_t * p_ctrl, adc_status_t * p_status) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + +#if ADC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_status); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Read the status of the ADST bit. ADST is set when a scan is in progress, including calibration scans. */ + p_status->state = (adc_state_t) p_instance_ctrl->p_reg->ADCSR_b.ADST; + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reads conversion results from a single channel or sensor. + * + * @retval FSP_SUCCESS Data read into provided p_data. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_ADC_Read (adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint16_t * const p_data) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + + /* Perform parameter checking. */ +#if ADC_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_data); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->initialized, FSP_ERR_NOT_INITIALIZED); + + /* Verify that the channel is valid for this MCU */ + if ((reg_id >= ADC_CHANNEL_0) && ((uint32_t) reg_id <= 31U)) + { + uint32_t requested_channel_mask = (1U << (uint32_t) reg_id); + FSP_ASSERT(0 != (requested_channel_mask & g_adc_valid_channels[p_instance_ctrl->p_cfg->unit])); + } + else + { + FSP_ASSERT((reg_id == ADC_CHANNEL_TEMPERATURE) || (reg_id == ADC_CHANNEL_VOLT) || + (reg_id == ADC_CHANNEL_DUPLEX) || (reg_id == ADC_CHANNEL_DUPLEX_A) || + (reg_id == ADC_CHANNEL_DUPLEX_B)); + } + + /* Data is not available to be read from ADDRn registers when ADBUF is enabled. Read API cannot be used with ADBUF enabled. */ + adc_extended_cfg_t * p_extend = (adc_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + FSP_ASSERT(1U != p_extend->enable_adbuf); +#endif + + /* Read the data from the requested ADC conversion register and return it */ + *p_data = p_instance_ctrl->p_reg->ADDR[reg_id]; + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reads conversion results from a single channel or sensor register into a 32-bit result. + * + * @retval FSP_SUCCESS Data read into provided p_data. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_ADC_Read32 (adc_ctrl_t * p_ctrl, adc_channel_t const reg_id, uint32_t * const p_data) +{ + uint16_t result = 0U; + uint32_t result_32 = 0U; + +#if ADC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_data); +#endif + + fsp_err_t err = R_ADC_Read(p_ctrl, reg_id, &result); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + result_32 = result; + + /* Left shift the result into the upper 16 bits if the unit is configured for left alignment. */ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + if (ADC_ALIGNMENT_LEFT == p_instance_ctrl->p_cfg->alignment) + { + result_32 <<= ADC_SHIFT_LEFT_ALIGNED_32_BIT; + } + + *p_data = result_32; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Sets the sample state count for individual channels. This only needs to be set for special use cases. Normally, use + * the default values out of reset. + * + * @note The sample states for the temperature and voltage sensor are set in R_ADC_ScanCfg. + * + * @retval FSP_SUCCESS Sample state count updated. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_INITIALIZED Unit is not initialized. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_SampleStateCountSet (adc_ctrl_t * p_ctrl, adc_sample_state_t * p_sample) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + fsp_err_t err = FSP_SUCCESS; + + /* Perform parameter checking */ +#if ADC_CFG_PARAM_CHECKING_ENABLE + + /* Verify the pointers are valid */ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_sample); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->initialized, FSP_ERR_NOT_INITIALIZED); + + /* Verify arguments are legal */ + err = r_adc_sample_state_cfg_check(p_instance_ctrl, p_sample); + if (FSP_SUCCESS != err) + { + return err; + } +#endif + + /* Set the sample state count for the specified register */ + p_instance_ctrl->p_reg->ADSSTR[p_sample->reg_id] = p_sample->num_states; + + /* Return the error code */ + return err; +} + +/*******************************************************************************************************************//** + * Returns the address of the lowest number configured channel and the total number of bytes to be read in order to + * read the results of the configured channels and return the ELC Event name. If no channels are configured, then a + * length of 0 is returned. + * + * Also provides the temperature sensor slope and the calibration data for the sensor if available on this MCU. + * Otherwise, invalid calibration data of 0xFFFFFFFF will be returned. + * + * @note In group mode, information is returned for group A only. Calculating information for group B is not currently + * supported. + * + * @retval FSP_SUCCESS Information stored in p_adc_info. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_InfoGet (adc_ctrl_t * p_ctrl, adc_info_t * p_adc_info) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + fsp_err_t err = FSP_SUCCESS; + uint32_t adc_mask = 0; + +#if ADC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_adc_info); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Retrieve the scan mask of active channels from the control structure */ + adc_mask = p_instance_ctrl->scan_mask; + + /* If at least one channel is configured, determine the highest and lowest configured channels. */ + if (adc_mask != 0U) + { + /* Determine the lowest channel that is configured. The lowest sensor is the temperature sensor, at -3 from + * channel 0. To get all channels in register order, shift up by 3, then add in the sensors in the bottom + * 2 bits. */ + uint32_t adc_mask_in_order = adc_mask & ~(uint32_t) ADC_MASK_SENSORS; + adc_mask_in_order <<= 3U; + adc_mask_in_order |= adc_mask >> 28U; + int32_t lowest_channel = r_adc_lowest_channel_get(adc_mask_in_order); + p_adc_info->p_address = &p_instance_ctrl->p_reg->ADDR[lowest_channel - 3]; + + /* Determine the highest channel that is configured. */ + int32_t highest_channel = 31 - __CLZ(adc_mask_in_order); + + /* Determine the size of data that must be read to read all the channels between and including the + * highest and lowest channels.*/ + p_adc_info->length = (uint32_t) ((highest_channel - lowest_channel) + 1); + } + else + { + /* If no channels are configured, set the return length 0. */ + p_adc_info->length = 0U; + } + + p_adc_info->transfer_size = TRANSFER_SIZE_2_BYTE; + +#if BSP_FEATURE_ADC_UNIT_1_CHANNELS + + /* Specify the peripheral name in the ELC list */ + p_adc_info->elc_event = + (elc_event_t) ((uint32_t) ELC_EVENT_ADC0_SCAN_END + + (p_instance_ctrl->p_cfg->unit * + ((uint32_t) ELC_EVENT_ADC1_SCAN_END - (uint32_t) ELC_EVENT_ADC0_SCAN_END))); +#else + p_adc_info->elc_event = ELC_EVENT_ADC0_SCAN_END; +#endif + + p_adc_info->elc_peripheral = (elc_peripheral_t) (ELC_PERIPHERAL_ADC0 + (2U * p_instance_ctrl->p_cfg->unit)); + + /* Set Temp Sensor calibration data to invalid value */ + p_adc_info->calibration_data = UINT32_MAX; + + /* If calibration register is available, retrieve it from the MCU */ +#if 1U == BSP_FEATURE_ADC_TSN_CALIBRATION_AVAILABLE + #if 1U == BSP_FEATURE_ADC_TSN_CALIBRATION32_AVAILABLE + + /* Read into memory. */ + uint32_t data = R_TSN_CAL->TSCDR; + + /* Read the temperature calibration data from ROM. */ + p_adc_info->calibration_data = (data & BSP_FEATURE_ADC_TSN_CALIBRATION32_MASK); + #else + + /* Read into memory to prevent compiler warning when performing "|" on volatile register data. */ + uint32_t high = R_TSN->TSCDRH; + uint32_t low = R_TSN->TSCDRL; + + /* Read the calibration data from ROM and shift to fit into result variable. */ + p_adc_info->calibration_data = ((high << 8) | low); + #endif +#endif + + /* Provide the previously retrieved slope information */ + p_adc_info->slope_microvolts = BSP_FEATURE_ADC_TSN_SLOPE; + + return err; +} + +/*******************************************************************************************************************//** + * This function ends any scan in progress, disables interrupts, and removes power to the A/D peripheral. + * + * @retval FSP_SUCCESS Module closed. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_Close (adc_ctrl_t * p_ctrl) +{ + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + +#if ADC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); +#endif + + /* Mark driver as closed */ + p_instance_ctrl->opened = 0U; + p_instance_ctrl->initialized = 0U; + + /* Disable interrupts. */ + adc_extended_cfg_t * p_extend = (adc_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + r_adc_irq_disable(p_instance_ctrl->p_cfg->scan_end_irq); + r_adc_irq_disable(p_instance_ctrl->p_cfg->scan_end_b_irq); + r_adc_irq_disable(p_extend->window_a_irq); + r_adc_irq_disable(p_extend->window_b_irq); + + /* Disable triggers. */ + p_instance_ctrl->p_reg->ADSTRGR = 0U; + + /* Stop the ADC. */ + p_instance_ctrl->p_reg->ADCSR = 0U; + +#if BSP_FEATURE_ADC_HAS_SAMPLE_HOLD_REG + + /* Disable sample and hold before entering module stop state to reduce power consumption (reference section 47.6.8 + * "Available Functions and Register Settings of AN000 to AN002, AN007, AN100 to AN102, and AN107" in the RA6M3 + * manual R01UH0886EJ0100. */ + p_instance_ctrl->p_reg->ADSHCR = 0U; +#endif + +#if BSP_FEATURE_ADC_HAS_VREFAMPCNT + + /* If VREFADC is selected as the high-potential reference voltage revert it to reduce power consumption. */ + p_instance_ctrl->p_reg->VREFAMPCNT = 0U; +#endif + + R_BSP_MODULE_STOP(FSP_IP_ADC, p_instance_ctrl->p_cfg->unit); + + /* Return the error code */ + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Initiates calibration of the ADC on MCUs that require calibration. This function must be called before starting + * a scan on MCUs that require calibration. + * + * Calibration is complete when the callback is called with ADC_EVENT_CALIBRATION_COMPLETE or when R_ADC_StatusGet + * returns ADC_STATUS_IDLE. Reference Figure 32.35 "Software flow and operation example of calibration operation." + * in the RA2A1 manual R01UH0888EJ0100. + * + * ADC calibration time: 12 PCLKB + 774,930 ADCLK. (Reference Table 32.16 "Required calibration time (shown + * as the number of ADCLK and PCLKB cycles)" in the RA2A1 manual R01UH0888EJ0100. The lowest supported ADCLK + * is 1MHz. + * + * Calibration will take a minimum of 24 milliseconds at 32 MHz PCLKB and ADCLK. This wait could take up to 780 + * milliseconds for a 1 MHz PCLKD (ADCLK). + * + * @param[in] p_ctrl Pointer to the instance control structure + * @param[in] p_extend Unused argument. Pass NULL. + * + * @retval FSP_SUCCESS Calibration successfully initiated. + * @retval FSP_ERR_INVALID_HW_CONDITION A scan is in progress or hardware triggers are enabled. + * @retval FSP_ERR_UNSUPPORTED Calibration not supported on this MCU. + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_NOT_OPEN Unit is not open. + **********************************************************************************************************************/ +fsp_err_t R_ADC_Calibrate (adc_ctrl_t * const p_ctrl, void const * p_extend) +{ + FSP_PARAMETER_NOT_USED(p_extend); + +#if BSP_FEATURE_ADC_CALIBRATION_REG_AVAILABLE + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) p_ctrl; + #if ADC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(ADC_OPEN == p_instance_ctrl->opened, FSP_ERR_NOT_OPEN); + #endif + + /* ADC Calibration can only happen if there is no ongoing scan and if the scan trigger is disabled */ + FSP_ERROR_RETURN(!(p_instance_ctrl->p_reg->ADCSR & ADC_PRV_ADCSR_ADST_TRGE_MASK), FSP_ERR_INVALID_HW_CONDITION); + + /* Set the normal mode interrupt request to occur when calibration is complete */ + p_instance_ctrl->p_reg->ADICR = ADC_ADICR_CALIBRATION_INTERRUPT_ENABLED; + + /* Initiate calibration */ + p_instance_ctrl->p_reg->ADCALEXE = ADC_ADCALEXE_SET_CALEXE; + + return FSP_SUCCESS; +#else + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_ERROR_LOG(FSP_ERR_UNSUPPORTED); + + return FSP_ERR_UNSUPPORTED; +#endif +} + +/*******************************************************************************************************************//** + * @ref adc_api_t::offsetSet is not supported on the ADC. + * + * @retval FSP_ERR_UNSUPPORTED Function not supported in this implementation. + **********************************************************************************************************************/ +fsp_err_t R_ADC_OffsetSet (adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, int32_t offset) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(reg_id); + FSP_PARAMETER_NOT_USED(offset); + + /* Return the unsupported error. */ + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup ADC) + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * Checks the sample state configuration. + * + * @param[in] p_instance_ctrl Pointer to instance control structure + * @param[in] p_sample Pointer to sample state configuration + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_adc_sample_state_cfg_check (adc_instance_ctrl_t * p_instance_ctrl, adc_sample_state_t * p_sample) +{ + /* Used to prevent compiler warning */ + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + + adc_sample_state_reg_t reg_id = p_sample->reg_id; + + /* Verify the requested channel exists on the MCU. */ + if (reg_id >= ADC_SAMPLE_STATE_CHANNEL_0) + { + uint32_t requested_channel_mask = (1U << (uint32_t) reg_id); + FSP_ASSERT(0 != (requested_channel_mask & g_adc_valid_channels[p_instance_ctrl->p_cfg->unit])); + } + + /* Verify the requested sample states is not less than the minimum. */ + FSP_ASSERT(p_sample->num_states >= ADC_SAMPLE_STATE_COUNT_MIN); + + return FSP_SUCCESS; +} + +#endif + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * Validates the configuration arguments for illegal combinations or options. + * + * @param[in] p_cfg Pointer to configuration structure + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT ADC unit not present on this MCU + * @retval FSP_ERR_INVALID_HW_CONDITION The ADC clock must be at least 1 MHz + **********************************************************************************************************************/ +static fsp_err_t r_adc_open_cfg_check (adc_cfg_t const * const p_cfg) +{ + FSP_ASSERT(NULL != p_cfg); + + /* Verify the unit exists on the MCU. */ + FSP_ERROR_RETURN(((1U << p_cfg->unit) & BSP_FEATURE_ADC_VALID_UNIT_MASK), FSP_ERR_IP_CHANNEL_NOT_PRESENT); + + /* Verify the ADC clock frequency is at least 1 MHz (reference "Frequency" row of table "60.5 ADC12 + * Characteristics" in the RA6M3 manual R01UH0886EJ0100. The maximum frequency is the maximum frequency supported + * by the ADCLK, so it is not verified here. */ + uint32_t freq_hz = R_FSP_SystemClockHzGet(BSP_FEATURE_ADC_CLOCK_SOURCE); + FSP_ERROR_RETURN(freq_hz >= ADC_PRV_MIN_ADCLK_HZ, FSP_ERR_INVALID_HW_CONDITION); + + /* Check for valid argument values for addition/averaging. Reference section 47.2.10 "A/D-Converted Value + * Addition/Average Count Select Register (ADADC)" in the RA6M3 manual R01UH0886EJ0100 and section 32.2.11 + * "A/D-Converted Value Average Count Select Register (ADADC)" in the RA2A1 manual R01UH0888EJ0100. */ + adc_extended_cfg_t const * p_cfg_extend = (adc_extended_cfg_t const *) p_cfg->p_extend; + if (ADC_ADD_OFF != p_cfg_extend->add_average_count) + { + #if BSP_FEATURE_ADC_ADDITION_SUPPORTED + + /* The ADC12 and ADC14 do not support averaging 8 or 16 samples. */ + FSP_ASSERT(p_cfg_extend->add_average_count <= ADC_ADD_AVERAGE_FOUR); + #else + + /* The ADC16 supports averaging only, it does not support addition. */ + FSP_ASSERT(0U != (ADC_ADADC_AVEE_BIT & p_cfg_extend->add_average_count)); + #endif + } + + /* If 16 time addition is used only 12 bit accuracy can be selected. Reference Note 1 of section 47.2.10 + * "A/D-Converted Value Addition/Average Count Select Register (ADADC)" in the RA6M3 manual R01UH0886EJ0100. */ + if (ADC_ADD_SIXTEEN == p_cfg_extend->add_average_count) + { + FSP_ASSERT(ADC_RESOLUTION_12_BIT == p_cfg->resolution); + } + + /* Only synchronous triggers (ELC) allowed in group scan mode (reference TRSA documentation in section 47.2.12 + * "A/D Conversion Start Trigger Select Register (ADSTRGR)" in the RA6M3 manual R01UH0886EJ0100. */ + if ((ADC_MODE_GROUP_SCAN == p_cfg->mode) || (ADC_DOUBLE_TRIGGER_DISABLED != p_cfg_extend->double_trigger_mode)) + { + FSP_ASSERT(ADC_TRIGGER_SYNC_ELC == p_cfg->trigger); + + if ((ADC_MODE_GROUP_SCAN == p_cfg->mode)) + { + FSP_ASSERT(ADC_TRIGGER_SYNC_ELC == p_cfg_extend->trigger_group_b); + } + } + + return FSP_SUCCESS; +} + +#endif + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * This function validates the resolution configuration arguments for illegal combinations or options. + * + * @param[in] p_cfg Pointer to configuration structure + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_adc_open_cfg_resolution_check (adc_cfg_t const * const p_cfg) +{ + #if 12U == BSP_FEATURE_ADC_MAX_RESOLUTION_BITS + #if BSP_FEATURE_ADC_HAS_ADCER_ADPRC + + /* Resolution options for ADC12 (reference section 47.2.11 "A/D Control Extended Register (ADCER)" in the RA6M3 + * manual R01UH0886EJ0100. */ + FSP_ASSERT((ADC_RESOLUTION_12_BIT == p_cfg->resolution) || + (ADC_RESOLUTION_10_BIT == p_cfg->resolution) || + (ADC_RESOLUTION_8_BIT == p_cfg->resolution)); + #else + FSP_ASSERT(ADC_RESOLUTION_12_BIT == p_cfg->resolution); + #endif + #endif + + #if 14U == BSP_FEATURE_ADC_MAX_RESOLUTION_BITS + + /* Resolution options for ADC14 (reference section 35.2.11 "A/D Control Extended Register (ADCER)" in the RA4M1 + * manual R01UH0886EJ0100. */ + FSP_ASSERT((ADC_RESOLUTION_12_BIT == p_cfg->resolution) || + (ADC_RESOLUTION_14_BIT == p_cfg->resolution)); + #endif + + #if 16U == BSP_FEATURE_ADC_MAX_RESOLUTION_BITS + + /* ADC16 only offers 16-bit resolution (reference Table 32.1 "ADC16 specifications (1 of 2)" in the RA2A1 manual + * R01UH0888EJ0100. */ + FSP_ASSERT(ADC_RESOLUTION_16_BIT == p_cfg->resolution); + #endif + + return FSP_SUCCESS; +} + +#endif + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * Checks the sample and hold arguments + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_channel_cfg Pointer to channel configuration + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_adc_scan_cfg_check_sample_hold (adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg) +{ + #if !BSP_FEATURE_ADC_HAS_SAMPLE_HOLD_REG + + /* If the MCU does not have sample and hold, verify the sample and hold feature is not used. */ + FSP_ASSERT(0U == p_channel_cfg->sample_hold_mask); + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + #else + if (0U != p_channel_cfg->sample_hold_mask) + { + /* Sample and Hold channels can only be 0, 1, 2 and must have at least minimum state count specified (reference + * section 47.2.15 "A/D Sample and Hold Circuit Control Register (ADSHCR)" in the RA6M3 manual + * R01UH0886EJ0100. */ + FSP_ASSERT(p_channel_cfg->sample_hold_mask <= ADC_SAMPLE_HOLD_CHANNELS); + FSP_ASSERT(p_channel_cfg->sample_hold_states >= ADC_SAMPLE_STATE_HOLD_COUNT_MIN); + + uint32_t b_mask = p_channel_cfg->sample_hold_mask & p_channel_cfg->scan_mask_group_b; + if (ADC_MODE_GROUP_SCAN == p_instance_ctrl->p_cfg->mode) + { + if (ADC_GROUP_A_PRIORITY_OFF != p_channel_cfg->priority_group_a) + { + /* Sample and hold channels cannot be in GroupB if GroupA priority enabled. (reference SHANS[2:0] bits + * in section 47.2.15 "A/D Sample and Hold Circuit Control Register (ADSHCR)" in the RA6M3 manual + * R01UH0886EJ0100.*/ + FSP_ASSERT(0 == b_mask); + } + } + } + #endif + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Enforces constraints on Window Compare function usage per section 47.3.5.3 "Constraints on the compare function" in + * the RA6M3 User's Manual (R01UH0886EJ0100) + * + * @param[in] p_window_cfg Pointer to window compare configuration + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_adc_scan_cfg_check_window_compare (adc_window_cfg_t const * const p_window_cfg) +{ + if (p_window_cfg) + { + uint32_t compare_cfg = p_window_cfg->compare_cfg; + if (0U != compare_cfg) + { + if ((compare_cfg & R_ADC0_ADCMPCR_CMPAE_Msk) && (compare_cfg & R_ADC0_ADCMPCR_CMPBE_Msk)) + { + /* Ensure channels selected for Window A do not conflict with Window B */ + uint32_t compare_b_ch = p_window_cfg->compare_b_channel; + compare_b_ch -= compare_b_ch > 31 ? 4 : 0; + FSP_ASSERT(!(p_window_cfg->compare_mask & (uint32_t) (1 << compare_b_ch))); + } + + if (compare_cfg & R_ADC0_ADCMPCR_WCMPE_Msk) + { + /* Ensure lower reference values are less than or equal to the high reference values */ + FSP_ASSERT((p_window_cfg->compare_ref_low <= p_window_cfg->compare_ref_high) && + (p_window_cfg->compare_b_ref_low <= p_window_cfg->compare_b_ref_high)); + } + } + } + + return FSP_SUCCESS; +} + +#endif + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * This function checks the Temperature and Voltage sensor arguments + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_channel_cfg Pointer to channel configuration + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION Sensor configuration has been selected for Group B on an MCU which does not allow + * Group B configuration or sensor is used in Normal/Group A with the double trigger + * not enabled or MCU does not allow both the sensors to be used simultaneously + **********************************************************************************************************************/ +static fsp_err_t r_adc_scan_cfg_check_sensors (adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg) +{ + /* Some MCUs have nothing to check here. */ + FSP_PARAMETER_NOT_USED(p_channel_cfg); + + #if !BSP_FEATURE_ADC_GROUP_B_SENSORS_ALLOWED + + /* Sensors are not supported in Group B in some MCUs. Reference section 32.2.14 "A/D Conversion Extended Input + * Control Register (ADEXICR)" of the RA2A1 manual R01UH0888EJ0100. */ + FSP_ASSERT(0U == (p_channel_cfg->scan_mask_group_b & ADC_MASK_SENSORS)); + #endif + + #if BSP_FEATURE_ADC_SENSORS_EXCLUSIVE + uint32_t sensor_mask = p_channel_cfg->scan_mask & ADC_MASK_SENSORS; + if (0U != sensor_mask) + { + /* If the temperature sensor or the internal voltage reference is used, then none of the channels can be used + * at the same time. The temperature sensor and the internal voltage reference can only be used in single scan + * mode. Reference TSSA and OCSA bits in section 35.2.13 "A/D Conversion Extended Input Control Register + * (ADEXICR)" of the RA4M1 manual R01UH0887EJ0100. */ + FSP_ASSERT(ADC_MASK_SENSORS != sensor_mask); + FSP_ASSERT(p_channel_cfg->scan_mask == sensor_mask); + FSP_ASSERT(ADC_MODE_SINGLE_SCAN == p_instance_ctrl->p_cfg->mode); + } + #endif + + /* When using double-trigger modes the sensors must not be configured or used in Group A. */ + adc_extended_cfg_t const * p_cfg_extend = (adc_extended_cfg_t const *) p_instance_ctrl->p_cfg->p_extend; + if (ADC_DOUBLE_TRIGGER_DISABLED != p_cfg_extend->double_trigger_mode) + { + FSP_ASSERT(0U == (p_channel_cfg->scan_mask & ADC_MASK_SENSORS)); + } + + return FSP_SUCCESS; +} + +#endif + +/*******************************************************************************************************************//** + * The Open function applies power to the A/D peripheral, sets the operational mode, trigger sources, and + * configurations common to all channels and sensors. + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_cfg Pointer to configuration structure + **********************************************************************************************************************/ +static void r_adc_open_sub (adc_instance_ctrl_t * const p_instance_ctrl, adc_cfg_t const * const p_cfg) +{ + adc_extended_cfg_t const * p_cfg_extend = (adc_extended_cfg_t const *) p_cfg->p_extend; + + /* Determine the value for ADCSR: + * * The configured mode is set in ADCSR.ADCS. + * * ADCSR.GBADIE is always set by this driver. It will only trigger an interrupt in group mode if the group B + * interrupt is enabled. + * * If double-trigger mode is selected ADCSR.DBLANS is set to the chosen double-trigger scan channel and + * ADCSR.DBLE is set to 1; otherwise, both are set to 0. + * * The configured trigger mode is set in ADCSR.EXTRG and ADCSR.TRGE. + * * The value to set in ADCSR to start a scan is stored in the control structure. ADCSR.ADST is set in + * R_ADC_ScanStart if software trigger mode is used. + */ + uint32_t adcsr = (uint32_t) (p_cfg->mode << R_ADC0_ADCSR_ADCS_Pos); + adcsr |= (uint32_t) (R_ADC0_ADCSR_GBADIE_Msk); + adcsr |= ((uint32_t) p_cfg->trigger << R_ADC0_ADCSR_EXTRG_Pos); + + if (ADC_DOUBLE_TRIGGER_DISABLED != p_cfg_extend->double_trigger_mode) + { + adcsr |= R_ADC0_ADCSR_TRGE_Msk | R_ADC0_ADCSR_DBLE_Msk; + } + else if (ADC_TRIGGER_SOFTWARE == p_cfg->trigger) + { + adcsr |= R_ADC0_ADCSR_ADST_Msk; + } + else + { + /* Do nothing. */ + } + + p_instance_ctrl->scan_start_adcsr = (uint16_t) adcsr; + + /* The default value for ADSTRGR is 0 out of reset. Update it only if the ADC is triggered on ELC events. */ + uint32_t adstrgr = 0U; + if (ADC_TRIGGER_SYNC_ELC == p_cfg->trigger) + { + /* Set ADSTRGR per the following: + * Extended double-trigger mode: + * - Normal (Group A): ELC_PERIPHERAL_ADCn and ELC_PERIPHERAL_ADCn_B + * - Group B: None + * All other modes: + * - Normal (Group A): ELC_PERIPHERAL_ADCn + * - Group B: ELC_PERIPHERAL_ADCn_B + */ + adstrgr = adc_elc_trigger_lut[p_cfg_extend->double_trigger_mode]; + } + + /* Determine the value for ADCER: + * * The resolution is set as configured in ADCER.ADPRC (on MCUs that have this bitfield). + * * The alignment is set as configured in ADCER.ADFMT (on MCUs that have this bitfield). + * * The clearing option is set as configured in ADCER.ACE. + * * Always select data range of 0 - 32767 in ADCER.INV (on MCUs that have this bitfield). + * * Always disable self-diagnosis (unsupported in this module). + */ + uint32_t adcer = 0U; +#if BSP_FEATURE_ADC_HAS_ADCER_ADPRC + adcer |= (uint32_t) p_cfg->resolution << R_ADC0_ADCER_ADPRC_Pos; +#endif +#if BSP_FEATURE_ADC_HAS_ADCER_ADRFMT + adcer |= (uint32_t) p_cfg->alignment << R_ADC0_ADCER_ADRFMT_Pos; +#endif + adcer |= (uint32_t) p_cfg_extend->clearing << R_ADC0_ADCER_ACE_Pos; + +#if BSP_FEATURE_ADC_CALIBRATION_REG_AVAILABLE + adcer |= 1U << R_ADC0_ADCER_ADINV_Pos; +#endif + + /* Determine the value for ADADC: + * * The addition/averaging modes are set as configured in ADADC.ADC and ADADC.AVEE. + * * On MCUs that do not have the ADADC.AVEE bit (addition not supported), the ADADC.AVEE bit is cleared. + */ + uint32_t adadc = p_cfg_extend->add_average_count; +#if !BSP_FEATURE_ADC_ADDITION_SUPPORTED + adadc &= ~ADC_ADADC_AVEE_BIT; +#endif + + /* Apply clock to peripheral. */ + R_BSP_MODULE_START(FSP_IP_ADC, p_cfg->unit); + + /* Set the predetermined values for ADCSR, ADSTRGR, ADCER, and ADADC without setting ADCSR.ADST or ADCSR.TRGE. + * ADCSR.ADST or ADCSR.TRGE are set as configured in R_ADC_ScanStart. */ + p_instance_ctrl->p_reg->ADCSR = (uint16_t) (adcsr & ADC_PRV_ADCSR_CLEAR_ADST_TRGE); + p_instance_ctrl->p_reg->ADSTRGR = (uint16_t) adstrgr; + p_instance_ctrl->p_reg->ADCER = (uint16_t) adcer; + p_instance_ctrl->p_reg->ADADC = (uint8_t) adadc; + +#if BSP_FEATURE_ADC_HAS_PGA + + /* Disable the unused ADC PGA feature (on MCUs where it is available) since the feature is enabled out of reset on + * some MCUs and disabled on others and affects the operation of the normal ADC channels that are multiplexed with + * the PGA. */ + p_instance_ctrl->p_reg->ADPGADCR0 = ADC_ADPGADCR0_DISABLE_PGA; + p_instance_ctrl->p_reg->ADPGACR = ADC_ADPGACR_DISABLE_PGA; +#endif + +#if BSP_FEATURE_ADC_CALIBRATION_REG_AVAILABLE + + /* Use ADC in single-ended mode. */ + p_instance_ctrl->p_reg->ADANIM = 0U; +#endif + +#if BSP_FEATURE_ADC_HAS_VREFAMPCNT + + /* If VREFADC is selected as the high-potential reference voltage. */ + if (ADC_VREF_CONTROL_VREFH != p_cfg_extend->adc_vref_control) + { + /* Configure Reference Voltage controls + * Reference section "32.6 Selecting Reference Voltage" in the RA2A1 manual R01UH0888EJ0100. */ + p_instance_ctrl->p_reg->VREFAMPCNT = + (uint8_t) (p_cfg_extend->adc_vref_control & + (R_ADC0_VREFAMPCNT_BGREN_Msk | R_ADC0_VREFAMPCNT_VREFADCG_Msk)); + + R_BSP_SoftwareDelay(ADC_BGR_STABILIZATION_DELAY_US, BSP_DELAY_UNITS_MICROSECONDS); + + /* Enable Over current detection and VREFADC output */ + p_instance_ctrl->p_reg->VREFAMPCNT = (uint8_t) (p_cfg_extend->adc_vref_control); + } +#endif + +#if BSP_FEATURE_ADC_HAS_ADHVREFCNT + + /* If the internal voltage is set as VREFH, discharge the VREF node for 1 us before setting ADHVREFCNT.HVSEL to 2. + * Reference section 35.7 "A/D Conversion Procedure when Selecting Internal Reference Voltage as High-Potential + * Reference Voltage" in the RA4M1 manual R01UH0887EJ0100. + * + * Also wait 5 us before using the ADC. This wait is the responsibility of the application. */ + if (ADC_PRV_ADHVREFCNT_VREF_INTERNAL_BIT_1 & p_cfg_extend->adc_vref_control) + { + p_instance_ctrl->p_reg->ADHVREFCNT = (uint8_t) (p_cfg_extend->adc_vref_control | R_ADC0_ADHVREFCNT_HVSEL_Msk); + + R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS); + } + p_instance_ctrl->p_reg->ADHVREFCNT = (uint8_t) p_cfg_extend->adc_vref_control; +#endif + +#if BSP_FEATURE_ADC_HAS_ADBUF + uint8_t adbuf = 0; + if (1U == p_cfg_extend->enable_adbuf) + { + adbuf = R_ADC0_ADBUFEN_BUFEN_Msk; + } + p_instance_ctrl->p_reg->ADBUFEN = adbuf; +#endif +} + +/*******************************************************************************************************************//** + * This function set the sensor bits taking into account group inclusion and addition/average mode. + * This function must only be called if it has been verified that sensors are used in this configuration + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_channel_cfg Pointer to channel configuration + **********************************************************************************************************************/ +static void r_adc_sensor_cfg (adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg) +{ + /* Calculate sample states required for temperature and voltage sensor at the current ADCLK speed. */ + uint32_t sample_states = 0U; + r_adc_sensor_sample_state_calculation(&sample_states); + + /* Check if the temperature sensor channel is enabled */ + uint32_t combined_scan_mask = p_channel_cfg->scan_mask | p_channel_cfg->scan_mask_group_b; + uint32_t adexicr = 0U; + if (combined_scan_mask & ADC_MASK_TEMPERATURE) + { +#if BSP_FEATURE_ADC_TSN_CONTROL_AVAILABLE + + /* Power on the temperature sensor. This is only needed for TSNs that have the control register */ + R_BSP_MODULE_START(FSP_IP_TSN, 0U); + + /* Enable the temperature sensor output to the ADC */ + R_TSN_CTRL->TSCR = ADC_PRV_TSCR_TSN_ENABLE; +#endif + + /* Set sample state register to the calculated value */ + p_instance_ctrl->p_reg->ADSSTRT = (uint8_t) sample_states; + +#if BSP_FEATURE_ADC_GROUP_B_SENSORS_ALLOWED + if (p_channel_cfg->scan_mask & ADC_MASK_TEMPERATURE) + { + /* Scan the temperature sensor in normal/group A. */ + adexicr |= R_ADC0_ADEXICR_TSSA_Msk; + } + else + { + /* Scan the temperature sensor in group B */ + adexicr |= R_ADC0_ADEXICR_TSSB_Msk; + } + +#else + + /* Scan the temperature sensor in normal/group A. */ + adexicr |= R_ADC0_ADEXICR_TSSA_Msk; +#endif + + /* Enable temperature addition mode if configured. */ + if (p_channel_cfg->add_mask & ADC_MASK_TEMPERATURE) + { + adexicr |= R_ADC0_ADEXICR_TSSAD_Msk; + } + } + + /* Check if the voltage sensor channel is enabled */ + if (combined_scan_mask & ADC_MASK_VOLT) + { + /*sample state registers are set to the calculated value */ + p_instance_ctrl->p_reg->ADSSTRO = (uint8_t) sample_states; +#if BSP_FEATURE_ADC_GROUP_B_SENSORS_ALLOWED + if (p_channel_cfg->scan_mask & ADC_MASK_VOLT) + { + /* Scan the internal reference voltage in normal/group A. */ + adexicr |= R_ADC0_ADEXICR_OCSA_Msk; + } + else + { + /* Scan the internal reference voltage in group B. */ + adexicr |= R_ADC0_ADEXICR_OCSB_Msk; + } + +#else + + /* Scan the internal reference voltage in normal/group A. */ + adexicr |= R_ADC0_ADEXICR_OCSA_Msk; +#endif + + /* Enable temperature addition mode if configured. */ + if (p_channel_cfg->add_mask & ADC_MASK_VOLT) + { + adexicr |= R_ADC0_ADEXICR_OCSAD_Msk; + } + } + + p_instance_ctrl->p_reg->ADEXICR = (uint16_t) adexicr; +} + +/*******************************************************************************************************************//** + * This function calculates the sample states value for the internal sensors and returns an error if the calculated + * value is outside the limit supported by the hardware + * + * @param[out] p_sample_states: The calculates sample state count. + **********************************************************************************************************************/ +static void r_adc_sensor_sample_state_calculation (uint32_t * const p_sample_states) +{ + /* Calculate sample state values such that the sample time for the temperature and voltage sensor is the + * minimum defined by the hardware manual. The minimum is 4.15 microseconds for MF3 devices and + * 5 microseconds for RV40. The sample states will be calculated to allow sampling for this duration. */ + + /* Retrieve the clock source and frequency used by the ADC peripheral and sampling time required for the sensor. */ + uint32_t freq_hz = R_FSP_SystemClockHzGet(BSP_FEATURE_ADC_CLOCK_SOURCE); + + /* Calculate sample states required for the current ADC conversion clock (reference section 47.2.14 "A/D Sampling + * State Register n (ADSSTRn) (n = 00 to 07, L, T, O)" in the RA6M3 manual R01UH0886EJ0100. + * + * sample_states = required_sample_time / adclk_period + * = required_sample_time (nsec) * adclk_frequency (kHz) / 1000000 (usec / sec) + 1 + * (refactored to avoid overflowing 32 bits, 1 added to round up) + */ + uint32_t sample_states = ((BSP_FEATURE_ADC_SENSOR_MIN_SAMPLING_TIME * (freq_hz / ADC_PRV_HZ_PER_KHZ)) / + ADC_PRV_USEC_PER_SEC) + 1U; + + /* The fastest ADC conversion clock is 60 MHz, and the associated sampling time is 4.15 microseconds. The number + * of sample states in this case is 0.00000415 / (1 / 60000000) = 249. This is the maximum number of sample states + * required for the on chip sensors, so this calculation will never overflow 8 bits (255). */ + + /* If sample states are less than the min number of states required, then set them to the minimum. */ + if (sample_states < ADC_SAMPLE_STATE_COUNT_MIN) + { + sample_states = ADC_SAMPLE_STATE_COUNT_MIN; + } + + *p_sample_states = sample_states; +} + +#if ADC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * This function does extensive checking on channel mask settings based upon operational mode. + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_channel_cfg Pointer to channel configuration + * + * @retval FSP_SUCCESS No configuration errors detected + * @retval FSP_ERR_ASSERTION An input argument is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_adc_scan_cfg_check (adc_instance_ctrl_t * const p_instance_ctrl, + adc_channel_cfg_t const * const p_channel_cfg) +{ + fsp_err_t err; + uint16_t unit = p_instance_ctrl->p_cfg->unit; + + /* Verify at least one channel is selected for normal / group A. */ + uint32_t valid_channels = g_adc_valid_channels[unit] | ADC_MASK_TEMPERATURE | ADC_MASK_VOLT; + FSP_ASSERT((0U != p_channel_cfg->scan_mask) && (0U == (p_channel_cfg->scan_mask & (~valid_channels)))); + + if (ADC_MODE_GROUP_SCAN == p_instance_ctrl->p_cfg->mode) + { + /* Verify at least one channel is selected for group B. */ + FSP_ASSERT((0U != p_channel_cfg->scan_mask_group_b) && + (0U == (p_channel_cfg->scan_mask_group_b & (~valid_channels)))); + + /* Cannot have the same channel in both groups. */ + FSP_ASSERT(0 == (p_channel_cfg->scan_mask & p_channel_cfg->scan_mask_group_b)); + } + else + { + /* If group mode is not enabled, no channels can be selected for group B. */ + FSP_ASSERT(ADC_MASK_OFF == p_channel_cfg->scan_mask_group_b); + } + + /* Verify sensor configuration. */ + err = r_adc_scan_cfg_check_sensors(p_instance_ctrl, p_channel_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Verify that if addition is enabled, then at least one channel is selected. */ + adc_extended_cfg_t const * p_cfg_extend = (adc_extended_cfg_t const *) p_instance_ctrl->p_cfg->p_extend; + if (ADC_ADD_OFF != p_cfg_extend->add_average_count) + { + /* Addition mask should not include bits from inactive channels. + * This also serves as a check for valid channels in the addition mask */ + uint32_t tmp_mask = p_channel_cfg->scan_mask_group_b | p_channel_cfg->scan_mask; + FSP_ASSERT((0U == (p_channel_cfg->add_mask & ~tmp_mask)) && (0U != p_channel_cfg->add_mask)); + } + else + { + /* Channels cannot be selected for addition if addition is not used. */ + FSP_ASSERT(ADC_MASK_OFF == p_channel_cfg->add_mask); + } + + /* Check sample and hold settings. */ + err = r_adc_scan_cfg_check_sample_hold(p_instance_ctrl, p_channel_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Check window compare settings. */ + err = r_adc_scan_cfg_check_window_compare(p_channel_cfg->p_window_cfg); + + return err; +} + +#endif + +/*******************************************************************************************************************//** + * This function does extensive checking on channel mask settings based upon operational mode. Mask registers are + * initialized and interrupts enabled in peripheral. Interrupts are also enabled in ICU if corresponding priority + * is not 0. + * + * @param[in] p_instance_ctrl Pointer to instance control block + * @param[in] p_channel_cfg Pointer to channel configuration + **********************************************************************************************************************/ +static void r_adc_scan_cfg (adc_instance_ctrl_t * const p_instance_ctrl, adc_channel_cfg_t const * const p_channel_cfg) +{ + /* Set mask for Group A channels. */ + uint32_t scan_mask = p_channel_cfg->scan_mask & ~(uint32_t) ADC_MASK_SENSORS; + adc_extended_cfg_t const * p_cfg_extend = (adc_extended_cfg_t const *) p_instance_ctrl->p_cfg->p_extend; + + /* Set other channel masks. */ + uint32_t scan_mask_group_b = p_channel_cfg->scan_mask_group_b & ~(uint32_t) ADC_MASK_SENSORS; + uint32_t add_mask = p_channel_cfg->add_mask & ~(uint32_t) ADC_MASK_SENSORS; + + p_instance_ctrl->p_reg->ADANSA[0] = (uint16_t) (scan_mask); + p_instance_ctrl->p_reg->ADANSB[0] = (uint16_t) (scan_mask_group_b); + p_instance_ctrl->p_reg->ADADS[0] = (uint16_t) (add_mask); + p_instance_ctrl->p_reg->ADANSA[1] = (uint16_t) ((scan_mask >> 16)); + p_instance_ctrl->p_reg->ADANSB[1] = (uint16_t) ((scan_mask_group_b >> 16)); + p_instance_ctrl->p_reg->ADADS[1] = (uint16_t) ((add_mask >> 16)); + + /* If either voltage or temperature sensor are used, configure them. */ + uint32_t temp_mask = p_channel_cfg->scan_mask | p_channel_cfg->scan_mask_group_b; + if (temp_mask & ADC_MASK_SENSORS) + { + /* Calculate sample state values such that the sample time for the temperature and voltage sensor is the + * minimum defined by the hardware manual. The minimum is 4.15 microseconds for MF3 devices and + * 5 microseconds for RV40. The sample states will be calculated to allow sampling for this duration. */ + + /* Retrieve the clock source and frequency used by the ADC peripheral and sampling time required for the sensor. */ + r_adc_sensor_cfg(p_instance_ctrl, p_channel_cfg); + } + +#if BSP_FEATURE_ADC_HAS_SAMPLE_HOLD_REG + + /* Configure sample and hold. */ + uint32_t adshcr = p_channel_cfg->sample_hold_states; + adshcr |= (p_channel_cfg->sample_hold_mask & ADC_MASK_SAMPLE_HOLD_BYPASS_CHANNELS) << + ADC_MASK_SAMPLE_HOLD_BYPASS_SHIFT; + p_instance_ctrl->p_reg->ADSHCR = (uint16_t) adshcr; +#endif + + /* Get window compare configuration */ + adc_window_cfg_t * p_window_cfg = p_channel_cfg->p_window_cfg; + + uint16_t adcmpcr = 0; + + if (p_window_cfg) + { + /* Save window compare config */ + adcmpcr = (uint16_t) p_window_cfg->compare_cfg; + + if (p_window_cfg->compare_cfg & R_ADC0_ADCMPCR_CMPAE_Msk) + { + /* Set Window A boundary values */ + p_instance_ctrl->p_reg->ADCMPCR = p_window_cfg->compare_cfg & UINT16_MAX; + p_instance_ctrl->p_reg->ADCMPDR0 = p_window_cfg->compare_ref_low; + p_instance_ctrl->p_reg->ADCMPDR1 = p_window_cfg->compare_ref_high; + + /* Set Window A channel mask */ + p_instance_ctrl->p_reg->ADCMPANSR[0] = p_window_cfg->compare_mask & UINT16_MAX; + p_instance_ctrl->p_reg->ADCMPANSR[1] = (uint16_t) ((p_window_cfg->compare_mask << 4) >> 20); + p_instance_ctrl->p_reg->ADCMPANSER = (uint8_t) (p_window_cfg->compare_mask >> 28); + + /* Set Window A channel inequality mode mask */ + p_instance_ctrl->p_reg->ADCMPLR[0] = p_window_cfg->compare_mode_mask & UINT16_MAX; + p_instance_ctrl->p_reg->ADCMPLR[1] = (uint16_t) ((p_window_cfg->compare_mode_mask << 4) >> 20); + p_instance_ctrl->p_reg->ADCMPLER = (uint8_t) (p_window_cfg->compare_mode_mask >> 28); + } + + if (p_window_cfg->compare_cfg & R_ADC0_ADCMPCR_CMPBE_Msk) + { + /* Set Window B channel and mode */ + p_instance_ctrl->p_reg->ADCMPBNSR = (uint8_t) ((adc_window_b_mode_t) p_window_cfg->compare_b_channel | + p_window_cfg->compare_b_mode); + + /* Set Window B boundary values */ + p_instance_ctrl->p_reg->ADWINLLB = p_window_cfg->compare_b_ref_low; + p_instance_ctrl->p_reg->ADWINULB = p_window_cfg->compare_b_ref_high; + } + } + + /* Set window compare config */ + p_instance_ctrl->p_reg->ADCMPCR = adcmpcr; + + /* Set group A priority action (not interrupt priority!) + * This will also start the Group B scans if configured for ADC_GROUP_A_GROUP_B_CONTINUOUS_SCAN. + */ + p_instance_ctrl->p_reg->ADGSPCR = (uint16_t) p_channel_cfg->priority_group_a; + + /* In double-trigger mode set the channel select bits to the highest selected channel number then return. */ + if (ADC_DOUBLE_TRIGGER_DISABLED != p_cfg_extend->double_trigger_mode) + { + uint32_t adcsr = p_instance_ctrl->p_reg->ADCSR; + adcsr = (adcsr & ~R_ADC0_ADCSR_DBLANS_Msk) + (31U - __CLZ(scan_mask)); + + p_instance_ctrl->p_reg->ADCSR = (uint16_t) adcsr; + p_instance_ctrl->scan_start_adcsr |= (uint16_t) adcsr; + } + + p_instance_ctrl->initialized = ADC_OPEN; +} + +/*******************************************************************************************************************//** + * Disables and clears context for the requested IRQ. + * + * @param[in] irq IRQ to enable + * @param[in] ipl Interrupt priority + * @param[in] p_context Pointer to interrupt context + **********************************************************************************************************************/ +static void r_adc_irq_enable (IRQn_Type irq, uint8_t ipl, void * p_context) +{ + if (irq >= 0) + { + R_BSP_IrqCfgEnable(irq, ipl, p_context); + } +} + +/*******************************************************************************************************************//** + * Disables and clears context for the requested IRQ. + * + * @param[in] irq IRQ to disable + **********************************************************************************************************************/ +static void r_adc_irq_disable (IRQn_Type irq) +{ + if (irq >= 0) + { + R_BSP_IrqDisable(irq); + R_FSP_IsrContextSet(irq, NULL); + } +} + +/*******************************************************************************************************************//** + * Returns the lowest channel index that is configured in order to read the results of the configured channels. + * + * @param[in] adc_mask scan mask of active channels retrieved from the control structure + * + * @retval adc_mask_count index value of lowest channel + **********************************************************************************************************************/ +static int32_t r_adc_lowest_channel_get (uint32_t adc_mask) +{ + /* Initialize the mask result */ + uint32_t adc_mask_result = 0U; + int32_t adc_mask_count = -1; + while (0U == adc_mask_result) + { + /* Increment channel until a channel is found in the mask. */ + adc_mask_count++; + adc_mask_result = (uint32_t) (adc_mask & (1U << adc_mask_count)); + } + + return adc_mask_count; +} + +/*******************************************************************************************************************//** + * Calls user callback. + * + * @param[in] p_ctrl Pointer to ADC instance control block + * @param[in] p_args Pointer to arguments on stack + **********************************************************************************************************************/ +static void r_adc_call_callback (adc_instance_ctrl_t * p_ctrl, adc_callback_args_t * p_args) +{ + adc_callback_args_t args; + + /* Store callback arguments in memory provided by user if available. This allows callback arguments to be + * stored in non-secure memory so they can be accessed by a non-secure callback function. */ + adc_callback_args_t * p_args_memory = p_ctrl->p_callback_memory; + if (NULL == p_args_memory) + { + /* Use provided args struct on stack */ + p_args_memory = p_args; + } + else + { + /* Save current arguments on the stack in case this is a nested interrupt. */ + args = *p_args_memory; + + /* Copy the stacked args to callback memory */ + *p_args_memory = *p_args; + } + +#if BSP_TZ_SECURE_BUILD + + /* p_callback can point to a secure function or a non-secure function. */ + if (!cmse_is_nsfptr(p_ctrl->p_callback)) + { + /* If p_callback is secure, then the project does not need to change security state. */ + p_ctrl->p_callback(p_args_memory); + } + else + { + /* If p_callback is Non-secure, then the project must change to Non-secure state in order to call the callback. */ + adc_prv_ns_callback p_callback = (adc_prv_ns_callback) (p_ctrl->p_callback); + p_callback(p_args_memory); + } + +#else + + /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the callback. */ + p_ctrl->p_callback(p_args_memory); +#endif + + if (NULL != p_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_ctrl->p_callback_memory = args; + } +} + +/*******************************************************************************************************************//** + * Clears interrupt flag and calls a callback to notify application of the event. + * + * @param[in] event Event that triggered the ISR + **********************************************************************************************************************/ +static void r_adc_scan_end_common_isr (adc_event_t event) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) R_FSP_IsrContextGet(R_FSP_CurrentIrqGet()); + + /* Clear the BSP IRQ Flag */ + R_BSP_IrqStatusClear(R_FSP_CurrentIrqGet()); + + adc_callback_args_t args; + args.event = event; +#if BSP_FEATURE_ADC_CALIBRATION_REG_AVAILABLE + + /* Store the correct event into the callback argument */ + if (ADC_ADICR_CALIBRATION_INTERRUPT_DISABLED != p_instance_ctrl->p_reg->ADICR) + { + args.event = ADC_EVENT_CALIBRATION_COMPLETE; + + /* Restore the interrupt source to disable interrupts after calibration is done. */ + p_instance_ctrl->p_reg->ADICR = 0U; + } +#endif + + /* Store the unit number into the callback argument */ + args.unit = p_instance_ctrl->p_cfg->unit; + + /* Initialize the channel to 0. It is not used in this implementation. */ + args.channel = ADC_CHANNEL_0; + + /* Populate the context field. */ + args.p_context = p_instance_ctrl->p_context; + + /* If a callback was provided, call it with the argument */ + if (NULL != p_instance_ctrl->p_callback) + { + r_adc_call_callback(p_instance_ctrl, &args); + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; +} + +/*******************************************************************************************************************//** + * This function implements the unit 0 interrupt handler for normal/Group A/double trigger scan complete. + **********************************************************************************************************************/ +void adc_scan_end_isr (void) +{ + r_adc_scan_end_common_isr(ADC_EVENT_SCAN_COMPLETE); +} + +/*******************************************************************************************************************//** + * This function implements the interrupt handler for Group B scan complete. + **********************************************************************************************************************/ +void adc_scan_end_b_isr (void) +{ + r_adc_scan_end_common_isr(ADC_EVENT_SCAN_COMPLETE_GROUP_B); +} + +/*******************************************************************************************************************//** + * This function implements the interrupt handler for window compare events. + **********************************************************************************************************************/ +void adc_window_compare_isr (void) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + + adc_instance_ctrl_t * p_instance_ctrl = (adc_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + adc_extended_cfg_t * p_extend = (adc_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + adc_callback_args_t args; + args.event = (irq == p_extend->window_a_irq) ? ADC_EVENT_WINDOW_COMPARE_A : ADC_EVENT_WINDOW_COMPARE_B; + + /* Store the unit number into the callback argument */ + args.unit = p_instance_ctrl->p_cfg->unit; + + if (ADC_EVENT_WINDOW_COMPARE_A == args.event) + { + args.channel = (adc_channel_t) 0; + + R_ADC0_Type * p_reg = p_instance_ctrl->p_reg; + + /* Get all Window A status registers */ + uint16_t adcmpsr0 = p_reg->ADCMPSR[0]; + uint16_t adcmpsr1 = p_reg->ADCMPSR[1]; + uint8_t adcmpser = p_reg->ADCMPSER; + + /* Get the lowest channel that meets Window A criteria */ + uint32_t lowest_channel = __CLZ(__RBIT(adcmpsr0 + (uint32_t) (adcmpsr1 << 16) + (uint32_t) (adcmpser << 28))); + + /* Clear the status flag corresponding to the lowest channel */ + if (lowest_channel < 16) + { + p_reg->ADCMPSR[0] = (uint16_t) (adcmpsr0 & ~(1 << (lowest_channel & 0xF))); + } + else if (lowest_channel < 28) + { + p_reg->ADCMPSR[1] = (uint16_t) (adcmpsr1 & ~(1 << (lowest_channel & 0xF))); + } + else + { + p_reg->ADCMPSER = (uint8_t) (adcmpser & ~(1 << (lowest_channel & 0x3))); + } + + args.channel = (adc_channel_t) lowest_channel; + + if (args.channel > 28) + { + /* Adjust sensor channels to align with the adc_channel_t enumeration */ + args.channel = (adc_channel_t) (ADC_CHANNEL_TEMPERATURE + (args.channel - 28)); + } + } + else + { + /* Get channel selected for Window B */ + args.channel = (adc_channel_t) p_instance_ctrl->p_reg->ADCMPBNSR_b.CMPCHB; + + if (args.channel > 31) + { + /* Adjust sensor channels to align with the adc_channel_t enumeration */ + args.channel = (adc_channel_t) (ADC_CHANNEL_TEMPERATURE + (args.channel & 0xF)); + } + + /* Clear IRQ */ + p_instance_ctrl->p_reg->ADCMPBSR_b.CMPSTB = 0; + } + + /* Populate the context field. */ + args.p_context = p_instance_ctrl->p_context; + + /* If a callback was provided, call it with the argument */ + if (NULL != p_instance_ctrl->p_callback) + { + r_adc_call_callback(p_instance_ctrl, &args); + } + + R_BSP_IrqStatusClear(irq); + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; +} diff --git a/bsp/renesas/ra6m3-hmi-board/ra/fsp/src/r_gpt/r_gpt.c b/bsp/renesas/ra6m3-hmi-board/ra/fsp/src/r_gpt/r_gpt.c new file mode 100644 index 0000000000..cc54467e55 --- /dev/null +++ b/bsp/renesas/ra6m3-hmi-board/ra/fsp/src/r_gpt/r_gpt.c @@ -0,0 +1,1830 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics America Inc. and may only be used with products + * of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. Renesas products are + * sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for the selection and use + * of Renesas products and Renesas assumes no liability. No license, express or implied, to any intellectual property + * right is granted by Renesas. This software is protected under all applicable laws, including copyright laws. Renesas + * reserves the right to change or discontinue this software and/or this documentation. THE SOFTWARE AND DOCUMENTATION + * IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND TO THE FULLEST EXTENT + * PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, INCLUDING WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE SOFTWARE OR + * DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. TO THE MAXIMUM + * EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR DOCUMENTATION + * (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, INCLUDING, + * WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY LOST PROFITS, + * OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE POSSIBILITY + * OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "r_gpt.h" +#include "r_gpt_cfg.h" + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/* "GPT" in ASCII, used to determine if channel is open. */ +#define GPT_OPEN (0x00475054ULL) + +#define GPT_PRV_GPTE_OR_GPTEH_CHANNEL_MASK (BSP_FEATURE_GPTEH_CHANNEL_MASK | \ + BSP_FEATURE_GPTE_CHANNEL_MASK) + +#define GPT_PRV_GTWP_RESET_VALUE (0xA500U) +#define GPT_PRV_GTWP_WRITE_PROTECT (0xA501U) + +#define GPT_PRV_GTIOR_STOP_LEVEL_BIT (6) +#define GPT_PRV_GTIOR_INITIAL_LEVEL_BIT (4) + +#define GPT_PRV_GTIO_HIGH_COMPARE_MATCH_LOW_CYCLE_END (0x6U) +#define GPT_PRV_GTIO_LOW_COMPARE_MATCH_HIGH_CYCLE_END (0x9U) + +#define GPT_PRV_GTIO_TOGGLE_COMPARE_MATCH (0x3U) + +#define GPT_PRV_GTBER_BUFFER_ENABLE_FORCE_TRANSFER (0x550000U) + +#define GPT_PRV_ENABLE_GROUP_SOFTWARE_UPDATE (0x80000000U) + +#define GPT_PRV_GTCCRA (0U) +#define GPT_PRV_GTCCRB (1U) +#define GPT_PRV_GTCCRC (2U) +#define GPT_PRV_GTCCRE (3U) +#define GPT_PRV_GTCCRD (4U) +#define GPT_PRV_GTCCRF (5U) + +/* GPT_CFG_OUTPUT_SUPPORT_ENABLE is set to 2 to enable extra features. */ +#define GPT_PRV_EXTRA_FEATURES_ENABLED (2U) + +#define R_GPT0_GTINTAD_ADTRAUEN_Pos (16U) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/* Duty cycle mode. */ +typedef enum e_gpt_duty_cycle_mode +{ + GPT_DUTY_CYCLE_MODE_REGISTER = 0, // Duty cycle depends on compare match + GPT_DUTY_CYCLE_MODE_0_PERCENT = 2, // Output low + GPT_DUTY_CYCLE_MODE_100_PERCENT = 3, // Output high +} gpt_duty_cycle_mode_t; + +/* Count direction */ +typedef enum e_gpt_dir +{ + GPT_DIR_COUNT_DOWN = 0, + GPT_DIR_COUNT_UP = 1 +} gpt_dir_t; + +typedef struct st_gpt_prv_duty_registers +{ + uint32_t gtccr_buffer; + uint32_t omdty; +} gpt_prv_duty_registers_t; + +typedef enum e_gpt_prv_capture_event +{ + GPT_PRV_CAPTURE_EVENT_A, + GPT_PRV_CAPTURE_EVENT_B, +} gpt_prv_capture_event_t; + +#if defined(__ARMCC_VERSION) || defined(__ICCARM__) +typedef void (BSP_CMSE_NONSECURE_CALL * gpt_prv_ns_callback)(timer_callback_args_t * p_args); +#elif defined(__GNUC__) +typedef BSP_CMSE_NONSECURE_CALL void (*volatile gpt_prv_ns_callback)(timer_callback_args_t * p_args); +#endif + +/*********************************************************************************************************************** + * Private function prototypes + **********************************************************************************************************************/ +static void gpt_hardware_initialize(gpt_instance_ctrl_t * const p_instance_ctrl, timer_cfg_t const * const p_cfg); + +static void gpt_common_open(gpt_instance_ctrl_t * const p_instance_ctrl, timer_cfg_t const * const p_cfg); + +static uint32_t gpt_clock_frequency_get(gpt_instance_ctrl_t * const p_instance_ctrl); + +static void gpt_hardware_events_disable(gpt_instance_ctrl_t * p_instance_ctrl); + +static void r_gpt_disable_irq(IRQn_Type irq); + +static inline void r_gpt_write_protect_enable(gpt_instance_ctrl_t * const p_instance_ctrl, + uint32_t write_protect_setting); +static inline uint32_t r_gpt_write_protect_disable(gpt_instance_ctrl_t * const p_instance_ctrl); + +/* Noinline attribute added to reduce code size for CM23 GCC build. */ +static void r_gpt_enable_irq(IRQn_Type const irq, uint32_t priority, void * p_context) __attribute__((noinline)); + +#if GPT_CFG_OUTPUT_SUPPORT_ENABLE + +static void gpt_calculate_duty_cycle(gpt_instance_ctrl_t * const p_instance_ctrl, + uint32_t const duty_cycle_counts, + gpt_prv_duty_registers_t * p_duty_reg, + uint32_t pin); + +static uint32_t gpt_gtior_calculate(timer_cfg_t const * const p_cfg, gpt_pin_level_t const stop_level); + +#endif + +static void r_gpt_call_callback(gpt_instance_ctrl_t * p_ctrl, timer_event_t event, uint32_t capture); + +/*********************************************************************************************************************** + * ISR prototypes + **********************************************************************************************************************/ +void gpt_counter_overflow_isr(void); +void gpt_counter_underflow_isr(void); +void gpt_capture_a_isr(void); +void gpt_capture_b_isr(void); + +/*********************************************************************************************************************** + * Private global variables + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Global Variables + **********************************************************************************************************************/ + +/* GPT implementation of timer interface */ +const timer_api_t g_timer_on_gpt = +{ + .open = R_GPT_Open, + .stop = R_GPT_Stop, + .start = R_GPT_Start, + .reset = R_GPT_Reset, + .enable = R_GPT_Enable, + .disable = R_GPT_Disable, + .periodSet = R_GPT_PeriodSet, + .dutyCycleSet = R_GPT_DutyCycleSet, + .infoGet = R_GPT_InfoGet, + .statusGet = R_GPT_StatusGet, + .callbackSet = R_GPT_CallbackSet, + .close = R_GPT_Close, +}; + +/*******************************************************************************************************************//** + * @addtogroup GPT + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Initializes the timer module and applies configurations. Implements @ref timer_api_t::open. + * + * GPT hardware does not support one-shot functionality natively. When using one-shot mode, the timer will be stopped + * in an ISR after the requested period has elapsed. + * + * The GPT implementation of the general timer can accept a gpt_extended_cfg_t extension parameter. + * + * Example: + * @snippet r_gpt_example.c R_GPT_Open + * + * @retval FSP_SUCCESS Initialization was successful and timer has started. + * @retval FSP_ERR_ASSERTION A required input pointer is NULL or the source divider is invalid. + * @retval FSP_ERR_ALREADY_OPEN Module is already open. + * @retval FSP_ERR_IRQ_BSP_DISABLED timer_cfg_t::mode is ::TIMER_MODE_ONE_SHOT or timer_cfg_t::p_callback is not + * NULL, but ISR is not enabled. ISR must be enabled to use one-shot mode or + * callback. + * @retval FSP_ERR_INVALID_MODE Triangle wave PWM is only supported if GPT_CFG_OUTPUT_SUPPORT_ENABLE is 2. + * Selected channel does not support external count sources. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The channel requested in the p_cfg parameter is not available on this device. + **********************************************************************************************************************/ +fsp_err_t R_GPT_Open (timer_ctrl_t * const p_ctrl, timer_cfg_t const * const p_cfg) +{ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl; +#if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_cfg); + FSP_ASSERT(NULL != p_cfg->p_extend); + FSP_ASSERT(NULL != p_instance_ctrl); + + #if (2U == BSP_FEATURE_GPT_CLOCK_DIVIDER_STEP_SIZE) + #if (BSP_FEATURE_GPT_CLOCK_DIVIDER_VALUE_7_9_VALID) + FSP_ASSERT(p_cfg->source_div <= 10U); + #else + FSP_ASSERT((p_cfg->source_div != 7U) && (p_cfg->source_div != 9U) && (p_cfg->source_div <= 10)); + #endif + #else + FSP_ASSERT((0U == (p_cfg->source_div % 2U)) && (p_cfg->source_div <= 10)); + #endif + + #if GPT_PRV_EXTRA_FEATURES_ENABLED != GPT_CFG_OUTPUT_SUPPORT_ENABLE + FSP_ERROR_RETURN(p_cfg->mode <= TIMER_MODE_PWM, FSP_ERR_INVALID_MODE); + #endif + + FSP_ERROR_RETURN(GPT_OPEN != p_instance_ctrl->open, FSP_ERR_ALREADY_OPEN); +#endif + + p_instance_ctrl->channel_mask = 1U << p_cfg->channel; + +#if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ERROR_RETURN((p_instance_ctrl->channel_mask & BSP_FEATURE_GPT_VALID_CHANNEL_MASK), + FSP_ERR_IP_CHANNEL_NOT_PRESENT); + if ((p_cfg->p_callback) || (TIMER_MODE_ONE_SHOT == p_cfg->mode)) + { + FSP_ERROR_RETURN(p_cfg->cycle_end_irq >= 0, FSP_ERR_IRQ_BSP_DISABLED); + } + + gpt_extended_cfg_t * p_extend = (gpt_extended_cfg_t *) p_cfg->p_extend; + FSP_ERROR_RETURN((!p_extend->count_up_source && !p_extend->count_down_source) || + (BSP_FEATURE_GPT_EVENT_COUNT_CHANNEL_MASK & p_instance_ctrl->channel_mask), + FSP_ERR_INVALID_MODE); + + #if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE + + /* Callback is required if underflow interrupt is enabled. */ + gpt_extended_pwm_cfg_t const * p_pwm_cfg = p_extend->p_pwm_cfg; + if (NULL != p_pwm_cfg) + { + if (p_pwm_cfg->trough_irq >= 0) + { + FSP_ASSERT(NULL != p_cfg->p_callback); + } + } + #endif +#endif + + /* Initialize control structure based on configurations. */ + gpt_common_open(p_instance_ctrl, p_cfg); + + gpt_hardware_initialize(p_instance_ctrl, p_cfg); + + p_instance_ctrl->open = GPT_OPEN; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Stops timer. Implements @ref timer_api_t::stop. + * + * Example: + * @snippet r_gpt_example.c R_GPT_Stop + * + * @retval FSP_SUCCESS Timer successfully stopped. + * @retval FSP_ERR_ASSERTION p_ctrl was NULL. + * @retval FSP_ERR_NOT_OPEN The instance is not opened. + **********************************************************************************************************************/ +fsp_err_t R_GPT_Stop (timer_ctrl_t * const p_ctrl) +{ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl; +#if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + /* Stop timer */ + p_instance_ctrl->p_reg->GTSTP = p_instance_ctrl->channel_mask; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Starts timer. Implements @ref timer_api_t::start. + * + * Example: + * @snippet r_gpt_example.c R_GPT_Start + * + * @retval FSP_SUCCESS Timer successfully started. + * @retval FSP_ERR_ASSERTION p_ctrl was NULL. + * @retval FSP_ERR_NOT_OPEN The instance is not opened. + **********************************************************************************************************************/ +fsp_err_t R_GPT_Start (timer_ctrl_t * const p_ctrl) +{ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl; +#if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + /* Start timer */ + p_instance_ctrl->p_reg->GTSTR = p_instance_ctrl->channel_mask; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Resets the counter value to 0. Implements @ref timer_api_t::reset. + * + * @note This function also updates to the new period if no counter overflow has occurred since the last call to + * R_GPT_PeriodSet(). + * + * @retval FSP_SUCCESS Counter value written successfully. + * @retval FSP_ERR_ASSERTION p_ctrl was NULL. + * @retval FSP_ERR_NOT_OPEN The instance is not opened. + **********************************************************************************************************************/ +fsp_err_t R_GPT_Reset (timer_ctrl_t * const p_ctrl) +{ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl; +#if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + /* Clear timer counter. */ + p_instance_ctrl->p_reg->GTCLR = p_instance_ctrl->channel_mask; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Enables external event triggers that start, stop, clear, or capture the counter. Implements @ref timer_api_t::enable. + * + * Example: + * @snippet r_gpt_example.c R_GPT_Enable + * + * @retval FSP_SUCCESS External events successfully enabled. + * @retval FSP_ERR_ASSERTION p_ctrl was NULL. + * @retval FSP_ERR_NOT_OPEN The instance is not opened. + **********************************************************************************************************************/ +fsp_err_t R_GPT_Enable (timer_ctrl_t * const p_ctrl) +{ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl; +#if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + /* Enable use of GTSTR, GTSTP, and GTCLR for this channel. */ + gpt_extended_cfg_t * p_extend = (gpt_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + uint32_t gtssr = GPT_PRV_ENABLE_GROUP_SOFTWARE_UPDATE; + uint32_t gtpsr = GPT_PRV_ENABLE_GROUP_SOFTWARE_UPDATE; + uint32_t gtcsr = GPT_PRV_ENABLE_GROUP_SOFTWARE_UPDATE; + + /* OR with user settings. */ + gtssr |= p_extend->start_source; + gtpsr |= p_extend->stop_source; + gtcsr |= p_extend->clear_source; + + uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl); + + /* Set the count sources. Ensure stop and clear sources are set before start source, and capture sources are set + * after start source. */ + p_instance_ctrl->p_reg->GTPSR = gtpsr; + p_instance_ctrl->p_reg->GTCSR = gtcsr; + p_instance_ctrl->p_reg->GTSSR = gtssr; + p_instance_ctrl->p_reg->GTICASR = p_extend->capture_a_source; + p_instance_ctrl->p_reg->GTICBSR = p_extend->capture_b_source; + + r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Disables external event triggers that start, stop, clear, or capture the counter. Implements @ref timer_api_t::disable. + * + * @note The timer could be running after R_GPT_Disable(). To ensure it is stopped, call R_GPT_Stop(). + * + * Example: + * @snippet r_gpt_example.c R_GPT_Disable + * + * @retval FSP_SUCCESS External events successfully disabled. + * @retval FSP_ERR_ASSERTION p_ctrl was NULL. + * @retval FSP_ERR_NOT_OPEN The instance is not opened. + **********************************************************************************************************************/ +fsp_err_t R_GPT_Disable (timer_ctrl_t * const p_ctrl) +{ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl; +#if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl); + + gpt_hardware_events_disable(p_instance_ctrl); + + r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Sets period value provided. If the timer is running, the period will be updated after the next counter overflow. + * If the timer is stopped, this function resets the counter and updates the period. + * Implements @ref timer_api_t::periodSet. + * + * @warning If periodic output is used, the duty cycle buffer registers are updated after the period buffer register. + * If this function is called while the timer is running and a GPT overflow occurs during processing, the duty cycle + * will not be the desired 50% duty cycle until the counter overflow after processing completes. + * + * Example: + * @snippet r_gpt_example.c R_GPT_PeriodSet + * + * @retval FSP_SUCCESS Period value written successfully. + * @retval FSP_ERR_ASSERTION p_ctrl was NULL. + * @retval FSP_ERR_NOT_OPEN The instance is not opened. + **********************************************************************************************************************/ +fsp_err_t R_GPT_PeriodSet (timer_ctrl_t * const p_ctrl, uint32_t const period_counts) +{ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl; +#if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl); + + /* Update period buffer register. The actual period is one cycle longer than the register value for saw waves + * and twice the register value for triangle waves. Reference section 23.2.21 "General PWM Timer Cycle Setting + * Register (GTPR)". The setting passed to the configuration is expected to be half the desired period for + * triangle waves. */ + uint32_t new_gtpr = period_counts - 1U; +#if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE + if (p_instance_ctrl->p_cfg->mode >= TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM) + { + new_gtpr = period_counts; + } +#endif + + p_instance_ctrl->p_reg->GTPBR = new_gtpr; + +#if GPT_CFG_OUTPUT_SUPPORT_ENABLE + + /* Set a 50% duty cycle so the period of the waveform on the output pin matches the requested period. */ + if (TIMER_MODE_PERIODIC == p_instance_ctrl->p_cfg->mode) + { + /* The GTIOCA/GTIOCB pins transition 1 cycle after compare match when buffer operation is used. Reference + * Figure 23.34 "Example setting for saw-wave PWM mode" in the RA6M3 manual R01UH0886EJ0100. To get a duty cycle + * as close to 50% as possible, duty cycle (register) = (period (counts) / 2) - 1. */ + uint32_t duty_cycle_50_percent = (period_counts >> 1) - 1U; + p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRC] = duty_cycle_50_percent; + p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRE] = duty_cycle_50_percent; + } +#endif + + /* If the counter is not counting, update period register and reset counter. */ + if (0U == p_instance_ctrl->p_reg->GTCR_b.CST) + { + p_instance_ctrl->p_reg->GTPR = new_gtpr; + +#if GPT_CFG_OUTPUT_SUPPORT_ENABLE + p_instance_ctrl->p_reg->GTBER = GPT_PRV_GTBER_BUFFER_ENABLE_FORCE_TRANSFER; +#endif + + p_instance_ctrl->p_reg->GTCLR = p_instance_ctrl->channel_mask; + } + + r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Sets duty cycle on requested pin. Implements @ref timer_api_t::dutyCycleSet. + * + * Duty cycle is updated in the buffer register. The updated duty cycle is reflected after the next cycle end (counter + * overflow). + * + * Example: + * @snippet r_gpt_example.c R_GPT_DutyCycleSet + * + * @param[in] p_ctrl Pointer to instance control block. + * @param[in] duty_cycle_counts Duty cycle to set in counts. + * @param[in] pin Use gpt_io_pin_t to select GPT_IO_PIN_GTIOCA or GPT_IO_PIN_GTIOCB + * + * @retval FSP_SUCCESS Duty cycle updated successfully. + * @retval FSP_ERR_ASSERTION p_ctrl was NULL or the pin is not one of gpt_io_pin_t + * @retval FSP_ERR_NOT_OPEN The instance is not opened. + * @retval FSP_ERR_INVALID_ARGUMENT Duty cycle is larger than period. + * @retval FSP_ERR_INVALID_MODE GPT_IO_PIN_TROUGH, and GPT_IO_PIN_CREST settings are invalid in the this mode. + * @retval FSP_ERR_UNSUPPORTED GPT_CFG_OUTPUT_SUPPORT_ENABLE is 0. + **********************************************************************************************************************/ +fsp_err_t R_GPT_DutyCycleSet (timer_ctrl_t * const p_ctrl, uint32_t const duty_cycle_counts, uint32_t const pin) +{ +#if GPT_CFG_OUTPUT_SUPPORT_ENABLE + uint32_t tmp_pin = pin & 3U; + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl; + #if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(tmp_pin <= GPT_IO_PIN_GTIOCA_AND_GTIOCB); + bool pwm_mode3_pin = 0 != (pin & (GPT_IO_PIN_CREST | GPT_IO_PIN_TROUGH)); + if (TIMER_MODE_TRIANGLE_WAVE_ASYMMETRIC_PWM_MODE3 == p_instance_ctrl->p_cfg->mode) + { + /* In TIMER_MODE_TRIANGLE_WAVE_ASYMMETRIC_PWM_MODE3, the duty cycle must be for either a trough or crest. */ + FSP_ERROR_RETURN(pwm_mode3_pin, FSP_ERR_INVALID_MODE); + } + else + { + FSP_ERROR_RETURN(!pwm_mode3_pin, FSP_ERR_INVALID_MODE); + } + + FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(duty_cycle_counts <= (p_instance_ctrl->p_reg->GTPR + 1), FSP_ERR_INVALID_ARGUMENT); + #endif + + /* Set duty cycle. */ + gpt_prv_duty_registers_t duty_regs = {UINT32_MAX, 0}; + + gpt_calculate_duty_cycle(p_instance_ctrl, duty_cycle_counts, &duty_regs, pin); + + uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl); + + /* Read modify write bitfield access is used to update GTUDDTYC to make sure we don't clobber settings for the + * other pin. */ + uint32_t gtuddtyc = p_instance_ctrl->p_reg->GTUDDTYC; + + /* Only update GTCCR if 0% or 100% duty is not requested */ + if (!duty_regs.omdty) + { + uint32_t reg_offset = 2U; + if (0 != (pin & GPT_IO_PIN_CREST)) + { + /* + * In TIMER_MODE_TRIANGLE_WAVE_ASYMMETRIC_PWM_MODE3, if this is a crest duty cycle, then update the crest + * duty cycle register. Otherwise, update the trough duty cycle register. + */ + reg_offset = 4U; + } + + if (0 != (pin & GPT_IO_PIN_GTIOCA_AND_GTIOCB)) + { + p_instance_ctrl->p_reg->GTCCR[reg_offset] = duty_regs.gtccr_buffer; + p_instance_ctrl->p_reg->GTCCR[reg_offset + 1] = duty_regs.gtccr_buffer; + } + else + { + p_instance_ctrl->p_reg->GTCCR[tmp_pin + reg_offset] = duty_regs.gtccr_buffer; + } + } + + if (GPT_IO_PIN_GTIOCB != tmp_pin) + { + /* GTIOCA or both GTIOCA and GTIOCB. */ + gtuddtyc &= ~R_GPT0_GTUDDTYC_OADTY_Msk; + gtuddtyc |= duty_regs.omdty << R_GPT0_GTUDDTYC_OADTY_Pos; + } + + if ((GPT_IO_PIN_GTIOCA_AND_GTIOCB == pin) && duty_regs.omdty) + { + /* When setting both pins to 0%/100% duty recalculate OBDTY before setting */ + gpt_calculate_duty_cycle(p_instance_ctrl, duty_cycle_counts, &duty_regs, GPT_IO_PIN_GTIOCB); + } + + if (GPT_IO_PIN_GTIOCA != tmp_pin) + { + /* GTIOCB or both GTIOCA and GTIOCB. */ + gtuddtyc &= ~R_GPT0_GTUDDTYC_OBDTY_Msk; + gtuddtyc |= duty_regs.omdty << R_GPT0_GTUDDTYC_OBDTY_Pos; + } + + p_instance_ctrl->p_reg->GTUDDTYC = gtuddtyc; + + r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE); + + return FSP_SUCCESS; +#else + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(duty_cycle_counts); + FSP_PARAMETER_NOT_USED(pin); + + FSP_RETURN(FSP_ERR_UNSUPPORTED); +#endif +} + +/*******************************************************************************************************************//** + * Get timer information and store it in provided pointer p_info. Implements @ref timer_api_t::infoGet. + * + * Example: + * @snippet r_gpt_example.c R_GPT_InfoGet + * + * @retval FSP_SUCCESS Period, count direction, frequency, and ELC event written to caller's + * structure successfully. + * @retval FSP_ERR_ASSERTION p_ctrl or p_info was NULL. + * @retval FSP_ERR_NOT_OPEN The instance is not opened. + **********************************************************************************************************************/ +fsp_err_t R_GPT_InfoGet (timer_ctrl_t * const p_ctrl, timer_info_t * const p_info) +{ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl; +#if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_info); + FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + /* Get and store period */ + uint32_t gtpr = p_instance_ctrl->p_reg->GTPR; + uint32_t period_counts = gtpr + 1; +#if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE + if (p_instance_ctrl->p_cfg->mode >= TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM) + { + period_counts = gtpr; + } +#endif + p_info->period_counts = period_counts; + + /* Get and store clock frequency */ + p_info->clock_frequency = gpt_clock_frequency_get(p_instance_ctrl); + + /* Get and store clock counting direction. Read count direction setting */ + p_info->count_direction = TIMER_DIRECTION_UP; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Get current timer status and store it in provided pointer p_status. Implements @ref timer_api_t::statusGet. + * + * Example: + * @snippet r_gpt_example.c R_GPT_StatusGet + * + * @retval FSP_SUCCESS Current timer state and counter value set successfully. + * @retval FSP_ERR_ASSERTION p_ctrl or p_status was NULL. + * @retval FSP_ERR_NOT_OPEN The instance is not opened. + **********************************************************************************************************************/ +fsp_err_t R_GPT_StatusGet (timer_ctrl_t * const p_ctrl, timer_status_t * const p_status) +{ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl; +#if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_status); + FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + /* Get counter state. */ + p_status->state = (timer_state_t) p_instance_ctrl->p_reg->GTCR_b.CST; + + /* Get counter value */ + p_status->counter = p_instance_ctrl->p_reg->GTCNT; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Set counter value. + * + * @note Do not call this API while the counter is counting. The counter value can only be updated while the counter + * is stopped. + * + * @retval FSP_SUCCESS Counter value updated. + * @retval FSP_ERR_ASSERTION p_ctrl or p_status was NULL. + * @retval FSP_ERR_NOT_OPEN The instance is not opened. + * @retval FSP_ERR_IN_USE The timer is running. Stop the timer before calling this function. + **********************************************************************************************************************/ +fsp_err_t R_GPT_CounterSet (timer_ctrl_t * const p_ctrl, uint32_t counter) +{ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl; +#if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(0U == p_instance_ctrl->p_reg->GTCR_b.CST, FSP_ERR_IN_USE); +#endif + + uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl); + + /* Set counter value */ + p_instance_ctrl->p_reg->GTCNT = counter; + + r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Enable output for GTIOCA and/or GTIOCB. + * + * @retval FSP_SUCCESS Output is enabled. + * @retval FSP_ERR_ASSERTION p_ctrl or p_status was NULL. + * @retval FSP_ERR_NOT_OPEN The instance is not opened. + **********************************************************************************************************************/ +fsp_err_t R_GPT_OutputEnable (timer_ctrl_t * const p_ctrl, gpt_io_pin_t pin) +{ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl; +#if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl); + + uint32_t gtior = p_instance_ctrl->p_reg->GTIOR; + if (GPT_IO_PIN_GTIOCB != pin) + { + /* GTIOCA or both GTIOCA and GTIOCB. */ + gtior |= R_GPT0_GTIOR_OAE_Msk; + } + + if (GPT_IO_PIN_GTIOCA != pin) + { + /* GTIOCB or both GTIOCA and GTIOCB. */ + gtior |= R_GPT0_GTIOR_OBE_Msk; + } + + p_instance_ctrl->p_reg->GTIOR = gtior; + + r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Disable output for GTIOCA and/or GTIOCB. + * + * @retval FSP_SUCCESS Output is disabled. + * @retval FSP_ERR_ASSERTION p_ctrl or p_status was NULL. + * @retval FSP_ERR_NOT_OPEN The instance is not opened. + **********************************************************************************************************************/ +fsp_err_t R_GPT_OutputDisable (timer_ctrl_t * const p_ctrl, gpt_io_pin_t pin) +{ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl; +#if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl); + + uint32_t gtior = p_instance_ctrl->p_reg->GTIOR; + if (GPT_IO_PIN_GTIOCB != pin) + { + /* GTIOCA or both GTIOCA and GTIOCB. */ + gtior &= ~R_GPT0_GTIOR_OAE_Msk; + } + + if (GPT_IO_PIN_GTIOCA != pin) + { + /* GTIOCB or both GTIOCA and GTIOCB. */ + gtior &= ~R_GPT0_GTIOR_OBE_Msk; + } + + p_instance_ctrl->p_reg->GTIOR = gtior; + + r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Set A/D converter start request compare match value. + * + * @retval FSP_SUCCESS Counter value updated. + * @retval FSP_ERR_ASSERTION p_ctrl or p_status was NULL. + * @retval FSP_ERR_NOT_OPEN The instance is not opened. + **********************************************************************************************************************/ +fsp_err_t R_GPT_AdcTriggerSet (timer_ctrl_t * const p_ctrl, + gpt_adc_compare_match_t which_compare_match, + uint32_t compare_match_value) +{ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl; +#if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl); + + /* Set A/D converter start request compare match value. */ + volatile uint32_t * p_gtadtr = &p_instance_ctrl->p_reg->GTADTRA; + p_gtadtr[which_compare_match] = compare_match_value; + + r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Set the Output Delay setting for the PWM output pin. + * + * @retval FSP_SUCCESS The output delay was set. + * @retval FSP_ERR_ASSERTION An input parameter was invalid. + * @retval FSP_ERR_NOT_OPEN The instance is not opened. + * @retval FSP_ERR_INVALID_CHANNEL The channel does not support this feature. + * @retval FSP_ERR_NOT_INITIALIZED The PWM Output Delay Circuit has not been initialized. + * @retval FSP_ERR_INVALID_STATE The PWM Output Delay setting cannot be updated in the current state. + * @retval FSP_ERR_UNSUPPORTED This feature is not supported on this MCU. + **********************************************************************************************************************/ +fsp_err_t R_GPT_PwmOutputDelaySet (timer_ctrl_t * const p_ctrl, + gpt_pwm_output_delay_edge_t edge, + gpt_pwm_output_delay_setting_t delay_setting, + uint32_t const pin) +{ +#if 0U != BSP_FEATURE_GPT_ODC_VALID_CHANNEL_MASK && GPT_CFG_OUTPUT_SUPPORT_ENABLE + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl; + + #if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(0U != (BSP_FEATURE_GPT_ODC_VALID_CHANNEL_MASK & p_instance_ctrl->channel_mask), + FSP_ERR_INVALID_CHANNEL); + FSP_ERROR_RETURN(0U != (R_GPT_ODC->GTDLYCR1 & R_GPT_ODC_GTDLYCR1_DLLEN_Msk), FSP_ERR_NOT_INITIALIZED); + + if (TIMER_MODE_PWM == p_instance_ctrl->p_cfg->mode) + { + /* In Saw-wave mode, do not change the settings for the delay while the compare-match value is greater than or + * equal to GTPR - 2. */ + uint32_t gtpr = p_instance_ctrl->p_reg->GTPR; + uint32_t compare_match = p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRC + pin]; + FSP_ERROR_RETURN(gtpr - 2 > compare_match, FSP_ERR_INVALID_STATE); + } + else + { + uint32_t compare_match; + if (TIMER_MODE_TRIANGLE_WAVE_ASYMMETRIC_PWM_MODE3 == p_instance_ctrl->p_cfg->mode) + { + /* In TIMER_MODE_TRIANGLE_WAVE_ASYMMETRIC_PWM_MODE3, the trough compare match value is set in + * GTCCRD, and GTCCRF. */ + compare_match = p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRD + pin]; + } + else + { + /* In TIMER_MODE_TRIANGLE_WAVE_ASYMMETRIC_PWM and TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM, the trough compare match value is + * set in GTCCRC, and GTCCRE. */ + compare_match = p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRC + pin]; + } + + timer_direction_t count_direction = (timer_direction_t) p_instance_ctrl->p_reg->GTST_b.TUCF; + + /* In Triangle-wave mode, do not change the settings for the delay while the counter if going down and the compare-match + * value is less than or equal to 2. */ + FSP_ERROR_RETURN(TIMER_DIRECTION_DOWN != count_direction || 2 < compare_match, FSP_ERR_INVALID_STATE); + } + #endif + + FSP_CRITICAL_SECTION_DEFINE; + + if (GPT_PWM_OUTPUT_DELAY_SETTING_BYPASS == delay_setting) + { + /* Enter a critical section in order to ensure that multiple GPT channels don't access the common + * register simultaneously. */ + FSP_CRITICAL_SECTION_ENTER; + + #if GPT_CFG_WRITE_PROTECT_ENABLE + + /* GTDLYCR2 is protected by R_GPT::GTWP. */ + uint32_t wp = R_GPT0->GTWP; + R_GPT0->GTWP = GPT_PRV_GTWP_RESET_VALUE; + R_GPT0->GTWP; + #endif + + /* Enable the Delay Generation Circuit bypass. */ + R_GPT_ODC->GTDLYCR2 &= (uint16_t) (~p_instance_ctrl->channel_mask & UINT16_MAX); + + #if GPT_CFG_WRITE_PROTECT_ENABLE + + /* Restore the previous value of GTWP. */ + R_GPT0->GTWP = wp | GPT_PRV_GTWP_RESET_VALUE; + #endif + + FSP_CRITICAL_SECTION_EXIT; + } + else + { + /* Calculate the offset for the register than needs to be set. */ + uint32_t channel_offset = sizeof(uint32_t) * p_instance_ctrl->p_cfg->channel; + uint32_t pin_offset = + (uint32_t) ((uint32_t) &R_GPT_ODC->GTDLYR[0].B - (uint32_t) &R_GPT_ODC->GTDLYR[0].A) * pin; + uint32_t edge_offset = + (uint32_t) ((uint32_t) &R_GPT_ODC->GTDLYF[0].A - (uint32_t) &R_GPT_ODC->GTDLYR[0].A) * edge; + uint16_t * p_gtdlyfnx = + (uint16_t *) ((uint32_t) &R_GPT_ODC->GTDLYR[0].A + channel_offset + pin_offset + edge_offset); + + /* Unprotect the delay setting register. */ + uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl); + + /* Write the delay setting to the register. */ + *p_gtdlyfnx = (uint16_t) delay_setting; + + /* Restore the previous value of GTWP. */ + r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE); + + /* Check if the channel has already been enabled. */ + if (0U == (R_GPT_ODC->GTDLYCR2 & p_instance_ctrl->channel_mask)) + { + /* Enter a critical section in order to ensure that multiple GPT channels don't access the common + * register simultaneously. */ + FSP_CRITICAL_SECTION_ENTER; + + #if GPT_CFG_WRITE_PROTECT_ENABLE + + /* GTDLYCR2 is protected by R_GPT::GTWP. */ + wp = R_GPT0->GTWP; + R_GPT0->GTWP = GPT_PRV_GTWP_RESET_VALUE; + R_GPT0->GTWP; + #endif + + /* Disable the Delay Generation Circuit bypass. */ + R_GPT_ODC->GTDLYCR2 |= (uint16_t) p_instance_ctrl->channel_mask; + + #if GPT_CFG_WRITE_PROTECT_ENABLE + + /* Restore the previous value of GTWP. */ + R_GPT0->GTWP = wp | GPT_PRV_GTWP_RESET_VALUE; + #endif + + FSP_CRITICAL_SECTION_EXIT; + } + } + + return FSP_SUCCESS; +#else + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(edge); + FSP_PARAMETER_NOT_USED(delay_setting); + FSP_PARAMETER_NOT_USED(pin); + + return FSP_ERR_UNSUPPORTED; +#endif +} + +/*******************************************************************************************************************//** + * Updates the user callback with the option to provide memory for the callback argument structure. + * Implements @ref timer_api_t::callbackSet. + * + * @retval FSP_SUCCESS Callback updated successfully. + * @retval FSP_ERR_ASSERTION A required pointer is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + * @retval FSP_ERR_NO_CALLBACK_MEMORY p_callback is non-secure and p_callback_memory is either secure or NULL. + **********************************************************************************************************************/ +fsp_err_t R_GPT_CallbackSet (timer_ctrl_t * const p_api_ctrl, + void ( * p_callback)(timer_callback_args_t *), + void const * const p_context, + timer_callback_args_t * const p_callback_memory) +{ + gpt_instance_ctrl_t * p_ctrl = (gpt_instance_ctrl_t *) p_api_ctrl; + +#if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(GPT_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + +#if BSP_TZ_SECURE_BUILD + + /* Get security state of p_callback */ + bool callback_is_secure = + (NULL == cmse_check_address_range((void *) p_callback, sizeof(void *), CMSE_AU_NONSECURE)); + + #if GPT_CFG_PARAM_CHECKING_ENABLE + + /* In secure projects, p_callback_memory must be provided in non-secure space if p_callback is non-secure */ + timer_callback_args_t * const p_callback_memory_checked = cmse_check_pointed_object(p_callback_memory, + CMSE_AU_NONSECURE); + FSP_ERROR_RETURN(callback_is_secure || (NULL != p_callback_memory_checked), FSP_ERR_NO_CALLBACK_MEMORY); + #endif +#endif + + /* Store callback and context */ +#if BSP_TZ_SECURE_BUILD + p_ctrl->p_callback = callback_is_secure ? p_callback : + (void (*)(timer_callback_args_t *))cmse_nsfptr_create(p_callback); +#else + p_ctrl->p_callback = p_callback; +#endif + p_ctrl->p_context = p_context; + p_ctrl->p_callback_memory = p_callback_memory; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Stops counter, disables output pins, and clears internal driver data. Implements @ref timer_api_t::close. + * + * @retval FSP_SUCCESS Successful close. + * @retval FSP_ERR_ASSERTION p_ctrl was NULL. + * @retval FSP_ERR_NOT_OPEN The instance is not opened. + **********************************************************************************************************************/ +fsp_err_t R_GPT_Close (timer_ctrl_t * const p_ctrl) +{ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) p_ctrl; + fsp_err_t err = FSP_SUCCESS; + +#if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(GPT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + /* Disable interrupts. */ + gpt_extended_cfg_t * p_extend = (gpt_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + r_gpt_disable_irq(p_instance_ctrl->p_cfg->cycle_end_irq); + r_gpt_disable_irq(p_extend->capture_a_irq); + r_gpt_disable_irq(p_extend->capture_b_irq); +#if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE + gpt_extended_pwm_cfg_t const * p_pwm_cfg = p_extend->p_pwm_cfg; + if (NULL != p_pwm_cfg) + { + r_gpt_disable_irq(p_pwm_cfg->trough_irq); + } +#endif + + /* Clear open flag. */ + p_instance_ctrl->open = 0U; + + uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl); + + /* Stop counter. */ + p_instance_ctrl->p_reg->GTSTP = p_instance_ctrl->channel_mask; + + /* Disable output. */ + p_instance_ctrl->p_reg->GTIOR = 0U; + + r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE); + + return err; +} + +/*******************************************************************************************************************//** + * Initialize the PWM Delay Generation Circuit (PDG). + * This function must be called before calling @ref R_GPT_PwmOutputDelaySet. + * + * @note This function will delay for 20 microseconds. + * + * @retval FSP_SUCCESS Initialization sequence completed successfully. + * @retval FSP_ERR_INVALID_STATE The source clock frequnecy is out of the required range for the PDG. + * @retval FSP_ERR_UNSUPPORTED This feature is not supported. + **********************************************************************************************************************/ +fsp_err_t R_GPT_PwmOutputDelayInitialize () +{ +#if 0U != BSP_FEATURE_GPT_ODC_VALID_CHANNEL_MASK && GPT_CFG_OUTPUT_SUPPORT_ENABLE + #if BSP_FEATURE_GPT_ODC_FRANGE_FREQ_MIN > 0 || GPT_CFG_PARAM_CHECKING_ENABLE + #if BSP_FEATURE_BSP_HAS_GPT_CLOCK && BSP_CFG_GPT_CLOCK_BYPASS == 0 + + /* Calculate the GPTCK Divider. */ + uint32_t divider = R_SYSTEM->GPTCKDIVCR; + + if (0U == divider) + { + divider = 1U; + } + else + { + divider *= 2U; + } + + /* Calculate the GPTCK Frequency. */ + uint32_t gpt_frequency = R_BSP_SourceClockHzGet((fsp_priv_source_clock_t) R_SYSTEM->GPTCKCR_b.GPTCKSEL) / divider; + #else + + /* Calculate the PCLKD Frequency. */ + uint32_t gpt_frequency = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKD); + #endif + #endif + + #if GPT_CFG_PARAM_CHECKING_ENABLE + FSP_ERROR_RETURN(BSP_FEATURE_GPT_ODC_FREQ_MAX >= gpt_frequency, FSP_ERR_INVALID_STATE); + FSP_ERROR_RETURN(BSP_FEATURE_GPT_ODC_FREQ_MIN <= gpt_frequency, FSP_ERR_INVALID_STATE); + #endif + + uint32_t gtdlycr1 = R_GPT_ODC_GTDLYCR1_DLYRST_Msk; + + #if BSP_FEATURE_GPT_ODC_FRANGE_FREQ_MIN > 0 + if (BSP_FEATURE_GPT_ODC_FRANGE_FREQ_MIN >= gpt_frequency) + { + gtdlycr1 |= R_GPT_ODC_GTDLYCR1_FRANGE_Msk; + } + #endif + + #if BSP_FEATURE_BSP_HAS_GPT_CLOCK && GPT_CFG_GPTCLK_BYPASS + + /* Bypass the GPTCLK. GPT instances will use PCLKD as the GPT Core clock. */ + R_GPT_GTCLK->GTCLKCR = 1U; + #endif + + /* Cancel the module-stop state for the PDG. */ + R_BSP_MODULE_START(FSP_IP_GPT, 0); + + #if GPT_CFG_WRITE_PROTECT_ENABLE + + /* Disable write protection for GPT registers if they are protected. */ + R_GPT0->GTWP = GPT_PRV_GTWP_RESET_VALUE; + R_GPT0->GTWP; + #endif + + /* Reset the PWM Delay Generation Circuit. */ + R_GPT_ODC->GTDLYCR1 = (uint16_t) gtdlycr1; + R_GPT_ODC->GTDLYCR2 = 0; + + /* Enable the DLL. */ + R_GPT_ODC->GTDLYCR1 = (uint16_t) (gtdlycr1 | R_GPT_ODC_GTDLYCR1_DLLEN_Msk); + + /* Wait for the DLL to be enabled. */ + R_BSP_SoftwareDelay(20, BSP_DELAY_UNITS_MICROSECONDS); + + /* Release the PWM Delay Generation Circuit from reset. */ + R_GPT_ODC->GTDLYCR1 &= (uint16_t) ~R_GPT_ODC_GTDLYCR1_DLYRST_Msk; + + #if GPT_CFG_WRITE_PROTECT_ENABLE + + /* Re-enable write protection for GPT registers. */ + R_GPT0->GTWP = GPT_PRV_GTWP_WRITE_PROTECT; + #endif + + return FSP_SUCCESS; +#else + + return FSP_ERR_UNSUPPORTED; +#endif +} + +/** @} (end addtogroup GPT) */ + +/*******************************************************************************************************************//** + * Private Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Enables write protection. + * + * @param[in] p_instance_ctrl Instance control block. + * @param[in] write_protect_setting The value of GTWP prior to being cleared. + **********************************************************************************************************************/ +static inline void r_gpt_write_protect_enable (gpt_instance_ctrl_t * const p_instance_ctrl, + uint32_t write_protect_setting) +{ +#if GPT_CFG_WRITE_PROTECT_ENABLE + p_instance_ctrl->p_reg->GTWP = write_protect_setting; +#else + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + FSP_PARAMETER_NOT_USED(write_protect_setting); +#endif +} + +/*******************************************************************************************************************//** + * Disables write protection. + * + * @param[in] p_instance_ctrl Instance control block. + **********************************************************************************************************************/ +static inline uint32_t r_gpt_write_protect_disable (gpt_instance_ctrl_t * const p_instance_ctrl) +{ +#if GPT_CFG_WRITE_PROTECT_ENABLE + uint32_t write_protect_setting = p_instance_ctrl->p_reg->GTWP; + p_instance_ctrl->p_reg->GTWP = GPT_PRV_GTWP_RESET_VALUE; + + return write_protect_setting; +#else + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + + return 0U; +#endif +} + +/*******************************************************************************************************************//** + * Initializes control structure based on configuration. + * + * @param[in] p_instance_ctrl Instance control block. + * @param[in] p_cfg Pointer to timer configuration. + **********************************************************************************************************************/ +static void gpt_common_open (gpt_instance_ctrl_t * const p_instance_ctrl, timer_cfg_t const * const p_cfg) +{ + /* Initialize control structure. */ + p_instance_ctrl->p_cfg = p_cfg; + + /* If callback is not null or timer mode is one shot, make sure the IRQ is enabled and store callback in the + * control block. + * @note The GPT hardware does not support one-shot mode natively. To support one-shot mode, the timer will be + * stopped and cleared using software in the ISR. *//* Determine if this is a 32-bit or a 16-bit timer. */ + p_instance_ctrl->variant = TIMER_VARIANT_16_BIT; + if (0U != (p_instance_ctrl->channel_mask & BSP_FEATURE_GPT_32BIT_CHANNEL_MASK)) + { + p_instance_ctrl->variant = TIMER_VARIANT_32_BIT; + } + + /* Save register base address. */ + uint32_t base_address = (uint32_t) R_GPT0 + (p_cfg->channel * ((uint32_t) R_GPT1 - (uint32_t) R_GPT0)); + p_instance_ctrl->p_reg = (R_GPT0_Type *) base_address; + + /* Set callback and context pointers, if configured */ + p_instance_ctrl->p_callback = p_cfg->p_callback; + p_instance_ctrl->p_context = p_cfg->p_context; + p_instance_ctrl->p_callback_memory = NULL; +} + +/*******************************************************************************************************************//** + * Performs hardware initialization of the GPT. + * + * @param[in] p_instance_ctrl Instance control block. + * @param[in] p_cfg Pointer to timer configuration. + **********************************************************************************************************************/ +static void gpt_hardware_initialize (gpt_instance_ctrl_t * const p_instance_ctrl, timer_cfg_t const * const p_cfg) +{ + /* Save pointer to extended configuration structure. */ + gpt_extended_cfg_t * p_extend = (gpt_extended_cfg_t *) p_cfg->p_extend; + +#if BSP_FEATURE_BSP_HAS_GPT_CLOCK && GPT_CFG_GPTCLK_BYPASS + + /* Bypass the GPTCLK. GPT instances will use PCLKD as the GPT Core clock. */ + R_GPT_GTCLK->GTCLKCR = 1U; +#endif + + /* Power on GPT before setting any hardware registers. Make sure the counter is stopped before setting mode + * register, PCLK divisor register, and counter register. */ + R_BSP_MODULE_START(FSP_IP_GPT, p_cfg->channel); + +#if GPT_CFG_OUTPUT_SUPPORT_ENABLE + if (0U != (BSP_FEATURE_GPT_ODC_VALID_CHANNEL_MASK & p_instance_ctrl->channel_mask)) + { + /* Enter a critical section in order to ensure that multiple GPT channels don't access the common + * register simultaneously. */ + FSP_CRITICAL_SECTION_DEFINE; + FSP_CRITICAL_SECTION_ENTER; + + #if GPT_CFG_WRITE_PROTECT_ENABLE + + /* Disable write protection for GPT registers if they are protected. */ + uint32_t wp = R_GPT0->GTWP; + R_GPT0->GTWP = GPT_PRV_GTWP_RESET_VALUE; + R_GPT0->GTWP; + #endif + + /* Enable the Delay Generation Circuit bypass. */ + R_GPT_ODC->GTDLYCR2 &= (uint16_t) (~p_instance_ctrl->channel_mask & UINT16_MAX); + + #if GPT_CFG_WRITE_PROTECT_ENABLE + R_GPT0->GTWP = wp | GPT_PRV_GTWP_RESET_VALUE; + #endif + + FSP_CRITICAL_SECTION_EXIT; + } +#endif + + /* Initialize all registers that may affect operation of this driver to reset values. Skip these since they + * affect all channels, and are initialized in GTCR and GTCNT: GTSTR, GTSTP, GTCLR. GTCR is set immediately after + * clearing the module stop bit to ensure the timer is stopped before proceeding with configuration. */ + p_instance_ctrl->p_reg->GTWP = GPT_PRV_GTWP_RESET_VALUE; + p_instance_ctrl->p_reg->GTCR = 0U; + p_instance_ctrl->p_reg->GTST = 0U; + p_instance_ctrl->p_reg->GTCNT = 0U; + + /* GTPR, GTCCRn, GTIOR, GTSSR, GTPSR, GTCSR, GTUPSR, GTDNSR, GTPBR, and GTUDDTYC are set by this driver. */ + + /* Initialization sets all register required for up counting as described in hardware manual (Figure 23.4 in the + * RA6M3 manual R01UH0886EJ0100) and other registers required by the driver. */ + + /* Dividers for GPT are half the enum value. */ + uint32_t gtcr_tpcs = p_cfg->source_div; + uint32_t gtcr = gtcr_tpcs << R_GPT0_GTCR_TPCS_Pos; + + /* Store period register setting. The actual period and is one cycle longer than the register value for saw waves + * and twice the register value for triangle waves. Reference section 23.2.21 "General PWM Timer Cycle Setting + * Register (GTPR)". The setting passed to the configuration is expected to be half the desired period for + * triangle waves. */ + uint32_t gtpr = p_cfg->period_counts - 1U; +#if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE + + /* Saw-wave PWM mode is set in GTCR.MD for all modes except TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM and + * TIMER_MODE_TRIANGLE_WAVE_ASYMMETRIC_PWM. */ + if (p_cfg->mode >= TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM) + { + gtcr |= ((uint32_t) p_cfg->mode << R_GPT0_GTCR_MD_Pos); + gtpr = p_cfg->period_counts; + } +#endif + + /* Counter must be stopped to update TPCS. Reference section 23.2.12 "General PWM Timer Control Register (GTCR)" + * in the RA6M3 manual R01UH0886EJ0100. */ + p_instance_ctrl->p_reg->GTCR = gtcr; + + gpt_hardware_events_disable(p_instance_ctrl); + + /* Configure the up/down count sources. These are not affected by enable/disable. */ + p_instance_ctrl->p_reg->GTUPSR = p_extend->count_up_source; + p_instance_ctrl->p_reg->GTDNSR = p_extend->count_down_source; + + /* Set period. The actual period is one cycle longer than the register value. Reference section 23.2.21 + * "General PWM Timer Cycle Setting Register (GTPR)". */ + p_instance_ctrl->p_reg->GTPBR = gtpr; + p_instance_ctrl->p_reg->GTPR = gtpr; + + uint32_t gtuddtyc = 0U; + uint32_t gtior = p_extend->gtior_setting.gtior; + +#if GPT_CFG_OUTPUT_SUPPORT_ENABLE + + /* For one shot mode, the compare match buffer register must be loaded with a value that exceeds the timer + * cycle end value so that second compare match event would never occur and hence there will be only a + * single pulse. Writing to the upper bits is ignored for 16-bit timers. */ + gpt_prv_duty_registers_t duty_regs = {UINT32_MAX, 0}; + + if (TIMER_MODE_PERIODIC == p_cfg->mode) + { + /* The GTIOCA/GTIOCB pins transition 1 cycle after compare match when buffer operation is used. Reference + * Figure 23.34 "Example setting for saw-wave PWM mode" in the RA6M3 manual R01UH0886EJ0100. To get a duty cycle + * as close to 50% as possible, duty cycle (register) = (period (counts) / 2) - 1. */ + uint32_t duty_cycle_50_percent = (p_cfg->period_counts >> 1) - 1U; + duty_regs.gtccr_buffer = duty_cycle_50_percent; + } + + if (p_cfg->mode >= TIMER_MODE_PWM) + { + gpt_calculate_duty_cycle(p_instance_ctrl, p_cfg->duty_cycle_counts, &duty_regs, GPT_IO_PIN_GTIOCA); + } + + /* Set the compare match and compare match buffer registers based on previously calculated values. */ + p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRC] = duty_regs.gtccr_buffer; + p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRE] = duty_regs.gtccr_buffer; + + /* If the requested duty cycle is 0% or 100%, set this in the registers. */ + gtuddtyc |= duty_regs.omdty << R_GPT0_GTUDDTYC_OADTY_Pos; + gtuddtyc |= duty_regs.omdty << R_GPT0_GTUDDTYC_OBDTY_Pos; + + /* Check if custom GTIOR settings are provided. */ + if (0 == p_extend->gtior_setting.gtior) + { + /* If custom GTIOR settings are not provided, calculate GTIOR. */ + if (p_extend->gtioca.output_enabled) + { + uint32_t gtioca_gtior = gpt_gtior_calculate(p_cfg, p_extend->gtioca.stop_level); + gtior |= gtioca_gtior << R_GPT0_GTIOR_GTIOA_Pos; + } + + if (p_extend->gtiocb.output_enabled) + { + uint32_t gtiocb_gtior = gpt_gtior_calculate(p_cfg, p_extend->gtiocb.stop_level); + gtior |= gtiocb_gtior << R_GPT0_GTIOR_GTIOB_Pos; + } + } +#endif + +#if GPT_PRV_GPTE_OR_GPTEH_CHANNEL_MASK + if ((1U << p_cfg->channel) & GPT_PRV_GPTE_OR_GPTEH_CHANNEL_MASK) + { + /* This register is available on GPTE and GPTEH only. It must be cleared before setting. When modifying the + * IVTT[2:0] bits, first set the IVTC[1:0] bits to 00b. Reference section 23.2.18 "General PWM Timer Interrupt + * and A/D Converter Start Request Skipping Setting Register (GTITC)"" of the RA6M3 manual R01UH0886EJ0100. */ + p_instance_ctrl->p_reg->GTITC = 0U; + } +#endif + +#if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE + gpt_extended_pwm_cfg_t const * p_pwm_cfg = p_extend->p_pwm_cfg; + if (NULL != p_pwm_cfg) + { + p_instance_ctrl->p_reg->GTINTAD = ((uint32_t) p_pwm_cfg->output_disable << R_GPT0_GTINTAD_GRPDTE_Pos) | + ((uint32_t) p_pwm_cfg->poeg_link << R_GPT0_GTINTAD_GRP_Pos) | + ((uint32_t) p_pwm_cfg->adc_trigger << R_GPT0_GTINTAD_ADTRAUEN_Pos); + p_instance_ctrl->p_reg->GTDVU = p_pwm_cfg->dead_time_count_up; + + /* Set GTDTCR.TDE only if one of the dead time values is non-zero. */ + uint32_t gtdtcr = + ((p_pwm_cfg->dead_time_count_up > 0) || (p_pwm_cfg->dead_time_count_down > 0)); + + #if GPT_PRV_GPTE_OR_GPTEH_CHANNEL_MASK + if ((1U << p_cfg->channel) & GPT_PRV_GPTE_OR_GPTEH_CHANNEL_MASK) + { + /* These registers are only available on GPTE and GPTEH. */ + p_instance_ctrl->p_reg->GTITC = ((uint32_t) p_pwm_cfg->interrupt_skip_source << R_GPT0_GTITC_IVTC_Pos) | + ((uint32_t) p_pwm_cfg->interrupt_skip_count << R_GPT0_GTITC_IVTT_Pos) | + ((uint32_t) p_pwm_cfg->interrupt_skip_adc << R_GPT0_GTITC_ADTAL_Pos); + p_instance_ctrl->p_reg->GTDVD = p_pwm_cfg->dead_time_count_down; + p_instance_ctrl->p_reg->GTADTRA = p_pwm_cfg->adc_a_compare_match; + p_instance_ctrl->p_reg->GTADTRB = p_pwm_cfg->adc_b_compare_match; + } + #endif + + /* Check if custom GTIOR settings are provided. */ + if (0 == p_extend->gtior_setting.gtior) + { + /* If custom GTIOR settings are not provided, set gtioca_disable_settings and gtiocb_disable_settings. */ + gtior |= (uint32_t) (p_pwm_cfg->gtioca_disable_setting << R_GPT0_GTIOR_OADF_Pos); + gtior |= (uint32_t) (p_pwm_cfg->gtiocb_disable_setting << R_GPT0_GTIOR_OBDF_Pos); + } + + p_instance_ctrl->p_reg->GTDTCR = gtdtcr; + } + else +#endif + { + /* GTADTR* registers are unused if GTINTAD is cleared. */ + p_instance_ctrl->p_reg->GTINTAD = 0U; + p_instance_ctrl->p_reg->GTDTCR = 0U; + + /* GTDVU, GTDVD, GTDBU, GTDBD, and GTSOTR are not used if GTDTCR is cleared. */ + } + + /* Check if custom GTIOR settings are provided. */ + if (0 == p_extend->gtior_setting.gtior) + { + /* + * If custom GTIOR settings are not provided, configure the noise filter for + * the GTIOC pins. + */ + gtior |= (uint32_t) (p_extend->capture_filter_gtioca << R_GPT0_GTIOR_NFAEN_Pos); + gtior |= (uint32_t) (p_extend->capture_filter_gtiocb << R_GPT0_GTIOR_NFBEN_Pos); + } + + /* Enable the compare match buffer. */ + p_instance_ctrl->p_reg->GTBER = GPT_PRV_GTBER_BUFFER_ENABLE_FORCE_TRANSFER; + +#if GPT_CFG_OUTPUT_SUPPORT_ENABLE + if (TIMER_MODE_ONE_SHOT == p_cfg->mode) + { + /* In one shot mode, the output pin toggles when counting starts, then again when the period expires. + * The buffer is enabled to set the compare match to UINT32_MAX after the one shot pulse is output + * so that the pin level will not change if the period expires again before the timer is stopped in + * the interrupt.*/ + p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRA] = 0U; + p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRB] = 0U; + } +#endif + + /* Reset counter to 0. */ + p_instance_ctrl->p_reg->GTCLR = p_instance_ctrl->channel_mask; + + /* Set the I/O control register. */ + p_instance_ctrl->p_reg->GTIOR = gtior; + + /* Configure duty cycle and force timer to count up. GTUDDTYC must be set, then cleared to force the count + * direction to be reflected when counting starts. Reference section 23.2.13 "General PWM Timer Count Direction + * and Duty Setting Register (GTUDDTYC)" in the RA6M3 manual R01UH0886EJ0100. */ + p_instance_ctrl->p_reg->GTUDDTYC = gtuddtyc | 3U; + p_instance_ctrl->p_reg->GTUDDTYC = gtuddtyc | 1U; + + r_gpt_write_protect_enable(p_instance_ctrl, GPT_PRV_GTWP_WRITE_PROTECT); + + /* Enable CPU interrupts if callback is not null. Also enable interrupts for one shot mode. + * @note The GPT hardware does not support one-shot mode natively. To support one-shot mode, the timer will be + * stopped and cleared using software in the ISR. */ + r_gpt_enable_irq(p_cfg->cycle_end_irq, p_cfg->cycle_end_ipl, p_instance_ctrl); + r_gpt_enable_irq(p_extend->capture_a_irq, p_extend->capture_a_ipl, p_instance_ctrl); + r_gpt_enable_irq(p_extend->capture_b_irq, p_extend->capture_b_ipl, p_instance_ctrl); +#if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE + if (NULL != p_pwm_cfg) + { + r_gpt_enable_irq(p_pwm_cfg->trough_irq, p_pwm_cfg->trough_ipl, p_instance_ctrl); + } +#endif +} + +/*******************************************************************************************************************//** + * Disables hardware events that would cause the timer to start, stop, clear, or capture. + * + * @param[in] p_instance_ctrl Instance control structure + **********************************************************************************************************************/ +static void gpt_hardware_events_disable (gpt_instance_ctrl_t * p_instance_ctrl) +{ + /* Enable use of GTSTR, GTSTP, and GTCLR for this channel. */ + p_instance_ctrl->p_reg->GTSSR = GPT_PRV_ENABLE_GROUP_SOFTWARE_UPDATE; + p_instance_ctrl->p_reg->GTPSR = GPT_PRV_ENABLE_GROUP_SOFTWARE_UPDATE; + p_instance_ctrl->p_reg->GTCSR = GPT_PRV_ENABLE_GROUP_SOFTWARE_UPDATE; + p_instance_ctrl->p_reg->GTICASR = GPT_SOURCE_NONE; + p_instance_ctrl->p_reg->GTICBSR = GPT_SOURCE_NONE; +} + +/*******************************************************************************************************************//** + * Disables interrupt if it is a valid vector number. + * + * @param[in] irq Interrupt number + **********************************************************************************************************************/ +static void r_gpt_disable_irq (IRQn_Type irq) +{ + /* Disable interrupts. */ + if (irq >= 0) + { + R_BSP_IrqDisable(irq); + R_FSP_IsrContextSet(irq, NULL); + } +} + +/*******************************************************************************************************************//** + * Configures and enables interrupt if it is a valid vector number. + * + * @param[in] irq Interrupt number + * @param[in] priority NVIC priority of the interrupt + * @param[in] p_context The interrupt context is a pointer to data required in the ISR. + **********************************************************************************************************************/ +static void r_gpt_enable_irq (IRQn_Type const irq, uint32_t priority, void * p_context) +{ + if (irq >= 0) + { + R_BSP_IrqCfgEnable(irq, priority, p_context); + } +} + +#if GPT_CFG_OUTPUT_SUPPORT_ENABLE + +/*******************************************************************************************************************//** + * Calculates duty cycle register values. GTPR must be set before entering this function. + * + * @param[in] p_instance_ctrl Instance control structure + * @param[in] duty_cycle_counts Duty cycle to set + * @param[out] p_duty_reg Duty cycle register values + **********************************************************************************************************************/ +static void gpt_calculate_duty_cycle (gpt_instance_ctrl_t * const p_instance_ctrl, + uint32_t const duty_cycle_counts, + gpt_prv_duty_registers_t * p_duty_reg, + uint32_t pin) +{ + /* Determine the current period. The actual period is one cycle longer than the register value for saw waves + * and twice the register value for triangle waves. Reference section 23.2.21 "General PWM Timer Cycle Setting + * Register (GTPR)". The setting passed to the configuration is expected to be half the desired duty cycle for + * triangle waves. */ + uint32_t current_period = p_instance_ctrl->p_reg->GTPR; + #if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE + if (p_instance_ctrl->p_cfg->mode < TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM) + #endif + { + current_period++; + } + + bool duty_zero = (0U == duty_cycle_counts); + bool duty_high = (duty_cycle_counts >= current_period); + + if (duty_zero || duty_high) + { + uint32_t gtior; + + if (!(GPT_IO_PIN_GTIOCB & pin)) + { + gtior = p_instance_ctrl->p_reg->GTIOR_b.GTIOA; + } + else + { + gtior = p_instance_ctrl->p_reg->GTIOR_b.GTIOB; + } + + bool first_level_low; + + if (p_instance_ctrl->p_cfg->mode >= TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM) + { + /* In triangle PWM modes use the initial pin level to determine 0%/100% setting. */ + first_level_low = !(gtior & 0x10); + } + else + { + /* In normal PWM mode use the cycle end setting to determine 0%/100% setting */ + first_level_low = (gtior & 0xC) == 0x4; + } + + if ((duty_zero && !first_level_low) || (duty_high && first_level_low)) + { + p_duty_reg->omdty = GPT_DUTY_CYCLE_MODE_0_PERCENT; + } + else + { + p_duty_reg->omdty = GPT_DUTY_CYCLE_MODE_100_PERCENT; + } + } + else + { + uint32_t temp_duty_cycle = duty_cycle_counts; + + #if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE + if (p_instance_ctrl->p_cfg->mode >= TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM) + { + p_duty_reg->gtccr_buffer = temp_duty_cycle; + } + else + #endif + { + /* The GTIOCA/GTIOCB pins transition 1 cycle after compare match when buffer operation is used. Reference + * Figure 23.34 "Example setting for saw-wave PWM mode" in the RA6M3 manual R01UH0886EJ0100. */ + temp_duty_cycle--; + p_duty_reg->gtccr_buffer = temp_duty_cycle; + } + } +} + +#endif + +/*******************************************************************************************************************//** + * Calculates clock frequency of GPT counter. Divides GPT clock by GPT clock divisor. + * + * @param[in] p_instance_ctrl Instance control block + * + * @return Clock frequency of the GPT counter. + **********************************************************************************************************************/ +static uint32_t gpt_clock_frequency_get (gpt_instance_ctrl_t * const p_instance_ctrl) +{ + /* Look up PCLKD frequency and divide it by GPT PCLKD divider. */ + timer_source_div_t pclk_divisor = (timer_source_div_t) (p_instance_ctrl->p_reg->GTCR_b.TPCS); + uint32_t pclk_freq_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKD); + + return pclk_freq_hz >> pclk_divisor; +} + +#if GPT_CFG_OUTPUT_SUPPORT_ENABLE + +/*******************************************************************************************************************//** + * Calculates GTIOR settings for given mode and stop level. + * + * @param[in] p_instance_ctrl Instance control block + * @param[in] p_cfg Timer configuration + * @param[in] level Output level after timer stops + **********************************************************************************************************************/ +static uint32_t gpt_gtior_calculate (timer_cfg_t const * const p_cfg, gpt_pin_level_t const stop_level) +{ + /* The stop level is used as both the initial level and the stop level. */ + uint32_t gtior = R_GPT0_GTIOR_OAE_Msk | ((uint32_t) stop_level << R_GPT0_GTIOR_OADFLT_Pos) | + ((uint32_t) stop_level << GPT_PRV_GTIOR_INITIAL_LEVEL_BIT); + + uint32_t gtion = GPT_PRV_GTIO_LOW_COMPARE_MATCH_HIGH_CYCLE_END; + + if (TIMER_MODE_PWM == p_cfg->mode) + { + /* Use default: GTIOn is high at cycle end, then low at compare match. */ + } + + #if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE + else if (p_cfg->mode >= TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM) + { + gtion = GPT_PRV_GTIO_TOGGLE_COMPARE_MATCH; + } + #endif + else + { + /* In one-shot mode, the output pin goes high after the first compare match (one cycle after the timer starts counting). */ + if (GPT_PIN_LEVEL_LOW == stop_level) + { + gtion = GPT_PRV_GTIO_HIGH_COMPARE_MATCH_LOW_CYCLE_END; + } + } + + gtior |= gtion; + + return gtior; +} + +#endif + +/*******************************************************************************************************************//** + * Calls user callback. + * + * @param[in] p_ctrl Pointer to GPT instance control block + * @param[in] event Event code + * @param[in] capture Event capture counts (if applicable) + **********************************************************************************************************************/ +static void r_gpt_call_callback (gpt_instance_ctrl_t * p_ctrl, timer_event_t event, uint32_t capture) +{ + timer_callback_args_t args; + + /* Store callback arguments in memory provided by user if available. This allows callback arguments to be + * stored in non-secure memory so they can be accessed by a non-secure callback function. */ + timer_callback_args_t * p_args = p_ctrl->p_callback_memory; + if (NULL == p_args) + { + /* Store on stack */ + p_args = &args; + } + else + { + /* Save current arguments on the stack in case this is a nested interrupt. */ + args = *p_args; + } + + p_args->event = event; + p_args->capture = capture; + p_args->p_context = p_ctrl->p_context; + +#if BSP_TZ_SECURE_BUILD + + /* p_callback can point to a secure function or a non-secure function. */ + if (!cmse_is_nsfptr(p_ctrl->p_callback)) + { + /* If p_callback is secure, then the project does not need to change security state. */ + p_ctrl->p_callback(p_args); + } + else + { + /* If p_callback is Non-secure, then the project must change to Non-secure state in order to call the callback. */ + gpt_prv_ns_callback p_callback = (gpt_prv_ns_callback) (p_ctrl->p_callback); + p_callback(p_args); + } + +#else + + /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the callback. */ + p_ctrl->p_callback(p_args); +#endif + + if (NULL != p_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_ctrl->p_callback_memory = args; + } +} + +/*******************************************************************************************************************//** + * Common processing for input capture interrupt. + * + * @param[in] event Which input capture event occurred + **********************************************************************************************************************/ +static void r_gpt_capture_common_isr (gpt_prv_capture_event_t event) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + + /* Clear pending IRQ to make sure it doesn't fire again after exiting */ + R_BSP_IrqStatusClear(irq); + + /* Recover ISR context saved in open. */ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + + /* Get captured value. */ + uint32_t counter = p_instance_ctrl->p_reg->GTCCR[event]; + + /* If we captured a one-shot pulse, then disable future captures. */ + if (TIMER_MODE_ONE_SHOT == p_instance_ctrl->p_cfg->mode) + { + /* Disable captures. */ + gpt_hardware_events_disable(p_instance_ctrl); + + /* Clear pending interrupt to make sure it doesn't fire again if another overflow has already occurred. */ + R_BSP_IrqClearPending(irq); + } + + /* If a callback is provided, then call it with the captured counter value. */ + if (NULL != p_instance_ctrl->p_callback) + { + r_gpt_call_callback(p_instance_ctrl, + (timer_event_t) ((uint32_t) TIMER_EVENT_CAPTURE_A + (uint32_t) event), + counter); + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE +} + +/*******************************************************************************************************************//** + * Stops the timer if one-shot mode, clears interrupts, and calls callback if one was provided in the open function. + **********************************************************************************************************************/ +void gpt_counter_overflow_isr (void) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + + /* Clear pending IRQ to make sure it doesn't fire again after exiting */ + R_BSP_IrqStatusClear(irq); + + /* Recover ISR context saved in open. */ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + + /* If one-shot mode is selected, stop the timer since period has expired. */ + if (TIMER_MODE_ONE_SHOT == p_instance_ctrl->p_cfg->mode) + { + uint32_t wp = r_gpt_write_protect_disable(p_instance_ctrl); + + p_instance_ctrl->p_reg->GTSTP = p_instance_ctrl->channel_mask; + + /* Clear the GPT counter and the overflow flag after the one shot pulse has being generated */ + p_instance_ctrl->p_reg->GTCNT = 0; + p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRA] = 0; + p_instance_ctrl->p_reg->GTCCR[GPT_PRV_GTCCRB] = 0; + + r_gpt_write_protect_enable(p_instance_ctrl, wp | GPT_PRV_GTWP_RESET_VALUE); + + /* Clear pending interrupt to make sure it doesn't fire again if another overflow has already occurred. */ + R_BSP_IrqClearPending(irq); + } + + if (NULL != p_instance_ctrl->p_callback) + { + r_gpt_call_callback(p_instance_ctrl, TIMER_EVENT_CYCLE_END, 0); + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; +} + +#if GPT_PRV_EXTRA_FEATURES_ENABLED == GPT_CFG_OUTPUT_SUPPORT_ENABLE + +/*******************************************************************************************************************//** + * Only supported for asymmetric triangle-wave PWM. Notifies application of trough event. + **********************************************************************************************************************/ +void gpt_counter_underflow_isr (void) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + + /* Clear pending IRQ to make sure it doesn't fire again after exiting */ + R_BSP_IrqStatusClear(irq); + + /* Recover ISR context saved in open. */ + gpt_instance_ctrl_t * p_instance_ctrl = (gpt_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + + /* Call user callback. */ + r_gpt_call_callback(p_instance_ctrl, TIMER_EVENT_TROUGH, 0); + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; +} + +#endif + +/*******************************************************************************************************************//** + * Interrupt triggered by a capture A source. + * + * Clears interrupt, disables captures if one-shot mode, and calls callback if one was provided in the open function. + **********************************************************************************************************************/ +void gpt_capture_a_isr (void) +{ + r_gpt_capture_common_isr(GPT_PRV_CAPTURE_EVENT_A); +} + +/*******************************************************************************************************************//** + * Interrupt triggered by a capture B source. + * + * Clears interrupt, disables captures if one-shot mode, and calls callback if one was provided in the open function. + **********************************************************************************************************************/ +void gpt_capture_b_isr (void) +{ + r_gpt_capture_common_isr(GPT_PRV_CAPTURE_EVENT_B); +} diff --git a/bsp/renesas/ra6m3-hmi-board/ra_cfg/fsp_cfg/r_adc_cfg.h b/bsp/renesas/ra6m3-hmi-board/ra_cfg/fsp_cfg/r_adc_cfg.h new file mode 100644 index 0000000000..9c59889ca8 --- /dev/null +++ b/bsp/renesas/ra6m3-hmi-board/ra_cfg/fsp_cfg/r_adc_cfg.h @@ -0,0 +1,5 @@ +/* generated configuration header file - do not edit */ +#ifndef R_ADC_CFG_H_ +#define R_ADC_CFG_H_ +#define ADC_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) +#endif /* R_ADC_CFG_H_ */ diff --git a/bsp/renesas/ra6m3-hmi-board/ra_cfg/fsp_cfg/r_gpt_cfg.h b/bsp/renesas/ra6m3-hmi-board/ra_cfg/fsp_cfg/r_gpt_cfg.h new file mode 100644 index 0000000000..fd876266d3 --- /dev/null +++ b/bsp/renesas/ra6m3-hmi-board/ra_cfg/fsp_cfg/r_gpt_cfg.h @@ -0,0 +1,8 @@ +/* generated configuration header file - do not edit */ +#ifndef R_GPT_CFG_H_ +#define R_GPT_CFG_H_ +#define GPT_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) +#define GPT_CFG_OUTPUT_SUPPORT_ENABLE (1) +#define GPT_CFG_WRITE_PROTECT_ENABLE (0) +#define GPT_CFG_GPTCLK_BYPASS 1 +#endif /* R_GPT_CFG_H_ */ diff --git a/bsp/renesas/ra6m3-hmi-board/ra_gen/hal_data.c b/bsp/renesas/ra6m3-hmi-board/ra_gen/hal_data.c index cdcffb3b68..848ce6e5a9 100644 --- a/bsp/renesas/ra6m3-hmi-board/ra_gen/hal_data.c +++ b/bsp/renesas/ra6m3-hmi-board/ra_gen/hal_data.c @@ -1,5 +1,279 @@ /* generated HAL source file - do not edit */ #include "hal_data.h" + +/* Macros to tie dynamic ELC links to ADC_TRIGGER_SYNC_ELC option in adc_trigger_t. */ +#define ADC_TRIGGER_ADC0 ADC_TRIGGER_SYNC_ELC +#define ADC_TRIGGER_ADC0_B ADC_TRIGGER_SYNC_ELC +#define ADC_TRIGGER_ADC1 ADC_TRIGGER_SYNC_ELC +#define ADC_TRIGGER_ADC1_B ADC_TRIGGER_SYNC_ELC +gpt_instance_ctrl_t g_timer2_ctrl; +#if 0 +const gpt_extended_pwm_cfg_t g_timer2_pwm_extend = +{ + .trough_ipl = (BSP_IRQ_DISABLED), +#if defined(VECTOR_NUMBER_GPT2_COUNTER_UNDERFLOW) + .trough_irq = VECTOR_NUMBER_GPT2_COUNTER_UNDERFLOW, +#else + .trough_irq = FSP_INVALID_VECTOR, +#endif + .poeg_link = GPT_POEG_LINK_POEG0, + .output_disable = GPT_OUTPUT_DISABLE_NONE, + .adc_trigger = GPT_ADC_TRIGGER_NONE, + .dead_time_count_up = 0, + .dead_time_count_down = 0, + .adc_a_compare_match = 0, + .adc_b_compare_match = 0, + .interrupt_skip_source = GPT_INTERRUPT_SKIP_SOURCE_NONE, + .interrupt_skip_count = GPT_INTERRUPT_SKIP_COUNT_0, + .interrupt_skip_adc = GPT_INTERRUPT_SKIP_ADC_NONE, + .gtioca_disable_setting = GPT_GTIOC_DISABLE_PROHIBITED, + .gtiocb_disable_setting = GPT_GTIOC_DISABLE_PROHIBITED, +}; +#endif +const gpt_extended_cfg_t g_timer2_extend = +{ + .gtioca = { .output_enabled = false, + .stop_level = GPT_PIN_LEVEL_LOW + }, + .gtiocb = { .output_enabled = true, + .stop_level = GPT_PIN_LEVEL_LOW + }, + .start_source = (gpt_source_t) ( GPT_SOURCE_NONE), + .stop_source = (gpt_source_t) ( GPT_SOURCE_NONE), + .clear_source = (gpt_source_t) ( GPT_SOURCE_NONE), + .count_up_source = (gpt_source_t) ( GPT_SOURCE_NONE), + .count_down_source = (gpt_source_t) ( GPT_SOURCE_NONE), + .capture_a_source = (gpt_source_t) ( GPT_SOURCE_NONE), + .capture_b_source = (gpt_source_t) ( GPT_SOURCE_NONE), + .capture_a_ipl = (BSP_IRQ_DISABLED), + .capture_b_ipl = (BSP_IRQ_DISABLED), +#if defined(VECTOR_NUMBER_GPT2_CAPTURE_COMPARE_A) + .capture_a_irq = VECTOR_NUMBER_GPT2_CAPTURE_COMPARE_A, +#else + .capture_a_irq = FSP_INVALID_VECTOR, +#endif +#if defined(VECTOR_NUMBER_GPT2_CAPTURE_COMPARE_B) + .capture_b_irq = VECTOR_NUMBER_GPT2_CAPTURE_COMPARE_B, +#else + .capture_b_irq = FSP_INVALID_VECTOR, +#endif + .capture_filter_gtioca = GPT_CAPTURE_FILTER_NONE, + .capture_filter_gtiocb = GPT_CAPTURE_FILTER_NONE, +#if 0 + .p_pwm_cfg = &g_timer2_pwm_extend, +#else + .p_pwm_cfg = NULL, +#endif +#if 0 + .gtior_setting.gtior_b.gtioa = (0U << 4U) | (0U << 2U) | (0U << 0U), + .gtior_setting.gtior_b.oadflt = (uint32_t) GPT_PIN_LEVEL_LOW, + .gtior_setting.gtior_b.oahld = 0U, + .gtior_setting.gtior_b.oae = (uint32_t) false, + .gtior_setting.gtior_b.oadf = (uint32_t) GPT_GTIOC_DISABLE_PROHIBITED, + .gtior_setting.gtior_b.nfaen = ((uint32_t) GPT_CAPTURE_FILTER_NONE & 1U), + .gtior_setting.gtior_b.nfcsa = ((uint32_t) GPT_CAPTURE_FILTER_NONE >> 1U), + .gtior_setting.gtior_b.gtiob = (0U << 4U) | (0U << 2U) | (0U << 0U), + .gtior_setting.gtior_b.obdflt = (uint32_t) GPT_PIN_LEVEL_LOW, + .gtior_setting.gtior_b.obhld = 0U, + .gtior_setting.gtior_b.obe = (uint32_t) true, + .gtior_setting.gtior_b.obdf = (uint32_t) GPT_GTIOC_DISABLE_PROHIBITED, + .gtior_setting.gtior_b.nfben = ((uint32_t) GPT_CAPTURE_FILTER_NONE & 1U), + .gtior_setting.gtior_b.nfcsb = ((uint32_t) GPT_CAPTURE_FILTER_NONE >> 1U), +#else + .gtior_setting.gtior = 0U, +#endif +}; +const timer_cfg_t g_timer2_cfg = +{ + .mode = TIMER_MODE_PWM, + /* Actual period: 35.791394133333334 seconds. Actual duty: 50%. */ .period_counts = (uint32_t) 0x100000000, .duty_cycle_counts = 0x80000000, .source_div = (timer_source_div_t)0, + .channel = 2, + .p_callback = NULL, + /** If NULL then do not add & */ +#if defined(NULL) + .p_context = NULL, +#else + .p_context = &NULL, +#endif + .p_extend = &g_timer2_extend, + .cycle_end_ipl = (BSP_IRQ_DISABLED), +#if defined(VECTOR_NUMBER_GPT2_COUNTER_OVERFLOW) + .cycle_end_irq = VECTOR_NUMBER_GPT2_COUNTER_OVERFLOW, +#else + .cycle_end_irq = FSP_INVALID_VECTOR, +#endif +}; +/* Instance structure to use this module. */ +const timer_instance_t g_timer2 = +{ + .p_ctrl = &g_timer2_ctrl, + .p_cfg = &g_timer2_cfg, + .p_api = &g_timer_on_gpt +}; +sci_uart_instance_ctrl_t g_uart4_ctrl; + + baud_setting_t g_uart4_baud_setting = + { + /* Baud rate calculated with 0.160% error. */ .abcse = 0, .abcs = 0, .bgdm = 1, .cks = 0, .brr = 64, .mddr = (uint8_t) 256, .brme = false + }; + + /** UART extended configuration for UARTonSCI HAL driver */ + const sci_uart_extended_cfg_t g_uart4_cfg_extend = + { + .clock = SCI_UART_CLOCK_INT, + .rx_edge_start = SCI_UART_START_BIT_FALLING_EDGE, + .noise_cancel = SCI_UART_NOISE_CANCELLATION_DISABLE, + .rx_fifo_trigger = SCI_UART_RX_FIFO_TRIGGER_MAX, + .p_baud_setting = &g_uart4_baud_setting, + .flow_control = SCI_UART_FLOW_CONTROL_RTS, + #if 0xFF != 0xFF + .flow_control_pin = BSP_IO_PORT_FF_PIN_0xFF, + #else + .flow_control_pin = (bsp_io_port_pin_t) UINT16_MAX, + #endif + }; + + /** UART interface configuration */ + const uart_cfg_t g_uart4_cfg = + { + .channel = 4, + .data_bits = UART_DATA_BITS_8, + .parity = UART_PARITY_OFF, + .stop_bits = UART_STOP_BITS_1, + .p_callback = user_uart4_callback, + .p_context = NULL, + .p_extend = &g_uart4_cfg_extend, +#define RA_NOT_DEFINED (1) +#if (RA_NOT_DEFINED == RA_NOT_DEFINED) + .p_transfer_tx = NULL, +#else + .p_transfer_tx = &RA_NOT_DEFINED, +#endif +#if (RA_NOT_DEFINED == RA_NOT_DEFINED) + .p_transfer_rx = NULL, +#else + .p_transfer_rx = &RA_NOT_DEFINED, +#endif +#undef RA_NOT_DEFINED + .rxi_ipl = (12), + .txi_ipl = (12), + .tei_ipl = (12), + .eri_ipl = (12), +#if defined(VECTOR_NUMBER_SCI4_RXI) + .rxi_irq = VECTOR_NUMBER_SCI4_RXI, +#else + .rxi_irq = FSP_INVALID_VECTOR, +#endif +#if defined(VECTOR_NUMBER_SCI4_TXI) + .txi_irq = VECTOR_NUMBER_SCI4_TXI, +#else + .txi_irq = FSP_INVALID_VECTOR, +#endif +#if defined(VECTOR_NUMBER_SCI4_TEI) + .tei_irq = VECTOR_NUMBER_SCI4_TEI, +#else + .tei_irq = FSP_INVALID_VECTOR, +#endif +#if defined(VECTOR_NUMBER_SCI4_ERI) + .eri_irq = VECTOR_NUMBER_SCI4_ERI, +#else + .eri_irq = FSP_INVALID_VECTOR, +#endif + }; + +/* Instance structure to use this module. */ +const uart_instance_t g_uart4 = +{ + .p_ctrl = &g_uart4_ctrl, + .p_cfg = &g_uart4_cfg, + .p_api = &g_uart_on_sci +}; +adc_instance_ctrl_t g_adc0_ctrl; +const adc_extended_cfg_t g_adc0_cfg_extend = +{ + .add_average_count = ADC_ADD_OFF, + .clearing = ADC_CLEAR_AFTER_READ_ON, + .trigger_group_b = ADC_TRIGGER_SYNC_ELC, + .double_trigger_mode = ADC_DOUBLE_TRIGGER_DISABLED, + .adc_vref_control = ADC_VREF_CONTROL_VREFH, + .enable_adbuf = 0, +#if defined(VECTOR_NUMBER_ADC0_WINDOW_A) + .window_a_irq = VECTOR_NUMBER_ADC0_WINDOW_A, +#else + .window_a_irq = FSP_INVALID_VECTOR, +#endif + .window_a_ipl = (BSP_IRQ_DISABLED), +#if defined(VECTOR_NUMBER_ADC0_WINDOW_B) + .window_b_irq = VECTOR_NUMBER_ADC0_WINDOW_B, +#else + .window_b_irq = FSP_INVALID_VECTOR, +#endif + .window_b_ipl = (BSP_IRQ_DISABLED), +}; +const adc_cfg_t g_adc0_cfg = +{ + .unit = 0, + .mode = ADC_MODE_CONTINUOUS_SCAN, + .resolution = ADC_RESOLUTION_12_BIT, + .alignment = (adc_alignment_t) ADC_ALIGNMENT_RIGHT, + .trigger = ADC_TRIGGER_SOFTWARE, + .p_callback = NULL, + /** If NULL then do not add & */ +#if defined(NULL) + .p_context = NULL, +#else + .p_context = &NULL, +#endif + .p_extend = &g_adc0_cfg_extend, +#if defined(VECTOR_NUMBER_ADC0_SCAN_END) + .scan_end_irq = VECTOR_NUMBER_ADC0_SCAN_END, +#else + .scan_end_irq = FSP_INVALID_VECTOR, +#endif + .scan_end_ipl = (BSP_IRQ_DISABLED), +#if defined(VECTOR_NUMBER_ADC0_SCAN_END_B) + .scan_end_b_irq = VECTOR_NUMBER_ADC0_SCAN_END_B, +#else + .scan_end_b_irq = FSP_INVALID_VECTOR, +#endif + .scan_end_b_ipl = (BSP_IRQ_DISABLED), +}; +#if ((0) | (0)) +const adc_window_cfg_t g_adc0_window_cfg = +{ + .compare_mask = 0, + .compare_mode_mask = 0, + .compare_cfg = (0) | (0) | (0) | (ADC_COMPARE_CFG_EVENT_OUTPUT_OR), + .compare_ref_low = 0, + .compare_ref_high = 0, + .compare_b_channel = (ADC_WINDOW_B_CHANNEL_0), + .compare_b_mode = (ADC_WINDOW_B_MODE_LESS_THAN_OR_OUTSIDE), + .compare_b_ref_low = 0, + .compare_b_ref_high = 0, +}; +#endif +const adc_channel_cfg_t g_adc0_channel_cfg = +{ + .scan_mask = ADC_MASK_CHANNEL_0 | ADC_MASK_CHANNEL_1 | ADC_MASK_CHANNEL_2 | ADC_MASK_CHANNEL_3 | ADC_MASK_CHANNEL_5 | ADC_MASK_CHANNEL_7 | ADC_MASK_CHANNEL_20 | 0, + .scan_mask_group_b = 0, + .priority_group_a = ADC_GROUP_A_PRIORITY_OFF, + .add_mask = 0, + .sample_hold_mask = 0, + .sample_hold_states = 24, +#if ((0) | (0)) + .p_window_cfg = (adc_window_cfg_t *) &g_adc0_window_cfg, +#else + .p_window_cfg = NULL, +#endif +}; +/* Instance structure to use this module. */ +const adc_instance_t g_adc0 = +{ + .p_ctrl = &g_adc0_ctrl, + .p_cfg = &g_adc0_cfg, + .p_channel_cfg = &g_adc0_channel_cfg, + .p_api = &g_adc_on_adc +}; sci_uart_instance_ctrl_t g_uart9_ctrl; baud_setting_t g_uart9_baud_setting = diff --git a/bsp/renesas/ra6m3-hmi-board/ra_gen/hal_data.h b/bsp/renesas/ra6m3-hmi-board/ra_gen/hal_data.h index 7e3e2152a5..8a38ab2658 100644 --- a/bsp/renesas/ra6m3-hmi-board/ra_gen/hal_data.h +++ b/bsp/renesas/ra6m3-hmi-board/ra_gen/hal_data.h @@ -4,9 +4,49 @@ #include #include "bsp_api.h" #include "common_data.h" +#include "r_gpt.h" +#include "r_timer_api.h" #include "r_sci_uart.h" #include "r_uart_api.h" +#include "r_adc.h" +#include "r_adc_api.h" FSP_HEADER +/** Timer on GPT Instance. */ +extern const timer_instance_t g_timer2; + +/** Access the GPT instance using these structures when calling API functions directly (::p_api is not used). */ +extern gpt_instance_ctrl_t g_timer2_ctrl; +extern const timer_cfg_t g_timer2_cfg; + +#ifndef NULL +void NULL(timer_callback_args_t * p_args); +#endif +/** UART on SCI Instance. */ + extern const uart_instance_t g_uart4; + + /** Access the UART instance using these structures when calling API functions directly (::p_api is not used). */ + extern sci_uart_instance_ctrl_t g_uart4_ctrl; + extern const uart_cfg_t g_uart4_cfg; + extern const sci_uart_extended_cfg_t g_uart4_cfg_extend; + + #ifndef user_uart4_callback + void user_uart4_callback(uart_callback_args_t * p_args); + #endif +/** ADC on ADC Instance. */ +extern const adc_instance_t g_adc0; + +/** Access the ADC instance using these structures when calling API functions directly (::p_api is not used). */ +extern adc_instance_ctrl_t g_adc0_ctrl; +extern const adc_cfg_t g_adc0_cfg; +extern const adc_channel_cfg_t g_adc0_channel_cfg; + +#ifndef NULL +void NULL(adc_callback_args_t * p_args); +#endif + +#ifndef NULL +#define ADC_DMAC_CHANNELS_PER_BLOCK_NULL 7 +#endif /** UART on SCI Instance. */ extern const uart_instance_t g_uart9; diff --git a/bsp/renesas/ra6m3-hmi-board/ra_gen/pin_data.c b/bsp/renesas/ra6m3-hmi-board/ra_gen/pin_data.c index cb6dc9d886..80f6607eb5 100644 --- a/bsp/renesas/ra6m3-hmi-board/ra_gen/pin_data.c +++ b/bsp/renesas/ra6m3-hmi-board/ra_gen/pin_data.c @@ -4,6 +4,30 @@ const ioport_pin_cfg_t g_bsp_pin_cfg_data[] = { + { + .pin = BSP_IO_PORT_00_PIN_00, + .pin_cfg = ((uint32_t) IOPORT_CFG_ANALOG_ENABLE) + }, + { + .pin = BSP_IO_PORT_00_PIN_01, + .pin_cfg = ((uint32_t) IOPORT_CFG_ANALOG_ENABLE) + }, + { + .pin = BSP_IO_PORT_00_PIN_02, + .pin_cfg = ((uint32_t) IOPORT_CFG_ANALOG_ENABLE) + }, + { + .pin = BSP_IO_PORT_00_PIN_03, + .pin_cfg = ((uint32_t) IOPORT_CFG_ANALOG_ENABLE) + }, + { + .pin = BSP_IO_PORT_00_PIN_08, + .pin_cfg = ((uint32_t) IOPORT_CFG_ANALOG_ENABLE) + }, + { + .pin = BSP_IO_PORT_00_PIN_14, + .pin_cfg = ((uint32_t) IOPORT_CFG_ANALOG_ENABLE) + }, { .pin = BSP_IO_PORT_01_PIN_08, .pin_cfg = ((uint32_t) IOPORT_CFG_PERIPHERAL_PIN | (uint32_t) IOPORT_PERIPHERAL_DEBUG) @@ -16,10 +40,26 @@ const ioport_pin_cfg_t g_bsp_pin_cfg_data[] = { .pin = BSP_IO_PORT_01_PIN_10, .pin_cfg = ((uint32_t) IOPORT_CFG_PERIPHERAL_PIN | (uint32_t) IOPORT_PERIPHERAL_SCI1_3_5_7_9) }, + { + .pin = BSP_IO_PORT_02_PIN_05, + .pin_cfg = ((uint32_t) IOPORT_CFG_PERIPHERAL_PIN | (uint32_t) IOPORT_PERIPHERAL_SCI0_2_4_6_8) + }, + { + .pin = BSP_IO_PORT_02_PIN_06, + .pin_cfg = ((uint32_t) IOPORT_CFG_PERIPHERAL_PIN | (uint32_t) IOPORT_PERIPHERAL_SCI0_2_4_6_8) + }, { .pin = BSP_IO_PORT_03_PIN_00, .pin_cfg = ((uint32_t) IOPORT_CFG_PERIPHERAL_PIN | (uint32_t) IOPORT_PERIPHERAL_DEBUG) }, + { + .pin = BSP_IO_PORT_05_PIN_08, + .pin_cfg = ((uint32_t) IOPORT_CFG_ANALOG_ENABLE) + }, + { + .pin = BSP_IO_PORT_07_PIN_12, + .pin_cfg = ((uint32_t) IOPORT_CFG_PERIPHERAL_PIN | (uint32_t) IOPORT_PERIPHERAL_GPT1) + }, }; const ioport_cfg_t g_bsp_pin_cfg = { diff --git a/bsp/renesas/ra6m3-hmi-board/ra_gen/vector_data.c b/bsp/renesas/ra6m3-hmi-board/ra_gen/vector_data.c index 487454d4ae..28065e8415 100644 --- a/bsp/renesas/ra6m3-hmi-board/ra_gen/vector_data.c +++ b/bsp/renesas/ra6m3-hmi-board/ra_gen/vector_data.c @@ -8,6 +8,10 @@ [1] = sci_uart_txi_isr, /* SCI9 TXI (Transmit data empty) */ [2] = sci_uart_tei_isr, /* SCI9 TEI (Transmit end) */ [3] = sci_uart_eri_isr, /* SCI9 ERI (Receive error) */ + [4] = sci_uart_rxi_isr, /* SCI4 RXI (Received data full) */ + [5] = sci_uart_txi_isr, /* SCI4 TXI (Transmit data empty) */ + [6] = sci_uart_tei_isr, /* SCI4 TEI (Transmit end) */ + [7] = sci_uart_eri_isr, /* SCI4 ERI (Receive error) */ }; const bsp_interrupt_event_t g_interrupt_event_link_select[BSP_ICU_VECTOR_MAX_ENTRIES] = { @@ -15,5 +19,9 @@ [1] = BSP_PRV_IELS_ENUM(EVENT_SCI9_TXI), /* SCI9 TXI (Transmit data empty) */ [2] = BSP_PRV_IELS_ENUM(EVENT_SCI9_TEI), /* SCI9 TEI (Transmit end) */ [3] = BSP_PRV_IELS_ENUM(EVENT_SCI9_ERI), /* SCI9 ERI (Receive error) */ + [4] = BSP_PRV_IELS_ENUM(EVENT_SCI4_RXI), /* SCI4 RXI (Received data full) */ + [5] = BSP_PRV_IELS_ENUM(EVENT_SCI4_TXI), /* SCI4 TXI (Transmit data empty) */ + [6] = BSP_PRV_IELS_ENUM(EVENT_SCI4_TEI), /* SCI4 TEI (Transmit end) */ + [7] = BSP_PRV_IELS_ENUM(EVENT_SCI4_ERI), /* SCI4 ERI (Receive error) */ }; - #endif + #endif \ No newline at end of file diff --git a/bsp/renesas/ra6m3-hmi-board/ra_gen/vector_data.h b/bsp/renesas/ra6m3-hmi-board/ra_gen/vector_data.h index 55d3da960a..bd5655b853 100644 --- a/bsp/renesas/ra6m3-hmi-board/ra_gen/vector_data.h +++ b/bsp/renesas/ra6m3-hmi-board/ra_gen/vector_data.h @@ -3,7 +3,7 @@ #define VECTOR_DATA_H /* Number of interrupts allocated */ #ifndef VECTOR_DATA_IRQ_COUNT - #define VECTOR_DATA_IRQ_COUNT (4) + #define VECTOR_DATA_IRQ_COUNT (8) #endif /* ISR prototypes */ void sci_uart_rxi_isr(void); @@ -20,4 +20,12 @@ #define SCI9_TEI_IRQn ((IRQn_Type) 2) /* SCI9 TEI (Transmit end) */ #define VECTOR_NUMBER_SCI9_ERI ((IRQn_Type) 3) /* SCI9 ERI (Receive error) */ #define SCI9_ERI_IRQn ((IRQn_Type) 3) /* SCI9 ERI (Receive error) */ - #endif /* VECTOR_DATA_H */ + #define VECTOR_NUMBER_SCI4_RXI ((IRQn_Type) 4) /* SCI4 RXI (Received data full) */ + #define SCI4_RXI_IRQn ((IRQn_Type) 4) /* SCI4 RXI (Received data full) */ + #define VECTOR_NUMBER_SCI4_TXI ((IRQn_Type) 5) /* SCI4 TXI (Transmit data empty) */ + #define SCI4_TXI_IRQn ((IRQn_Type) 5) /* SCI4 TXI (Transmit data empty) */ + #define VECTOR_NUMBER_SCI4_TEI ((IRQn_Type) 6) /* SCI4 TEI (Transmit end) */ + #define SCI4_TEI_IRQn ((IRQn_Type) 6) /* SCI4 TEI (Transmit end) */ + #define VECTOR_NUMBER_SCI4_ERI ((IRQn_Type) 7) /* SCI4 ERI (Receive error) */ + #define SCI4_ERI_IRQn ((IRQn_Type) 7) /* SCI4 ERI (Receive error) */ + #endif /* VECTOR_DATA_H */ \ No newline at end of file diff --git a/bsp/renesas/ra6m3-hmi-board/rtconfig.h b/bsp/renesas/ra6m3-hmi-board/rtconfig.h index fb20434e1d..dfd1959641 100644 --- a/bsp/renesas/ra6m3-hmi-board/rtconfig.h +++ b/bsp/renesas/ra6m3-hmi-board/rtconfig.h @@ -47,6 +47,7 @@ #define RT_CONSOLEBUF_SIZE 128 #define RT_CONSOLE_DEVICE_NAME "uart9" #define RT_VER_NUM 0x50100 +#define RT_BACKTRACE_LEVEL_MAX_NR 32 #define RT_USING_HW_ATOMIC #define RT_USING_CPU_FFS #define ARCH_ARM @@ -84,7 +85,11 @@ #define RT_USING_SERIAL #define RT_USING_SERIAL_V2 #define RT_SERIAL_USING_DMA +#define RT_USING_I2C +#define RT_USING_I2C_BITOPS #define RT_USING_PIN +#define RT_USING_ADC +#define RT_USING_PWM /* Using USB */ @@ -108,6 +113,7 @@ /* Socket is in the 'Network' category */ +#define RT_USING_CPLUSPLUS /* Network */ @@ -175,6 +181,8 @@ /* Micrium: Micrium software products porting for RT-Thread */ +#define PKG_USING_PERF_COUNTER +#define PKG_USING_PERF_COUNTER_LATEST_VERSION /* peripheral libraries and drivers */ @@ -205,6 +213,14 @@ /* Arduino libraries */ +#define PKG_USING_RTDUINO +#define RTDUINO_THREAD_SIZE 2048 +#define RTDUINO_THREAD_PRIO 30 +#define RTDUINO_SUPPORT_HIGH_PRECISION_MICROS +#define RTDUINO_USING_WIRE +#define RTDUINO_WIRE_BUFFER_LENGTH 32 +#define RTDUINO_USING_SERVO +#define PKG_USING_RTDUINO_LATEST_VERSION /* Projects and Demos */ @@ -246,13 +262,24 @@ /* Onboard Peripheral Drivers */ +#define BSP_USING_ARDUINO + /* On-chip Peripheral Drivers */ #define BSP_USING_GPIO #define BSP_USING_UART +#define BSP_USING_UART4 +#define BSP_UART4_RX_BUFSIZE 256 +#define BSP_UART4_TX_BUFSIZE 0 #define BSP_USING_UART9 #define BSP_UART9_RX_BUFSIZE 256 #define BSP_UART9_TX_BUFSIZE 0 +#define BSP_USING_I2C +#define BSP_USING_ADC +#define BSP_USING_ADC0 +#define BSP_USING_PWM +#define BSP_USING_PWM2 +#define BSP_USING_PWM2_CH2 /* Board extended module Drivers */ diff --git a/bsp/renesas/ra6m3-hmi-board/script/fsp.ld b/bsp/renesas/ra6m3-hmi-board/script/fsp.ld index 16571b094d..8af6bc1aca 100644 --- a/bsp/renesas/ra6m3-hmi-board/script/fsp.ld +++ b/bsp/renesas/ra6m3-hmi-board/script/fsp.ld @@ -223,6 +223,14 @@ SECTIONS KEEP(*(.eh_frame*)) + /* new GCC version uses .init_array */ + PROVIDE(__ctors_start__ = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE(__ctors_end__ = .); + + . = ALIGN(4); + __ROM_End = .; } > FLASH = 0xFF @@ -327,6 +335,14 @@ SECTIONS . = ALIGN(4); + /* .data section which is used for initialized data */ + PROVIDE(__dtors_start__ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(__dtors_end__ = .); + + . = ALIGN(4); + /* All data end */ __data_end__ = .;