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