rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
hal_pal_lld.c
Go to the documentation of this file.
1/*
2 ChibiOS - Copyright (C) 2014-2015 Fabio Utzig
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17/**
18 * @file GPIOv2/hal_pal_lld.c
19 * @brief PAL subsystem low level driver.
20 * @author andreika <prometheus.pcb@gmail.com>
21 *
22 * @addtogroup PAL
23 * @{
24 */
25
26#include "osal.h"
27#include "hal.h"
28
29#if HAL_USE_PAL || defined(__DOXYGEN__)
30
31#include "fsl_port.h"
32
33/*===========================================================================*/
34/* Driver local definitions. */
35/*===========================================================================*/
36
37/*===========================================================================*/
38/* Driver exported variables. */
39/*===========================================================================*/
40
41#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
42/**
43 * @brief Event records for the 16 GPIO EXTI channels.
44 */
45palevent_t _pal_events[KINETIS_GPIO_NUM_LINES];
46#endif
47
48/*===========================================================================*/
49/* Driver local variables and types. */
50/*===========================================================================*/
51
52/*===========================================================================*/
53/* Driver local functions. */
54/*===========================================================================*/
55
56#ifdef KE1xF
57
58void _pal_lld_irq_handler(PORT_Type *base) {
59 uint32_t flags = PORT_GetPinsInterruptFlags(base);
60 for (int i = 0; i < 16; i++) {
61 if (flags & (1 << i)) {
62 // todo: add port-dependent lines?
63 _pal_isr_code(i);
64 }
65 }
67}
68
69#endif /* KE1xF */
70
72 PORT_TypeDef *portcfg = NULL;
73 if (port == IOPORT1)
74 portcfg = PORTA;
75 else if (port == IOPORT2)
76 portcfg = PORTB;
77 else if (port == IOPORT3)
78 portcfg = PORTC;
79 else if (port == IOPORT4)
80 portcfg = PORTD;
81 else if (port == IOPORT5)
82 portcfg = PORTE;
83 return portcfg;
84}
85
86/**
87 * @brief Reads a logical state from an I/O pad.
88 * @note The @ref PAL provides a default software implementation of this
89 * functionality, implement this function if can optimize it by using
90 * special hardware functionalities or special coding.
91 *
92 * @param[in] port port identifier
93 * @param[in] pad pad number within the port
94 * @return The logical state.
95 * @retval PAL_LOW low logical state.
96 * @retval PAL_HIGH high logical state.
97 *
98 * @notapi
99 */
101 uint8_t pad) {
102
103 return (port->PDIR & ((uint32_t) 1 << pad)) ? PAL_HIGH : PAL_LOW;
104}
105
106/**
107 * @brief Writes a logical state on an output pad.
108 * @note This function is not meant to be invoked directly by the
109 * application code.
110 * @note The @ref PAL provides a default software implementation of this
111 * functionality, implement this function if can optimize it by using
112 * special hardware functionalities or special coding.
113 *
114 * @param[in] port port identifier
115 * @param[in] pad pad number within the port
116 * @param[in] bit logical value, the value must be @p PAL_LOW or
117 * @p PAL_HIGH
118 *
119 * @notapi
120 */
122 uint8_t pad,
123 uint8_t bit) {
124
125 if (bit == PAL_HIGH)
126 port->PDOR |= ((uint32_t) 1 << pad);
127 else
128 port->PDOR &= ~((uint32_t) 1 << pad);
129}
130
131/**
132 * @brief Pad mode setup.
133 * @details This function programs a pad with the specified mode.
134 * @note The @ref PAL provides a default software implementation of this
135 * functionality, implement this function if can optimize it by using
136 * special hardware functionalities or special coding.
137 * @note Programming an unknown or unsupported mode is silently ignored.
138 *
139 * @param[in] port port identifier
140 * @param[in] pad pad number within the port
141 * @param[in] mode pad mode
142 *
143 * @notapi
144 */
146 uint8_t pad,
147 iomode_t mode) {
148
149 osalDbgAssert(pad < PADS_PER_PORT, "pal_lld_setpadmode() #1, invalid pad");
150
151 if (mode == PAL_MODE_OUTPUT_PUSHPULL || mode == PAL_MODE_OUTPUT_OPENDRAIN)
152 port->PDDR |= ((uint32_t) 1 << pad);
153 else
154 port->PDDR &= ~((uint32_t) 1 << pad);
155
156 PORT_TypeDef *portcfg = _pal_lld_get_port_config(port);
157 osalDbgAssert(portcfg != NULL, "pal_lld_setpadmode() #2, invalid port");
158
159 switch (mode) {
160 case PAL_MODE_RESET:
161 case PAL_MODE_INPUT:
162 case PAL_MODE_OUTPUT_PUSHPULL:
163 portcfg->PCR[pad] = PIN_MUX_ALTERNATIVE(1);
164 break;
165#if KINETIS_GPIO_HAS_OPENDRAIN
166 case PAL_MODE_OUTPUT_OPENDRAIN:
167 portcfg->PCR[pad] = PIN_MUX_ALTERNATIVE(1) |
168 PORTx_PCRn_ODE;
169 break;
170#else
171#undef PAL_MODE_OUTPUT_OPENDRAIN
172#endif
173 case PAL_MODE_INPUT_PULLUP:
174 portcfg->PCR[pad] = PIN_MUX_ALTERNATIVE(1) |
175 PORTx_PCRn_PE |
176 PORTx_PCRn_PS;
177 break;
178 case PAL_MODE_INPUT_PULLDOWN:
179 portcfg->PCR[pad] = PIN_MUX_ALTERNATIVE(1) |
180 PORTx_PCRn_PE;
181 break;
182 case PAL_MODE_UNCONNECTED:
183 case PAL_MODE_INPUT_ANALOG:
184 portcfg->PCR[pad] = PIN_MUX_ALTERNATIVE(0);
185 break;
186 case PAL_MODE_ALTERNATIVE_1:
187 portcfg->PCR[pad] = PIN_MUX_ALTERNATIVE(1);
188 break;
189 case PAL_MODE_ALTERNATIVE_2:
190 portcfg->PCR[pad] = PIN_MUX_ALTERNATIVE(2);
191 break;
192 case PAL_MODE_ALTERNATIVE_3:
193 portcfg->PCR[pad] = PIN_MUX_ALTERNATIVE(3);
194 break;
195 case PAL_MODE_ALTERNATIVE_4:
196 portcfg->PCR[pad] = PIN_MUX_ALTERNATIVE(4);
197 break;
198 case PAL_MODE_ALTERNATIVE_5:
199 portcfg->PCR[pad] = PIN_MUX_ALTERNATIVE(5);
200 break;
201 case PAL_MODE_ALTERNATIVE_6:
202 portcfg->PCR[pad] = PIN_MUX_ALTERNATIVE(6);
203 break;
204 case PAL_MODE_ALTERNATIVE_7:
205 portcfg->PCR[pad] = PIN_MUX_ALTERNATIVE(7);
206 break;
207 }
208
209 // a little 'hack' for complex pin modes like MISO+PULLUP
210 if (mode & PAL_STM32_PUPDR_PULLUP) {
211 portcfg->PCR[pad] |= PAL_STM32_PUPDR_PULLUP;
212 }
213
214 // enable high-current drive strength for push-pull outputs (Kinetis-specific feature)
215 if (mode & PAL_MODE_OUTPUT_PUSHPULL) {
216 // todo: Not all pins are capable of high-drive. Is is a problem?
218 }
219}
220
221/*===========================================================================*/
222/* Driver interrupt handlers. */
223/*===========================================================================*/
224
225/*===========================================================================*/
226/* Driver exported functions. */
227/*===========================================================================*/
228
229/**
230 * @brief Kinetis I/O ports configuration.
231 * @details Ports A-E clocks enabled.
232 *
233 * @param[in] config the Kinetis ports configuration
234 *
235 * @notapi
236 */
237#ifdef KE1xF
238void _pal_lld_init(void) {
239 /* Enable clocking on all Ports */
240 PCC->CLKCFG[PCC_PORTA_INDEX] |= PCC_CLKCFG_CGC_MASK;
241 PCC->CLKCFG[PCC_PORTB_INDEX] |= PCC_CLKCFG_CGC_MASK;
242 PCC->CLKCFG[PCC_PORTC_INDEX] |= PCC_CLKCFG_CGC_MASK;
243 PCC->CLKCFG[PCC_PORTD_INDEX] |= PCC_CLKCFG_CGC_MASK;
244 PCC->CLKCFG[PCC_PORTE_INDEX] |= PCC_CLKCFG_CGC_MASK;
245
246 nvicEnableVector(PORTA_IRQn, KINETIS_GPIO_IRQ_PRIORITY);
247 nvicEnableVector(PORTB_IRQn, KINETIS_GPIO_IRQ_PRIORITY);
248 nvicEnableVector(PORTC_IRQn, KINETIS_GPIO_IRQ_PRIORITY);
249 nvicEnableVector(PORTD_IRQn, KINETIS_GPIO_IRQ_PRIORITY);
250 nvicEnableVector(PORTE_IRQn, KINETIS_GPIO_IRQ_PRIORITY);
251}
252#else
254
255 int i, j;
256
257 /* Enable clocking on all Ports */
258 SIM->SCGC5 |= SIM_SCGC5_PORTA |
259 SIM_SCGC5_PORTB |
260 SIM_SCGC5_PORTC |
261 SIM_SCGC5_PORTD |
262 SIM_SCGC5_PORTE;
263
264 /* Initial PORT and GPIO setup */
265 for (i = 0; i < TOTAL_PORTS; i++) {
266 for (j = 0; j < PADS_PER_PORT; j++) {
267 pal_lld_setpadmode(config->ports[i].port,
268 j,
269 config->ports[i].pads[j]);
270 }
271 }
272}
273#endif
274
275/**
276 * @brief Pads mode setup.
277 * @details This function programs a pads group belonging to the same port
278 * with the specified mode.
279 *
280 * @param[in] port the port identifier
281 * @param[in] mask the group mask
282 * @param[in] mode the mode
283 *
284 * @notapi
285 */
287 ioportmask_t mask,
288 iomode_t mode) {
289
290 int i;
291
292 (void)mask;
293
294 for (i = 0; i < PADS_PER_PORT; i++) {
295 pal_lld_setpadmode(port, i, mode);
296 }
297}
298
299#if PAL_USE_CALLBACKS || PAL_USE_WAIT
300
303 ioeventmode_t mode) {
305 switch (mode) {
306 case PAL_EVENT_MODE_RISING_EDGE:
308 break;
309 case PAL_EVENT_MODE_FALLING_EDGE:
311 break;
312 case PAL_EVENT_MODE_BOTH_EDGES:
314 break;
315 case PAL_EVENT_MODE_DISABLED:
316 default:
318 }
319
320 PORT_TypeDef *portcfg = _pal_lld_get_port_config(port);
321 PORT_SetPinInterruptConfig(portcfg, pad, cfg);
322
323}
324
326 PORT_TypeDef *portcfg = _pal_lld_get_port_config(port);
327 PORT_SetPinInterruptConfig(portcfg, pad, PAL_EVENT_MODE_DISABLED);
328 PORT_ClearPinsInterruptFlags(portcfg, 0xffffffff);
329}
330
331#endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */
332
333#endif /* HAL_USE_PAL */
334
335/** @} */
uint8_t pad[3]
static constexpr persistent_config_s * config
void _pal_lld_setpadmode(ioportid_t port, uint8_t pad, iomode_t mode)
Pad mode setup.
void _pal_lld_writepad(ioportid_t port, uint8_t pad, uint8_t bit)
Writes a logical state on an output pad.
uint32_t ioeventmode_t
Type of an event mode.
Definition hal_pal_lld.h:93
uint32_t ioportmask_t
Digital I/O port sized unsigned type.
Definition hal_pal_lld.h:78
void _pal_lld_init(void)
Kinetis I/O ports configuration.
palevent_t _pal_events[KINETIS_GPIO_NUM_LINES]
Event records for the 16 GPIO EXTI channels.
Definition hal_pal_lld.c:45
uint8_t _pal_lld_readpad(ioportid_t port, uint8_t pad)
Reads a logical state from an I/O pad.
void _pal_lld_enablepadevent(ioportid_t port, iopadid_t pad, ioeventmode_t mode)
void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad)
void _pal_lld_setgroupmode(ioportid_t port, ioportmask_t mask, iomode_t mode)
Pads mode setup.
void _pal_lld_irq_handler(PORT_Type *base)
Definition hal_pal_lld.c:58
GPIO_TypeDef * ioportid_t
Port Identifier.
uint32_t iomode_t
Digital I/O modes.
Definition hal_pal_lld.h:83
uint32_t iopadid_t
Type of an pad identifier.
PORT_TypeDef * _pal_lld_get_port_config(ioportid_t port)
Definition hal_pal_lld.c:71
static void PORT_SetPinInterruptConfig(PORT_Type *base, uint32_t pin, port_interrupt_t config)
Configures the port pin interrupt/DMA request.
Definition fsl_port.h:415
enum _port_interrupt port_interrupt_t
Configures the interrupt generation condition.
static void PORT_SetPinDriveStrength(PORT_Type *base, uint32_t pin, uint8_t strength)
Configures the port pin drive strength.
Definition fsl_port.h:431
static uint32_t PORT_GetPinsInterruptFlags(PORT_Type *base)
Reads the whole port status flag.
Definition fsl_port.h:451
static void PORT_ClearPinsInterruptFlags(PORT_Type *base, uint32_t mask)
Clears the multiple pin interrupt status flag.
Definition fsl_port.h:462
@ kPORT_HighDriveStrength
Definition fsl_port.h:75
@ kPORT_InterruptEitherEdge
Definition fsl_port.h:129
@ kPORT_InterruptRisingEdge
Definition fsl_port.h:127
@ kPORT_InterruptOrDMADisabled
Definition fsl_port.h:115
@ kPORT_InterruptFallingEdge
Definition fsl_port.h:128
Generic I/O ports static initializer.