libuav original
Dependents: UAVCAN UAVCAN_Subscriber
board.cpp
00001 /* 00002 * Pavel Kirienko, 2014 <pavel.kirienko@gmail.com> 00003 * Board initialization for Olimex LPC11C24 00004 */ 00005 00006 #include "board.hpp" 00007 #include <chip.h> 00008 #include <cstdlib> 00009 #include <cstring> 00010 #include <numeric> 00011 00012 static constexpr unsigned long PDRUNCFGUSEMASK = 0x0000ED00U; 00013 static constexpr unsigned long PDRUNCFGMASKTMP = 0x000000FFU; 00014 00015 const std::uint32_t OscRateIn = 12000000; ///< External crystal 00016 const std::uint32_t ExtRateIn = 0; 00017 00018 std::uint32_t SystemCoreClock = 12000000; ///< Initialized to default clock value, will be changed on init 00019 00020 namespace board 00021 { 00022 namespace 00023 { 00024 00025 constexpr unsigned TargetSystemCoreClock = 48000000; 00026 00027 constexpr unsigned ErrorLedPort = 1; 00028 constexpr unsigned ErrorLedPin = 10; 00029 00030 constexpr unsigned StatusLedPort = 1; 00031 constexpr unsigned StatusLedPin = 11; 00032 00033 struct PinMuxGroup 00034 { 00035 unsigned pin : 8; 00036 unsigned modefunc : 24; 00037 }; 00038 00039 constexpr PinMuxGroup pinmux[] = 00040 { 00041 { IOCON_PIO1_10, IOCON_FUNC0 | IOCON_MODE_INACT }, // Error LED 00042 { IOCON_PIO1_11, IOCON_FUNC0 | IOCON_MODE_INACT }, // Status LED 00043 { IOCON_PIO1_7, IOCON_FUNC1 | IOCON_HYS_EN | IOCON_MODE_PULLUP }, // UART_TXD 00044 }; 00045 00046 00047 void sysctlPowerDown(unsigned long powerdownmask) 00048 { 00049 unsigned long pdrun = LPC_SYSCTL->PDRUNCFG & PDRUNCFGMASKTMP; 00050 pdrun |= (powerdownmask & PDRUNCFGMASKTMP); 00051 LPC_SYSCTL->PDRUNCFG = pdrun | PDRUNCFGUSEMASK; 00052 } 00053 00054 void sysctlPowerUp(unsigned long powerupmask) 00055 { 00056 unsigned long pdrun = LPC_SYSCTL->PDRUNCFG & PDRUNCFGMASKTMP; 00057 pdrun &= ~(powerupmask & PDRUNCFGMASKTMP); 00058 LPC_SYSCTL->PDRUNCFG = pdrun | PDRUNCFGUSEMASK; 00059 } 00060 00061 void initWatchdog() 00062 { 00063 Chip_WWDT_Init(LPC_WWDT); // Initialize watchdog 00064 sysctlPowerUp(SYSCTL_POWERDOWN_WDTOSC_PD); // Enable watchdog oscillator 00065 Chip_Clock_SetWDTOSC(WDTLFO_OSC_0_60 , 4); // WDT osc rate 0.6 MHz / 4 = 150 kHz 00066 Chip_Clock_SetWDTClockSource(SYSCTL_WDTCLKSRC_WDTOSC , 1); // Clocking watchdog from its osc, div rate 1 00067 Chip_WWDT_SetTimeOut(LPC_WWDT, 37500); // 1 sec (hardcoded to reduce code size) 00068 Chip_WWDT_SetOption(LPC_WWDT, WWDT_WDMOD_WDRESET); // Mode: reset on timeout 00069 Chip_WWDT_Start(LPC_WWDT); // Go 00070 } 00071 00072 void initClock() 00073 { 00074 sysctlPowerUp(SYSCTL_POWERDOWN_SYSOSC_PD); // Enable system oscillator 00075 for (volatile int i = 0; i < 1000; i++) { } 00076 00077 Chip_Clock_SetSystemPLLSource(SYSCTL_PLLCLKSRC_MAINOSC ); 00078 sysctlPowerDown(SYSCTL_POWERDOWN_SYSPLL_PD); 00079 00080 /* 00081 * Setup PLL for main oscillator rate (FCLKIN = 12MHz) * 4 = 48MHz 00082 * MSEL = 3 (this is pre-decremented), PSEL = 1 (for P = 2) 00083 * FCLKOUT = FCLKIN * (MSEL + 1) = 12MHz * 4 = 48MHz 00084 * FCCO = FCLKOUT * 2 * P = 48MHz * 2 * 2 = 192MHz (within FCCO range) 00085 */ 00086 Chip_Clock_SetupSystemPLL(3, 1); 00087 sysctlPowerUp(SYSCTL_POWERDOWN_SYSPLL_PD); 00088 while (!Chip_Clock_IsSystemPLLLocked()) { } 00089 00090 Chip_Clock_SetSysClockDiv(1); 00091 00092 Chip_FMC_SetFLASHAccess(FLASHTIM_50MHZ_CPU ); 00093 00094 Chip_Clock_SetMainClockSource(SYSCTL_MAINCLKSRC_PLLOUT ); 00095 00096 SystemCoreClock = Chip_Clock_GetSystemClockRate(); 00097 00098 while (SystemCoreClock != TargetSystemCoreClock) { } // Loop forever if the clock failed to initialize properly 00099 } 00100 00101 void initGpio() 00102 { 00103 LPC_SYSCTL->SYSAHBCLKCTRL |= 1 << SYSCTL_CLOCK_IOCON ; 00104 LPC_SYSCTL->SYSAHBCLKCTRL |= 1 << SYSCTL_CLOCK_GPIO ; 00105 00106 for (unsigned i = 0; i < (sizeof(pinmux) / sizeof(PinMuxGroup)); i++) 00107 { 00108 LPC_IOCON->REG[pinmux[i].pin] = pinmux[i].modefunc; 00109 } 00110 00111 LPC_GPIO[ErrorLedPort].DIR |= 1 << ErrorLedPin; 00112 LPC_GPIO[StatusLedPort].DIR |= 1 << StatusLedPin; 00113 } 00114 00115 void initUart() 00116 { 00117 Chip_UART_Init(LPC_USART); 00118 Chip_UART_SetBaud(LPC_USART, 115200); 00119 Chip_UART_TXEnable(LPC_USART); 00120 } 00121 00122 void init() 00123 { 00124 Chip_SYSCTL_SetBODLevels(SYSCTL_BODRSTLVL_2_06V , SYSCTL_BODINTVAL_RESERVED1); 00125 Chip_SYSCTL_EnableBODReset(); 00126 00127 initWatchdog(); 00128 initClock(); 00129 initGpio(); 00130 initUart(); 00131 00132 resetWatchdog(); 00133 } 00134 00135 } // namespace 00136 00137 void die() 00138 { 00139 static const volatile unsigned& DHCSR = *reinterpret_cast<unsigned*>(0xE000EDF0U); 00140 00141 syslog("FATAL\r\n"); 00142 00143 while (true) 00144 { 00145 if ((DHCSR & 1U) != 0) 00146 { 00147 __asm volatile ("bkpt #0\n"); // Break into the debugger 00148 } 00149 } 00150 } 00151 00152 #if __GNUC__ 00153 __attribute__((optimize(0))) // Optimization must be disabled lest it hardfaults in the IAP call 00154 #endif 00155 void readUniqueID(std::uint8_t out_uid[UniqueIDSize]) 00156 { 00157 unsigned aligned_array[5] = {}; // out_uid may be unaligned, so we need to use temp array 00158 unsigned iap_command = 58; 00159 reinterpret_cast<void(*)(void*, void*)>(0x1FFF1FF1)(&iap_command, aligned_array); 00160 std::memcpy(out_uid, &aligned_array[1], 16); 00161 } 00162 00163 void setStatusLed(bool state) 00164 { 00165 LPC_GPIO[StatusLedPort].DATA[1 << StatusLedPin] = static_cast<unsigned long>(!state) << StatusLedPin; 00166 } 00167 00168 void setErrorLed(bool state) 00169 { 00170 LPC_GPIO[ErrorLedPort].DATA[1 << ErrorLedPin] = static_cast<unsigned long>(!state) << ErrorLedPin; 00171 } 00172 00173 void resetWatchdog() 00174 { 00175 Chip_WWDT_Feed(LPC_WWDT); 00176 } 00177 00178 void syslog(const char* msg) 00179 { 00180 Chip_UART_SendBlocking(LPC_USART, msg, static_cast<int>(std::strlen(msg))); 00181 } 00182 00183 } // namespace board 00184 00185 extern "C" 00186 { 00187 00188 void SystemInit(); 00189 00190 void SystemInit() 00191 { 00192 board::init(); 00193 } 00194 00195 }
Generated on Tue Jul 12 2022 17:17:30 by 1.7.2