source: rtems/c/src/lib/libbsp/arm/lpc32xx/startup/bspstarthooks.c @ 598a4505

4.115
Last change on this file since 598a4505 was 598a4505, checked in by Sebastian Huber <sebastian.huber@…>, on 12/03/10 at 09:29:08

2010-12-03 Sebastian Huber <sebastian.huber@…>

  • include/lpc32xx.h: Added I2S module.
  • Makefile.am, bsp_specs, preinstall.am, startup/bspstarthooks.c, startup/linkcmds.lpc32xx, startup/linkcmds.lpc32xx_mzx, startup/linkcmds.lpc32xx_mzx_stage_1, startup/linkcmds.lpc32xx_mzx_stage_2, startup/linkcmds.lpc32xx_phycore: Update due to linker command file changes.
  • Property mode set to 100644
File size: 9.2 KB
RevLine 
[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]45LINKER_SYMBOL(lpc32xx_translation_table_base);
46
[598a4505]47static 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]176static 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]199static 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]218void BSP_START_TEXT_SECTION bsp_start_hook_0(void)
[c468f18b]219{
[3103d4cb]220  setup_pll();
221  setup_mmu_and_cache();
[c468f18b]222}
223
[598a4505]224static 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]258static 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]293static 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]308void 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}
Note: See TracBrowser for help on using the repository browser.