1 /*!
2  * \file      gpio-board.c
3  *
4  * \brief     Target board GPIO driver implementation
5  *
6  * \copyright Revised BSD License, see section \ref LICENSE.
7  *
8  * \code
9  *                ______                              _
10  *               / _____)             _              | |
11  *              ( (____  _____ ____ _| |_ _____  ____| |__
12  *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
13  *               _____) ) ____| | | || |_| ____( (___| | | |
14  *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
15  *              (C)2013-2017 Semtech
16  *
17  * \endcode
18  *
19  * \author    Miguel Luis ( Semtech )
20  *
21  * \author    Gregory Cristian ( Semtech )
22  */
23 #include "stm32l4xx.h"
24 #include "utilities.h"
25 #include "sysIrqHandlers.h"
26 #include "board-config.h"
27 #include "rtc-board.h"
28 #include "gpio-board.h"
29 #if defined( BOARD_IOE_EXT )
30 #include "gpio-ioe.h"
31 #endif
32 
33 static Gpio_t *GpioIrq[16];
34 
GpioMcuInit(Gpio_t * obj,PinNames pin,PinModes mode,PinConfigs config,PinTypes type,uint32_t value)35 void GpioMcuInit( Gpio_t *obj, PinNames pin, PinModes mode, PinConfigs config, PinTypes type, uint32_t value )
36 {
37     if( pin < IOE_0 )
38     {
39         GPIO_InitTypeDef GPIO_InitStructure;
40 
41         obj->pin = pin;
42 
43         if( pin == NC )
44         {
45             return;
46         }
47 
48         obj->pinIndex = ( 0x01 << ( obj->pin & 0x0F ) );
49 
50         if( ( obj->pin & 0xF0 ) == 0x00 )
51         {
52             obj->port = GPIOA;
53             __HAL_RCC_GPIOA_CLK_ENABLE( );
54         }
55         else if( ( obj->pin & 0xF0 ) == 0x10 )
56         {
57             obj->port = GPIOB;
58             __HAL_RCC_GPIOB_CLK_ENABLE( );
59         }
60         else if( ( obj->pin & 0xF0 ) == 0x20 )
61         {
62             obj->port = GPIOC;
63             __HAL_RCC_GPIOC_CLK_ENABLE( );
64         }
65         else if( ( obj->pin & 0xF0 ) == 0x30 )
66         {
67             obj->port = GPIOD;
68             __HAL_RCC_GPIOD_CLK_ENABLE( );
69         }
70         else
71         {
72             obj->port = GPIOH;
73             __HAL_RCC_GPIOH_CLK_ENABLE( );
74         }
75 
76         GPIO_InitStructure.Pin =  obj->pinIndex ;
77         GPIO_InitStructure.Pull = obj->pull = type;
78         GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
79 
80         if( mode == PIN_INPUT )
81         {
82             GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
83         }
84         else if( mode == PIN_ANALOGIC )
85         {
86             GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
87         }
88         else if( mode == PIN_ALTERNATE_FCT )
89         {
90             if( config == PIN_OPEN_DRAIN )
91             {
92                 GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
93             }
94             else
95             {
96                 GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
97             }
98             GPIO_InitStructure.Alternate = value;
99         }
100         else // mode output
101         {
102             if( config == PIN_OPEN_DRAIN )
103             {
104                 GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
105             }
106             else
107             {
108                 GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
109             }
110         }
111 
112         // Sets initial output value
113         if( mode == PIN_OUTPUT )
114         {
115             GpioMcuWrite( obj, value );
116         }
117 
118         HAL_GPIO_Init( obj->port, &GPIO_InitStructure );
119     }
120     else
121     {
122 #if defined( BOARD_IOE_EXT )
123         // IOExt Pin
124         GpioIoeInit( obj, pin, mode, config, type, value );
125 #endif
126     }
127 }
128 
GpioMcuSetContext(Gpio_t * obj,void * context)129 void GpioMcuSetContext( Gpio_t *obj, void* context )
130 {
131     obj->Context = context;
132 }
133 
GpioMcuSetInterrupt(Gpio_t * obj,IrqModes irqMode,IrqPriorities irqPriority,GpioIrqHandler * irqHandler)134 void GpioMcuSetInterrupt( Gpio_t *obj, IrqModes irqMode, IrqPriorities irqPriority, GpioIrqHandler *irqHandler )
135 {
136     if( obj->pin < IOE_0 )
137     {
138         uint32_t priority = 0;
139 
140         IRQn_Type IRQnb = EXTI0_IRQn;
141         GPIO_InitTypeDef   GPIO_InitStructure;
142 
143         if( irqHandler == NULL )
144         {
145             return;
146         }
147 
148         obj->IrqHandler = irqHandler;
149 
150         GPIO_InitStructure.Pin =  obj->pinIndex;
151 
152         if( irqMode == IRQ_RISING_EDGE )
153         {
154             GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
155         }
156         else if( irqMode == IRQ_FALLING_EDGE )
157         {
158             GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING;
159         }
160         else
161         {
162             GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING_FALLING;
163         }
164 
165         GPIO_InitStructure.Pull = obj->pull;
166         GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
167 
168         HAL_GPIO_Init( obj->port, &GPIO_InitStructure );
169 
170         switch( irqPriority )
171         {
172         case IRQ_VERY_LOW_PRIORITY:
173         case IRQ_LOW_PRIORITY:
174             priority = 3;
175             break;
176         case IRQ_MEDIUM_PRIORITY:
177             priority = 2;
178             break;
179         case IRQ_HIGH_PRIORITY:
180             priority = 1;
181             break;
182         case IRQ_VERY_HIGH_PRIORITY:
183         default:
184             priority = 0;
185             break;
186         }
187 
188         switch( obj->pinIndex )
189         {
190         case GPIO_PIN_0:
191             IRQnb = EXTI0_IRQn;
192             break;
193         case GPIO_PIN_1:
194             IRQnb = EXTI1_IRQn;
195             break;
196         case GPIO_PIN_2:
197             IRQnb = EXTI2_IRQn;
198             break;
199         case GPIO_PIN_3:
200             IRQnb = EXTI3_IRQn;
201             break;
202         case GPIO_PIN_4:
203             IRQnb = EXTI4_IRQn;
204             break;
205         case GPIO_PIN_5:
206         case GPIO_PIN_6:
207         case GPIO_PIN_7:
208         case GPIO_PIN_8:
209         case GPIO_PIN_9:
210             IRQnb = EXTI9_5_IRQn;
211             break;
212         case GPIO_PIN_10:
213         case GPIO_PIN_11:
214         case GPIO_PIN_12:
215         case GPIO_PIN_13:
216         case GPIO_PIN_14:
217         case GPIO_PIN_15:
218             IRQnb = EXTI15_10_IRQn;
219             break;
220         default:
221             break;
222         }
223 
224         GpioIrq[( obj->pin ) & 0x0F] = obj;
225 
226         HAL_NVIC_SetPriority( IRQnb , priority, 0 );
227         HAL_NVIC_EnableIRQ( IRQnb );
228     }
229     else
230     {
231 #if defined( BOARD_IOE_EXT )
232         // IOExt Pin
233         GpioIoeSetInterrupt( obj, irqMode, irqPriority, irqHandler );
234 #endif
235     }
236 }
237 
GpioMcuRemoveInterrupt(Gpio_t * obj)238 void GpioMcuRemoveInterrupt( Gpio_t *obj )
239 {
240     if( obj->pin < IOE_0 )
241     {
242         // Clear callback before changing pin mode
243         GpioIrq[( obj->pin ) & 0x0F] = NULL;
244 
245         GPIO_InitTypeDef   GPIO_InitStructure;
246 
247         GPIO_InitStructure.Pin =  obj->pinIndex ;
248         GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
249         HAL_GPIO_Init( obj->port, &GPIO_InitStructure );
250     }
251     else
252     {
253 #if defined( BOARD_IOE_EXT )
254         // IOExt Pin
255         GpioIoeRemoveInterrupt( obj );
256 #endif
257     }
258 }
259 
GpioMcuWrite(Gpio_t * obj,uint32_t value)260 void GpioMcuWrite( Gpio_t *obj, uint32_t value )
261 {
262     if( obj->pin < IOE_0 )
263     {
264         if( obj == NULL )
265         {
266             assert_param( LMN_STATUS_ERROR );
267         }
268         // Check if pin is not connected
269         if( obj->pin == NC )
270         {
271             return;
272         }
273         HAL_GPIO_WritePin( obj->port, obj->pinIndex , ( GPIO_PinState )value );
274     }
275     else
276     {
277 #if defined( BOARD_IOE_EXT )
278         // IOExt Pin
279         GpioIoeWrite( obj, value );
280 #endif
281     }
282 }
283 
GpioMcuToggle(Gpio_t * obj)284 void GpioMcuToggle( Gpio_t *obj )
285 {
286     if( obj->pin < IOE_0 )
287     {
288         if( obj == NULL )
289         {
290             assert_param( LMN_STATUS_ERROR );
291         }
292 
293         // Check if pin is not connected
294         if( obj->pin == NC )
295         {
296             return;
297         }
298         HAL_GPIO_TogglePin( obj->port, obj->pinIndex );
299     }
300     else
301     {
302 #if defined( BOARD_IOE_EXT )
303         // IOExt Pin
304         GpioIoeToggle( obj );
305 #endif
306     }
307 }
308 
GpioMcuRead(Gpio_t * obj)309 uint32_t GpioMcuRead( Gpio_t *obj )
310 {
311     if( obj->pin < IOE_0 )
312     {
313         if( obj == NULL )
314         {
315             assert_param( LMN_STATUS_ERROR );
316         }
317         // Check if pin is not connected
318         if( obj->pin == NC )
319         {
320             return 0;
321         }
322         return HAL_GPIO_ReadPin( obj->port, obj->pinIndex );
323     }
324     else
325     {
326 #if defined( BOARD_IOE_EXT )
327         // IOExt Pin
328         return GpioIoeRead( obj );
329 #else
330         return 0;
331 #endif
332     }
333 }
334 
EXTI0_IRQHandler(void)335 void EXTI0_IRQHandler( void )
336 {
337     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_0 );
338 }
339 
EXTI1_IRQHandler(void)340 void EXTI1_IRQHandler( void )
341 {
342     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_1 );
343 }
344 
EXTI2_IRQHandler(void)345 void EXTI2_IRQHandler( void )
346 {
347     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_2 );
348 }
349 
EXTI3_IRQHandler(void)350 void EXTI3_IRQHandler( void )
351 {
352     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_3 );
353 }
354 
EXTI4_IRQHandler(void)355 void EXTI4_IRQHandler( void )
356 {
357     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_4 );
358 }
359 
EXTI9_5_IRQHandler(void)360 void EXTI9_5_IRQHandler( void )
361 {
362     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_5 );
363     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_6 );
364     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_7 );
365     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_8 );
366     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_9 );
367 }
368 
EXTI15_10_IRQHandler(void)369 void EXTI15_10_IRQHandler( void )
370 {
371     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_10 );
372     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_11 );
373     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_12 );
374     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_13 );
375     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_14 );
376     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_15 );
377 }
378 
HAL_GPIO_EXTI_Callback(uint16_t gpioPin)379 void HAL_GPIO_EXTI_Callback( uint16_t gpioPin )
380 {
381     uint8_t callbackIndex = 0;
382 
383     if( gpioPin > 0 )
384     {
385         while( gpioPin != 0x01 )
386         {
387             gpioPin = gpioPin >> 1;
388             callbackIndex++;
389         }
390     }
391 
392     if( ( GpioIrq[callbackIndex] != NULL ) && ( GpioIrq[callbackIndex]->IrqHandler != NULL ) )
393     {
394         GpioIrq[callbackIndex]->IrqHandler( GpioIrq[callbackIndex]->Context );
395     }
396 }
397