blob: 3ac21c8da79445d81fb23cba526920c91c53a21a [file] [log] [blame]
/*
FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
***NOTE*** The exception to the GPL is included to allow you to distribute
a combined work that includes FreeRTOS without being obliged to provide the
source code for proprietary components outside of the FreeRTOS kernel.
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details. You should have received a copy of the GNU General Public
License and the FreeRTOS license exception along with FreeRTOS; if not it
can be viewed here: http://www.freertos.org/a00114.html and also obtained
by writing to Richard Barry, contact details for whom are available on the
FreeRTOS WEB site.
*/
/* Standard includes. */
#include "stdio.h"
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "queue.h"
#include "task.h"
/* Demo app includes. */
#include "flash.h"
#include "partest.h"
#include "LPCUSB/usbapi.h"
#include "analog.h"
#include "digital.h"
#include "encoder.h"
#include "CAN.h"
#include "gyro.h"
extern void usb_init(void);
// Sets up (and connects) PLL0.
// The CPU will be running at 100 MHz with a 12 MHz clock input when this is
// done.
static void setup_PLL0(void) {
// If PLL0 is currently connected.
if (SC->PLL0STAT & (1 << 25)) {
/* Enable PLL0, disconnected. */
SC->PLL0CON = 1;
SC->PLL0FEED = PLLFEED_FEED1;
SC->PLL0FEED = PLLFEED_FEED2;
}
// Disable PLL0, disconnected.
SC->PLL0CON = 0;
SC->PLL0FEED = PLLFEED_FEED1;
SC->PLL0FEED = PLLFEED_FEED2;
// Enable main OSC.
SC->SCS |= 1 << 5;
// Wait until it's ready.
while (!(SC->SCS & (1 << 6)));
// Select main OSC as the PLL0 clock source.
SC->CLKSRCSEL = 0x1;
// Set up PLL0 to output 400MHz.
// 12MHz * 50 / 3 * 2 = 400MHz.
// The input is 12MHz (from the crystal), M = 50, and N = 3.
SC->PLL0CFG = 0x20031;
SC->PLL0FEED = PLLFEED_FEED1;
SC->PLL0FEED = PLLFEED_FEED2;
// Enable PLL0, disconnected.
SC->PLL0CON = 1;
SC->PLL0FEED = PLLFEED_FEED1;
SC->PLL0FEED = PLLFEED_FEED2;
// Set clock divider to dividing by 4 to give a final frequency of 100MHz.
SC->CCLKCFG = 0x03;
// Configure flash accelerator to use 5 CPU clocks like the datasheet says for
// a 100MHz clock.
SC->FLASHCFG = 0x403a;
// Wait until PLL0 is locked.
while (((SC->PLL0STAT & (1 << 26)) == 0));
// Enable PLL0 and connect.
SC->PLL0CON = 3;
SC->PLL0FEED = PLLFEED_FEED1;
SC->PLL0FEED = PLLFEED_FEED2;
// Wait until PLL0 is connected.
while (((SC->PLL0STAT & (1 << 25)) == 0));
}
// Configures PLL1 as the clock for USB.
static void setup_PLL1(void) {
// If PLL1 is currently connected.
if (SC->PLL1STAT & (1 << 9)) {
// Enable PLL1, disconnected.
SC->PLL1CON = 1;
SC->PLL1FEED = PLLFEED_FEED1;
SC->PLL1FEED = PLLFEED_FEED2;
}
// Disable PLL1, disconnected.
SC->PLL1CON = 0;
SC->PLL1FEED = PLLFEED_FEED1;
SC->PLL1FEED = PLLFEED_FEED2;
// Set up PLL1 to produce the required 48MHz from the crystal.
// USBCLK = 12MHz * 4 = 48MHz.
// FCCO = USBCLK * 2 * 3 = 288MHz.
// The input is 12MHz, M = 4, and P = 3.
SC->PLL1CFG = 0x23;
SC->PLL1FEED = PLLFEED_FEED1;
SC->PLL1FEED = PLLFEED_FEED2;
/* Enable PLL1, disconnected. */
SC->PLL1CON = 1;
SC->PLL1FEED = PLLFEED_FEED1;
SC->PLL1FEED = PLLFEED_FEED2;
// Wait until PLL1 is locked.
while (((SC->PLL1STAT & (1 << 10)) == 0));
/* Enable PLL1 and connect it. */
SC->PLL1CON = 3;
SC->PLL1FEED = PLLFEED_FEED1;
SC->PLL1FEED = PLLFEED_FEED2;
// Wait until PLL1 is connected.
while (((SC->PLL1STAT & (1 << 9)) == 0));
}
// Setup the peripherals.
static void setup_hardware(void) {
// Setup GPIO power.
SC->PCONP = PCONP_PCGPIO;
// Disable TPIU.
PINCON->PINSEL10 = 0;
setup_PLL0();
setup_PLL1();
// Set CAN to run at CCLK/6, which should have it running about 1 Mbit (1.042)
SC->PCLKSEL0 = 0xff555555;
/* Configure the LEDs. */
vParTestInitialise();
}
int main(void) {
setup_hardware();
digital_init();
analog_init();
encoder_init();
gyro_init();
initCAN();
usb_init();
// Start the scheduler.
vTaskStartScheduler();
/* Will only get here if there was insufficient memory to create the idle
task. The idle task is created within vTaskStartScheduler(). */
for (;;) {}
}
void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed char *pcTaskName)
{
/* This function will get called if a task overflows its stack. */
(void) pxTask;
(void) pcTaskName;
for (;;);
}
// This is what portCONFIGURE_TIMER_FOR_RUN_TIME_STATS in FreeRTOSConfig.h
// actually calls.
// It sets up timer 0 to use for timing.
void vConfigureTimerForRunTimeStats(void) {
const unsigned long TCR_COUNT_RESET = 2, CTCR_CTM_TIMER = 0x00, TCR_COUNT_ENABLE = 0x01;
/* This function configures a timer that is used as the time base when
collecting run time statistical information - basically the percentage
of CPU time that each task is utilising. It is called automatically when
the scheduler is started (assuming configGENERATE_RUN_TIME_STATS is set
to 1). */
/* Power up and feed the timer. */
SC->PCONP |= 0x02UL;
SC->PCLKSEL0 = (SC->PCLKSEL0 & (~(0x3 << 2))) | (0x01 << 2);
/* Reset Timer 0 */
TIM0->TCR = TCR_COUNT_RESET;
/* Just count up. */
TIM0->CTCR = CTCR_CTM_TIMER;
/* Prescale to a frequency that is good enough to get a decent resolution,
but not too fast so as to overflow all the time. */
TIM0->PR = (configCPU_CLOCK_HZ / 10000UL) - 1UL;
/* Start the counter. */
TIM0->TCR = TCR_COUNT_ENABLE;
}