1 /**************************************************************************//**
2 * @file bmc.c
3 * @version V3.00
4 * @brief M460 series BMC driver source file
5 *
6 * @copyright SPDX-License-Identifier: Apache-2.0
7 * @copyright Copyright (C) 2021 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9 #include "NuMicro.h"
10
11 /** @addtogroup Standard_Driver Standard Driver
12 @{
13 */
14
15 /** @addtogroup BMC_Driver BMC Driver
16 @{
17 */
18
19
20 /** @addtogroup BMC_EXPORTED_FUNCTIONS BMC Exported Functions
21 @{
22 */
23
24 /**
25 * @brief Set the BMC bit clock
26 * @param[in] u32BitClock The expected frequency of BMC bit clock in Hz
27 * @return Actual frequency of BMC bit clock
28 * @details The actual clock rate may be different from the target BMC bit clock rate.
29 * For example, if the system clock rate is 200 MHz and the target BMC bit clock rate is 3 MHz, the actual BMC bit clock
30 * rate will be 2 MHz.
31 * \hideinitializer
32 */
BMC_SetBitClock(uint32_t u32BitClock)33 uint32_t BMC_SetBitClock(uint32_t u32BitClock)
34 {
35 uint32_t u32HCLKFreq, u32Div, u32RetValue;
36
37 /* Get system clock frequency */
38 u32HCLKFreq = CLK_GetHCLKFreq();
39
40 u32Div = ((u32HCLKFreq * 10UL) / u32BitClock + 5UL) / 10UL; /* Round to the nearest integer */
41
42 BMC->CTL = (BMC->CTL & (~BMC_CTL_BTDIV_Msk)) | (u32Div << BMC_CTL_BTDIV_Pos);
43
44 /* Return BMC bit clock rate */
45 u32RetValue = u32HCLKFreq / u32Div;
46
47 return u32RetValue;
48 }
49
50 /**
51 * @brief Get the actual frequency of BMC bit clock
52 * @return Actual BMC bit frequency in Hz
53 * @details This API will calculate the actual BMC bit clock rate according to the HBTDIV setting.
54 * \hideinitializer
55 */
BMC_GetBitClock(void)56 uint32_t BMC_GetBitClock(void)
57 {
58 uint32_t u32HCLKFreq, u32Div;
59
60 /* Get BTDIV setting */
61 u32Div = (BMC->CTL & BMC_CTL_BTDIV_Msk) >> BMC_CTL_BTDIV_Pos;
62
63 /* Get system clock frequency */
64 u32HCLKFreq = CLK_GetHCLKFreq();
65
66 /* Return BMC bit clock rate */
67 return (u32HCLKFreq / u32Div);
68 }
69
70 /**
71 * @brief Set the dummy delay time period of each group
72 * @param[in] u32ChGroup BMC channel group selection, valid values are:
73 * - \ref BMC_GROUP_0
74 * - \ref BMC_GROUP_1
75 * - \ref BMC_GROUP_2
76 * - \ref BMC_GROUP_3
77 * - \ref BMC_GROUP_4
78 * - \ref BMC_GROUP_5
79 * - \ref BMC_GROUP_6
80 * - \ref BMC_GROUP_7
81 * @param[in] u32DumDelay The expected BMC dummy delay period in microsecond
82 * @return Actual dummy delay time period in microsecond
83 * @details This API is used to set each group dummy delay time period.
84 * \hideinitializer
85 */
BMC_SetDummyDelayPeriod(uint32_t u32ChGroup,uint32_t u32DumDelay)86 uint32_t BMC_SetDummyDelayPeriod(uint32_t u32ChGroup, uint32_t u32DumDelay)
87 {
88 uint32_t i, u32BitNum;
89
90 u32BitNum = ((BMC_GetBitClock() * u32DumDelay) / 1000000UL) / 8UL;
91
92 for(i = 0UL; i < (uint32_t)BMC_CHANNEL_NUM; i += 4UL)
93 {
94 if((u32ChGroup == i) && (u32ChGroup <= BMC_GROUP_3))
95 {
96 outp8((uint32_t)&(BMC->DNUM0) + (i >> 2UL), u32BitNum);
97 break;
98 }
99 else if((u32ChGroup == i) && (u32ChGroup > BMC_GROUP_3))
100 {
101 outp8((uint32_t)&(BMC->DNUM1) + ((i >> 2UL) - 4UL), u32BitNum);
102 break;
103 }
104 }
105
106 /* Return BMC dummy delay time period */
107 return (8UL * 1000000UL / BMC_GetBitClock() * u32BitNum);
108 }
109
110 /**
111 * @brief Enable interrupt function
112 * @param[in] u32Mask The combination of all related interrupt enable bits.
113 * Each bit corresponds to a interrupt enable bit.
114 * This parameter decides which interrupts will be enabled. It is combination of:
115 * - \ref BMC_FTXD_INT_MASK
116 * - \ref BMC_TXUND_INT_MASK
117 * @return None
118 * @details This API is used to enable BMC related interrupts specified by u32Mask parameter.
119 * \hideinitializer
120 */
BMC_EnableInt(uint32_t u32Mask)121 void BMC_EnableInt(uint32_t u32Mask)
122 {
123 /* Enable frame transmit done interrupt flag */
124 if((u32Mask & BMC_FTXD_INT_MASK) == BMC_FTXD_INT_MASK)
125 {
126 BMC->INTEN |= BMC_INTEN_FTXDIEN_Msk;
127 }
128
129 /* Enable transmit data under run interrupt flag */
130 if((u32Mask & BMC_TXUND_INT_MASK) == BMC_TXUND_INT_MASK)
131 {
132 BMC->INTEN |= BMC_INTEN_TXUNDIEN_Msk;
133 }
134 }
135
136 /**
137 * @brief Disable interrupt function
138 * @param[in] u32Mask The combination of all related interrupt enable bits.
139 * Each bit corresponds to a interrupt enable bit.
140 * This parameter decides which interrupts will be disabled. It is combination of:
141 * - \ref BMC_FTXD_INT_MASK
142 * - \ref BMC_TXUND_INT_MASK
143 * @return None
144 * @details This API is used to disable BMC related interrupts specified by u32Mask parameter.
145 * \hideinitializer
146 */
BMC_DisableInt(uint32_t u32Mask)147 void BMC_DisableInt(uint32_t u32Mask)
148 {
149 /* Disable frame transmit done interrupt flag */
150 if((u32Mask & BMC_FTXD_INT_MASK) == BMC_FTXD_INT_MASK)
151 {
152 BMC->INTEN &= ~BMC_INTEN_FTXDIEN_Msk;
153 }
154
155 /* Disable transmit data under run interrupt flag */
156 if((u32Mask & BMC_TXUND_INT_MASK) == BMC_TXUND_INT_MASK)
157 {
158 BMC->INTEN &= ~BMC_INTEN_TXUNDIEN_Msk;
159 }
160 }
161
162 /**
163 * @brief Get interrupt flag
164 * @param[in] u32Mask The combination of all related interrupt sources.
165 * Each bit corresponds to a interrupt source.
166 * This parameter decides which interrupt flags will be read. It is combination of:
167 * - \ref BMC_FTXD_INT_MASK
168 * - \ref BMC_TXUND_INT_MASK
169 * @return Interrupt flags of selected sources
170 * @details This API is used to get BMC related interrupt flags specified by u32Mask parameter.
171 * \hideinitializer
172 */
BMC_GetIntFlag(uint32_t u32Mask)173 uint32_t BMC_GetIntFlag(uint32_t u32Mask)
174 {
175 uint32_t u32IntStatus;
176 uint32_t u32IntFlag = 0UL;
177
178 u32IntStatus = BMC->INTSTS;
179
180 /* Check frame transmit done interrupt flag */
181 if((u32Mask & BMC_FTXD_INT_MASK) && (u32IntStatus & BMC_INTSTS_FTXDIF_Msk))
182 {
183 u32IntFlag |= BMC_FTXD_INT_MASK;
184 }
185
186 /* Check transmit data under run interrupt flag */
187 if((u32Mask & BMC_TXUND_INT_MASK) && (u32IntStatus & BMC_INTSTS_TXUNDIF_Msk))
188 {
189 u32IntFlag |= BMC_TXUND_INT_MASK;
190 }
191
192 return u32IntFlag;
193 }
194
195 /**
196 * @brief Clear interrupt flag
197 * @param[in] u32Mask The related interrupt source.
198 * This parameter decides which interrupt flag will be cleared. Possible option is:
199 * - \ref BMC_FTXD_INT_MASK
200 * @return None
201 * @details This API is used to clear BMC related interrupt flag specified by u32Mask parameter.
202 * \hideinitializer
203 */
BMC_ClearIntFlag(uint32_t u32Mask)204 void BMC_ClearIntFlag(uint32_t u32Mask)
205 {
206 if(u32Mask & BMC_FTXD_INT_MASK)
207 {
208 BMC->INTSTS = BMC_INTSTS_FTXDIF_Msk; /* Clear frame transmit done interrupt flag */
209 }
210 }
211
212 /**
213 * @brief Get BMC status
214 * @param[in] u32Mask The combination of all related sources.
215 * Each bit corresponds to a related source.
216 * This parameter decides which flags will be read. It is combination of:
217 * - \ref BMC_G0TXUND_MASK
218 * - \ref BMC_G1TXUND_MASK
219 * - \ref BMC_G2TXUND_MASK
220 * - \ref BMC_G3TXUND_MASK
221 * - \ref BMC_G4TXUND_MASK
222 * - \ref BMC_G5TXUND_MASK
223 * - \ref BMC_G6TXUND_MASK
224 * - \ref BMC_G7TXUND_MASK
225 * @return Flags of selected sources
226 * @details This API is used to get BMC related status specified by u32Mask parameter.
227 * \hideinitializer
228 */
BMC_GetStatus(uint32_t u32Mask)229 uint32_t BMC_GetStatus(uint32_t u32Mask)
230 {
231 uint32_t u32TmpStatus;
232 uint32_t u32Flag = 0UL;
233
234 u32TmpStatus = BMC->INTSTS;
235
236 /* Check group 0 transmit data under run status */
237 if((u32Mask & BMC_G0TXUND_MASK) && (u32TmpStatus & BMC_INTSTS_G0TXUND_Msk))
238 {
239 u32Flag |= BMC_G0TXUND_MASK;
240 }
241
242 /* Check group 1 transmit data under run status */
243 if((u32Mask & BMC_G1TXUND_MASK) && (u32TmpStatus & BMC_INTSTS_G1TXUND_Msk))
244 {
245 u32Flag |= BMC_G1TXUND_MASK;
246 }
247
248 /* Check group 2 transmit data under run status */
249 if((u32Mask & BMC_G2TXUND_MASK) && (u32TmpStatus & BMC_INTSTS_G2TXUND_Msk))
250 {
251 u32Flag |= BMC_G2TXUND_MASK;
252 }
253
254 /* Check group 3 transmit data under run status */
255 if((u32Mask & BMC_G3TXUND_MASK) && (u32TmpStatus & BMC_INTSTS_G3TXUND_Msk))
256 {
257 u32Flag |= BMC_G3TXUND_MASK;
258 }
259
260 /* Check group 4 transmit data under run status */
261 if((u32Mask & BMC_G4TXUND_MASK) && (u32TmpStatus & BMC_INTSTS_G4TXUND_Msk))
262 {
263 u32Flag |= BMC_G4TXUND_MASK;
264 }
265
266 /* Check group 5 transmit data under run status */
267 if((u32Mask & BMC_G5TXUND_MASK) && (u32TmpStatus & BMC_INTSTS_G5TXUND_Msk))
268 {
269 u32Flag |= BMC_G5TXUND_MASK;
270 }
271
272 /* Check group 6 transmit data under run status */
273 if((u32Mask & BMC_G6TXUND_MASK) && (u32TmpStatus & BMC_INTSTS_G6TXUND_Msk))
274 {
275 u32Flag |= BMC_G6TXUND_MASK;
276 }
277
278 /* Check group 7 transmit data under run status */
279 if((u32Mask & BMC_G7TXUND_MASK) && (u32TmpStatus & BMC_INTSTS_G7TXUND_Msk))
280 {
281 u32Flag |= BMC_G7TXUND_MASK;
282 }
283
284 return u32Flag;
285 }
286
287 /**
288 * @brief Clear BMC status
289 * @param[in] u32Mask The combination of all related sources.
290 * Each bit corresponds to a related source.
291 * This parameter decides which flags will be cleared. It is combination of:
292 * - \ref BMC_G0TXUND_MASK
293 * - \ref BMC_G1TXUND_MASK
294 * - \ref BMC_G2TXUND_MASK
295 * - \ref BMC_G3TXUND_MASK
296 * - \ref BMC_G4TXUND_MASK
297 * - \ref BMC_G5TXUND_MASK
298 * - \ref BMC_G6TXUND_MASK
299 * - \ref BMC_G7TXUND_MASK
300 * @return None
301 * @details This API is used to clear BMC related status specified by u32Mask parameter.
302 * \hideinitializer
303 */
BMC_ClearStatus(uint32_t u32Mask)304 void BMC_ClearStatus(uint32_t u32Mask)
305 {
306 if(u32Mask & BMC_G0TXUND_MASK)
307 {
308 BMC->INTSTS = BMC_INTSTS_G0TXUND_Msk; /* Check group 0 transmit data under run status */
309 }
310
311 if(u32Mask & BMC_G1TXUND_MASK)
312 {
313 BMC->INTSTS = BMC_INTSTS_G1TXUND_Msk; /* Check group 1 transmit data under run status */
314 }
315
316 if(u32Mask & BMC_G2TXUND_MASK)
317 {
318 BMC->INTSTS = BMC_INTSTS_G2TXUND_Msk; /* Check group 2 transmit data under run status */
319 }
320
321 if(u32Mask & BMC_G3TXUND_MASK)
322 {
323 BMC->INTSTS = BMC_INTSTS_G3TXUND_Msk; /* Check group 3 transmit data under run status */
324 }
325
326 if(u32Mask & BMC_G4TXUND_MASK)
327 {
328 BMC->INTSTS = BMC_INTSTS_G4TXUND_Msk; /* Check group 4 transmit data under run status */
329 }
330
331 if(u32Mask & BMC_G5TXUND_MASK)
332 {
333 BMC->INTSTS = BMC_INTSTS_G5TXUND_Msk; /* Check group 5 transmit data under run status */
334 }
335
336 if(u32Mask & BMC_G6TXUND_MASK)
337 {
338 BMC->INTSTS = BMC_INTSTS_G6TXUND_Msk; /* Check group 6 transmit data under run status */
339 }
340
341 if(u32Mask & BMC_G7TXUND_MASK)
342 {
343 BMC->INTSTS = BMC_INTSTS_G7TXUND_Msk; /* Check group 7 transmit data under run status */
344 }
345 }
346
347
348 /*@}*/ /* end of group BMC_EXPORTED_FUNCTIONS */
349
350 /*@}*/ /* end of group BMC_Driver */
351
352 /*@}*/ /* end of group Standard_Driver */
353