-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.c
233 lines (183 loc) · 5.85 KB
/
main.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
/*
FabOS example implementation
(c) 2008-2013 Fabian Huslik
This is free software according GNU GENERAL PUBLIC LICENSE Version 3.
Please change this file to your needs.
*/
#include "OS/FabOS.h"
// ********* Task definitions
OS_DeclareTask(Task1,200);
OS_DeclareTask(Task2,200);
OS_DeclareTask(Task3,200);
OS_DeclareQueue(DemoQ,10,4);
// ********* Prototypes
void CPU_init(void);
// ********* THE main()
int main(void)
{
CPU_init();
#if OS_DO_TESTSUITE == 1
OS_TestSuite(); // call automated tests of OS. may be removed in production code.
#endif
OS_CreateTask(Task1, 0); // ID 0 with higest priority
OS_CreateTask(Task2, 1);
OS_CreateTask(Task3, 2); // ID 2 with lowest prio, but higher than Idle
OS_CreateAlarm(0, OSALM1);
OS_CreateAlarm(1, OSALM2);
OS_CreateAlarm(2, OSALM3);
OS_StartExecution() ;
while(1)
{
// THIS IS the idle task (ID 3 in this case) which will be preemted by all other tasks.
// NO OS_Wait.. functions are allowed here!!!
// TODO add your code here
asm("nop"); //at least one instruction is required for debugging!
}
}
// ********* Code to be executed inside Timer ISR used for the OS, defined in FabOS_config.h
void OS_CustomISRCode(void)
{
// TODO add your Timer ISR here
#if defined (__AVR_ATmega32__)
TCNT1 =0; // reset the timer on ISR to have correct timing
#elif defined (__AVR_ATxmega32A4__)
TCC1.CNT=0; // reset the timer on ISR to have correct timing
#elif defined (__AVR_ATmega644P__)
TCNT1 = 0;
#elif defined (__AVR_ATmega168__)
TCNT1 = 0;
#elif defined (__AVR_ATmega2560__)
TCNT1 = 0;
#else
#error MCU not yet supported, you must configure a timer yourself.
#endif
}
// ********* Controller initialisation
void CPU_init(void)
{
// init OS timer and interrupt
//Timer0 Initializations for ATMEGA16
//TCCR0 |= 5; // Enable TMR0, set clock source to CLKIO/1024. Interrupts @ 32.768ms intervals @ 8 MHz. This means tasks can execute at least 130,000 instructions before being preempted.
//TIMSK |= 1 ; // Interrupt on TMR0 Overflow.
#if defined (__AVR_ATmega32__)
TCCR1A = 0b00000000;
TCCR1B = 0b00000011; //250kHZ timer ck
OCR1A = 250; //interrupt every 1ms
TIMSK |= 1<<OCIE1A; // Output Compare Interrupt ON
#elif defined (__AVR_ATmega644P__)
// init cyclic ISR
TCCR1A = 0b00000000;
TCCR1B = 0b00000010; //1250 kHZ timer ck
OCR1A = 12500; //interrupt every 10ms at 10MHz
TIMSK1 |= 1<<OCIE1A;
#elif defined (__AVR_ATmega168__)
// init cyclic ISR
TCCR1A = 0b00000000;
TCCR1B = 0b00000010; //1250 kHZ timer ck
OCR1A = 12500; //interrupt every 10ms at 10MHz
TIMSK1 |= 1<<OCIE1A;
#elif defined (__AVR_ATmega2560__)
// init cyclic ISR
TCCR1A = 0b00000000;
TCCR1B = 0b00000010; //1250 kHZ timer ck
OCR1A = 12500; //interrupt every 10ms at 10MHz
TIMSK1 |= 1<<OCIE1A;
#elif defined (__AVR_ATxmega32A4__)
// set ck = 32MHz,
// PLL (128 MHz) -> peripheral x4
// Presc. B (64MHz) -> peripheral x2
// Presc. C (32MHz) -> CPU
#if USEEXTERNALOSC == 1
OSC.XOSCCTRL = OSC_FRQRANGE_12TO16_gc | OSC_XOSCSEL_XTAL_16KCLK_gc;
OSC.CTRL |= OSC_XOSCEN_bm; // enable XTAL
// ! PLL MUST run at least 10MHz
OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | 8; // configure pll x 8; // fixme check if correct!!
while (!(OSC.STATUS & OSC_XOSCRDY_bm))
{
asm("nop"); // wait for the bit to become set
}
OSC.CTRL |= OSC_PLLEN_bm; // enable PLL
CCP = CCP_IOREG_gc; // unlock
CLK.PSCTRL = CLK_PSADIV_1_gc|CLK_PSBCDIV_2_2_gc;
while (!(OSC.STATUS & OSC_PLLRDY_bm))
{
asm("nop"); // wait for the bit to become set
}
#else
CCP = CCP_IOREG_gc; // unlock
OSC_XOSCFAIL = OSC_XOSCFDEN_bm; // enable NMI for oscillator failure.
// Desired Clock : 16MHz,
// PLL (16 MHz) -> peripheral x1
// Presc. B (16MHz) -> peripheral x1
// Presc. C (16MHz) -> CPU
//OSC_XOSCCTRL = 0;
OSC_CTRL = OSC_RC2MEN_bm; // enable XTAL
OSC_PLLCTRL = OSC_PLLSRC_RC2M_gc | 8; // configure pll x 8; (min 10MHz!)
while (!(OSC_STATUS & OSC_RC2MRDY_bm))
{
asm("nop"); // wait for the bit to become set
}
OSC_DFLLCTRL = OSC_RC2MCREF_bm; // enable auto calib.
DFLLRC2M_CTRL = DFLL_ENABLE_bm;
OSC_CTRL |= OSC_PLLEN_bm; // enable PLL
CCP = CCP_IOREG_gc; // unlock
CLK_PSCTRL = CLK_PSADIV_1_gc|CLK_PSBCDIV_1_1_gc;
while (!(OSC_STATUS & OSC_PLLRDY_bm))
{
asm("nop"); // wait for the bit to become set
}
#endif
CCP = CCP_IOREG_gc; // unlock
CLK.CTRL = CLK_SCLKSEL_PLL_gc; // select PLL to run with
// setup Timer for OS
TCC1.CTRLA = TC_CLKSEL_DIV1_gc; // select clk/1 for clock source
TCC1.CTRLB = TC0_CCAEN_bm;
TCC1.CTRLC = 0;
TCC1.CTRLD = 0;
TCC1.CTRLE = 0;
TCC1.INTCTRLA = 0;
TCC1.INTCTRLB = TC_CCAINTLVL_HI_gc; // enable compare match A as HIGH level interrupt.
TCC1.CCA = 32000;// compare at 32000 gives 1ms clock
//Enable Interrupts in INT CTRL
PMIC.CTRL = PMIC_HILVLEN_bm|PMIC_MEDLVLEN_bm|PMIC_LOLVLEN_bm;
#else
#error MCU not yet supported, you must do the CPU init yourself.
#endif
// *** NO global interrupts enabled at this point!!!
}
#if OS_USEEXTCHECKS == 1
void OS_ErrorHook(uint8_t ErrNo)
{
static uint8_t dummy =0;
switch(ErrNo)
{
case 2:
// OS_WaitEvent: waiting in idle is not allowed
break;
case 4:
// OS_WaitAlarm: waiting in idle is not allowed
break;
case 5:
// OS_MutexGet: invalid Mutex number
break;
case 6:
// OS_MutexRelease: invalid Mutex number
break;
case 7:
// OS_Alarm misconfiguration / ID bigger than array size
break;
case 8:
// OS_WaitAlarm: Alarm was not active
break;
case 9:
// OS_WaitAlarm: Alarm is not assigned to the task (critical!)
break;
default:
break;
}
dummy = ErrNo; // dummy code
#if OS_DO_TESTSUITE == 1
asm("break"); // for automated tests of OS. may be removed in production code.
#endif
}
#endif