File indexing completed on 2025-05-11 08:23:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #include <bsp.h>
0037 #include <bsp/io.h>
0038 #include <bsp/start.h>
0039 #include <bsp/lpc24xx.h>
0040 #include <bsp/lpc-emc.h>
0041 #include <bsp/start-config.h>
0042
0043 static BSP_START_TEXT_SECTION void lpc24xx_cpu_delay(unsigned ticks)
0044 {
0045 unsigned i = 0;
0046
0047
0048 ticks /= 4;
0049
0050 for (i = 0; i <= ticks; ++i) {
0051 __asm__ volatile ("nop");
0052 }
0053 }
0054
0055 static BSP_START_TEXT_SECTION void lpc24xx_udelay(unsigned us)
0056 {
0057 lpc24xx_cpu_delay(us * (LPC24XX_CCLK / 1000000));
0058 }
0059
0060 static BSP_START_TEXT_SECTION void lpc24xx_init_pinsel(void)
0061 {
0062 lpc24xx_pin_config(
0063 &lpc24xx_start_config_pinsel [0],
0064 LPC24XX_PIN_SET_FUNCTION
0065 );
0066 }
0067
0068 static BSP_START_TEXT_SECTION void lpc24xx_init_emc_static(void)
0069 {
0070 size_t i = 0;
0071 size_t chip_count = lpc24xx_start_config_emc_static_chip_count;
0072
0073 for (i = 0; i < chip_count; ++i) {
0074 const lpc24xx_emc_static_chip_config *chip_config =
0075 &lpc24xx_start_config_emc_static_chip [i];
0076 lpc24xx_emc_static_chip_config chip_config_on_stack;
0077 size_t config_size = sizeof(chip_config_on_stack.config);
0078
0079 bsp_start_memcpy(
0080 (int *) &chip_config_on_stack.config,
0081 (const int *) &chip_config->config,
0082 config_size
0083 );
0084 bsp_start_memcpy(
0085 (int *) chip_config->chip_select,
0086 (const int *) &chip_config_on_stack.config,
0087 config_size
0088 );
0089 }
0090 }
0091
0092 static BSP_START_TEXT_SECTION void lpc24xx_init_emc_dynamic(void)
0093 {
0094 size_t chip_count = lpc24xx_start_config_emc_dynamic_chip_count;
0095
0096 if (chip_count > 0) {
0097 bool do_initialization = true;
0098 size_t i = 0;
0099
0100 for (i = 0; do_initialization && i < chip_count; ++i) {
0101 const lpc24xx_emc_dynamic_chip_config *chip_cfg =
0102 &lpc24xx_start_config_emc_dynamic_chip [i];
0103 volatile lpc_emc_dynamic *chip_select = chip_cfg->chip_select;
0104
0105 do_initialization = (chip_select->config & EMC_DYN_CFG_B) == 0;
0106 }
0107
0108 if (do_initialization) {
0109 volatile lpc_emc *emc = (volatile lpc_emc *) EMC_BASE_ADDR;
0110 const lpc24xx_emc_dynamic_config *cfg =
0111 &lpc24xx_start_config_emc_dynamic [0];
0112 uint32_t dynamiccontrol = EMC_DYN_CTRL_CE | EMC_DYN_CTRL_CS;
0113
0114 #ifdef ARM_MULTILIB_ARCH_V7M
0115 volatile lpc17xx_scb *scb = &LPC17XX_SCB;
0116
0117
0118 scb->emcdlyctl = cfg->emcdlyctl;
0119 #endif
0120
0121 emc->dynamicreadconfig = cfg->readconfig;
0122
0123
0124 emc->dynamictrp = cfg->trp;
0125 emc->dynamictras = cfg->tras;
0126 emc->dynamictsrex = cfg->tsrex;
0127 emc->dynamictapr = cfg->tapr;
0128 emc->dynamictdal = cfg->tdal;
0129 emc->dynamictwr = cfg->twr;
0130 emc->dynamictrc = cfg->trc;
0131 emc->dynamictrfc = cfg->trfc;
0132 emc->dynamictxsr = cfg->txsr;
0133 emc->dynamictrrd = cfg->trrd;
0134 emc->dynamictmrd = cfg->tmrd;
0135
0136
0137 emc->dynamiccontrol = dynamiccontrol | EMC_DYN_CTRL_I_NOP;
0138 lpc24xx_udelay(200);
0139
0140
0141 emc->dynamiccontrol = dynamiccontrol | EMC_DYN_CTRL_I_PALL;
0142 emc->dynamicrefresh = 1;
0143
0144
0145
0146
0147
0148
0149 lpc24xx_cpu_delay(128);
0150
0151
0152 emc->dynamicrefresh = cfg->refresh;
0153 lpc24xx_cpu_delay(128);
0154
0155 for (i = 0; i < chip_count; ++i) {
0156 const lpc24xx_emc_dynamic_chip_config *chip_cfg =
0157 &lpc24xx_start_config_emc_dynamic_chip [i];
0158 volatile lpc_emc_dynamic *chip_select = chip_cfg->chip_select;
0159 uint32_t config = chip_cfg->config;
0160
0161
0162 chip_select->config = config;
0163 chip_select->rascas = chip_cfg->rascas;
0164
0165
0166 emc->dynamiccontrol = dynamiccontrol | EMC_DYN_CTRL_I_MODE;
0167 *(volatile uint32_t *)(chip_cfg->address + chip_cfg->mode);
0168
0169
0170 chip_select->config = config | EMC_DYN_CFG_B;
0171 }
0172
0173 emc->dynamiccontrol = 0;
0174 }
0175 }
0176 }
0177
0178 static BSP_START_TEXT_SECTION void lpc24xx_init_main_oscillator(void)
0179 {
0180 #ifdef ARM_MULTILIB_ARCH_V4
0181 if ((SCS & 0x40) == 0) {
0182 SCS |= 0x20;
0183 while ((SCS & 0x40) == 0) {
0184
0185 }
0186 }
0187 #else
0188 volatile lpc17xx_scb *scb = &LPC17XX_SCB;
0189
0190 if ((scb->scs & LPC17XX_SCB_SCS_OSC_STATUS) == 0) {
0191 scb->scs |= LPC17XX_SCB_SCS_OSC_ENABLE;
0192 while ((scb->scs & LPC17XX_SCB_SCS_OSC_STATUS) == 0) {
0193
0194 }
0195 }
0196 #endif
0197 }
0198
0199 #ifdef ARM_MULTILIB_ARCH_V4
0200
0201 static BSP_START_TEXT_SECTION void lpc24xx_pll_config(
0202 uint32_t val
0203 )
0204 {
0205 PLLCON = val;
0206 PLLFEED = 0xaa;
0207 PLLFEED = 0x55;
0208 }
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224 static BSP_START_TEXT_SECTION void lpc24xx_set_pll(
0225 unsigned clksrc,
0226 unsigned nsel,
0227 unsigned msel,
0228 unsigned cclksel
0229 )
0230 {
0231 uint32_t pllstat = PLLSTAT;
0232 uint32_t pllcfg = SET_PLLCFG_NSEL(0, nsel) | SET_PLLCFG_MSEL(0, msel);
0233 uint32_t clksrcsel = SET_CLKSRCSEL_CLKSRC(0, clksrc);
0234 uint32_t cclkcfg = SET_CCLKCFG_CCLKSEL(0, cclksel | 1);
0235 bool pll_enabled = (pllstat & PLLSTAT_PLLE) != 0;
0236
0237
0238 if ((pllstat & PLLSTAT_PLLC) != 0) {
0239 if (pll_enabled) {
0240
0241 if (PLLCFG == pllcfg && CLKSRCSEL == clksrcsel && CCLKCFG == cclkcfg) {
0242
0243 return;
0244 }
0245 lpc24xx_pll_config(PLLCON_PLLE);
0246 } else {
0247 lpc24xx_pll_config(0);
0248 }
0249 }
0250
0251
0252 CCLKCFG = 0;
0253
0254
0255 if (pll_enabled) {
0256 lpc24xx_pll_config(0);
0257 }
0258
0259
0260 CLKSRCSEL = clksrcsel;
0261
0262
0263 PLLCFG = pllcfg;
0264
0265
0266 lpc24xx_pll_config(PLLCON_PLLE);
0267
0268
0269 while ((PLLSTAT & PLLSTAT_PLOCK) == 0) {
0270
0271 }
0272
0273
0274 CCLKCFG = cclkcfg;
0275
0276
0277 lpc24xx_pll_config(PLLCON_PLLE | PLLCON_PLLC);
0278 }
0279
0280 #else
0281
0282 static BSP_START_TEXT_SECTION void lpc17xx_pll_config(
0283 volatile lpc17xx_pll *pll,
0284 uint32_t val
0285 )
0286 {
0287 pll->con = val;
0288 pll->feed = 0xaa;
0289 pll->feed = 0x55;
0290 }
0291
0292 static BSP_START_TEXT_SECTION void lpc17xx_set_pll(
0293 unsigned msel,
0294 unsigned psel,
0295 unsigned cclkdiv
0296 )
0297 {
0298 volatile lpc17xx_scb *scb = &LPC17XX_SCB;
0299 volatile lpc17xx_pll *pll = &scb->pll_0;
0300 uint32_t pllcfg = LPC17XX_PLL_SEL_MSEL(msel)
0301 | LPC17XX_PLL_SEL_PSEL(psel);
0302 uint32_t pllstat = LPC17XX_PLL_STAT_PLLE
0303 | LPC17XX_PLL_STAT_PLOCK | pllcfg;
0304 uint32_t cclksel_cclkdiv = LPC17XX_SCB_CCLKSEL_CCLKDIV(cclkdiv);
0305 uint32_t cclksel = LPC17XX_SCB_CCLKSEL_CCLKSEL | cclksel_cclkdiv;
0306
0307 if (
0308 pll->stat != pllstat
0309 || scb->cclksel != cclksel
0310 || scb->clksrcsel != LPC17XX_SCB_CLKSRCSEL_CLKSRC
0311 ) {
0312
0313 scb->cclksel = LPC17XX_SCB_CCLKSEL_CCLKDIV(1);
0314
0315
0316 scb->usbclksel = 0;
0317
0318
0319 lpc17xx_pll_config(pll, 0);
0320
0321
0322 scb->clksrcsel = LPC17XX_SCB_CLKSRCSEL_CLKSRC;
0323
0324
0325 pll->cfg = pllcfg;
0326
0327
0328 scb->cclksel = cclksel_cclkdiv;
0329 scb->pclksel = LPC17XX_SCB_PCLKSEL_PCLKDIV(cclkdiv * LPC24XX_PCLKDIV);
0330 scb->emcclksel = LPC24XX_EMCCLKDIV == 1 ? 0 : LPC17XX_SCB_EMCCLKSEL_EMCDIV;
0331
0332
0333 lpc17xx_pll_config(pll, LPC17XX_PLL_CON_PLLE);
0334
0335
0336 while ((pll->stat & LPC17XX_PLL_STAT_PLOCK) == 0) {
0337
0338 }
0339
0340
0341 scb->cclksel = cclksel;
0342 }
0343 }
0344
0345 #endif
0346
0347 static BSP_START_TEXT_SECTION void lpc24xx_init_pll(void)
0348 {
0349 #ifdef ARM_MULTILIB_ARCH_V4
0350 #if LPC24XX_OSCILLATOR_MAIN == 12000000U
0351 #if LPC24XX_CCLK == 72000000U
0352 lpc24xx_set_pll(1, 0, 11, 3);
0353 #elif LPC24XX_CCLK == 51612800U
0354 lpc24xx_set_pll(1, 30, 399, 5);
0355 #else
0356 #error "unexpected CCLK"
0357 #endif
0358 #elif LPC24XX_OSCILLATOR_MAIN == 3686400U
0359 #if LPC24XX_CCLK == 58982400U
0360 lpc24xx_set_pll(1, 0, 47, 5);
0361 #else
0362 #error "unexpected CCLK"
0363 #endif
0364 #else
0365 #error "unexpected main oscillator frequency"
0366 #endif
0367 #else
0368 #if LPC24XX_OSCILLATOR_MAIN == 12000000U
0369 #if LPC24XX_CCLK == 120000000U
0370 lpc17xx_set_pll(9, 0, 1);
0371 #elif LPC24XX_CCLK == 96000000U
0372 lpc17xx_set_pll(7, 0, 1);
0373 #elif LPC24XX_CCLK == 72000000U
0374 lpc17xx_set_pll(5, 1, 1);
0375 #elif LPC24XX_CCLK == 48000000U
0376 lpc17xx_set_pll(3, 1, 1);
0377 #else
0378 #error "unexpected CCLK"
0379 #endif
0380 #else
0381 #error "unexpected main oscillator frequency"
0382 #endif
0383 #endif
0384 }
0385
0386 static BSP_START_TEXT_SECTION void lpc24xx_init_memory_map(void)
0387 {
0388 #ifdef ARM_MULTILIB_ARCH_V4
0389
0390 MEMMAP = SET_MEMMAP_MAP(MEMMAP, 2);
0391 #else
0392 volatile lpc17xx_scb *scb = &LPC17XX_SCB;
0393
0394 scb->memmap = LPC17XX_SCB_MEMMAP_MAP;
0395 #endif
0396
0397
0398 EMC_CTRL &= ~0x2U;
0399 }
0400
0401 static BSP_START_TEXT_SECTION void lpc24xx_init_memory_accelerator(void)
0402 {
0403 #ifdef ARM_MULTILIB_ARCH_V4
0404
0405 MAMCR = 0;
0406 #if LPC24XX_CCLK <= 20000000U
0407 MAMTIM = 0x1;
0408 #elif LPC24XX_CCLK <= 40000000U
0409 MAMTIM = 0x2;
0410 #elif LPC24XX_CCLK <= 60000000U
0411 MAMTIM = 0x3;
0412 #else
0413 MAMTIM = 0x4;
0414 #endif
0415 MAMCR = 0x2;
0416
0417
0418 SCS |= 0x1;
0419 #else
0420 volatile lpc17xx_scb *scb = &LPC17XX_SCB;
0421
0422 #if LPC24XX_CCLK <= 20000000U
0423 scb->flashcfg = LPC17XX_SCB_FLASHCFG_FLASHTIM(0x0);
0424 #elif LPC24XX_CCLK <= 40000000U
0425 scb->flashcfg = LPC17XX_SCB_FLASHCFG_FLASHTIM(0x1);
0426 #elif LPC24XX_CCLK <= 60000000U
0427 scb->flashcfg = LPC17XX_SCB_FLASHCFG_FLASHTIM(0x2);
0428 #elif LPC24XX_CCLK <= 80000000U
0429 scb->flashcfg = LPC17XX_SCB_FLASHCFG_FLASHTIM(0x3);
0430 #elif LPC24XX_CCLK <= 100000000U
0431 scb->flashcfg = LPC17XX_SCB_FLASHCFG_FLASHTIM(0x4);
0432 #else
0433 scb->flashcfg = LPC17XX_SCB_FLASHCFG_FLASHTIM(0x5);
0434 #endif
0435 #endif
0436 }
0437
0438 static BSP_START_TEXT_SECTION void lpc24xx_stop_gpdma(void)
0439 {
0440 #ifdef LPC24XX_STOP_GPDMA
0441 #ifdef ARM_MULTILIB_ARCH_V4
0442 bool has_power = (PCONP & PCONP_GPDMA) != 0;
0443 #else
0444 volatile lpc17xx_scb *scb = &LPC17XX_SCB;
0445 bool has_power = (scb->pconp & LPC17XX_SCB_PCONP_GPDMA) != 0;
0446 #endif
0447
0448 if (has_power) {
0449 GPDMA_CONFIG = 0;
0450
0451 #ifdef ARM_MULTILIB_ARCH_V4
0452 PCONP &= ~PCONP_GPDMA;
0453 #else
0454 scb->pconp &= ~LPC17XX_SCB_PCONP_GPDMA;
0455 #endif
0456 }
0457 #endif
0458 }
0459
0460 static BSP_START_TEXT_SECTION void lpc24xx_stop_ethernet(void)
0461 {
0462 #ifdef LPC24XX_STOP_ETHERNET
0463 #ifdef ARM_MULTILIB_ARCH_V4
0464 bool has_power = (PCONP & PCONP_ETHERNET) != 0;
0465 #else
0466 volatile lpc17xx_scb *scb = &LPC17XX_SCB;
0467 bool has_power = (scb->pconp & LPC17XX_SCB_PCONP_ENET) != 0;
0468 #endif
0469
0470 if (has_power) {
0471 MAC_COMMAND = 0x38;
0472 MAC_MAC1 = 0xcf00;
0473 MAC_MAC1 = 0;
0474
0475 #ifdef ARM_MULTILIB_ARCH_V4
0476 PCONP &= ~PCONP_ETHERNET;
0477 #else
0478 scb->pconp &= ~LPC17XX_SCB_PCONP_ENET;
0479 #endif
0480 }
0481 #endif
0482 }
0483
0484 static BSP_START_TEXT_SECTION void lpc24xx_stop_usb(void)
0485 {
0486 #ifdef LPC24XX_STOP_USB
0487 #ifdef ARM_MULTILIB_ARCH_V4
0488 bool has_power = (PCONP & PCONP_USB) != 0;
0489 #else
0490 volatile lpc17xx_scb *scb = &LPC17XX_SCB;
0491 bool has_power = (scb->pconp & LPC17XX_SCB_PCONP_USB) != 0;
0492 #endif
0493
0494 if (has_power) {
0495 OTG_CLK_CTRL = 0;
0496
0497 #ifdef ARM_MULTILIB_ARCH_V4
0498 PCONP &= ~PCONP_USB;
0499 #else
0500 scb->pconp &= ~LPC17XX_SCB_PCONP_USB;
0501 scb->usbclksel = 0;
0502 #endif
0503 }
0504 #endif
0505 }
0506
0507 static BSP_START_TEXT_SECTION void lpc24xx_init_mpu(void)
0508 {
0509 #ifdef ARM_MULTILIB_ARCH_V7M
0510 volatile ARMV7M_MPU *mpu = _ARMV7M_MPU;
0511 size_t region_count = lpc24xx_start_config_mpu_region_count;
0512 size_t i = 0;
0513
0514 for (i = 0; i < region_count; ++i) {
0515 mpu->rbar = lpc24xx_start_config_mpu_region [i].rbar;
0516 mpu->rasr = lpc24xx_start_config_mpu_region [i].rasr;
0517 }
0518
0519 if (region_count > 0) {
0520 mpu->ctrl = ARMV7M_MPU_CTRL_ENABLE;
0521 }
0522 #endif
0523 }
0524
0525 BSP_START_TEXT_SECTION void bsp_start_hook_0(void)
0526 {
0527 lpc24xx_init_main_oscillator();
0528 lpc24xx_init_pll();
0529 lpc24xx_init_pinsel();
0530 lpc24xx_init_emc_static();
0531 }
0532
0533 BSP_START_TEXT_SECTION void bsp_start_hook_1(void)
0534 {
0535 lpc24xx_init_memory_map();
0536 lpc24xx_init_memory_accelerator();
0537 lpc24xx_init_emc_dynamic();
0538 lpc24xx_init_mpu();
0539 lpc24xx_stop_gpdma();
0540 lpc24xx_stop_ethernet();
0541 lpc24xx_stop_usb();
0542 bsp_start_copy_sections();
0543 bsp_start_clear_bss();
0544
0545
0546 }