1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
|
/**************************************************************************//**
*
* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-11-11 Wayne First version
*
******************************************************************************/
#include <rthw.h>
#include <rtthread.h>
#include "NuMicro.h"
#include "drv_sys.h"
#define SYS_MIN_INT_SOURCE 1
#define SYS_MAX_INT_SOURCE 63
#define SYS_NUM_OF_AICREG 16
#define INT_IRQ 0x00
#define INT_FIQ 0x01
extern rt_atomic_t rt_interrupt_nest;
rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
rt_uint32_t rt_thread_switch_interrupt_flag;
struct rt_irq_desc irq_desc[SYS_MAX_INT_SOURCE + 1];
void rt_hw_interrupt_dummy_handler(int vector, void *param)
{
rt_kprintf("Unhandled interrupt %d occurred!!!\n", vector);
RT_ASSERT(0);
}
rt_uint32_t rt_hw_interrupt_get_active(rt_uint32_t fiq_irq)
{
rt_uint32_t active = 0;
#if 0
rt_uint32_t volatile _mIPER, _mISNR;
_mIPER = (inpw(REG_AIC_IPER) >> 2) & 0x3f;
_mISNR = inpw(REG_AIC_ISNR);
if ((_mISNR != 0) && (_mIPER == _mISNR))
active = _mISNR;
#else
if (fiq_irq != INT_FIQ)
{
active = inpw(REG_AIC_IRQNUM);
}
else
active = inpw(REG_AIC_FIQNUM);
#endif
return active;
}
void rt_hw_interrupt_set_priority(int vector, int IntTypeLevel)
{
rt_uint32_t _mRegAddr;
rt_uint32_t shift;
if ((vector > SYS_MAX_INT_SOURCE) || (vector < SYS_MIN_INT_SOURCE))
return;
_mRegAddr = REG_AIC_SRCCTL0 + ((vector / 4) * 4);
shift = (vector % 4) * 8;
IntTypeLevel &= 0x7;
outpw(_mRegAddr, (inpw(_mRegAddr) & ~(0x07 << shift)) | (IntTypeLevel << shift));
}
void rt_hw_interrupt_ack(rt_uint32_t fiq_irq, rt_uint32_t id)
{
if (fiq_irq != INT_FIQ)
outpw(REG_AIC_EOIS, 1);
else
outpw(REG_AIC_EOFS, 1);
}
void rt_interrupt_dispatch(rt_uint32_t fiq_irq)
{
rt_isr_handler_t isr_func;
rt_uint32_t irq;
void *param;
/* get irq number */
irq = rt_hw_interrupt_get_active(fiq_irq);
/* get interrupt service routine */
isr_func = irq_desc[irq].handler;
param = irq_desc[irq].param;
/* turn to interrupt service routine */
isr_func(irq, param);
rt_hw_interrupt_ack(fiq_irq, irq);
#ifdef RT_USING_INTERRUPT_INFO
irq_desc[irq].counter ++;
#endif
}
void rt_hw_interrupt_init(void)
{
int i;
outpw(REG_AIC_INTDIS0, 0xFFFFFFFF); // disable all interrupt channel
outpw(REG_AIC_INTDIS1, 0xFFFFFFFF); // disable all interrupt channel
outpw(REG_AIC_EOIS, 1); // resetand restart AIC's IRQ processing
outpw(REG_AIC_EOFS, 1); // resetand restart AIC's IRQ processing
/* init interrupt nest, and context in thread sp */
rt_interrupt_nest = 0;
rt_interrupt_from_thread = 0;
rt_interrupt_to_thread = 0;
rt_thread_switch_interrupt_flag = 0;
for (i = 1; i <= SYS_MAX_INT_SOURCE; i++)
{
rt_hw_interrupt_install(i, rt_hw_interrupt_dummy_handler, RT_NULL, (char *)"dummy");
rt_hw_interrupt_mask(i);
}
}
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, const char *name)
{
rt_isr_handler_t old_handler = RT_NULL;
if (vector > SYS_MAX_INT_SOURCE)
return RT_NULL;
/* Set default priority IRQ_LEVEL_7 */
rt_hw_interrupt_set_priority(vector, IRQ_LEVEL_7);
old_handler = irq_desc[vector].handler;
if (handler != RT_NULL)
{
irq_desc[vector].handler = (rt_isr_handler_t)handler;
irq_desc[vector].param = param;
#ifdef RT_USING_INTERRUPT_INFO
rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name);
irq_desc[vector].counter = 0;
#endif
}
return old_handler;
}
/* Disable interrupt */
void rt_hw_interrupt_mask(int vector)
{
sysDisableInterrupt((IRQn_Type)vector);
}
void rt_hw_interrupt_umask(int vector)
{
sysEnableInterrupt((IRQn_Type)vector);
}
/* TYPE
* #define LOW_LEVEL_SENSITIVE 0x00
* #define HIGH_LEVEL_SENSITIVE 0x40
* #define NEGATIVE_EDGE_TRIGGER 0x80
* #define POSITIVE_EDGE_TRIGGER 0xC0
*/
void rt_hw_interrupt_set_type(int vector, int type)
{
rt_uint32_t _mRegAddr;
rt_uint32_t shift;
if ((vector > SYS_MAX_INT_SOURCE) || (vector < SYS_MIN_INT_SOURCE))
return ;
_mRegAddr = REG_AIC_SRCCTL0 + ((vector / 4) * 4);
shift = (vector % 4) * 8;
type &= 0xC0;
outpw(_mRegAddr, (inpw(_mRegAddr) & ~(0xC0 << shift)) | (type << shift));
}
void rt_low_level_init(void)
{
}
void nu_clock_base_init(void)
{
nu_sys_ipclk_enable(CPUCKEN);
nu_sys_ipclk_enable(HCLKCKEN);
nu_sys_ipclk_enable(HCLK1CKEN);
nu_sys_ipclk_enable(HCLK3CKEN);
nu_sys_ipclk_enable(HCLK4CKEN);
nu_sys_ipclk_enable(PCLK0CKEN);
nu_sys_ipclk_enable(PCLK1CKEN);
nu_sys_ipclk_enable(SRAMCKEN);
nu_sys_ipclk_enable(SDICCKEN);
nu_sys_ipclk_enable(PCLK2CKEN);
nu_sys_ipclk_enable(PCLKEN0_Reserved_3);
}
void machine_reset(void)
{
rt_kprintf("machine_reset...\n");
rt_hw_interrupt_disable();
/* Unlock */
SYS_UnlockReg();
nu_sys_ip_reset(CHIPRST);
while (1);
}
void machine_shutdown(void)
{
rt_kprintf("machine_shutdown...\n");
rt_hw_interrupt_disable();
/* Unlock */
SYS_UnlockReg();
while (1);
}
void nu_sys_ip_reset(E_SYS_IPRST eIPRstIdx)
{
uint32_t volatile u32IPRSTRegAddr;
uint32_t u32IPRSTRegBit;
rt_uint32_t level;
if (eIPRstIdx >= SYS_IPRST_CNT)
return;
u32IPRSTRegAddr = REG_SYS_AHBIPRST + (4ul * (eIPRstIdx / 32));
u32IPRSTRegBit = eIPRstIdx % 32;
/* Enter critical section */
level = rt_hw_interrupt_disable();
/* Unlock write-protect */
SYS_UnlockReg();
/* Enable IP reset */
outpw(u32IPRSTRegAddr, inpw(u32IPRSTRegAddr) | (1 << u32IPRSTRegBit));
/* Disable IP reset */
outpw(u32IPRSTRegAddr, inpw(u32IPRSTRegAddr) & ~(1 << u32IPRSTRegBit));
/* Wait it done. */
while (inpw(u32IPRSTRegAddr) & (1 << u32IPRSTRegBit)) {}
/* Lock write protect */
SYS_LockReg();
/* Leave critical section */
rt_hw_interrupt_enable(level);
}
static void _nu_sys_ipclk(E_SYS_IPCLK eIPClkIdx, uint32_t bEnable)
{
uint32_t volatile u32IPCLKRegAddr;
uint32_t u32IPCLKRegBit;
rt_uint32_t level;
if (eIPClkIdx >= SYS_IPCLK_CNT)
return;
u32IPCLKRegAddr = REG_CLK_HCLKEN + (4ul * (eIPClkIdx / 32));
u32IPCLKRegBit = eIPClkIdx % 32;
/* Enter critical section */
level = rt_hw_interrupt_disable();
SYS_UnlockReg();
if (bEnable)
{
/* Enable IP CLK */
outpw(u32IPCLKRegAddr, inpw(u32IPCLKRegAddr) | (1 << u32IPCLKRegBit));
}
else
{
/* Disable IP CLK */
outpw(u32IPCLKRegAddr, inpw(u32IPCLKRegAddr) & ~(1 << u32IPCLKRegBit));
}
SYS_LockReg();
/* Leave critical section */
rt_hw_interrupt_enable(level);
}
void nu_sys_ipclk_enable(E_SYS_IPCLK eIPClkIdx)
{
_nu_sys_ipclk(eIPClkIdx, 1);
}
void nu_sys_ipclk_disable(E_SYS_IPCLK eIPClkIdx)
{
_nu_sys_ipclk(eIPClkIdx, 0);
}
E_SYS_USB0_ID nu_sys_usb0_role(void)
{
/* Check Role on USB0 dual-role port. */
/*
[17] USB0_IDS
USB0_ID Status
0 = USB port 0 used as a USB device port.
1 = USB port 0 used as a USB host port.
*/
return ((inpw(REG_SYS_MISCISR) & (1 << 17)) > 0) ? USB0_ID_HOST : USB0_ID_DEVICE;
}
#ifdef RT_USING_FINSH
#include <finsh.h>
#ifdef FINSH_USING_MSH
int cmd_reset(int argc, char **argv)
{
rt_hw_cpu_reset();
return 0;
}
MSH_CMD_EXPORT_ALIAS(cmd_reset, reset, restart the system);
int cmd_shutdown(int argc, char **argv)
{
rt_hw_cpu_shutdown();
return 0;
}
MSH_CMD_EXPORT_ALIAS(cmd_shutdown, shutdown, shutdown the system);
int nu_clocks(int argc, char **argv)
{
rt_kprintf("SYS_UPLL = %d MHz\n", sysGetClock(SYS_UPLL));
rt_kprintf("SYS_APLL = %d MHz\n", sysGetClock(SYS_APLL));
rt_kprintf("SYS_SYSTEM = %d MHz\n", sysGetClock(SYS_SYSTEM));
rt_kprintf("SYS_HCLK = %d MHz\n", sysGetClock(SYS_HCLK));
rt_kprintf("SYS_PCLK01 = %d MHz\n", sysGetClock(SYS_PCLK01));
rt_kprintf("SYS_PCLK2 = %d MHz\n", sysGetClock(SYS_PCLK2));
rt_kprintf("SYS_CPU = %d MHz\n", sysGetClock(SYS_CPU));
rt_kprintf("CLK_HCLKEN = %08X\n", inpw(REG_CLK_HCLKEN));
rt_kprintf("CLK_PCLKEN0 = %08X\n", inpw(REG_CLK_PCLKEN0));
rt_kprintf("CLK_PCLKEN1 = %08X\n", inpw(REG_CLK_PCLKEN1));
rt_kprintf("AIC_INTMSK0 = %08X\n", inpw(REG_AIC_INTMSK0));
rt_kprintf("AIC_INTMSK1 = %08X\n", inpw(REG_AIC_INTMSK1));
rt_kprintf("AIC_INTEN0 = %08X\n", inpw(REG_AIC_INTEN0));
rt_kprintf("AIC_INTEN1 = %08X\n", inpw(REG_AIC_INTEN1));
rt_kprintf("AIC_INTDIS0 = %08X\n", inpw(REG_AIC_INTDIS0));
rt_kprintf("AIC_INTDIS1 = %08X\n", inpw(REG_AIC_INTDIS1));
return 0;
}
MSH_CMD_EXPORT(nu_clocks, get all system clocks);
#endif
#ifdef RT_USING_INTERRUPT_INFO
int list_interrupt(int argc, char **argv)
{
int i;
for (i = 1; i <= SYS_MAX_INT_SOURCE; i++)
{
if (irq_desc[i].handler != rt_hw_interrupt_dummy_handler)
{
rt_kprintf("[%d] %s: %d\n", i, irq_desc[i].name, irq_desc[i].counter);
}
}
return 0;
}
MSH_CMD_EXPORT(list_interrupt, list registered interrupts);
#endif
#endif
|