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 "stm32l0xx.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             assert_param( LMN_STATUS_ERROR );
73         }
74 
75         GPIO_InitStructure.Pin =  obj->pinIndex ;
76         GPIO_InitStructure.Pull = obj->pull = type;
77         GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
78 
79         if( mode == PIN_INPUT )
80         {
81             GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
82         }
83         else if( mode == PIN_ANALOGIC )
84         {
85             GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
86         }
87         else if( mode == PIN_ALTERNATE_FCT )
88         {
89             if( config == PIN_OPEN_DRAIN )
90             {
91                 GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
92             }
93             else
94             {
95                 GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
96             }
97             GPIO_InitStructure.Alternate = value;
98         }
99         else // mode output
100         {
101             if( config == PIN_OPEN_DRAIN )
102             {
103                 GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
104             }
105             else
106             {
107                 GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
108             }
109         }
110 
111         // Sets initial output value
112         if( mode == PIN_OUTPUT )
113         {
114             GpioMcuWrite( obj, value );
115         }
116 
117         HAL_GPIO_Init( obj->port, &GPIO_InitStructure );
118     }
119     else
120     {
121 #if defined( BOARD_IOE_EXT )
122         // IOExt Pin
123         GpioIoeInit( obj, pin, mode, config, type, value );
124 #endif
125     }
126 }
127 
GpioMcuSetContext(Gpio_t * obj,void * context)128 void GpioMcuSetContext( Gpio_t *obj, void* context )
129 {
130     obj->Context = context;
131 }
132 
GpioMcuSetInterrupt(Gpio_t * obj,IrqModes irqMode,IrqPriorities irqPriority,GpioIrqHandler * irqHandler)133 void GpioMcuSetInterrupt( Gpio_t *obj, IrqModes irqMode, IrqPriorities irqPriority, GpioIrqHandler *irqHandler )
134 {
135     if( obj->pin < IOE_0 )
136     {
137         uint32_t priority = 0;
138 
139         IRQn_Type IRQnb = EXTI0_1_IRQn;
140         GPIO_InitTypeDef   GPIO_InitStructure;
141 
142         if( irqHandler == NULL )
143         {
144             return;
145         }
146 
147         obj->IrqHandler = irqHandler;
148 
149         GPIO_InitStructure.Pin =  obj->pinIndex;
150 
151         if( irqMode == IRQ_RISING_EDGE )
152         {
153             GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
154         }
155         else if( irqMode == IRQ_FALLING_EDGE )
156         {
157             GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING;
158         }
159         else
160         {
161             GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING_FALLING;
162         }
163 
164         GPIO_InitStructure.Pull = obj->pull;
165         GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
166 
167         HAL_GPIO_Init( obj->port, &GPIO_InitStructure );
168 
169         switch( irqPriority )
170         {
171         case IRQ_VERY_LOW_PRIORITY:
172         case IRQ_LOW_PRIORITY:
173             priority = 3;
174             break;
175         case IRQ_MEDIUM_PRIORITY:
176             priority = 2;
177             break;
178         case IRQ_HIGH_PRIORITY:
179             priority = 1;
180             break;
181         case IRQ_VERY_HIGH_PRIORITY:
182         default:
183             priority = 0;
184             break;
185         }
186 
187         switch( obj->pinIndex )
188         {
189         case GPIO_PIN_0:
190         case GPIO_PIN_1:
191             IRQnb = EXTI0_1_IRQn;
192             break;
193         case GPIO_PIN_2:
194         case GPIO_PIN_3:
195             IRQnb = EXTI2_3_IRQn;
196             break;
197         case GPIO_PIN_4:
198         case GPIO_PIN_5:
199         case GPIO_PIN_6:
200         case GPIO_PIN_7:
201         case GPIO_PIN_8:
202         case GPIO_PIN_9:
203         case GPIO_PIN_10:
204         case GPIO_PIN_11:
205         case GPIO_PIN_12:
206         case GPIO_PIN_13:
207         case GPIO_PIN_14:
208         case GPIO_PIN_15:
209             IRQnb = EXTI4_15_IRQn;
210             break;
211         default:
212             break;
213         }
214 
215         GpioIrq[( obj->pin ) & 0x0F] = obj;
216 
217         HAL_NVIC_SetPriority( IRQnb , priority, 0 );
218         HAL_NVIC_EnableIRQ( IRQnb );
219     }
220     else
221     {
222 #if defined( BOARD_IOE_EXT )
223         // IOExt Pin
224         GpioIoeSetInterrupt( obj, irqMode, irqPriority, irqHandler );
225 #endif
226     }
227 }
228 
GpioMcuRemoveInterrupt(Gpio_t * obj)229 void GpioMcuRemoveInterrupt( Gpio_t *obj )
230 {
231     if( obj->pin < IOE_0 )
232     {
233         // Clear callback before changing pin mode
234         GpioIrq[( obj->pin ) & 0x0F] = NULL;
235 
236         GPIO_InitTypeDef   GPIO_InitStructure;
237 
238         GPIO_InitStructure.Pin =  obj->pinIndex ;
239         GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
240         HAL_GPIO_Init( obj->port, &GPIO_InitStructure );
241     }
242     else
243     {
244 #if defined( BOARD_IOE_EXT )
245         // IOExt Pin
246         GpioIoeRemoveInterrupt( obj );
247 #endif
248     }
249 }
250 
GpioMcuWrite(Gpio_t * obj,uint32_t value)251 void GpioMcuWrite( Gpio_t *obj, uint32_t value )
252 {
253     if( obj->pin < IOE_0 )
254     {
255         if( obj == NULL )
256         {
257             assert_param( LMN_STATUS_ERROR );
258         }
259         // Check if pin is not connected
260         if( obj->pin == NC )
261         {
262             return;
263         }
264         HAL_GPIO_WritePin( obj->port, obj->pinIndex , ( GPIO_PinState )value );
265     }
266     else
267     {
268 #if defined( BOARD_IOE_EXT )
269         // IOExt Pin
270         GpioIoeWrite( obj, value );
271 #endif
272     }
273 }
274 
GpioMcuToggle(Gpio_t * obj)275 void GpioMcuToggle( Gpio_t *obj )
276 {
277     if( obj->pin < IOE_0 )
278     {
279         if( obj == NULL )
280         {
281             assert_param( LMN_STATUS_ERROR );
282         }
283 
284         // Check if pin is not connected
285         if( obj->pin == NC )
286         {
287             return;
288         }
289         HAL_GPIO_TogglePin( obj->port, obj->pinIndex );
290     }
291     else
292     {
293 #if defined( BOARD_IOE_EXT )
294         // IOExt Pin
295         GpioIoeToggle( obj );
296 #endif
297     }
298 }
299 
GpioMcuRead(Gpio_t * obj)300 uint32_t GpioMcuRead( Gpio_t *obj )
301 {
302     if( obj->pin < IOE_0 )
303     {
304         if( obj == NULL )
305         {
306             assert_param( LMN_STATUS_ERROR );
307         }
308         // Check if pin is not connected
309         if( obj->pin == NC )
310         {
311             return 0;
312         }
313         return HAL_GPIO_ReadPin( obj->port, obj->pinIndex );
314     }
315     else
316     {
317 #if defined( BOARD_IOE_EXT )
318         // IOExt Pin
319         return GpioIoeRead( obj );
320 #else
321         return 0;
322 #endif
323     }
324 }
325 
EXTI0_1_IRQHandler(void)326 void EXTI0_1_IRQHandler( void )
327 {
328     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_0 );
329     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_1 );
330 }
331 
EXTI2_3_IRQHandler(void)332 void EXTI2_3_IRQHandler( void )
333 {
334     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_2 );
335     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_3 );
336 }
337 
EXTI4_15_IRQHandler(void)338 void EXTI4_15_IRQHandler( void )
339 {
340     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_4 );
341     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_5 );
342     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_6 );
343     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_7 );
344     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_8 );
345     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_9 );
346     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_10 );
347     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_11 );
348     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_12 );
349     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_13 );
350     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_14 );
351     HAL_GPIO_EXTI_IRQHandler( GPIO_PIN_15 );
352 }
353 
HAL_GPIO_EXTI_Callback(uint16_t gpioPin)354 void HAL_GPIO_EXTI_Callback( uint16_t gpioPin )
355 {
356     uint8_t callbackIndex = 0;
357 
358     if( gpioPin > 0 )
359     {
360         while( gpioPin != 0x01 )
361         {
362             gpioPin = gpioPin >> 1;
363             callbackIndex++;
364         }
365     }
366 
367     if( ( GpioIrq[callbackIndex] != NULL ) && ( GpioIrq[callbackIndex]->IrqHandler != NULL ) )
368     {
369         GpioIrq[callbackIndex]->IrqHandler( GpioIrq[callbackIndex]->Context );
370     }
371 }
372