1 /***********************************************************************************************************************
2 * Copyright [2020-2022] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved.
3 *
4 * This software and documentation are supplied by Renesas Electronics America Inc. and may only be used with products
5 * of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. Renesas products are
6 * sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for the selection and use
7 * of Renesas products and Renesas assumes no liability. No license, express or implied, to any intellectual property
8 * right is granted by Renesas. This software is protected under all applicable laws, including copyright laws. Renesas
9 * reserves the right to change or discontinue this software and/or this documentation. THE SOFTWARE AND DOCUMENTATION
10 * IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND TO THE FULLEST EXTENT
11 * PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, INCLUDING WARRANTIES
12 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE SOFTWARE OR
13 * DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. TO THE MAXIMUM
14 * EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR DOCUMENTATION
15 * (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, INCLUDING,
16 * WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY LOST PROFITS,
17 * OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE POSSIBILITY
18 * OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS.
19 **********************************************************************************************************************/
20
21 /***********************************************************************************************************************
22 * Includes
23 **********************************************************************************************************************/
24 #include <stdint.h>
25 #include "bsp_api.h"
26 #include "r_ioport.h"
27 #include "r_ioport_api.h"
28
29 /***********************************************************************************************************************
30 * Macro definitions
31 **********************************************************************************************************************/
32
33 /* "PORT" in ASCII, used to determine if the module is open */
34 #define IOPORT_OPEN (0x504F5254U)
35 #define IOPORT_CLOSED (0x00000000U)
36
37 /* Mask to get PSEL bitfield from PFS register. */
38 #define BSP_PRV_PFS_PSEL_MASK (0x1F000000UL)
39
40 /* Shift to get pin 0 on a package in extended data. */
41 #define IOPORT_PRV_EXISTS_B0_SHIFT (16UL)
42
43 /* Mask to determine if any pins on port exist on this package. */
44 #define IOPORT_PRV_PORT_EXISTS_MASK (0xFFFF0000U)
45
46 /* Shift to get port in bsp_io_port_t and bsp_io_port_pin_t enums. */
47 #define IOPORT_PRV_PORT_OFFSET (8U)
48
49 #ifndef BSP_MCU_VBATT_SUPPORT
50 #define BSP_MCU_VBATT_SUPPORT (0U)
51 #endif
52
53 #define IOPORT_PRV_PORT_BITS (0xFF00U)
54 #define IOPORT_PRV_PIN_BITS (0x00FFU)
55
56 #define IOPORT_PRV_PCNTR_OFFSET 0x00000020U
57
58 #define IOPORT_PRV_PERIPHERAL_FUNCTION (1U << 16)
59 #define IOPORT_PRV_CLEAR_BITS_MASK (0x1F01FCD5U) ///< Zero bits in mask must be written as zero to PFS register
60
61 #define IOPORT_PRV_8BIT_MASK (0xFFU)
62 #define IOPORT_PRV_16BIT_MASK (0xFFFFU)
63 #define IOPORT_PRV_UPPER_16BIT_MASK (0xFFFF0000U)
64 #define IOPORT_PRV_PFENET_MASK (0x30U)
65
66 #define IOPORT_PRV_SET_PWPR_PFSWE (0x40U)
67 #define IOPORT_PRV_SET_PWPR_BOWI (0x80U)
68
69 #define IOPORT_PRV_PORT_ADDRESS(port_number) ((uint32_t) (R_PORT1 - R_PORT0) * (port_number) + R_PORT0)
70
71 /***********************************************************************************************************************
72 * Typedef definitions
73 **********************************************************************************************************************/
74
75 /***********************************************************************************************************************
76 * Private function prototypes
77 **********************************************************************************************************************/
78 static void r_ioport_pins_config(const ioport_cfg_t * p_cfg);
79
80 static void r_ioport_hw_pin_event_output_data_write(bsp_io_port_t port,
81 ioport_size_t set_value,
82 ioport_size_t reset_value,
83 bsp_io_level_t pin_level);
84
85 static void r_ioport_pfs_write(bsp_io_port_pin_t pin, uint32_t value);
86
87 #if BSP_MCU_VBATT_SUPPORT
88 static void bsp_vbatt_init(ioport_cfg_t const * const p_pin_cfg); // Used internally by BSP
89
90 #endif
91
92 /***********************************************************************************************************************
93 * Private global variables
94 **********************************************************************************************************************/
95
96 /***********************************************************************************************************************
97 * Global Variables
98 **********************************************************************************************************************/
99
100 /* IOPort Implementation of IOPort Driver */
101 const ioport_api_t g_ioport_on_ioport =
102 {
103 .open = R_IOPORT_Open,
104 .close = R_IOPORT_Close,
105 .pinsCfg = R_IOPORT_PinsCfg,
106 .pinCfg = R_IOPORT_PinCfg,
107 .pinEventInputRead = R_IOPORT_PinEventInputRead,
108 .pinEventOutputWrite = R_IOPORT_PinEventOutputWrite,
109 .pinEthernetModeCfg = R_IOPORT_EthernetModeCfg,
110 .pinRead = R_IOPORT_PinRead,
111 .pinWrite = R_IOPORT_PinWrite,
112 .portDirectionSet = R_IOPORT_PortDirectionSet,
113 .portEventInputRead = R_IOPORT_PortEventInputRead,
114 .portEventOutputWrite = R_IOPORT_PortEventOutputWrite,
115 .portRead = R_IOPORT_PortRead,
116 .portWrite = R_IOPORT_PortWrite,
117 };
118
119 #if BSP_MCU_VBATT_SUPPORT
120 static const bsp_io_port_pin_t g_vbatt_pins_input[] =
121 {
122 BSP_IO_PORT_04_PIN_02, ///< Associated with VBTICTLR->VCH0INEN
123 BSP_IO_PORT_04_PIN_03, ///< Associated with VBTICTLR->VCH1INEN
124 BSP_IO_PORT_04_PIN_04 ///< Associated with VBTICTLR->VCH2INEN
125 };
126 #endif
127
128 /*******************************************************************************************************************//**
129 * @addtogroup IOPORT
130 * @{
131 **********************************************************************************************************************/
132
133 /***********************************************************************************************************************
134 * Functions
135 **********************************************************************************************************************/
136
137 /*******************************************************************************************************************//**
138 * Initializes internal driver data, then calls pin configuration function to configure pins.
139 *
140 * @retval FSP_SUCCESS Pin configuration data written to PFS register(s)
141 * @retval FSP_ERR_ASSERTION NULL pointer
142 * @retval FSP_ERR_ALREADY_OPEN Module is already open.
143 **********************************************************************************************************************/
R_IOPORT_Open(ioport_ctrl_t * const p_ctrl,const ioport_cfg_t * p_cfg)144 fsp_err_t R_IOPORT_Open (ioport_ctrl_t * const p_ctrl, const ioport_cfg_t * p_cfg)
145 {
146 ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
147
148 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
149 FSP_ASSERT(NULL != p_instance_ctrl);
150 FSP_ASSERT(NULL != p_cfg);
151 FSP_ASSERT(NULL != p_cfg->p_pin_cfg_data);
152 FSP_ERROR_RETURN(IOPORT_OPEN != p_instance_ctrl->open, FSP_ERR_ALREADY_OPEN);
153 #else
154 FSP_PARAMETER_NOT_USED(p_ctrl);
155 #endif
156
157 /* Set driver status to open */
158 p_instance_ctrl->open = IOPORT_OPEN;
159
160 r_ioport_pins_config(p_cfg);
161
162 return FSP_SUCCESS;
163 }
164
165 /*******************************************************************************************************************//**
166 * Resets IOPORT registers. Implements @ref ioport_api_t::close
167 *
168 * @retval FSP_SUCCESS The IOPORT was successfully uninitialized
169 * @retval FSP_ERR_ASSERTION p_ctrl was NULL
170 * @retval FSP_ERR_NOT_OPEN The module has not been opened
171 *
172 **********************************************************************************************************************/
R_IOPORT_Close(ioport_ctrl_t * const p_ctrl)173 fsp_err_t R_IOPORT_Close (ioport_ctrl_t * const p_ctrl)
174 {
175 ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
176
177 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
178 FSP_ASSERT(NULL != p_instance_ctrl);
179 FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
180 #else
181 FSP_PARAMETER_NOT_USED(p_ctrl);
182 #endif
183
184 /* Set state to closed */
185 p_instance_ctrl->open = IOPORT_CLOSED;
186
187 return FSP_SUCCESS;
188 }
189
190 /*******************************************************************************************************************//**
191 * Configures the functions of multiple pins by loading configuration data into pin PFS registers.
192 * Implements @ref ioport_api_t::pinsCfg.
193 *
194 * This function initializes the supplied list of PmnPFS registers with the supplied values. This data can be generated
195 * by the Pins tab of the RA Configuration editor or manually by the developer. Different pin configurations can be
196 * loaded for different situations such as low power modes and testing.
197 *
198 * @retval FSP_SUCCESS Pin configuration data written to PFS register(s)
199 * @retval FSP_ERR_NOT_OPEN The module has not been opened
200 * @retval FSP_ERR_ASSERTION NULL pointer
201 **********************************************************************************************************************/
R_IOPORT_PinsCfg(ioport_ctrl_t * const p_ctrl,const ioport_cfg_t * p_cfg)202 fsp_err_t R_IOPORT_PinsCfg (ioport_ctrl_t * const p_ctrl, const ioport_cfg_t * p_cfg)
203 {
204 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
205 ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
206 FSP_ASSERT(NULL != p_instance_ctrl);
207 FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
208 FSP_ASSERT(NULL != p_cfg);
209 FSP_ASSERT(NULL != p_cfg->p_pin_cfg_data);
210 #else
211 FSP_PARAMETER_NOT_USED(p_ctrl);
212 #endif
213
214 r_ioport_pins_config(p_cfg);
215
216 return FSP_SUCCESS;
217 }
218
219 /*******************************************************************************************************************//**
220 * Configures the settings of a pin. Implements @ref ioport_api_t::pinCfg.
221 *
222 * @retval FSP_SUCCESS Pin configured
223 * @retval FSP_ERR_NOT_OPEN The module has not been opened
224 * @retval FSP_ERR_ASSERTION NULL pointer
225 *
226 * @note This function is re-entrant for different pins.
227 * This function will change the configuration of the pin with the new configuration. For example it is not possible
228 * with this function to change the drive strength of a pin while leaving all the other pin settings unchanged. To
229 * achieve this the original settings with the required change will need to be written using this function.
230 **********************************************************************************************************************/
R_IOPORT_PinCfg(ioport_ctrl_t * const p_ctrl,bsp_io_port_pin_t pin,uint32_t cfg)231 fsp_err_t R_IOPORT_PinCfg (ioport_ctrl_t * const p_ctrl, bsp_io_port_pin_t pin, uint32_t cfg)
232 {
233 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
234 ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
235 FSP_ASSERT(NULL != p_instance_ctrl);
236 FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
237 #else
238 FSP_PARAMETER_NOT_USED(p_ctrl);
239 #endif
240
241 #if BSP_MCU_VBATT_SUPPORT
242
243 /* Create temporary structure for handling VBATT pins. */
244 ioport_cfg_t temp_cfg;
245 ioport_pin_cfg_t temp_pin_cfg;
246
247 temp_pin_cfg.pin = pin;
248 temp_pin_cfg.pin_cfg = cfg;
249
250 temp_cfg.number_of_pins = 1U;
251 temp_cfg.p_pin_cfg_data = &temp_pin_cfg;
252
253 /* Handle any VBATT domain pin configuration. */
254 bsp_vbatt_init(&temp_cfg);
255 #endif
256
257 R_BSP_PinAccessEnable();
258
259 r_ioport_pfs_write(pin, cfg);
260
261 R_BSP_PinAccessDisable();
262
263 return FSP_SUCCESS;
264 }
265
266 /*******************************************************************************************************************//**
267 * Reads the level on a pin. Implements @ref ioport_api_t::pinRead.
268 *
269 * @retval FSP_SUCCESS Pin read
270 * @retval FSP_ERR_ASSERTION NULL pointer
271 * @retval FSP_ERR_NOT_OPEN The module has not been opened
272 *
273 * @note This function is re-entrant for different pins.
274 **********************************************************************************************************************/
R_IOPORT_PinRead(ioport_ctrl_t * const p_ctrl,bsp_io_port_pin_t pin,bsp_io_level_t * p_pin_value)275 fsp_err_t R_IOPORT_PinRead (ioport_ctrl_t * const p_ctrl, bsp_io_port_pin_t pin, bsp_io_level_t * p_pin_value)
276 {
277 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
278 ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
279 FSP_ASSERT(NULL != p_instance_ctrl);
280 FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
281 FSP_ASSERT(NULL != p_pin_value);
282 #else
283 FSP_PARAMETER_NOT_USED(p_ctrl);
284 #endif
285
286 *p_pin_value = (bsp_io_level_t) R_BSP_PinRead(pin);
287
288 return FSP_SUCCESS;
289 }
290
291 /*******************************************************************************************************************//**
292 * Reads the value on an IO port. Implements @ref ioport_api_t::portRead.
293 *
294 * The specified port will be read, and the levels for all the pins will be returned.
295 * Each bit in the returned value corresponds to a pin on the port. For example, bit 7 corresponds
296 * to pin 7, bit 6 to pin 6, and so on.
297 *
298 * @retval FSP_SUCCESS Port read
299 * @retval FSP_ERR_ASSERTION NULL pointer
300 * @retval FSP_ERR_NOT_OPEN The module has not been opened
301 *
302 * @note This function is re-entrant for different ports.
303 **********************************************************************************************************************/
R_IOPORT_PortRead(ioport_ctrl_t * const p_ctrl,bsp_io_port_t port,ioport_size_t * p_port_value)304 fsp_err_t R_IOPORT_PortRead (ioport_ctrl_t * const p_ctrl, bsp_io_port_t port, ioport_size_t * p_port_value)
305 {
306 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
307 ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
308 FSP_ASSERT(NULL != p_instance_ctrl);
309 FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
310 FSP_ASSERT(NULL != p_port_value);
311 #else
312 FSP_PARAMETER_NOT_USED(p_ctrl);
313 #endif
314
315 /* Get the port address */
316 R_PORT0_Type * p_ioport_regs = IOPORT_PRV_PORT_ADDRESS((port >> IOPORT_PRV_PORT_OFFSET) & IOPORT_PRV_8BIT_MASK);
317
318 /* Read current value of PCNTR2 register for the specified port */
319 *p_port_value = p_ioport_regs->PCNTR2 & IOPORT_PRV_16BIT_MASK;
320
321 return FSP_SUCCESS;
322 }
323
324 /*******************************************************************************************************************//**
325 * Writes to multiple pins on a port. Implements @ref ioport_api_t::portWrite.
326 *
327 * The input value will be written to the specified port. Each bit in the value parameter corresponds to a bit
328 * on the port. For example, bit 7 corresponds to pin 7, bit 6 to pin 6, and so on.
329 * Each bit in the mask parameter corresponds to a pin on the port.
330 *
331 * Only the bits with the corresponding bit in the mask value set will be updated.
332 * For example, value = 0xFFFF, mask = 0x0003 results in only bits 0 and 1 being updated.
333 *
334 * @retval FSP_SUCCESS Port written to
335 * @retval FSP_ERR_INVALID_ARGUMENT The port and/or mask not valid
336 * @retval FSP_ERR_NOT_OPEN The module has not been opened
337 * @retval FSP_ERR_ASSERTION NULL pointerd
338 *
339 * @note This function is re-entrant for different ports. This function makes use of the PCNTR3 register to atomically
340 * modify the levels on the specified pins on a port.
341 **********************************************************************************************************************/
R_IOPORT_PortWrite(ioport_ctrl_t * const p_ctrl,bsp_io_port_t port,ioport_size_t value,ioport_size_t mask)342 fsp_err_t R_IOPORT_PortWrite (ioport_ctrl_t * const p_ctrl, bsp_io_port_t port, ioport_size_t value, ioport_size_t mask)
343 {
344 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
345 ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
346 FSP_ASSERT(NULL != p_instance_ctrl);
347 FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
348 FSP_ERROR_RETURN(mask > (ioport_size_t) 0, FSP_ERR_INVALID_ARGUMENT);
349 #else
350 FSP_PARAMETER_NOT_USED(p_ctrl);
351 #endif
352
353 ioport_size_t setbits;
354 ioport_size_t clrbits;
355
356 /* High bits */
357 setbits = value & mask;
358
359 /* Low bits */
360 /* Cast to ensure size */
361 clrbits = (ioport_size_t) ((~value) & mask);
362
363 /* Get the port address */
364 R_PORT0_Type * p_ioport_regs = IOPORT_PRV_PORT_ADDRESS((port >> IOPORT_PRV_PORT_OFFSET) & IOPORT_PRV_8BIT_MASK);
365
366 /* PCNTR3 register: lower word = set data, upper word = reset_data */
367 p_ioport_regs->PCNTR3 = (uint32_t) (((uint32_t) clrbits << 16) | setbits);
368
369 return FSP_SUCCESS;
370 }
371
372 /*******************************************************************************************************************//**
373 * Sets a pin's output either high or low. Implements @ref ioport_api_t::pinWrite.
374 *
375 * @retval FSP_SUCCESS Pin written to
376 * @retval FSP_ERR_INVALID_ARGUMENT The pin and/or level not valid
377 * @retval FSP_ERR_NOT_OPEN The module has not been opene
378 * @retval FSP_ERR_ASSERTION NULL pointerd
379 *
380 * @note This function is re-entrant for different pins. This function makes use of the PCNTR3 register to atomically
381 * modify the level on the specified pin on a port.
382 **********************************************************************************************************************/
R_IOPORT_PinWrite(ioport_ctrl_t * const p_ctrl,bsp_io_port_pin_t pin,bsp_io_level_t level)383 fsp_err_t R_IOPORT_PinWrite (ioport_ctrl_t * const p_ctrl, bsp_io_port_pin_t pin, bsp_io_level_t level)
384 {
385 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
386 ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
387 FSP_ASSERT(NULL != p_instance_ctrl);
388 FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
389 FSP_ERROR_RETURN(level <= BSP_IO_LEVEL_HIGH, FSP_ERR_INVALID_ARGUMENT);
390 #else
391 FSP_PARAMETER_NOT_USED(p_ctrl);
392 #endif
393
394 ioport_size_t setbits = 0U;
395 ioport_size_t clrbits = 0U;
396 bsp_io_port_t port = (bsp_io_port_t) (IOPORT_PRV_PORT_BITS & (ioport_size_t) pin);
397
398 ioport_size_t shift = IOPORT_PRV_PIN_BITS & (ioport_size_t) pin;
399 ioport_size_t pin_mask = (ioport_size_t) (1U << shift);
400
401 if (BSP_IO_LEVEL_LOW == level)
402 {
403 clrbits = pin_mask;
404 }
405 else
406 {
407 setbits = pin_mask;
408 }
409
410 /* PCNTR register is updated instead of using PFS as access is atomic and PFS requires seperate enable/disable
411 * using PWPR register */
412
413 /* Get the port address */
414 R_PORT0_Type * p_ioport_regs = IOPORT_PRV_PORT_ADDRESS((port >> IOPORT_PRV_PORT_OFFSET) & IOPORT_PRV_8BIT_MASK);
415
416 /* PCNTR3 register: lower word = set data, upper word = reset_data */
417 p_ioport_regs->PCNTR3 = (uint32_t) (((uint32_t) clrbits << 16) | setbits);
418
419 return FSP_SUCCESS;
420 }
421
422 /*******************************************************************************************************************//**
423 * Sets the direction of individual pins on a port. Implements @ref ioport_api_t::portDirectionSet().
424 *
425 * Multiple pins on a port can be set to inputs or outputs at once.
426 * Each bit in the mask parameter corresponds to a pin on the port. For example, bit 7 corresponds to
427 * 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
428 * an input or an output as specified by the direction values. If a mask bit is set to 0 then the direction of
429 * the pin will not be changed.
430 *
431 * @retval FSP_SUCCESS Port direction updated
432 * @retval FSP_ERR_INVALID_ARGUMENT The port and/or mask not valid
433 * @retval FSP_ERR_NOT_OPEN The module has not been opened
434 * @retval FSP_ERR_ASSERTION NULL pointer
435 *
436 * @note This function is re-entrant for different ports.
437 **********************************************************************************************************************/
R_IOPORT_PortDirectionSet(ioport_ctrl_t * const p_ctrl,bsp_io_port_t port,ioport_size_t direction_values,ioport_size_t mask)438 fsp_err_t R_IOPORT_PortDirectionSet (ioport_ctrl_t * const p_ctrl,
439 bsp_io_port_t port,
440 ioport_size_t direction_values,
441 ioport_size_t mask)
442 {
443 uint32_t orig_value;
444 uint32_t set_bits;
445 uint32_t clr_bits;
446 uint32_t write_value;
447
448 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
449 ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
450 FSP_ASSERT(NULL != p_instance_ctrl);
451 FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
452 FSP_ERROR_RETURN(mask > (ioport_size_t) 0, FSP_ERR_INVALID_ARGUMENT);
453 #else
454 FSP_PARAMETER_NOT_USED(p_ctrl);
455 #endif
456
457 /* Get the port address */
458 R_PORT0_Type * p_ioport_regs = IOPORT_PRV_PORT_ADDRESS((port >> IOPORT_PRV_PORT_OFFSET) & IOPORT_PRV_8BIT_MASK);
459
460 /* Read current value of PCNTR1 register for the specified port */
461 orig_value = p_ioport_regs->PCNTR1;
462
463 /* High bits */
464 set_bits = direction_values & mask;
465
466 /* Low bits */
467 /* Cast to ensure size */
468 clr_bits = (uint32_t) ((~direction_values) & mask);
469
470 /* New value to write to port direction register */
471 write_value = orig_value;
472 write_value |= set_bits;
473
474 /* Clear bits as needed */
475 write_value &= ~clr_bits;
476
477 p_ioport_regs->PCNTR1 = write_value;
478
479 return FSP_SUCCESS;
480 }
481
482 /*******************************************************************************************************************//**
483 * Reads the value of the event input data. Implements @ref ioport_api_t::portEventInputRead().
484 *
485 * The event input data for the port will be read. Each bit in the returned value corresponds to a pin on the port.
486 * For example, bit 7 corresponds to pin 7, bit 6 to pin 6, and so on.
487 *
488 * The port event data is captured in response to a trigger from the ELC. This function enables this data to be read.
489 * Using the event system allows the captured data to be stored when it occurs and then read back at a later time.
490 *
491 * @retval FSP_SUCCESS Port read
492 * @retval FSP_ERR_INVALID_ARGUMENT Port not a valid ELC port
493 * @retval FSP_ERR_ASSERTION NULL pointer
494 * @retval FSP_ERR_NOT_OPEN The module has not been opened
495 *
496 * @note This function is re-entrant for different ports.
497 *
498 **********************************************************************************************************************/
R_IOPORT_PortEventInputRead(ioport_ctrl_t * const p_ctrl,bsp_io_port_t port,ioport_size_t * p_event_data)499 fsp_err_t R_IOPORT_PortEventInputRead (ioport_ctrl_t * const p_ctrl, bsp_io_port_t port, ioport_size_t * p_event_data)
500 {
501 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
502 ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
503 FSP_ASSERT(NULL != p_instance_ctrl);
504 FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
505 FSP_ASSERT(NULL != p_event_data);
506 uint32_t port_number = port >> IOPORT_PRV_PORT_OFFSET;
507 FSP_ERROR_RETURN((BSP_FEATURE_IOPORT_ELC_PORTS & (1 << port_number)), FSP_ERR_INVALID_ARGUMENT);
508 #else
509 FSP_PARAMETER_NOT_USED(p_ctrl);
510 #endif
511
512 /* Get the port address */
513 R_PORT0_Type * p_ioport_regs = IOPORT_PRV_PORT_ADDRESS(port >> IOPORT_PRV_PORT_OFFSET & IOPORT_PRV_8BIT_MASK);
514
515 /* Read current value of EIDR value from PCNTR2 register for the specified port */
516 *p_event_data = p_ioport_regs->PCNTR2_b.EIDR;
517
518 return FSP_SUCCESS;
519 }
520
521 /*******************************************************************************************************************//**
522 * Reads the value of the event input data of a specific pin. Implements @ref ioport_api_t::pinEventInputRead.
523 *
524 * The pin event data is captured in response to a trigger from the ELC. This function enables this data to be read.
525 * Using the event system allows the captured data to be stored when it occurs and then read back at a later time.
526 *
527 * @retval FSP_SUCCESS Pin read
528 * @retval FSP_ERR_ASSERTION NULL pointer
529 * @retval FSP_ERR_NOT_OPEN The module has not been opened
530 * @retval FSP_ERR_INVALID_ARGUMENT Port is not valid ELC PORT.
531 *
532 * @note This function is re-entrant.
533 *
534 **********************************************************************************************************************/
R_IOPORT_PinEventInputRead(ioport_ctrl_t * const p_ctrl,bsp_io_port_pin_t pin,bsp_io_level_t * p_pin_event)535 fsp_err_t R_IOPORT_PinEventInputRead (ioport_ctrl_t * const p_ctrl, bsp_io_port_pin_t pin, bsp_io_level_t * p_pin_event)
536 {
537 ioport_size_t portvalue;
538 ioport_size_t mask;
539
540 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
541 ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
542 FSP_ASSERT(NULL != p_instance_ctrl);
543 FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
544 FSP_ASSERT(NULL != p_pin_event);
545 uint32_t port_number = pin >> IOPORT_PRV_PORT_OFFSET;
546 FSP_ERROR_RETURN((BSP_FEATURE_IOPORT_ELC_PORTS & (1 << port_number)), FSP_ERR_INVALID_ARGUMENT);
547 #else
548 FSP_PARAMETER_NOT_USED(p_ctrl);
549 #endif
550
551 /* Get the port address */
552 R_PORT0_Type * p_ioport_regs = IOPORT_PRV_PORT_ADDRESS((pin >> IOPORT_PRV_PORT_OFFSET) & IOPORT_PRV_8BIT_MASK);
553
554 /* Read current value of EIDR value from PCNTR2 register for the specified port */
555 portvalue = p_ioport_regs->PCNTR2_b.EIDR;
556 mask = (ioport_size_t) (1U << (IOPORT_PRV_PIN_BITS & (bsp_io_port_t) pin));
557
558 if ((portvalue & mask) == mask)
559 {
560 *p_pin_event = BSP_IO_LEVEL_HIGH;
561 }
562 else
563 {
564 *p_pin_event = BSP_IO_LEVEL_LOW;
565 }
566
567 return FSP_SUCCESS;
568 }
569
570 /*******************************************************************************************************************//**
571 * This function writes the set and reset event output data for a port. Implements
572 * @ref ioport_api_t::portEventOutputWrite.
573 *
574 * Using the event system enables a port state to be stored by this function in advance of being output on the port.
575 * The output to the port will occur when the ELC event occurs.
576 *
577 * The input value will be written to the specified port when an ELC event configured for that port occurs.
578 * Each bit in the value parameter corresponds to a bit on the port. For example, bit 7 corresponds to pin 7,
579 * bit 6 to pin 6, and so on. Each bit in the mask parameter corresponds to a pin on the port.
580 *
581 * @retval FSP_SUCCESS Port event data written
582 * @retval FSP_ERR_INVALID_ARGUMENT Port or Mask not valid
583 * @retval FSP_ERR_NOT_OPEN The module has not been opened
584 * @retval FSP_ERR_ASSERTION NULL pointer
585 *
586 * @note This function is re-entrant for different ports.
587 **********************************************************************************************************************/
R_IOPORT_PortEventOutputWrite(ioport_ctrl_t * const p_ctrl,bsp_io_port_t port,ioport_size_t event_data,ioport_size_t mask_value)588 fsp_err_t R_IOPORT_PortEventOutputWrite (ioport_ctrl_t * const p_ctrl,
589 bsp_io_port_t port,
590 ioport_size_t event_data,
591 ioport_size_t mask_value)
592 {
593 ioport_size_t set_bits;
594 ioport_size_t reset_bits;
595
596 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
597 ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
598 FSP_ASSERT(NULL != p_instance_ctrl);
599 FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
600 FSP_ERROR_RETURN(mask_value > (ioport_size_t) 0, FSP_ERR_INVALID_ARGUMENT);
601 uint32_t port_number = port >> IOPORT_PRV_PORT_OFFSET;
602 FSP_ERROR_RETURN((BSP_FEATURE_IOPORT_ELC_PORTS & (1 << port_number)), FSP_ERR_INVALID_ARGUMENT);
603 #else
604 FSP_PARAMETER_NOT_USED(p_ctrl);
605 #endif
606
607 set_bits = event_data & mask_value;
608
609 /* Cast to ensure size */
610 reset_bits = (ioport_size_t) ((~event_data) & mask_value);
611
612 /* Get the port address */
613 R_PORT0_Type * p_ioport_regs = IOPORT_PRV_PORT_ADDRESS((port >> IOPORT_PRV_PORT_OFFSET) & IOPORT_PRV_8BIT_MASK);
614
615 /* PCNTR4 register: lower word = set data, upper word = reset_data */
616 p_ioport_regs->PCNTR4 = (uint32_t) (((uint32_t) reset_bits << 16) | set_bits);
617
618 return FSP_SUCCESS;
619 }
620
621 /**********************************************************************************************************************//**
622 * This function writes the event output data value to a pin. Implements @ref ioport_api_t::pinEventOutputWrite.
623 *
624 * Using the event system enables a pin state to be stored by this function in advance of being output on the pin.
625 * The output to the pin will occur when the ELC event occurs.
626 *
627 * @retval FSP_SUCCESS Pin event data written
628 * @retval FSP_ERR_INVALID_ARGUMENT Port or Pin or value not valid
629 * @retval FSP_ERR_NOT_OPEN The module has not been opened
630 * @retval FSP_ERR_ASSERTION NULL pointer
631 *
632 * @note This function is re-entrant for different ports.
633 *
634 **********************************************************************************************************************/
R_IOPORT_PinEventOutputWrite(ioport_ctrl_t * const p_ctrl,bsp_io_port_pin_t pin,bsp_io_level_t pin_value)635 fsp_err_t R_IOPORT_PinEventOutputWrite (ioport_ctrl_t * const p_ctrl, bsp_io_port_pin_t pin, bsp_io_level_t pin_value)
636 {
637 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
638 ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
639 FSP_ASSERT(NULL != p_instance_ctrl);
640 FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
641 FSP_ERROR_RETURN((pin_value == BSP_IO_LEVEL_HIGH) || (pin_value == BSP_IO_LEVEL_LOW), FSP_ERR_INVALID_ARGUMENT);
642 uint32_t port_number = pin >> IOPORT_PRV_PORT_OFFSET;
643 FSP_ERROR_RETURN((BSP_FEATURE_IOPORT_ELC_PORTS & (1 << port_number)), FSP_ERR_INVALID_ARGUMENT);
644 #else
645 FSP_PARAMETER_NOT_USED(p_ctrl);
646 #endif
647
648 ioport_size_t set_bits;
649 ioport_size_t reset_bits;
650 bsp_io_port_t port;
651 uint16_t pin_to_port;
652
653 /* Cast to ensure correct conversion of parameter. */
654 pin_to_port = (uint16_t) pin;
655 pin_to_port = pin_to_port & (uint16_t) IOPORT_PRV_PORT_BITS;
656 port = (bsp_io_port_t) pin_to_port;
657 set_bits = (ioport_size_t) 0;
658 reset_bits = (ioport_size_t) 0;
659
660 if (BSP_IO_LEVEL_HIGH == pin_value)
661 {
662 /* Cast to ensure size */
663 set_bits = (ioport_size_t) (1U << ((ioport_size_t) pin & IOPORT_PRV_PIN_BITS));
664 }
665 else
666 {
667 /* Cast to ensure size */
668 reset_bits = (ioport_size_t) (1U << ((ioport_size_t) pin & IOPORT_PRV_PIN_BITS));
669 }
670
671 r_ioport_hw_pin_event_output_data_write(port, set_bits, reset_bits, pin_value);
672
673 return FSP_SUCCESS;
674 }
675
676 /***********************************************************************************************************************
677 * DEPRECATED Configures Ethernet channel PHY mode. Implements @ref ioport_api_t::pinEthernetModeCfg.
678 *
679 * @retval FSP_SUCCESS Ethernet PHY mode set
680 * @retval FSP_ERR_INVALID_ARGUMENT Channel or mode not valid
681 * @retval FSP_ERR_UNSUPPORTED Ethernet configuration not supported on this device.
682 * @retval FSP_ERR_NOT_OPEN The module has not been opened
683 * @retval FSP_ERR_ASSERTION NULL pointer
684 *
685 * @note This function is not re-entrant.
686 **********************************************************************************************************************/
R_IOPORT_EthernetModeCfg(ioport_ctrl_t * const p_ctrl,ioport_ethernet_channel_t channel,ioport_ethernet_mode_t mode)687 fsp_err_t R_IOPORT_EthernetModeCfg (ioport_ctrl_t * const p_ctrl,
688 ioport_ethernet_channel_t channel,
689 ioport_ethernet_mode_t mode)
690 {
691 FSP_ERROR_RETURN(1U == BSP_FEATURE_IOPORT_HAS_ETHERNET, FSP_ERR_UNSUPPORTED);
692
693 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
694 ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
695 FSP_ASSERT(NULL != p_instance_ctrl);
696 FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
697 FSP_ERROR_RETURN(channel < IOPORT_ETHERNET_CHANNEL_END, FSP_ERR_INVALID_ARGUMENT);
698 FSP_ERROR_RETURN(mode < IOPORT_ETHERNET_MODE_END, FSP_ERR_INVALID_ARGUMENT);
699 #else
700 FSP_PARAMETER_NOT_USED(p_ctrl);
701 FSP_PARAMETER_NOT_USED(channel);
702 #endif
703
704 R_PMISC->PFENET = (uint8_t) mode;
705
706 return FSP_SUCCESS;
707 }
708
709 /*******************************************************************************************************************//**
710 * @} (end addtogroup IOPORT)
711 **********************************************************************************************************************/
712
713 /***********************************************************************************************************************
714 * Private Functions
715 **********************************************************************************************************************/
716
717 /*******************************************************************************************************************//**
718 * Configures pins.
719 *
720 * @param[in] p_cfg Pin configuration data
721 **********************************************************************************************************************/
r_ioport_pins_config(const ioport_cfg_t * p_cfg)722 void r_ioport_pins_config (const ioport_cfg_t * p_cfg)
723 {
724 #if BSP_MCU_VBATT_SUPPORT
725
726 /* Handle any VBATT domain pin configuration. */
727 bsp_vbatt_init(p_cfg);
728 #endif
729
730 uint16_t pin_count;
731 ioport_cfg_t * p_pin_data;
732
733 p_pin_data = (ioport_cfg_t *) p_cfg;
734
735 R_BSP_PinAccessEnable(); // Protect PWPR from re-entrancy
736
737 for (pin_count = 0U; pin_count < p_pin_data->number_of_pins; pin_count++)
738 {
739 r_ioport_pfs_write(p_pin_data->p_pin_cfg_data[pin_count].pin, p_pin_data->p_pin_cfg_data[pin_count].pin_cfg);
740 }
741
742 R_BSP_PinAccessDisable();
743 }
744
745 /*******************************************************************************************************************//**
746 * Writes the set and clear values on a pin of the port when an ELC event occurs. This allows accurate timing of
747 * pin output level.
748 *
749 * @param[in] port Port to read event data
750 * @param[in] set_value Bit in the port to set high (1 = that bit will be set high)
751 * @param[in] reset_value Bit in the port to clear low (1 = that bit will be cleared low)
752 * @param[in] pin_level Event data for pin
753 **********************************************************************************************************************/
r_ioport_hw_pin_event_output_data_write(bsp_io_port_t port,ioport_size_t set_value,ioport_size_t reset_value,bsp_io_level_t pin_level)754 static void r_ioport_hw_pin_event_output_data_write (bsp_io_port_t port,
755 ioport_size_t set_value,
756 ioport_size_t reset_value,
757 bsp_io_level_t pin_level)
758 {
759 uint32_t port_value = 0;
760
761 /* Get the port address */
762 R_PORT0_Type * p_ioport_regs = IOPORT_PRV_PORT_ADDRESS((port >> IOPORT_PRV_PORT_OFFSET) & IOPORT_PRV_8BIT_MASK);
763
764 /* Read current value of PCNTR4 register */
765 port_value = p_ioport_regs->PCNTR4;
766
767 if (BSP_IO_LEVEL_HIGH == pin_level)
768 {
769 /* set value contains the bit to be set high (bit mask) */
770 port_value |= (uint32_t) (set_value);
771
772 /* reset value contains the mask to clear the corresponding bit in EOSR because both EOSR and EORR
773 * bit of a particular pin should not be high at the same time */
774 port_value &= (((uint32_t) reset_value << 16) | IOPORT_PRV_16BIT_MASK);
775 }
776 else
777 {
778 /* reset_value contains the bit to be cleared low */
779 port_value |= (uint32_t) reset_value << 16;
780
781 /* set value contains the mask to clear the corresponding bit in EOSR because both EOSR and EORR bit of a
782 * particular pin should not be high at the same time */
783 port_value &= (uint32_t) ((set_value | IOPORT_PRV_UPPER_16BIT_MASK));
784 }
785
786 p_ioport_regs->PCNTR4 = port_value;
787 }
788
789 /*******************************************************************************************************************//**
790 * Writes to the specified pin's PFS register
791 *
792 * @param[in] pin Pin to write PFS data for
793 * @param[in] value Value to be written to the PFS register
794 *
795 **********************************************************************************************************************/
r_ioport_pfs_write(bsp_io_port_pin_t pin,uint32_t value)796 static void r_ioport_pfs_write (bsp_io_port_pin_t pin, uint32_t value)
797 {
798 /* PMR bits should be cleared before specifying PSEL. Reference section "20.7 Notes on the PmnPFS Register Setting"
799 * in the RA6M3 manual R01UH0886EJ0100. */
800 if ((value & IOPORT_PRV_PERIPHERAL_FUNCTION) > 0)
801 {
802 /* Clear PMR */
803 R_PFS->PORT[pin >> IOPORT_PRV_PORT_OFFSET].PIN[pin & BSP_IO_PRV_8BIT_MASK].PmnPFS_b.PMR = 0;
804
805 /* New config with PMR = 0 */
806 R_PFS->PORT[pin >> IOPORT_PRV_PORT_OFFSET].PIN[pin &
807 BSP_IO_PRV_8BIT_MASK].PmnPFS =
808 (value & ~((uint32_t) IOPORT_PRV_PERIPHERAL_FUNCTION));
809 }
810
811 /* Write configuration */
812 R_PFS->PORT[pin >> IOPORT_PRV_PORT_OFFSET].PIN[pin & BSP_IO_PRV_8BIT_MASK].PmnPFS = value;
813 }
814
815 #if BSP_MCU_VBATT_SUPPORT
816
817 /*******************************************************************************************************************//**
818 * @brief Initializes VBTICTLR register based on pin configuration.
819 *
820 * The VBTICTLR register may need to be modified based on the project's pin configuration. There is a set of pins that
821 * needs to be checked. If one of these pins is found in the pin configuration table then it will be tested to see if
822 * the appropriate VBTICTLR bit needs to be set or cleared. If one of the pins that is being searched for is not found
823 * then the accompanying VBTICTLR bit is left as-is.
824 **********************************************************************************************************************/
bsp_vbatt_init(ioport_cfg_t const * const p_pin_cfg)825 static void bsp_vbatt_init (ioport_cfg_t const * const p_pin_cfg)
826 {
827 uint32_t pin_index;
828 uint32_t vbatt_index;
829 uint8_t local_vbtictlr_set; ///< Will hold bits to set in VBTICTLR
830 uint8_t local_vbtictlr_clear; ///< Will hold bits to clear in VBTICTLR
831
832 /* Make no changes unless required. */
833 local_vbtictlr_set = 0U;
834 local_vbtictlr_clear = 0U;
835
836 /* Must loop over all pins as pin configuration table is unordered. */
837 for (pin_index = 0U; pin_index < p_pin_cfg->number_of_pins; pin_index++)
838 {
839 /* Loop over VBATT input pins. */
840 for (vbatt_index = 0U;
841 vbatt_index < (sizeof(g_vbatt_pins_input) / sizeof(g_vbatt_pins_input[0]));
842 vbatt_index++)
843 {
844 if (p_pin_cfg->p_pin_cfg_data[pin_index].pin == g_vbatt_pins_input[vbatt_index])
845 {
846 /* Get PSEL value for pin. */
847 uint32_t pfs_psel_value = p_pin_cfg->p_pin_cfg_data[pin_index].pin_cfg & BSP_PRV_PFS_PSEL_MASK;
848
849 /* Check if pin is being used for RTC or AGT use. */
850 if ((IOPORT_PERIPHERAL_AGT == pfs_psel_value) || (IOPORT_PERIPHERAL_CLKOUT_COMP_RTC == pfs_psel_value))
851 {
852 /* Bit should be set to 1. */
853 local_vbtictlr_set |= (uint8_t) (1U << vbatt_index);
854 }
855 else
856 {
857 /* Bit should be cleared to 0. */
858 local_vbtictlr_clear |= (uint8_t) (1U << vbatt_index);
859 }
860 }
861 }
862 }
863
864 /* Disable write protection on VBTICTLR. */
865 R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_OM_LPC_BATT);
866
867 /* Read value, set and clear bits as needed and write back. */
868 uint8_t local_vbtictlr = R_SYSTEM->VBTICTLR;
869 local_vbtictlr |= local_vbtictlr_set; ///< Set appropriate bits
870 local_vbtictlr &= (uint8_t) ~local_vbtictlr_clear; ///< Clear appropriate bits
871
872 R_SYSTEM->VBTICTLR = local_vbtictlr;
873
874 /* Enable write protection on VBTICTLR. */
875 R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_OM_LPC_BATT);
876 }
877
878 #endif
879