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