[c468f18b] | 1 | /** |
---|
| 2 | * @file |
---|
| 3 | * |
---|
| 4 | * @ingroup lpc32xx |
---|
| 5 | * |
---|
| 6 | * @brief Startup code. |
---|
| 7 | */ |
---|
| 8 | |
---|
| 9 | /* |
---|
| 10 | * Copyright (c) 2009 |
---|
| 11 | * embedded brains GmbH |
---|
| 12 | * Obere Lagerstr. 30 |
---|
| 13 | * D-82178 Puchheim |
---|
| 14 | * Germany |
---|
| 15 | * <rtems@embedded-brains.de> |
---|
| 16 | * |
---|
| 17 | * The license and distribution terms for this file may be |
---|
| 18 | * found in the file LICENSE in this distribution or at |
---|
| 19 | * http://www.rtems.com/license/LICENSE. |
---|
| 20 | */ |
---|
| 21 | |
---|
| 22 | #include <stdbool.h> |
---|
| 23 | |
---|
| 24 | #include <bspopts.h> |
---|
| 25 | #include <bsp/start.h> |
---|
| 26 | #include <bsp/lpc32xx.h> |
---|
[39c8fdb] | 27 | #include <bsp/mmu.h> |
---|
[c468f18b] | 28 | #include <bsp/linker-symbols.h> |
---|
[4c4974e] | 29 | #include <bsp/uart-output-char.h> |
---|
[c468f18b] | 30 | |
---|
[33785342] | 31 | #ifdef LPC32XX_DISABLE_READ_WRITE_DATA_CACHE |
---|
| 32 | #define LPC32XX_MMU_READ_WRITE_DATA LPC32XX_MMU_READ_WRITE |
---|
| 33 | #else |
---|
| 34 | #define LPC32XX_MMU_READ_WRITE_DATA LPC32XX_MMU_READ_WRITE_CACHED |
---|
| 35 | #endif |
---|
| 36 | |
---|
[22f107b6] | 37 | #ifdef LPC32XX_DISABLE_READ_ONLY_PROTECTION |
---|
| 38 | #define LPC32XX_MMU_READ_ONLY_DATA LPC32XX_MMU_READ_WRITE_CACHED |
---|
| 39 | #define LPC32XX_MMU_CODE LPC32XX_MMU_READ_WRITE_CACHED |
---|
| 40 | #else |
---|
| 41 | #define LPC32XX_MMU_READ_ONLY_DATA LPC32XX_MMU_READ_ONLY_CACHED |
---|
| 42 | #define LPC32XX_MMU_CODE LPC32XX_MMU_READ_ONLY_CACHED |
---|
| 43 | #endif |
---|
| 44 | |
---|
[3103d4cb] | 45 | LINKER_SYMBOL(lpc32xx_translation_table_base); |
---|
| 46 | |
---|
[598a4505] | 47 | static void BSP_START_TEXT_SECTION clear_bss(void) |
---|
[c468f18b] | 48 | { |
---|
| 49 | const int *end = (const int *) bsp_section_bss_end; |
---|
| 50 | int *out = (int *) bsp_section_bss_begin; |
---|
| 51 | |
---|
| 52 | /* Clear BSS */ |
---|
| 53 | while (out != end) { |
---|
| 54 | *out = 0; |
---|
| 55 | ++out; |
---|
| 56 | } |
---|
| 57 | } |
---|
| 58 | |
---|
[4c4974e] | 59 | #ifndef LPC32XX_DISABLE_MMU |
---|
| 60 | typedef struct { |
---|
| 61 | uint32_t begin; |
---|
| 62 | uint32_t end; |
---|
| 63 | uint32_t flags; |
---|
| 64 | } lpc32xx_mmu_config; |
---|
[39c8fdb] | 65 | |
---|
[4c4974e] | 66 | static const BSP_START_DATA_SECTION lpc32xx_mmu_config |
---|
| 67 | lpc32xx_mmu_config_table [] = { |
---|
| 68 | { |
---|
[598a4505] | 69 | .begin = (uint32_t) bsp_section_fast_text_begin, |
---|
| 70 | .end = (uint32_t) bsp_section_fast_text_end, |
---|
| 71 | .flags = LPC32XX_MMU_CODE |
---|
| 72 | }, { |
---|
| 73 | .begin = (uint32_t) bsp_section_fast_data_begin, |
---|
| 74 | .end = (uint32_t) bsp_section_fast_data_end, |
---|
| 75 | .flags = LPC32XX_MMU_READ_WRITE_DATA |
---|
| 76 | }, { |
---|
[4c4974e] | 77 | .begin = (uint32_t) bsp_section_start_begin, |
---|
| 78 | .end = (uint32_t) bsp_section_start_end, |
---|
| 79 | .flags = LPC32XX_MMU_CODE |
---|
| 80 | }, { |
---|
| 81 | .begin = (uint32_t) bsp_section_vector_begin, |
---|
| 82 | .end = (uint32_t) bsp_section_vector_end, |
---|
| 83 | .flags = LPC32XX_MMU_READ_WRITE_CACHED |
---|
| 84 | }, { |
---|
| 85 | .begin = (uint32_t) bsp_section_text_begin, |
---|
| 86 | .end = (uint32_t) bsp_section_text_end, |
---|
| 87 | .flags = LPC32XX_MMU_CODE |
---|
| 88 | }, { |
---|
| 89 | .begin = (uint32_t) bsp_section_rodata_begin, |
---|
| 90 | .end = (uint32_t) bsp_section_rodata_end, |
---|
| 91 | .flags = LPC32XX_MMU_READ_ONLY_DATA |
---|
| 92 | }, { |
---|
| 93 | .begin = (uint32_t) bsp_section_data_begin, |
---|
| 94 | .end = (uint32_t) bsp_section_data_end, |
---|
| 95 | .flags = LPC32XX_MMU_READ_WRITE_DATA |
---|
| 96 | }, { |
---|
| 97 | .begin = (uint32_t) bsp_section_bss_begin, |
---|
| 98 | .end = (uint32_t) bsp_section_bss_end, |
---|
| 99 | .flags = LPC32XX_MMU_READ_WRITE_DATA |
---|
| 100 | }, { |
---|
| 101 | .begin = (uint32_t) bsp_section_work_begin, |
---|
| 102 | .end = (uint32_t) bsp_section_work_end, |
---|
| 103 | .flags = LPC32XX_MMU_READ_WRITE_DATA |
---|
| 104 | }, { |
---|
| 105 | .begin = (uint32_t) bsp_section_stack_begin, |
---|
| 106 | .end = (uint32_t) bsp_section_stack_end, |
---|
| 107 | .flags = LPC32XX_MMU_READ_WRITE_DATA |
---|
| 108 | }, { |
---|
| 109 | .begin = 0x0U, |
---|
| 110 | .end = 0x100000U, |
---|
| 111 | .flags = LPC32XX_MMU_READ_ONLY_CACHED |
---|
| 112 | }, { |
---|
| 113 | .begin = 0x20000000U, |
---|
| 114 | .end = 0x200c0000U, |
---|
| 115 | .flags = LPC32XX_MMU_READ_WRITE |
---|
| 116 | }, { |
---|
| 117 | .begin = 0x30000000U, |
---|
| 118 | .end = 0x32000000U, |
---|
| 119 | .flags = LPC32XX_MMU_READ_WRITE |
---|
| 120 | }, { |
---|
| 121 | .begin = 0x40000000U, |
---|
| 122 | .end = 0x40100000U, |
---|
| 123 | .flags = LPC32XX_MMU_READ_WRITE |
---|
[3103d4cb] | 124 | }, { |
---|
| 125 | .begin = (uint32_t) lpc32xx_magic_zero_begin, |
---|
| 126 | .end = (uint32_t) lpc32xx_magic_zero_end, |
---|
| 127 | .flags = LPC32XX_MMU_READ_WRITE_DATA |
---|
[4c4974e] | 128 | } |
---|
| 129 | }; |
---|
| 130 | |
---|
[598a4505] | 131 | static void BSP_START_TEXT_SECTION set_translation_table_entries( |
---|
[4c4974e] | 132 | uint32_t *ttb, |
---|
| 133 | const lpc32xx_mmu_config *config |
---|
| 134 | ) |
---|
[39c8fdb] | 135 | { |
---|
[4c4974e] | 136 | uint32_t i = ARM_MMU_SECT_GET_INDEX(config->begin); |
---|
| 137 | uint32_t iend = |
---|
| 138 | ARM_MMU_SECT_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(config->end)); |
---|
| 139 | |
---|
| 140 | if (config->begin != config->end) { |
---|
| 141 | while (i < iend) { |
---|
| 142 | ttb [i] = (i << ARM_MMU_SECT_BASE_SHIFT) | config->flags; |
---|
| 143 | ++i; |
---|
| 144 | } |
---|
| 145 | } |
---|
[39c8fdb] | 146 | } |
---|
| 147 | |
---|
[598a4505] | 148 | static void BSP_START_TEXT_SECTION |
---|
[3103d4cb] | 149 | setup_translation_table_and_enable_mmu(uint32_t ctrl) |
---|
[4c4974e] | 150 | { |
---|
| 151 | uint32_t const dac = |
---|
| 152 | ARM_CP15_DAC_DOMAIN(LPC32XX_MMU_CLIENT_DOMAIN, ARM_CP15_DAC_CLIENT); |
---|
[3103d4cb] | 153 | uint32_t *const ttb = (uint32_t *) lpc32xx_translation_table_base; |
---|
[4c4974e] | 154 | size_t const config_entry_count = |
---|
| 155 | sizeof(lpc32xx_mmu_config_table) / sizeof(lpc32xx_mmu_config_table [0]); |
---|
| 156 | size_t i = 0; |
---|
| 157 | |
---|
| 158 | arm_cp15_set_domain_access_control(dac); |
---|
| 159 | arm_cp15_set_translation_table_base(ttb); |
---|
[39c8fdb] | 160 | |
---|
[4c4974e] | 161 | /* Initialize translation table with invalid entries */ |
---|
| 162 | for (i = 0; i < ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT; ++i) { |
---|
| 163 | ttb [i] = 0; |
---|
[39c8fdb] | 164 | } |
---|
[4c4974e] | 165 | |
---|
| 166 | for (i = 0; i < config_entry_count; ++i) { |
---|
[3103d4cb] | 167 | set_translation_table_entries(ttb, &lpc32xx_mmu_config_table [i]); |
---|
[4c4974e] | 168 | } |
---|
| 169 | |
---|
| 170 | /* Enable MMU and cache */ |
---|
| 171 | ctrl |= ARM_CP15_CTRL_I | ARM_CP15_CTRL_C | ARM_CP15_CTRL_M; |
---|
| 172 | arm_cp15_set_control(ctrl); |
---|
[39c8fdb] | 173 | } |
---|
[4c4974e] | 174 | #endif |
---|
[39c8fdb] | 175 | |
---|
[598a4505] | 176 | static void BSP_START_TEXT_SECTION setup_mmu_and_cache(void) |
---|
[39c8fdb] | 177 | { |
---|
| 178 | uint32_t ctrl = 0; |
---|
| 179 | |
---|
| 180 | /* Disable MMU and cache, basic settings */ |
---|
| 181 | ctrl = arm_cp15_get_control(); |
---|
| 182 | ctrl &= ~(ARM_CP15_CTRL_I | ARM_CP15_CTRL_R | ARM_CP15_CTRL_C |
---|
| 183 | | ARM_CP15_CTRL_V | ARM_CP15_CTRL_M); |
---|
| 184 | ctrl |= ARM_CP15_CTRL_S | ARM_CP15_CTRL_A; |
---|
| 185 | arm_cp15_set_control(ctrl); |
---|
| 186 | |
---|
| 187 | arm_cp15_cache_invalidate(); |
---|
| 188 | arm_cp15_tlb_invalidate(); |
---|
| 189 | |
---|
[4c4974e] | 190 | #ifndef LPC32XX_DISABLE_MMU |
---|
[3103d4cb] | 191 | setup_translation_table_and_enable_mmu(ctrl); |
---|
[4c4974e] | 192 | #endif |
---|
[39c8fdb] | 193 | } |
---|
| 194 | |
---|
[bc74b337] | 195 | #if LPC32XX_OSCILLATOR_MAIN != 13000000U |
---|
| 196 | #error "unexpected main oscillator frequency" |
---|
| 197 | #endif |
---|
| 198 | |
---|
[598a4505] | 199 | static void BSP_START_TEXT_SECTION setup_pll(void) |
---|
[bc74b337] | 200 | { |
---|
| 201 | uint32_t pwr_ctrl = LPC32XX_PWR_CTRL; |
---|
| 202 | |
---|
| 203 | if ((pwr_ctrl & PWR_NORMAL_RUN_MODE) == 0) { |
---|
| 204 | /* Enable HCLK PLL */ |
---|
| 205 | LPC32XX_HCLKPLL_CTRL = HCLK_PLL_POWER | HCLK_PLL_DIRECT | HCLK_PLL_M(16 - 1); |
---|
| 206 | while ((LPC32XX_HCLKPLL_CTRL & HCLK_PLL_LOCK) == 0) { |
---|
| 207 | /* Wait */ |
---|
| 208 | } |
---|
| 209 | |
---|
| 210 | /* Setup HCLK divider */ |
---|
| 211 | LPC32XX_HCLKDIV_CTRL = HCLK_DIV_HCLK(2 - 1) | HCLK_DIV_PERIPH_CLK(16 - 1); |
---|
| 212 | |
---|
| 213 | /* Enable HCLK PLL output */ |
---|
| 214 | LPC32XX_PWR_CTRL = pwr_ctrl | PWR_NORMAL_RUN_MODE; |
---|
| 215 | } |
---|
| 216 | } |
---|
| 217 | |
---|
[598a4505] | 218 | void BSP_START_TEXT_SECTION bsp_start_hook_0(void) |
---|
[c468f18b] | 219 | { |
---|
[3103d4cb] | 220 | setup_pll(); |
---|
| 221 | setup_mmu_and_cache(); |
---|
[c468f18b] | 222 | } |
---|
| 223 | |
---|
[598a4505] | 224 | static void BSP_START_TEXT_SECTION stop_dma_activities(void) |
---|
[f140fdc] | 225 | { |
---|
| 226 | #ifdef LPC32XX_STOP_GPDMA |
---|
| 227 | if ((LPC32XX_DMACLK_CTRL & 0x1) != 0) { |
---|
| 228 | if ((lpc32xx.dma.cfg & LPC_DMA_CFG_EN) != 0) { |
---|
| 229 | int i = 0; |
---|
| 230 | |
---|
| 231 | for (i = 0; i < 8; ++i) { |
---|
| 232 | lpc32xx.dma.channels [i].cfg = 0; |
---|
| 233 | } |
---|
| 234 | |
---|
| 235 | lpc32xx.dma.cfg &= ~LPC_DMA_CFG_EN; |
---|
| 236 | } |
---|
| 237 | LPC32XX_DMACLK_CTRL = 0; |
---|
| 238 | } |
---|
| 239 | #endif |
---|
| 240 | |
---|
| 241 | #ifdef LPC32XX_STOP_ETHERNET |
---|
| 242 | if ((LPC32XX_MAC_CLK_CTRL & 0x7) == 0x7) { |
---|
| 243 | lpc32xx.eth.command = 0x38; |
---|
| 244 | lpc32xx.eth.mac1 = 0xcf00; |
---|
| 245 | lpc32xx.eth.mac1 = 0; |
---|
| 246 | LPC32XX_MAC_CLK_CTRL = 0; |
---|
| 247 | } |
---|
| 248 | #endif |
---|
| 249 | |
---|
| 250 | #ifdef LPC32XX_STOP_USB |
---|
| 251 | if ((LPC32XX_USB_CTRL & 0x010e8000) != 0) { |
---|
| 252 | LPC32XX_OTG_CLK_CTRL = 0; |
---|
| 253 | LPC32XX_USB_CTRL = 0x80000; |
---|
| 254 | } |
---|
| 255 | #endif |
---|
| 256 | } |
---|
| 257 | |
---|
[598a4505] | 258 | static void BSP_START_TEXT_SECTION setup_uarts(void) |
---|
[4c4974e] | 259 | { |
---|
| 260 | uint32_t uartclk_ctrl = 0; |
---|
| 261 | |
---|
| 262 | #ifdef LPC32XX_CONFIG_U3CLK |
---|
| 263 | uartclk_ctrl |= 1U << 0; |
---|
| 264 | LPC32XX_U3CLK = LPC32XX_CONFIG_U3CLK; |
---|
| 265 | #endif |
---|
| 266 | #ifdef LPC32XX_CONFIG_U4CLK |
---|
| 267 | uartclk_ctrl |= 1U << 1; |
---|
| 268 | LPC32XX_U4CLK = LPC32XX_CONFIG_U4CLK; |
---|
| 269 | #endif |
---|
| 270 | #ifdef LPC32XX_CONFIG_U5CLK |
---|
| 271 | uartclk_ctrl |= 1U << 2; |
---|
| 272 | LPC32XX_U5CLK = LPC32XX_CONFIG_U5CLK; |
---|
| 273 | #endif |
---|
| 274 | #ifdef LPC32XX_CONFIG_U6CLK |
---|
| 275 | uartclk_ctrl |= 1U << 3; |
---|
| 276 | LPC32XX_U6CLK = LPC32XX_CONFIG_U6CLK; |
---|
| 277 | #endif |
---|
| 278 | |
---|
| 279 | #ifdef LPC32XX_CONFIG_UART_CLKMODE |
---|
| 280 | LPC32XX_UART_CLKMODE = LPC32XX_CONFIG_UART_CLKMODE; |
---|
| 281 | #endif |
---|
| 282 | |
---|
| 283 | LPC32XX_UARTCLK_CTRL = uartclk_ctrl; |
---|
| 284 | LPC32XX_UART_CTRL = 0x0; |
---|
| 285 | LPC32XX_UART_LOOP = 0x0; |
---|
| 286 | |
---|
| 287 | #ifdef LPC32XX_CONFIG_U5CLK |
---|
| 288 | /* Clock is already set in LPC32XX_U5CLK */ |
---|
| 289 | BSP_CONSOLE_UART_INIT(0x01); |
---|
| 290 | #endif |
---|
| 291 | } |
---|
| 292 | |
---|
[598a4505] | 293 | static void BSP_START_TEXT_SECTION setup_timer(void) |
---|
[3103d4cb] | 294 | { |
---|
| 295 | volatile lpc_timer *timer = LPC32XX_STANDARD_TIMER; |
---|
| 296 | |
---|
| 297 | LPC32XX_TIMCLK_CTRL1 = (1U << 2) | (1U << 3); |
---|
| 298 | |
---|
| 299 | timer->tcr = LPC_TIMER_TCR_RST; |
---|
| 300 | timer->ctcr = 0x0; |
---|
| 301 | timer->pr = 0x0; |
---|
| 302 | timer->ir = 0xff; |
---|
| 303 | timer->mcr = 0x0; |
---|
| 304 | timer->ccr = 0x0; |
---|
| 305 | timer->tcr = LPC_TIMER_TCR_EN; |
---|
| 306 | } |
---|
| 307 | |
---|
[598a4505] | 308 | void BSP_START_TEXT_SECTION bsp_start_hook_1(void) |
---|
[c468f18b] | 309 | { |
---|
[f140fdc] | 310 | stop_dma_activities(); |
---|
[3103d4cb] | 311 | setup_uarts(); |
---|
| 312 | setup_timer(); |
---|
[c468f18b] | 313 | |
---|
| 314 | /* Copy .text section */ |
---|
[39c8fdb] | 315 | arm_cp15_instruction_cache_invalidate(); |
---|
[22f107b6] | 316 | bsp_start_memcpy( |
---|
[c468f18b] | 317 | (int *) bsp_section_text_begin, |
---|
| 318 | (const int *) bsp_section_text_load_begin, |
---|
| 319 | (size_t) bsp_section_text_size |
---|
| 320 | ); |
---|
| 321 | |
---|
| 322 | /* Copy .rodata section */ |
---|
[39c8fdb] | 323 | arm_cp15_instruction_cache_invalidate(); |
---|
[22f107b6] | 324 | bsp_start_memcpy( |
---|
[c468f18b] | 325 | (int *) bsp_section_rodata_begin, |
---|
| 326 | (const int *) bsp_section_rodata_load_begin, |
---|
| 327 | (size_t) bsp_section_rodata_size |
---|
| 328 | ); |
---|
| 329 | |
---|
| 330 | /* Copy .data section */ |
---|
[39c8fdb] | 331 | arm_cp15_instruction_cache_invalidate(); |
---|
[22f107b6] | 332 | bsp_start_memcpy( |
---|
[c468f18b] | 333 | (int *) bsp_section_data_begin, |
---|
| 334 | (const int *) bsp_section_data_load_begin, |
---|
| 335 | (size_t) bsp_section_data_size |
---|
| 336 | ); |
---|
| 337 | |
---|
[598a4505] | 338 | /* Copy .fast_text section */ |
---|
| 339 | arm_cp15_instruction_cache_invalidate(); |
---|
| 340 | bsp_start_memcpy( |
---|
| 341 | (int *) bsp_section_fast_text_begin, |
---|
| 342 | (const int *) bsp_section_fast_text_load_begin, |
---|
| 343 | (size_t) bsp_section_fast_text_size |
---|
| 344 | ); |
---|
| 345 | |
---|
| 346 | /* Copy .fast_data section */ |
---|
[39c8fdb] | 347 | arm_cp15_instruction_cache_invalidate(); |
---|
[22f107b6] | 348 | bsp_start_memcpy( |
---|
[598a4505] | 349 | (int *) bsp_section_fast_data_begin, |
---|
| 350 | (const int *) bsp_section_fast_data_load_begin, |
---|
| 351 | (size_t) bsp_section_fast_data_size |
---|
[c468f18b] | 352 | ); |
---|
| 353 | |
---|
| 354 | /* Clear .bss section */ |
---|
[3103d4cb] | 355 | clear_bss(); |
---|
[c468f18b] | 356 | |
---|
| 357 | /* At this point we can use objects outside the .start section */ |
---|
| 358 | } |
---|