blob: 4a5eca476682140a6aaea1122feddca5486e861e [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"
brians0ab60bb2013-01-31 02:21:51 +000034#include "LPCUSB/usbapi.h"
35
Brian Silvermanf92396c2013-09-12 20:13:13 -070036#include "analog.h"
37#include "digital.h"
38#include "encoder.h"
Brian Silvermancb332812013-10-08 13:33:11 -070039#include "CAN.h"
Brian Silverman49876942013-10-11 17:50:26 -070040#include "gyro.h"
brians0ab60bb2013-01-31 02:21:51 +000041
42/*
43 * The task that handles the USB stack.
44 */
45extern void vUSBTask(void *pvParameters);
46
Brian Silvermancb332812013-10-08 13:33:11 -070047// Sets up (and connects) PLL0.
48// The CPU will be running at 100 MHz with a 12 MHz clock input when this is
49// done.
50static void setup_PLL0(void) {
51 // If PLL0 is currently connected.
52 if (SC->PLL0STAT & (1 << 25)) {
53 /* Enable PLL0, disconnected. */
54 SC->PLL0CON = 1;
55 SC->PLL0FEED = PLLFEED_FEED1;
56 SC->PLL0FEED = PLLFEED_FEED2;
57 }
58
59 // Disable PLL0, disconnected.
60 SC->PLL0CON = 0;
61 SC->PLL0FEED = PLLFEED_FEED1;
62 SC->PLL0FEED = PLLFEED_FEED2;
63
64 // Enable main OSC.
65 SC->SCS |= 1 << 5;
66 // Wait until it's ready.
67 while (!(SC->SCS & (1 << 6)));
68
69 // Select main OSC as the PLL0 clock source.
70 SC->CLKSRCSEL = 0x1;
71
72 // Set up PLL0 to output 400MHz.
73 // 12MHz * 50 / 3 * 2 = 400MHz.
74 // The input is 12MHz (from the crystal), M = 50, and N = 3.
75 SC->PLL0CFG = 0x20031;
76 SC->PLL0FEED = PLLFEED_FEED1;
77 SC->PLL0FEED = PLLFEED_FEED2;
78
79 // Enable PLL0, disconnected.
80 SC->PLL0CON = 1;
81 SC->PLL0FEED = PLLFEED_FEED1;
82 SC->PLL0FEED = PLLFEED_FEED2;
83
84 // Set clock divider to dividing by 4 to give a final frequency of 100MHz.
85 SC->CCLKCFG = 0x03;
86
87 // Configure flash accelerator to use 5 CPU clocks like the datasheet says for
88 // a 100MHz clock.
89 SC->FLASHCFG = 0x403a;
90
91 // Wait until PLL0 is locked.
92 while (((SC->PLL0STAT & (1 << 26)) == 0));
93
94 // Enable PLL0 and connect.
95 SC->PLL0CON = 3;
96 SC->PLL0FEED = PLLFEED_FEED1;
97 SC->PLL0FEED = PLLFEED_FEED2;
98
99 // Wait until PLL0 is connected.
100 while (((SC->PLL0STAT & (1 << 25)) == 0));
101}
102
103// Configures PLL1 as the clock for USB.
104static void setup_PLL1(void) {
105 // If PLL1 is currently connected.
106 if (SC->PLL1STAT & (1 << 9)) {
107 // Enable PLL1, disconnected.
108 SC->PLL1CON = 1;
109 SC->PLL1FEED = PLLFEED_FEED1;
110 SC->PLL1FEED = PLLFEED_FEED2;
111 }
112
113 // Disable PLL1, disconnected.
114 SC->PLL1CON = 0;
115 SC->PLL1FEED = PLLFEED_FEED1;
116 SC->PLL1FEED = PLLFEED_FEED2;
117
118 // Set up PLL1 to produce the required 48MHz from the crystal.
119 // USBCLK = 12MHz * 4 = 48MHz.
120 // FCCO = USBCLK * 2 * 3 = 288MHz.
121 // The input is 12MHz, M = 4, and P = 3.
122 SC->PLL1CFG = 0x23;
123 SC->PLL1FEED = PLLFEED_FEED1;
124 SC->PLL1FEED = PLLFEED_FEED2;
125
126 /* Enable PLL1, disconnected. */
127 SC->PLL1CON = 1;
128 SC->PLL1FEED = PLLFEED_FEED1;
129 SC->PLL1FEED = PLLFEED_FEED2;
130
131 // Wait until PLL1 is locked.
132 while (((SC->PLL1STAT & (1 << 10)) == 0));
133
134 /* Enable PLL1 and connect it. */
135 SC->PLL1CON = 3;
136 SC->PLL1FEED = PLLFEED_FEED1;
137 SC->PLL1FEED = PLLFEED_FEED2;
138
139 // Wait until PLL1 is connected.
140 while (((SC->PLL1STAT & (1 << 9)) == 0));
141}
142
Brian Silverman49876942013-10-11 17:50:26 -0700143// Setup the peripherals.
144static void setup_hardware(void) {
Brian Silvermancb332812013-10-08 13:33:11 -0700145 // Setup GPIO power.
146 SC->PCONP = PCONP_PCGPIO;
brians0ab60bb2013-01-31 02:21:51 +0000147
Brian Silvermancb332812013-10-08 13:33:11 -0700148 // Disable TPIU.
149 PINCON->PINSEL10 = 0;
brians0ab60bb2013-01-31 02:21:51 +0000150
Brian Silvermancb332812013-10-08 13:33:11 -0700151 setup_PLL0();
brians0ab60bb2013-01-31 02:21:51 +0000152
Brian Silvermancb332812013-10-08 13:33:11 -0700153 setup_PLL1();
brians0ab60bb2013-01-31 02:21:51 +0000154
Brian Silvermancb332812013-10-08 13:33:11 -0700155 // Set CAN to run at CCLK/6, which should have it running about 1 Mbit (1.042)
156 SC->PCLKSEL0 = 0xff555555;
brians0ab60bb2013-01-31 02:21:51 +0000157
Brian Silvermancb332812013-10-08 13:33:11 -0700158 /* Configure the LEDs. */
159 vParTestInitialise();
brians0ab60bb2013-01-31 02:21:51 +0000160}
Brian Silverman49876942013-10-11 17:50:26 -0700161
162int main(void) {
163 setup_hardware();
164
165 /* Create the USB task. */
166 xTaskCreate(vUSBTask, (signed char *) "USB",
167 configMINIMAL_STACK_SIZE + 1020, (void *) NULL,
168 tskIDLE_PRIORITY + 3, NULL);
169
170 digital_init();
171
172 analog_init();
173
174 encoder_init();
175
176 gyro_init();
177
178 // Enable USB. The PC has probably disconnected it now.
179 USBHwAllowConnect();
180
181 initCAN();
182
183 // Start the scheduler.
184 vTaskStartScheduler();
185
186 /* Will only get here if there was insufficient memory to create the idle
187 task. The idle task is created within vTaskStartScheduler(). */
188 for (;;) {}
189}
brians0ab60bb2013-01-31 02:21:51 +0000190
191void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed char *pcTaskName)
192{
Brian Silvermancb332812013-10-08 13:33:11 -0700193 /* This function will get called if a task overflows its stack. */
brians0ab60bb2013-01-31 02:21:51 +0000194
Brian Silvermancb332812013-10-08 13:33:11 -0700195 (void) pxTask;
196 (void) pcTaskName;
brians0ab60bb2013-01-31 02:21:51 +0000197
Brian Silvermancb332812013-10-08 13:33:11 -0700198 for (;;);
brians0ab60bb2013-01-31 02:21:51 +0000199}
brians0ab60bb2013-01-31 02:21:51 +0000200
Brian Silvermancb332812013-10-08 13:33:11 -0700201// This is what portCONFIGURE_TIMER_FOR_RUN_TIME_STATS in FreeRTOSConfig.h
202// actually calls.
Brian Silverman49876942013-10-11 17:50:26 -0700203// It sets up timer 0 to use for timing.
204void vConfigureTimerForRunTimeStats(void) {
Brian Silvermancb332812013-10-08 13:33:11 -0700205 const unsigned long TCR_COUNT_RESET = 2, CTCR_CTM_TIMER = 0x00, TCR_COUNT_ENABLE = 0x01;
brians0ab60bb2013-01-31 02:21:51 +0000206
Brian Silvermancb332812013-10-08 13:33:11 -0700207 /* This function configures a timer that is used as the time base when
208 collecting run time statistical information - basically the percentage
209 of CPU time that each task is utilising. It is called automatically when
210 the scheduler is started (assuming configGENERATE_RUN_TIME_STATS is set
211 to 1). */
brians0ab60bb2013-01-31 02:21:51 +0000212
Brian Silvermancb332812013-10-08 13:33:11 -0700213 /* Power up and feed the timer. */
214 SC->PCONP |= 0x02UL;
215 SC->PCLKSEL0 = (SC->PCLKSEL0 & (~(0x3 << 2))) | (0x01 << 2);
brians0ab60bb2013-01-31 02:21:51 +0000216
Brian Silvermancb332812013-10-08 13:33:11 -0700217 /* Reset Timer 0 */
218 TIM0->TCR = TCR_COUNT_RESET;
brians0ab60bb2013-01-31 02:21:51 +0000219
Brian Silvermancb332812013-10-08 13:33:11 -0700220 /* Just count up. */
221 TIM0->CTCR = CTCR_CTM_TIMER;
brians0ab60bb2013-01-31 02:21:51 +0000222
Brian Silvermancb332812013-10-08 13:33:11 -0700223 /* Prescale to a frequency that is good enough to get a decent resolution,
224 but not too fast so as to overflow all the time. */
225 TIM0->PR = (configCPU_CLOCK_HZ / 10000UL) - 1UL;
brians0ab60bb2013-01-31 02:21:51 +0000226
Brian Silvermancb332812013-10-08 13:33:11 -0700227 /* Start the counter. */
228 TIM0->TCR = TCR_COUNT_ENABLE;
brians0ab60bb2013-01-31 02:21:51 +0000229}