1 /*
2 * Copyright (c) 2022 OpenLuat & AirM2M
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy of
5 * this software and associated documentation files (the "Software"), to deal in
6 * the Software without restriction, including without limitation the rights to
7 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8 * the Software, and to permit persons to whom the Software is furnished to do so,
9 * subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 */
21
22 #include "user.h"
23 typedef struct
24 {
25 volatile GPIO_TypeDef *RegBase;
26 const int32_t IrqLine;
27 uint16_t ODBitMap;
28
29 }GPIO_ResourceStruct;
30
31 typedef struct
32 {
33 CBFuncEx_t AllCB;
34 CBFuncEx_t HWTimerCB;
35 void *pParam;
36 }GPIO_CtrlStruct;
37
38 static GPIO_CtrlStruct prvGPIO;
39
40 static GPIO_ResourceStruct prvGPIO_Resource[6] =
41 {
42 {
43 GPIOA,
44 EXTI0_IRQn,
45 0,
46 },
47 {
48 GPIOB,
49 EXTI1_IRQn,
50 0,
51 },
52 {
53 GPIOC,
54 EXTI2_IRQn,
55 0,
56 },
57 {
58 GPIOD,
59 EXTI3_IRQn,
60 0,
61 },
62 {
63 GPIOE,
64 EXTI4_IRQn,
65 0,
66 },
67 {
68 GPIOF,
69 EXTI5_IRQn,
70 0,
71 },
72 };
73
GPIO_IrqDummyCB(void * pData,void * pParam)74 static int32_t GPIO_IrqDummyCB(void *pData, void *pParam)
75 {
76 // DBG("%d", pData);
77 return 0;
78 }
GPIO_IrqHandle(int32_t IrqLine,void * pData)79 static void __FUNC_IN_RAM__ GPIO_IrqHandle(int32_t IrqLine, void *pData)
80 {
81 volatile uint32_t Port = (uint32_t)pData;
82 volatile uint32_t Sn, i;
83 if (GPIO->INTP_TYPE_STA[Port].INTP_STA)
84 {
85 Sn = GPIO->INTP_TYPE_STA[Port].INTP_STA;
86 GPIO->INTP_TYPE_STA[Port].INTP_STA = 0xffff;
87 prvGPIO.HWTimerCB((Port << 16) | Sn, prvGPIO.pParam);
88 Port = (Port << 4);
89
90 for(i = 0; i < 16; i++)
91 {
92 if (Sn & (1 << i))
93 {
94 prvGPIO.AllCB((void *)(Port+i), 0);
95 }
96 }
97 }
98 ISR_Clear(IrqLine);
99 }
100
GPIO_GlobalInit(CBFuncEx_t Fun)101 void GPIO_GlobalInit(CBFuncEx_t Fun)
102 {
103 uint32_t i;
104 if (Fun)
105 {
106 prvGPIO.AllCB = Fun;
107 }
108 else
109 {
110 prvGPIO.AllCB = GPIO_IrqDummyCB;
111 }
112 prvGPIO.HWTimerCB = GPIO_IrqDummyCB;
113 for(i = 0; i < 6; i++)
114 {
115 GPIO->INTP_TYPE_STA[i].INTP_TYPE = 0;
116 GPIO->INTP_TYPE_STA[i].INTP_STA = 0xffff;
117 #ifdef __BUILD_OS__
118 ISR_SetPriority(prvGPIO_Resource[i].IrqLine, IRQ_MAX_PRIORITY + 1);
119 #else
120 ISR_SetPriority(prvGPIO_Resource[i].IrqLine, 3);
121 #endif
122 ISR_SetHandler(prvGPIO_Resource[i].IrqLine, GPIO_IrqHandle, (void *)i);
123 ISR_OnOff(prvGPIO_Resource[i].IrqLine, 1);
124 }
125
126 }
127
GPIO_Config(uint32_t Pin,uint8_t IsInput,uint8_t InitValue)128 void __FUNC_IN_RAM__ GPIO_Config(uint32_t Pin, uint8_t IsInput, uint8_t InitValue)
129 {
130 uint8_t Port = (Pin >> 4);
131 uint8_t orgPin = Pin;
132 Pin = 1 << (Pin & 0x0000000f);
133 GPIO_Iomux(orgPin, 1);
134 if (IsInput)
135 {
136 prvGPIO_Resource[Port].RegBase->OEN |= Pin;
137 }
138 else
139 {
140 prvGPIO_Resource[Port].RegBase->BSRR |= InitValue?Pin:(Pin << 16);
141 prvGPIO_Resource[Port].RegBase->OEN &= ~Pin;
142 }
143 prvGPIO_Resource[Port].ODBitMap &= ~Pin;
144 }
145
GPIO_ODConfig(uint32_t Pin,uint8_t InitValue)146 void __FUNC_IN_RAM__ GPIO_ODConfig(uint32_t Pin, uint8_t InitValue)
147 {
148 uint8_t Port = (Pin >> 4);
149 uint8_t orgPin = Pin;
150 Pin = 1 << (Pin & 0x0000000f);
151 GPIO_Iomux(orgPin, 1);
152 prvGPIO_Resource[Port].RegBase->OEN |= Pin;
153 if (InitValue)
154 {
155 prvGPIO_Resource[Port].RegBase->PUE |= Pin;
156 }
157 else
158 {
159 prvGPIO_Resource[Port].RegBase->PUE &= ~Pin;
160 }
161 prvGPIO_Resource[Port].ODBitMap |= Pin;
162 }
163
GPIO_PullConfig(uint32_t Pin,uint8_t IsPull,uint8_t IsUp)164 void __FUNC_IN_RAM__ GPIO_PullConfig(uint32_t Pin, uint8_t IsPull, uint8_t IsUp)
165 {
166 uint8_t Port = (Pin >> 4);
167 Pin = 1 << (Pin & 0x0000000f);
168 if (IsPull && IsUp)
169 {
170 prvGPIO_Resource[Port].RegBase->PUE |= Pin;
171 }
172 else
173 {
174 prvGPIO_Resource[Port].RegBase->PUE &= ~Pin;
175 }
176 }
177
GPIO_ExtiConfig(uint32_t Pin,uint8_t IsLevel,uint8_t IsRiseHigh,uint8_t IsFallLow)178 void GPIO_ExtiConfig(uint32_t Pin, uint8_t IsLevel, uint8_t IsRiseHigh, uint8_t IsFallLow)
179 {
180 uint8_t Port = (Pin >> 4);
181 uint32_t Type = 0;
182 uint32_t Mask = ~(0x03 << ((Pin & 0x0000000f) * 2));
183 if (!IsLevel)
184 {
185 if (IsRiseHigh && IsFallLow)
186 {
187 Type = 0x03 << ((Pin & 0x0000000f) * 2);
188 }
189 else if (IsFallLow)
190 {
191 Type = 0x02 << ((Pin & 0x0000000f) * 2);
192 }
193 else if (IsRiseHigh)
194 {
195 Type = 0x01 << ((Pin & 0x0000000f) * 2);
196 }
197 }
198 GPIO->INTP_TYPE_STA[Port].INTP_TYPE = (GPIO->INTP_TYPE_STA[Port].INTP_TYPE & Mask) | Type;
199 }
200
GPIO_ExtiSetHWTimerCB(CBFuncEx_t CB,void * pParam)201 void GPIO_ExtiSetHWTimerCB(CBFuncEx_t CB, void *pParam)
202 {
203 if (CB)
204 {
205 prvGPIO.HWTimerCB = CB;
206 }
207 else
208 {
209 prvGPIO.HWTimerCB = GPIO_IrqDummyCB;
210 }
211 prvGPIO.pParam = pParam;
212 }
213
GPIO_Iomux(uint32_t Pin,uint32_t Function)214 void __FUNC_IN_RAM__ GPIO_Iomux(uint32_t Pin, uint32_t Function)
215 {
216 uint8_t Port = (Pin >> 4);
217 uint32_t Mask = ~(0x03 << ((Pin & 0x0000000f) * 2));
218 Function = Function << ((Pin & 0x0000000f) * 2);
219 GPIO->ALT[Port] = (GPIO->ALT[Port] & Mask) | Function;
220 }
221
GPIO_Output(uint32_t Pin,uint8_t Level)222 void __FUNC_IN_RAM__ GPIO_Output(uint32_t Pin, uint8_t Level)
223 {
224 uint8_t Port = (Pin >> 4);
225 Pin = 1 << (Pin & 0x0000000f);
226 if (prvGPIO_Resource[Port].ODBitMap & Pin)
227 {
228 if (Level)
229 {
230 prvGPIO_Resource[Port].RegBase->PUE |= Pin;
231 }
232 else
233 {
234 prvGPIO_Resource[Port].RegBase->PUE &= ~Pin;
235 }
236 }
237 else
238 {
239 prvGPIO_Resource[Port].RegBase->BSRR |= Level?Pin:(Pin << 16);
240 }
241
242 // DBG("%d, %x, %x, %x",Port, Pin, prvGPIO_Resource[Port].RegBase, prvGPIO_Resource[Port].RegBase->IODR);
243 }
244
GPIO_Input(uint32_t Pin)245 uint8_t __FUNC_IN_RAM__ GPIO_Input(uint32_t Pin)
246 {
247 uint8_t Port = (Pin >> 4);
248 Pin = 1 << (Pin & 0x0000000f);
249 return (prvGPIO_Resource[Port].RegBase->IODR & (Pin << 16))?1:0;
250 }
251
GPIO_OutputMulti(uint32_t Port,uint32_t Pins,uint32_t Level)252 void __FUNC_IN_RAM__ GPIO_OutputMulti(uint32_t Port, uint32_t Pins, uint32_t Level)
253 {
254 prvGPIO_Resource[Port].RegBase->BSRR |= Level?Pins:(Pins << 16);
255 }
256
GPIO_InputMulti(uint32_t Port)257 uint32_t __FUNC_IN_RAM__ GPIO_InputMulti(uint32_t Port)
258 {
259 return (prvGPIO_Resource[Port].RegBase->IODR >> 16);
260 }
261