blob: 11191a45466ab82a9ec67286338a87a64ec088ba [file] [log] [blame]
brians0ab60bb2013-01-31 02:21:51 +00001/*
2 FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
3
4 This file is part of the FreeRTOS distribution.
5
6 FreeRTOS is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License (version 2) as published by the
8 Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
9 ***NOTE*** The exception to the GPL is included to allow you to distribute
10 a combined work that includes FreeRTOS without being obliged to provide the
11 source code for proprietary components outside of the FreeRTOS kernel.
12 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 more details. You should have received a copy of the GNU General Public
16 License and the FreeRTOS license exception along with FreeRTOS; if not it
17 can be viewed here: http://www.freertos.org/a00114.html and also obtained
18 by writing to Richard Barry, contact details for whom are available on the
19 FreeRTOS WEB site.
20
21*/
22
23/* Standard includes. */
24#include "stdio.h"
25
26/* Scheduler includes. */
27#include "FreeRTOS.h"
28#include "queue.h"
29#include "task.h"
30
31/* Demo app includes. */
32#include "flash.h"
33#include "partest.h"
34#include "analog.h"
35#include "spi.h"
36#include "LPCUSB/usbapi.h"
37
38/*-----------------------------------------------------------*/
39
40/* The time between cycles of the 'check' functionality (defined within the
41tick hook. */
42#define mainCHECK_DELAY ((portTickType) 5000 / portTICK_RATE_MS)
43
44/* Task priorities. */
45#define mainQUEUE_POLL_PRIORITY (tskIDLE_PRIORITY + 2)
46#define mainSEM_TEST_PRIORITY (tskIDLE_PRIORITY + 1)
47#define mainBLOCK_Q_PRIORITY (tskIDLE_PRIORITY + 2)
48#define mainUIP_TASK_PRIORITY (tskIDLE_PRIORITY + 3)
49#define mainINTEGER_TASK_PRIORITY (tskIDLE_PRIORITY)
50#define mainGEN_QUEUE_TASK_PRIORITY (tskIDLE_PRIORITY)
51#define mainFLASH_TASK_PRIORITY (tskIDLE_PRIORITY + 2)
52
53/* The WEB server has a larger stack as it utilises stack hungry string
54handling library calls. */
55#define mainBASIC_WEB_STACK_SIZE (configMINIMAL_STACK_SIZE * 4)
56
57int32_t goal = 0;
58int64_t gyro_angle = 0;
59
60/*-----------------------------------------------------------*/
61
62/*
63 * Configure the hardware for the demo.
64 */
65static void prvSetupHardware(void);
66
67/*
68 * The task that handles the USB stack.
69 */
70extern void vUSBTask(void *pvParameters);
71
72extern int VCOM_getchar(void);
73
74int VCOM_putchar(int c);
75
76inline int32_t encoder()
77{
78 return (int32_t)QEI->QEIPOS;
79}
80
81static portTASK_FUNCTION(vPrintPeriodic, pvParameters)
82{
83 portTickType xLastFlashTime;
84
85 /* We need to initialise xLastFlashTime prior to the first call to
86 vTaskDelayUntil(). */
87 xLastFlashTime = xTaskGetTickCount();
88
89 analog_init();
90
91 encoder_init();
92
93 // Wait 100 ms for it to boot.
94 vTaskDelayUntil(&xLastFlashTime, 100 / portTICK_RATE_MS);
95 spi_init();
96
97 // Enable USB. The PC has probably disconnected it now.
98 USBHwAllowConnect();
99
100 // TODO(aschuh): Write this into a gyro calibration function, and check all the outputs.
101 vTaskDelayUntil(&xLastFlashTime, 50 / portTICK_RATE_MS);
102 enable_gyro_csel();
103 printf("SPI Gyro Second Response 0x%x %x\n", transfer_spi_bytes(0x2000), transfer_spi_bytes(0x0000));
104 disable_gyro_csel();
105
106 vTaskDelayUntil(&xLastFlashTime, 50 / portTICK_RATE_MS);
107 enable_gyro_csel();
108 printf("SPI Gyro Third Response 0x%x %x\n", transfer_spi_bytes(0x2000), transfer_spi_bytes(0x0000));
109 disable_gyro_csel();
110
111 vTaskDelayUntil(&xLastFlashTime, 10 / portTICK_RATE_MS);
112 enable_gyro_csel();
113 printf("SPI Gyro Fourth Response 0x%x %x\n", transfer_spi_bytes(0x2000), transfer_spi_bytes(0x0000));
114 disable_gyro_csel();
115 const int hz = 200;
116 const int flash_hz = 10;
117 const int startup_cycles = hz * 2;
118 const int zeroing_cycles = hz * 6;
119 int32_t zero_bias = 0;
120 int32_t startup_cycles_left = startup_cycles;
121 int32_t zeroing_cycles_left = zeroing_cycles;
122 int32_t full_units_offset = 0;
123 int32_t remainder_offset = 0;
124 int32_t remainder_sum = 0;
125 int32_t led_flash = 0;
126 vParTestSetLED(0, 0);
127
128 for (;;) {
129 led_flash ++;
130 if (led_flash < hz / flash_hz / 2) {
131 vParTestSetLED(1, 0);
132 } else {
133 vParTestSetLED(1, 1);
134 }
135 if (led_flash >= hz / flash_hz) {
136 led_flash = 0;
137 }
138 /* Delay for half the flash period then turn the LED on. */
139 vTaskDelayUntil(&xLastFlashTime, 1000 / hz / portTICK_RATE_MS);
140 enable_gyro_csel();
141 uint16_t high_value = transfer_spi_bytes(0x2000);
142 uint16_t low_value = transfer_spi_bytes(0x0000);
143 disable_gyro_csel();
144 int16_t gyro_value = -((int16_t)((((uint32_t)high_value << 16) | (uint32_t)low_value) >> 10));
145
146 if (startup_cycles_left) {
147 vParTestSetLED(2, 0);
148 --startup_cycles_left;
149 } else if (zeroing_cycles_left) {
150 vParTestSetLED(2, 1);
151 //printf("Zeroing ");
152 --zeroing_cycles_left;
153 zero_bias -= gyro_value;
154 if (zeroing_cycles_left == 0) {
155 // Do all the nice math
156 full_units_offset = zero_bias / zeroing_cycles;
157 remainder_offset = zero_bias % zeroing_cycles;
158 if (remainder_offset < 0) {
159 remainder_offset += zeroing_cycles;
160 --full_units_offset;
161 }
162 }
163 } else {
164 vParTestSetLED(2, 0);
165 int64_t new_angle = gyro_angle + gyro_value + full_units_offset;
166 if (remainder_sum >= zeroing_cycles) {
167 remainder_sum -= zeroing_cycles;
168 new_angle += 1;
169 }
170 NVIC_DisableIRQ(USB_IRQn);
171 gyro_angle = new_angle;
172 NVIC_EnableIRQ(USB_IRQn);
173 remainder_sum += remainder_offset;
174 }
175 //printf("Angle %d Rate %d\n", (int)(gyro_angle / 16), (int)(gyro_value + full_units_offset));
176
177 //printf("time: %d analog %d encoder %d goal %d\n", (int)i, (int)analog(5), (int)encoder(), (int)goal);
178
179 //printf("time: %d encoder %d goal %d\n", (int)i, (int)encoder(), (int)goal);
180 /*
181 for(i = 0; i < 4; i++){
182 printf("analog(%d) => %d\n",i,analog(i));
183 }
184 for(i = 1; i < 13; i++){
185 printf("digital(%d) => %d\n",i,digital(i));
186 }
187 for(i = 0; i < 4; i++){
188 printf("dip(%d) => %d\n",i,dip(i));
189 }
190 for(i = 0; i < 4; i++){
191 printf("encoder(%d) => %d\n",i,encoder_bits(i));
192 }
193 for(i = 0; i < 4; i++){
194 printf("encoder_val(%d) => %d\n",i,(int)encoder_val(i));
195 }*/
196 }
197}
198
199#include "CAN.h"
200
201
202
203void motor(int32_t speed)
204{
205 if (speed > 2047) speed = 2047;
206 if (speed < -2047) speed = -2047;
207 return;
208 if (speed > 0) {
209 MCPWM->MCMAT1 = 2047 - speed;
210 MCPWM->MCMAT0 = 2048;
211 } else {
212 MCPWM->MCMAT1 = 2048;
213 MCPWM->MCMAT0 = speed + 2047;
214 }
215}
216
217
218
219/*-----------------------------------------------------------*/
220
221int main(void)
222{
223 // Configure the hardware
224 prvSetupHardware();
225
226 /* Start the standard demo tasks. These are just here to exercise the
227 kernel port and provide examples of how the FreeRTOS API can be used. */
228 //vStartLEDFlashTasks(mainFLASH_TASK_PRIORITY);
229
230 /* Create the USB task. */
231 xTaskCreate(vUSBTask, (signed char *) "USB", configMINIMAL_STACK_SIZE + 1020, (void *) NULL, tskIDLE_PRIORITY + 3, NULL);
232
233 xTaskCreate(vPrintPeriodic, (signed char *) "PRINTx", configMINIMAL_STACK_SIZE + 100, NULL, tskIDLE_PRIORITY + 2, NULL);
234
235 initCAN();
236
237 // Start the scheduler.
238 vTaskStartScheduler();
239
240 /* Will only get here if there was insufficient memory to create the idle
241 task. The idle task is created within vTaskStartScheduler(). */
242 for (;;);
243}
244/*-----------------------------------------------------------*/
245
246
247void vApplicationTickHook(void)
248{
249 static unsigned long ulTicksSinceLastDisplay = 0;
250
251 /* Called from every tick interrupt as described in the comments at the top
252 of this file.
253
254 Have enough ticks passed to make it time to perform our health status
255 check again? */
256
257 ulTicksSinceLastDisplay++;
258
259 if (ulTicksSinceLastDisplay >= mainCHECK_DELAY) {
260 /* Reset the counter so these checks run again in mainCHECK_DELAY
261 ticks time. */
262 ulTicksSinceLastDisplay = 0;
263 }
264}
265/*-----------------------------------------------------------*/
266
267void prvSetupHardware(void)
268{
269 // Setup the peripherals.
270 // The CPU will be running at 100 MHz with a 12 MHz clock input.
271
272 // Setup GPIO power.
273 SC->PCONP = PCONP_PCGPIO;
274 // Disable TPIU.
275 PINCON->PINSEL10 = 0;
276
277 // Setup PLL0 so that the CPU runs at 100 MHz.
278 if (SC->PLL0STAT & (1 << 25)) {
279 /* Enable PLL, disconnected. */
280 SC->PLL0CON = 1;
281 SC->PLL0FEED = PLLFEED_FEED1;
282 SC->PLL0FEED = PLLFEED_FEED2;
283 }
284
285 // Disable PLL, disconnected.
286 SC->PLL0CON = 0;
287 SC->PLL0FEED = PLLFEED_FEED1;
288 SC->PLL0FEED = PLLFEED_FEED2;
289
290 // Enable main OSC and wait until it's ready.
291 SC->SCS |= 0x20;
292 while (!(SC->SCS & 0x40));
293
294 // select main OSC, 12MHz, as the PLL clock source.
295 SC->CLKSRCSEL = 0x1;
296
297 SC->PLL0CFG = 0x20031;
298 SC->PLL0FEED = PLLFEED_FEED1;
299 SC->PLL0FEED = PLLFEED_FEED2;
300
301 // Enable PLL, disconnected.
302 SC->PLL0CON = 1;
303 SC->PLL0FEED = PLLFEED_FEED1;
304 SC->PLL0FEED = PLLFEED_FEED2;
305
306 // Set clock divider.
307 SC->CCLKCFG = 0x03;
308
309 // Configure flash accelerator.
310 SC->FLASHCFG = 0x403a;
311
312 // Check lock bit status.
313 while (((SC->PLL0STAT & (1 << 26)) == 0));
314
315 // Enable and connect.
316 SC->PLL0CON = 3;
317 SC->PLL0FEED = PLLFEED_FEED1;
318 SC->PLL0FEED = PLLFEED_FEED2;
319
320 while (((SC->PLL0STAT & (1 << 25)) == 0));
321
322 // Configure the clock for the USB.
323 if (SC->PLL1STAT & (1 << 9)) {
324 // Enable PLL, disconnected.
325 SC->PLL1CON = 1;
326 SC->PLL1FEED = PLLFEED_FEED1;
327 SC->PLL1FEED = PLLFEED_FEED2;
328 }
329
330 // Disable PLL, disconnected.
331 SC->PLL1CON = 0;
332 SC->PLL1FEED = PLLFEED_FEED1;
333 SC->PLL1FEED = PLLFEED_FEED2;
334
335 SC->PLL1CFG = 0x23;
336 SC->PLL1FEED = PLLFEED_FEED1;
337 SC->PLL1FEED = PLLFEED_FEED2;
338
339 /* Enable PLL, disconnected. */
340 SC->PLL1CON = 1;
341 SC->PLL1FEED = PLLFEED_FEED1;
342 SC->PLL1FEED = PLLFEED_FEED2;
343 while (((SC->PLL1STAT & (1 << 10)) == 0));
344
345 /* Enable and connect. */
346 SC->PLL1CON = 3;
347 SC->PLL1FEED = PLLFEED_FEED1;
348 SC->PLL1FEED = PLLFEED_FEED2;
349 while (((SC->PLL1STAT & (1 << 9)) == 0));
350
351 // Setup the peripheral bus to be the same as the CCLK, 100 MHz.
352 // Set CAN to run at CCLK/6, which should have it running about 1 Mbit (1.042)
353 SC->PCLKSEL0 = 0xff555555;
354
355 /* Configure the LEDs. */
356 vParTestInitialise();
357}
358/*-----------------------------------------------------------*/
359
360void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed char *pcTaskName)
361{
362 /* This function will get called if a task overflows its stack. */
363
364 (void) pxTask;
365 (void) pcTaskName;
366
367 for (;;);
368}
369/*-----------------------------------------------------------*/
370
371void vConfigureTimerForRunTimeStats(void)
372{
373 const unsigned long TCR_COUNT_RESET = 2, CTCR_CTM_TIMER = 0x00, TCR_COUNT_ENABLE = 0x01;
374
375 /* This function configures a timer that is used as the time base when
376 collecting run time statistical information - basically the percentage
377 of CPU time that each task is utilising. It is called automatically when
378 the scheduler is started (assuming configGENERATE_RUN_TIME_STATS is set
379 to 1). */
380
381 /* Power up and feed the timer. */
382 SC->PCONP |= 0x02UL;
383 SC->PCLKSEL0 = (SC->PCLKSEL0 & (~(0x3 << 2))) | (0x01 << 2);
384
385 /* Reset Timer 0 */
386 TIM0->TCR = TCR_COUNT_RESET;
387
388 /* Just count up. */
389 TIM0->CTCR = CTCR_CTM_TIMER;
390
391 /* Prescale to a frequency that is good enough to get a decent resolution,
392 but not too fast so as to overflow all the time. */
393 TIM0->PR = (configCPU_CLOCK_HZ / 10000UL) - 1UL;
394
395 /* Start the counter. */
396 TIM0->TCR = TCR_COUNT_ENABLE;
397}
398