Skip to content

Commit 32e8b8e

Browse files
GUIDINGLIxiaoxiang781216
authored andcommitted
mps2: add zero-latency-interrupt case on mps2
Signed-off-by: ligd <liguiding1@xiaomi.com>
1 parent d5d8e9e commit 32e8b8e

File tree

2 files changed

+272
-0
lines changed

2 files changed

+272
-0
lines changed

testing/drivertest/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ ifeq ($(CONFIG_ARCH_CHIP_MPS2_AN500),y)
135135
ifeq ($(CONFIG_ARCH_IRQPRIO),y)
136136
MAINSRC += drivertest_mps2.c
137137
PROGNAME += cmocka_driver_mps2
138+
MAINSRC += drivertest_mps2_zerointerrupt.c
139+
PROGNAME += cmocka_driver_mps2_zerointerrupt
138140
endif
139141
endif
140142

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
/****************************************************************************
2+
* apps/testing/drivertest/drivertest_mps2_zerointerrupt.c
3+
*
4+
* Licensed to the Apache Software Foundation (ASF) under one or more
5+
* contributor license agreements. See the NOTICE file distributed with
6+
* this work for additional information regarding copyright ownership. The
7+
* ASF licenses this file to you under the Apache License, Version 2.0 (the
8+
* "License"); you may not use this file except in compliance with the
9+
* License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16+
* License for the specific language governing permissions and limitations
17+
* under the License.
18+
*
19+
****************************************************************************/
20+
21+
/****************************************************************************
22+
* Included Files
23+
****************************************************************************/
24+
25+
#include <nuttx/nuttx.h>
26+
#include <stdbool.h>
27+
#include <stdint.h>
28+
#include <stdio.h>
29+
#include <stdlib.h>
30+
#include <stdarg.h>
31+
#include <stddef.h>
32+
#include <setjmp.h>
33+
#include <string.h>
34+
#include <cmocka.h>
35+
36+
#include <nuttx/arch.h>
37+
#include <nuttx/irq.h>
38+
#include <nuttx/semaphore.h>
39+
40+
#include <pthread.h>
41+
42+
/****************************************************************************
43+
* Pre-processor Definitions
44+
****************************************************************************/
45+
46+
#define CONFIG_TEST_IRQPRIO_TTHREAD 8
47+
#define CONFIG_TEST_IRQPRIO_LOOP_CNT 5000
48+
49+
#ifndef NVIC_IRQ_PENDSV
50+
# define NVIC_IRQ_PENDSV 14
51+
#endif
52+
53+
#define MPS2_ADDR2REG_PTR(base, off) (uint32_t*)((uint32_t*)(base) + (off))
54+
#define MPS2_IRQ_FROMBASE(base, off) ((base) + (off))
55+
56+
/* https://developer.arm.com/documentation/101104/0200/programmers-model/
57+
* base-element/cmsdk-timer
58+
*/
59+
60+
#define MPS_TIMER_CTRL_OFFSET 0
61+
#define MPS_TIMER_VALUE_OFFSET 1
62+
#define MPS_TIMER_RELOAD_OFFSET 2
63+
#define MPS_TIMER_CLEAR_OFFSET 3
64+
65+
#define MPS_TIMER_CTRL_ENABLE (1<<0)
66+
#define MPS_TIMER_CTRL_IE (1<<3)
67+
68+
static_assert(NVIC_SYSH_PRIORITY_DEFAULT == 0x80, "prio");
69+
70+
/****************************************************************************
71+
* Private Types
72+
****************************************************************************/
73+
74+
typedef struct mps2_an500_timer_s
75+
{
76+
volatile uint32_t *reload;
77+
volatile uint32_t *ctrl;
78+
volatile uint32_t *clear;
79+
int irq;
80+
int before;
81+
sem_t *sem;
82+
int after;
83+
} mps2_an500_timer_t;
84+
85+
/****************************************************************************
86+
* Private Functions Prototypes
87+
****************************************************************************/
88+
89+
static int pendsv_irq_handle(int irq, void *context, void *arg);
90+
static int timer_irq_handle(int irq, void *context, void *arg);
91+
static int g_tag = 0;
92+
93+
/****************************************************************************
94+
* Private Data
95+
****************************************************************************/
96+
97+
static mps2_an500_timer_t g_timer;
98+
static sem_t test_sem = SEM_INITIALIZER(0);
99+
100+
static const int armv7m_gpio_base = 16;
101+
102+
/****************************************************************************
103+
* Private Functions
104+
****************************************************************************/
105+
106+
static void mps_timer_init(void)
107+
{
108+
static const uint32_t timerbase[] =
109+
{
110+
0x40000000, 0x40001000
111+
};
112+
113+
static const int timerirq[] =
114+
{
115+
8, 9
116+
};
117+
118+
static const int timer_irq_prio[] =
119+
{
120+
0x60, 0x70
121+
};
122+
123+
mps2_an500_timer_t *t = &g_timer;
124+
125+
t->reload = MPS2_ADDR2REG_PTR(timerbase[0], MPS_TIMER_RELOAD_OFFSET);
126+
t->ctrl = MPS2_ADDR2REG_PTR(timerbase[0], MPS_TIMER_CTRL_OFFSET);
127+
t->clear = MPS2_ADDR2REG_PTR(timerbase[0], MPS_TIMER_CLEAR_OFFSET);
128+
t->irq = MPS2_IRQ_FROMBASE(armv7m_gpio_base, timerirq[0]);
129+
130+
irq_attach(t->irq, timer_irq_handle, t);
131+
up_enable_irq(t->irq);
132+
133+
up_prioritize_irq(t->irq, timer_irq_prio[0]);
134+
135+
irq_attach(NVIC_IRQ_PENDSV, pendsv_irq_handle, NULL);
136+
}
137+
138+
static int pendsv_irq_handle(int irq, void *context, void *arg)
139+
{
140+
mps2_an500_timer_t *t = &g_timer;
141+
142+
if (t->sem != NULL)
143+
{
144+
sem_post(t->sem);
145+
}
146+
147+
up_udelay(t->after);
148+
149+
DEBUGASSERT(g_tag == 0);
150+
151+
return 0;
152+
}
153+
154+
static int timer_irq_handle(int irq, void *context, void *arg)
155+
{
156+
mps2_an500_timer_t *t = arg;
157+
*t->clear = 1;
158+
159+
up_udelay(t->before);
160+
161+
up_trigger_irq(NVIC_IRQ_PENDSV, 0);
162+
163+
return 0;
164+
}
165+
166+
static void timer_begin_test(mps2_an500_timer_t *t, uint32_t reload_us)
167+
{
168+
uint32_t reload = reload_us * 25;
169+
*t->reload = reload;
170+
t->sem = &test_sem;
171+
172+
*t->ctrl = MPS_TIMER_CTRL_IE | MPS_TIMER_CTRL_ENABLE;
173+
}
174+
175+
static void timer_end_test(mps2_an500_timer_t *t)
176+
{
177+
*t->ctrl = 0;
178+
*t->clear = 1;
179+
}
180+
181+
static void *test_irq_awaker_thread_entry(void *arg)
182+
{
183+
struct timespec ts;
184+
int cnt = 0;
185+
int ret;
186+
187+
while (cnt++ < CONFIG_TEST_IRQPRIO_LOOP_CNT)
188+
{
189+
clock_gettime(CLOCK_REALTIME, &ts);
190+
ts.tv_sec++;
191+
ret = sem_timedwait(&test_sem, &ts);
192+
if (ret != OK)
193+
{
194+
break;
195+
}
196+
197+
if (cnt % 1000 == 0)
198+
{
199+
printf("cnt %d\n", cnt);
200+
}
201+
}
202+
203+
printf("timeoutquit %d\n", cnt);
204+
return 0;
205+
}
206+
207+
static void test_irqprio(void **argv)
208+
{
209+
pid_t tid;
210+
irqstate_t flags;
211+
pthread_attr_t attr;
212+
int cnt = 0;
213+
214+
printf("init done\n");
215+
216+
printf("simple_test done\n");
217+
g_timer.before = 1;
218+
g_timer.after = 1;
219+
timer_begin_test(&g_timer, 1000);
220+
221+
pthread_attr_init(&attr);
222+
223+
attr.priority = 255;
224+
pthread_create(&tid,
225+
&attr,
226+
test_irq_awaker_thread_entry,
227+
NULL);
228+
printf("thread init done\n");
229+
230+
while (cnt++ < CONFIG_TEST_IRQPRIO_LOOP_CNT)
231+
{
232+
flags = enter_critical_section();
233+
g_tag++;
234+
up_udelay(100);
235+
g_tag--;
236+
leave_critical_section(flags);
237+
}
238+
239+
pthread_join(tid, NULL);
240+
241+
timer_end_test(&g_timer);
242+
printf("timer end done\n");
243+
pthread_join(tid, NULL);
244+
printf("sem thread join done\n");
245+
}
246+
247+
static int setup(void **argv)
248+
{
249+
mps_timer_init();
250+
return 0;
251+
}
252+
253+
static int teardown(void **argv)
254+
{
255+
return 0;
256+
}
257+
258+
/****************************************************************************
259+
* Public Functions
260+
****************************************************************************/
261+
262+
int main(int argc, char *argv[])
263+
{
264+
const struct CMUnitTest tests[] = {
265+
cmocka_unit_test_prestate_setup_teardown(
266+
test_irqprio, setup, teardown, NULL),
267+
};
268+
269+
return cmocka_run_group_tests(tests, NULL, NULL);
270+
}

0 commit comments

Comments
 (0)