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

4.115
Last change on this file since f140fdc was f140fdc, checked in by Sebastian Huber <sebastian.huber@…>, on Sep 28, 2010 at 2:38:26 PM

2010-09-28 Sebastian Huber <sebastian.huber@…>

  • misc/mmu.c: New file.
  • Makefile.am: Reflect change above.
  • configure.ac, include/bspopts.h.in, include/irq.h, include/lpc32xx.h, include/mmu.h, misc/emc.c, misc/restart.c, startup/bspstarthooks.c: Changes throughout.
  • Property mode set to 100644
File size: 8.8 KB
Line 
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>
27#include <bsp/mmu.h>
28#include <bsp/linker-symbols.h>
29#include <bsp/uart-output-char.h>
30
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
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
45LINKER_SYMBOL(lpc32xx_translation_table_base);
46
47static void BSP_START_SECTION clear_bss(void)
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
59#ifndef LPC32XX_DISABLE_MMU
60  typedef struct {
61    uint32_t begin;
62    uint32_t end;
63    uint32_t flags;
64  } lpc32xx_mmu_config;
65
66  static const BSP_START_DATA_SECTION lpc32xx_mmu_config
67    lpc32xx_mmu_config_table [] = {
68    {
69      .begin = (uint32_t) bsp_section_start_begin,
70      .end = (uint32_t) bsp_section_start_end,
71      .flags = LPC32XX_MMU_CODE
72    }, {
73      .begin = (uint32_t) bsp_section_vector_begin,
74      .end = (uint32_t) bsp_section_vector_end,
75      .flags = LPC32XX_MMU_READ_WRITE_CACHED
76    }, {
77      .begin = (uint32_t) bsp_section_text_begin,
78      .end = (uint32_t) bsp_section_text_end,
79      .flags = LPC32XX_MMU_CODE
80    }, {
81      .begin = (uint32_t) bsp_section_rodata_begin,
82      .end = (uint32_t) bsp_section_rodata_end,
83      .flags = LPC32XX_MMU_READ_ONLY_DATA
84    }, {
85      .begin = (uint32_t) bsp_section_data_begin,
86      .end = (uint32_t) bsp_section_data_end,
87      .flags = LPC32XX_MMU_READ_WRITE_DATA
88    }, {
89      .begin = (uint32_t) bsp_section_fast_begin,
90      .end = (uint32_t) bsp_section_fast_end,
91      .flags = LPC32XX_MMU_CODE
92    }, {
93      .begin = (uint32_t) bsp_section_bss_begin,
94      .end = (uint32_t) bsp_section_bss_end,
95      .flags = LPC32XX_MMU_READ_WRITE_DATA
96    }, {
97      .begin = (uint32_t) bsp_section_work_begin,
98      .end = (uint32_t) bsp_section_work_end,
99      .flags = LPC32XX_MMU_READ_WRITE_DATA
100    }, {
101      .begin = (uint32_t) bsp_section_stack_begin,
102      .end = (uint32_t) bsp_section_stack_end,
103      .flags = LPC32XX_MMU_READ_WRITE_DATA
104    }, {
105      .begin = 0x0U,
106      .end = 0x100000U,
107      .flags = LPC32XX_MMU_READ_ONLY_CACHED
108    }, {
109      .begin = 0x20000000U,
110      .end = 0x200c0000U,
111      .flags = LPC32XX_MMU_READ_WRITE
112    }, {
113      .begin = 0x30000000U,
114      .end = 0x32000000U,
115      .flags = LPC32XX_MMU_READ_WRITE
116    }, {
117      .begin = 0x40000000U,
118      .end = 0x40100000U,
119      .flags = LPC32XX_MMU_READ_WRITE
120    }, {
121      .begin = (uint32_t) lpc32xx_magic_zero_begin,
122      .end = (uint32_t) lpc32xx_magic_zero_end,
123      .flags = LPC32XX_MMU_READ_WRITE_DATA
124    }
125  };
126
127  static void BSP_START_SECTION set_translation_table_entries(
128    uint32_t *ttb,
129    const lpc32xx_mmu_config *config
130  )
131  {
132    uint32_t i = ARM_MMU_SECT_GET_INDEX(config->begin);
133    uint32_t iend =
134      ARM_MMU_SECT_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(config->end));
135
136    if (config->begin != config->end) {
137      while (i < iend) {
138        ttb [i] = (i << ARM_MMU_SECT_BASE_SHIFT) | config->flags;
139        ++i;
140      }
141    }
142  }
143
144  static void BSP_START_SECTION
145    setup_translation_table_and_enable_mmu(uint32_t ctrl)
146  {
147    uint32_t const dac =
148      ARM_CP15_DAC_DOMAIN(LPC32XX_MMU_CLIENT_DOMAIN, ARM_CP15_DAC_CLIENT);
149    uint32_t *const ttb = (uint32_t *) lpc32xx_translation_table_base;
150    size_t const config_entry_count =
151      sizeof(lpc32xx_mmu_config_table) / sizeof(lpc32xx_mmu_config_table [0]);
152    size_t i = 0;
153
154    arm_cp15_set_domain_access_control(dac);
155    arm_cp15_set_translation_table_base(ttb);
156
157    /* Initialize translation table with invalid entries */
158    for (i = 0; i < ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT; ++i) {
159      ttb [i] = 0;
160    }
161
162    for (i = 0; i < config_entry_count; ++i) {
163      set_translation_table_entries(ttb, &lpc32xx_mmu_config_table [i]);
164    }
165
166    /* Enable MMU and cache */
167    ctrl |= ARM_CP15_CTRL_I | ARM_CP15_CTRL_C | ARM_CP15_CTRL_M;
168    arm_cp15_set_control(ctrl);
169  }
170#endif
171
172static void BSP_START_SECTION setup_mmu_and_cache(void)
173{
174  uint32_t ctrl = 0;
175
176  /* Disable MMU and cache, basic settings */
177  ctrl = arm_cp15_get_control();
178  ctrl &= ~(ARM_CP15_CTRL_I | ARM_CP15_CTRL_R | ARM_CP15_CTRL_C
179    | ARM_CP15_CTRL_V | ARM_CP15_CTRL_M);
180  ctrl |= ARM_CP15_CTRL_S | ARM_CP15_CTRL_A;
181  arm_cp15_set_control(ctrl);
182
183  arm_cp15_cache_invalidate();
184  arm_cp15_tlb_invalidate();
185
186  #ifndef LPC32XX_DISABLE_MMU
187    setup_translation_table_and_enable_mmu(ctrl);
188  #endif
189}
190
191#if LPC32XX_OSCILLATOR_MAIN != 13000000U
192  #error "unexpected main oscillator frequency"
193#endif
194
195static void BSP_START_SECTION setup_pll(void)
196{
197  uint32_t pwr_ctrl = LPC32XX_PWR_CTRL;
198
199  if ((pwr_ctrl & PWR_NORMAL_RUN_MODE) == 0) {
200    /* Enable HCLK PLL */
201    LPC32XX_HCLKPLL_CTRL = HCLK_PLL_POWER | HCLK_PLL_DIRECT | HCLK_PLL_M(16 - 1);
202    while ((LPC32XX_HCLKPLL_CTRL & HCLK_PLL_LOCK) == 0) {
203      /* Wait */
204    }
205
206    /* Setup HCLK divider */
207    LPC32XX_HCLKDIV_CTRL = HCLK_DIV_HCLK(2 - 1) | HCLK_DIV_PERIPH_CLK(16 - 1);
208
209    /* Enable HCLK PLL output */
210    LPC32XX_PWR_CTRL = pwr_ctrl | PWR_NORMAL_RUN_MODE;
211  }
212}
213
214void BSP_START_SECTION bsp_start_hook_0(void)
215{
216  setup_pll();
217  setup_mmu_and_cache();
218}
219
220static void BSP_START_SECTION stop_dma_activities(void)
221{
222  #ifdef LPC32XX_STOP_GPDMA
223    if ((LPC32XX_DMACLK_CTRL & 0x1) != 0) {
224      if ((lpc32xx.dma.cfg & LPC_DMA_CFG_EN) != 0) {
225        int i = 0;
226
227        for (i = 0; i < 8; ++i) {
228          lpc32xx.dma.channels [i].cfg = 0;
229        }
230
231        lpc32xx.dma.cfg &= ~LPC_DMA_CFG_EN;
232      }
233      LPC32XX_DMACLK_CTRL = 0;
234    }
235  #endif
236
237  #ifdef LPC32XX_STOP_ETHERNET
238    if ((LPC32XX_MAC_CLK_CTRL & 0x7) == 0x7) {
239      lpc32xx.eth.command = 0x38;
240      lpc32xx.eth.mac1 = 0xcf00;
241      lpc32xx.eth.mac1 = 0;
242      LPC32XX_MAC_CLK_CTRL = 0;
243    }
244  #endif
245
246  #ifdef LPC32XX_STOP_USB
247    if ((LPC32XX_USB_CTRL & 0x010e8000) != 0) {
248      LPC32XX_OTG_CLK_CTRL = 0;
249      LPC32XX_USB_CTRL = 0x80000;
250    }
251  #endif
252}
253
254static void BSP_START_SECTION setup_uarts(void)
255{
256  uint32_t uartclk_ctrl = 0;
257
258  #ifdef LPC32XX_CONFIG_U3CLK
259    uartclk_ctrl |= 1U << 0;
260    LPC32XX_U3CLK = LPC32XX_CONFIG_U3CLK;
261  #endif
262  #ifdef LPC32XX_CONFIG_U4CLK
263    uartclk_ctrl |= 1U << 1;
264    LPC32XX_U4CLK = LPC32XX_CONFIG_U4CLK;
265  #endif
266  #ifdef LPC32XX_CONFIG_U5CLK
267    uartclk_ctrl |= 1U << 2;
268    LPC32XX_U5CLK = LPC32XX_CONFIG_U5CLK;
269  #endif
270  #ifdef LPC32XX_CONFIG_U6CLK
271    uartclk_ctrl |= 1U << 3;
272    LPC32XX_U6CLK = LPC32XX_CONFIG_U6CLK;
273  #endif
274
275  #ifdef LPC32XX_CONFIG_UART_CLKMODE
276    LPC32XX_UART_CLKMODE = LPC32XX_CONFIG_UART_CLKMODE;
277  #endif
278
279  LPC32XX_UARTCLK_CTRL = uartclk_ctrl;
280  LPC32XX_UART_CTRL = 0x0;
281  LPC32XX_UART_LOOP = 0x0;
282
283  #ifdef LPC32XX_CONFIG_U5CLK
284    /* Clock is already set in LPC32XX_U5CLK */
285    BSP_CONSOLE_UART_INIT(0x01);
286  #endif
287}
288
289static void BSP_START_SECTION setup_timer(void)
290{
291  volatile lpc_timer *timer = LPC32XX_STANDARD_TIMER;
292
293  LPC32XX_TIMCLK_CTRL1 = (1U << 2) | (1U << 3);
294
295  timer->tcr = LPC_TIMER_TCR_RST;
296  timer->ctcr = 0x0;
297  timer->pr = 0x0;
298  timer->ir = 0xff;
299  timer->mcr = 0x0;
300  timer->ccr = 0x0;
301  timer->tcr = LPC_TIMER_TCR_EN;
302}
303
304void BSP_START_SECTION bsp_start_hook_1(void)
305{
306  stop_dma_activities();
307  setup_uarts();
308  setup_timer();
309
310  /* Copy .text section */
311  arm_cp15_instruction_cache_invalidate();
312  bsp_start_memcpy(
313    (int *) bsp_section_text_begin,
314    (const int *) bsp_section_text_load_begin,
315    (size_t) bsp_section_text_size
316  );
317
318  /* Copy .rodata section */
319  arm_cp15_instruction_cache_invalidate();
320  bsp_start_memcpy(
321    (int *) bsp_section_rodata_begin,
322    (const int *) bsp_section_rodata_load_begin,
323    (size_t) bsp_section_rodata_size
324  );
325
326  /* Copy .data section */
327  arm_cp15_instruction_cache_invalidate();
328  bsp_start_memcpy(
329    (int *) bsp_section_data_begin,
330    (const int *) bsp_section_data_load_begin,
331    (size_t) bsp_section_data_size
332  );
333
334  /* Copy .fast section */
335  arm_cp15_instruction_cache_invalidate();
336  bsp_start_memcpy(
337    (int *) bsp_section_fast_begin,
338    (const int *) bsp_section_fast_load_begin,
339    (size_t) bsp_section_fast_size
340  );
341
342  /* Clear .bss section */
343  clear_bss();
344
345  /* At this point we can use objects outside the .start section */
346}
Note: See TracBrowser for help on using the repository browser.