summaryrefslogblamecommitdiffstats
path: root/c/src/lib/libbsp/arm/lpc32xx/startup/bspstarthooks.c
blob: 93b3437569ac50b521962e5118fda848c880879f (plain) (tree)

























                                                          
                    
                               
                                 
 





                                                                   







                                                                  











                                                     





                           
 




























































                                                        
   









                                                                     
   
 











                                                                              
 


                                                                 
     







                                                                  
   
      


                                                               
                    










                                                               


                                                         

 

                                             
                                

 


































                                                          

                                             
                           

                          
                                          
                   





                                              
                                          
                   





                                                
                                          
                   





                                              
                                          
                   









                                                                   
/**
 * @file
 *
 * @ingroup lpc32xx
 *
 * @brief Startup code.
 */

/*
 * Copyright (c) 2009
 * embedded brains GmbH
 * Obere Lagerstr. 30
 * D-82178 Puchheim
 * Germany
 * <rtems@embedded-brains.de>
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rtems.com/license/LICENSE.
 */

#include <stdbool.h>

#include <bspopts.h>
#include <bsp/start.h>
#include <bsp/lpc32xx.h>
#include <bsp/mmu.h>
#include <bsp/linker-symbols.h>
#include <bsp/uart-output-char.h>

#ifdef LPC32XX_DISABLE_READ_WRITE_DATA_CACHE
  #define LPC32XX_MMU_READ_WRITE_DATA LPC32XX_MMU_READ_WRITE
#else
  #define LPC32XX_MMU_READ_WRITE_DATA LPC32XX_MMU_READ_WRITE_CACHED
#endif

#ifdef LPC32XX_DISABLE_READ_ONLY_PROTECTION
  #define LPC32XX_MMU_READ_ONLY_DATA LPC32XX_MMU_READ_WRITE_CACHED
  #define LPC32XX_MMU_CODE LPC32XX_MMU_READ_WRITE_CACHED
#else
  #define LPC32XX_MMU_READ_ONLY_DATA LPC32XX_MMU_READ_ONLY_CACHED
  #define LPC32XX_MMU_CODE LPC32XX_MMU_READ_ONLY_CACHED
#endif

static void BSP_START_SECTION lpc32xx_clear_bss(void)
{
  const int *end = (const int *) bsp_section_bss_end;
  int *out = (int *) bsp_section_bss_begin;

  /* Clear BSS */
  while (out != end) {
    *out = 0;
    ++out;
  }
}

#ifndef LPC32XX_DISABLE_MMU
  typedef struct {
    uint32_t begin;
    uint32_t end;
    uint32_t flags;
  } lpc32xx_mmu_config;

  static const BSP_START_DATA_SECTION lpc32xx_mmu_config
    lpc32xx_mmu_config_table [] = {
    {
      .begin = (uint32_t) bsp_section_start_begin,
      .end = (uint32_t) bsp_section_start_end,
      .flags = LPC32XX_MMU_CODE
    }, {
      .begin = (uint32_t) bsp_section_vector_begin,
      .end = (uint32_t) bsp_section_vector_end,
      .flags = LPC32XX_MMU_READ_WRITE_CACHED
    }, {
      .begin = (uint32_t) bsp_section_text_begin,
      .end = (uint32_t) bsp_section_text_end,
      .flags = LPC32XX_MMU_CODE
    }, {
      .begin = (uint32_t) bsp_section_rodata_begin,
      .end = (uint32_t) bsp_section_rodata_end,
      .flags = LPC32XX_MMU_READ_ONLY_DATA
    }, {
      .begin = (uint32_t) bsp_section_data_begin,
      .end = (uint32_t) bsp_section_data_end,
      .flags = LPC32XX_MMU_READ_WRITE_DATA
    }, {
      .begin = (uint32_t) bsp_section_fast_begin,
      .end = (uint32_t) bsp_section_fast_end,
      .flags = LPC32XX_MMU_CODE
    }, {
      .begin = (uint32_t) bsp_section_bss_begin,
      .end = (uint32_t) bsp_section_bss_end,
      .flags = LPC32XX_MMU_READ_WRITE_DATA
    }, {
      .begin = (uint32_t) bsp_section_work_begin,
      .end = (uint32_t) bsp_section_work_end,
      .flags = LPC32XX_MMU_READ_WRITE_DATA
    }, {
      .begin = (uint32_t) bsp_section_stack_begin,
      .end = (uint32_t) bsp_section_stack_end,
      .flags = LPC32XX_MMU_READ_WRITE_DATA
    }, {
      .begin = 0x0U,
      .end = 0x100000U,
      .flags = LPC32XX_MMU_READ_ONLY_CACHED
    }, {
      .begin = 0x20000000U,
      .end = 0x200c0000U,
      .flags = LPC32XX_MMU_READ_WRITE
    }, {
      .begin = 0x30000000U,
      .end = 0x32000000U,
      .flags = LPC32XX_MMU_READ_WRITE
    }, {
      .begin = 0x40000000U,
      .end = 0x40100000U,
      .flags = LPC32XX_MMU_READ_WRITE
    }
  };

  static void BSP_START_SECTION lpc32xx_mmu_set_entries(
    uint32_t *ttb,
    const lpc32xx_mmu_config *config
  )
  {
    uint32_t i = ARM_MMU_SECT_GET_INDEX(config->begin);
    uint32_t iend =
      ARM_MMU_SECT_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(config->end));

    if (config->begin != config->end) {
      while (i < iend) {
        ttb [i] = (i << ARM_MMU_SECT_BASE_SHIFT) | config->flags;
        ++i;
      }
    }
  }

  static void BSP_START_SECTION
    lpc32xx_setup_translation_table_and_enable_mmu(uint32_t ctrl)
  {
    uint32_t const dac =
      ARM_CP15_DAC_DOMAIN(LPC32XX_MMU_CLIENT_DOMAIN, ARM_CP15_DAC_CLIENT);
    uint32_t *const ttb = (uint32_t *) bsp_section_work_end;
    size_t const config_entry_count =
      sizeof(lpc32xx_mmu_config_table) / sizeof(lpc32xx_mmu_config_table [0]);
    size_t i = 0;

    arm_cp15_set_domain_access_control(dac);
    arm_cp15_set_translation_table_base(ttb);

    /* Initialize translation table with invalid entries */
    for (i = 0; i < ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT; ++i) {
      ttb [i] = 0;
    }

    for (i = 0; i < config_entry_count; ++i) {
      lpc32xx_mmu_set_entries(ttb, &lpc32xx_mmu_config_table [i]);
    }

    /* Enable MMU and cache */
    ctrl |= ARM_CP15_CTRL_I | ARM_CP15_CTRL_C | ARM_CP15_CTRL_M;
    arm_cp15_set_control(ctrl);
  }
