xref: /btstack/port/renesas-tb-s1ja-cc256x/template/btstack_example/synergy/ssp/src/driver/r_ioport/r_ioport.c (revision 3b5c872a8c45689e8cc17891f01530f5aa5e911c)
1 /***********************************************************************************************************************
2  * Copyright [2015-2017] Renesas Electronics Corporation and/or its licensors. All Rights Reserved.
3  *
4  * This file is part of Renesas SynergyTM Software Package (SSP)
5  *
6  * The contents of this file (the "contents") are proprietary and confidential to Renesas Electronics Corporation
7  * and/or its licensors ("Renesas") and subject to statutory and contractual protections.
8  *
9  * This file is subject to a Renesas SSP license agreement. Unless otherwise agreed in an SSP license agreement with
10  * Renesas: 1) you may not use, copy, modify, distribute, display, or perform the contents; 2) you may not use any name
11  * or mark of Renesas for advertising or publicity purposes or in connection with your use of the contents; 3) RENESAS
12  * MAKES NO WARRANTY OR REPRESENTATIONS ABOUT THE SUITABILITY OF THE CONTENTS FOR ANY PURPOSE; THE CONTENTS ARE PROVIDED
13  * "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14  * PARTICULAR PURPOSE, AND NON-INFRINGEMENT; AND 4) RENESAS SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, OR
15  * CONSEQUENTIAL DAMAGES, INCLUDING DAMAGES RESULTING FROM LOSS OF USE, DATA, OR PROJECTS, WHETHER IN AN ACTION OF
16  * CONTRACT OR TORT, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE CONTENTS. Third-party contents
17  * included in this file may be subject to different terms.
18  **********************************************************************************************************************/
19 
20 /**********************************************************************************************************************
21  * File Name    : r_ioport.c
22  * Description  : IOPORT HAL API implementation.
23  **********************************************************************************************************************/
24 
25 
26 
27 
28 /***********************************************************************************************************************
29  * Includes
30  **********************************************************************************************************************/
31 #include <stdint.h>
32 #include "r_ioport.h"
33 #include "r_ioport_private.h"
34 #include "r_ioport_api.h"
35 #include "./hw/hw_ioport_private.h"
36 #include "r_ioport_private_api.h"
37 
38 /***********************************************************************************************************************
39  * Macro definitions
40  **********************************************************************************************************************/
41 /** Macro for error logger. */
42 #ifndef IOPORT_ERROR_RETURN
43 /*LDRA_INSPECTED 77 S This macro does not work when surrounded by parentheses. */
44 #define IOPORT_ERROR_RETURN(a, err) SSP_ERROR_RETURN((a), (err), &g_module_name[0], &g_ioport_version)
45 #endif
46 
47 /** Mask to get PSEL bitfield from PFS register. */
48 #define BSP_PRV_PFS_PSEL_MASK         (0x1F000000uL)
49 
50 /** Shift to get pin 0 on a package in extended data. */
51 #define IOPORT_PRV_EXISTS_B0_SHIFT    (16UL)
52 
53 /** Mask to determine if any pins on port exist on this package. */
54 #define IOPORT_PRV_PORT_EXISTS_MASK   (0xFFFF0000U)
55 
56 /** Shift to get port in ioport_port_t and ioport_port_pin_t enums. */
57 #define IOPORT_PRV_PORT_OFFSET        (8U)
58 
59 #ifndef BSP_MCU_VBATT_SUPPORT
60 #define BSP_MCU_VBATT_SUPPORT         (0U)
61 #endif
62 
63 /***********************************************************************************************************************
64  * Typedef definitions
65  **********************************************************************************************************************/
66 
67 
68 /***********************************************************************************************************************
69  * Private function prototypes
70  **********************************************************************************************************************/
71 #if ((1 == IOPORT_CFG_PARAM_CHECKING_ENABLE))
72 static ssp_err_t r_ioport_pin_exists(ioport_port_pin_t pin);
73 static ssp_err_t r_ioport_port_exists(ioport_port_t port);
74 #endif
75 
76 #if BSP_MCU_VBATT_SUPPORT
77 static void bsp_vbatt_init(ioport_cfg_t const * const p_pin_cfg);   // Used internally by BSP
78 #endif
79 
80 /***********************************************************************************************************************
81  * Private global variables
82  **********************************************************************************************************************/
83 /** Name of module used by error logger macro */
84 #if BSP_CFG_ERROR_LOG != 0
85 static const char g_module_name[] = "ioport";
86 #endif
87 
88 #if defined(__GNUC__)
89 /* This structure is affected by warnings from a GCC compiler bug. This pragma suppresses the warnings in this
90  * structure only. */
91 /*LDRA_INSPECTED 69 S */
92 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
93 #endif
94 /** Version data structure used by error logger macro. */
95 static const ssp_version_t g_ioport_version =
96 {
97     .api_version_minor  = IOPORT_API_VERSION_MINOR,
98     .api_version_major  = IOPORT_API_VERSION_MAJOR,
99     .code_version_major = IOPORT_CODE_VERSION_MAJOR,
100     .code_version_minor = IOPORT_CODE_VERSION_MINOR
101 };
102 #if defined(__GNUC__)
103 /* Restore warning settings for 'missing-field-initializers' to as specified on command line. */
104 /*LDRA_INSPECTED 69 S */
105 #pragma GCC diagnostic pop
106 #endif
107 
108 /***********************************************************************************************************************
109  * Global Variables
110  **********************************************************************************************************************/
111 /** IOPort Implementation of IOPort Driver  */
112 /*LDRA_INSPECTED 27 D This structure must be accessible in user code. It cannot be static. */
113 const ioport_api_t g_ioport_on_ioport =
114 {
115     .init                 = R_IOPORT_Init,
116     .pinCfg               = R_IOPORT_PinCfg,
117     .pinsCfg              = R_IOPORT_PinsCfg,
118     .pinDirectionSet      = R_IOPORT_PinDirectionSet,
119     .pinEventInputRead    = R_IOPORT_PinEventInputRead,
120     .pinEventOutputWrite  = R_IOPORT_PinEventOutputWrite,
121     .pinEthernetModeCfg   = R_IOPORT_EthernetModeCfg,
122     .pinRead              = R_IOPORT_PinRead,
123     .pinWrite             = R_IOPORT_PinWrite,
124     .portDirectionSet     = R_IOPORT_PortDirectionSet,
125     .portEventInputRead   = R_IOPORT_PortEventInputRead,
126     .portEventOutputWrite = R_IOPORT_PortEventOutputWrite,
127     .portRead             = R_IOPORT_PortRead,
128     .portWrite            = R_IOPORT_PortWrite,
129     .versionGet           = R_IOPORT_VersionGet,
130 };
131 
132 /** Pointer to IOPORT base register. */
133 /*LDRA_INSPECTED 219 S In the GCC compiler, section placement requires a GCC attribute, which starts with underscore. */
134 /* This variable is not initialized at declaration because it is initialized and used before C runtime initialization */
135 /*LDRA_INSPECTED 57 D *//*LDRA_INSPECTED 57 D */
136 static R_IOPORT1_Type * gp_ioport_reg BSP_PLACE_IN_SECTION_V2(".noinit");
137 
138 /** Pointer to PFS base register. */
139 /*LDRA_INSPECTED 219 S In the GCC compiler, section placement requires a GCC attribute, which starts with underscore. */
140 /* This variable is not initialized at declaration because it is initialized and used before C runtime initialization */
141 /*LDRA_INSPECTED 57 D *//*LDRA_INSPECTED 57 D */
142 static R_PFS_Type * gp_pfs_reg BSP_PLACE_IN_SECTION_V2(".noinit");
143 
144 /** Pointer to PMISC base register. */
145 /*LDRA_INSPECTED 219 S In the GCC compiler, section placement requires a GCC attribute, which starts with underscore. */
146 /* This variable is not initialized at declaration because it is initialized and used before C runtime initialization */
147 /*LDRA_INSPECTED 57 D *//*LDRA_INSPECTED 57 D */
148 static R_PMISC_Type * gp_pmisc_reg BSP_PLACE_IN_SECTION_V2(".noinit");
149 
150 /** Pointer to IOPORT extended variant data, used to determine if pins exist on this package. */
151 /*LDRA_INSPECTED 219 S In the GCC compiler, section placement requires a GCC attribute, which starts with underscore. */
152 /* This variable is not initialized at declaration because it is initialized and used before C runtime initialization */
153 /*LDRA_INSPECTED 57 D *//*LDRA_INSPECTED 57 D */
154 static uint32_t const * gp_ioport_exists BSP_PLACE_IN_SECTION_V2(".noinit");
155 
156 /** Number of I/O ports in this package. */
157 /*LDRA_INSPECTED 219 S In the GCC compiler, section placement requires a GCC attribute, which starts with underscore. */
158 /* This variable is not initialized at declaration because it is initialized and used before C runtime initialization */
159 /*LDRA_INSPECTED 57 D *//*LDRA_INSPECTED 57 D */
160 static uint32_t g_ioport_num_ports BSP_PLACE_IN_SECTION_V2(".noinit");
161 
162 #if BSP_MCU_VBATT_SUPPORT
163 static const ioport_port_pin_t g_vbatt_pins_input[] =
164 {
165     IOPORT_PORT_04_PIN_02,  ///< Associated with VBTICTLR->VCH0INEN
166     IOPORT_PORT_04_PIN_03,  ///< Associated with VBTICTLR->VCH1INEN
167     IOPORT_PORT_04_PIN_04   ///< Associated with VBTICTLR->VCH2INEN
168 };
169 #endif
170 
171 /** Used for holding reference counters for PFSWE. */
172 volatile uint16_t g_protect_pfswe_counter = 0U;
173 
174 /*******************************************************************************************************************//**
175  * @addtogroup IOPORT
176  * @{
177  **********************************************************************************************************************/
178 
179 /***********************************************************************************************************************
180  * Functions
181  **********************************************************************************************************************/
182 
183 /*******************************************************************************************************************//**
184  * @brief  Initializes internal driver data, then calls R_IOPORT_PinsCfg to configure pins.
185  *
186  * @retval SSP_SUCCESS                  Pin configuration data written to PFS register(s)
187  * @retval SSP_ERR_ASSERTION            NULL pointer
188  * @return                              See @ref Common_Error_Codes or functions called by this function for other possible
189  *                                      return codes. This function calls:
190  *                                        * fmi_api_t::productFeatureGet
191  **********************************************************************************************************************/
R_IOPORT_Init(const ioport_cfg_t * p_cfg)192 ssp_err_t R_IOPORT_Init (const ioport_cfg_t * p_cfg)
193 {
194 #if ((1 == IOPORT_CFG_PARAM_CHECKING_ENABLE))
195     SSP_ASSERT(NULL != p_cfg);
196     SSP_ASSERT(NULL != p_cfg->p_pin_cfg_data);
197 #endif
198 
199     ssp_feature_t ssp_feature = {{(ssp_ip_t) 0U}};
200     fmi_feature_info_t info = {0U};
201     ssp_feature.channel = 0U;
202     ssp_feature.unit = 0U;
203     ssp_feature.id = SSP_IP_IOPORT;
204     g_fmi_on_fmi.productFeatureGet(&ssp_feature, &info);
205     gp_ioport_reg = (R_IOPORT1_Type *) info.ptr;
206     gp_ioport_exists = info.ptr_extended_data;
207     g_ioport_num_ports = info.channel_count;
208     ssp_feature.id = SSP_IP_PFS;
209     g_fmi_on_fmi.productFeatureGet(&ssp_feature, &info);
210     gp_pfs_reg = (R_PFS_Type *) info.ptr;
211     ssp_feature.unit = 1U;
212     g_fmi_on_fmi.productFeatureGet(&ssp_feature, &info);
213     gp_pmisc_reg = (R_PMISC_Type *) info.ptr;
214 
215     return R_IOPORT_PinsCfg(p_cfg);
216 } /* End of function R_IOPORT_Init */
217 
218 /*******************************************************************************************************************//**
219  * @brief  Configures the functions of multiple pins by loading configuration data into pin PFS registers.
220  * Implements ioport_api_t::pinsCfg.
221  *
222  * This function initializes the supplied list of PmnPFS registers with the supplied values.
223  * This data can be generated by the ISDE pin configurator or manually by the developer. Different pin configurations
224  * can be loaded for different situations such as low power modes and test.*
225  *
226  * @retval SSP_SUCCESS                  Pin configuration data written to PFS register(s)
227  * @retval SSP_ERR_ASSERTION            NULL pointer
228  *
229  **********************************************************************************************************************/
R_IOPORT_PinsCfg(const ioport_cfg_t * p_cfg)230 ssp_err_t R_IOPORT_PinsCfg (const ioport_cfg_t * p_cfg)
231 {
232 #if ((1 == IOPORT_CFG_PARAM_CHECKING_ENABLE))
233     SSP_ASSERT(NULL != p_cfg);
234     SSP_ASSERT(NULL != p_cfg->p_pin_cfg_data);
235 #endif
236 
237 #if BSP_MCU_VBATT_SUPPORT
238     /** Handle any VBATT domain pin configuration. */
239     bsp_vbatt_init(p_cfg);
240 #endif
241 
242     uint16_t     pin_count;
243     ioport_cfg_t * p_pin_data;
244 
245     p_pin_data = (ioport_cfg_t *) p_cfg;
246 
247     for (pin_count = 0u; pin_count < p_pin_data->number_of_pins; pin_count++)
248     {
249         HW_IOPORT_PFSWrite(gp_pfs_reg, gp_pmisc_reg, p_pin_data->p_pin_cfg_data[pin_count].pin, p_pin_data->p_pin_cfg_data[pin_count].pin_cfg);
250     }
251 
252     return SSP_SUCCESS;
253 }
254 
255 /*******************************************************************************************************************//**
256  * @brief  Configures the settings of a pin. Implements ioport_api_t::pinCfg.
257  *
258  * @retval SSP_SUCCESS                    Pin configured.
259  * @retval SSP_ERR_INVALID_ARGUMENT     Invalid pin
260  *
261  * @note This function is re-entrant for different pins.
262  * This function will change the configuration of the pin with the new configuration. For example it is not possible
263  * with this function to change the drive strength of a pin while leaving all the other pin settings unchanged. To
264  * achieve this the original settings with the required change will need to be written using this function.
265  **********************************************************************************************************************/
R_IOPORT_PinCfg(ioport_port_pin_t pin,uint32_t cfg)266 ssp_err_t R_IOPORT_PinCfg (ioport_port_pin_t pin, uint32_t cfg)
267 {
268 #if ((1 == IOPORT_CFG_PARAM_CHECKING_ENABLE))
269     ssp_err_t err = SSP_SUCCESS;
270     err = r_ioport_pin_exists(pin);
271     IOPORT_ERROR_RETURN(SSP_SUCCESS == err, err);
272 #endif
273 
274 #if BSP_MCU_VBATT_SUPPORT
275     /** Create temporary structure for handling VBATT pins. */
276     ioport_cfg_t     temp_cfg;
277     ioport_pin_cfg_t temp_pin_cfg;
278 
279     temp_pin_cfg.pin = pin;
280     temp_pin_cfg.pin_cfg = cfg;
281 
282     temp_cfg.number_of_pins = 1U;
283     temp_cfg.p_pin_cfg_data = &temp_pin_cfg;
284 
285     /** Handle any VBATT domain pin configuration. */
286     bsp_vbatt_init(&temp_cfg);
287 #endif
288 
289     HW_IOPORT_PFSWrite(gp_pfs_reg, gp_pmisc_reg, pin, cfg);
290 
291     return SSP_SUCCESS;
292 } /* End of function R_IOPORT_PinCfg */
293 
294 /*******************************************************************************************************************//**
295  * @brief  Reads the level on a pin. Implements ioport_api_t::pinRead.
296  *
297  * @retval SSP_SUCCESS                    Pin read.
298  * @retval SSP_ERR_INVALID_ARGUMENT     Invalid argument
299  * @retval SSP_ERR_ASSERTION                NULL pointer
300  *
301  * @note This function is re-entrant for different pins.
302  **********************************************************************************************************************/
R_IOPORT_PinRead(ioport_port_pin_t pin,ioport_level_t * p_pin_value)303 ssp_err_t R_IOPORT_PinRead (ioport_port_pin_t pin, ioport_level_t * p_pin_value)
304 {
305 #if ((1 == IOPORT_CFG_PARAM_CHECKING_ENABLE))
306     ssp_err_t err = SSP_SUCCESS;
307     err = r_ioport_pin_exists(pin);
308     IOPORT_ERROR_RETURN(SSP_SUCCESS == err, err);
309     SSP_ASSERT(NULL != p_pin_value);
310 #endif
311 
312     *p_pin_value = HW_IOPORT_PinRead(gp_pfs_reg, pin);
313 
314     return SSP_SUCCESS;
315 } /* End of function R_IOPORT_PinRead */
316 
317 /*******************************************************************************************************************//**
318  * @brief  Reads the value on an IO port. Implements ioport_api_t::portRead.
319  *
320  * The specified port will be read, and the levels for all the pins will be returned.
321  * Each bit in the returned value corresponds to a pin on the port. For example, bit 7 corresponds
322  * to pin 7, bit 6 to pin 6, and so on. *
323  *
324  * @retval SSP_SUCCESS              Port read.
325  * @retval SSP_ERR_INVALID_ARGUMENT     Port not valid.
326  * @retval SSP_ERR_ASSERTION            NULL pointer
327  *
328  * @note This function is re-entrant for different ports.
329  **********************************************************************************************************************/
R_IOPORT_PortRead(ioport_port_t port,ioport_size_t * p_port_value)330 ssp_err_t R_IOPORT_PortRead (ioport_port_t port, ioport_size_t * p_port_value)
331 {
332 #if ((1 == IOPORT_CFG_PARAM_CHECKING_ENABLE))
333     ssp_err_t err = SSP_SUCCESS;
334     err = r_ioport_port_exists(port);
335     IOPORT_ERROR_RETURN(SSP_SUCCESS == err, err);
336     SSP_ASSERT(NULL != p_port_value);
337 #endif
338 
339     *p_port_value = HW_IOPORT_PortRead(gp_ioport_reg, port);
340 
341     return SSP_SUCCESS;
342 } /* End of function R_IOPORT_PortRead */
343 
344 /*******************************************************************************************************************//**
345  * @brief  Writes to multiple pins on a port. Implements ioport_api_t::portWrite.
346  *
347  * The input value will be written to the specified port. Each bit in the value parameter corresponds to a bit
348  * on the port. For example, bit 7 corresponds to pin 7, bit 6 to pin 6, and so on.
349  * Each bit in the mask parameter corresponds to a pin on the port.
350  *
351  * Only the bits with the corresponding bit in the mask value set will be updated.
352  * e.g. value = 0xFFFF, mask = 0x0003 results in only bits 0 and 1 being updated.
353  *
354  * @retval SSP_SUCCESS                  Port written to.
355  * @retval SSP_ERR_INVALID_ARGUMENT     The port and/or mask not valid.
356  *
357  * @note This function is re-entrant for different ports. This function makes use of the PCNTR3 register to atomically
358  * modify the levels on the specified pins on a port.
359  **********************************************************************************************************************/
R_IOPORT_PortWrite(ioport_port_t port,ioport_size_t value,ioport_size_t mask)360 ssp_err_t R_IOPORT_PortWrite (ioport_port_t port, ioport_size_t value, ioport_size_t mask)
361 {
362     ioport_size_t setbits;
363     ioport_size_t clrbits;
364 
365 #if ((1 == IOPORT_CFG_PARAM_CHECKING_ENABLE))
366     /* Cast to ensure correct conversion of parameter. */
367     IOPORT_ERROR_RETURN(mask > (ioport_size_t)0, SSP_ERR_INVALID_ARGUMENT);
368     ssp_err_t err = SSP_SUCCESS;
369     err = r_ioport_port_exists(port);
370     IOPORT_ERROR_RETURN(SSP_SUCCESS == err, err);
371 #endif
372 
373     /** High bits */
374     setbits = value & mask;
375 
376     /** Low bits */
377     /* Cast to ensure size */
378     clrbits = (ioport_size_t)((~value) & mask);
379 
380     HW_IOPORT_PortWriteWithPCNTR3(gp_ioport_reg, port, setbits, clrbits);
381 
382     return SSP_SUCCESS;
383 } /* End of function R_IOPORT_PortWrite */
384 
385 /*******************************************************************************************************************//**
386  * @brief  Sets a pin's output either high or low. Implements ioport_api_t::pinWrite.
387  *
388  * @retval SSP_SUCCESS              Pin written to.
389  * @retval SSP_ERR_INVALID_ARGUMENT     The pin and/or level not valid.
390  *
391  * @note This function is re-entrant for different pins. This function makes use of the PCNTR3 register to atomically
392  * modify the level on the specified pin on a port.
393  **********************************************************************************************************************/
R_IOPORT_PinWrite(ioport_port_pin_t pin,ioport_level_t level)394 ssp_err_t R_IOPORT_PinWrite (ioport_port_pin_t pin, ioport_level_t level)
395 {
396 #if ((1 == IOPORT_CFG_PARAM_CHECKING_ENABLE))
397     IOPORT_ERROR_RETURN(level <= IOPORT_LEVEL_HIGH, SSP_ERR_INVALID_ARGUMENT);
398     ssp_err_t err = SSP_SUCCESS;
399     err = r_ioport_pin_exists(pin);
400     IOPORT_ERROR_RETURN(SSP_SUCCESS == err, err);
401 #endif
402 
403     ioport_size_t setbits = 0U;
404     ioport_size_t clrbits = 0U;
405     ioport_port_t port = (ioport_port_t) (0xFF00U & (ioport_size_t) pin);
406 
407     ioport_size_t shift = 0x00FFU & (ioport_size_t) pin;
408     ioport_size_t pin_mask = (ioport_size_t) (1U << shift);
409 
410     if (IOPORT_LEVEL_LOW == level)
411     {
412         clrbits = pin_mask;
413     }
414     else
415     {
416         setbits = pin_mask;
417     }
418 
419     HW_IOPORT_PortWriteWithPCNTR3(gp_ioport_reg, port, setbits, clrbits);
420 
421     return SSP_SUCCESS;
422 } /* End of function R_IOPORT_PinWrite */
423 
424 /*******************************************************************************************************************//**
425  * @brief  Sets the direction of individual pins on a port. Implements ioport_api_t::portDirectionSet().
426  *
427  * Multiple pins on a port can be set to inputs or outputs at once.
428  * Each bit in the mask parameter corresponds to a pin on the port. For example, bit 7 corresponds to
429  * pin 7, bit 6 to pin 6, and so on. If a bit is set to 1 then the corresponding pin will be changed to
430  * an input or an output as specified by the direction values. If a mask bit is set to 0 then the direction of
431  * the pin will not be changed.
432  *
433  * @retval SSP_SUCCESS              Port direction updated.
434  * @retval SSP_ERR_INVALID_ARGUMENT    The port and/or mask not valid.
435  *
436  * @note This function is re-entrant for different ports.
437  **********************************************************************************************************************/
R_IOPORT_PortDirectionSet(ioport_port_t port,ioport_size_t direction_values,ioport_size_t mask)438 ssp_err_t R_IOPORT_PortDirectionSet (ioport_port_t port, ioport_size_t direction_values, ioport_size_t mask)
439 {
440     ioport_size_t orig_value;
441     ioport_size_t set_bits;
442     ioport_size_t clr_bits;
443     ioport_size_t write_value;
444 #if ((1 == IOPORT_CFG_PARAM_CHECKING_ENABLE))
445     /* Cast to ensure correct conversion of parameter. */
446     IOPORT_ERROR_RETURN(mask > (ioport_size_t)0, SSP_ERR_INVALID_ARGUMENT);
447     ssp_err_t err = SSP_SUCCESS;
448     err = r_ioport_port_exists(port);
449     IOPORT_ERROR_RETURN(SSP_SUCCESS == err, err);
450 #endif
451 
452     orig_value = HW_IOPORT_PortDirectionRead(gp_ioport_reg, port);
453 
454     /** High bits */
455     set_bits = direction_values & mask;
456 
457     /**  Low bits */
458     /* Cast to ensure size */
459     clr_bits = (ioport_size_t)((~direction_values) & mask);
460 
461     /** New value to write to port direction register */
462     write_value  = orig_value;
463     write_value |= set_bits;
464     /* Cast to ensure size */
465     write_value &= (ioport_size_t)(~clr_bits);
466 
467     HW_IOPORT_PortDirectionSet(gp_ioport_reg, port, write_value);
468 
469     return SSP_SUCCESS;
470 } /* End of function R_IOPORT_PortDirectionSet */
471 
472 /*******************************************************************************************************************//**
473  * @brief  Sets the direction of an individual pin on a port. Implements ioport_api_t::pinDirectionSet.
474  *
475  * @retval SSP_SUCCESS              Pin direction updated.
476  * @retval SSP_ERR_INVALID_ARGUMENT    The pin and/or direction not valid.
477  *
478  * @note This function is re-entrant for different pins.
479  **********************************************************************************************************************/
R_IOPORT_PinDirectionSet(ioport_port_pin_t pin,ioport_direction_t direction)480 ssp_err_t R_IOPORT_PinDirectionSet (ioport_port_pin_t pin, ioport_direction_t direction)
481 {
482 #if ((1 == IOPORT_CFG_PARAM_CHECKING_ENABLE))
483     IOPORT_ERROR_RETURN((direction == IOPORT_DIRECTION_INPUT) || (direction == IOPORT_DIRECTION_OUTPUT),
484                         SSP_ERR_INVALID_ARGUMENT);
485     ssp_err_t err = SSP_SUCCESS;
486     err = r_ioport_pin_exists(pin);
487     IOPORT_ERROR_RETURN(SSP_SUCCESS == err, err);
488 #endif
489 
490     HW_IOPORT_PinDirectionSet(gp_pfs_reg, gp_pmisc_reg, pin, direction);
491 
492     return SSP_SUCCESS;
493 } /* End of function R_IOPORT_PinDirectionSet */
494 
495 /*******************************************************************************************************************//**
496  * @brief  Reads the value of the event input data. Implements ioport_api_t::portEventInputRead().
497  *
498  * The event input data for the port will be read. Each bit in the returned value corresponds to a pin on the port.
499  * For example, bit 7 corresponds to pin 7, bit 6 to pin 6, and so on.
500  *
501  * The port event data is captured in response to a trigger from the ELC. This function enables this data to be read.
502  * Using the event system allows the captured data to be stored when it occurs and then read back at a later time.
503  *
504  * @retval SSP_SUCCESS              Port read.
505  * @retval SSP_ERR_INVALID_ARGUMENT     Port not valid.
506  * @retval SSP_ERR_ASSERTION            NULL pointer
507  *
508  * @note This function is re-entrant for different ports.
509  *
510  **********************************************************************************************************************/
R_IOPORT_PortEventInputRead(ioport_port_t port,ioport_size_t * p_event_data)511 ssp_err_t R_IOPORT_PortEventInputRead (ioport_port_t port, ioport_size_t * p_event_data)
512 {
513 #if ((1 == IOPORT_CFG_PARAM_CHECKING_ENABLE))
514     ssp_err_t err = SSP_SUCCESS;
515     err = r_ioport_port_exists(port);
516     IOPORT_ERROR_RETURN(SSP_SUCCESS == err, err);
517     SSP_ASSERT(NULL != p_event_data);
518 #endif
519 
520     *p_event_data = HW_IOPORT_PortEventInputDataRead(gp_ioport_reg, port);
521 
522     return SSP_SUCCESS;
523 } /* End of function R_IOPORT_PortEventInputRead */
524 
525 /*******************************************************************************************************************//**
526  * @brief  Reads the value of the event input data of a specific pin. Implements ioport_api_t::pinEventInputRead.
527  *
528  * The pin event data is captured in response to a trigger from the ELC. This function enables this data to be read.
529  * Using the event system allows the captured data to be stored when it occurs and then read back at a later time.
530  *
531  * @retval SSP_SUCCESS                  Pin read.
532  * @retval SSP_ERR_INVALID_ARGUMENT  Pin not valid.
533  * @retval SSP_ERR_ASSERTION            NULL pointer
534  *
535  * @note This function is re-entrant.
536  *
537  **********************************************************************************************************************/
R_IOPORT_PinEventInputRead(ioport_port_pin_t pin,ioport_level_t * p_pin_event)538 ssp_err_t R_IOPORT_PinEventInputRead (ioport_port_pin_t pin, ioport_level_t * p_pin_event)
539 {
540     ioport_size_t portvalue;
541     ioport_size_t mask;
542     ioport_port_t port;
543     uint16_t      pin_to_port;
544 
545 #if ((1 == IOPORT_CFG_PARAM_CHECKING_ENABLE))
546     ssp_err_t err = SSP_SUCCESS;
547     err = r_ioport_pin_exists(pin);
548     IOPORT_ERROR_RETURN(SSP_SUCCESS == err, err);
549     SSP_ASSERT(NULL != p_pin_event);
550 #endif
551 
552     /* Cast to ensure correct conversion of parameter. */
553     pin_to_port = (uint16_t)pin;
554     pin_to_port = pin_to_port & (uint16_t)0xFF00;
555     port = (ioport_port_t)pin_to_port;
556     portvalue = HW_IOPORT_PortEventInputDataRead(gp_ioport_reg, port);
557     mask      = (ioport_size_t) (1U << (0x00FFU & (ioport_port_t) pin));
558 
559     if ((portvalue & mask) == mask)
560     {
561         *p_pin_event = IOPORT_LEVEL_HIGH;
562     }
563     else
564     {
565         *p_pin_event = IOPORT_LEVEL_LOW;
566     }
567 
568     return SSP_SUCCESS;
569 } /* End of function R_IOPORT_PinEventInputRead */
570 
571 /*******************************************************************************************************************//**
572  * @brief  This function writes the set and reset event output data for a port. Implements
573  *ioport_api_t::portEventOutputWrite.
574  *
575  * Using the event system enables a port state to be stored by this function in advance of being output on the port.
576  * The output to the port will occur when the ELC event occurs.
577  *
578  * The input value will be written to the specified port when an ELC event configured for that port occurs.
579  * Each bit in the value parameter corresponds to a bit on the port. For example, bit 7 corresponds to pin 7,
580  * bit 6 to pin 6, and so on. Each bit in the mask parameter corresponds to a pin on the port.
581  *
582  * @retval SSP_SUCCESS              Port event data written.
583  * @retval SSP_ERR_INVALID_ARGUMENT     Port and/or mask not valid.
584  * *
585  * @note This function is re-entrant for different ports.
586  **********************************************************************************************************************/
R_IOPORT_PortEventOutputWrite(ioport_port_t port,ioport_size_t event_data,ioport_size_t mask_value)587 ssp_err_t R_IOPORT_PortEventOutputWrite (ioport_port_t port, ioport_size_t event_data, ioport_size_t mask_value)
588 {
589     ioport_size_t set_bits;
590     ioport_size_t reset_bits;
591 
592 #if ((1 == IOPORT_CFG_PARAM_CHECKING_ENABLE))
593     ssp_err_t err = SSP_SUCCESS;
594     err = r_ioport_port_exists(port);
595     IOPORT_ERROR_RETURN(SSP_SUCCESS == err, err);
596     IOPORT_ERROR_RETURN(mask_value > (ioport_size_t)0, SSP_ERR_INVALID_ARGUMENT);
597 #endif
598 
599     set_bits   = event_data & mask_value;
600     /* Cast to ensure size */
601     reset_bits = (ioport_size_t)((~event_data) & mask_value);
602 
603     HW_IOPORT_PortEventOutputDataWrite(gp_ioport_reg, port, set_bits, reset_bits);
604 
605     return SSP_SUCCESS;
606 } /* End of function R_IOPORT_PortEventOutputWrite */
607 
608 /**********************************************************************************************************************//**
609  * @brief  This function writes the event output data value to a pin. Implements ioport_api_t::pinEventOutputWrite.
610  *
611  * Using the event system enables a pin state to be stored by this function in advance of being output on the pin.
612  * The output to the pin will occur when the ELC event occurs.
613  *
614  * @retval SSP_SUCCESS              Pin event data written.
615  * @retval SSP_ERR_INVALID_ARGUMENT  Pin or value not valid.
616  *
617  * @note This function is re-entrant for different ports.
618  *
619  **********************************************************************************************************************/
R_IOPORT_PinEventOutputWrite(ioport_port_pin_t pin,ioport_level_t pin_value)620 ssp_err_t R_IOPORT_PinEventOutputWrite (ioport_port_pin_t pin, ioport_level_t pin_value)
621 {
622     ioport_size_t set_bits;
623     ioport_size_t reset_bits;
624     ioport_port_t port;
625     uint16_t      pin_to_port;
626 
627 #if ((1 == IOPORT_CFG_PARAM_CHECKING_ENABLE))
628     ssp_err_t err = SSP_SUCCESS;
629     err = r_ioport_pin_exists(pin);
630     IOPORT_ERROR_RETURN(SSP_SUCCESS == err, err);
631     IOPORT_ERROR_RETURN((pin_value == IOPORT_LEVEL_HIGH) || (pin_value == IOPORT_LEVEL_LOW), SSP_ERR_INVALID_ARGUMENT);
632 #endif
633 
634     /* Cast to ensure correct conversion of parameter. */
635     pin_to_port = (uint16_t)pin;
636     pin_to_port = pin_to_port & (uint16_t)0xFF00;
637     port = (ioport_port_t)pin_to_port;
638     set_bits   = (ioport_size_t)0;
639     reset_bits = (ioport_size_t)0;
640 
641     if (IOPORT_LEVEL_HIGH == pin_value)
642     {
643         /* Cast to ensure size */
644         set_bits = (ioport_size_t)(1U << ((ioport_size_t) pin & 0x00FFU));
645     }
646     else
647     {
648         /* Cast to ensure size */
649         reset_bits = (ioport_size_t)(1U << ((ioport_size_t) pin & 0x00FFU));
650     }
651 
652     HW_IOPORT_PinEventOutputDataWrite(gp_ioport_reg, port, set_bits, reset_bits, pin_value);
653 
654     return SSP_SUCCESS;
655 } /* End of function R_IOPORT_PinEventOutputWrite */
656 
657 /*******************************************************************************************************************//**
658  * @brief   Returns IOPort HAL driver version. Implements ioport_api_t::versionGet.
659  *
660  * @retval      SSP_SUCCESS    Version information read.
661  * @retval      SSP_ERR_ASSERTION The parameter p_data is NULL.
662  *
663  * @note This function is reentrant.
664  **********************************************************************************************************************/
R_IOPORT_VersionGet(ssp_version_t * p_data)665 ssp_err_t R_IOPORT_VersionGet (ssp_version_t * p_data)
666 {
667 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
668     /** Verify parameters are valid */
669     SSP_ASSERT(NULL != p_data);
670 #endif
671 
672     *p_data = g_ioport_version;
673 
674     return SSP_SUCCESS;
675 } /* End of function R_IOPORT_VersionGet */
676 
677 /*******************************************************************************************************************//**
678  * @brief  Configures Ethernet channel PHY mode. Implements ioport_api_t::ethModeCfg.
679  *
680  * @retval SSP_SUCCESS              Ethernet PHY mode set.
681  * @retval SSP_ERR_INVALID_ARGUMENT Channel or mode not valid.
682  * @retval SSP_ERR_UNSUPPORTED      Ethernet configuration not supported on this device.
683  *
684  * @note This function is not re-entrant.
685  **********************************************************************************************************************/
R_IOPORT_EthernetModeCfg(ioport_ethernet_channel_t channel,ioport_ethernet_mode_t mode)686 ssp_err_t R_IOPORT_EthernetModeCfg (ioport_ethernet_channel_t channel, ioport_ethernet_mode_t mode)
687 {
688     bsp_feature_ioport_t ioport_feature = {0U};
689     R_BSP_FeatureIoportGet(&ioport_feature);
690 
691     IOPORT_ERROR_RETURN(1U == ioport_feature.has_ethernet, SSP_ERR_UNSUPPORTED);
692 
693 #if ((1 == IOPORT_CFG_PARAM_CHECKING_ENABLE))
694     IOPORT_ERROR_RETURN(channel < IOPORT_ETHERNET_CHANNEL_END, SSP_ERR_INVALID_ARGUMENT);
695     IOPORT_ERROR_RETURN(mode < IOPORT_ETHERNET_MODE_END, SSP_ERR_INVALID_ARGUMENT);
696 #endif
697 
698     HW_IOPORT_EthernetModeCfg(gp_pmisc_reg, channel, mode);
699 
700     return SSP_SUCCESS;
701 } /* End of function R_IOPORT_EthModeCfg */
702 
703 /*******************************************************************************************************************//**
704  * @} (end addtogroup IOPORT)
705  **********************************************************************************************************************/
706 
707 #if ((1 == IOPORT_CFG_PARAM_CHECKING_ENABLE))
708 /******************************************************************************************************************//**
709  * @brief  Checks the existence of the valid pin as per port.
710  *
711  * @param[in]   pin                  Pin number to be used.
712  *
713  * @retval SSP_SUCCESS               Pin number is valid.
714  * @retval SSP_ERR_INVALID_ARGUMENT  An invalid pin number is used.
715  *********************************************************************************************************************/
r_ioport_pin_exists(ioport_port_pin_t pin)716 static ssp_err_t r_ioport_pin_exists(ioport_port_pin_t pin)
717 {
718     uint32_t port_local = (uint32_t) pin >> IOPORT_PRV_PORT_OFFSET;
719     uint32_t pin_local = (uint32_t) pin & 0xFFU;
720     if (port_local < g_ioport_num_ports)
721     {
722         uint32_t pin_mask = 1U << (IOPORT_PRV_EXISTS_B0_SHIFT + pin_local);
723         if (0U != (gp_ioport_exists[port_local] & pin_mask))
724         {
725             return SSP_SUCCESS;
726         }
727     }
728     return SSP_ERR_INVALID_ARGUMENT;
729 }
730 
731 /******************************************************************************************************************//**
732 * @brief  Checks the existence of the valid port.
733 *
734 * @param[in]   port                 Port number to be used.
735 *
736 * @retval SSP_SUCCESS               Port number is valid.
737 * @retval SSP_ERR_INVALID_ARGUMENT  An invalid port number is used.
738 *********************************************************************************************************************/
r_ioport_port_exists(ioport_port_t port)739 static ssp_err_t r_ioport_port_exists(ioport_port_t port)
740 {
741     uint32_t port_local = (uint32_t) port >> IOPORT_PRV_PORT_OFFSET;
742     if (port_local < g_ioport_num_ports)
743     {
744         return SSP_SUCCESS;
745     }
746     return SSP_ERR_INVALID_ARGUMENT;
747 }
748 #endif
749 
750 #if BSP_MCU_VBATT_SUPPORT
751 /*******************************************************************************************************************//**
752  * @brief Initializes VBTICTLR register based on pin configuration.
753  *
754  * @param[in,out]   p_pin_cfg       Pointer to pin configuration data.
755  *
756  * The VBTICTLR register may need to be modified based on the project's pin configuration. There is a set of pins that
757  * needs to be checked. If one of these pins is found in the pin configuration table then it will be tested to see if
758  * the appropriate VBTICTLR bit needs to be set or cleared. If one of the pins that is being searched for is not found
759  * then the accompanying VBTICTLR bit is left as-is.
760  **********************************************************************************************************************/
bsp_vbatt_init(ioport_cfg_t const * const p_pin_cfg)761 static void bsp_vbatt_init (ioport_cfg_t const * const p_pin_cfg)
762 {
763     uint32_t pin_index;
764     uint32_t vbatt_index;
765     uint8_t  local_vbtictlr_set;    ///< Will hold bits to set in VBTICTLR
766     uint8_t  local_vbtictlr_clear;  ///< Will hold bits to clear in VBTICTLR
767 
768     /** Make no changes unless required. */
769     local_vbtictlr_set = 0U;
770     local_vbtictlr_clear = 0U;
771 
772     /** Must loop over all pins as pin configuration table is unordered. */
773     for (pin_index = 0U; pin_index < p_pin_cfg->number_of_pins; pin_index++)
774     {
775         /** Loop over VBATT input pins. */
776         for (vbatt_index = 0U; vbatt_index < (sizeof(g_vbatt_pins_input)/sizeof(g_vbatt_pins_input[0])); vbatt_index++)
777         {
778             if (p_pin_cfg->p_pin_cfg_data[pin_index].pin == g_vbatt_pins_input[vbatt_index])
779             {
780                 /** Get PSEL value for pin. */
781                 uint32_t pfs_psel_value = p_pin_cfg->p_pin_cfg_data[pin_index].pin_cfg & BSP_PRV_PFS_PSEL_MASK;
782 
783                 /** Check if pin is being used for RTC or AGT use. */
784                 if ((IOPORT_PERIPHERAL_AGT == pfs_psel_value) || (IOPORT_PERIPHERAL_CLKOUT_COMP_RTC == pfs_psel_value))
785                 {
786                     /** Bit should be set to 1. */
787                     local_vbtictlr_set |= (uint8_t)(1U << vbatt_index);
788                 }
789                 else
790                 {
791                     /** Bit should be cleared to 0. */
792                     local_vbtictlr_clear |= (uint8_t)(1U << vbatt_index);
793                 }
794             }
795         }
796     }
797 
798     /** Disable write protection on VBTICTLR. */
799     R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_OM_LPC_BATT);
800 
801     /** Read value, set and clear bits as needed and write back. */
802     uint8_t local_vbtictlr = R_SYSTEM->VBTICTLR;
803     local_vbtictlr |= local_vbtictlr_set;               ///< Set appropriate bits
804     local_vbtictlr &= (uint8_t)~local_vbtictlr_clear;   ///< Clear appropriate bits
805 
806     R_SYSTEM->VBTICTLR = local_vbtictlr;
807 
808     /** Enable write protection on VBTICTLR. */
809     R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_OM_LPC_BATT);
810 }
811 
812 #endif
813