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 : hw_ioport_private.h
22 * Description : IOPORT private macros and HW private function definition
23 **********************************************************************************************************************/
24
25 #ifndef HW_IOPORT_PRIVATE_H
26 #define HW_IOPORT_PRIVATE_H
27
28
29 /**********************************************************************************************************************
30 * Includes
31 **********************************************************************************************************************/
32 #include "bsp_api.h"
33 #include "r_ioport.h"
34 #include "r_ioport_api.h"
35
36 /* Common macro for SSP header files. There is also a corresponding SSP_FOOTER macro at the end of this file. */
37 SSP_HEADER
38
39 /**********************************************************************************************************************
40 * Macro definitions
41 **********************************************************************************************************************/
42 #define IOPORT_PRV_PCNTR_OFFSET 0x00000020U
43
44 #define IOPORT_PRV_PORT_OUTPUT_HIGH (1U)
45 #define IOPORT_PRV_PORT_INPUT (1U << 1)
46 #define IOPORT_PRV_PORT_DIR_OUTPUT (1U << 2)
47 #define IOPORT_PRV_PULL_UP_ENABLE (1U << 4)
48 #define IOPORT_PRV_EVENT_RISING_EDGE (1U << 12)
49 #define IOPORT_PRV_EVENT_FALLING_EDGE (1U << 13)
50 #define IOPORT_PRV_EVENT_BOTH_EDGES (3U << 12)
51 #define IOPORT_PRV_ANALOG_INPUT (1U << 15)
52 #define IOPORT_PRV_PERIPHERAL_FUNCTION (1U << 16)
53 #define IOPORT_PRV_CLEAR_BITS_MASK (0x1F01FCD5U) ///< Zero bits in mask must be written as zero to PFS register
54
55 /**********************************************************************************************************************
56 * Typedef definitions
57 **********************************************************************************************************************/
58 /** PFS writing enable/disable. */
59 typedef enum e_ioport_pwpr
60 {
61 IOPORT_PFS_WRITE_DISABLE = 0, ///< Disable PFS write access
62 IOPORT_PFS_WRITE_ENABLE = 1 ///< Enable PFS write access
63 } ioport_pwpr_t;
64
65 /***********************************************************************************************************************
66 * Private global variables
67 **********************************************************************************************************************/
68 extern volatile uint16_t g_protect_pfswe_counter;
69
70 /**********************************************************************************************************************
71 * Function Prototypes
72 **********************************************************************************************************************/
73 __STATIC_INLINE uint32_t * ioport_port_address_get (uint32_t volatile * p_base_address, ioport_port_t index);
74
75 __STATIC_INLINE uint32_t * ioport_pfs_address_get (uint32_t volatile * p_base_address, ioport_port_pin_t pin);
76
77 __STATIC_INLINE void HW_IOPORT_PortWriteWithPCNTR3 (R_IOPORT1_Type * p_ioport_regs,
78 ioport_port_t port,
79 ioport_size_t set_value,
80 ioport_size_t reset_value);
81
82 __STATIC_INLINE void HW_IOPORT_Init_Reference_Counter(void);
83
84 __STATIC_INLINE ioport_level_t HW_IOPORT_PinRead (R_PFS_Type * p_pfs_reg, ioport_port_pin_t pin);
85
86 __STATIC_INLINE ioport_size_t HW_IOPORT_PortRead (R_IOPORT1_Type * p_ioport_regs, ioport_port_t port);
87
88 __STATIC_INLINE ioport_size_t HW_IOPORT_PortDirectionRead (R_IOPORT1_Type * p_ioport_regs, ioport_port_t port);
89
90 __STATIC_INLINE void HW_IOPORT_PortDirectionSet (R_IOPORT1_Type * p_ioport_regs, ioport_port_t port, ioport_size_t value);
91
92 __STATIC_INLINE void HW_IOPORT_PinDirectionSet (R_PFS_Type * p_pfs_reg, R_PMISC_Type * p_pmisc_reg, ioport_port_pin_t pin, ioport_direction_t direction);
93
94 __STATIC_INLINE ioport_size_t HW_IOPORT_PortOutputDataRead (R_IOPORT1_Type * p_ioport_regs, ioport_port_t port);
95
96 __STATIC_INLINE ioport_size_t HW_IOPORT_PortEventInputDataRead (R_IOPORT1_Type * p_ioport_regs, ioport_port_t port);
97
98 __STATIC_INLINE void HW_IOPORT_PortEventOutputDataWrite (R_IOPORT1_Type * p_ioport_regs,
99 ioport_port_t port,
100 ioport_size_t set_value,
101 ioport_size_t reset_value);
102
103 __STATIC_INLINE void HW_IOPORT_PinEventOutputDataWrite (R_IOPORT1_Type * p_ioport_regs,
104 ioport_port_t port,
105 ioport_size_t set_value,
106 ioport_size_t reset_value,ioport_level_t pin_level);
107
108 __STATIC_INLINE void HW_IOPORT_EthernetModeCfg (R_PMISC_Type * p_pmisc_reg, ioport_ethernet_channel_t channel, ioport_ethernet_mode_t mode);
109
110 __STATIC_INLINE void HW_IOPORT_PFSWrite (R_PFS_Type * p_pfs_reg, R_PMISC_Type * p_pmisc_reg, ioport_port_pin_t pin, uint32_t value);
111
112 __STATIC_INLINE void HW_IOPORT_PFSSetDirection (R_PFS_Type * p_pfs_reg, R_PMISC_Type * p_pmisc_reg, ioport_port_pin_t pin, ioport_direction_t direction);
113
114 __STATIC_INLINE uint32_t HW_IOPORT_PFSRead (R_PFS_Type * p_pfs_reg, ioport_port_pin_t pin);
115
116 __STATIC_INLINE void HW_IOPORT_PFSAccess (R_PMISC_Type * p_pmisc_reg, ioport_pwpr_t value);
117
118
119
120 /***********************************************************************************************************************
121 Functions
122 **********************************************************************************************************************/
123
124 /*******************************************************************************************************************//**
125 * Zero the reference counter used by the HW_IOPORT_PFSAccessDisable() and HW_IOPORT_PFSAccessEnable() functions.
126 * This function will be replaced in a future release and has been added only to insure that the reference counter
127 * is 0 when g_ioport_on_ioport.init() is called (prior to the C Runtime initialization) as part of the BSP init.
128 *
129 **********************************************************************************************************************/
HW_IOPORT_Init_Reference_Counter(void)130 __STATIC_INLINE void HW_IOPORT_Init_Reference_Counter(void)
131 {
132 g_protect_pfswe_counter = 0U;
133 }
134
135 /*******************************************************************************************************************//**
136 * @internal Returns the address of the specified port register.
137 *
138 * @param[in] p_base_address Base address of the required register
139 * @param[in] index Required port
140 *
141 * @retval Address of the port register
142 * @endinternal
143 **********************************************************************************************************************/
ioport_port_address_get(uint32_t volatile * p_base_address,ioport_port_t index)144 __STATIC_INLINE uint32_t * ioport_port_address_get (uint32_t volatile * p_base_address, ioport_port_t index)
145 {
146 /** base address - First port register of this type */
147 /** index - Index off the base */
148 /* Cast to ensure treated as unsigned */
149 return (uint32_t *) ((uint32_t) (((((uint32_t) index >>
150 8) &
151 0xFFU) *
152 (uint32_t) IOPORT_PRV_PCNTR_OFFSET) + ((uint32_t) p_base_address)));
153 }
154
155
156 /*******************************************************************************************************************//**
157 * @internal Returns the address of the specified PFS register.
158 *
159 * @param[in] p_base_address Base address of the required register
160 * @param[in] pin Required pin
161 *
162 * @retval Address of the PFS register
163 * @endinternal
164 **********************************************************************************************************************/
ioport_pfs_address_get(uint32_t volatile * p_base_address,ioport_port_pin_t pin)165 __STATIC_INLINE uint32_t * ioport_pfs_address_get (uint32_t volatile * p_base_address, ioport_port_pin_t pin)
166 {
167 /** base address - First port register of this type */
168 /** pin - Pin for which address is required in format 0xTTPP where TT is the port and PP is the pin */
169
170 /** (16 * 4) to jump a whole set of port addresses as 16 pins in a port and each PFS register is 4 bytes */
171 /** (* 4) to jump a pin address as each PFS register is 4 bytes */
172 /* Cast to ensure treated as unsigned */
173 return (uint32_t *) ((uint32_t) ((((((uint32_t) pin >>
174 8) &
175 0x00FFU) *
176 (16U * 4U))) + (((uint32_t) pin & 0x00FFU) * 4U) + ((uint32_t) p_base_address)));
177 }
178
179 /*******************************************************************************************************************//**
180 * Writes the Ethernet PHY configuration.
181 *
182 * @param[in] p_pmisc_reg Base address of the PMISC registers
183 * @param[in] channel Ethenet channel number
184 * @param[in] mode Required PHY mode
185 *
186 **********************************************************************************************************************/
HW_IOPORT_EthernetModeCfg(R_PMISC_Type * p_pmisc_reg,ioport_ethernet_channel_t channel,ioport_ethernet_mode_t mode)187 __STATIC_INLINE void HW_IOPORT_EthernetModeCfg (R_PMISC_Type * p_pmisc_reg, ioport_ethernet_channel_t channel, ioport_ethernet_mode_t mode)
188 {
189 uint8_t value;
190
191 if (IOPORT_ETHERNET_MODE_RMII == mode)
192 {
193 value = p_pmisc_reg->PFENET;
194 /* Cast to ensure unsigned value */
195 value &= (uint8_t) (~((uint8_t) channel));
196 value &= 0x30U;
197 p_pmisc_reg->PFENET = value;
198 }
199 else if (IOPORT_ETHERNET_MODE_MII == mode)
200 {
201 value = p_pmisc_reg->PFENET;
202 value |= channel;
203 value &= 0x30U;
204 p_pmisc_reg->PFENET = value;
205 }
206 }
207
208 /*******************************************************************************************************************//**
209 * Writes to the pins in a port using the PCNTR3 register. This register allows individual bits to be set high or
210 * cleared low while leaving other pins unchanged. This allows automic setting and clearing of pins.
211 *
212 * @param[in] p_ioport_regs Base address of the IOPORT registers
213 * @param[in] port Port to write to
214 * @param[in] set_value Bits in the port to set high (1 = that bit will be set high)
215 * @param[in] reset_value Bits in the port to clear low (1 = that bit will be cleared low)
216 *
217 **********************************************************************************************************************/
HW_IOPORT_PortWriteWithPCNTR3(R_IOPORT1_Type * p_ioport_regs,ioport_port_t port,ioport_size_t set_value,ioport_size_t reset_value)218 __STATIC_INLINE void HW_IOPORT_PortWriteWithPCNTR3 (R_IOPORT1_Type * p_ioport_regs,
219 ioport_port_t port,
220 ioport_size_t set_value,
221 ioport_size_t reset_value)
222 {
223 /** set_value contains the bits to be set high (bit mask) */
224
225 /** reset_value contains the bits to be cleared low - a high bit indicates that bit should be cleared low (bit mask)
226 **/
227
228 volatile uint32_t * p_dest;
229
230 p_dest = ioport_port_address_get((uint32_t volatile *) &p_ioport_regs->PCNTR3, port);
231
232 /** PCNTR4 register: lower word = set data, upper word = reset_data */
233 *p_dest = (uint32_t) (((uint32_t) reset_value << 16) | set_value);
234 }
235
236 /*******************************************************************************************************************//**
237 * Returns the input event data for the specified port.
238 *
239 * @param[in] p_ioport_regs Base address of the IOPORT registers
240 * @param[in] port Port to read event data
241 *
242 * @retval Input event data for the specified port.
243 **********************************************************************************************************************/
HW_IOPORT_PortEventInputDataRead(R_IOPORT1_Type * p_ioport_regs,ioport_port_t port)244 __STATIC_INLINE ioport_size_t HW_IOPORT_PortEventInputDataRead (R_IOPORT1_Type * p_ioport_regs, ioport_port_t port)
245 {
246 /** Returns specified port's event input data from PCNTR2 */
247
248 volatile uint32_t * p_dest;
249 uint32_t pcntr_reg_value;
250 ioport_size_t port_data;
251
252 p_dest = ioport_port_address_get((uint32_t volatile *) &p_ioport_regs->PCNTR2, port);
253 /** Read current value of PCNTR register value for the specified port */
254 pcntr_reg_value = *p_dest;
255 /** Only the upper 16-bits are required */
256 pcntr_reg_value = pcntr_reg_value >> 16;
257 pcntr_reg_value &= 0x0000FFFFU;
258 port_data = (ioport_size_t) pcntr_reg_value;
259
260 return port_data;
261 }
262
263 /*******************************************************************************************************************//**
264 * Writes the set and clear values for pin on a port to be written when an event occurs. This allows accurate timing of
265 * pin output level.
266 *
267 * @param[in] p_ioport_regs Base address of the IOPORT registers
268 * @param[in] set_value Bits in the port to set high (1 = that bit will be set high)
269 * @param[in] reset_value Bits in the port to clear low (1 = that bit will be cleared low)
270 *
271 **********************************************************************************************************************/
HW_IOPORT_PortEventOutputDataWrite(R_IOPORT1_Type * p_ioport_regs,ioport_port_t port,ioport_size_t set_value,ioport_size_t reset_value)272 __STATIC_INLINE void HW_IOPORT_PortEventOutputDataWrite (R_IOPORT1_Type * p_ioport_regs,
273 ioport_port_t port,
274 ioport_size_t set_value,
275 ioport_size_t reset_value)
276 {
277 /** set_value contains the bits to be set high (bit mask) */
278
279 /** reset_value contains the bits to be cleared low - a high bit indicates that bit should be cleared low (bit mask)
280 **/
281
282 volatile uint32_t * p_dest;
283
284 /** IOPORT0 does not have a PCNTR4 register. So, address of PCNTR3 is used then 4 bytes added */
285 p_dest = ioport_port_address_get((uint32_t volatile *) &p_ioport_regs->PCNTR3, port);
286 p_dest += 1;
287
288 /** PCNTR4 register: lower word = set data, upper word = reset_data */
289 *p_dest = (uint32_t) (((uint32_t) reset_value << 16) | (uint32_t) set_value);
290 }
291
292 /*******************************************************************************************************************//**
293 * Writes the set and clear values on a pin of the port when an ELC event occurs. This allows accurate timing of
294 * pin output level.
295 *
296 * @param[in] p_ioport_regs Base address of the IOPORT registers
297 * @param[in] port Port to read event data
298 * @param[in] set_value Bit in the port to set high (1 = that bit will be set high)
299 * @param[in] reset_value Bit in the port to clear low (1 = that bit will be cleared low)
300 * @param[in] pin_level Event data for pin
301 **********************************************************************************************************************/
HW_IOPORT_PinEventOutputDataWrite(R_IOPORT1_Type * p_ioport_regs,ioport_port_t port,ioport_size_t set_value,ioport_size_t reset_value,ioport_level_t pin_level)302 __STATIC_INLINE void HW_IOPORT_PinEventOutputDataWrite (R_IOPORT1_Type * p_ioport_regs,
303 ioport_port_t port,
304 ioport_size_t set_value,
305 ioport_size_t reset_value,ioport_level_t pin_level)
306 {
307 volatile uint32_t * p_dest;
308 uint32_t port_value = 0;
309
310 /** IOPORT0 does not have a PCNTR4 register. So, address of PCNTR3 is used then 4 bytes added */
311 p_dest = ioport_port_address_get((uint32_t volatile *) &p_ioport_regs->PCNTR3, port);
312 p_dest += 1;
313 port_value = *p_dest;
314
315 if (IOPORT_LEVEL_HIGH == pin_level)
316 {
317 /** set value contains the bit to be set high (bit mask) */
318 port_value |= (uint32_t) (set_value);
319 /** reset value contains the mask to clear the corresponding bit in EOSR because both EOSR and EORR
320 bit of a particular pin should not be high at the same time */
321 port_value &= (uint32_t) ((reset_value << 16) | 0x0000FFFF);
322 }
323 else
324 {
325 /** reset_value contains the bit to be cleared low */
326 port_value |= (uint32_t) reset_value << 16;
327 /** set value contains the mask to clear the corresponding bit in EOSR because both EOSR and EORR bit of a
328 particular pin should not be high at the same time */
329 port_value &= (uint32_t) ((set_value | 0xFFFF0000));
330 }
331
332 *p_dest = port_value;
333 }
334
335 /*******************************************************************************************************************//**
336 * Returns the current output levels of pin on a port.
337 *
338 * @param[in] p_ioport_regs Base address of the IOPORT registers
339 * @param[in] port Port to read
340 *
341 * @retval Output data for the specified port
342 **********************************************************************************************************************/
HW_IOPORT_PortOutputDataRead(R_IOPORT1_Type * p_ioport_regs,ioport_port_t port)343 __STATIC_INLINE ioport_size_t HW_IOPORT_PortOutputDataRead (R_IOPORT1_Type * p_ioport_regs, ioport_port_t port)
344 {
345 /** Returns value of specified's port Output Data from PCNTR1 */
346 /** Used by set pin level function to read current output levels on port */
347
348 volatile uint32_t * p_dest;
349 uint32_t pcntr_reg_value;
350
351 p_dest = ioport_port_address_get((uint32_t volatile *) &p_ioport_regs->PCNTR1, port);
352
353 /** Read current value of PCNTR register value for the specified port */
354 pcntr_reg_value = *p_dest;
355 /** Only the upper 16-bits are required */
356 pcntr_reg_value = pcntr_reg_value >> 16;
357 pcntr_reg_value &= 0x0000FFFFU;
358
359 return (ioport_size_t) pcntr_reg_value;
360 }
361
362 /*******************************************************************************************************************//**
363 * Returns the level of an individual pin.
364 *
365 * @param[in] p_pfs_reg Base address of the PFS registers
366 * @param[in] pin Pin to read the level from
367 *
368 * @retval Level of the specified pin.
369 **********************************************************************************************************************/
HW_IOPORT_PinRead(R_PFS_Type * p_pfs_reg,ioport_port_pin_t pin)370 __STATIC_INLINE ioport_level_t HW_IOPORT_PinRead (R_PFS_Type * p_pfs_reg, ioport_port_pin_t pin)
371 {
372 uint32_t pfs;
373
374 pfs = HW_IOPORT_PFSRead(p_pfs_reg, pin);
375
376 if ((uint32_t) IOPORT_PRV_PORT_INPUT == (pfs & (uint32_t) IOPORT_PRV_PORT_INPUT))
377 {
378 return IOPORT_LEVEL_HIGH;
379 }
380 else
381 {
382 return IOPORT_LEVEL_LOW;
383 }
384 }
385
386 /*******************************************************************************************************************//**
387 * Returns the value of all pins on the specified port.
388 *
389 * @param[in] p_ioport_regs Base address of the IOPORT registers
390 * @param[in] port Port to read
391 *
392 * @retval Value of the pins on the specified port.
393 **********************************************************************************************************************/
HW_IOPORT_PortRead(R_IOPORT1_Type * p_ioport_regs,ioport_port_t port)394 __STATIC_INLINE ioport_size_t HW_IOPORT_PortRead (R_IOPORT1_Type * p_ioport_regs, ioport_port_t port)
395 {
396 volatile uint32_t * p_dest;
397 uint32_t pcntr_reg_value;
398 uint16_t port_data;
399
400 p_dest = ioport_port_address_get((uint32_t volatile *) &p_ioport_regs->PCNTR2, port);
401 /** Read current value of PCNTR register value for the specified port */
402 pcntr_reg_value = *p_dest;
403 /** Only the lower 16-bits are required */
404 pcntr_reg_value &= 0x0000FFFFU;
405 port_data = (ioport_size_t) pcntr_reg_value;
406
407 return port_data;
408 }
409
410 /*******************************************************************************************************************//**
411 * Returns the direction of pins on the specified port.
412 *
413 * @param[in] p_ioport_regs Base address of the IOPORT registers
414 * @param[in] port Port to read direction information from
415 *
416 * @retval Direction information of the specified port.
417 **********************************************************************************************************************/
HW_IOPORT_PortDirectionRead(R_IOPORT1_Type * p_ioport_regs,ioport_port_t port)418 __STATIC_INLINE ioport_size_t HW_IOPORT_PortDirectionRead (R_IOPORT1_Type * p_ioport_regs, ioport_port_t port)
419 {
420 volatile uint32_t * p_dest;
421 uint32_t pcntr_reg_value;
422
423 p_dest = ioport_port_address_get((uint32_t volatile *) &p_ioport_regs->PCNTR1, port);
424 /** Read current value of PCNTR register value for the specified port */
425 pcntr_reg_value = *p_dest;
426 /** Only the lower 16-bits should be written too */
427 pcntr_reg_value &= 0x0000FFFFU;
428
429 return (ioport_size_t) pcntr_reg_value;
430 }
431
432 /*******************************************************************************************************************//**
433 * Sets the direction of an individual pin.
434 *
435 * @param[in] p_pfs_reg Base address of the PFS registers
436 * @param[in] pin Pin to set direction for
437 * @param[in] direction Direction for the specified pin
438 *
439 **********************************************************************************************************************/
HW_IOPORT_PinDirectionSet(R_PFS_Type * p_pfs_reg,R_PMISC_Type * p_pmisc_reg,ioport_port_pin_t pin,ioport_direction_t direction)440 __STATIC_INLINE void HW_IOPORT_PinDirectionSet (R_PFS_Type * p_pfs_reg, R_PMISC_Type * p_pmisc_reg, ioport_port_pin_t pin, ioport_direction_t direction)
441 {
442 uint32_t pfs;
443
444 pfs = HW_IOPORT_PFSRead(p_pfs_reg, pin);
445
446 if (IOPORT_DIRECTION_INPUT == direction)
447 {
448 /** Clear PDR bit (2) */
449 pfs &= (~((uint32_t) IOPORT_PRV_PORT_DIR_OUTPUT));
450 }
451 else
452 {
453 /** Set PDR bit (2) */
454 pfs |= IOPORT_PRV_PORT_DIR_OUTPUT;
455 }
456
457 /** mask out bits which must be written as zero */
458 pfs &= IOPORT_PRV_CLEAR_BITS_MASK;
459
460 HW_IOPORT_PFSWrite(p_pfs_reg, p_pmisc_reg, pin, pfs);
461 }
462
463 /*******************************************************************************************************************//**
464 * Sets the direction of multiple pins on the specified port.
465 *
466 * @param[in] p_ioport_regs Base address of the IOPORT registers
467 * @param[in] port Port to write direction information to
468 * @param[in] value Direction data to write to the port
469 *
470 **********************************************************************************************************************/
HW_IOPORT_PortDirectionSet(R_IOPORT1_Type * p_ioport_regs,ioport_port_t port,ioport_size_t value)471 __STATIC_INLINE void HW_IOPORT_PortDirectionSet (R_IOPORT1_Type * p_ioport_regs, ioport_port_t port, ioport_size_t value)
472 {
473 volatile uint32_t * p_dest;
474 uint32_t pcntr_reg_value;
475
476 p_dest = ioport_port_address_get((uint32_t volatile *) &p_ioport_regs->PCNTR1, port);
477 /** Read current value of PCNTR register value for the specified port */
478 pcntr_reg_value = *p_dest;
479 /** Only the lower 16-bits should be written too */
480 pcntr_reg_value &= 0xFFFF0000U;
481 pcntr_reg_value |= (uint32_t) ((value) & 0x0000FFFFU);
482
483 *p_dest = pcntr_reg_value;
484 }
485
486
487 /*******************************************************************************************************************//**
488 * Enable access to the PFS registers. Uses a reference counter to protect against interrupts that could occur
489 * via multiple threads or an ISR re-entering this code.
490 *
491 * @param[in] p_pmisc_reg Base address of the PMISC registers
492 *
493 **********************************************************************************************************************/
HW_IOPORT_PFSAccessEnable(R_PMISC_Type * p_pmisc_reg)494 __STATIC_INLINE void HW_IOPORT_PFSAccessEnable(R_PMISC_Type * p_pmisc_reg)
495 {
496 /** Get the current state of interrupts */
497 SSP_CRITICAL_SECTION_DEFINE;
498 SSP_CRITICAL_SECTION_ENTER;
499
500 /** If this is first entry then allow writing of PFS. */
501 if (0 == g_protect_pfswe_counter)
502 {
503 p_pmisc_reg->PWPR = 0; ///< Clear BOWI bit - writing to PFSWE bit enabled
504 p_pmisc_reg->PWPR = 0x40; ///< Set PFSWE bit - writing to PFS register enabled
505 }
506
507 /** Increment the protect counter */
508 g_protect_pfswe_counter++;
509
510 /** Restore the interrupt state */
511 SSP_CRITICAL_SECTION_EXIT;
512 }
513
514 /*******************************************************************************************************************//**
515 * Disable access to the PFS registers. Uses a reference counter to protect against interrupts that could occur
516 * via multiple threads or an ISR re-entering this code.
517 *
518 * @param[in] p_pmisc_reg Base address of the PMISC registers
519 *
520 **********************************************************************************************************************/
HW_IOPORT_PFSAccessDisable(R_PMISC_Type * p_pmisc_reg)521 __STATIC_INLINE void HW_IOPORT_PFSAccessDisable(R_PMISC_Type * p_pmisc_reg)
522 {
523 /** Get the current state of interrupts */
524 SSP_CRITICAL_SECTION_DEFINE;
525 SSP_CRITICAL_SECTION_ENTER;
526
527 /** Is it safe to disable PFS register? */
528 if (0 != g_protect_pfswe_counter)
529 {
530 /* Decrement the protect counter */
531 g_protect_pfswe_counter--;
532 }
533
534 /** Is it safe to disable writing of PFS? */
535 if (0 == g_protect_pfswe_counter)
536 {
537 p_pmisc_reg->PWPR = 0; ///< Clear PFSWE bit - writing to PFS register disabled
538 p_pmisc_reg->PWPR = 0x80; ///< Set BOWI bit - writing to PFSWE bit disabled
539 }
540
541 /** Restore the interrupt state */
542 SSP_CRITICAL_SECTION_EXIT;
543 }
544 /*******************************************************************************************************************//**
545 * Enable/disable access to the PFS registers.
546 *
547 * @param[in] p_pmisc_reg Base address of the PMISC registers
548 * @param[in] value Enable/disable access state
549 *
550 **********************************************************************************************************************/
HW_IOPORT_PFSAccess(R_PMISC_Type * p_pmisc_reg,ioport_pwpr_t value)551 __STATIC_INLINE void HW_IOPORT_PFSAccess (R_PMISC_Type * p_pmisc_reg, ioport_pwpr_t value)
552 {
553 if (IOPORT_PFS_WRITE_ENABLE == value)
554 {
555 p_pmisc_reg->PWPR = 0; ///< Clear BOWI bit - writing to PFSWE bit enabled
556 p_pmisc_reg->PWPR = 0x40; ///< Set PFSWE bit - writing to PFS register enabled
557 }
558 else
559 {
560 p_pmisc_reg->PWPR = 0; ///< Clear PFSWE bit - writing to PFS register disabled
561 p_pmisc_reg->PWPR = 0x80; ///< Set BOWI bit - writing to PFSWE bit disabled
562 }
563 }
564
565 /*******************************************************************************************************************//**
566 * Returns the contents of the specified pin's PFS register.
567 *
568 * @param[in] p_pfs_reg Base address of the PFS registers
569 * @param[in] pin Pin to read the PFS data for
570 *
571 * @retval PFS contents for the specified pin.
572 **********************************************************************************************************************/
HW_IOPORT_PFSRead(R_PFS_Type * p_pfs_reg,ioport_port_pin_t pin)573 __STATIC_INLINE uint32_t HW_IOPORT_PFSRead (R_PFS_Type * p_pfs_reg, ioport_port_pin_t pin)
574 {
575 volatile uint32_t * p_dest;
576
577 p_dest = ioport_pfs_address_get((uint32_t volatile *) p_pfs_reg, pin);
578
579 return *p_dest;
580 }
581
582 /*******************************************************************************************************************//**
583 * Writes to the specified pin's PFS register
584 *
585 * @param[in] p_pfs_reg Base address of the PFS registers
586 * @param[in] pin Pin to write PFS data for
587 * @param[in] value Value to be written to the PFS register
588 *
589 **********************************************************************************************************************/
HW_IOPORT_PFSWrite(R_PFS_Type * p_pfs_reg,R_PMISC_Type * p_pmisc_reg,ioport_port_pin_t pin,uint32_t value)590 __STATIC_INLINE void HW_IOPORT_PFSWrite (R_PFS_Type * p_pfs_reg, R_PMISC_Type * p_pmisc_reg, ioport_port_pin_t pin, uint32_t value)
591 {
592 volatile uint32_t * p_dest;
593 uint32_t pfs_original;
594 uint32_t pfs_new;
595
596 p_dest = ioport_pfs_address_get((uint32_t volatile *) p_pfs_reg, pin);
597
598 HW_IOPORT_PFSAccessEnable(p_pmisc_reg); // Protect PWPR from re-entrancy
599
600 /* Read the current PFS value */
601 pfs_original = *p_dest;
602
603 /* Check if new PMR bit is set to 1 */
604 if ((value & IOPORT_PRV_PERIPHERAL_FUNCTION) > 0)
605 {
606 pfs_new = pfs_original;
607 /* Safely change PSEL bits to minimise risk of glitching. */
608 /* Clear PMR bit to zero */
609 pfs_new &= ~((uint32_t) IOPORT_PRV_PERIPHERAL_FUNCTION);
610 *p_dest = pfs_new;
611 /* New PFS value - zero PMR bit */
612 pfs_new = (value & ~((uint32_t) IOPORT_PRV_PERIPHERAL_FUNCTION));
613 *p_dest = pfs_new;
614 }
615
616 /* New value can be safely written to PFS. */
617 *p_dest = value;
618
619 HW_IOPORT_PFSAccessDisable(p_pmisc_reg);
620 }
621
622 /*******************************************************************************************************************//**
623 * Sets a pin's direction using its PFS register
624 *
625 * @param[in] p_pfs_reg Base address of the PFS registers
626 * @param[in] p_pmisc_reg Base address of the PMISC registers
627 * @param[in] pin Pin to set direction for
628 * @param[in] direction Direction to set for the pin
629 *
630 **********************************************************************************************************************/
HW_IOPORT_PFSSetDirection(R_PFS_Type * p_pfs_reg,R_PMISC_Type * p_pmisc_reg,ioport_port_pin_t pin,ioport_direction_t direction)631 __STATIC_INLINE void HW_IOPORT_PFSSetDirection (R_PFS_Type * p_pfs_reg, R_PMISC_Type * p_pmisc_reg, ioport_port_pin_t pin, ioport_direction_t direction)
632 {
633 uint32_t pfs;
634
635 pfs = HW_IOPORT_PFSRead(p_pfs_reg, pin);
636
637 if (direction == IOPORT_DIRECTION_INPUT)
638 {
639 /* Cast to ensure unsigned */
640 pfs &= (uint32_t) (~(IOPORT_PRV_PORT_DIR_OUTPUT));
641 }
642 else
643 {
644 pfs |= IOPORT_PRV_PORT_DIR_OUTPUT;
645 }
646
647 /** mask out bits which must be written as zero */
648 pfs &= IOPORT_PRV_CLEAR_BITS_MASK;
649
650 HW_IOPORT_PFSWrite(p_pfs_reg, p_pmisc_reg, pin, pfs);
651 }
652
653 /* Common macro for SSP header files. There is also a corresponding SSP_HEADER macro at the top of this file. */
654 SSP_FOOTER
655
656 #endif /* HW_IOPORT_PRIVATE_H */
657