-
Notifications
You must be signed in to change notification settings - Fork 163
/
Copy pathbsp.c
345 lines (309 loc) · 12.7 KB
/
bsp.c
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
//============================================================================
// BSP for "real-time" Example
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// This software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// NOTE:
// The GPL does NOT permit the incorporation of this code into proprietary
// programs. Please contact Quantum Leaps for commercial licensing options,
// which expressly supersede the GPL and are designed explicitly for
// closed-source distribution.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
#include "qpc.h" // QP/C real-time event framework
#include "bsp.h" // Board Support Package
#include "app.h" // Application interface
#include "TM4C123GH6PM.h" /* the device specific header (TI) */
/* add other drivers if necessary... */
Q_DEFINE_THIS_FILE // define the name of this file for assertions
/* Local-scope defines -----------------------------------------------------*/
/* test pins on GPIOF */
#define TST1_PIN (1U << 1U) /* LED Red */
#define TST3_PIN (1U << 2U) /* LED Blue */
#define TST7_PIN (1U << 3U) /* LED Green */
/* test pins on GPIOD */
#define TST4_PIN (1U << 0U)
#define TST5_PIN (1U << 1U)
#define TST6_PIN (1U << 2U)
/* Buttons on GPIOF */
#define BTN_SW1 (1U << 4)
#define BTN_SW2 (1U << 0)
//============================================================================
// Error handler and ISRs...
Q_NORETURN Q_onError(char const * const module, int_t const id) {
// NOTE: this implementation of the error handler is intended only
// for debugging and MUST be changed for deployment of the application
// (assuming that you ship your production code with assertions enabled).
Q_UNUSED_PAR(module);
Q_UNUSED_PAR(id);
QS_ASSERTION(module, id, 10000U); // report assertion to QS
#ifndef NDEBUG
// light up the user LED
GPIOF_AHB->DATA_Bits[TST1_PIN | TST3_PIN | TST7_PIN] = 0xFFU; /* all ON */
// for debugging, hang on in an endless loop...
for (;;) {
}
#endif
NVIC_SystemReset();
}
//............................................................................
// assertion failure handler for the STM32 library, including the startup code
void assert_failed(char const * const module, int_t const id); // prototype
void assert_failed(char const * const module, int_t const id) {
Q_onError(module, id);
}
//............................................................................
#ifdef __UVISION_VERSION
// dummy initialization of the ctors (not used in C)
void _init(void);
void _init(void) {
}
#endif // __UVISION_VERSION
// ISRs used in the application ============================================
void SysTick_Handler(void); // prototype
void SysTick_Handler(void) {
BSP_d1on();
QTIMEEVT_TICK_X(0U, &l_SysTick_Handler); // time events at rate 0
// Perform the debouncing of buttons. The algorithm for debouncing
// adapted from the book "Embedded Systems Dictionary" by Jack Ganssle
// and Michael Barr, page 71.
static struct {
uint32_t depressed;
uint32_t previous;
} buttons = { 0U, 0U };
/* read SW1 & SW2 */
uint32_t current = ~GPIOF_AHB->DATA_Bits[BTN_SW1 | BTN_SW2];
uint32_t tmp = buttons.depressed; // save the depressed buttons
buttons.depressed |= (buttons.previous & current); // set depressed
buttons.depressed &= (buttons.previous | current); // clear released
buttons.previous = current; // update the history
tmp ^= buttons.depressed; // changed debounced depressed
current = buttons.depressed;
if ((tmp & BTN_SW1) != 0U) { /* debounced SW1 state changed? */
if ((buttons.depressed & BTN_SW1) != 0U) { /* is SW1 depressed? */
// immutable sporadic-press event
static SporadicSpecEvt const sporadicA = {
QEVT_INITIALIZER(SPORADIC_A_SIG),
.toggles = 189U,
};
// immutable forward-press event
static SporadicSpecEvt const sporadicB = {
QEVT_INITIALIZER(SPORADIC_B_SIG),
.toggles = 89U,
};
QACTIVE_POST(AO_Sporadic2, &sporadicA.super, &l_SysTick_Handler);
QACTIVE_POST(AO_Sporadic2, &sporadicB.super, &l_SysTick_Handler);
}
else { /* the button is released */
QACTIVE_POST(AO_Periodic4, BSP_getEvtPeriodic4(0U), &l_SysTick_Handler);
QACTIVE_POST(AO_Periodic1, BSP_getEvtPeriodic1(0U), &l_SysTick_Handler);
}
}
QV_ARM_ERRATUM_838869();
BSP_d1off();
}
/* BSP functions ===========================================================*/
void BSP_init(void) {
/* enable clock for to the peripherals used by this application... */
SYSCTL->RCGCGPIO |= (1U << 5U); /* enable Run mode for GPIOF */
SYSCTL->RCGCGPIO |= (1U << 3U); /* enable Run mode for GPIOD */
SYSCTL->GPIOHBCTL |= (1U << 5U); /* enable AHB for GPIOF */
SYSCTL->GPIOHBCTL |= (1U << 3U); /* enable AHB for GPIOD */
__ISB();
__DSB();
/* configure test pins on GPIOF (digital output) */
GPIOF_AHB->DIR |= (TST1_PIN | TST3_PIN | TST7_PIN);
GPIOF_AHB->DEN |= (TST1_PIN | TST3_PIN | TST7_PIN);
/* configure button on GPIOF (digital input) */
GPIOF_AHB->DIR &= ~(BTN_SW1); /* input */
GPIOF_AHB->DEN |= (BTN_SW1); /* digital enable */
GPIOF_AHB->PUR |= (BTN_SW1); /* pull-up resistor enable */
/* configure test pins on GPIOD (digital output) */
GPIOD_AHB->DIR |= (TST4_PIN | TST5_PIN | TST6_PIN);
GPIOD_AHB->DEN |= (TST4_PIN | TST5_PIN | TST6_PIN);
/* configure switches... */
/* unlock access to the SW2 pin because it is PROTECTED */
GPIOF_AHB->LOCK = 0x4C4F434BU; /* unlock GPIOCR register for SW2 */
/* commit the write (cast const away) */
*(uint32_t volatile *)&GPIOF_AHB->CR = 0x01U;
GPIOF_AHB->DIR &= ~(BTN_SW1 | BTN_SW2); /* input */
GPIOF_AHB->DEN |= (BTN_SW1 | BTN_SW2); /* digital enable */
GPIOF_AHB->PUR |= (BTN_SW1 | BTN_SW2); /* pull-up resistor enable */
*(uint32_t volatile *)&GPIOF_AHB->CR = 0x00U;
GPIOF_AHB->LOCK = 0x0; /* lock GPIOCR register for SW2 */
}
//............................................................................
void BSP_start(void) {
// instantiate and start QP/C active objects...
Periodic1_ctor();
static QEvtPtr periodic1QSto[10]; // Event queue storage
QActive_start(
AO_Periodic1, // AO pointer to start
1U, // QF-prio
periodic1QSto, // storage for the AO's queue
Q_DIM(periodic1QSto), // queue length
(void *)0, 0U, // stack storage, size (not used)
BSP_getEvtPeriodic1(0U)); // initialization param
Sporadic2_ctor();
static QEvtPtr sporadic2QSto[8]; // Event queue storage
QActive_start(
AO_Sporadic2, // AO pointer to start
2U, // QF-prio
sporadic2QSto, // storage for the AO's queue
Q_DIM(sporadic2QSto), // queue length
(void *)0, 0U, // stack storage, size (not used)
(void const *)0); // initialization param -- not used
Sporadic3_ctor();
static QEvtPtr sporadic3QSto[8]; // Event queue storage
QActive_start(
AO_Sporadic3, // AO pointer to start
3U, // QF-prio
sporadic3QSto, // storage for the AO's queue
Q_DIM(sporadic3QSto), // queue length
(void *)0, 0U, // stack storage, size (not used)
(void const *)0); // initialization param -- not used
Periodic4_ctor();
static QEvtPtr periodic4QSto[8]; // Event queue storage
QActive_start(
AO_Periodic4, // AO pointer to start
4U, // QF-prio
periodic4QSto, // storage for the AO's queue
Q_DIM(periodic4QSto), // queue length
(void *)0, 0U, // stack storage, size (not used)
BSP_getEvtPeriodic4(0U)); // initialization event
}
//............................................................................
QEvt const *BSP_getEvtPeriodic1(uint8_t num) {
// immutable PERIODIC_SPEC events for Periodic1
static PeriodicSpecEvt const periodicSpec1[] = {
{
QEVT_INITIALIZER(PERIODIC_SPEC_SIG),
.toggles = 40U,
.ticks = 5U,
},
{
QEVT_INITIALIZER(PERIODIC_SPEC_SIG),
.toggles = 30U,
.ticks = 7U,
}
};
Q_REQUIRE_ID(500, num < Q_DIM(periodicSpec1)); // must be in range
return &periodicSpec1[num].super;
}
//............................................................................
QEvt const *BSP_getEvtPeriodic4(uint8_t num) {
// immutable PERIODIC_SPEC events for Periodic4
static PeriodicSpecEvt const periodicSpec4[] = {
{
QEVT_INITIALIZER(PERIODIC_SPEC_SIG),
.toggles = 20U,
.ticks = 2U,
},
{
QEVT_INITIALIZER(PERIODIC_SPEC_SIG),
.toggles = 10U,
.ticks = 1U,
},
};
Q_REQUIRE_ID(600, num < Q_DIM(periodicSpec4)); // must be in range
return &periodicSpec4[num].super;
}
// QF callbacks ==============================================================
void QF_onStartup(void) {
/* NOTE: SystemInit() has been already called from the startup code
* but SystemCoreClock needs to be updated
*/
SystemCoreClockUpdate();
/* set up the SysTick timer to fire at BSP_TICKS_PER_SEC rate
* NOTE: do NOT call OS_CPU_SysTickInit() from uC/OS-II
*/
SysTick_Config(SystemCoreClock / BSP_TICKS_PER_SEC);
/* set priorities of ALL ISRs used in the system, see NOTE1 */
NVIC_SetPriority(SysTick_IRQn, QF_AWARE_ISR_CMSIS_PRI + 1U);
/* ... */
/* enable IRQs in the NVIC... */
/* ... */
}
/*..........................................................................*/
void BSP_d1on(void) { /* LED-Red */
GPIOF_AHB->DATA_Bits[TST1_PIN] = 0xFFU;
/* don't use the FPU in the ISR */
}
void BSP_d1off(void) {
GPIOF_AHB->DATA_Bits[TST1_PIN] = 0x00U;
}
/*..........................................................................*/
void BSP_d3on(void) { /* LED-Blue */
GPIOF_AHB->DATA_Bits[TST3_PIN] = 0xFFU;
}
void BSP_d3off(void) {
GPIOF_AHB->DATA_Bits[TST3_PIN] = 0x00U;
}
/*..........................................................................*/
void BSP_d4on(void) {
GPIOD_AHB->DATA_Bits[TST4_PIN] = 0xFFU;
}
void BSP_d4off(void) {
GPIOD_AHB->DATA_Bits[TST4_PIN] = 0x00U;
}
/*..........................................................................*/
void BSP_d5on(void) {
GPIOD_AHB->DATA_Bits[TST5_PIN] = 0xFFU;
}
void BSP_d5off(void) {
GPIOD_AHB->DATA_Bits[TST5_PIN] = 0x00U;
}
/*..........................................................................*/
void BSP_d6on(void) {
GPIOD_AHB->DATA_Bits[TST6_PIN] = 0xFFU;
}
void BSP_d6off(void) {
GPIOD_AHB->DATA_Bits[TST6_PIN] = 0x00U;
}
/*..........................................................................*/
void BSP_d7on(void) { /* LED2-Green */
GPIOF_AHB->DATA_Bits[TST7_PIN] = 0xFFU;
}
void BSP_d7off(void) {
GPIOF_AHB->DATA_Bits[TST7_PIN] = 0x00U;
}
//............................................................................
void QF_onCleanup(void) {
}
//............................................................................
void QV_onIdle(void) { // CAUTION: called with interrupts DISABLED, see NOTE0
BSP_d7on(); // LED LD2
#ifdef NDEBUG
// Put the CPU and peripherals to the low-power mode.
// you might need to customize the clock management for your application,
// see the datasheet for your particular Cortex-M MCU.
//
QV_CPU_SLEEP(); // atomically go to sleep and enable interrupts
#else
QF_INT_ENABLE(); // just enable interrupts
#endif
BSP_d7off();
}
//============================================================================
// NOTE0:
// The QV_onIdle() callback is called with interrupts disabled, because the
// determination of the idle condition might change by any interrupt posting
// an event. QV_onIdle() must internally enable interrupts, ideally
// atomically with putting the CPU to the power-saving mode.
//