#endif

static void BSP_START_SECTION lpc32xx_mmu_and_cache_setup(void)
{
  uint32_t ctrl = 0;

  /* Disable MMU and cache, basic settings */
  ctrl = arm_cp15_get_control();
  ctrl &= ~(ARM_CP15_CTRL_I | ARM_CP15_CTRL_R | ARM_CP15_CTRL_C
    | ARM_CP15_CTRL_V | ARM_CP15_CTRL_M);
  ctrl |= ARM_CP15_CTRL_S | ARM_CP15_CTRL_A;
  arm_cp15_set_control(ctrl);

  arm_cp15_cache_invalidate();
  arm_cp15_tlb_invalidate();

  #ifndef LPC32XX_DISABLE_MMU
    lpc32xx_setup_translation_table_and_enable_mmu(ctrl);
  #endif
}

void BSP_START_SECTION bsp_start_hook_0(void)
{
  lpc32xx_mmu_and_cache_setup();
}

static void BSP_START_SECTION bsp_start_config_uarts(void)
{
  uint32_t uartclk_ctrl = 0;

  #ifdef LPC32XX_CONFIG_U3CLK
    uartclk_ctrl |= 1U << 0;
    LPC32XX_U3CLK = LPC32XX_CONFIG_U3CLK;
  #endif
  #ifdef LPC32XX_CONFIG_U4CLK
    uartclk_ctrl |= 1U << 1;
    LPC32XX_U4CLK = LPC32XX_CONFIG_U4CLK;
  #endif
  #ifdef LPC32XX_CONFIG_U5CLK
    uartclk_ctrl |= 1U << 2;
    LPC32XX_U5CLK = LPC32XX_CONFIG_U5CLK;
  #endif
  #ifdef LPC32XX_CONFIG_U6CLK
    uartclk_ctrl |= 1U << 3;
    LPC32XX_U6CLK = LPC32XX_CONFIG_U6CLK;
  #endif

  #ifdef LPC32XX_CONFIG_UART_CLKMODE
    LPC32XX_UART_CLKMODE = LPC32XX_CONFIG_UART_CLKMODE;
  #endif

  LPC32XX_UARTCLK_CTRL = uartclk_ctrl;
  LPC32XX_UART_CTRL = 0x0;
  LPC32XX_UART_LOOP = 0x0;

  #ifdef LPC32XX_CONFIG_U5CLK
    /* Clock is already set in LPC32XX_U5CLK */
    BSP_CONSOLE_UART_INIT(0x01);
  #endif
}

void BSP_START_SECTION bsp_start_hook_1(void)
{
  bsp_start_config_uarts();

  /* Copy .text section */
  arm_cp15_instruction_cache_invalidate();
  bsp_start_memcpy(
    (int *) bsp_section_text_begin,
    (const int *) bsp_section_text_load_begin,
    (size_t) bsp_section_text_size
  );

  /* Copy .rodata section */
  arm_cp15_instruction_cache_invalidate();
  bsp_start_memcpy(
    (int *) bsp_section_rodata_begin,
    (const int *) bsp_section_rodata_load_begin,
    (size_t) bsp_section_rodata_size
  );

  /* Copy .data section */
  arm_cp15_instruction_cache_invalidate();
  bsp_start_memcpy(
    (int *) bsp_section_data_begin,
    (const int *) bsp_section_data_load_begin,
    (size_t) bsp_section_data_size
  );

  /* Copy .fast section */
  arm_cp15_instruction_cache_invalidate();
  bsp_start_memcpy(
    (int *) bsp_section_fast_begin,
    (const int *) bsp_section_fast_load_begin,
    (size_t) bsp_section_fast_size
  );

  /* Clear .bss section */
  lpc32xx_clear_bss();

  /* At this point we can use objects outside the .start section */
}