diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-20 10:35:35 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-20 13:52:14 +0200 |
commit | 99648958668d3a33ee57974479b36201fe303f34 (patch) | |
tree | 6f27ea790e2823c6156e71219a4f54680263fac6 /bsps/arm | |
parent | bsps: Move start files to bsps (diff) | |
download | rtems-99648958668d3a33ee57974479b36201fe303f34.tar.bz2 |
bsps: Move startup files to bsps
Adjust build support files to new directory layout.
This patch is a part of the BSP source reorganization.
Update #3285.
Diffstat (limited to 'bsps/arm')
173 files changed, 11254 insertions, 0 deletions
diff --git a/bsps/arm/altera-cyclone-v/start/bsp_specs b/bsps/arm/altera-cyclone-v/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/altera-cyclone-v/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/altera-cyclone-v/start/bspclean.c b/bsps/arm/altera-cyclone-v/start/bspclean.c new file mode 100644 index 0000000000..8b95deb801 --- /dev/null +++ b/bsps/arm/altera-cyclone-v/start/bspclean.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <rtems/bspIo.h> +#include <rtems/score/smpimpl.h> + +void bsp_fatal_extension( + rtems_fatal_source src, + bool always_set_to_false, + rtems_fatal_code code +) +{ +#ifdef RTEMS_SMP + if (src == RTEMS_FATAL_SOURCE_SMP && code == SMP_FATAL_SHUTDOWN_RESPONSE) { + while (true) { + _ARM_Wait_for_event(); + } + } +#endif + +#if BSP_PRINT_EXCEPTION_CONTEXT + if (src == RTEMS_FATAL_SOURCE_EXCEPTION) { + rtems_exception_frame_print((const rtems_exception_frame *) code); + } +#endif + +#if BSP_RESET_BOARD_AT_EXIT + bsp_reset(); +#endif +} diff --git a/bsps/arm/altera-cyclone-v/start/bspgetworkarea.c b/bsps/arm/altera-cyclone-v/start/bspgetworkarea.c new file mode 100644 index 0000000000..a3c702de98 --- /dev/null +++ b/bsps/arm/altera-cyclone-v/start/bspgetworkarea.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2017 embedded brains GmbH + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/bootcard.h> +#include <bsp/arm-cp15-start.h> +#include <bsp/fdt.h> +#include <bsp/linker-symbols.h> + +#include <libcpu/arm-cp15.h> + +#include <libfdt.h> + +#define AREA_COUNT_MAX 16 + +static const char memory_path[] = "/memory"; + +static const char reserved_memory_path[] = "/reserved-memory"; + +static void adjust_memory_size(const void *fdt, Heap_Area *area) +{ + int node; + + node = fdt_path_offset_namelen( + fdt, + memory_path, + (int) sizeof(memory_path) - 1 + ); + + if (node >= 0) { + int len; + const void *val; + uintptr_t begin; + uintptr_t size; + uintptr_t a_bit; + + val = fdt_getprop(fdt, node, "reg", &len); + if (len == 8) { + begin = fdt32_to_cpu(((fdt32_t *) val)[0]); + size = fdt32_to_cpu(((fdt32_t *) val)[1]); + } else { + begin = 0; + size = 0; + } + + /* + * Remove a bit to avoid problems with speculative memory accesses beyond + * the valid memory area. + */ + a_bit = 0x100000; + if (size >= a_bit) { + size -= a_bit; + } + + if ( + begin == 0 + && size > (uintptr_t) bsp_section_work_end + && (uintptr_t) bsp_section_nocache_end + < (uintptr_t) bsp_section_work_end + ) { + area->size += size - (uintptr_t) bsp_section_work_end; + } + } +} + +static Heap_Area *find_area( + Heap_Area *areas, + size_t area_count, + uint32_t begin +) +{ + size_t i; + + for (i = 0; i < area_count; ++i) { + uintptr_t b; + uintptr_t e; + + b = (uintptr_t) areas[i].begin; + e = b + (uintptr_t) areas[i].size; + + if (b <= begin && begin < e) { + return &areas[i]; + } + } + + return NULL; +} + +static size_t remove_reserved_memory( + const void *fdt, + Heap_Area *areas, + size_t area_count +) +{ + int node; + + node = fdt_path_offset_namelen( + fdt, + reserved_memory_path, + (int) sizeof(reserved_memory_path) - 1 + ); + + if (node >= 0) { + node = fdt_first_subnode(fdt, node); + + while (node >= 0) { + int len; + const void *val; + uintptr_t area_begin; + uintptr_t area_end; + uintptr_t hole_begin; + uintptr_t hole_end; + Heap_Area *area; + + val = fdt_getprop(fdt, node, "reg", &len); + if (len == 8) { + hole_begin = fdt32_to_cpu(((fdt32_t *) val)[0]); + hole_end = hole_begin + fdt32_to_cpu(((fdt32_t *) val)[1]); + } else { + rtems_panic("unexpected reserved memory area"); + } + + area = find_area(areas, area_count, hole_begin); + area_begin = (uintptr_t) area->begin; + area_end = area_begin + (uintptr_t) area->size; + area->size = hole_begin - area_begin; + + if (hole_end <= area_end) { + if (area_count >= AREA_COUNT_MAX) { + rtems_panic("too many reserved memory areas"); + } + + area = &areas[area_count]; + ++area_count; + area->begin = (void *) hole_end; + area->size = area_end - hole_end; + } + + node = fdt_next_subnode(fdt, node); + } + } + + return area_count; +} + +void bsp_work_area_initialize(void) +{ + const void *fdt; + Heap_Area areas[AREA_COUNT_MAX]; + size_t area_count; + size_t i; + + areas[0].begin = bsp_section_work_begin; + areas[0].size = (uintptr_t) bsp_section_work_size; + area_count = 1; + + fdt = bsp_fdt_get(); + + adjust_memory_size(fdt, &areas[0]); + area_count = remove_reserved_memory(fdt, areas, area_count); + + for (i = 0; i < area_count; ++i) { + arm_cp15_set_translation_table_entries( + areas[i].begin, + (void *) ((uintptr_t) areas[i].begin + areas[i].size), + ARMV7_MMU_READ_WRITE_CACHED + ); + } + + bsp_work_area_initialize_with_table(areas, area_count); +} diff --git a/bsps/arm/altera-cyclone-v/start/bspreset.c b/bsps/arm/altera-cyclone-v/start/bspreset.c new file mode 100644 index 0000000000..c4af106fed --- /dev/null +++ b/bsps/arm/altera-cyclone-v/start/bspreset.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <bsp/bootcard.h> +#include <bsp/alt_reset_manager.h> + +void bsp_reset(void) +{ + alt_reset_cold_reset(); +} diff --git a/bsps/arm/altera-cyclone-v/start/bspsmp.c b/bsps/arm/altera-cyclone-v/start/bspsmp.c new file mode 100644 index 0000000000..9c3c9dcffe --- /dev/null +++ b/bsps/arm/altera-cyclone-v/start/bspsmp.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <rtems/score/smpimpl.h> + +#include <bsp/start.h> + +#include <bsp/socal/alt_rstmgr.h> +#include <bsp/socal/alt_sysmgr.h> +#include <bsp/socal/hps.h> +#include <bsp/socal/socal.h> + +bool _CPU_SMP_Start_processor(uint32_t cpu_index) +{ + bool started; + + if (cpu_index == 1) { + alt_write_word( + ALT_SYSMGR_ROMCODE_ADDR + ALT_SYSMGR_ROMCODE_CPU1STARTADDR_OFST, + ALT_SYSMGR_ROMCODE_CPU1STARTADDR_VALUE_SET((uint32_t) _start) + ); + + alt_clrbits_word( + ALT_RSTMGR_MPUMODRST_ADDR, + ALT_RSTMGR_MPUMODRST_CPU1_SET_MSK + ); + + /* + * Wait for secondary processor to complete its basic initialization so + * that we can enable the unified L2 cache. + */ + started = _Per_CPU_State_wait_for_non_initial_state(cpu_index, 0); + } else { + started = false; + } + + return started; +} diff --git a/bsps/arm/altera-cyclone-v/start/bspstart.c b/bsps/arm/altera-cyclone-v/start/bspstart.c new file mode 100644 index 0000000000..0345a4c0a7 --- /dev/null +++ b/bsps/arm/altera-cyclone-v/start/bspstart.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2013, 2018 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <bsp/bootcard.h> +#include <bsp/arm-a9mpcore-clock.h> +#include <bsp/fdt.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> + +#include <bsp/alt_clock_manager.h> + +#include <libfdt.h> + +uint32_t bsp_fdt_map_intr(const uint32_t *intr, size_t icells) +{ + return intr[1] + 32; +} + +static void set_clock( + const void *fdt, + int parent, + ALT_CLK_t clk, + const char *name +) +{ + int node; + int len; + const uint32_t *val; + + node = fdt_subnode_offset(fdt, parent, name); + val = fdt_getprop(fdt, node, "clock-frequency", &len); + + if (val != NULL && len >= 4) { + alt_clk_ext_clk_freq_set(clk, fdt32_to_cpu(val[0])); + } +} + +static void set_clock_by_output_name( + const void *fdt, + ALT_CLK_t clk, + const char *clock_output_name +) +{ + int node; + int len; + const uint32_t *val; + + node = fdt_node_offset_by_prop_value( + fdt, + -1, + "clock-output-names", + clock_output_name, + strlen(clock_output_name) + 1 + ); + val = fdt_getprop(fdt, node, "clock-frequency", &len); + + if (val != NULL && len >= 4) { + alt_clk_ext_clk_freq_set(clk, fdt32_to_cpu(val[0])); + } +} + +static void update_clocks(void) +{ + const void *fdt; + int parent; + + fdt = bsp_fdt_get(); + + /* Try to set by node name */ + parent = fdt_node_offset_by_compatible(fdt, -1, "altr,clk-mgr"); + parent = fdt_subnode_offset(fdt, parent, "clocks"); + set_clock(fdt, parent, ALT_CLK_OSC1, "osc1"); + set_clock(fdt, parent, ALT_CLK_IN_PIN_OSC2, "osc2"); + set_clock(fdt, parent, ALT_CLK_F2H_PERIPH_REF, "f2s_periph_ref_clk"); + set_clock(fdt, parent, ALT_CLK_F2H_SDRAM_REF, "f2s_sdram_ref_clk"); + + /* Try to set by "clock-output-names" property value */ + set_clock_by_output_name(fdt, ALT_CLK_OSC1, "hps_0_eosc1-clk"); + set_clock_by_output_name(fdt, ALT_CLK_IN_PIN_OSC2, "hps_0_eosc2-clk"); + set_clock_by_output_name(fdt, ALT_CLK_F2H_PERIPH_REF, "hps_0_f2s_periph_ref_clk-clk"); + set_clock_by_output_name(fdt, ALT_CLK_F2H_SDRAM_REF, "hps_0_f2s_sdram_ref_clk-clk"); +} + +void bsp_start(void) +{ + update_clocks(); + a9mpcore_clock_initialize_early(); + bsp_interrupt_initialize(); + rtems_cache_coherent_add_area( + bsp_section_nocacheheap_begin, + (uintptr_t) bsp_section_nocacheheap_size + ); +} diff --git a/bsps/arm/altera-cyclone-v/start/bspstarthooks.c b/bsps/arm/altera-cyclone-v/start/bspstarthooks.c new file mode 100644 index 0000000000..69a178e3ad --- /dev/null +++ b/bsps/arm/altera-cyclone-v/start/bspstarthooks.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#define ARM_CP15_TEXT_SECTION BSP_START_TEXT_SECTION + +#include <bsp.h> +#include <bsp/start.h> +#include <bsp/arm-cp15-start.h> +#include <bsp/arm-a9mpcore-start.h> +#include <bsp/linker-symbols.h> +#include <bsp/alt_address_space.h> +#include <bsp/socal/socal.h> +#include <bsp/socal/alt_sdr.h> +#include <bsp/socal/hps.h> + +/* 1 MB reset default value for address filtering start */ +#define BSPSTART_L2_CACHE_ADDR_FILTERING_START_RESET 0x100000 + +BSP_START_TEXT_SECTION void bsp_start_hook_0( void ) +{ + arm_cp15_instruction_cache_invalidate(); + arm_cp15_data_cache_invalidate_all_levels(); + arm_a9mpcore_start_hook_0(); +} + +BSP_START_TEXT_SECTION static void setup_mmu_and_cache(void) +{ + uint32_t ctrl = arm_cp15_start_setup_mmu_and_cache( + ARM_CP15_CTRL_A | ARM_CP15_CTRL_M, + ARM_CP15_CTRL_AFE | ARM_CP15_CTRL_Z + ); + + arm_cp15_start_setup_translation_table_and_enable_mmu_and_cache( + ctrl, + (uint32_t *) bsp_translation_table_base, + ARM_MMU_DEFAULT_CLIENT_DOMAIN, + &arm_cp15_start_mmu_config_table[0], + arm_cp15_start_mmu_config_table_size + ); +} + +BSP_START_TEXT_SECTION void bsp_start_hook_1( void ) +{ + uint32_t addr_filt_start; + uint32_t addr_filt_end; + + /* Disable ECC. Preloader respectively UBoot enable ECC. + But they do run without interrupts. Our BSP will enable interrupts + and get spurious ECC error interrupts. Thus we disasable ECC + until we either know about a better handling or Altera has modified + it's SDRAM settings to not create possibly false ECC errors */ + uint32_t ctlcfg = alt_read_word( ALT_SDR_CTL_CTLCFG_ADDR ); + ctlcfg &= ALT_SDR_CTL_CTLCFG_ECCEN_CLR_MSK; + alt_write_word( ALT_SDR_CTL_CTLCFG_ADDR, ctlcfg ); + + /* Perform L3 remap register programming first by setting the desired new MPU + address space 0 mapping. Assume BOOTROM in order to be able to boot the + second core. */ + alt_addr_space_remap( + ALT_ADDR_SPACE_MPU_ZERO_AT_BOOTROM, + ALT_ADDR_SPACE_NONMPU_ZERO_AT_SDRAM, + ALT_ADDR_SPACE_H2F_ACCESSIBLE, + ALT_ADDR_SPACE_LWH2F_ACCESSIBLE ); + + /* Next, adjust the L2 cache address filtering range. Set the start address + * to the default reset value and retain the existing end address + * configuration. */ + alt_l2_addr_filter_cfg_get( &addr_filt_start, &addr_filt_end ); + + if ( addr_filt_start != BSPSTART_L2_CACHE_ADDR_FILTERING_START_RESET ) { + alt_l2_addr_filter_cfg_set( BSPSTART_L2_CACHE_ADDR_FILTERING_START_RESET, + addr_filt_end ); + } + + arm_a9mpcore_start_hook_1(); + bsp_start_copy_sections(); + setup_mmu_and_cache(); +#ifndef RTEMS_SMP + /* Enable unified L2 cache */ + rtems_cache_enable_data(); +#endif + bsp_start_clear_bss(); +} diff --git a/bsps/arm/altera-cyclone-v/start/linkcmds.altcycv b/bsps/arm/altera-cyclone-v/start/linkcmds.altcycv new file mode 100644 index 0000000000..810c4eb1b8 --- /dev/null +++ b/bsps/arm/altera-cyclone-v/start/linkcmds.altcycv @@ -0,0 +1,29 @@ +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_VECTOR", RAM); +REGION_ALIAS ("REGION_TEXT", RAM); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_RODATA", RAM); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", NOCACHE); + +bsp_stack_irq_size = DEFINED (bsp_stack_irq_size) ? bsp_stack_irq_size : 4096; +bsp_stack_abt_size = DEFINED (bsp_stack_abt_size) ? bsp_stack_abt_size : 1024; + +bsp_section_rwbarrier_align = DEFINED (bsp_section_rwbarrier_align) ? bsp_section_rwbarrier_align : 1M; + +bsp_vector_table_in_start_section = 1; + +bsp_translation_table_base = ORIGIN (RAM_MMU); +bsp_translation_table_end = ORIGIN (RAM_MMU) + LENGTH (RAM_MMU); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/altera-cyclone-v/start/linkcmds.altcycv_devkit b/bsps/arm/altera-cyclone-v/start/linkcmds.altcycv_devkit new file mode 100644 index 0000000000..546db0e123 --- /dev/null +++ b/bsps/arm/altera-cyclone-v/start/linkcmds.altcycv_devkit @@ -0,0 +1,7 @@ +MEMORY { + RAM_MMU : ORIGIN = 0x00100000, LENGTH = 16k + NOCACHE : ORIGIN = 0x00200000, LENGTH = 1M + RAM : ORIGIN = 0x00300000, LENGTH = 256M - 1M - 1M - 1M +} + +INCLUDE linkcmds.altcycv diff --git a/bsps/arm/altera-cyclone-v/start/linkcmds.altcycv_devkit_smp b/bsps/arm/altera-cyclone-v/start/linkcmds.altcycv_devkit_smp new file mode 100644 index 0000000000..2da086579f --- /dev/null +++ b/bsps/arm/altera-cyclone-v/start/linkcmds.altcycv_devkit_smp @@ -0,0 +1,3 @@ +bsp_processor_count = DEFINED (bsp_processor_count) ? bsp_processor_count : 2; + +INCLUDE linkcmds.altcycv_devkit diff --git a/bsps/arm/altera-cyclone-v/start/mmu-config.c b/bsps/arm/altera-cyclone-v/start/mmu-config.c new file mode 100644 index 0000000000..9d56e5c8f5 --- /dev/null +++ b/bsps/arm/altera-cyclone-v/start/mmu-config.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <bsp/arm-cp15-start.h> + +const arm_cp15_start_section_config arm_cp15_start_mmu_config_table[] = { + ARMV7_CP15_START_DEFAULT_SECTIONS, + { /* Periphery area */ + .begin = 0xFC000000U, + .end = 0x00000000U, + .flags = ARMV7_MMU_DEVICE + } +}; + +const size_t arm_cp15_start_mmu_config_table_size = + RTEMS_ARRAY_SIZE(arm_cp15_start_mmu_config_table); diff --git a/bsps/arm/atsam/start/bsp_specs b/bsps/arm/atsam/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/atsam/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/atsam/start/bspstart.c b/bsps/arm/atsam/start/bspstart.c new file mode 100644 index 0000000000..b463bab696 --- /dev/null +++ b/bsps/arm/atsam/start/bspstart.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> + +#include <chip.h> + +RTEMS_STATIC_ASSERT( + PERIPH_COUNT_IRQn <= BSP_INTERRUPT_VECTOR_MAX, + PERIPH_COUNT_IRQn +); + +void bsp_start(void) +{ + bsp_interrupt_initialize(); + SCB_CleanDCache(); + SCB_InvalidateICache(); + rtems_cache_coherent_add_area( + bsp_section_nocacheheap_begin, + (uintptr_t) bsp_section_nocacheheap_size + ); +} diff --git a/bsps/arm/atsam/start/bspstarthooks.c b/bsps/arm/atsam/start/bspstarthooks.c new file mode 100644 index 0000000000..697ec88d67 --- /dev/null +++ b/bsps/arm/atsam/start/bspstarthooks.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2016 embedded brains GmbH Huber. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/start.h> +#include <bsp/pin-config.h> +#include <bsp/atsam-clock-config.h> + +#include <chip.h> +#include <include/board_lowlevel.h> +#include <include/board_memories.h> + +#define SIZE_0K 0 +#define SIZE_32K (32 * 1024) +#define SIZE_64K (64 * 1024) +#define SIZE_128K (128 * 1024) + +#define ITCMCR_SZ_0K 0x0 +#define ITCMCR_SZ_32K 0x6 +#define ITCMCR_SZ_64K 0x7 +#define ITCMCR_SZ_128K 0x8 + +static BSP_START_TEXT_SECTION void efc_send_command(uint32_t eefc) +{ + EFC->EEFC_FCR = eefc | EEFC_FCR_FKEY_PASSWD; +} + +static BSP_START_TEXT_SECTION void tcm_enable(void) +{ + SCB->ITCMCR |= SCB_ITCMCR_EN_Msk; + SCB->DTCMCR |= SCB_DTCMCR_EN_Msk; +} + +static BSP_START_TEXT_SECTION void tcm_disable(void) +{ + SCB->ITCMCR &= ~SCB_ITCMCR_EN_Msk; + SCB->DTCMCR &= ~SCB_DTCMCR_EN_Msk; +} + +static BSP_START_TEXT_SECTION bool tcm_setup_and_check_if_do_efc_config( + uintptr_t tcm_size, + uint32_t itcmcr_sz +) +{ + if (tcm_size == SIZE_0K && itcmcr_sz == ITCMCR_SZ_0K) { + tcm_disable(); + return false; + } else if (tcm_size == SIZE_32K && itcmcr_sz == ITCMCR_SZ_32K) { + tcm_enable(); + return false; + } else if (tcm_size == SIZE_64K && itcmcr_sz == ITCMCR_SZ_64K) { + tcm_enable(); + return false; + } else if (tcm_size == SIZE_128K && itcmcr_sz == ITCMCR_SZ_128K) { + tcm_enable(); + return false; + } else { + return true; + } +} + +static bool ATSAM_START_SRAM_SECTION sdram_settings_unchanged(void) +{ + return ( + (SDRAMC->SDRAMC_CR == BOARD_Sdram_Config.sdramc_cr) && + (SDRAMC->SDRAMC_TR == BOARD_Sdram_Config.sdramc_tr) && + (SDRAMC->SDRAMC_MDR == BOARD_Sdram_Config.sdramc_mdr) && + (SDRAMC->SDRAMC_CFR1 == BOARD_Sdram_Config.sdramc_cfr1) + ); +} + +static void ATSAM_START_SRAM_SECTION setup_CPU_and_SDRAM(void) +{ + SystemInit(); + if (!PMC_IsPeriphEnabled(ID_SDRAMC) || !sdram_settings_unchanged()) { + BOARD_ConfigureSdram(); + } +} + +static void configure_tcm(void) +{ + uintptr_t tcm_size; + uint32_t itcmcr_sz; + + tcm_size = (uintptr_t) atsam_memory_itcm_size; + itcmcr_sz = (SCB->ITCMCR & SCB_ITCMCR_SZ_Msk) >> SCB_ITCMCR_SZ_Pos; + + if (tcm_setup_and_check_if_do_efc_config(tcm_size, itcmcr_sz)) { + if (tcm_size == SIZE_128K) { + efc_send_command(EEFC_FCR_FCMD_SGPB | EEFC_FCR_FARG(7)); + efc_send_command(EEFC_FCR_FCMD_SGPB | EEFC_FCR_FARG(8)); + tcm_enable(); + } else if (tcm_size == SIZE_64K) { + efc_send_command(EEFC_FCR_FCMD_CGPB | EEFC_FCR_FARG(7)); + efc_send_command(EEFC_FCR_FCMD_SGPB | EEFC_FCR_FARG(8)); + tcm_enable(); + } else if (tcm_size == SIZE_32K) { + efc_send_command(EEFC_FCR_FCMD_SGPB | EEFC_FCR_FARG(7)); + efc_send_command(EEFC_FCR_FCMD_CGPB | EEFC_FCR_FARG(8)); + tcm_enable(); + } else { + efc_send_command(EEFC_FCR_FCMD_CGPB | EEFC_FCR_FARG(7)); + efc_send_command(EEFC_FCR_FCMD_CGPB | EEFC_FCR_FARG(8)); + tcm_disable(); + } + } +} + +void BSP_START_TEXT_SECTION bsp_start_hook_0(void) +{ + system_init_flash(BOARD_MCK); + + PIO_Configure(&atsam_pin_config[0], atsam_pin_config_count); + MATRIX->CCFG_SYSIO = atsam_matrix_ccfg_sysio; + + configure_tcm(); +#if ATSAM_CHANGE_CLOCK_FROM_SRAM != 0 + /* Early copy of .fast_text section for CPU and SDRAM setup. */ + bsp_start_memcpy_libc( + bsp_section_fast_text_begin, + bsp_section_fast_text_load_begin, + (size_t) bsp_section_fast_text_size + ); +#endif + setup_CPU_and_SDRAM(); + + if ((SCB->CCR & SCB_CCR_IC_Msk) == 0) { + SCB_EnableICache(); + } + + if ((SCB->CCR & SCB_CCR_DC_Msk) == 0) { + SCB_EnableDCache(); + } + + _SetupMemoryRegion(); +} + +void BSP_START_TEXT_SECTION bsp_start_hook_1(void) +{ + bsp_start_copy_sections_compact(); + SCB_CleanDCache(); + SCB_InvalidateICache(); + bsp_start_clear_bss(); + WDT_Disable(WDT); +} diff --git a/bsps/arm/atsam/start/getentropy-trng.c b/bsps/arm/atsam/start/getentropy-trng.c new file mode 100644 index 0000000000..11e24dcda1 --- /dev/null +++ b/bsps/arm/atsam/start/getentropy-trng.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 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.org/license/LICENSE. + */ + +#include <libchip/chip.h> +#include <unistd.h> +#include <string.h> +#include <rtems/sysinit.h> + +static void atsam_trng_enable(void) +{ + PMC_EnablePeripheral(ID_TRNG); + TRNG_Enable(); +} + +int getentropy(void *ptr, size_t n) +{ + while (n > 0) { + uint32_t random; + size_t copy; + + while ((TRNG_GetStatus() & TRNG_ISR_DATRDY) == 0) { + /* wait */ + } + random = TRNG_GetRandData(); + + /* + * Read TRNG status one more time to avoid race condition. + * Otherwise we can read (and clear) an old ready status but get + * a new value. The ready status for this value wouldn't be + * reset. + */ + TRNG_GetStatus(); + + copy = sizeof(random); + if (n < copy ) { + copy = n; + } + memcpy(ptr, &random, copy); + n -= copy; + ptr += copy; + } + + return 0; +} + +RTEMS_SYSINIT_ITEM( + atsam_trng_enable, + RTEMS_SYSINIT_DEVICE_DRIVERS, + RTEMS_SYSINIT_ORDER_LAST +); diff --git a/bsps/arm/atsam/start/linkcmds b/bsps/arm/atsam/start/linkcmds new file mode 100644 index 0000000000..79cdfc2b18 --- /dev/null +++ b/bsps/arm/atsam/start/linkcmds @@ -0,0 +1,21 @@ +INCLUDE linkcmds.memory + +REGION_ALIAS ("REGION_START", INTFLASH); +REGION_ALIAS ("REGION_VECTOR", INTSRAM); +REGION_ALIAS ("REGION_TEXT", INTFLASH); +REGION_ALIAS ("REGION_TEXT_LOAD", INTFLASH); +REGION_ALIAS ("REGION_RODATA", INTFLASH); +REGION_ALIAS ("REGION_RODATA_LOAD", INTFLASH); +REGION_ALIAS ("REGION_DATA", INTSRAM); +REGION_ALIAS ("REGION_DATA_LOAD", INTFLASH); +REGION_ALIAS ("REGION_FAST_TEXT", ITCM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", INTFLASH); +REGION_ALIAS ("REGION_FAST_DATA", DTCM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", INTFLASH); +REGION_ALIAS ("REGION_BSS", INTSRAM); +REGION_ALIAS ("REGION_WORK", INTSRAM); +REGION_ALIAS ("REGION_STACK", INTSRAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", INTFLASH); + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/atsam/start/linkcmds.intsram b/bsps/arm/atsam/start/linkcmds.intsram new file mode 100644 index 0000000000..3e9d07e61c --- /dev/null +++ b/bsps/arm/atsam/start/linkcmds.intsram @@ -0,0 +1,23 @@ +INCLUDE linkcmds.memory + +bsp_vector_table_in_start_section = 1; + +REGION_ALIAS ("REGION_START", INTSRAM); +REGION_ALIAS ("REGION_VECTOR", INTSRAM); +REGION_ALIAS ("REGION_TEXT", INTSRAM); +REGION_ALIAS ("REGION_TEXT_LOAD", INTSRAM); +REGION_ALIAS ("REGION_RODATA", INTSRAM); +REGION_ALIAS ("REGION_RODATA_LOAD", INTSRAM); +REGION_ALIAS ("REGION_DATA", INTSRAM); +REGION_ALIAS ("REGION_DATA_LOAD", INTSRAM); +REGION_ALIAS ("REGION_FAST_TEXT", ITCM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", INTSRAM); +REGION_ALIAS ("REGION_FAST_DATA", DTCM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", INTSRAM); +REGION_ALIAS ("REGION_BSS", INTSRAM); +REGION_ALIAS ("REGION_WORK", INTSRAM); +REGION_ALIAS ("REGION_STACK", INTSRAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", INTSRAM); + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/atsam/start/linkcmds.memory.in b/bsps/arm/atsam/start/linkcmds.memory.in new file mode 100644 index 0000000000..de4d818283 --- /dev/null +++ b/bsps/arm/atsam/start/linkcmds.memory.in @@ -0,0 +1,39 @@ +MEMORY { + ITCM : ORIGIN = 0x00000000, LENGTH = @ATSAM_MEMORY_TCM_SIZE@ + INTFLASH : ORIGIN = 0x00400000, LENGTH = @ATSAM_MEMORY_INTFLASH_SIZE@ + DTCM : ORIGIN = 0x20000000, LENGTH = @ATSAM_MEMORY_TCM_SIZE@ + INTSRAM : ORIGIN = 0x20400000, LENGTH = @ATSAM_MEMORY_INTSRAM_SIZE@ - 2 * @ATSAM_MEMORY_TCM_SIZE@ - @ATSAM_MEMORY_NOCACHE_SIZE@ + NOCACHE : ORIGIN = 0x20400000 + @ATSAM_MEMORY_INTSRAM_SIZE@ - 2 * @ATSAM_MEMORY_TCM_SIZE@ - @ATSAM_MEMORY_NOCACHE_SIZE@, LENGTH = @ATSAM_MEMORY_NOCACHE_SIZE@ + SDRAM : ORIGIN = 0x70000000, LENGTH = @ATSAM_MEMORY_SDRAM_SIZE@ + QSPIFLASH : ORIGIN = 0x80000000, LENGTH = @ATSAM_MEMORY_QSPIFLASH_SIZE@ +} + +/* Must be used only for MPU definitions */ + +atsam_memory_itcm_begin = ORIGIN (ITCM); +atsam_memory_itcm_end = ORIGIN (ITCM) + LENGTH (ITCM); +atsam_memory_itcm_size = LENGTH (ITCM); + +atsam_memory_intflash_begin = ORIGIN (INTFLASH); +atsam_memory_intflash_end = ORIGIN (INTFLASH) + LENGTH (INTFLASH); +atsam_memory_intflash_size = LENGTH (INTFLASH); + +atsam_memory_dtcm_begin = ORIGIN (DTCM); +atsam_memory_dtcm_end = ORIGIN (DTCM) + LENGTH (DTCM); +atsam_memory_dtcm_size = LENGTH (DTCM); + +atsam_memory_intsram_begin = ORIGIN (INTSRAM); +atsam_memory_intsram_end = ORIGIN (INTSRAM) + LENGTH (INTSRAM); +atsam_memory_intsram_size = LENGTH (INTSRAM); + +atsam_memory_nocache_begin = ORIGIN (NOCACHE); +atsam_memory_nocache_end = ORIGIN (NOCACHE) + LENGTH (NOCACHE); +atsam_memory_nocache_size = LENGTH (NOCACHE); + +atsam_memory_sdram_begin = ORIGIN (SDRAM); +atsam_memory_sdram_end = ORIGIN (SDRAM) + LENGTH (SDRAM); +atsam_memory_sdram_size = LENGTH (SDRAM); + +atsam_memory_qspiflash_begin = ORIGIN (QSPIFLASH); +atsam_memory_qspiflash_end = ORIGIN (QSPIFLASH) + LENGTH (QSPIFLASH); +atsam_memory_qspiflash_size = LENGTH (QSPIFLASH); diff --git a/bsps/arm/atsam/start/linkcmds.qspiflash b/bsps/arm/atsam/start/linkcmds.qspiflash new file mode 100644 index 0000000000..d7529f7484 --- /dev/null +++ b/bsps/arm/atsam/start/linkcmds.qspiflash @@ -0,0 +1,21 @@ +INCLUDE linkcmds.memory + +REGION_ALIAS ("REGION_START", QSPIFLASH); +REGION_ALIAS ("REGION_VECTOR", INTSRAM); +REGION_ALIAS ("REGION_TEXT", QSPIFLASH); +REGION_ALIAS ("REGION_TEXT_LOAD", QSPIFLASH); +REGION_ALIAS ("REGION_RODATA", QSPIFLASH); +REGION_ALIAS ("REGION_RODATA_LOAD", QSPIFLASH); +REGION_ALIAS ("REGION_DATA", INTSRAM); +REGION_ALIAS ("REGION_DATA_LOAD", QSPIFLASH); +REGION_ALIAS ("REGION_FAST_TEXT", ITCM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", QSPIFLASH); +REGION_ALIAS ("REGION_FAST_DATA", DTCM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", QSPIFLASH); +REGION_ALIAS ("REGION_BSS", INTSRAM); +REGION_ALIAS ("REGION_WORK", INTSRAM); +REGION_ALIAS ("REGION_STACK", INTSRAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", QSPIFLASH); + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/atsam/start/linkcmds.sdram b/bsps/arm/atsam/start/linkcmds.sdram new file mode 100644 index 0000000000..958b128c6a --- /dev/null +++ b/bsps/arm/atsam/start/linkcmds.sdram @@ -0,0 +1,21 @@ +INCLUDE linkcmds.memory + +REGION_ALIAS ("REGION_START", SDRAM); +REGION_ALIAS ("REGION_VECTOR", INTSRAM); +REGION_ALIAS ("REGION_TEXT", SDRAM); +REGION_ALIAS ("REGION_TEXT_LOAD", SDRAM); +REGION_ALIAS ("REGION_RODATA", SDRAM); +REGION_ALIAS ("REGION_RODATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_DATA", SDRAM); +REGION_ALIAS ("REGION_DATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_FAST_TEXT", ITCM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", SDRAM); +REGION_ALIAS ("REGION_FAST_DATA", DTCM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_BSS", SDRAM); +REGION_ALIAS ("REGION_WORK", SDRAM); +REGION_ALIAS ("REGION_STACK", SDRAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", SDRAM); + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/atsam/start/pin-config.c b/bsps/arm/atsam/start/pin-config.c new file mode 100644 index 0000000000..8a18ae8df7 --- /dev/null +++ b/bsps/arm/atsam/start/pin-config.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 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.org/license/LICENSE. + */ + +#include <bsp/pin-config.h> + +const Pin atsam_pin_config[] = { + /* Console */ + {PIO_PA21A_RXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}, + {PIO_PB4D_TXD1, PIOB, ID_PIOB, PIO_PERIPH_D, PIO_DEFAULT}, + + /* SDRAM */ + + /* D0_7 */ {0x000000FF, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_DEFAULT}, + /* D8_13 */ {0x0000003F, PIOE, ID_PIOE, PIO_PERIPH_A, PIO_DEFAULT}, + /* D14_15 */ {0x00018000, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}, + /* A0_9 */ {0x3FF00000, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_DEFAULT}, + /* SDA10 */ {0x00002000, PIOD, ID_PIOD, PIO_PERIPH_C, PIO_DEFAULT}, + /* CAS */ {0x00020000, PIOD, ID_PIOD, PIO_PERIPH_C, PIO_DEFAULT}, + /* RAS */ {0x00010000, PIOD, ID_PIOD, PIO_PERIPH_C, PIO_DEFAULT}, + /* SDCKE */ {0x00004000, PIOD, ID_PIOD, PIO_PERIPH_C, PIO_DEFAULT}, + /* SDCK */ {0x00800000, PIOD, ID_PIOD, PIO_PERIPH_C, PIO_DEFAULT}, + /* SDSC */ {0x00008000, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_DEFAULT}, + /* NBS0 */ {0x00040000, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_DEFAULT}, + /* NBS1 */ {0x00008000, PIOD, ID_PIOD, PIO_PERIPH_C, PIO_DEFAULT}, + /* SDWE */ {0x20000000, PIOD, ID_PIOD, PIO_PERIPH_C, PIO_DEFAULT}, + /* BA0 */ {0x00100000, PIOA, ID_PIOA, PIO_PERIPH_C, PIO_DEFAULT} +}; + +const size_t atsam_pin_config_count = PIO_LISTSIZE(atsam_pin_config); + +const uint32_t atsam_matrix_ccfg_sysio = 0x20400010; diff --git a/bsps/arm/atsam/start/pmc-config.c b/bsps/arm/atsam/start/pmc-config.c new file mode 100644 index 0000000000..41902d03dd --- /dev/null +++ b/bsps/arm/atsam/start/pmc-config.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 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.org/license/LICENSE. + */ + +#include <bsp/atsam-clock-config.h> +#include <bspopts.h> +#include <chip.h> + +#if ATSAM_MCK == 123000000 +/* PLLA/HCLK/MCK clock is set to 492/246/123MHz */ +const struct atsam_clock_config atsam_clock_config = { + .pllar_init = (CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0x28U) | + CKGR_PLLAR_PLLACOUNT(0x3fU) | CKGR_PLLAR_DIVA(0x1U)), + .mckr_init = (PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK | + PMC_MCKR_MDIV_PCK_DIV2), + .mck_freq = 123*1000*1000 +}; +#elif ATSAM_MCK == 150000000 +/* PLLA/HCLK/MCK clock is set to 300/300/150MHz */ +const struct atsam_clock_config atsam_clock_config = { + .pllar_init = (CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0x18U) | + CKGR_PLLAR_PLLACOUNT(0x3fU) | CKGR_PLLAR_DIVA(0x1U)), + .mckr_init = (PMC_MCKR_PRES_CLK_1 | PMC_MCKR_CSS_PLLA_CLK | + PMC_MCKR_MDIV_PCK_DIV2), + .mck_freq = 150*1000*1000 +}; +#elif ATSAM_MCK == 60000000 +/* PLLA/HCLK/MCK clock is set to 60/60/60MHz */ +const struct atsam_clock_config atsam_clock_config = { + .pllar_init = (CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0x4U) | + CKGR_PLLAR_PLLACOUNT(0x3fU) | CKGR_PLLAR_DIVA(0x1U)), + .mckr_init = (PMC_MCKR_PRES_CLK_1 | PMC_MCKR_CSS_PLLA_CLK | + PMC_MCKR_MDIV_EQ_PCK), + .mck_freq = 60*1000*1000 +}; +#error Unknown ATSAM_MCK. +#endif diff --git a/bsps/arm/atsam/start/power-clock.c b/bsps/arm/atsam/start/power-clock.c new file mode 100644 index 0000000000..e04933285e --- /dev/null +++ b/bsps/arm/atsam/start/power-clock.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/power.h> +#include <bsp/irq.h> + +#include <libchip/chip.h> + +#include <rtems/score/armv7m.h> + +void atsam_power_handler_clock_driver( + const atsam_power_control *control, + atsam_power_state state +) +{ + volatile ARMV7M_Systick *systick = _ARMV7M_Systick; + + (void) control; + + switch (state) { + case ATSAM_POWER_ON: + systick->csr = ARMV7M_SYSTICK_CSR_ENABLE | + ARMV7M_SYSTICK_CSR_TICKINT | + ARMV7M_SYSTICK_CSR_CLKSOURCE; + break; + case ATSAM_POWER_OFF: + systick->csr = 0; + break; + default: + break; + } +} diff --git a/bsps/arm/atsam/start/power-rtc.c b/bsps/arm/atsam/start/power-rtc.c new file mode 100644 index 0000000000..b60235ac29 --- /dev/null +++ b/bsps/arm/atsam/start/power-rtc.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/power.h> +#include <bsp/irq.h> + +#include <libchip/chip.h> + +#define ATSAM_ENABLE_ALARM_INTERRUPT (1u << 1) + +static void set_rtc_alarm_interrupt(uint8_t interval) +{ + Rtc *rtc = RTC; + rtems_time_of_day tod; + + /* Clear current status register */ + RTC_ClearSCCR(rtc, 0x3F); + + atsam_rtc_get_time(&tod); + tod.second = (tod.second + interval) % 60; + tod.second = (((tod.second / 10) << 4) | (tod.second % 10)); + + rtc->RTC_TIMALR &= ~RTC_TIMALR_SECEN; + rtc->RTC_TIMALR = tod.second; + rtc->RTC_TIMALR |= RTC_TIMALR_SECEN; + RTC_EnableIt(rtc, ATSAM_ENABLE_ALARM_INTERRUPT); +} + +static void rtc_interrupt_handler(void *arg) +{ + atsam_power_data_rtc_driver *rtc_data; + + rtc_data = (atsam_power_data_rtc_driver *)arg; + set_rtc_alarm_interrupt(rtc_data->interval); +} + +static void rtc_alarm_handler(void *arg) +{ + Rtc *rtc = RTC; + rtems_status_code sc; + + /* Clear current status register */ + RTC_ClearSCCR(rtc, 0x3F); + + /* Switch off all RTC interrupts */ + RTC_DisableIt(rtc, 0x1F); + + /* Install RTC interrupt handler */ + sc = rtems_interrupt_handler_install(RTC_IRQn, + "RTC", + RTEMS_INTERRUPT_UNIQUE, + rtc_interrupt_handler, + arg + ); + assert(sc == RTEMS_SUCCESSFUL); +} + +static void set_time(void) +{ + rtems_time_of_day tod; + rtems_status_code sc; + + atsam_rtc_get_time(&tod); + sc = rtems_clock_set(&tod); + assert(sc == RTEMS_SUCCESSFUL); +} + +void atsam_power_handler_rtc_driver( + const atsam_power_control *control, + atsam_power_state state +) +{ + atsam_power_data_rtc_driver *rtc_data; + Rtc *rtc = RTC; + + rtc_data = (atsam_power_data_rtc_driver *)control->data.arg; + + switch (state) { + case ATSAM_POWER_ON: + RTC_DisableIt(rtc, ATSAM_ENABLE_ALARM_INTERRUPT); + set_time(); + break; + case ATSAM_POWER_OFF: + set_rtc_alarm_interrupt(rtc_data->interval); + break; + case ATSAM_POWER_INIT: + rtc_alarm_handler(rtc_data); + break; + default: + break; + } +} diff --git a/bsps/arm/atsam/start/power.c b/bsps/arm/atsam/start/power.c new file mode 100644 index 0000000000..f9b5a3925d --- /dev/null +++ b/bsps/arm/atsam/start/power.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/power.h> +#include <bsp/irq.h> + +#include <libchip/chip.h> + +/* SCR Sleep deep bit */ +#define SCR_SLEEPDEEP (1u << 2) + +void atsam_power_change_state( + const atsam_power_control *controls, + size_t n, + atsam_power_state state +) +{ + size_t i; + + switch (state) { + case ATSAM_POWER_ON: + for (i = n; i > 0; --i) { + const atsam_power_control *c; + + c = &controls[i - 1]; + (*c->handler)(c, state); + } + + break; + case ATSAM_POWER_INIT: + case ATSAM_POWER_OFF: + for (i = 0; i < n; ++i) { + const atsam_power_control *c; + + c = &controls[i]; + (*c->handler)(c, state); + } + + break; + default: + break; + } +} + +void atsam_power_handler_peripheral( + const atsam_power_control *control, + atsam_power_state state +) +{ + uint32_t id; + uint32_t end; + + id = control->data.peripherals.first; + end = control->data.peripherals.last + 1; + + switch (state) { + case ATSAM_POWER_ON: + while (id != end) { + PMC_EnablePeripheral(id); + ++id; + } + break; + case ATSAM_POWER_OFF: + while (id != end) { + PMC_DisablePeripheral(id); + ++id; + } + break; + default: + break; + } +} + +void atsam_power_handler_sleep_mode(const atsam_power_control *control, atsam_power_state state) +{ + (void) control; + + switch (state) { + case ATSAM_POWER_OFF: + /* Enable Low Power Mode in the Fast Startup Mode Register */ + PMC->PMC_FSMR &= (uint32_t)~PMC_FSMR_LPM; + /* Do not set deep sleep, but "normal" sleep */ + SCB->SCR &= (uint32_t)~SCR_SLEEPDEEP; + + __asm__ volatile ("wfi"); + break; + default: + break; + } +} diff --git a/bsps/arm/atsam/start/restart.c b/bsps/arm/atsam/start/restart.c new file mode 100644 index 0000000000..9934fbd298 --- /dev/null +++ b/bsps/arm/atsam/start/restart.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 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.org/license/LICENSE. + */ + +#include <rtems.h> +#include <rtems/score/armv7m.h> +#include <bsp.h> + +static void ARMV7M_Systick_cleanup(void) +{ + volatile ARMV7M_Systick *systick = _ARMV7M_Systick; + systick->csr = 0; +} + +void bsp_restart( const void *const addr ) +{ + rtems_interrupt_level level; + void(*start)(void) = (void(*)(void))(addr); + + rtems_interrupt_disable(level); + (void)level; + rtems_cache_disable_instruction(); + rtems_cache_disable_data(); + rtems_cache_invalidate_entire_instruction(); + rtems_cache_invalidate_entire_data(); + ARMV7M_Systick_cleanup(); + + start(); +} diff --git a/bsps/arm/atsam/start/sdram-config.c b/bsps/arm/atsam/start/sdram-config.c new file mode 100644 index 0000000000..a2f1158377 --- /dev/null +++ b/bsps/arm/atsam/start/sdram-config.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 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.org/license/LICENSE. + */ + +#include <bspopts.h> +#include <chip.h> +#include <include/board_memories.h> + +#if defined ATSAM_SDRAM_IS42S16100E_7BLI + +#if ATSAM_MCK != 123000000 +#error Please check SDRAM settings for this clock frequency. +#endif + +const struct BOARD_Sdram_Config BOARD_Sdram_Config = { + /* FIXME: a lot of these values should be calculated using CPU frequency */ + .sdramc_tr = 1562, + .sdramc_cr = + SDRAMC_CR_NC_COL8 /* 8 column bits */ + | SDRAMC_CR_NR_ROW11 /* 12 row bits (4K) */ + | SDRAMC_CR_CAS_LATENCY3 /* CAS Latency 3 */ + | SDRAMC_CR_NB_BANK2 /* 2 banks */ + | SDRAMC_CR_DBW /* 16 bit */ + | SDRAMC_CR_TWR(5) + | SDRAMC_CR_TRC_TRFC(13) /* 63ns min */ + | SDRAMC_CR_TRP(5) /* Command period (PRE to ACT) 21 ns min */ + | SDRAMC_CR_TRCD(5) /* Active Command to R/W Cmd delay time 21ns min */ + | SDRAMC_CR_TRAS(9) /* Command period (ACT to PRE) 42ns min */ + | SDRAMC_CR_TXSR(15U), /* Exit self-refresh to active time 70ns Min */ + .sdramc_mdr = SDRAMC_MDR_MD_SDRAM, + .sdramc_cfr1 = SDRAMC_CFR1_UNAL_SUPPORTED | SDRAMC_CFR1_TMRD(2) +}; + +#elif defined ATSAM_SDRAM_IS42S16320F_7BL + +#if ATSAM_MCK != 123000000 +#error Please check SDRAM settings for this clock frequency. +#endif + +#define CLOCK_CYCLES_FROM_NS_MAX(ns) \ + (((ns) * (ATSAM_MCK / 1000ul / 1000ul)) / 1000ul) +#define CLOCK_CYCLES_FROM_NS_MIN(ns) (CLOCK_CYCLES_FROM_NS_MAX(ns) + 1) + +const struct BOARD_Sdram_Config BOARD_Sdram_Config = { + /* 8k refresh cycles every 64ms => 7.8125us */ + .sdramc_tr = CLOCK_CYCLES_FROM_NS_MAX(7812ul), + .sdramc_cr = + SDRAMC_CR_NC_COL10 + | SDRAMC_CR_NR_ROW13 + | SDRAMC_CR_CAS_LATENCY3 + | SDRAMC_CR_NB_BANK4 + | SDRAMC_CR_DBW + /* t_WR = 30ns min (t_RC - t_RP - t_RCD; + * see data sheet November 2015 page 55); + * add some security margin */ + | SDRAMC_CR_TWR(CLOCK_CYCLES_FROM_NS_MIN(40)) + | SDRAMC_CR_TRC_TRFC(CLOCK_CYCLES_FROM_NS_MIN(60)) + | SDRAMC_CR_TRP(CLOCK_CYCLES_FROM_NS_MIN(15)) + | SDRAMC_CR_TRCD(CLOCK_CYCLES_FROM_NS_MIN(15)) + | SDRAMC_CR_TRAS(CLOCK_CYCLES_FROM_NS_MIN(37)) + | SDRAMC_CR_TXSR(CLOCK_CYCLES_FROM_NS_MIN(67)), + .sdramc_mdr = SDRAMC_MDR_MD_SDRAM, + .sdramc_cfr1 = SDRAMC_CFR1_UNAL_SUPPORTED | + SDRAMC_CFR1_TMRD(CLOCK_CYCLES_FROM_NS_MIN(14)) +}; + +#elif defined ATSAM_SDRAM_MT48LC16M16A2P_6A + +/* + * Refresh: 7.81 us + * TWR: 12 ns + * TRC_TRFC: 60 ns + * TRP: 15 ns + * TRCD: 18 ns + * TRAS: 42 ns + * TXSR: 67 ns + * TMRD: 2 clock cycles + */ + +#if ATSAM_MCK == 60000000 +const struct BOARD_Sdram_Config BOARD_Sdram_Config = { + .sdramc_tr = 0x1D4, + .sdramc_cr = + SDRAMC_CR_NC_COL9 + | SDRAMC_CR_NR_ROW13 + | SDRAMC_CR_NB_BANK4 + | SDRAMC_CR_CAS_LATENCY3 + | SDRAMC_CR_DBW + | SDRAMC_CR_TWR(3) + | SDRAMC_CR_TRC_TRFC(8) + | SDRAMC_CR_TRP(3) + | SDRAMC_CR_TRCD(3) + | SDRAMC_CR_TRAS(5) + | SDRAMC_CR_TXSR(9), + .sdramc_mdr = SDRAMC_MDR_MD_SDRAM, + .sdramc_cfr1 = SDRAMC_CFR1_UNAL_SUPPORTED | + SDRAMC_CFR1_TMRD(2) +}; + +#elif ATSAM_MCK == 123000000 +const struct BOARD_Sdram_Config BOARD_Sdram_Config = { + .sdramc_tr = 960, + .sdramc_cr = + SDRAMC_CR_NC_COL9 + | SDRAMC_CR_NR_ROW13 + | SDRAMC_CR_NB_BANK4 + | SDRAMC_CR_CAS_LATENCY3 + | SDRAMC_CR_DBW + | SDRAMC_CR_TWR(2) + | SDRAMC_CR_TRC_TRFC(8) + | SDRAMC_CR_TRP(2) + | SDRAMC_CR_TRCD(3) + | SDRAMC_CR_TRAS(6) + | SDRAMC_CR_TXSR(9), + .sdramc_mdr = SDRAMC_MDR_MD_SDRAM, + .sdramc_cfr1 = SDRAMC_CFR1_UNAL_SUPPORTED | + SDRAMC_CFR1_TMRD(2) +}; + +#else /* ATSAM_MCK unknown */ +#error Please check SDRAM settings for this frequency. +#endif + +#else + #error SDRAM not supported. +#endif diff --git a/bsps/arm/beagle/start/bsp_specs b/bsps/arm/beagle/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/beagle/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/beagle/start/bspreset.c b/bsps/arm/beagle/start/bspreset.c new file mode 100644 index 0000000000..5865b7badf --- /dev/null +++ b/bsps/arm/beagle/start/bspreset.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014 Ben Gras <beng@shrike-systems.com>. All rights reserved. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +#define AM335X_CM_BASE 0x44E00000 +#define AM335X_CM_SIZE 0x1000 + +#define AM335X_PRM_DEVICE_OFFSET 0xf00 +#define AM335X_PRM_RSTCTRL_REG 0x00 +#define AM335X_RST_GLOBAL_WARM_SW_BIT 0 + +#define DM37XX_CM_BASE 0x48307000 +#define DM37XX_CM_SIZE 0x1000 +#define DM37XX_PRM_RSTCTRL_REG 0x250 +#define DM37XX_RST_DPLL3_BIT 2 + +void bsp_reset(void) +{ +#if IS_DM3730 + static uint32_t reset_base = DM37XX_CM_BASE; + while (true) { + mmio_set((reset_base + DM37XX_PRM_RSTCTRL_REG), + (1 << DM37XX_RST_DPLL3_BIT)); + } +#endif + +#if IS_AM335X + static uint32_t reset_base = AM335X_CM_BASE; + while (true) { + mmio_set((reset_base + AM335X_PRM_DEVICE_OFFSET + + AM335X_PRM_RSTCTRL_REG), + (1 << AM335X_RST_GLOBAL_WARM_SW_BIT)); + } +#endif +} diff --git a/bsps/arm/beagle/start/bspstart.c b/bsps/arm/beagle/start/bspstart.c new file mode 100644 index 0000000000..292b576aef --- /dev/null +++ b/bsps/arm/beagle/start/bspstart.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> +#include <bsp/fdt.h> + +void bsp_start(void) +{ +#if IS_DM3730 + const char* type = "dm3730-based"; +#endif +#if IS_AM335X + const char* type = "am335x-based"; +#endif + bsp_interrupt_initialize(); + printk("\nRTEMS Beagleboard: %s\n", type); +} + +uint32_t bsp_fdt_map_intr(const uint32_t *intr, size_t icells) +{ + return intr[0]; +} diff --git a/bsps/arm/beagle/start/bspstarthooks.c b/bsps/arm/beagle/start/bspstarthooks.c new file mode 100644 index 0000000000..2efa3042a8 --- /dev/null +++ b/bsps/arm/beagle/start/bspstarthooks.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/start.h> +#include <bsp/arm-cp15-start.h> +#include <bsp/arm-a8core-start.h> + +#include <bsp/uart-output-char.h> + +BSP_START_TEXT_SECTION void bsp_start_hook_0(void) +{ +} + +BSP_START_TEXT_SECTION void bsp_start_hook_1(void) +{ + arm_a8core_start_hook_1(); + bsp_start_copy_sections(); + beagle_setup_mmu_and_cache(); + bsp_start_clear_bss(); +} diff --git a/bsps/arm/beagle/start/bspstartmmu.c b/bsps/arm/beagle/start/bspstartmmu.c new file mode 100644 index 0000000000..157edfa0a7 --- /dev/null +++ b/bsps/arm/beagle/start/bspstartmmu.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@embedded-brains.de> + * + * Copyright (c) 2014 Chris Johns. All rights reserved. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/start.h> +#include <bsp/arm-cp15-start.h> + +#define ARM_SECTIONS 4096 /* all sections needed to describe the + virtual address space */ +#define ARM_SECTION_SIZE (1024 * 1024) /* how much virtual memory is described + by one section */ + +//static uint32_t pagetable[ARM_SECTIONS] __attribute__((aligned (1024*16))); + +BSP_START_DATA_SECTION static const arm_cp15_start_section_config +beagle_mmu_config_table[] = { + ARMV7_CP15_START_DEFAULT_SECTIONS, + { + .begin = 0x40000000U, + .end = 0x4FFFFFFFU, + .flags = ARMV7_MMU_DEVICE + } +}; + +/* + * Make weak and let the user override. + */ +BSP_START_TEXT_SECTION void beagle_setup_mmu_and_cache(void) __attribute__ ((weak)); + +BSP_START_TEXT_SECTION void beagle_setup_mmu_and_cache(void) +{ + /* turn mmu off first in case it's on */ + uint32_t ctrl = arm_cp15_start_setup_mmu_and_cache( + ARM_CP15_CTRL_M | ARM_CP15_CTRL_A, /* clear - mmu off */ + ARM_CP15_CTRL_AFE | ARM_CP15_CTRL_Z + ); + + arm_cp15_start_setup_translation_table_and_enable_mmu_and_cache( + ctrl, + (uint32_t *) bsp_translation_table_base, + ARM_MMU_DEFAULT_CLIENT_DOMAIN, + &beagle_mmu_config_table[0], + RTEMS_ARRAY_SIZE(beagle_mmu_config_table) + ); +} diff --git a/bsps/arm/beagle/start/linkcmds.beagle b/bsps/arm/beagle/start/linkcmds.beagle new file mode 100644 index 0000000000..20ea3eb195 --- /dev/null +++ b/bsps/arm/beagle/start/linkcmds.beagle @@ -0,0 +1,48 @@ +/** + * @file + * + * @ingroup arm_beagle + * + * @brief Linker script for beagles. + */ + +MEMORY { + /* Beagleboards and beaglebones all + * have either 256M or 512M memory. We just + * use 256M for all. + */ + RAM : ORIGIN = 0x80000000, LENGTH = 256M - 4M + RAM_MMU : ORIGIN = 0x80000000 + 256M - 4M, LENGTH = 16k +} + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_VECTOR", RAM); +REGION_ALIAS ("REGION_TEXT", RAM); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_RODATA", RAM); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", RAM); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM); + +bsp_stack_irq_size = DEFINED (bsp_stack_irq_size) ? bsp_stack_irq_size : 4096; +bsp_stack_abt_size = DEFINED (bsp_stack_abt_size) ? bsp_stack_abt_size : 1024; + +bsp_section_rwbarrier_align = DEFINED (bsp_section_rwbarrier_align) ? bsp_section_rwbarrier_align : 1M; + +bsp_vector_table_in_start_section = 1; + +bsp_translation_table_base = ORIGIN (RAM_MMU); +bsp_translation_table_end = ORIGIN (RAM_MMU) + LENGTH (RAM_MMU); + +INCLUDE linkcmds.armv4 + +HeapSize = 1024 * 1024; diff --git a/bsps/arm/csb336/start/bsp_specs b/bsps/arm/csb336/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/csb336/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/csb336/start/bspstart.c b/bsps/arm/csb336/start/bspstart.c new file mode 100644 index 0000000000..8970dfbe4a --- /dev/null +++ b/bsps/arm/csb336/start/bspstart.c @@ -0,0 +1,122 @@ +/* + * Cogent CSB336 - MC9328MXL SBC startup code + */ + +/* + * Copyright (c) 2004 by Cogent Computer Systems + * Written by Jay Monkman <jtm@lopingdog.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/irq-generic.h> +#include <rtems/bspIo.h> +#include <mc9328mxl.h> +#include <libcpu/mmu.h> + +/* + * bsp_start_default - BSP initialization function + * + * This function is called before RTEMS is initialized and used + * adjust the kernel's configuration. + * + * This function also configures the CPU's memory protection unit. + * + * RESTRICTIONS/LIMITATIONS: + * Since RTEMS is not configured, no RTEMS functions can be called. + * + */ +static void bsp_start_default( void ) +{ + int i; + + /* Set the MCU prescaler to divide by 1 */ + MC9328MXL_PLL_CSCR &= ~MC9328MXL_PLL_CSCR_PRESC; + + /* Enable the MCU PLL */ + MC9328MXL_PLL_CSCR |= MC9328MXL_PLL_CSCR_MPEN; + + /* Delay to allow time for PLL to get going */ + for (i = 0; i < 100; i++) { + __asm__ volatile ("nop\n"); + } + + /* Set the CPU to asynchrous clock mode, so it uses its fastest clock */ + mmu_set_cpu_async_mode(); + + /* disable interrupts */ + MC9328MXL_AITC_INTENABLEL = 0; + MC9328MXL_AITC_INTENABLEH = 0; + + /* Set interrupt priority to -1 (allow all priorities) */ + MC9328MXL_AITC_NIMASK = 0x1f; + + /* + * Init rtems interrupt management + */ + bsp_interrupt_initialize(); +} /* bsp_start */ + +/* Calcuate the frequency for perclk1 */ +int get_perclk1_freq(void) +{ + unsigned int fin; + unsigned int fpll; + unsigned int pd; + unsigned int mfd; + unsigned int mfi; + unsigned int mfn; + uint32_t reg; + int perclk1; + + if (MC9328MXL_PLL_CSCR & MC9328MXL_PLL_CSCR_SYSSEL) { + /* Use external oscillator */ + fin = BSP_OSC_FREQ; + } else { + /* Use scaled xtal freq */ + fin = BSP_XTAL_FREQ * 512; + } + + /* calculate the output of the system PLL */ + reg = MC9328MXL_PLL_SPCTL0; + pd = ((reg & MC9328MXL_PLL_SPCTL_PD_MASK) >> + MC9328MXL_PLL_SPCTL_PD_SHIFT); + mfd = ((reg & MC9328MXL_PLL_SPCTL_MFD_MASK) >> + MC9328MXL_PLL_SPCTL_MFD_SHIFT); + mfi = ((reg & MC9328MXL_PLL_SPCTL_MFI_MASK) >> + MC9328MXL_PLL_SPCTL_MFI_SHIFT); + mfn = ((reg & MC9328MXL_PLL_SPCTL_MFN_MASK) >> + MC9328MXL_PLL_SPCTL_MFN_SHIFT); + +#if 0 + printk("fin = %d\n", fin); + printk("pd = %d\n", pd); + printk("mfd = %d\n", mfd); + printk("mfi = %d\n", mfi); + printk("mfn = %d\n", mfn); + printk("rounded (fin * mfi) / (pd + 1) = %d\n", (fin * mfi) / (pd + 1)); + printk("rounded (fin * mfn) / ((pd + 1) * (mfd + 1)) = %d\n", + ((long long)fin * mfn) / ((pd + 1) * (mfd + 1))); +#endif + + fpll = 2 * ( ((fin * mfi + (pd + 1) / 2) / (pd + 1)) + + (((long long)fin * mfn + ((pd + 1) * (mfd + 1)) / 2) / + ((pd + 1) * (mfd + 1))) ); + + /* calculate the output of the PERCLK1 divider */ + reg = MC9328MXL_PLL_PCDR; + perclk1 = fpll / (1 + ((reg & MC9328MXL_PLL_PCDR_PCLK1_MASK) >> + MC9328MXL_PLL_PCDR_PCLK1_SHIFT)); + + return perclk1; +} + +/* + * By making this a weak alias for bsp_start_default, a brave soul + * can override the actual bsp_start routine used. + */ +void bsp_start (void) __attribute__ ((weak, alias("bsp_start_default"))); + diff --git a/bsps/arm/csb336/start/linkcmds b/bsps/arm/csb336/start/linkcmds new file mode 100644 index 0000000000..2f6f8bd89d --- /dev/null +++ b/bsps/arm/csb336/start/linkcmds @@ -0,0 +1,27 @@ +MEMORY { + SDRAM_VEC : ORIGIN = 0x08200000, LENGTH = 16k + SDRAM_MMU : ORIGIN = 0x08204000, LENGTH = 16k + SDRAM : ORIGIN = 0x08208000, LENGTH = 30M - 32k +} + +REGION_ALIAS ("REGION_START", SDRAM_VEC); +REGION_ALIAS ("REGION_VECTOR", SDRAM); +REGION_ALIAS ("REGION_TEXT", SDRAM); +REGION_ALIAS ("REGION_TEXT_LOAD", SDRAM); +REGION_ALIAS ("REGION_RODATA", SDRAM); +REGION_ALIAS ("REGION_RODATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_DATA", SDRAM); +REGION_ALIAS ("REGION_DATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_FAST_TEXT", SDRAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", SDRAM); +REGION_ALIAS ("REGION_FAST_DATA", SDRAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_BSS", SDRAM); +REGION_ALIAS ("REGION_WORK", SDRAM); +REGION_ALIAS ("REGION_STACK", SDRAM); +REGION_ALIAS ("REGION_NOCACHE", SDRAM); +REGION_ALIAS ("REGION_NOCACHE_LOAD", SDRAM); + +_ttbl_base = ORIGIN (SDRAM_MMU); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/csb336/start/memmap.c b/bsps/arm/csb336/start/memmap.c new file mode 100644 index 0000000000..a61fc6e2cf --- /dev/null +++ b/bsps/arm/csb336/start/memmap.c @@ -0,0 +1,35 @@ +/* + * CSB336 Memory Map + * + * Copyright (c) 2004 by Cogent Computer Systems + * Written by Jay Monkman <jtm@lopingdog.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ +#include <rtems.h> +#include <libcpu/mmu.h> + +/* Remember, the ARM920 has 64 TLBs. If you have more 1MB sections than + * that, you'll have TLB lookups, which could hurt performance. + */ +mmu_sect_map_t mem_map[] = { +/* <phys addr> <virt addr> <size> <flags> */ + {0x08200000, 0x00000000, 1, MMU_CACHE_WBACK}, /* Mirror of SDRAM */ + {0x00100000, 0x00100000, 1, MMU_CACHE_NONE}, /* Bootstrap ROM */ + {0x00200000, 0x00200000, 2, MMU_CACHE_NONE}, /* Internal Regs + eSRAM */ + + {0x08000000, 0x08000000, 1, MMU_CACHE_NONE}, /* SDRAM */ + {0x08100000, 0x08100000, 1, MMU_CACHE_WTHROUGH}, /* SDRAM */ + {0x08200000, 0x08200000, 30, MMU_CACHE_WBACK}, /* SDRAM */ + + {0x10000000, 0x10000000, 8, MMU_CACHE_NONE}, /* CS0 - Flash */ + {0x12000000, 0x12000000, 1, MMU_CACHE_NONE}, /* CS1 - enet */ + {0x13000000, 0x13000000, 1, MMU_CACHE_NONE}, /* CS2 - */ + {0x14000000, 0x14000000, 1, MMU_CACHE_NONE}, /* CS3 - */ + {0x15000000, 0x15000000, 1, MMU_CACHE_NONE}, /* CS4 - */ + {0x16000000, 0x16000000, 1, MMU_CACHE_NONE}, /* CS5 - */ + {0x50000000, 0x50000000, 1, MMU_CACHE_NONE}, /* ARM Test Regs */ + {0x00000000, 0x00000000, 0, 0} /* The end */ +}; diff --git a/bsps/arm/csb337/start/bsp_specs b/bsps/arm/csb337/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/csb337/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/csb337/start/bspreset.c b/bsps/arm/csb337/start/bspreset.c new file mode 100644 index 0000000000..a4605dcaf3 --- /dev/null +++ b/bsps/arm/csb337/start/bspreset.c @@ -0,0 +1,31 @@ +/* + * Cogent CSB337 - AT91RM9200 Startup code + */ + +/* + * Copyright (c) 2004 by Cogent Computer Systems + * Written by Jay Monkman <jtm@lopingdog.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. +*/ +#include <bsp.h> +#include <bsp/bootcard.h> +#include <at91rm9200.h> +#include <at91rm9200_pmc.h> +#include <at91rm9200_emac.h> + +void bsp_reset(void) +{ + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + (void) level; /* avoid set but not used warning */ + + /* Enable the watchdog timer, then wait for the world to end. */ + ST_REG(ST_WDMR) = ST_WDMR_RSTEN | 1; + + while(1) + ; +} diff --git a/bsps/arm/csb337/start/bspstart.c b/bsps/arm/csb337/start/bspstart.c new file mode 100644 index 0000000000..a47198598c --- /dev/null +++ b/bsps/arm/csb337/start/bspstart.c @@ -0,0 +1,158 @@ +/* + * Cogent CSB337 - AT91RM9200 Startup Code + * + * Copyright (c) 2004 by Cogent Computer Systems + * Written by Jay Monkman <jtm@lopingdog.com> + * + * Modified by Joel Sherill + * from OAR Corporation and + * Fernando Nicodemos <fgnicodemos@terra.com.br> + * from NCB - Sistemas Embarcados Ltda. (Brazil) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/irq-generic.h> +#include <at91rm9200.h> +#include <at91rm9200_pmc.h> +#include <at91rm9200_emac.h> +#include <at91rm9200_gpio.h> +#include <at91rm9200_usart.h> + +/* Function prototypes */ +static void fix_mac_addr(void); +void bsp_usart_init(void); + +/* + * bsp_start_default - BSP initialization function + * + * This function is called before RTEMS is initialized and used + * adjust the kernel's configuration. + * + * This function also configures the CPU's memory protection unit. + * + * RESTRICTIONS/LIMITATIONS: + * Since RTEMS is not configured, no RTEMS functions can be called. + */ +static void bsp_start_default( void ) +{ + /* disable interrupts */ + AIC_CTL_REG(AIC_IDCR) = 0xffffffff; + + /* + * Some versions of the bootloader have the MAC address + * reversed. This fixes it, if necessary. + */ + fix_mac_addr(); + + /* + * Init rtems PIO configuration for USARTs + */ + bsp_usart_init(); + + /* + * Init rtems interrupt management + */ + bsp_interrupt_initialize(); + +} /* bsp_start */ + +/* + * Some versions of the bootloader shipped with the CSB337 + * reverse the MAC address. This function tests for that, + * and fixes the MAC address. + */ +static void fix_mac_addr(void) +{ + uint8_t addr[6]; + + /* Read the MAC address */ + addr[0] = (EMAC_REG(EMAC_SA1L) >> 0) & 0xff; + addr[1] = (EMAC_REG(EMAC_SA1L) >> 8) & 0xff; + addr[2] = (EMAC_REG(EMAC_SA1L) >> 16) & 0xff; + addr[3] = (EMAC_REG(EMAC_SA1L) >> 24) & 0xff; + addr[4] = (EMAC_REG(EMAC_SA1H) >> 0) & 0xff; + addr[5] = (EMAC_REG(EMAC_SA1H) >> 8) & 0xff; + + /* Check which 3 bytes have Cogent's OUI */ + if ((addr[5] == 0x00) && (addr[4] == 0x23) && (addr[3] == 0x31)) { + EMAC_REG(EMAC_SA1L) = ((addr[5] << 0) | + (addr[4] << 8) | + (addr[3] << 16) | + (addr[2] << 24)); + + EMAC_REG(EMAC_SA1H) = ((addr[1] << 0) | + (addr[0] << 8)); + } +} + +/* + * + * NAME: bsp_usart_init - Function to setup the PIO in USART mode + * before startup + * + * DESCRIPTION: + * This function is called before usart driver is initialized and is + * used to setup the proper mode of PIO operation for USART. + * + * NOTES: + * The initialization could be done smarter by programming only the + * bits you need to program for each USART when the port is ENABLED. + * + */ +void bsp_usart_init(void) +{ + /* + * Configure shared pins for USARTs. + * Disables the PIO from controlling the corresponding pin. + */ + PIOA_REG(PIO_PDR) |= ( BIT5 | /* USART3 TXD3 */ + BIT6 | /* USART3 RXD3 */ + BIT17 | /* USART0 TXD0 */ + BIT18 | /* USART0 RXD0 */ + BIT22 | /* USART2 RXD2 */ + BIT23 ); /* USART2 TXD2 */ + + PIOB_REG(PIO_PDR) |= ( BIT20 | /* USART1 TXD1 */ + BIT21 ); /* USART1 RXD1 */ + + /**** PIO Controller A - Pins you want in mode B ****/ + PIOA_REG(PIO_BSR) |= ( BIT5 | /* USART3 TXD3 */ /* add */ + BIT6 ); /* USART3 RXD3 */ + PIOA_REG(PIO_ASR) &= ~( BIT5 | /* USART3 TXD3 */ + BIT6 ); /* USART3 RXD3 */ + + /**** PIO Controller A - Pins you want in mode A ****/ + PIOA_REG(PIO_ASR) |= ( BIT17 | /* USART0 TXD0 */ + BIT18 | /* USART0 RXD0 */ + BIT22 | /* USART2 RXD2 */ + BIT23 ); /* USART2 TXD2 */ + PIOA_REG(PIO_BSR) &= ~( BIT17 | /* USART0 TXD0 */ /* add */ + BIT18 | /* USART0 RXD0 */ + BIT22 | /* USART2 RXD2 */ + BIT23 ); /* USART2 TXD2 */ + + /**** PIO Controller B - Pins you want in mode A ****/ + PIOB_REG(PIO_ASR) |= ( BIT20 | /* USART1 TXD1 */ + BIT21 ); /* USART1 RXD1 */ + PIOB_REG(PIO_BSR) &= ~( BIT20 | /* USART1 TXD1 */ + BIT21 ); /* USART1 RXD1 */ + + /**** PIO Controller B - Pins you want in mode B ****/ + /**** none ****/ + + /* Enable the clock to the USARTs */ + PMC_REG(PMC_PCER) |= ( PMC_PCR_PID_US0 | /* USART 0 Peripheral Clock */ + PMC_PCR_PID_US1 | /* USART 1 Peripheral Clock */ + PMC_PCR_PID_US2 | /* USART 2 Peripheral Clock */ + PMC_PCR_PID_US3 ); /* USART 3 Peripheral Clock */ +} + +/* + * By making this a weak alias for bsp_start_default, a brave soul + * can override the actual bsp_start routine used. + */ +void bsp_start (void) __attribute__ ((weak, alias("bsp_start_default"))); diff --git a/bsps/arm/csb337/start/linkcmds.csb337 b/bsps/arm/csb337/start/linkcmds.csb337 new file mode 100644 index 0000000000..f59a33c703 --- /dev/null +++ b/bsps/arm/csb337/start/linkcmds.csb337 @@ -0,0 +1,27 @@ +MEMORY { + SDRAM : ORIGIN = 0x20100000, LENGTH = 15M - 16k + SDRAM_MMU : ORIGIN = 0x20ffc000, LENGTH = 16k + SRAM : ORIGIN = 0x00200000, LENGTH = 16k +} + +REGION_ALIAS ("REGION_START", SDRAM); +REGION_ALIAS ("REGION_VECTOR", SRAM); +REGION_ALIAS ("REGION_TEXT", SDRAM); +REGION_ALIAS ("REGION_TEXT_LOAD", SDRAM); +REGION_ALIAS ("REGION_RODATA", SDRAM); +REGION_ALIAS ("REGION_RODATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_DATA", SDRAM); +REGION_ALIAS ("REGION_DATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_FAST_TEXT", SDRAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", SDRAM); +REGION_ALIAS ("REGION_FAST_DATA", SDRAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_BSS", SDRAM); +REGION_ALIAS ("REGION_WORK", SDRAM); +REGION_ALIAS ("REGION_STACK", SDRAM); +REGION_ALIAS ("REGION_NOCACHE", SDRAM); +REGION_ALIAS ("REGION_NOCACHE_LOAD", SDRAM); + +_ttbl_base = ORIGIN (SDRAM_MMU); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/csb337/start/linkcmds.csb637 b/bsps/arm/csb337/start/linkcmds.csb637 new file mode 100644 index 0000000000..91a34b7229 --- /dev/null +++ b/bsps/arm/csb337/start/linkcmds.csb637 @@ -0,0 +1,27 @@ +MEMORY { + SDRAM : ORIGIN = 0x20100000, LENGTH = 63M - 16k + SDRAM_MMU : ORIGIN = 0x23ffc000, LENGTH = 16k + SRAM : ORIGIN = 0x00200000, LENGTH = 16k +} + +REGION_ALIAS ("REGION_START", SDRAM); +REGION_ALIAS ("REGION_VECTOR", SRAM); +REGION_ALIAS ("REGION_TEXT", SDRAM); +REGION_ALIAS ("REGION_TEXT_LOAD", SDRAM); +REGION_ALIAS ("REGION_RODATA", SDRAM); +REGION_ALIAS ("REGION_RODATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_DATA", SDRAM); +REGION_ALIAS ("REGION_DATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_FAST_TEXT", SDRAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", SDRAM); +REGION_ALIAS ("REGION_FAST_DATA", SDRAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_BSS", SDRAM); +REGION_ALIAS ("REGION_WORK", SDRAM); +REGION_ALIAS ("REGION_STACK", SDRAM); +REGION_ALIAS ("REGION_NOCACHE", SDRAM); +REGION_ALIAS ("REGION_NOCACHE_LOAD", SDRAM); + +_ttbl_base = ORIGIN (SDRAM_MMU); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/csb337/start/memmap.c b/bsps/arm/csb337/start/memmap.c new file mode 100644 index 0000000000..bdd5487432 --- /dev/null +++ b/bsps/arm/csb337/start/memmap.c @@ -0,0 +1,50 @@ +/* + * CSB337 and CSB637 (KIT637_V6) Memory map + * + * Copyright (c) 2004 by Jay Monkman <jtm@lopingdog.com> + * File from the old CSB337 RTEMS BSP + * + * Modified by Joel Sherill + * from OAR Corporation and + * Fernando Nicodemos <fgnicodemos@terra.com.br> + * from NCB - Sistemas Embarcados Ltda. (Brazil) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems.h> +#include <libcpu/mmu.h> + +#include <bspopts.h> + +/* Remember, the ARM920 has 64 TLBs. If you have more 1MB sections than + * that, you'll have TLB lookups, which could hurt performance. + */ +mmu_sect_map_t mem_map[] = { +/* <phys addr> <virt addr> <size> <flags> */ + {0x00200000, 0x00000000, 1, MMU_CACHE_NONE}, /* SRAM */ + {0x00200000, 0x00200000, 1, MMU_CACHE_NONE}, /* SRAM */ + {0x10000000, 0x10000000, 8, MMU_CACHE_NONE}, /* FLASH */ +#if csb637 /* CSB637 or KIT637_V6 */ + {0x20000000, 0x20000000, 64, MMU_CACHE_WTHROUGH}, /* SDRAM */ +#elif kit637_v6 + {0x20000000, 0x20000000, 64, MMU_CACHE_WTHROUGH}, /* SDRAM */ +#else /* CSB337 */ + {0x20000000, 0x20000000, 32, MMU_CACHE_WTHROUGH}, /* SDRAM */ +#endif +#if ENABLE_LCD /* KIT637_V6 Video buffer */ + {0x30000000, 0x30000000, 8, MMU_CACHE_NONE}, /* Video buffer - 8MB */ +#else /* CSB337 Video buffer */ + {0x30000000, 0x30000000, 1, MMU_CACHE_NONE}, /* Video buffer - 1MB */ +#endif + {0x40000000, 0x40000000, 1, MMU_CACHE_NONE}, /* Expansion CS0 */ + {0x50000000, 0x50000000, 1, MMU_CACHE_NONE}, /* CF CE 1 */ + {0x60000000, 0x60000000, 1, MMU_CACHE_NONE}, /* CF CE 1 */ + {0x70000000, 0x70000000, 1, MMU_CACHE_NONE}, /* CF CE 2 */ + {0x80000000, 0x80000000, 1, MMU_CACHE_NONE}, /* Expansion CS0 */ + {0xfff00000, 0xfff00000, 1, MMU_CACHE_NONE}, /* Internal regs */ + {0x00000000, 0x00000000, 0, 0} /* The end */ +}; + diff --git a/bsps/arm/csb337/start/pmc.c b/bsps/arm/csb337/start/pmc.c new file mode 100644 index 0000000000..a15bf3c075 --- /dev/null +++ b/bsps/arm/csb337/start/pmc.c @@ -0,0 +1,96 @@ +/* + * Atmel AT91RM9200 PMC functions + * + * Copyright (c) 2004 by Jay Monkman <jtm@lopingdog.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems.h> +#include <bsp.h> +#include <at91rm9200.h> +#include <at91rm9200_pmc.h> + +int at91rm9200_get_mainclk(void) +{ + return BSP_MAIN_FREQ; +} + +int at91rm9200_get_slck(void) +{ + return BSP_SLCK_FREQ; +} + +int at91rm9200_get_mck(void) +{ + uint32_t mck_reg; + uint32_t mck_freq = 0; /* to avoid warnings */ + uint32_t pll_reg; + int prescaler = 0; /* to avoid warnings */ + + mck_reg = PMC_REG(PMC_MCKR); + + switch(mck_reg & PMC_MCKR_PRES_MASK) { + case PMC_MCKR_PRES_1: + prescaler = 1; + break; + case PMC_MCKR_PRES_2: + prescaler = 2; + break; + case PMC_MCKR_PRES_4: + prescaler = 4; + break; + case PMC_MCKR_PRES_8: + prescaler = 8; + break; + case PMC_MCKR_PRES_16: + prescaler = 16; + break; + case PMC_MCKR_PRES_32: + prescaler = 32; + break; + case PMC_MCKR_PRES_64: + prescaler = 64; + break; + } + + /* Let's find out what MCK's source is */ + switch (mck_reg & PMC_MCKR_CSS_MASK) { + case PMC_MCKR_CSS_SLOW: + /* I'm assuming the slow clock is 32.768 MHz */ + mck_freq = at91rm9200_get_slck() / prescaler; + break; + + case PMC_MCKR_CSS_MAIN: + mck_freq = at91rm9200_get_mainclk() / prescaler; + break; + + case PMC_MCKR_CSS_PLLA: + pll_reg = PMC_REG(PMC_PLLAR); + mck_freq = at91rm9200_get_mainclk() / prescaler; + mck_freq = mck_freq / (pll_reg & PMC_PLLAR_DIV_MASK); + mck_freq = mck_freq * (((pll_reg & PMC_PLLAR_MUL_MASK) >> 16) + 1); + break; + + case PMC_MCKR_CSS_PLLB: + pll_reg = PMC_REG(PMC_PLLBR); + mck_freq = at91rm9200_get_mainclk() / prescaler; + mck_freq = mck_freq / (pll_reg & PMC_PLLBR_DIV_MASK); + mck_freq = mck_freq * (((pll_reg & PMC_PLLBR_MUL_MASK) >> 16) + 1); + break; + } + + if ((mck_reg & PMC_MCKR_MDIV_MASK) == PMC_MCKR_MDIV_2) { + mck_freq = mck_freq / 2; + } else if ((mck_reg & PMC_MCKR_MDIV_MASK) == PMC_MCKR_MDIV_3) { + mck_freq = mck_freq / 3; + } else if ((mck_reg & PMC_MCKR_MDIV_MASK) == PMC_MCKR_MDIV_4) { + mck_freq = mck_freq / 4; + } + + + return mck_freq; +} + diff --git a/bsps/arm/csb337/start/umonsupp.c b/bsps/arm/csb337/start/umonsupp.c new file mode 100644 index 0000000000..d4bf731c5d --- /dev/null +++ b/bsps/arm/csb337/start/umonsupp.c @@ -0,0 +1,25 @@ +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * Modified by Fernando Nicodemos <fgnicodemos@terra.com.br> + * from NCB - Sistemas Embarcados Ltda. (Brazil) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <rtems/umon.h> + +/* + * BSP specific routine to help when calling monConnect(). This + * returns the value known to uMon as MONCOMPTR. + */ + +void *rtems_bsp_get_umon_monptr(void) +{ + return (void *)0x10000020; +} + diff --git a/bsps/arm/edb7312/start/bsp_specs b/bsps/arm/edb7312/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/edb7312/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/edb7312/start/bspreset.c b/bsps/arm/edb7312/start/bspreset.c new file mode 100644 index 0000000000..436bdf09e4 --- /dev/null +++ b/bsps/arm/edb7312/start/bspreset.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2002 by Jay Monkman <jtm@smoothsmoothie.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <ep7312.h> + +void bsp_reset(void) +{ +#if ON_SKYEYE == 1 + #define SKYEYE_MAGIC_ADDRESS (*(volatile unsigned int *)(0xb0000000)) + + SKYEYE_MAGIC_ADDRESS = 0xff; +#else + __asm__ volatile ("b _start"); +#endif +} diff --git a/bsps/arm/edb7312/start/bspstart.c b/bsps/arm/edb7312/start/bspstart.c new file mode 100644 index 0000000000..0f9c64d2d8 --- /dev/null +++ b/bsps/arm/edb7312/start/bspstart.c @@ -0,0 +1,45 @@ +/* + * Cirrus EP7312 Startup code + */ + +/* + * Copyright (c) 2002 by Jay Monkman <jtm@smoothsmoothie.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/irq-generic.h> +#include <ep7312.h> +#include <uart.h> + +/* + * NAME: bsp_start_default - BSP initialization function + * + * This function is called before RTEMS is initialized + * This function also configures the CPU's memory protection unit. + * + * + * RESTRICTIONS/LIMITATIONS: + * Since RTEMS is not configured, no RTEMS functions can be called. + * + */ +static void bsp_start_default( void ) +{ + /* disable interrupts */ + *EP7312_INTMR1 = 0; + *EP7312_INTMR2 = 0; + + /* + * Init rtems interrupt management + */ + bsp_interrupt_initialize(); +} /* bsp_start */ + +/* + * By making this a weak alias for bsp_start_default, a brave soul + * can override the actual bsp_start routine used. + */ +void bsp_start (void) __attribute__ ((weak, alias("bsp_start_default"))); diff --git a/bsps/arm/edb7312/start/linkcmds b/bsps/arm/edb7312/start/linkcmds new file mode 100644 index 0000000000..a0afc0ad5e --- /dev/null +++ b/bsps/arm/edb7312/start/linkcmds @@ -0,0 +1,25 @@ +MEMORY { + SDRAM : ORIGIN = 0x00000000, LENGTH = 16M +} + +REGION_ALIAS ("REGION_START", SDRAM); +REGION_ALIAS ("REGION_VECTOR", SDRAM); +REGION_ALIAS ("REGION_TEXT", SDRAM); +REGION_ALIAS ("REGION_TEXT_LOAD", SDRAM); +REGION_ALIAS ("REGION_RODATA", SDRAM); +REGION_ALIAS ("REGION_RODATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_DATA", SDRAM); +REGION_ALIAS ("REGION_DATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_FAST_TEXT", SDRAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", SDRAM); +REGION_ALIAS ("REGION_FAST_DATA", SDRAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_BSS", SDRAM); +REGION_ALIAS ("REGION_WORK", SDRAM); +REGION_ALIAS ("REGION_STACK", SDRAM); +REGION_ALIAS ("REGION_NOCACHE", SDRAM); +REGION_ALIAS ("REGION_NOCACHE_LOAD", SDRAM); + +bsp_vector_table_in_start_section = 1; + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/gdbarmsim/start/bsp_specs b/bsps/arm/gdbarmsim/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/gdbarmsim/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/gdbarmsim/start/bspreset.c b/bsps/arm/gdbarmsim/start/bspreset.c new file mode 100644 index 0000000000..b32c80e4e1 --- /dev/null +++ b/bsps/arm/gdbarmsim/start/bspreset.c @@ -0,0 +1,17 @@ +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems.h> +#include <bsp/bootcard.h> +#include <bsp/swi.h> + +void bsp_reset( void ) +{ + __asm__ ("swi %a0" :: "i" (SWI_Exit)); +} diff --git a/bsps/arm/gdbarmsim/start/bspstart.c b/bsps/arm/gdbarmsim/start/bspstart.c new file mode 100644 index 0000000000..de3126499d --- /dev/null +++ b/bsps/arm/gdbarmsim/start/bspstart.c @@ -0,0 +1,22 @@ +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +void initialise_monitor_handles(void); + +/* + * This routine would usually do the bulk of the system initialization. + * But if a BSP doesn't need to do anything, it can use this version. + */ +void bsp_start( void ) +{ + initialise_monitor_handles(void); +} diff --git a/bsps/arm/gdbarmsim/start/bspstarthooks.c b/bsps/arm/gdbarmsim/start/bspstarthooks.c new file mode 100644 index 0000000000..996d35859d --- /dev/null +++ b/bsps/arm/gdbarmsim/start/bspstarthooks.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2014 Chris Johns <chrisj@rtems.org> All rights reserved. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/start.h> +# +BSP_START_TEXT_SECTION void bsp_start_hook_0(void) +{ +} + +BSP_START_TEXT_SECTION void bsp_start_hook_1(void) +{ + bsp_start_copy_sections(); + bsp_start_clear_bss(); +} diff --git a/bsps/arm/gdbarmsim/start/linkcmds b/bsps/arm/gdbarmsim/start/linkcmds new file mode 100644 index 0000000000..536dbf5fee --- /dev/null +++ b/bsps/arm/gdbarmsim/start/linkcmds @@ -0,0 +1,23 @@ +MEMORY { + RAM : ORIGIN = 0x00000000, LENGTH = 4M +} + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_VECTOR", RAM); +REGION_ALIAS ("REGION_TEXT", RAM); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_RODATA", RAM); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", RAM); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/gdbarmsim/start/syscalls.c b/bsps/arm/gdbarmsim/start/syscalls.c new file mode 100644 index 0000000000..2e761dd28b --- /dev/null +++ b/bsps/arm/gdbarmsim/start/syscalls.c @@ -0,0 +1,763 @@ +/* + * Copied from libgloss 1 Oct 2009. + * Minor modifications to work with RTEMS. + */ + +/* Support files for GNU libc. Files in the system namespace go here. + Files in the C namespace (ie those that do not start with an + underscore) go in .c. */ + +/* + * Rename all the functions present here to stop then clashing with RTEMS + * names. + */ + +#include <_ansi.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/fcntl.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <sys/time.h> +#include <sys/times.h> +#include <errno.h> +#include <reent.h> +#include <unistd.h> +#include <sys/wait.h> +#include <bsp/swi.h> + +#include <bsp.h> + +/* Forward prototypes. */ +static int checkerror(int); +static int error(int); +static int get_errno(void); + +/* Struct used to keep track of the file position, just so we + can implement fseek(fh,x,SEEK_CUR). */ +struct fdent +{ + int handle; + int pos; +}; + +#define MAX_OPEN_FILES 20 + +/* User file descriptors (fd) are integer indexes into + the openfiles[] array. Error checking is done by using + findslot(). + + This openfiles array is manipulated directly by only + these 5 functions: + + findslot() - Translate entry. + newslot() - Find empty entry. + initilise_monitor_handles() - Initialize entries. + _swiopen() - Initialize entry. + _close() - Handle stdout == stderr case. + + Every other function must use findslot(). */ + +static struct fdent openfiles [MAX_OPEN_FILES]; + +static struct fdent* findslot (int); +static int newslot (void); + +/* Register name faking - works in collusion with the linker. */ +register char * stack_ptr __asm__ ("sp"); + + +/* following is copied from libc/stdio/local.h to check std streams */ +extern void __sinit(struct _reent *); +#define CHECK_INIT(ptr) \ + do \ + { \ + if ((ptr) && !(ptr)->__sdidinit) \ + __sinit (ptr); \ + } \ + while (0) + +static int monitor_stdin; +static int monitor_stdout; +static int monitor_stderr; + +/* Return a pointer to the structure associated with + the user file descriptor fd. */ +static struct fdent* +findslot (int fd) +{ + CHECK_INIT(_REENT); + + /* User file descriptor is out of range. */ + if ((unsigned int)fd >= MAX_OPEN_FILES) + return NULL; + + /* User file descriptor is open? */ + if (openfiles[fd].handle == -1) + return NULL; + + /* Valid. */ + return &openfiles[fd]; +} + +/* Return the next lowest numbered free file + structure, or -1 if we can't find one. */ +static int +newslot (void) +{ + int i; + + for (i = 0; i < MAX_OPEN_FILES; i++) + if (openfiles[i].handle == -1) + break; + + if (i == MAX_OPEN_FILES) + return -1; + + return i; +} + +void +initialise_monitor_handles (void) +{ + int i; + + /* Open the standard file descriptors by opening the special + * teletype device, ":tt", read-only to obtain a descritpor for + * standard input and write-only to obtain a descriptor for standard + * output. Finally, open ":tt" in append mode to obtain a descriptor + * for standard error. Since this is a write mode, most kernels will + * probably return the same value as for standard output, but the + * kernel can differentiate the two using the mode flag and return a + * different descriptor for standard error. + */ + +#ifdef ARM_RDI_MONITOR + int volatile block[3]; + + block[0] = (int) ":tt"; + block[2] = 3; /* length of filename */ + block[1] = 0; /* mode "r" */ + monitor_stdin = do_AngelSWI (AngelSWI_Reason_Open, (void *) block); + + block[0] = (int) ":tt"; + block[2] = 3; /* length of filename */ + block[1] = 4; /* mode "w" */ + monitor_stdout = do_AngelSWI (AngelSWI_Reason_Open, (void *) block); + + block[0] = (int) ":tt"; + block[2] = 3; /* length of filename */ + block[1] = 8; /* mode "a" */ + monitor_stderr = do_AngelSWI (AngelSWI_Reason_Open, (void *) block); +#else + int fh; + const char * name; + + name = ":tt"; + __asm__ ("mov r0,%2; mov r1, #0; swi %a1; mov %0, r0" + : "=r"(fh) + : "i" (SWI_Open),"r"(name) + : "r0","r1"); + monitor_stdin = fh; + + name = ":tt"; + __asm__ ("mov r0,%2; mov r1, #4; swi %a1; mov %0, r0" + : "=r"(fh) + : "i" (SWI_Open),"r"(name) + : "r0","r1"); + monitor_stdout = fh; + + name = ":tt"; + __asm__ ("mov r0,%2; mov r1, #8; swi %a1; mov %0, r0" + : "=r"(fh) + : "i" (SWI_Open),"r"(name) + : "r0","r1"); + monitor_stderr = fh; +#endif + + /* If we failed to open stderr, redirect to stdout. */ + if (monitor_stderr == -1) + monitor_stderr = monitor_stdout; + + for (i = 0; i < MAX_OPEN_FILES; i ++) + openfiles[i].handle = -1; + + openfiles[0].handle = monitor_stdin; + openfiles[0].pos = 0; + openfiles[1].handle = monitor_stdout; + openfiles[1].pos = 0; + openfiles[2].handle = monitor_stderr; + openfiles[2].pos = 0; +} + +static int +get_errno (void) +{ +#ifdef ARM_RDI_MONITOR + return do_AngelSWI (AngelSWI_Reason_Errno, NULL); +#else + register int r0 __asm__ ("r0"); + __asm__ ("swi %a1" : "=r"(r0) : "i" (SWI_GetErrno)); + return r0; +#endif +} + +/* Set errno and return result. */ +static int +error (int result) +{ + errno = get_errno (); + return result; +} + +/* Check the return and set errno appropriately. */ +static int +checkerror (int result) +{ + if (result == -1) + return error (-1); + return result; +} + +/* fh, is a valid internal file handle. + ptr, is a null terminated string. + len, is the length in bytes to read. + Returns the number of bytes *not* written. */ +int +gdbarmsim_swiread (int fh, + char * ptr, + int len) +{ +#ifdef ARM_RDI_MONITOR + int block[3]; + + block[0] = fh; + block[1] = (int) ptr; + block[2] = len; + + return checkerror (do_AngelSWI (AngelSWI_Reason_Read, block)); +#else + register int r0 __asm__ ("r0"); + register int r1 __asm__ ("r1"); + register int r2 __asm__ ("r2"); + r0 = fh; + r1 = (int)ptr; + r2 = len; + __asm__ ("swi %a4" + : "=r" (r0) + : "0"(r0), "r"(r1), "r"(r2), "i"(SWI_Read)); + return checkerror (r0); +#endif +} + +/* fd, is a valid user file handle. + Translates the return of _swiread into + bytes read. */ +int +gdbarmsim_read (int fd, + char * ptr, + int len) +{ + int res; + struct fdent *pfd; + + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } + + res = gdbarmsim_swiread (pfd->handle, ptr, len); + + if (res == -1) + return res; + + pfd->pos += len - res; + + /* res == len is not an error, + at least if we want feof() to work. */ + return len - res; +} + +/* fd, is a user file descriptor. */ +int +gdbarmsim_swilseek (int fd, + int ptr, + int dir) +{ + int res; + struct fdent *pfd; + + /* Valid file descriptor? */ + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } + + /* Valid whence? */ + if ((dir != SEEK_CUR) + && (dir != SEEK_SET) + && (dir != SEEK_END)) + { + errno = EINVAL; + return -1; + } + + /* Convert SEEK_CUR to SEEK_SET */ + if (dir == SEEK_CUR) + { + ptr = pfd->pos + ptr; + /* The resulting file offset would be negative. */ + if (ptr < 0) + { + errno = EINVAL; + if ((pfd->pos > 0) && (ptr > 0)) + errno = EOVERFLOW; + return -1; + } + dir = SEEK_SET; + } + +#ifdef ARM_RDI_MONITOR + int block[2]; + if (dir == SEEK_END) + { + block[0] = pfd->handle; + res = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, block)); + if (res == -1) + return -1; + ptr += res; + } + + /* This code only does absolute seeks. */ + block[0] = pfd->handle; + block[1] = ptr; + res = checkerror (do_AngelSWI (AngelSWI_Reason_Seek, block)); +#else + if (dir == SEEK_END) + { + __asm__ ("mov r0, %2; swi %a1; mov %0, r0" + : "=r" (res) + : "i" (SWI_Flen), "r" (pfd->handle) + : "r0"); + checkerror (res); + if (res == -1) + return -1; + ptr += res; + } + + /* This code only does absolute seeks. */ + __asm__ ("mov r0, %2; mov r1, %3; swi %a1; mov %0, r0" + : "=r" (res) + : "i" (SWI_Seek), "r" (pfd->handle), "r" (ptr) + : "r0", "r1"); + checkerror (res); +#endif + /* At this point ptr is the current file position. */ + if (res >= 0) + { + pfd->pos = ptr; + return ptr; + } + else + return -1; +} + +int +gdbarmsim_lseek (int fd, + int ptr, + int dir) +{ + return gdbarmsim_swilseek (fd, ptr, dir); +} + +/* write a single character out the hosts stdout */ +int +gdbarmsim_writec (const char c) +{ +#ifdef ARM_RDI_MONITOR + int block[1]; + + block[0] = ((int) c) & 0xff;; + + return checkerror (do_AngelSWI (AngelSWI_Reason_WriteC, block)); +#else + register int r0 __asm__ ("r0"); + r0 = ((int) c) & 0xff; + __asm__ ("swi %a2" + : "=r" (r0) + : "0"(r0), "i"(SWI_WriteC)); + return checkerror (r0); +#endif +} + +/* fh, is a valid internal file handle. + Returns the number of bytes *not* written. */ +int +gdbarmsim_swiwrite (int fh, + char * ptr, + int len) +{ +#ifdef ARM_RDI_MONITOR + int block[3]; + + block[0] = fh; + block[1] = (int) ptr; + block[2] = len; + + return checkerror (do_AngelSWI (AngelSWI_Reason_Write, block)); +#else + register int r0 __asm__ ("r0"); + register int r1 __asm__ ("r1"); + register int r2 __asm__ ("r2"); + r0 = fh; + r1 = (int)ptr; + r2 = len; + __asm__ ("swi %a4" + : "=r" (r0) + : "0"(r0), "r"(r1), "r"(r2), "i"(SWI_Write)); + return checkerror (r0); +#endif +} + +/* fd, is a user file descriptor. */ +int +gdbarmsim_write (int fd, + char * ptr, + int len) +{ + int res; + struct fdent *pfd; + + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } + + res = gdbarmsim_swiwrite (pfd->handle, ptr,len); + + /* Clearly an error. */ + if (res < 0) + return -1; + + pfd->pos += len - res; + + /* We wrote 0 bytes? + Retrieve errno just in case. */ + if ((len - res) == 0) + return error (0); + + return (len - res); +} + +int +gdbarmsim_swiopen (const char * path, int flags) +{ + int aflags = 0, fh; +#ifdef ARM_RDI_MONITOR + int block[3]; +#endif + + int fd = newslot (); + + if (fd == -1) + { + errno = EMFILE; + return -1; + } + + /* It is an error to open a file that already exists. */ + if ((flags & O_CREAT) + && (flags & O_EXCL)) + { + struct stat st; + int res; + res = gdbarmsim_stat (path, &st); + if (res != -1) + { + errno = EEXIST; + return -1; + } + } + + /* The flags are Unix-style, so we need to convert them. */ +#ifdef O_BINARY + if (flags & O_BINARY) + aflags |= 1; +#endif + + /* In O_RDONLY we expect aflags == 0. */ + + if (flags & O_RDWR) + aflags |= 2; + + if ((flags & O_CREAT) + || (flags & O_TRUNC) + || (flags & O_WRONLY)) + aflags |= 4; + + if (flags & O_APPEND) + { + /* Can't ask for w AND a; means just 'a'. */ + aflags &= ~4; + aflags |= 8; + } + +#ifdef ARM_RDI_MONITOR + block[0] = (int) path; + block[2] = strlen (path); + block[1] = aflags; + + fh = do_AngelSWI (AngelSWI_Reason_Open, block); + +#else + __asm__ ("mov r0,%2; mov r1, %3; swi %a1; mov %0, r0" + : "=r"(fh) + : "i" (SWI_Open),"r"(path),"r"(aflags) + : "r0","r1"); +#endif + + /* Return a user file descriptor or an error. */ + if (fh >= 0) + { + openfiles[fd].handle = fh; + openfiles[fd].pos = 0; + return fd; + } + else + return error (fh); +} + +int +gdbarmsim_open (const char * path, int flags, ...) +{ + return gdbarmsim_swiopen (path, flags); +} + +/* fh, is a valid internal file handle. */ +int +gdbarmsim_swiclose (int fh) +{ +#ifdef ARM_RDI_MONITOR + return checkerror (do_AngelSWI (AngelSWI_Reason_Close, &fh)); +#else + register int r0 __asm__ ("r0"); + r0 = fh; + __asm__ ("swi %a2" + : "=r"(r0) + : "0"(r0), "i" (SWI_Close)); + return checkerror (r0); +#endif +} + +/* fd, is a user file descriptor. */ +int +gdbarmsim_close (int fd) +{ + int res; + struct fdent *pfd; + + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } + + /* Handle stderr == stdout. */ + if ((fd == 1 || fd == 2) + && (openfiles[1].handle == openfiles[2].handle)) + { + pfd->handle = -1; + return 0; + } + + /* Attempt to close the handle. */ + res = gdbarmsim_swiclose (pfd->handle); + + /* Reclaim handle? */ + if (res == 0) + pfd->handle = -1; + + return res; +} + +int +gdbarmsim_swistat (int fd, struct stat * st) +{ + struct fdent *pfd; + int res; + + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } + + /* Always assume a character device, + with 1024 byte blocks. */ + st->st_mode |= S_IFCHR; + st->st_blksize = 1024; +#ifdef ARM_RDI_MONITOR + res = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, &pfd->handle)); +#else + __asm__ ("mov r0, %2; swi %a1; mov %0, r0" + : "=r" (res) + : "i" (SWI_Flen), "r" (pfd->handle) + : "r0"); + checkerror (res); +#endif + if (res == -1) + return -1; + /* Return the file size. */ + st->st_size = res; + return 0; +} + +int +gdbarmsim_fstat (int fd, struct stat * st) +{ + memset (st, 0, sizeof (* st)); + return gdbarmsim_swistat (fd, st); +} + +int +gdbarmsim_stat (const char *fname, struct stat *st) +{ + int fd, res; + memset (st, 0, sizeof (* st)); + /* The best we can do is try to open the file readonly. + If it exists, then we can guess a few things about it. */ + if ((fd = gdbarmsim_open (fname, O_RDONLY)) == -1) + return -1; + st->st_mode |= S_IFREG | S_IREAD; + res = gdbarmsim_swistat (fd, st); + /* Not interested in the error. */ + gdbarmsim_close (fd); + return res; +} + +int +gdbarmsim_unlink (const char *path) +{ + int res; +#ifdef ARM_RDI_MONITOR + int block[2]; + block[0] = (int)path; + block[1] = strlen(path); + res = do_AngelSWI (AngelSWI_Reason_Remove, block); +#else + register int r0 __asm__ ("r0"); + r0 = (int)path; + __asm__ ("swi %a2" + : "=r"(r0) + : "0"(r0), "i" (SWI_Remove)); + res = r0; +#endif + if (res == -1) + return error (res); + return 0; +} + +/* Return a clock that ticks at 100Hz. */ +clock_t +gdbarmsim_clock (void) +{ + clock_t timeval; + +#ifdef ARM_RDI_MONITOR + timeval = do_AngelSWI (AngelSWI_Reason_Clock,NULL); +#else + __asm__ ("swi %a1; mov %0, r0" : "=r" (timeval): "i" (SWI_Clock) : "r0"); +#endif + return timeval; +} + +int +gdbarmsim__isatty (int fd) +{ + struct fdent *pfd; + + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } + +#ifdef ARM_RDI_MONITOR + return checkerror (do_AngelSWI (AngelSWI_Reason_IsTTY, &pfd->handle)); +#else + register int r0 __asm__ ("r0"); + r0 = pfd->handle; + __asm__ ("swi %a2" + : "=r" (r0) + : "0"(r0), "i" (SWI_IsTTY)); + return checkerror (r0); +#endif +} + +int +gdbarmsim_system (const char *s) +{ +#ifdef ARM_RDI_MONITOR + int block[2]; + int e; + + /* Hmmm. The ARM debug interface specification doesn't say whether + SYS_SYSTEM does the right thing with a null argument, or assign any + meaning to its return value. Try to do something reasonable.... */ + if (!s) + return 1; /* maybe there is a shell available? we can hope. :-P */ + block[0] = (int)s; + block[1] = strlen (s); + e = checkerror (do_AngelSWI (AngelSWI_Reason_System, block)); + if ((e >= 0) && (e < 256)) + { + /* We have to convert e, an exit status to the encoded status of + the command. To avoid hard coding the exit status, we simply + loop until we find the right position. */ + int exit_code; + + for (exit_code = e; e && WEXITSTATUS (e) != exit_code; e <<= 1) + continue; + } + return e; +#else + register int r0 __asm__ ("r0"); + r0 = (int)s; + __asm__ ("swi %a2" + : "=r" (r0) + : "0"(r0), "i" (SWI_CLI)); + return checkerror (r0); +#endif +} + +int +gdbarmsim_rename (const char * oldpath, const char * newpath) +{ +#ifdef ARM_RDI_MONITOR + int block[4]; + block[0] = (int)oldpath; + block[1] = strlen(oldpath); + block[2] = (int)newpath; + block[3] = strlen(newpath); + return checkerror (do_AngelSWI (AngelSWI_Reason_Rename, block)) ? -1 : 0; +#else + register int r0 __asm__ ("r0"); + register int r1 __asm__ ("r1"); + r0 = (int)oldpath; + r1 = (int)newpath; + __asm__ ("swi %a3" + : "=r" (r0) + : "0" (r0), "r" (r1), "i" (SWI_Rename)); + return checkerror (r0); +#endif +} diff --git a/bsps/arm/gumstix/start/bsp_specs b/bsps/arm/gumstix/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/gumstix/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/gumstix/start/bspreset.c b/bsps/arm/gumstix/start/bspreset.c new file mode 100644 index 0000000000..ab7c5ffc8f --- /dev/null +++ b/bsps/arm/gumstix/start/bspreset.c @@ -0,0 +1,18 @@ +/* + * By Yang Xi <hiyangxi@gmail.com>. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <pxa255.h> + +void bsp_reset( void ) +{ +#if ON_SKYEYE == 1 + SKYEYE_MAGIC_ADDRESS = 0xff; +#endif +} diff --git a/bsps/arm/gumstix/start/bspstart.c b/bsps/arm/gumstix/start/bspstart.c new file mode 100644 index 0000000000..f86bf3d6e3 --- /dev/null +++ b/bsps/arm/gumstix/start/bspstart.c @@ -0,0 +1,40 @@ +/* + * By Yang Xi <hiyangxi@gmail.com>. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/irq-generic.h> +#include <rtems/libcsupport.h> +#include <rtems/libio.h> +#include <pxa255.h> + +/* + * + * NAME: bsp_start_default - BSP initialization function + * + * DESCRIPTION: + * This function is called before RTEMS is initialized and used + * adjust the kernel's configuration. + * + * This function also configures the CPU's memory protection unit. + * + * RESTRICTIONS/LIMITATIONS: + * Since RTEMS is not configured, no RTEMS functions can be called. + * + */ +static void bsp_start_default( void ) +{ + /* disable interrupts */ + XSCALE_INT_ICMR = 0x0; + bsp_interrupt_initialize(); +} /* bsp_start */ + +/* + * By making this a weak alias for bsp_start_default, a brave soul + * can override the actual bsp_start routine used. + */ +void bsp_start (void) __attribute__ ((weak, alias("bsp_start_default"))); diff --git a/bsps/arm/gumstix/start/linkcmds b/bsps/arm/gumstix/start/linkcmds new file mode 100644 index 0000000000..08cb2fc47a --- /dev/null +++ b/bsps/arm/gumstix/start/linkcmds @@ -0,0 +1,27 @@ +MEMORY { + SDRAM_MMU : ORIGIN = 0xa0000000, LENGTH = 16k + SDRAM : ORIGIN = 0xa0004000, LENGTH = 64M - 16k + SRAM : ORIGIN = 0x00000000, LENGTH = 16k +} + +REGION_ALIAS ("REGION_START", SDRAM); +REGION_ALIAS ("REGION_VECTOR", SDRAM); +REGION_ALIAS ("REGION_TEXT", SDRAM); +REGION_ALIAS ("REGION_TEXT_LOAD", SDRAM); +REGION_ALIAS ("REGION_RODATA", SDRAM); +REGION_ALIAS ("REGION_RODATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_DATA", SDRAM); +REGION_ALIAS ("REGION_DATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_FAST_TEXT", SDRAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", SDRAM); +REGION_ALIAS ("REGION_FAST_DATA", SDRAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_BSS", SDRAM); +REGION_ALIAS ("REGION_WORK", SDRAM); +REGION_ALIAS ("REGION_STACK", SDRAM); +REGION_ALIAS ("REGION_NOCACHE", SDRAM); +REGION_ALIAS ("REGION_NOCACHE_LOAD", SDRAM); + +_ttbl_base = ORIGIN (SDRAM_MMU); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/gumstix/start/memmap.c b/bsps/arm/gumstix/start/memmap.c new file mode 100644 index 0000000000..8923083576 --- /dev/null +++ b/bsps/arm/gumstix/start/memmap.c @@ -0,0 +1,17 @@ +/* + * Gumstix Memory Map + * 2008 By Yang Xi <hiyangxi@gmail.com> + * Copyright (c) 2004 by Cogent Computer Systems + * Written by Jay Monkman <jtm@lopingdog.com> + */ + +#include <rtems.h> +#include <libcpu/mmu.h> + +mmu_sect_map_t mem_map[] = { +/* <phys addr> <virt addr> <size> <flags> */ + {0x40000000, 0x40000000, 1216, MMU_CACHE_NONE}, /*Map I/O*/ + {0xA0000000, 0x00000000, 1, MMU_CACHE_NONE}, /*sram*/ + {0xA0000000, 0xA0000000, 64, MMU_CACHE_WBACK}, /* SDRAM */ + {0x00000000, 0x00000000, 0, 0} /* The end */ +}; diff --git a/bsps/arm/imx/start/bsp_specs b/bsps/arm/imx/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/imx/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/imx/start/bspreset.c b/bsps/arm/imx/start/bspreset.c new file mode 100644 index 0000000000..c3c9f69566 --- /dev/null +++ b/bsps/arm/imx/start/bspreset.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <bsp/bootcard.h> +#include <bsp.h> +#include <arm/freescale/imx/imx_wdogreg.h> + +void bsp_reset(void) +{ + volatile uint16_t *pcr; + + imx_uart_console_drain(); + + pcr = (volatile uint16_t *) 0x30280000; + *pcr = WDOG_CR_WDE; + *pcr = WDOG_CR_WDE; + *pcr = WDOG_CR_WDE; + + while (true) { + /* Wait */ + } +} diff --git a/bsps/arm/imx/start/bspsmp.c b/bsps/arm/imx/start/bspsmp.c new file mode 100644 index 0000000000..51c7aef12a --- /dev/null +++ b/bsps/arm/imx/start/bspsmp.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <rtems/score/smpimpl.h> + +#include <arm/freescale/imx/imx_srcreg.h> +#include <arm/freescale/imx/imx_gpcreg.h> + +#include <bsp/start.h> + +bool _CPU_SMP_Start_processor(uint32_t cpu_index) +{ + bool started; + + if (cpu_index == 1) { + volatile imx_src *src = (volatile imx_src *) 0x30390000; + volatile imx_gpc *gpc = (volatile imx_gpc *) 0x303a0000; + + src->gpr3 = (uint32_t) _start; + gpc->pgc_a7core0_ctrl |= IMX_GPC_PGC_CTRL_PCR; + gpc->cpu_pgc_sw_pup_req |= IMX_GPC_CPU_PGC_CORE1_A7; + + while ((gpc->cpu_pgc_pup_status1 & IMX_GPC_CPU_PGC_CORE1_A7) != 0) { + /* Wait */ + } + + gpc->pgc_a7core0_ctrl &= ~IMX_GPC_PGC_CTRL_PCR; + src->a7rcr1 |= IMX_SRC_A7RCR1_A7_CORE1_ENABLE; + + started = true; + } else { + started = false; + } + + return started; +} diff --git a/bsps/arm/imx/start/bspstart.c b/bsps/arm/imx/start/bspstart.c new file mode 100644 index 0000000000..046336655b --- /dev/null +++ b/bsps/arm/imx/start/bspstart.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/fatal.h> +#include <bsp/fdt.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> + +#include <libfdt.h> + +#define MAGIC_IRQ_OFFSET 32 + +void *imx_get_reg_of_node(const void *fdt, int node) +{ + int len; + const uint32_t *val; + + val = fdt_getprop(fdt, node, "reg", &len); + if (val == NULL || len < 4) { + return NULL; + } + + return (void *) fdt32_to_cpu(val[0]); +} + +rtems_vector_number imx_get_irq_of_node( + const void *fdt, + int node, + size_t index +) +{ + int len; + const uint32_t *val; + + val = fdt_getprop(fdt, node, "interrupts", &len); + if (val == NULL || len < (int) ((index + 1) * 12)) { + return UINT32_MAX; + } + + return fdt32_to_cpu(val[index * 3 + 1]) + MAGIC_IRQ_OFFSET; +} + +uint32_t bsp_fdt_map_intr(const uint32_t *intr, size_t icells) +{ + return intr[1] + MAGIC_IRQ_OFFSET; +} + +void arm_generic_timer_get_config( + uint32_t *frequency, + uint32_t *irq +) +{ + const void *fdt; + int node; + int len; + const uint32_t *val; + + fdt = bsp_fdt_get(); + node = fdt_path_offset(fdt, "/timer"); + + val = fdt_getprop(fdt, node, "clock-frequency", &len); + if (val != NULL && len >= 4) { + *frequency = fdt32_to_cpu(val[0]); + } else { + bsp_fatal(IMX_FATAL_GENERIC_TIMER_FREQUENCY); + } + + /* FIXME: Figure out how Linux gets a proper IRQ number */ + *irq = imx_get_irq_of_node(fdt, node, 0) - 16; +} + +void bsp_start(void) +{ + bsp_interrupt_initialize(); + rtems_cache_coherent_add_area( + bsp_section_nocacheheap_begin, + (uintptr_t) bsp_section_nocacheheap_size + ); +} diff --git a/bsps/arm/imx/start/bspstarthooks.c b/bsps/arm/imx/start/bspstarthooks.c new file mode 100644 index 0000000000..c75b03415b --- /dev/null +++ b/bsps/arm/imx/start/bspstarthooks.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013, 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#define ARM_CP15_TEXT_SECTION BSP_START_TEXT_SECTION + +#include <bsp.h> +#include <bsp/start.h> +#include <bsp/arm-cp15-start.h> +#include <bsp/arm-a9mpcore-start.h> + +BSP_START_DATA_SECTION static const arm_cp15_start_section_config +imx_mmu_config_table[] = { + ARMV7_CP15_START_DEFAULT_SECTIONS, + { + .begin = 0x07000000U, + .end = 0x70000000U, + .flags = ARMV7_MMU_DEVICE + } +}; + +BSP_START_TEXT_SECTION static void setup_mmu_and_cache(void) +{ + uint32_t ctrl = arm_cp15_start_setup_mmu_and_cache( + ARM_CP15_CTRL_A, + ARM_CP15_CTRL_AFE | ARM_CP15_CTRL_Z + ); + + arm_cp15_start_setup_translation_table_and_enable_mmu_and_cache( + ctrl, + (uint32_t *) bsp_translation_table_base, + ARM_MMU_DEFAULT_CLIENT_DOMAIN, + &imx_mmu_config_table[0], + RTEMS_ARRAY_SIZE(imx_mmu_config_table) + ); +} + +BSP_START_TEXT_SECTION void bsp_start_hook_0(void) +{ +#ifdef RTEMS_SMP + uint32_t cpu_id = arm_cortex_a9_get_multiprocessor_cpu_id(); + + arm_a9mpcore_start_enable_smp_in_auxiliary_control(); + + if (cpu_id != 0) { + arm_a9mpcore_start_on_secondary_processor(); + } +#endif +} + +BSP_START_TEXT_SECTION void bsp_start_hook_1(void) +{ + arm_a9mpcore_start_set_vector_base(); + bsp_start_copy_sections(); + setup_mmu_and_cache(); + bsp_start_clear_bss(); +} diff --git a/bsps/arm/imx/start/ccm.c b/bsps/arm/imx/start/ccm.c new file mode 100644 index 0000000000..bbb72db639 --- /dev/null +++ b/bsps/arm/imx/start/ccm.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <stdint.h> +#include <bspopts.h> + +#include <arm/freescale/imx/imx_ccmvar.h> + +uint32_t imx_ccm_ipg_hz(void) +{ + return IMX_CCM_IPG_HZ; +} + +uint32_t imx_ccm_uart_hz(void) +{ + return IMX_CCM_UART_HZ; +} + +uint32_t imx_ccm_ahb_hz(void) +{ + return IMX_CCM_AHB_HZ; +} diff --git a/bsps/arm/imx/start/imx_iomux.c b/bsps/arm/imx/start/imx_iomux.c new file mode 100644 index 0000000000..cd4591fa6f --- /dev/null +++ b/bsps/arm/imx/start/imx_iomux.c @@ -0,0 +1,424 @@ +/*- + * Copyright (c) 2014 Ian Lepore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/sys/arm/freescale/imx/imx_iomux.c 321938 2017-08-02 18:28:06Z ian $ + */ + +/* + * Pin mux and pad control driver for imx5 and imx6. + * + * This driver implements the fdt_pinctrl interface for configuring the gpio and + * peripheral pins based on fdt configuration data. + * + * When the driver attaches, it walks the entire fdt tree and automatically + * configures the pins for each device which has a pinctrl-0 property and whose + * status is "okay". In addition it implements the fdt_pinctrl_configure() + * method which any other driver can call at any time to reconfigure its pins. + * + * The nature of the fsl,pins property in fdt data makes this driver's job very + * easy. Instead of representing each pin and pad configuration using symbolic + * properties such as pullup-enable="true" and so on, the data simply contains + * the addresses of the registers that control the pins, and the raw values to + * store in those registers. + * + * The imx5 and imx6 SoCs also have a small number of "general purpose + * registers" in the iomuxc device which are used to control an assortment + * of completely unrelated aspects of SoC behavior. This driver provides other + * drivers with direct access to those registers via simple accessor functions. + */ + +#include <sys/param.h> +#ifndef __rtems__ +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/malloc.h> +#include <sys/rman.h> + +#include <machine/bus.h> + +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> +#include <dev/fdt/fdt_pinctrl.h> +#endif /* __rtems__ */ + +#include <arm/freescale/imx/imx_iomuxvar.h> +#ifndef __rtems__ +#include <arm/freescale/imx/imx_machdep.h> +#else /* __rtems__ */ +#include <bsp.h> +#include <bsp/fdt.h> +#include <rtems/sysinit.h> +#include <errno.h> +#include <libfdt.h> +#include <stdlib.h> + +typedef size_t bus_size_t; +typedef int phandle_t; +#endif /* __rtems__ */ + +struct iomux_softc { +#ifndef __rtems__ + device_t dev; + struct resource *mem_res; + u_int last_gpregaddr; +#else /* __rtems__ */ + volatile uint32_t *regs; +#endif /* __rtems__ */ +}; + +#ifndef __rtems__ +static struct iomux_softc *iomux_sc; + +static struct ofw_compat_data compat_data[] = { + {"fsl,imx6dl-iomuxc", true}, + {"fsl,imx6q-iomuxc", true}, + {"fsl,imx6sl-iomuxc", true}, + {"fsl,imx6ul-iomuxc", true}, + {"fsl,imx6sx-iomuxc", true}, + {"fsl,imx53-iomuxc", true}, + {"fsl,imx51-iomuxc", true}, + {NULL, false}, +}; +#else /* __rtems__ */ +static struct iomux_softc iomux_sc_instance; + +#define iomux_sc (&iomux_sc_instance); + +static void +imx_iomux_init(void) +{ + const void *fdt; + int node; + struct iomux_softc *sc; + + fdt = bsp_fdt_get(); + node = fdt_node_offset_by_compatible(fdt, -1, "fsl,imx7d-iomuxc"); + sc = iomux_sc; + sc->regs = imx_get_reg_of_node(fdt, node); +} + +RTEMS_SYSINIT_ITEM(imx_iomux_init, RTEMS_SYSINIT_BSP_START, + RTEMS_SYSINIT_ORDER_MIDDLE); + +#define OF_node_from_xref(phandle) fdt_node_offset_by_phandle(fdt, phandle) + +static int +imx_iomux_getencprop_alloc(const char *fdt, int node, const char *name, + size_t elsz, void **buf) +{ + int len; + const uint32_t *val; + int i; + uint32_t *cell; + + val = fdt_getprop(fdt, node, "fsl,pins", &len); + if (val == NULL || len < 0 || len % elsz != 0) { + return (-1); + } + + cell = malloc((size_t)len); + *buf = cell; + if (cell == NULL) { + return (-1); + } + + for (i = 0; i < len / 4; ++i) { + cell[i] = fdt32_to_cpu(val[i]); + } + + return (len / (int)elsz); +} + +#define OF_getencprop_alloc(node, name, elsz, buf) \ + imx_iomux_getencprop_alloc(fdt, node, name, elsz, buf) + +#define OF_prop_free(buf) free(buf) +#endif /* __rtems__ */ + +/* + * Each tuple in an fsl,pins property contains these fields. + */ +struct pincfg { + uint32_t mux_reg; + uint32_t padconf_reg; + uint32_t input_reg; + uint32_t mux_val; + uint32_t input_val; + uint32_t padconf_val; +}; + +#define PADCONF_NONE (1U << 31) /* Do not configure pad. */ +#define PADCONF_SION (1U << 30) /* Force SION bit in mux register. */ +#define PADMUX_SION (1U << 4) /* The SION bit in the mux register. */ + +static inline uint32_t +RD4(struct iomux_softc *sc, bus_size_t off) +{ + +#ifndef __rtems__ + return (bus_read_4(sc->mem_res, off)); +#else /* __rtems__ */ + return (sc->regs[off / 4]); +#endif /* __rtems__ */ +} + +static inline void +WR4(struct iomux_softc *sc, bus_size_t off, uint32_t val) +{ + +#ifndef __rtems__ + bus_write_4(sc->mem_res, off, val); +#else /* __rtems__ */ + sc->regs[off / 4] = val; +#endif /* __rtems__ */ +} + +static void +iomux_configure_input(struct iomux_softc *sc, uint32_t reg, uint32_t val) +{ + u_int select, mask, shift, width; + + /* If register and value are zero, there is nothing to configure. */ + if (reg == 0 && val == 0) + return; + + /* + * If the config value has 0xff in the high byte it is encoded: + * 31 23 15 7 0 + * | 0xff | shift | width | select | + * We need to mask out the old select value and OR in the new, using a + * mask of the given width and shifting the values up by shift. + */ + if ((val & 0xff000000) == 0xff000000) { + select = val & 0x000000ff; + width = (val & 0x0000ff00) >> 8; + shift = (val & 0x00ff0000) >> 16; + mask = ((1u << width) - 1) << shift; + val = (RD4(sc, reg) & ~mask) | (select << shift); + } + WR4(sc, reg, val); +} + +#ifndef __rtems__ +static int +iomux_configure_pins(device_t dev, phandle_t cfgxref) +#else /* __rtems__ */ +int imx_iomux_configure_pins(const void *fdt, uint32_t cfgxref) +#endif /* __rtems__ */ +{ + struct iomux_softc *sc; + struct pincfg *cfgtuples, *cfg; + phandle_t cfgnode; + int i, ntuples; + uint32_t sion; + +#ifndef __rtems__ + sc = device_get_softc(dev); +#else /* __rtems__ */ + sc = iomux_sc; +#endif /* __rtems__ */ + cfgnode = OF_node_from_xref(cfgxref); + ntuples = OF_getencprop_alloc(cfgnode, "fsl,pins", sizeof(*cfgtuples), + (void **)&cfgtuples); + if (ntuples < 0) + return (ENOENT); + if (ntuples == 0) + return (0); /* Empty property is not an error. */ + for (i = 0, cfg = cfgtuples; i < ntuples; i++, cfg++) { + sion = (cfg->padconf_val & PADCONF_SION) ? PADMUX_SION : 0; + WR4(sc, cfg->mux_reg, cfg->mux_val | sion); + iomux_configure_input(sc, cfg->input_reg, cfg->input_val); + if ((cfg->padconf_val & PADCONF_NONE) == 0) + WR4(sc, cfg->padconf_reg, cfg->padconf_val); +#ifndef __rtems__ + if (bootverbose) { + char name[32]; + OF_getprop(cfgnode, "name", &name, sizeof(name)); + printf("%16s: muxreg 0x%04x muxval 0x%02x " + "inpreg 0x%04x inpval 0x%02x " + "padreg 0x%04x padval 0x%08x\n", + name, cfg->mux_reg, cfg->mux_val | sion, + cfg->input_reg, cfg->input_val, + cfg->padconf_reg, cfg->padconf_val); + } +#endif /* __rtems__ */ + } + OF_prop_free(cfgtuples); + return (0); +} + +#ifndef __rtems__ +static int +iomux_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) + return (ENXIO); + + device_set_desc(dev, "Freescale i.MX pin configuration"); + return (BUS_PROBE_DEFAULT); +} + +static int +iomux_detach(device_t dev) +{ + + /* This device is always present. */ + return (EBUSY); +} + +static int +iomux_attach(device_t dev) +{ + struct iomux_softc * sc; + int rid; + + sc = device_get_softc(dev); + sc->dev = dev; + + switch (imx_soc_type()) { + case IMXSOC_51: + sc->last_gpregaddr = 1 * sizeof(uint32_t); + break; + case IMXSOC_53: + sc->last_gpregaddr = 2 * sizeof(uint32_t); + break; + case IMXSOC_6DL: + case IMXSOC_6S: + case IMXSOC_6SL: + case IMXSOC_6Q: + sc->last_gpregaddr = 13 * sizeof(uint32_t); + break; + case IMXSOC_6UL: + sc->last_gpregaddr = 14 * sizeof(uint32_t); + break; + default: + device_printf(dev, "Unknown SoC type\n"); + return (ENXIO); + } + + rid = 0; + sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (sc->mem_res == NULL) { + device_printf(dev, "Cannot allocate memory resources\n"); + return (ENXIO); + } + + iomux_sc = sc; + + /* + * Register as a pinctrl device, and call the convenience function that + * walks the entire device tree invoking FDT_PINCTRL_CONFIGURE() on any + * pinctrl-0 property cells whose xref phandle refers to a configuration + * that is a child node of our node in the tree. + * + * The pinctrl bindings documentation specifically mentions that the + * pinctrl device itself may have a pinctrl-0 property which contains + * static configuration to be applied at device init time. The tree + * walk will automatically handle this for us when it passes through our + * node in the tree. + */ + fdt_pinctrl_register(dev, "fsl,pins"); + fdt_pinctrl_configure_tree(dev); + + return (0); +} + +uint32_t +imx_iomux_gpr_get(u_int regaddr) +{ + struct iomux_softc * sc; + + sc = iomux_sc; + KASSERT(sc != NULL, ("%s called before attach", __FUNCTION__)); + KASSERT(regaddr >= 0 && regaddr <= sc->last_gpregaddr, + ("%s bad regaddr %u, max %u", __FUNCTION__, regaddr, + sc->last_gpregaddr)); + + return (RD4(iomux_sc, regaddr)); +} + +void +imx_iomux_gpr_set(u_int regaddr, uint32_t val) +{ + struct iomux_softc * sc; + + sc = iomux_sc; + KASSERT(sc != NULL, ("%s called before attach", __FUNCTION__)); + KASSERT(regaddr >= 0 && regaddr <= sc->last_gpregaddr, + ("%s bad regaddr %u, max %u", __FUNCTION__, regaddr, + sc->last_gpregaddr)); + + WR4(iomux_sc, regaddr, val); +} + +void +imx_iomux_gpr_set_masked(u_int regaddr, uint32_t clrbits, uint32_t setbits) +{ + struct iomux_softc * sc; + uint32_t val; + + sc = iomux_sc; + KASSERT(sc != NULL, ("%s called before attach", __FUNCTION__)); + KASSERT(regaddr >= 0 && regaddr <= sc->last_gpregaddr, + ("%s bad regaddr %u, max %u", __FUNCTION__, regaddr, + sc->last_gpregaddr)); + + val = RD4(iomux_sc, regaddr * 4); + val = (val & ~clrbits) | setbits; + WR4(iomux_sc, regaddr, val); +} + +static device_method_t imx_iomux_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, iomux_probe), + DEVMETHOD(device_attach, iomux_attach), + DEVMETHOD(device_detach, iomux_detach), + + /* fdt_pinctrl interface */ + DEVMETHOD(fdt_pinctrl_configure,iomux_configure_pins), + + DEVMETHOD_END +}; + +static driver_t imx_iomux_driver = { + "imx_iomux", + imx_iomux_methods, + sizeof(struct iomux_softc), +}; + +static devclass_t imx_iomux_devclass; + +EARLY_DRIVER_MODULE(imx_iomux, simplebus, imx_iomux_driver, + imx_iomux_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_LATE); + +#endif /* __rtems__ */ diff --git a/bsps/arm/imx/start/linkcmds.imx7 b/bsps/arm/imx/start/linkcmds.imx7 new file mode 100644 index 0000000000..750e1def1d --- /dev/null +++ b/bsps/arm/imx/start/linkcmds.imx7 @@ -0,0 +1,37 @@ +MEMORY { + RAM_MMU : ORIGIN = 0x80000000, LENGTH = 16k + NOCACHE : ORIGIN = 0x80100000, LENGTH = 1M + RAM : ORIGIN = 0x80200000, LENGTH = 512M - 2M +} + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_VECTOR", RAM); +REGION_ALIAS ("REGION_TEXT", RAM); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_RODATA", RAM); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", NOCACHE); + +bsp_processor_count = DEFINED (bsp_processor_count) ? bsp_processor_count : 2; + +bsp_stack_irq_size = DEFINED (bsp_stack_irq_size) ? bsp_stack_irq_size : 4096; +bsp_stack_abt_size = DEFINED (bsp_stack_abt_size) ? bsp_stack_abt_size : 1024; + +bsp_section_rwbarrier_align = DEFINED (bsp_section_rwbarrier_align) ? bsp_section_rwbarrier_align : 1M; + +bsp_vector_table_in_start_section = 1; + +bsp_translation_table_base = ORIGIN (RAM_MMU); +bsp_translation_table_end = ORIGIN (RAM_MMU) + LENGTH (RAM_MMU); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/lm3s69xx/start/bsp_specs b/bsps/arm/lm3s69xx/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/lm3s69xx/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/lm3s69xx/start/bspstart.c b/bsps/arm/lm3s69xx/start/bspstart.c new file mode 100644 index 0000000000..da3029e58c --- /dev/null +++ b/bsps/arm/lm3s69xx/start/bspstart.c @@ -0,0 +1,155 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * Copyright © 2013 Eugeniy Meshcheryakov <eugen@debian.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bspopts.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> +#include <bsp/lm3s69xx.h> +#include <bsp/io.h> +#include <bsp/syscon.h> +#include <assert.h> + +static void init_main_osc(void) +{ + volatile lm3s69xx_syscon *syscon = LM3S69XX_SYSCON; + + uint32_t sysdiv_val = LM3S69XX_PLL_FREQUENCY / LM3S69XX_SYSTEM_CLOCK; +#if defined(LM3S69XX_MCU_LM3S6965) || defined(LM3S69XX_MCU_LM3S3749) + assert(sysdiv_val * LM3S69XX_SYSTEM_CLOCK == LM3S69XX_PLL_FREQUENCY); +#endif + assert((sysdiv_val >= 4) && (sysdiv_val <= 16)); + + uint32_t rcc = syscon->rcc; + uint32_t rcc2 = syscon->rcc2; + + rcc = (rcc & ~SYSCONRCC_USESYSDIV) | SYSCONRCC_BYPASS; + rcc2 |= SYSCONRCC2_BYPASS2; + + syscon->rcc = rcc; + syscon->rcc2 = rcc2; + + /* + As per a note in Stellaris® LM4F120H5QR Microcontroller Data + Sheet on page 219: "When transitioning the system clock + configuration to use the MOSC as the fundamental clock source, the + MOSCDIS bit must be set prior to reselecting the MOSC or an + undefined system clock configuration can sporadically occur." + */ + + rcc |= SYSCONRCC_MOSCDIS; + syscon->rcc = rcc; + + rcc = (rcc & ~(SYSCONRCC_XTAL_MSK)) + | SYSCONRCC_XTAL(LM3S69XX_XTAL_CONFIG); + rcc2 = (rcc2 & ~(SYSCONRCC2_PWRDN2 | SYSCONRCC2_OSCSRC2_MSK)) + | SYSCONRCC2_USERCC2 | SYSCONRCC2_OSCSRC2(0x0); + + /* clear PLL lock interrupt */ + syscon->misc &= (SYSCONMISC_PLLLMIS); + + syscon->rcc = rcc; + syscon->rcc2 = rcc2; + lm3s69xx_syscon_delay_3x_clocks(16); + + /* since now, we'll use only RCC2 as SYSCONRCC2_USERCC2 and XTAL + (only available in RCC) are already set */ + + if (sysdiv_val % 2 == 0) { + rcc2 = (rcc2 & ~SYSCONRCC2_SYSDIV2_MSK) | SYSCONRCC2_SYSDIV2(sysdiv_val / 2 - 1); + + rcc2 &= ~(SYSCONRCC2_DIV400); + } + else { + /* need to use DIV400 */ + rcc2 = (rcc2 & ~SYSCONRCC2_SYSDIV2EXT_MSK) | SYSCONRCC2_SYSDIV2EXT(sysdiv_val - 1) + | SYSCONRCC2_DIV400; + } + syscon->rcc2 = rcc2; + + while ((syscon->ris & SYSCONRIS_PLLLRIS) == 0) + /* Wait for PLL lock */; + + rcc2 &= ~(SYSCONRCC2_BYPASS2); + + syscon->rcc2 = rcc2; + lm3s69xx_syscon_delay_3x_clocks(16); +} + +static const lm3s69xx_gpio_config start_config_gpio[] = { +#ifdef LM3S69XX_ENABLE_UART_0 +#if defined(LM3S69XX_MCU_LM3S3749) || defined(LM3S69XX_MCU_LM3S6965) || defined(LM3S69XX_MCU_LM4F120) + LM3S69XX_PIN_UART_RX(LM3S69XX_PORT_A, 0), + LM3S69XX_PIN_UART_TX(LM3S69XX_PORT_A, 1), +#else +#error No GPIO pin configuration for UART 0 +#endif +#endif /* LM3S69XX_ENABLE_UART_0 */ + +#ifdef LM3S69XX_ENABLE_UART_1 +#if defined(LM3S69XX_MCU_LM3S3749) + LM3S69XX_PIN_UART_RX(LM3S69XX_PORT_B, 0), + LM3S69XX_PIN_UART_TX(LM3S69XX_PORT_B, 1), +#elif defined(LM3S69XX_MCU_LM3S6965) + LM3S69XX_PIN_UART_RX(LM3S69XX_PORT_D, 2), + LM3S69XX_PIN_UART_TX(LM3S69XX_PORT_D, 3), +#elif defined(LM3S69XX_MCU_LM4F120) + LM3S69XX_PIN_UART_RX(LM3S69XX_PORT_B, 0), + LM3S69XX_PIN_UART_TX(LM3S69XX_PORT_B, 1), + LM3S69XX_PIN_UART_RTS(LM3S69XX_PORT_C, 4), + LM3S69XX_PIN_UART_CTS(LM3S69XX_PORT_C, 5), +#else +#error No GPIO pin configuration for UART 1 +#endif +#endif /* LM3S69XX_ENABLE_UART_1 */ + +#ifdef LM3S69XX_ENABLE_UART_2 +#if defined(LM3S69XX_MCU_LM3S3749) + LM3S69XX_PIN_UART_RX(LM3S69XX_PORT_D, 0), + LM3S69XX_PIN_UART_TX(LM3S69XX_PORT_D, 1), +#elif defined(LM3S69XX_MCU_LM3S6965) + LM3S69XX_PIN_UART_RX(LM3S69XX_PORT_G, 0), + LM3S69XX_PIN_UART_TX(LM3S69XX_PORT_G, 1), +#else +#error No GPIO pin configuration for UART 2 +#endif +#endif /* LM3S69XX_ENABLE_UART_2 */ +}; + +static void init_gpio(void) +{ +#if LM3S69XX_USE_AHB_FOR_GPIO + volatile lm3s69xx_syscon *syscon = LM3S69XX_SYSCON; + + syscon->gpiohbctl |= SYSCONGPIOHBCTL_PORTA | SYSCONGPIOHBCTL_PORTB + | SYSCONGPIOHBCTL_PORTC | SYSCONGPIOHBCTL_PORTD + | SYSCONGPIOHBCTL_PORTE | SYSCONGPIOHBCTL_PORTF +#if LM3S69XX_NUM_GPIO_BLOCKS > 6 + | SYSCONGPIOHBCTL_PORTG +#if LM3S69XX_NUM_GPIO_BLOCKS > 7 + | SYSCONGPIOHBCTL_PORTH +#endif +#endif + ; + +#endif /* LM3S69XX_USE_AHB_FOR_GPIO */ + + lm3s69xx_gpio_set_config_array(start_config_gpio, + sizeof(start_config_gpio) / sizeof(start_config_gpio[0])); +} + +void bsp_start(void) +{ + init_main_osc(); + init_gpio(); + bsp_interrupt_initialize(); +} diff --git a/bsps/arm/lm3s69xx/start/bspstarthook.c b/bsps/arm/lm3s69xx/start/bspstarthook.c new file mode 100644 index 0000000000..0524577ea7 --- /dev/null +++ b/bsps/arm/lm3s69xx/start/bspstarthook.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011-2012 Sebastian Huber. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/start.h> + +void BSP_START_TEXT_SECTION bsp_start_hook_0(void) +{ + /* Do nothing */ +} + +void BSP_START_TEXT_SECTION bsp_start_hook_1(void) +{ + bsp_start_copy_sections(); + bsp_start_clear_bss(); + + /* At this point we can use objects outside the .start section */ +} diff --git a/bsps/arm/lm3s69xx/start/io.c b/bsps/arm/lm3s69xx/start/io.c new file mode 100644 index 0000000000..b476e7b6dd --- /dev/null +++ b/bsps/arm/lm3s69xx/start/io.c @@ -0,0 +1,144 @@ +/* + * Copyright © 2013 Eugeniy Meshcheryakov <eugen@debian.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/io.h> +#include <bsp/lm3s69xx.h> +#include <bsp/syscon.h> +#include <rtems.h> + +static void set_bit(volatile uint32_t *reg, unsigned index, uint32_t set) +{ + uint32_t mask = 1U; + uint32_t val = *reg; + + val &= ~(mask << index); + val |= set << index; + + *reg = val; +} + +static void set_config(unsigned int pin, const lm3s69xx_gpio_config *config) +{ + unsigned int port = LM3S69XX_GPIO_PORT_OF_PIN(pin); + volatile lm3s69xx_gpio *gpio = LM3S69XX_GPIO(port); + unsigned int index = LM3S69XX_GPIO_INDEX_OF_PIN(pin); + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + + lm3s69xx_syscon_enable_gpio_clock(port, true); + + /* Disable digital and analog functions before reconfiguration. */ + set_bit(&gpio->den, index, 0); + set_bit(&gpio->amsel, index, 0); + + set_bit(&gpio->afsel, index, config->alternate); + set_bit(&gpio->dir, index, config->dir); + set_bit(&gpio->odr, index, config->otype); + + switch (config->drive) { + case LM3S69XX_GPIO_DRIVE_4MA: + gpio->dr4r |= 1 << index; + break; + case LM3S69XX_GPIO_DRIVE_8MA: + gpio->dr8r |= 1 << index; + break; + default: + gpio->dr2r |= 1 << index; + break; + } + + switch (config->pull) { + case LM3S69XX_GPIO_PULL_UP: + gpio->pur |= 1 << index; + break; + case LM3S69XX_GPIO_PULL_DOWN: + gpio->pdr |= 1 << index; + break; + default: + set_bit(&gpio->pdr, index, 0); + set_bit(&gpio->pur, index, 0); + break; + } + + set_bit(&gpio->slr, index, config->slr); + + set_bit(&gpio->den, index, config->digital); + set_bit(&gpio->amsel, index, config->analog); + + rtems_interrupt_enable(level); +} + +void lm3s69xx_gpio_set_config(const lm3s69xx_gpio_config *config) +{ + unsigned int current = config->pin_first; + unsigned int last = config->pin_last; + + while (current <= last) { + set_config(current, config); + current++; + } +} + +void lm3s69xx_gpio_set_config_array(const lm3s69xx_gpio_config *configs, unsigned int count) +{ + unsigned int i; + + for (i = 0; i < count; i++) + lm3s69xx_gpio_set_config(&configs[i]); +} + +/** + * Enables/disables digital function on the specified pin. + */ +void lm3s69xx_gpio_digital_enable(unsigned int pin, bool enable) +{ + unsigned int port = LM3S69XX_GPIO_PORT_OF_PIN(pin); + volatile lm3s69xx_gpio *gpio = LM3S69XX_GPIO(port); + unsigned int index = LM3S69XX_GPIO_INDEX_OF_PIN(pin); + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + set_bit(&gpio->den, index, enable); + rtems_interrupt_enable(level); +} + +/** + * Enables/disables analog mode on the specified pin. + */ +void lm3s69xx_gpio_analog_mode_select(unsigned int pin, bool enable) +{ + unsigned int port = LM3S69XX_GPIO_PORT_OF_PIN(pin); + volatile lm3s69xx_gpio *gpio = LM3S69XX_GPIO(port); + unsigned int index = LM3S69XX_GPIO_INDEX_OF_PIN(pin); + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + set_bit(&gpio->amsel, index, enable); + rtems_interrupt_enable(level); +} + +void lm3s69xx_gpio_set_pin(unsigned int pin, bool set) +{ + unsigned int port = LM3S69XX_GPIO_PORT_OF_PIN(pin); + volatile lm3s69xx_gpio *gpio = LM3S69XX_GPIO(port); + unsigned int index = LM3S69XX_GPIO_INDEX_OF_PIN(pin); + uint32_t mask = 1U << index; + + gpio->data[mask] = set ? mask : 0; +} + +bool lm3s69xx_gpio_get_pin(unsigned int pin) +{ + unsigned int port = LM3S69XX_GPIO_PORT_OF_PIN(pin); + volatile lm3s69xx_gpio *gpio = LM3S69XX_GPIO(port); + unsigned int index = LM3S69XX_GPIO_INDEX_OF_PIN(pin); + uint32_t mask = 1U << index; + + return gpio->data[mask] != 0; +} diff --git a/bsps/arm/lm3s69xx/start/linkcmds.lm3s3749 b/bsps/arm/lm3s69xx/start/linkcmds.lm3s3749 new file mode 100644 index 0000000000..ff165c7835 --- /dev/null +++ b/bsps/arm/lm3s69xx/start/linkcmds.lm3s3749 @@ -0,0 +1,30 @@ +/** + * @file + * + * @brief Memory map. + */ + +MEMORY { + RAM_INT (AIW) : ORIGIN = 0x20000000, LENGTH = 64K + ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 128K +} + +REGION_ALIAS ("REGION_START", ROM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_INT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_INT); +REGION_ALIAS ("REGION_WORK", RAM_INT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/lm3s69xx/start/linkcmds.lm3s6965 b/bsps/arm/lm3s69xx/start/linkcmds.lm3s6965 new file mode 100644 index 0000000000..02d2487dc9 --- /dev/null +++ b/bsps/arm/lm3s69xx/start/linkcmds.lm3s6965 @@ -0,0 +1,30 @@ +/** + * @file + * + * @brief Memory map. + */ + +MEMORY { + RAM_INT (AIW) : ORIGIN = 0x20000000, LENGTH = 64K + ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 256K +} + +REGION_ALIAS ("REGION_START", ROM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_INT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_INT); +REGION_ALIAS ("REGION_WORK", RAM_INT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/lm3s69xx/start/linkcmds.lm3s6965_qemu b/bsps/arm/lm3s69xx/start/linkcmds.lm3s6965_qemu new file mode 100644 index 0000000000..a4d3a1972d --- /dev/null +++ b/bsps/arm/lm3s69xx/start/linkcmds.lm3s6965_qemu @@ -0,0 +1,30 @@ +/** + * @file + * + * @brief Memory map. + */ + +MEMORY { + RAM_INT (AIW) : ORIGIN = 0x20000000, LENGTH = 16M + ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 64M +} + +REGION_ALIAS ("REGION_START", ROM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_INT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_INT); +REGION_ALIAS ("REGION_WORK", RAM_INT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/lm3s69xx/start/linkcmds.lm4f120 b/bsps/arm/lm3s69xx/start/linkcmds.lm4f120 new file mode 100644 index 0000000000..e995a3ddbf --- /dev/null +++ b/bsps/arm/lm3s69xx/start/linkcmds.lm4f120 @@ -0,0 +1,30 @@ +/** + * @file + * + * @brief Memory map. + */ + +MEMORY { + RAM_INT (AIW) : ORIGIN = 0x20000000, LENGTH = 32K + ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 256K +} + +REGION_ALIAS ("REGION_START", ROM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_INT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_INT); +REGION_ALIAS ("REGION_WORK", RAM_INT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/lm3s69xx/start/syscon.c b/bsps/arm/lm3s69xx/start/syscon.c new file mode 100644 index 0000000000..1f5a1a3596 --- /dev/null +++ b/bsps/arm/lm3s69xx/start/syscon.c @@ -0,0 +1,115 @@ +/* + * Copyright © 2013 Eugeniy Meshcheryakov <eugen@debian.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/syscon.h> +#include <bsp/lm3s69xx.h> +#include <rtems.h> + +static void delay_3_clocks(void) +{ + asm volatile( + "nop\n\t" + "nop\n\t" + "nop"); +} + +void __attribute__((naked)) lm3s69xx_syscon_delay_3x_clocks(unsigned long x_count) +{ + asm volatile( + "subs r0, #1\n\t" + "bne lm3s69xx_syscon_delay_3x_clocks\n\t" + "bx lr" + ); +} + +void lm3s69xx_syscon_enable_gpio_clock(unsigned int port, bool enable) +{ + volatile lm3s69xx_syscon *syscon = LM3S69XX_SYSCON; + uint32_t mask = 1 << port; + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + + if (enable) + syscon->rcgc2 |= mask; + else + syscon->rcgc2 &= ~mask; + + delay_3_clocks(); + + rtems_interrupt_enable(level); +} + +void lm3s69xx_syscon_enable_uart_clock(unsigned int port, bool enable) +{ + volatile lm3s69xx_syscon *syscon = LM3S69XX_SYSCON; + uint32_t mask = 1 << port; + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + + if (enable) + syscon->rcgc1 |= mask; + else + syscon->rcgc1 &= ~mask; + + delay_3_clocks(); + + rtems_interrupt_enable(level); +} + +void lm3s69xx_syscon_enable_ssi_clock(unsigned int port, bool enable) +{ + volatile lm3s69xx_syscon *syscon = LM3S69XX_SYSCON; + uint32_t mask = 1 << (port + 4); + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + + if (enable) + syscon->rcgc1 |= mask; + else + syscon->rcgc1 &= ~mask; + + delay_3_clocks(); + + rtems_interrupt_enable(level); +} + +void lm3s69xx_syscon_enable_pwm_clock(bool enable) +{ + volatile lm3s69xx_syscon *syscon = LM3S69XX_SYSCON; + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + + if (enable) + syscon->rcgc0 |= SYSCONRCGC0_PWM; + else + syscon->rcgc0 &= ~SYSCONRCGC0_PWM; + + delay_3_clocks(); + + rtems_interrupt_enable(level); +} + +/** + * Sets PWMDIV field in the RCC register. + * + * @note div should be one of SCRCC_PWMDIV_DIV?_VAL constants. + */ +void lm3s69xx_syscon_set_pwmdiv(unsigned int div) +{ + volatile lm3s69xx_syscon *syscon = LM3S69XX_SYSCON; + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + syscon->rcc = (syscon->rcc & ~SYSCONRCC_PWMDIV_MSK) | SYSCONRCC_PWMDIV(div) + | SYSCONRCC_USEPWMDIV; + rtems_interrupt_enable(level); +} diff --git a/bsps/arm/lpc176x/start/bsp_specs b/bsps/arm/lpc176x/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/lpc176x/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/lpc176x/start/bspstart.c b/bsps/arm/lpc176x/start/bspstart.c new file mode 100644 index 0000000000..f1aba444fc --- /dev/null +++ b/bsps/arm/lpc176x/start/bspstart.c @@ -0,0 +1,91 @@ +/** + * @file + * + * @ingroup lpc176x + * + * @brief Startup code. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/io.h> +#include <bsp/irq.h> +#include <bsp/dma.h> +#include <bsp/bootcard.h> +#include <bsp/timer.h> +#include <bsp/irq-generic.h> +#include <bsp/system-clocks.h> +#include <bsp/linker-symbols.h> +#include <bsp/common-types.h> +#include <bsp/uart-output-char.h> + +#ifdef LPC176X_HEAP_EXTEND +LINKER_SYMBOL( lpc176x_region_heap_0_begin ); +LINKER_SYMBOL( lpc176x_region_heap_0_size ); +LINKER_SYMBOL( lpc176x_region_heap_0_end ); +LINKER_SYMBOL( lpc176x_region_heap_1_begin ); +LINKER_SYMBOL( lpc176x_region_heap_1_size ); +LINKER_SYMBOL( lpc176x_region_heap_1_end ); +extern Heap_Control *RTEMS_Malloc_Heap; +#endif + +static void heap_extend( void ) +{ +#ifdef LPC176X_HEAP_EXTEND + _Heap_Extend( RTEMS_Malloc_Heap, + lpc176x_region_heap_0_begin, + (uintptr_t) lpc176x_region_heap_0_size, + NULL ); + _Heap_Extend( RTEMS_Malloc_Heap, + lpc176x_region_heap_1_begin, + (uintptr_t) lpc176x_region_heap_1_size, + NULL ); +#endif +} + +/** + * @brief Console initialization + */ +static void initialize_console( void ) +{ +#ifdef LPC176X_CONFIG_CONSOLE + + lpc176x_module_enable( LPC176X_MODULE_UART_0, LPC176X_MODULE_PCLK_DEFAULT ); + + lpc176x_pin_select( LPC176X_PIN_UART_0_TXD, LPC176X_PIN_FUNCTION_01 ); + lpc176x_pin_select( LPC176X_PIN_UART_0_RXD, LPC176X_PIN_FUNCTION_01 ); + + BSP_CONSOLE_UART_INIT( LPC176X_PCLK / 16 / LPC176X_UART_BAUD ); +#endif +} + +void bsp_start( void ) +{ + /* Initialize console */ + initialize_console(); + + /*Initialize timer*/ + lpc176x_timer_init( LPC176X_TIMER_1 ); + lpc176x_timer_start( LPC176X_TIMER_1 ); + + /* Interrupts */ + bsp_interrupt_initialize(); + + /* DMA */ + lpc176x_dma_initialize(); + + heap_extend(); +} diff --git a/bsps/arm/lpc176x/start/bspstarthooks.c b/bsps/arm/lpc176x/start/bspstarthooks.c new file mode 100644 index 0000000000..a60c5bdf89 --- /dev/null +++ b/bsps/arm/lpc176x/start/bspstarthooks.c @@ -0,0 +1,227 @@ +/** + * @file bspstarthooks.c + * + * @ingroup lpc176x + * + * @brief First configurations and initializations to the correct + * functionality of the board. + */ + +/* + * Copyright (c) 2014 Taller Technologies. + * + * @author Boretto Martin (martin.boretto@tallertechnologies.com) + * @author Diaz Marcos (marcos.diaz@tallertechnologies.com) + * @author Lenarduzzi Federico (federico.lenarduzzi@tallertechnologies.com) + * @author Daniel Chicco (daniel.chicco@tallertechnologies.com) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/start.h> +#include <bsp/io.h> + +/** + * @brief Initializes the oscillator according to the lpc176x board. + */ +static BSP_START_TEXT_SECTION void lpc176x_init_main_oscillator( void ) +{ + if ( ( LPC176X_SCB.scs & LPC176X_SCB_SCS_OSC_STATUS ) == 0u ) { + LPC176X_SCB.scs |= LPC176X_SCB_SCS_OSC_ENABLE; + + while ( ( LPC176X_SCB.scs & LPC176X_SCB_SCS_OSC_STATUS ) == 0u ) { + /* Wait. */ + } + } + + /* else implies that the oscillator is initialized. Also, + there is nothing to do. */ +} + +/** + * @brief Sets the PLL configuration. + * + * @param pll Value to set. + * @param val Set value. + */ +static BSP_START_TEXT_SECTION void lpc176x_pll_config( const uint32_t val ) +{ + ( LPC176X_SCB.pll_0 ).con = val; + /* The two register writes must be in correct sequence. */ + ( LPC176X_SCB.pll_0 ).feed = LPC176X_PLL0CON; + ( LPC176X_SCB.pll_0 ).feed = LPC176X_PLL0CFG; +} + +/** + * @brief Sets the PLL. + * + * @param msel Multiplier value. + * @param psel Divider value. + * @param cclkdiv Divisor clock. + */ +static BSP_START_TEXT_SECTION void lpc176x_set_pll( + const unsigned msel, + const unsigned psel, + const unsigned cclkdiv +) +{ + const uint32_t pllcfg = LPC176X_PLL_SEL_MSEL( msel ) | + LPC176X_PLL_SEL_PSEL( psel ); + const uint32_t pllstat = LPC176X_PLL_STAT_PLLE | LPC176X_PLL_STAT_PLOCK | + pllcfg; + const uint32_t cclksel_cclkdiv = LPC176X_SCB_CCLKSEL_CCLKDIV( cclkdiv ); + + if ( ( LPC176X_SCB.pll_0 ).stat != pllstat + || LPC176X_SCB.cclksel != cclksel_cclkdiv + || LPC176X_SCB.clksrcsel != LPC176X_SCB_CLKSRCSEL_CLKSRC ) { + lpc176x_pll_config( ( LPC176X_SCB.pll_0 ).con & ~LPC176X_PLL_CON_PLLC ); + + /* Turn off USB. */ + LPC176X_SCB.usbclksel = 0u; + + /* Disable PLL. */ + lpc176x_pll_config( 0u ); + + /* Use SYSCLK for CCLK. */ + LPC176X_SCB.cclksel = LPC176X_SCB_CCLKSEL_CCLKDIV( 0u ); + + /* Set the CCLK, PCLK and EMCCLK divider. */ + LPC176X_SCB.cclksel = cclksel_cclkdiv; + + /* Select main oscillator as clock source. */ + LPC176X_SCB.clksrcsel = LPC176X_SCB_CLKSRCSEL_CLKSRC; + + /* The two register writes must be in correct sequence. */ + /* Set PLL configuration. */ + ( LPC176X_SCB.pll_0 ).cfg = pllcfg; + ( LPC176X_SCB.pll_0 ).feed = LPC176X_PLL0CON; + ( LPC176X_SCB.pll_0 ).feed = LPC176X_PLL0CFG; + + /* Enable PLL. */ + lpc176x_pll_config( LPC176X_PLL_CON_PLLE ); + + /* Wait for lock. */ + while ( ( ( LPC176X_SCB.pll_0 ).stat & LPC176X_PLL_STAT_PLOCK ) == 0u ) { + /* Wait */ + } + + /* Connect PLL. */ + lpc176x_pll_config( ( LPC176X_PLL_CON_PLLE | LPC176X_PLL_CON_PLLC ) ); + + /* Wait for connected and enabled. */ + while ( ( ( LPC176X_SCB.pll_0 ).stat & ( LPC176X_PLL_STAT_PLLE | + LPC176X_PLL_STAT_PLLC ) ) == + 0u ) { + /* Wait */ + } + } + + /* else implies that the pll has a wrong value. Also, + there is nothing to do. */ +} + +/** + * @brief Pll initialization. + */ +static BSP_START_TEXT_SECTION void lpc176x_init_pll( void ) +{ +#if ( LPC176X_OSCILLATOR_MAIN == 12000000u ) +#if ( LPC176X_CCLK == 96000000U ) + lpc176x_set_pll( 11u, 0u, 2u ); +#else +#error "unexpected CCLK" +#endif +#else +#error "unexpected main oscillator frequency" +#endif +} + +/** + * @brief Memory map initialization. + */ +static BSP_START_TEXT_SECTION void lpc176x_init_memory_map( void ) +{ + LPC176X_SCB.memmap = LPC176X_SCB_MEMMAP_MAP; +} + +/** + * @brief Memory accelerator initialization. + */ +static BSP_START_TEXT_SECTION void lpc176x_init_memory_accelerator( void ) +{ +#if ( LPC176X_CCLK <= 20000000U ) + LPC176X_SCB.flashcfg = LPC176X_SCB_FLASHCFG_FLASHTIM( 0x0U ); +#elif ( LPC176X_CCLK <= 40000000U ) + LPC176X_SCB.flashcfg = LPC176X_SCB_FLASHCFG_FLASHTIM( 0x1U ); +#elif ( LPC176X_CCLK <= 60000000U ) + LPC176X_SCB.flashcfg = LPC176X_SCB_FLASHCFG_FLASHTIM( 0x2U ); +#elif ( LPC176X_CCLK <= 80000000U ) + LPC176X_SCB.flashcfg = LPC176X_SCB_FLASHCFG_FLASHTIM( 0x3U ); +#elif ( LPC176X_CCLK <= 100000000U ) + LPC176X_SCB.flashcfg = LPC176X_SCB_FLASHCFG_FLASHTIM( 0x4U ); +#else + LPC176X_SCB.flashcfg = LPC176X_SCB_FLASHCFG_FLASHTIM( 0x5U ); +#endif +} + +/** + * @brief Stops the gpdma device. + */ +static BSP_START_TEXT_SECTION void lpc176x_stop_gpdma( void ) +{ +#ifdef LPC176X_STOP_GPDMA + + bool has_power = ( LPC176X_SCB.pconp & LPC176X_SCB_PCONP_GPDMA ) != 0u; + + if ( has_power ) { + GPDMA_CONFIG = 0u; + LPC176X_SCB.pconp &= ~LPC176X_SCB_PCONP_GPDMA; + } + + /* else implies that the current module (gpdma) is turn off. Also, + there is nothing to do. */ + +#endif +} + +/** + * @brief Stops the usb device. + */ +static BSP_START_TEXT_SECTION void lpc176x_stop_usb( void ) +{ +#ifdef LPC176X_STOP_USB + + bool has_power = ( LPC176X_SCB.pconp & LPC176X_SCB_PCONP_USB ) != 0u; + + if ( has_power ) { + OTG_CLK_CTRL = 0u; + + LPC176X_SCB.pconp &= ~LPC176X_SCB_PCONP_USB; + LPC176X_SCB.usbclksel = 0u; + } + + /* else implies that the current module (usb) is turn off. Also, + there is nothing to do. */ +#endif +} + +BSP_START_TEXT_SECTION void bsp_start_hook_0( void ) +{ + lpc176x_init_main_oscillator(); + lpc176x_init_pll(); +} + +BSP_START_TEXT_SECTION void bsp_start_hook_1( void ) +{ + lpc176x_init_memory_map(); + lpc176x_init_memory_accelerator(); + lpc176x_stop_gpdma(); + lpc176x_stop_usb(); + bsp_start_copy_sections(); + bsp_start_clear_bss(); + + /* At this point we can use objects outside the .start section */ +}
\ No newline at end of file diff --git a/bsps/arm/lpc176x/start/linkcmds.lpc1768_mbed b/bsps/arm/lpc176x/start/linkcmds.lpc1768_mbed new file mode 100644 index 0000000000..133d2f487c --- /dev/null +++ b/bsps/arm/lpc176x/start/linkcmds.lpc1768_mbed @@ -0,0 +1,29 @@ +/* LPC1768 OEM Board from Embedded Artists */ + +MEMORY { + ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 512k + RAM_INT (AIW) : ORIGIN = 0x10000000, LENGTH = 32k +} + +REGION_ALIAS ("REGION_START", ROM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_INT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_INT); +REGION_ALIAS ("REGION_WORK", RAM_INT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +bsp_stack_main_size = DEFINED (bsp_stack_main_size) ? bsp_stack_main_size : 1024; +bsp_stack_main_size = ALIGN (bsp_stack_main_size, bsp_stack_align); + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/lpc176x/start/linkcmds.lpc1768_mbed_ahb_ram b/bsps/arm/lpc176x/start/linkcmds.lpc1768_mbed_ahb_ram new file mode 100644 index 0000000000..75bdd75d83 --- /dev/null +++ b/bsps/arm/lpc176x/start/linkcmds.lpc1768_mbed_ahb_ram @@ -0,0 +1,30 @@ +/* LPC1768 OEM Board from Embedded Artists */ + +MEMORY { + ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 512k + RAM_INT (AIW) : ORIGIN = 0x10000000, LENGTH = 32k + RAM_AHB (AIW) : ORIGIN = 0x2007C000, LENGTH = 32k +} + +REGION_ALIAS ("REGION_START", ROM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_INT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_INT); +REGION_ALIAS ("REGION_WORK", RAM_AHB); +REGION_ALIAS ("REGION_STACK", RAM_AHB); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +bsp_stack_main_size = DEFINED (bsp_stack_main_size) ? bsp_stack_main_size : 1024; +bsp_stack_main_size = ALIGN (bsp_stack_main_size, bsp_stack_align); + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/lpc176x/start/linkcmds.lpc1768_mbed_ahb_ram_eth b/bsps/arm/lpc176x/start/linkcmds.lpc1768_mbed_ahb_ram_eth new file mode 100644 index 0000000000..7d91d8a5ef --- /dev/null +++ b/bsps/arm/lpc176x/start/linkcmds.lpc1768_mbed_ahb_ram_eth @@ -0,0 +1,41 @@ +/* LPC1768 OEM Board from Embedded Artists */ + +MEMORY { + ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 512k + RAM_INT (AIW) : ORIGIN = 0x10000000, LENGTH = 32k + RAM_AHB1 (AIW) : ORIGIN = 0x2007C000, LENGTH = 16k + RAM_AHB2 (AIW) : ORIGIN = 0x20080000, LENGTH = 16k +} + +REGION_ALIAS ("REGION_START", ROM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_INT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_AHB1); +REGION_ALIAS ("REGION_WORK", RAM_INT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_ETH", RAM_AHB2); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +bsp_stack_main_size = DEFINED (bsp_stack_main_size) ? bsp_stack_main_size : 1024; +bsp_stack_main_size = ALIGN (bsp_stack_main_size, bsp_stack_align); + +SECTIONS { + .eth (NOLOAD) : ALIGN_WITH_INPUT { + bsp_section_eth_begin = .; + *(.eth) + bsp_section_eth_end = .; + } > REGION_ETH AT > REGION_ETH + bsp_section_eth_size = bsp_section_eth_end - bsp_section_eth_begin; +} + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/lpc24xx/start/bsp_specs b/bsps/arm/lpc24xx/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/lpc24xx/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/lpc24xx/start/bspreset-armv4.c b/bsps/arm/lpc24xx/start/bspreset-armv4.c new file mode 100644 index 0000000000..c53b4e2447 --- /dev/null +++ b/bsps/arm/lpc24xx/start/bspreset-armv4.c @@ -0,0 +1,51 @@ +/** + * @file + * + * @ingroup lpc24xx + * + * @brief Reset code. + */ + +/* + * Copyright (c) 2008-2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <rtems.h> +#include <rtems/score/armv7m.h> + +#include <bsp/bootcard.h> +#include <bsp/lpc24xx.h> +#include <bsp/start.h> + +#ifdef ARM_MULTILIB_ARCH_V4 + +BSP_START_TEXT_SECTION __attribute__((flatten)) void bsp_reset(void) +{ + rtems_interrupt_level level; + + (void) level; + rtems_interrupt_disable(level); + + /* Trigger watchdog reset */ + WDCLKSEL = 0; + WDTC = 0xff; + WDMOD = 0x3; + WDFEED = 0xaa; + WDFEED = 0x55; + + while (true) { + /* Do nothing */ + } +} + +#endif /* ARM_MULTILIB_ARCH_V4 */ diff --git a/bsps/arm/lpc24xx/start/bspstart.c b/bsps/arm/lpc24xx/start/bspstart.c new file mode 100644 index 0000000000..6f00f35f99 --- /dev/null +++ b/bsps/arm/lpc24xx/start/bspstart.c @@ -0,0 +1,96 @@ +/** + * @file + * + * @ingroup lpc24xx + * + * @brief Startup code. + */ + +/* + * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/dma.h> +#include <bsp/io.h> +#include <bsp/irq-generic.h> +#include <bsp/irq.h> +#include <bsp/linker-symbols.h> +#include <bsp/lpc24xx.h> +#include <bsp/system-clocks.h> +#include <bsp/uart-output-char.h> + +#ifdef LPC24XX_HEAP_EXTEND + LINKER_SYMBOL(lpc24xx_region_heap_0_begin); + LINKER_SYMBOL(lpc24xx_region_heap_0_size); + LINKER_SYMBOL(lpc24xx_region_heap_0_end); + + LINKER_SYMBOL(lpc24xx_region_heap_1_begin); + LINKER_SYMBOL(lpc24xx_region_heap_1_size); + LINKER_SYMBOL(lpc24xx_region_heap_1_end); + + extern Heap_Control *RTEMS_Malloc_Heap; +#endif + +static void heap_extend(void) +{ + #ifdef LPC24XX_HEAP_EXTEND + _Heap_Extend( + RTEMS_Malloc_Heap, + lpc24xx_region_heap_0_begin, + (uintptr_t) lpc24xx_region_heap_0_size, + 0 + ); + _Heap_Extend( + RTEMS_Malloc_Heap, + lpc24xx_region_heap_1_begin, + (uintptr_t) lpc24xx_region_heap_1_size, + 0 + ); + #endif +} + +static void initialize_console(void) +{ + #ifdef LPC24XX_CONFIG_CONSOLE + static const lpc24xx_pin_range pins [] = { + LPC24XX_PIN_UART_0_TXD, + LPC24XX_PIN_UART_0_RXD, + LPC24XX_PIN_TERMINAL + }; + + lpc24xx_module_enable(LPC24XX_MODULE_UART_0, LPC24XX_MODULE_PCLK_DEFAULT); + lpc24xx_pin_config(&pins [0], LPC24XX_PIN_SET_FUNCTION); + BSP_CONSOLE_UART_INIT(LPC24XX_PCLK / 16 / LPC24XX_UART_BAUD); + #endif +} + +void bsp_start(void) +{ + /* Initialize Timer 1 */ + lpc24xx_module_enable(LPC24XX_MODULE_TIMER_1, LPC24XX_MODULE_PCLK_DEFAULT); + + /* Initialize standard timer */ + lpc24xx_timer_initialize(); + + initialize_console(); + + /* Interrupts */ + bsp_interrupt_initialize(); + + /* DMA */ + lpc24xx_dma_initialize(); + + heap_extend(); +} diff --git a/bsps/arm/lpc24xx/start/bspstarthooks.c b/bsps/arm/lpc24xx/start/bspstarthooks.c new file mode 100644 index 0000000000..6ceb066935 --- /dev/null +++ b/bsps/arm/lpc24xx/start/bspstarthooks.c @@ -0,0 +1,533 @@ +/** + * @file + * + * @ingroup lpc24xx + * + * @brief Startup code. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/io.h> +#include <bsp/start.h> +#include <bsp/lpc24xx.h> +#include <bsp/lpc-emc.h> +#include <bsp/start-config.h> + +static BSP_START_TEXT_SECTION void lpc24xx_cpu_delay(unsigned ticks) +{ + unsigned i = 0; + + /* One loop execution needs four instructions */ + ticks /= 4; + + for (i = 0; i <= ticks; ++i) { + __asm__ volatile ("nop"); + } +} + +static BSP_START_TEXT_SECTION void lpc24xx_udelay(unsigned us) +{ + lpc24xx_cpu_delay(us * (LPC24XX_CCLK / 1000000)); +} + +static BSP_START_TEXT_SECTION void lpc24xx_init_pinsel(void) +{ + lpc24xx_pin_config( + &lpc24xx_start_config_pinsel [0], + LPC24XX_PIN_SET_FUNCTION + ); +} + +static BSP_START_TEXT_SECTION void lpc24xx_init_emc_static(void) +{ + size_t i = 0; + size_t chip_count = lpc24xx_start_config_emc_static_chip_count; + + for (i = 0; i < chip_count; ++i) { + const lpc24xx_emc_static_chip_config *chip_config = + &lpc24xx_start_config_emc_static_chip [i]; + lpc24xx_emc_static_chip_config chip_config_on_stack; + size_t config_size = sizeof(chip_config_on_stack.config); + + bsp_start_memcpy( + (int *) &chip_config_on_stack.config, + (const int *) &chip_config->config, + config_size + ); + bsp_start_memcpy( + (int *) chip_config->chip_select, + (const int *) &chip_config_on_stack.config, + config_size + ); + } +} + +static BSP_START_TEXT_SECTION void lpc24xx_init_emc_dynamic(void) +{ + size_t chip_count = lpc24xx_start_config_emc_dynamic_chip_count; + + if (chip_count > 0) { + bool do_initialization = true; + size_t i = 0; + + for (i = 0; do_initialization && i < chip_count; ++i) { + const lpc24xx_emc_dynamic_chip_config *chip_cfg = + &lpc24xx_start_config_emc_dynamic_chip [i]; + volatile lpc_emc_dynamic *chip_select = chip_cfg->chip_select; + + do_initialization = (chip_select->config & EMC_DYN_CFG_B) == 0; + } + + if (do_initialization) { + volatile lpc_emc *emc = (volatile lpc_emc *) EMC_BASE_ADDR; + const lpc24xx_emc_dynamic_config *cfg = + &lpc24xx_start_config_emc_dynamic [0]; + uint32_t dynamiccontrol = EMC_DYN_CTRL_CE | EMC_DYN_CTRL_CS; + + #ifdef ARM_MULTILIB_ARCH_V7M + volatile lpc17xx_scb *scb = &LPC17XX_SCB; + + /* Delay control */ + scb->emcdlyctl = cfg->emcdlyctl; + #endif + + emc->dynamicreadconfig = cfg->readconfig; + + /* Timings */ + emc->dynamictrp = cfg->trp; + emc->dynamictras = cfg->tras; + emc->dynamictsrex = cfg->tsrex; + emc->dynamictapr = cfg->tapr; + emc->dynamictdal = cfg->tdal; + emc->dynamictwr = cfg->twr; + emc->dynamictrc = cfg->trc; + emc->dynamictrfc = cfg->trfc; + emc->dynamictxsr = cfg->txsr; + emc->dynamictrrd = cfg->trrd; + emc->dynamictmrd = cfg->tmrd; + + /* NOP period */ + emc->dynamiccontrol = dynamiccontrol | EMC_DYN_CTRL_I_NOP; + lpc24xx_udelay(200); + + /* Precharge */ + emc->dynamiccontrol = dynamiccontrol | EMC_DYN_CTRL_I_PALL; + emc->dynamicrefresh = 1; + + /* + * Perform several refresh cycles with a memory refresh every 16 AHB + * clock cycles. Wait until eight SDRAM refresh cycles have occurred + * (128 AHB clock cycles). + */ + lpc24xx_cpu_delay(128); + + /* Refresh timing */ + emc->dynamicrefresh = cfg->refresh; + lpc24xx_cpu_delay(128); + + for (i = 0; i < chip_count; ++i) { + const lpc24xx_emc_dynamic_chip_config *chip_cfg = + &lpc24xx_start_config_emc_dynamic_chip [i]; + volatile lpc_emc_dynamic *chip_select = chip_cfg->chip_select; + uint32_t config = chip_cfg->config; + + /* Chip select */ + chip_select->config = config; + chip_select->rascas = chip_cfg->rascas; + + /* Set modes */ + emc->dynamiccontrol = dynamiccontrol | EMC_DYN_CTRL_I_MODE; + *(volatile uint32_t *)(chip_cfg->address + chip_cfg->mode); + + /* Enable buffer */ + chip_select->config = config | EMC_DYN_CFG_B; + } + + emc->dynamiccontrol = 0; + } + } +} + +static BSP_START_TEXT_SECTION void lpc24xx_init_main_oscillator(void) +{ + #ifdef ARM_MULTILIB_ARCH_V4 + if ((SCS & 0x40) == 0) { + SCS |= 0x20; + while ((SCS & 0x40) == 0) { + /* Wait */ + } + } + #else + volatile lpc17xx_scb *scb = &LPC17XX_SCB; + + if ((scb->scs & LPC17XX_SCB_SCS_OSC_STATUS) == 0) { + scb->scs |= LPC17XX_SCB_SCS_OSC_ENABLE; + while ((scb->scs & LPC17XX_SCB_SCS_OSC_STATUS) == 0) { + /* Wait */ + } + } + #endif +} + +#ifdef ARM_MULTILIB_ARCH_V4 + +static BSP_START_TEXT_SECTION void lpc24xx_pll_config( + uint32_t val +) +{ + PLLCON = val; + PLLFEED = 0xaa; + PLLFEED = 0x55; +} + +/** + * @brief Sets the Phase Locked Loop (PLL). + * + * All parameter values are the actual register field values. + * + * @param clksrc Selects the clock source for the PLL. + * + * @param nsel Selects PLL pre-divider value (sometimes named psel). + * + * @param msel Selects PLL multiplier value. + * + * @param cclksel Selects the divide value for creating the CPU clock (CCLK) + * from the PLL output. + */ +static BSP_START_TEXT_SECTION void lpc24xx_set_pll( + unsigned clksrc, + unsigned nsel, + unsigned msel, + unsigned cclksel +) +{ + uint32_t pllstat = PLLSTAT; + uint32_t pllcfg = SET_PLLCFG_NSEL(0, nsel) | SET_PLLCFG_MSEL(0, msel); + uint32_t clksrcsel = SET_CLKSRCSEL_CLKSRC(0, clksrc); + uint32_t cclkcfg = SET_CCLKCFG_CCLKSEL(0, cclksel | 1); + bool pll_enabled = (pllstat & PLLSTAT_PLLE) != 0; + + /* Disconnect PLL if necessary */ + if ((pllstat & PLLSTAT_PLLC) != 0) { + if (pll_enabled) { + /* Check if we run already with the desired settings */ + if (PLLCFG == pllcfg && CLKSRCSEL == clksrcsel && CCLKCFG == cclkcfg) { + /* Nothing to do */ + return; + } + lpc24xx_pll_config(PLLCON_PLLE); + } else { + lpc24xx_pll_config(0); + } + } + + /* Set CPU clock divider to a reasonable save value */ + CCLKCFG = 0; + + /* Disable PLL if necessary */ + if (pll_enabled) { + lpc24xx_pll_config(0); + } + + /* Select clock source */ + CLKSRCSEL = clksrcsel; + + /* Set PLL Configuration Register */ + PLLCFG = pllcfg; + + /* Enable PLL */ + lpc24xx_pll_config(PLLCON_PLLE); + + /* Wait for lock */ + while ((PLLSTAT & PLLSTAT_PLOCK) == 0) { + /* Wait */ + } + + /* Set CPU clock divider and ensure that we have an odd value */ + CCLKCFG = cclkcfg; + + /* Connect PLL */ + lpc24xx_pll_config(PLLCON_PLLE | PLLCON_PLLC); +} + +#else /* ARM_MULTILIB_ARCH_V4 */ + +static BSP_START_TEXT_SECTION void lpc17xx_pll_config( + volatile lpc17xx_pll *pll, + uint32_t val +) +{ + pll->con = val; + pll->feed = 0xaa; + pll->feed = 0x55; +} + +static BSP_START_TEXT_SECTION void lpc17xx_set_pll( + unsigned msel, + unsigned psel, + unsigned cclkdiv +) +{ + volatile lpc17xx_scb *scb = &LPC17XX_SCB; + volatile lpc17xx_pll *pll = &scb->pll_0; + uint32_t pllcfg = LPC17XX_PLL_SEL_MSEL(msel) + | LPC17XX_PLL_SEL_PSEL(psel); + uint32_t pllstat = LPC17XX_PLL_STAT_PLLE + | LPC17XX_PLL_STAT_PLOCK | pllcfg; + uint32_t cclksel_cclkdiv = LPC17XX_SCB_CCLKSEL_CCLKDIV(cclkdiv); + uint32_t cclksel = LPC17XX_SCB_CCLKSEL_CCLKSEL | cclksel_cclkdiv; + + if ( + pll->stat != pllstat + || scb->cclksel != cclksel + || scb->clksrcsel != LPC17XX_SCB_CLKSRCSEL_CLKSRC + ) { + /* Use SYSCLK for CCLK */ + scb->cclksel = LPC17XX_SCB_CCLKSEL_CCLKDIV(1); + + /* Turn off USB */ + scb->usbclksel = 0; + + /* Disable PLL */ + lpc17xx_pll_config(pll, 0); + + /* Select main oscillator as clock source */ + scb->clksrcsel = LPC17XX_SCB_CLKSRCSEL_CLKSRC; + + /* Set PLL configuration */ + pll->cfg = pllcfg; + + /* Set the CCLK, PCLK and EMCCLK divider */ + scb->cclksel = cclksel_cclkdiv; + scb->pclksel = LPC17XX_SCB_PCLKSEL_PCLKDIV(cclkdiv * LPC24XX_PCLKDIV); + scb->emcclksel = LPC24XX_EMCCLKDIV == 1 ? 0 : LPC17XX_SCB_EMCCLKSEL_EMCDIV; + + /* Enable PLL */ + lpc17xx_pll_config(pll, LPC17XX_PLL_CON_PLLE); + + /* Wait for lock */ + while ((pll->stat & LPC17XX_PLL_STAT_PLOCK) == 0) { + /* Wait */ + } + + /* Use the PLL clock */ + scb->cclksel = cclksel; + } +} + +#endif /* ARM_MULTILIB_ARCH_V4 */ + +static BSP_START_TEXT_SECTION void lpc24xx_init_pll(void) +{ + #ifdef ARM_MULTILIB_ARCH_V4 + #if LPC24XX_OSCILLATOR_MAIN == 12000000U + #if LPC24XX_CCLK == 72000000U + lpc24xx_set_pll(1, 0, 11, 3); + #elif LPC24XX_CCLK == 51612800U + lpc24xx_set_pll(1, 30, 399, 5); + #else + #error "unexpected CCLK" + #endif + #elif LPC24XX_OSCILLATOR_MAIN == 3686400U + #if LPC24XX_CCLK == 58982400U + lpc24xx_set_pll(1, 0, 47, 5); + #else + #error "unexpected CCLK" + #endif + #else + #error "unexpected main oscillator frequency" + #endif + #else + #if LPC24XX_OSCILLATOR_MAIN == 12000000U + #if LPC24XX_CCLK == 120000000U + lpc17xx_set_pll(9, 0, 1); + #elif LPC24XX_CCLK == 96000000U + lpc17xx_set_pll(7, 0, 1); + #elif LPC24XX_CCLK == 72000000U + lpc17xx_set_pll(5, 1, 1); + #elif LPC24XX_CCLK == 48000000U + lpc17xx_set_pll(3, 1, 1); + #else + #error "unexpected CCLK" + #endif + #else + #error "unexpected main oscillator frequency" + #endif + #endif +} + +static BSP_START_TEXT_SECTION void lpc24xx_init_memory_map(void) +{ + #ifdef ARM_MULTILIB_ARCH_V4 + /* Re-map interrupt vectors to internal RAM */ + MEMMAP = SET_MEMMAP_MAP(MEMMAP, 2); + #else + volatile lpc17xx_scb *scb = &LPC17XX_SCB; + + scb->memmap = LPC17XX_SCB_MEMMAP_MAP; + #endif + + /* Use normal memory map */ + EMC_CTRL &= ~0x2U; +} + +static BSP_START_TEXT_SECTION void lpc24xx_init_memory_accelerator(void) +{ + #ifdef ARM_MULTILIB_ARCH_V4 + /* Fully enable memory accelerator module functions (MAM) */ + MAMCR = 0; + #if LPC24XX_CCLK <= 20000000U + MAMTIM = 0x1; + #elif LPC24XX_CCLK <= 40000000U + MAMTIM = 0x2; + #elif LPC24XX_CCLK <= 60000000U + MAMTIM = 0x3; + #else + MAMTIM = 0x4; + #endif + MAMCR = 0x2; + + /* Enable fast IO for ports 0 and 1 */ + SCS |= 0x1; + #else + volatile lpc17xx_scb *scb = &LPC17XX_SCB; + + #if LPC24XX_CCLK <= 20000000U + scb->flashcfg = LPC17XX_SCB_FLASHCFG_FLASHTIM(0x0); + #elif LPC24XX_CCLK <= 40000000U + scb->flashcfg = LPC17XX_SCB_FLASHCFG_FLASHTIM(0x1); + #elif LPC24XX_CCLK <= 60000000U + scb->flashcfg = LPC17XX_SCB_FLASHCFG_FLASHTIM(0x2); + #elif LPC24XX_CCLK <= 80000000U + scb->flashcfg = LPC17XX_SCB_FLASHCFG_FLASHTIM(0x3); + #elif LPC24XX_CCLK <= 100000000U + scb->flashcfg = LPC17XX_SCB_FLASHCFG_FLASHTIM(0x4); + #else + scb->flashcfg = LPC17XX_SCB_FLASHCFG_FLASHTIM(0x5); + #endif + #endif +} + +static BSP_START_TEXT_SECTION void lpc24xx_stop_gpdma(void) +{ + #ifdef LPC24XX_STOP_GPDMA + #ifdef ARM_MULTILIB_ARCH_V4 + bool has_power = (PCONP & PCONP_GPDMA) != 0; + #else + volatile lpc17xx_scb *scb = &LPC17XX_SCB; + bool has_power = (scb->pconp & LPC17XX_SCB_PCONP_GPDMA) != 0; + #endif + + if (has_power) { + GPDMA_CONFIG = 0; + + #ifdef ARM_MULTILIB_ARCH_V4 + PCONP &= ~PCONP_GPDMA; + #else + scb->pconp &= ~LPC17XX_SCB_PCONP_GPDMA; + #endif + } + #endif +} + +static BSP_START_TEXT_SECTION void lpc24xx_stop_ethernet(void) +{ + #ifdef LPC24XX_STOP_ETHERNET + #ifdef ARM_MULTILIB_ARCH_V4 + bool has_power = (PCONP & PCONP_ETHERNET) != 0; + #else + volatile lpc17xx_scb *scb = &LPC17XX_SCB; + bool has_power = (scb->pconp & LPC17XX_SCB_PCONP_ENET) != 0; + #endif + + if (has_power) { + MAC_COMMAND = 0x38; + MAC_MAC1 = 0xcf00; + MAC_MAC1 = 0; + + #ifdef ARM_MULTILIB_ARCH_V4 + PCONP &= ~PCONP_ETHERNET; + #else + scb->pconp &= ~LPC17XX_SCB_PCONP_ENET; + #endif + } + #endif +} + +static BSP_START_TEXT_SECTION void lpc24xx_stop_usb(void) +{ + #ifdef LPC24XX_STOP_USB + #ifdef ARM_MULTILIB_ARCH_V4 + bool has_power = (PCONP & PCONP_USB) != 0; + #else + volatile lpc17xx_scb *scb = &LPC17XX_SCB; + bool has_power = (scb->pconp & LPC17XX_SCB_PCONP_USB) != 0; + #endif + + if (has_power) { + OTG_CLK_CTRL = 0; + + #ifdef ARM_MULTILIB_ARCH_V4 + PCONP &= ~PCONP_USB; + #else + scb->pconp &= ~LPC17XX_SCB_PCONP_USB; + scb->usbclksel = 0; + #endif + } + #endif +} + +static BSP_START_TEXT_SECTION void lpc24xx_init_mpu(void) +{ + #ifdef ARM_MULTILIB_ARCH_V7M + volatile ARMV7M_MPU *mpu = _ARMV7M_MPU; + size_t region_count = lpc24xx_start_config_mpu_region_count; + size_t i = 0; + + for (i = 0; i < region_count; ++i) { + mpu->rbar = lpc24xx_start_config_mpu_region [i].rbar; + mpu->rasr = lpc24xx_start_config_mpu_region [i].rasr; + } + + if (region_count > 0) { + mpu->ctrl = ARMV7M_MPU_CTRL_ENABLE; + } + #endif +} + +BSP_START_TEXT_SECTION void bsp_start_hook_0(void) +{ + lpc24xx_init_main_oscillator(); + lpc24xx_init_pll(); + lpc24xx_init_pinsel(); + lpc24xx_init_emc_static(); +} + +BSP_START_TEXT_SECTION void bsp_start_hook_1(void) +{ + lpc24xx_init_memory_map(); + lpc24xx_init_memory_accelerator(); + lpc24xx_init_emc_dynamic(); + lpc24xx_init_mpu(); + lpc24xx_stop_gpdma(); + lpc24xx_stop_ethernet(); + lpc24xx_stop_usb(); + bsp_start_copy_sections(); + bsp_start_clear_bss(); + + /* At this point we can use objects outside the .start section */ +} diff --git a/bsps/arm/lpc24xx/start/fb-config.c b/bsps/arm/lpc24xx/start/fb-config.c new file mode 100644 index 0000000000..d1fa33c95a --- /dev/null +++ b/bsps/arm/lpc24xx/start/fb-config.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <bsp/arm-pl111-fb.h> + +#include <bsp.h> +#include <bsp/fatal.h> +#include <bsp/io.h> +#include <bsp/lcd.h> +#include <bsp/lpc24xx.h> + +static const lpc24xx_pin_range tft_16_bit_5_6_5_pins[] = { + LPC24XX_PIN_LCD_DCLK, + LPC24XX_PIN_LCD_FP, + LPC24XX_PIN_LCD_LP, + LPC24XX_PIN_LCD_VD_3_P4_29, + LPC24XX_PIN_LCD_VD_4_P2_6, + LPC24XX_PIN_LCD_VD_5_P2_7, + LPC24XX_PIN_LCD_VD_6_P2_8, + LPC24XX_PIN_LCD_VD_7_P2_9, + LPC24XX_PIN_LCD_VD_10_P1_20, + LPC24XX_PIN_LCD_VD_11_P1_21, + LPC24XX_PIN_LCD_VD_12_P1_22, + LPC24XX_PIN_LCD_VD_13_P1_23, + LPC24XX_PIN_LCD_VD_14_P1_24, + LPC24XX_PIN_LCD_VD_15_P1_25, + LPC24XX_PIN_LCD_VD_19_P2_13, + LPC24XX_PIN_LCD_VD_20_P1_26, + LPC24XX_PIN_LCD_VD_21_P1_27, + LPC24XX_PIN_LCD_VD_22_P1_28, + LPC24XX_PIN_LCD_VD_23_P1_29, + LPC24XX_PIN_TERMINAL +}; + +static void fb_set_up(const pl111_fb_config *cfg) +{ + rtems_status_code sc; + + sc = lpc24xx_module_enable(LPC24XX_MODULE_LCD, LPC24XX_MODULE_PCLK_DEFAULT); + if (sc != RTEMS_SUCCESSFUL) { + bsp_fatal(LPC24XX_FATAL_PL111_SET_UP); + } + + #ifdef ARM_MULTILIB_ARCH_V4 + PINSEL11 = BSP_FLD32(LCD_MODE_TFT_16_BIT_5_6_5, 1, 3) | BSP_BIT32(0); + #endif + + #ifdef ARM_MULTILIB_ARCH_V7M + volatile lpc17xx_scb *scb = &LPC17XX_SCB; + + scb->matrixarb = 0x0c09; + #endif +} + +static void fb_pins_set_up(const pl111_fb_config *cfg) +{ + rtems_status_code sc; + + sc = lpc24xx_pin_config(tft_16_bit_5_6_5_pins, LPC24XX_PIN_SET_FUNCTION); + if (sc != RTEMS_SUCCESSFUL) { + bsp_fatal(LPC24XX_FATAL_PL111_PINS_SET_UP); + } +} + +static void fb_pins_tear_down(const pl111_fb_config *cfg) +{ + rtems_status_code sc; + + sc = lpc24xx_pin_config(tft_16_bit_5_6_5_pins, LPC24XX_PIN_SET_INPUT); + if (sc != RTEMS_SUCCESSFUL) { + bsp_fatal(LPC24XX_FATAL_PL111_PINS_TEAR_DOWN); + } +} + +static void fb_tear_down(const pl111_fb_config *cfg) +{ + rtems_status_code sc; + + #ifdef ARM_MULTILIB_ARCH_V4 + PINSEL11 = 0; + #endif + + sc = lpc24xx_module_disable(LPC24XX_MODULE_LCD); + if (sc != RTEMS_SUCCESSFUL) { + bsp_fatal(LPC24XX_FATAL_PL111_TEAR_DOWN); + } +} + +static const pl111_fb_config fb_config = { + .regs = (volatile pl111 *) LCD_BASE_ADDR, + + .timing0 = PL111_LCD_TIMING0_PPL(640 / 16 - 1) + | PL111_LCD_TIMING0_HSW(0x1d) + | PL111_LCD_TIMING0_HFP(0x0f) + | PL111_LCD_TIMING0_HBP(0x71), + .timing1 = PL111_LCD_TIMING1_LPP(480 - 1) + | PL111_LCD_TIMING1_VSW(0x02) + | PL111_LCD_TIMING1_VFP(0x0a) + | PL111_LCD_TIMING1_VBP(0x20), + .timing2 = PL111_LCD_TIMING2_PCD_LO(0x3) + | PL111_LCD_TIMING2_ACB(0x0) + | PL111_LCD_TIMING2_IVS + | PL111_LCD_TIMING2_IHS + | PL111_LCD_TIMING2_IPC + | PL111_LCD_TIMING2_CPL(640 - 1) + | PL111_LCD_TIMING2_PCD_HI(0x0), + .timing3 = 0x0, + .control = PL111_LCD_CONTROL_LCD_TFT + | PL111_LCD_CONTROL_LCD_BPP(PL111_LCD_CONTROL_LCD_BPP_16) + | PL111_LCD_CONTROL_BGR, + .power_delay_in_us = 100000, + + .set_up = fb_set_up, + .pins_set_up = fb_pins_set_up, + .pins_tear_down = fb_pins_tear_down, + .tear_down = fb_tear_down +}; + +const pl111_fb_config *arm_pl111_fb_get_config(void) +{ + return &fb_config; +} diff --git a/bsps/arm/lpc24xx/start/linkcmds.lpc17xx_ea_ram b/bsps/arm/lpc24xx/start/linkcmds.lpc17xx_ea_ram new file mode 100644 index 0000000000..d98626108d --- /dev/null +++ b/bsps/arm/lpc24xx/start/linkcmds.lpc17xx_ea_ram @@ -0,0 +1,27 @@ +/* LPC1788 OEM Board from Embedded Artists */ + +MEMORY { + RAM_INT (AIW) : ORIGIN = 0x10000000, LENGTH = 64k + RAM_PER (AIW) : ORIGIN = 0x20000000, LENGTH = 32k + RAM_EXT (AIW) : ORIGIN = 0xa0000000, LENGTH = 32M +} + +REGION_ALIAS ("REGION_START", RAM_EXT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", RAM_EXT); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_RODATA", RAM_EXT); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_DATA", RAM_EXT); +REGION_ALIAS ("REGION_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM_INT); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/lpc24xx/start/linkcmds.lpc17xx_ea_rom_int b/bsps/arm/lpc24xx/start/linkcmds.lpc17xx_ea_rom_int new file mode 100644 index 0000000000..db8c27f37f --- /dev/null +++ b/bsps/arm/lpc24xx/start/linkcmds.lpc17xx_ea_rom_int @@ -0,0 +1,27 @@ +/* LPC1788 OEM Board from Embedded Artists */ + +MEMORY { + ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 512k + RAM_INT (AIW) : ORIGIN = 0x10000000, LENGTH = 64k + RAM_EXT (AIW) : ORIGIN = 0xa0000000, LENGTH = 32M +} + +REGION_ALIAS ("REGION_START", ROM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_EXT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM_EXT); +REGION_ALIAS ("REGION_NOCACHE", RAM_EXT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_EXT); + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/lpc24xx/start/linkcmds.lpc17xx_plx800_ram b/bsps/arm/lpc24xx/start/linkcmds.lpc17xx_plx800_ram new file mode 100644 index 0000000000..e507877a84 --- /dev/null +++ b/bsps/arm/lpc24xx/start/linkcmds.lpc17xx_plx800_ram @@ -0,0 +1,33 @@ +/** + * @file + * + * @brief Memory map for PLX800 (LPC1778). + */ + +MEMORY { + ROM_INT : ORIGIN = 0x00000000, LENGTH = 512k + RAM_INT : ORIGIN = 0x10000000, LENGTH = 64k + RAM_PER : ORIGIN = 0x20000000, LENGTH = 32k + ROM_EXT : ORIGIN = 0x80000000, LENGTH = 4M + RAM_EXT : ORIGIN = 0xa0000000, LENGTH = 32M +} + +REGION_ALIAS ("REGION_START", RAM_EXT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", RAM_EXT); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_RODATA", RAM_EXT); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_DATA", RAM_EXT); +REGION_ALIAS ("REGION_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/lpc24xx/start/linkcmds.lpc17xx_plx800_rom_int b/bsps/arm/lpc24xx/start/linkcmds.lpc17xx_plx800_rom_int new file mode 100644 index 0000000000..2ae0a58840 --- /dev/null +++ b/bsps/arm/lpc24xx/start/linkcmds.lpc17xx_plx800_rom_int @@ -0,0 +1,33 @@ +/** + * @file + * + * @brief Memory map for PLX800 (LPC1778). + */ + +MEMORY { + ROM_INT : ORIGIN = 0x00000000, LENGTH = 512k + RAM_INT : ORIGIN = 0x10000000, LENGTH = 64k + RAM_PER : ORIGIN = 0x20000000, LENGTH = 32k + ROM_EXT : ORIGIN = 0x80000000, LENGTH = 4M + RAM_EXT : ORIGIN = 0xa0000000, LENGTH = 32M +} + +REGION_ALIAS ("REGION_START", ROM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_EXT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/lpc24xx/start/linkcmds.lpc2362 b/bsps/arm/lpc24xx/start/linkcmds.lpc2362 new file mode 100644 index 0000000000..e5bae18075 --- /dev/null +++ b/bsps/arm/lpc24xx/start/linkcmds.lpc2362 @@ -0,0 +1,70 @@ +/** + * @file + * + * @ingroup lpc24xx_linker_lpc2362 + * + * @brief Memory map. + */ + +/** + * @defgroup lpc24xx_linker_lpc2362 LPC2362 Memory Map + * + * @ingroup bsp_linker + * + * @brief LPC2362 memory map. + * + * <table> + * <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr> + * <tr><td>RAM_INT</td><td>0x40000000</td><td>32k</td></tr> + * <tr><td>RAM_USB</td><td>0x7fd00000</td><td>8k</td></tr> + * <tr><td>RAM_ETH</td><td>0x7fe00000</td><td>16k</td></tr> + * <tr><td>ROM_INT</td><td>0x00000000</td><td>128k</td></tr> + * </table> + * + * <table> + * <tr><th>Section Name</th><th>Section Runtime Region</th><th>Section Load Region</th></tr> + * <tr><td>.start</td><td>ROM_INT</td><td></td></tr> + * <tr><td>.text</td><td>ROM_INT</td><td>ROM_INT</td></tr> + * <tr><td>.rodata</td><td>ROM_INT</td><td>ROM_INT</td></tr> + * <tr><td>.data</td><td>RAM_INT</td><td>ROM_INT</td></tr> + * <tr><td>.fast</td><td>RAM_INT</td><td>ROM_INT</td></tr> + * <tr><td>.bss</td><td>RAM_INT</td><td></td></tr> + * <tr><td>.work</td><td>RAM_INT</td><td></td></tr> + * <tr><td>.stack</td><td>RAM_INT</td><td></td></tr> + * </table> + */ + +MEMORY { + RAM_INT (AIW) : ORIGIN = 0x40000000, LENGTH = 32k + RAM_USB (AIW) : ORIGIN = 0x7fd00000, LENGTH = 8k + RAM_ETH (AIW) : ORIGIN = 0x7fe00000, LENGTH = 16k + ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 128k +} + +REGION_ALIAS ("REGION_START", ROM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_INT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_INT); +REGION_ALIAS ("REGION_WORK", RAM_INT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +lpc24xx_region_heap_0_begin = ORIGIN (RAM_ETH); +lpc24xx_region_heap_0_size = LENGTH (RAM_ETH); +lpc24xx_region_heap_0_end = lpc24xx_region_heap_0_begin + lpc24xx_region_heap_0_size; + +lpc24xx_region_heap_1_begin = ORIGIN (RAM_USB); +lpc24xx_region_heap_1_size = LENGTH (RAM_USB); +lpc24xx_region_heap_1_end = lpc24xx_region_heap_1_begin + lpc24xx_region_heap_1_size; + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/lpc24xx/start/linkcmds.lpc23xx_tli800 b/bsps/arm/lpc24xx/start/linkcmds.lpc23xx_tli800 new file mode 100644 index 0000000000..697b040a84 --- /dev/null +++ b/bsps/arm/lpc24xx/start/linkcmds.lpc23xx_tli800 @@ -0,0 +1,74 @@ +/** + * @file + * + * @ingroup lpc24xx_linker_lpc23xx_tli800 + * + * @brief Memory map. + */ + +/** + * @defgroup lpc24xx_linker_lpc23xx_tli800 TLI800 Memory Map + * + * @ingroup bsp_linker + * + * @brief TLI800 memory map. + * + * <table> + * <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr> + * <tr><td>RAM_INT</td><td>0x40000000</td><td>32k</td></tr> + * <tr><td>RAM_USB</td><td>0x7fd00000</td><td>8k</td></tr> + * <tr><td>RAM_ETH</td><td>0x7fe00000</td><td>16k</td></tr> + * <tr><td>ROM_BOOT</td><td>0x00000000</td><td>4k</td></tr> + * <tr><td>ROM_CFG</td><td>0x00001000</td><td>4k</td></tr> + * <tr><td>ROM_INT</td><td>0x00002000</td><td>120k</td></tr> + * </table> + * + * <table> + * <tr><th>Section Name</th><th>Section Runtime Region</th><th>Section Load Region</th></tr> + * <tr><td>.start</td><td>ROM_BOOT</td><td></td></tr> + * <tr><td>.text</td><td>ROM_INT</td><td>ROM_INT</td></tr> + * <tr><td>.rodata</td><td>ROM_INT</td><td>ROM_INT</td></tr> + * <tr><td>.data</td><td>RAM_INT</td><td>ROM_INT</td></tr> + * <tr><td>.fast</td><td>RAM_INT</td><td>ROM_INT</td></tr> + * <tr><td>.bss</td><td>RAM_INT</td><td></td></tr> + * <tr><td>.work</td><td>RAM_INT</td><td></td></tr> + * <tr><td>.stack</td><td>RAM_INT</td><td></td></tr> + * </table> + */ + +MEMORY { + RAM_INT (AIW) : ORIGIN = 0x40000000, LENGTH = 32k + RAM_USB (AIW) : ORIGIN = 0x7fd00000, LENGTH = 8k + RAM_ETH (AIW) : ORIGIN = 0x7fe00000, LENGTH = 16k + ROM_BOOT (RX) : ORIGIN = 0x00000000, LENGTH = 4k + ROM_CFG (RX) : ORIGIN = 0x00001000, LENGTH = 4k + ROM_INT (RX) : ORIGIN = 0x00002000, LENGTH = 120k +} + +REGION_ALIAS ("REGION_START", ROM_BOOT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_INT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_INT); +REGION_ALIAS ("REGION_WORK", RAM_INT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +lpc24xx_region_heap_0_begin = ORIGIN (RAM_ETH); +lpc24xx_region_heap_0_size = LENGTH (RAM_ETH); +lpc24xx_region_heap_0_end = lpc24xx_region_heap_0_begin + lpc24xx_region_heap_0_size; + +lpc24xx_region_heap_1_begin = ORIGIN (RAM_USB); +lpc24xx_region_heap_1_size = LENGTH (RAM_USB); +lpc24xx_region_heap_1_end = lpc24xx_region_heap_1_begin + lpc24xx_region_heap_1_size; + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_ea b/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_ea new file mode 100644 index 0000000000..80b1e13187 --- /dev/null +++ b/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_ea @@ -0,0 +1,59 @@ +/** + * @file + * + * @ingroup lpc24xx_linker_ea + * + * @brief Memory map. + */ + +/** + * @defgroup lpc24xx_linker_ea QVGA Base Board Memory Map + * + * @ingroup bsp_linker + * + * @brief QVGA Base Board from Embedded Artists (LPC2478) memory map. + * + * <table> + * <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr> + * <tr><td>RAM_INT</td><td>0x40000000</td><td>64k</td></tr> + * <tr><td>RAM_EXT</td><td>0xa0000000</td><td>32M</td></tr> + * </table> + * + * <table> + * <tr><th>Section Name</th><th>Section Runtime Region</th><th>Section Load Region</th></tr> + * <tr><td>.start</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.vector</td><td>RAM_INT</td><td></td></tr> + * <tr><td>.text</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.rodata</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.data</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.fast</td><td>RAM_INT</td><td>RAM_EXT</td></tr> + * <tr><td>.bss</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.work</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.stack</td><td>RAM_INT</td><td></td></tr> + * </table> + */ + +MEMORY { + RAM_INT (AIW) : ORIGIN = 0x40000000, LENGTH = 64k + RAM_EXT (AIW) : ORIGIN = 0xa0000000, LENGTH = 32M +} + +REGION_ALIAS ("REGION_START", RAM_EXT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", RAM_EXT); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_RODATA", RAM_EXT); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_DATA", RAM_EXT); +REGION_ALIAS ("REGION_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_ncs_ram b/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_ncs_ram new file mode 100644 index 0000000000..9f421f3555 --- /dev/null +++ b/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_ncs_ram @@ -0,0 +1,60 @@ +/** + * @file + * + * @ingroup lpc24xx_linker_ncs_ram + * + * @brief Memory map. + */ + +/** + * @defgroup lpc24xx_linker_ncs_ram NCS Application Memory Map + * + * @ingroup bsp_linker + * + * @brief NCS application memory map. + * + * <table> + * <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr> + * <tr><td>RAM_INT</td><td>0x40000000</td><td>64k</td></tr> + * <tr><td>RAM_EXT</td><td>0xa0000000</td><td>8M</td></tr> + * </table> + * + * <table> + * <tr><th>Section Name</th><th>Section Runtime Region</th><th>Section Load Region</th></tr> + * <tr><td>.start</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.vector</td><td>RAM_INT</td><td></td></tr> + * <tr><td>.text</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.rodata</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.data</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.fast</td><td>RAM_INT</td><td>RAM_EXT</td></tr> + * <tr><td>.bss</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.work</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.stack</td><td>RAM_INT</td><td></td></tr> + * </table> + */ + +MEMORY { + RAM_INT (AIW) : ORIGIN = 0x40000000, LENGTH = 64k + RAM_USB (AIW) : ORIGIN = 0x7fd00000, LENGTH = 16k + RAM_EXT (AIW) : ORIGIN = 0xa0000000, LENGTH = 8M +} + +REGION_ALIAS ("REGION_START", RAM_EXT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", RAM_EXT); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_RODATA", RAM_EXT); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_DATA", RAM_EXT); +REGION_ALIAS ("REGION_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_USB); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_ncs_rom_ext b/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_ncs_rom_ext new file mode 100644 index 0000000000..7618a342bd --- /dev/null +++ b/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_ncs_rom_ext @@ -0,0 +1,64 @@ +/** + * @file + * + * @ingroup lpc24xx_linker_ncs_rom_ext + * + * @brief Memory map. + */ + +/** + * @defgroup lpc24xx_linker_ncs_rom_ext NCS Bootloader (LPC2470) Memory Map + * + * @ingroup bsp_linker + * + * @brief NCS bootloader (LPC2470) memory map. + * + * <table> + * <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr> + * <tr><td>RAM_INT</td><td>0x40000000</td><td>64k</td></tr> + * <tr><td>RAM_EXT</td><td>0xa0400000</td><td>4M</td></tr> + * <tr><td>ROM_BOOT</td><td>0x81000000</td><td>16k</td></tr> + * <tr><td>ROM_EXT</td><td>0x81010000</td><td>2M - 64k</td></tr> + * </table> + * + * <table> + * <tr><th>Section Name</th><th>Section Runtime Region</th><th>Section Load Region</th></tr> + * <tr><td>.start</td><td>ROM_BOOT</td><td></td></tr> + * <tr><td>.vector</td><td>RAM_INT</td><td></td></tr> + * <tr><td>.text</td><td>RAM_EXT</td><td>ROM_EXT</td></tr> + * <tr><td>.rodata</td><td>RAM_EXT</td><td>ROM_EXT</td></tr> + * <tr><td>.data</td><td>RAM_EXT</td><td>ROM_EXT</td></tr> + * <tr><td>.fast</td><td>RAM_INT</td><td>ROM_BOOT</td></tr> + * <tr><td>.bss</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.work</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.stack</td><td>RAM_INT</td><td></td></tr> + * </table> + */ + +MEMORY { + RAM_INT (AIW) : ORIGIN = 0x40000000, LENGTH = 64k + RAM_USB (AIW) : ORIGIN = 0x7fd00000, LENGTH = 16k + RAM_EXT (AIW) : ORIGIN = 0xa0400000, LENGTH = 4M + ROM_BOOT (RX) : ORIGIN = 0x81000000, LENGTH = 16k + ROM_EXT (RX) : ORIGIN = 0x81010000, LENGTH = 2M - 64k +} + +REGION_ALIAS ("REGION_START", ROM_BOOT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", RAM_EXT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_EXT); +REGION_ALIAS ("REGION_RODATA", RAM_EXT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_EXT); +REGION_ALIAS ("REGION_DATA", RAM_EXT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_EXT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_BOOT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_USB); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_BOOT); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_ncs_rom_int b/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_ncs_rom_int new file mode 100644 index 0000000000..47b79e7b5c --- /dev/null +++ b/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_ncs_rom_int @@ -0,0 +1,64 @@ +/** + * @file + * + * @ingroup lpc24xx_linker_ncs_rom_int + * + * @brief Memory map. + */ + +/** + * @defgroup lpc24xx_linker_ncs_rom_int NCS Bootloader (LPC2478) Memory Map + * + * @ingroup bsp_linker + * + * @brief NCS bootloader (LPC2478) memory map. + * + * <table> + * <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr> + * <tr><td>RAM_VEC</td><td>0x40000000</td><td>32k</td></tr> + * <tr><td>RAM_INT</td><td>0x40008000</td><td>32k</td></tr> + * <tr><td>RAM_EXT</td><td>0xa0400000</td><td>4M</td></tr> + * <tr><td>ROM_INT</td><td>0x00000000</td><td>512k - 8k</td></tr> + * </table> + * + * <table> + * <tr><th>Section Name</th><th>Section Runtime Region</th><th>Section Load Region</th></tr> + * <tr><td>.start</td><td>ROM_INT</td><td></td></tr> + * <tr><td>.vector</td><td>RAM_VEC</td><td></td></tr> + * <tr><td>.text</td><td>ROM_INT</td><td>ROM_INT</td></tr> + * <tr><td>.rodata</td><td>ROM_INT</td><td>ROM_INT</td></tr> + * <tr><td>.data</td><td>RAM_EXT</td><td>ROM_INT</td></tr> + * <tr><td>.fast</td><td>RAM_INT</td><td>ROM_INT</td></tr> + * <tr><td>.bss</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.work</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.stack</td><td>RAM_INT</td><td></td></tr> + */ + + +MEMORY { + RAM_VEC (AIW) : ORIGIN = 0x40000000, LENGTH = 32k + RAM_INT (AIW) : ORIGIN = 0x40008000, LENGTH = 32k + RAM_USB (AIW) : ORIGIN = 0x7fd00000, LENGTH = 16k + RAM_EXT (AIW) : ORIGIN = 0xa0400000, LENGTH = 4M + ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 512k - 8k +} + +REGION_ALIAS ("REGION_START", ROM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_VEC); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_EXT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_USB); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_plx800_ram b/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_plx800_ram new file mode 100644 index 0000000000..2dcc6d233f --- /dev/null +++ b/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_plx800_ram @@ -0,0 +1,32 @@ +/** + * @file + * + * @brief Memory map for PLX800 (LPC2478). + */ + +MEMORY { + RAM_INT : ORIGIN = 0x40000000, LENGTH = 64k + RAM_EXT : ORIGIN = 0xa0000000, LENGTH = 32M + ROM_INT : ORIGIN = 0x00000000, LENGTH = 512k - 8k + ROM_EXT : ORIGIN = 0x80000000, LENGTH = 4M +} + +REGION_ALIAS ("REGION_START", RAM_EXT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", RAM_EXT); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_RODATA", RAM_EXT); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_DATA", RAM_EXT); +REGION_ALIAS ("REGION_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_plx800_rom_int b/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_plx800_rom_int new file mode 100644 index 0000000000..f00c1d8f93 --- /dev/null +++ b/bsps/arm/lpc24xx/start/linkcmds.lpc24xx_plx800_rom_int @@ -0,0 +1,32 @@ +/** + * @file + * + * @brief Memory map for PLX800 (LPC2478). + */ + +MEMORY { + RAM_INT : ORIGIN = 0x40000000, LENGTH = 64k + RAM_EXT : ORIGIN = 0xa0000000, LENGTH = 32M + ROM_INT : ORIGIN = 0x00000000, LENGTH = 512k - 8k + ROM_EXT : ORIGIN = 0x80000000, LENGTH = 4M +} + +REGION_ALIAS ("REGION_START", ROM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_EXT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/lpc24xx/start/linkcmds.lpc40xx_ea_ram b/bsps/arm/lpc24xx/start/linkcmds.lpc40xx_ea_ram new file mode 100644 index 0000000000..d4535963cb --- /dev/null +++ b/bsps/arm/lpc24xx/start/linkcmds.lpc40xx_ea_ram @@ -0,0 +1 @@ +INCLUDE linkcmds.lpc17xx_ea_ram diff --git a/bsps/arm/lpc24xx/start/linkcmds.lpc40xx_ea_rom_int b/bsps/arm/lpc24xx/start/linkcmds.lpc40xx_ea_rom_int new file mode 100644 index 0000000000..612f4916d3 --- /dev/null +++ b/bsps/arm/lpc24xx/start/linkcmds.lpc40xx_ea_rom_int @@ -0,0 +1 @@ +INCLUDE linkcmds.lpc17xx_ea_rom_int diff --git a/bsps/arm/lpc24xx/start/start-config-emc-dynamic.c b/bsps/arm/lpc24xx/start/start-config-emc-dynamic.c new file mode 100644 index 0000000000..3a08f0b49d --- /dev/null +++ b/bsps/arm/lpc24xx/start/start-config-emc-dynamic.c @@ -0,0 +1,271 @@ +/** + * @file + * + * @ingroup lpc24xx + * + * @brief BSP start EMC dynamic memory configuration. + */ + +/* + * Copyright (c) 2011-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <bsp/start-config.h> +#include <bsp/lpc24xx.h> + +/* + * FIXME: The NXP example code uses different values for the follwing two + * defines. In the NXP example code they depend on the EMCCLK. It is unclear + * how these values are determined. The values from the NXP example code do + * not work. + */ + +/* Use command delayed strategy */ +#define LPC24XX_EMC_DYNAMIC_READCONFIG_DEFAULT 0x1 + +#define LPC24XX_EMCDLYCTL_DEFAULT 0x1112 + +BSP_START_DATA_SECTION const lpc24xx_emc_dynamic_config + lpc24xx_start_config_emc_dynamic [] = { +#if defined(LPC24XX_EMC_MT48LC4M16A2) + /* Dynamic Memory 0: Micron M T48LC 4M16 A2 P 75 IT */ + { + /* 15.6 us */ + .refresh = LPC24XX_PS_TO_EMCCLK(15600000, 0) / 16, + + .readconfig = LPC24XX_EMC_DYNAMIC_READCONFIG_DEFAULT, + + /* Precharge command period 20 ns */ + .trp = 1, + + /* Active to precharge command period 44 ns */ + .tras = 3, + + /* FIXME */ + .tsrex = 5, + + /* FIXME */ + .tapr = 2, + + /* Data-in to active command period tWR + tRP */ + .tdal = 4, + + /* Write recovery time 15 ns */ + .twr = 1, + + /* Active to active command period 66 ns */ + .trc = 4, + + /* Auto refresh period 66 ns */ + .trfc = 4, + + /* Exit self refresh to active command period 75 ns */ + .txsr = 5, + + /* Active bank a to active bank b command period 15 ns */ + .trrd = 1, + + /* Load mode register to active or refresh command period 2 tCK */ + .tmrd = 1 + } +#elif defined(LPC24XX_EMC_IS42S32800D7) + /* Dynamic Memory 0: ISSI IS42S32800D7 */ + { + /* 15.6 us */ + .refresh = LPC24XX_PS_TO_EMCCLK(15600000, 0) / 16, + + .readconfig = LPC24XX_EMC_DYNAMIC_READCONFIG_DEFAULT, + + /* 20ns */ + .trp = LPC24XX_PS_TO_EMCCLK(20000, 1), + + /* 45ns */ + .tras = LPC24XX_PS_TO_EMCCLK(45000, 1), + + /* 70ns (tXSR) */ + .tsrex = LPC24XX_PS_TO_EMCCLK(70000, 1), + + /* 20ns (tRCD) */ + .tapr = LPC24XX_PS_TO_EMCCLK(20000, 1), + + /* n clock cycles -> 38.8ns >= 35ns */ + .tdal = LPC24XX_PS_TO_EMCCLK(35000, 0), + + /* 14ns (tDPL) */ + .twr = LPC24XX_PS_TO_EMCCLK(14000, 1), + + /* 67.5ns */ + .trc = LPC24XX_PS_TO_EMCCLK(67500, 1), + + /* 67.5ns (tRC) */ + .trfc = LPC24XX_PS_TO_EMCCLK(67500, 1), + + /* 70ns */ + .txsr = LPC24XX_PS_TO_EMCCLK(70000, 1), + + /* 14ns */ + .trrd = LPC24XX_PS_TO_EMCCLK(14000, 1), + + /* 14ns */ + .tmrd = LPC24XX_PS_TO_EMCCLK(14000, 1), + + .emcdlyctl = LPC24XX_EMCDLYCTL_DEFAULT + } +#elif defined(LPC24XX_EMC_W9825G2JB75I) + /* Dynamic Memory 0: Winbond W9825G2JB75I */ + { + /* 15.6 us */ + .refresh = LPC24XX_PS_TO_EMCCLK(15600000, 0) / 16, + + .readconfig = LPC24XX_EMC_DYNAMIC_READCONFIG_DEFAULT, + + /* 20ns */ + .trp = LPC24XX_PS_TO_EMCCLK(20000, 1), + + /* 45ns */ + .tras = LPC24XX_PS_TO_EMCCLK(45000, 1), + + /* 75ns (tXSR) */ + .tsrex = LPC24XX_PS_TO_EMCCLK(75000, 1), + + /* 20ns (tRCD) */ + .tapr = LPC24XX_PS_TO_EMCCLK(20000, 1), + + /* tWR + tRP -> 2 * tCK + 20ns */ + .tdal = 2 + LPC24XX_PS_TO_EMCCLK(20000, 0), + + /* (n + 1) clock cycles == 2 * tCK */ + .twr = 1, + + /* 65ns */ + .trc = LPC24XX_PS_TO_EMCCLK(65000, 1), + + /* 65ns (tRC) */ + .trfc = LPC24XX_PS_TO_EMCCLK(65000, 1), + + /* 75ns */ + .txsr = LPC24XX_PS_TO_EMCCLK(50000, 1), + + /* (n + 1) clock cycles == 2 * tCK */ + .trrd = 1, + + /* (n + 1) clock cycles == 2 * tCK (tRSC)*/ + .tmrd = 1, + + .emcdlyctl = LPC24XX_EMCDLYCTL_DEFAULT + } +#elif defined(LPC24XX_EMC_K4S561632E) + { + .refresh = 35, + .readconfig = LPC24XX_EMC_DYNAMIC_READCONFIG_DEFAULT, + .trp = 2, + .tras = 4, + .tsrex = 5, + .tapr = 1, + .tdal = 5, + .twr = 3, + .trc = 5, + .trfc = 5, + .txsr = 5, + .trrd = 3, + .tmrd = 2 + } +#elif defined(LPC24XX_EMC_IS42S32800B) + { + /* 15.6us */ + .refresh = LPC24XX_PS_TO_EMCCLK(15600000, 0) / 16, + + .readconfig = LPC24XX_EMC_DYNAMIC_READCONFIG_DEFAULT, + + /* 20ns */ + .trp = LPC24XX_PS_TO_EMCCLK(20000, 1), + + /* 45ns */ + .tras = LPC24XX_PS_TO_EMCCLK(45000, 1), + + /* 70ns (tRC) */ + .tsrex = LPC24XX_PS_TO_EMCCLK(70000, 1), + + /* FIXME */ + .tapr = LPC24XX_PS_TO_EMCCLK(40000, 1), + + /* tWR + tRP -> 2 * tCK + 20ns */ + .tdal = 2 + LPC24XX_PS_TO_EMCCLK(20000, 0), + + /* (n + 1) clock cycles == 2 * tCK */ + .twr = 1, + + /* 70ns */ + .trc = LPC24XX_PS_TO_EMCCLK(70000, 1), + + /* 70ns */ + .trfc = LPC24XX_PS_TO_EMCCLK(70000, 1), + + /* 70ns (tRC) */ + .txsr = LPC24XX_PS_TO_EMCCLK(70000, 1), + + /* 14ns */ + .trrd = LPC24XX_PS_TO_EMCCLK(14000, 1), + + /* (n + 1) clock cycles == 2 * tCK */ + .tmrd = 1, + + .emcdlyctl = LPC24XX_EMCDLYCTL_DEFAULT + } +#endif +}; + +BSP_START_DATA_SECTION const lpc24xx_emc_dynamic_chip_config + lpc24xx_start_config_emc_dynamic_chip [] = { +#if defined(LPC24XX_EMC_MT48LC4M16A2) + { + .chip_select = (volatile lpc_emc_dynamic *) &EMC_DYN_CFG0, + + /* + * Use SDRAM, 0 0 001 01 address mapping, disabled buffer, unprotected + * writes. 4 banks, 12 row lines, 8 column lines. + */ + .config = 0x280, + + .rascas = EMC_DYN_RASCAS_RAS(2) | EMC_DYN_RASCAS_CAS(2, 0), + .mode = 0xa0000000 | (0x23 << (1 + 2 + 8)) + } +#elif defined(LPC24XX_EMC_W9825G2JB75I) \ + || defined(LPC24XX_EMC_IS42S32800D7) \ + || defined(LPC24XX_EMC_IS42S32800B) + { + .chip_select = (volatile lpc_emc_dynamic *) &EMC_DYN_CFG0, + + /* 32-bit data bus, 4 banks, 12 row lines, 9 column lines, RBC */ + .config = 0x4480, + + /* RAS based on tRCD = 20ns */ + .rascas = EMC_DYN_RASCAS_RAS(2) | EMC_DYN_RASCAS_CAS(2, 0), + + /* CAS 2, burst length 4 */ + .mode = 0xa0000000 | (0x22 << (2 + 2 + 9)) + } +#elif defined(LPC24XX_EMC_K4S561632E) + { + .chip_select = (volatile lpc_emc_dynamic *) &EMC_DYN_CFG0, + .config = 0x680, + .rascas = EMC_DYN_RASCAS_RAS(3) | EMC_DYN_RASCAS_CAS(3, 0), + .mode = 0xa0000000 | (0x33 << 12) + } +#endif +}; + +BSP_START_DATA_SECTION const size_t + lpc24xx_start_config_emc_dynamic_chip_count = + sizeof(lpc24xx_start_config_emc_dynamic_chip) + / sizeof(lpc24xx_start_config_emc_dynamic_chip [0]); diff --git a/bsps/arm/lpc24xx/start/start-config-emc-static.c b/bsps/arm/lpc24xx/start/start-config-emc-static.c new file mode 100644 index 0000000000..4a427664f6 --- /dev/null +++ b/bsps/arm/lpc24xx/start/start-config-emc-static.c @@ -0,0 +1,133 @@ +/** + * @file + * + * @ingroup lpc24xx + * + * @brief BSP start EMC static memory configuration. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <bsp/start-config.h> +#include <bsp/lpc24xx.h> + +BSP_START_DATA_SECTION const lpc24xx_emc_static_chip_config + lpc24xx_start_config_emc_static_chip [] = { +#if defined(LPC24XX_EMC_M29W160E) + /* + * Static Memory 1: Numonyx M29W160EB + * + * 1 clock cycle = 1/72MHz = 13.9ns + */ + { + .chip_select = (volatile lpc_emc_static *) EMC_STA_BASE_1, + .config = { + /* + * 16 bit, page mode disabled, active LOW chip select, extended wait + * disabled, writes not protected, byte lane state LOW/LOW (!). + */ + .config = 0x81, + + /* 1 clock cycles delay from the chip select 1 to the write enable */ + .waitwen = 0, + + /* + * 0 clock cycles delay from the chip select 1 or address change + * (whichever is later) to the output enable + */ + .waitoen = 0, + + /* 7 clock cycles delay from the chip select 1 to the read access */ + .waitrd = 0x6, + + /* + * 32 clock cycles delay for asynchronous page mode sequential accesses + */ + .waitpage = 0x1f, + + /* 5 clock cycles delay from the chip select 1 to the write access */ + .waitwr = 0x3, + + /* 16 bus turnaround cycles */ + .waitrun = 0xf + } + } +#elif defined(LPC24XX_EMC_M29W320E70) + /* Static Memory 0: M29W320E70 */ + { + .chip_select = (volatile lpc_emc_static *) EMC_STA_BASE_0, + .config = { + /* + * 16 bit, page mode disabled, active LOW chip select, extended wait + * disabled, writes not protected, byte lane state LOW/LOW. + */ + .config = 0x81, + + /* 30ns (tWHWL) */ + .waitwen = LPC24XX_PS_TO_EMCCLK(30000, 1), + + /* 0ns */ + .waitoen = LPC24XX_PS_TO_EMCCLK(0, 1), + + /* 70ns (tAVQV, tELQV) */ + .waitrd = LPC24XX_PS_TO_EMCCLK(70000, 1), + + /* 70ns (tAVQV, tELQV) */ + .waitpage = LPC24XX_PS_TO_EMCCLK(70000, 1), + + /* max(30ns (tWHWL) + 45ns (tWLWH), 70ns (tAVAV)) */ + .waitwr = LPC24XX_PS_TO_EMCCLK(75000, 2), + + /* 25ns (tEHQZ) */ + .waitrun = LPC24XX_PS_TO_EMCCLK(25000, 1) + } + } +#elif defined(LPC24XX_EMC_SST39VF3201) + /* Static Memory 0: SST39VF3201 */ + { + .chip_select = (volatile lpc_emc_static *) EMC_STA_BASE_0, + .config = { + /* + * 16 bit, page mode disabled, active LOW chip select, extended wait + * disabled, writes not protected, byte lane state LOW/LOW. + */ + .config = 0x81, + + /* 0ns (tCS, tAS) */ + .waitwen = LPC24XX_PS_TO_EMCCLK(0, 1), + + /* 0ns (tOES) */ + .waitoen = LPC24XX_PS_TO_EMCCLK(0, 1), + + /* 70ns (tRC) */ + .waitrd = LPC24XX_PS_TO_EMCCLK(70000, 1), + + /* 70ns (tRC) */ + .waitpage = LPC24XX_PS_TO_EMCCLK(70000, 1), + + /* 20ns (tCHZ, TOHZ) */ + .waitwr = LPC24XX_PS_TO_EMCCLK(20000, 2), + + /* 20ns (tCHZ, TOHZ) */ + .waitrun = LPC24XX_PS_TO_EMCCLK(20000, 1) + } + } +#endif +}; + +BSP_START_DATA_SECTION const size_t + lpc24xx_start_config_emc_static_chip_count = + sizeof(lpc24xx_start_config_emc_static_chip) + / sizeof(lpc24xx_start_config_emc_static_chip [0]); diff --git a/bsps/arm/lpc24xx/start/start-config-mpu.c b/bsps/arm/lpc24xx/start/start-config-mpu.c new file mode 100644 index 0000000000..9d9846c69a --- /dev/null +++ b/bsps/arm/lpc24xx/start/start-config-mpu.c @@ -0,0 +1,86 @@ +/** + * @file + * + * @ingroup lpc24xx + * + * @brief BSP start MPU configuration. + */ + +/* + * Copyright (c) 2011-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <bsp/start-config.h> + +#ifdef ARM_MULTILIB_ARCH_V7M + BSP_START_DATA_SECTION const ARMV7M_MPU_Region + lpc24xx_start_config_mpu_region [] = { + #if defined(LPC24XX_EMC_IS42S32800D7) \ + || defined(LPC24XX_EMC_W9825G2JB75I) \ + || defined(LPC24XX_EMC_IS42S32800B) + ARMV7M_MPU_REGION_INITIALIZER( + 0, + 0x00000000, + ARMV7M_MPU_SIZE_512_KB, + ARMV7M_MPU_ATTR_RX + ), + ARMV7M_MPU_REGION_INITIALIZER( + 1, + 0x10000000, + ARMV7M_MPU_SIZE_64_KB, + ARMV7M_MPU_ATTR_RWX + ), + ARMV7M_MPU_REGION_INITIALIZER( + 2, + 0x20000000, + ARMV7M_MPU_SIZE_32_KB, + ARMV7M_MPU_ATTR_RWX + ), + ARMV7M_MPU_REGION_INITIALIZER( + 3, + 0xa0000000, + ARMV7M_MPU_SIZE_32_MB, + ARMV7M_MPU_ATTR_RWX + ), + ARMV7M_MPU_REGION_INITIALIZER( + 4, + 0x20080000, + ARMV7M_MPU_SIZE_128_KB, + ARMV7M_MPU_ATTR_IO + ), + ARMV7M_MPU_REGION_INITIALIZER( + 5, + 0x40000000, + ARMV7M_MPU_SIZE_1_MB, + ARMV7M_MPU_ATTR_IO + ), + #if defined(LPC24XX_EMC_M29W320E70) \ + || defined(LPC24XX_EMC_SST39VF3201) + ARMV7M_MPU_REGION_INITIALIZER( + 6, + 0x80000000, + ARMV7M_MPU_SIZE_4_MB, + ARMV7M_MPU_ATTR_RWX + ), + #else + ARMV7M_MPU_REGION_DISABLED_INITIALIZER(6), + #endif + ARMV7M_MPU_REGION_DISABLED_INITIALIZER(7) + #endif + }; + + BSP_START_DATA_SECTION const size_t + lpc24xx_start_config_mpu_region_count = + sizeof(lpc24xx_start_config_mpu_region) + / sizeof(lpc24xx_start_config_mpu_region [0]); +#endif diff --git a/bsps/arm/lpc24xx/start/start-config-pinsel.c b/bsps/arm/lpc24xx/start/start-config-pinsel.c new file mode 100644 index 0000000000..db44099664 --- /dev/null +++ b/bsps/arm/lpc24xx/start/start-config-pinsel.c @@ -0,0 +1,74 @@ +/** + * @file + * + * @ingroup lpc24xx + * + * @brief BSP start pin selection configuration. + */ + +/* + * Copyright (c) 2011-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <bsp/start-config.h> + +BSP_START_DATA_SECTION const lpc24xx_pin_range + lpc24xx_start_config_pinsel [] = { +#if defined(LPC24XX_EMC_MT48LC4M16A2) \ + && defined(LPC24XX_EMC_M29W160E) + LPC24XX_PIN_EMC_A_0_20, + LPC24XX_PIN_EMC_D_0_15, + LPC24XX_PIN_EMC_RAS, + LPC24XX_PIN_EMC_CAS, + LPC24XX_PIN_EMC_WE, + LPC24XX_PIN_EMC_DYCS_0, + LPC24XX_PIN_EMC_CLK_0, + LPC24XX_PIN_EMC_CKE_0, + LPC24XX_PIN_EMC_DQM_0, + LPC24XX_PIN_EMC_DQM_1, + LPC24XX_PIN_EMC_OE, + LPC24XX_PIN_EMC_CS_1, +#endif +#if (defined(LPC24XX_EMC_IS42S32800D7) || defined(LPC24XX_EMC_W9825G2JB75I)) \ + && (defined(LPC24XX_EMC_M29W320E70) || defined(LPC24XX_EMC_SST39VF3201)) + LPC24XX_PIN_EMC_A_0_22, + LPC24XX_PIN_EMC_D_0_31, + LPC24XX_PIN_EMC_RAS, + LPC24XX_PIN_EMC_CAS, + LPC24XX_PIN_EMC_WE, + LPC24XX_PIN_EMC_DYCS_0, + LPC24XX_PIN_EMC_CLK_0, + LPC24XX_PIN_EMC_CKE_0, + LPC24XX_PIN_EMC_DQM_0, + LPC24XX_PIN_EMC_DQM_1, + LPC24XX_PIN_EMC_DQM_2, + LPC24XX_PIN_EMC_DQM_3, + LPC24XX_PIN_EMC_OE, + LPC24XX_PIN_EMC_CS_0, +#endif +#if defined(LPC24XX_EMC_IS42S32800B) + LPC24XX_PIN_EMC_A_0_14, + LPC24XX_PIN_EMC_D_0_31, + LPC24XX_PIN_EMC_RAS, + LPC24XX_PIN_EMC_CAS, + LPC24XX_PIN_EMC_WE, + LPC24XX_PIN_EMC_DYCS_0, + LPC24XX_PIN_EMC_CLK_0, + LPC24XX_PIN_EMC_CKE_0, + LPC24XX_PIN_EMC_DQM_0, + LPC24XX_PIN_EMC_DQM_1, + LPC24XX_PIN_EMC_DQM_2, + LPC24XX_PIN_EMC_DQM_3, +#endif + LPC24XX_PIN_TERMINAL +}; diff --git a/bsps/arm/lpc32xx/start/bsp_specs b/bsps/arm/lpc32xx/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/lpc32xx/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/lpc32xx/start/bspreset.c b/bsps/arm/lpc32xx/start/bspreset.c new file mode 100644 index 0000000000..e3c4cfbbd2 --- /dev/null +++ b/bsps/arm/lpc32xx/start/bspreset.c @@ -0,0 +1,48 @@ +/** + * @file + * + * @ingroup arm_lpc32xx + * + * @brief Reset code. + */ + +/* + * Copyright (c) 2009-2010 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <stdbool.h> + +#include <bspopts.h> +#include <bsp/bootcard.h> +#include <bsp/lpc32xx.h> + +static void watchdog_reset(void) +{ + #ifdef LPC32XX_ENABLE_WATCHDOG_RESET + LPC32XX_TIMCLK_CTRL |= TIMCLK_CTRL_WDT; + lpc32xx.wdt.mctrl |= WDTTIM_MCTRL_M_RES1 | WDTTIM_MCTRL_M_RES2; + lpc32xx.wdt.emr = WDTTIM_EMR_MATCH_CTRL_SET(lpc32xx.wdt.emr, 0x2); + lpc32xx.wdt.ctrl |= WDTTIM_CTRL_COUNT_ENAB; + lpc32xx.wdt.match0 = 1; + lpc32xx.wdt.counter = 0; + #endif +} + +void bsp_reset( void) +{ + watchdog_reset(); + + while (true) { + /* Do nothing */ + } +} diff --git a/bsps/arm/lpc32xx/start/bspstart.c b/bsps/arm/lpc32xx/start/bspstart.c new file mode 100644 index 0000000000..7ade16bbb8 --- /dev/null +++ b/bsps/arm/lpc32xx/start/bspstart.c @@ -0,0 +1,38 @@ +/** + * @file + * + * @ingroup arm_lpc32xx + * + * @brief Startup code. + */ + +/* + * Copyright (c) 2009-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <rtems/counter.h> + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> + +CPU_Counter_ticks _CPU_Counter_read(void) +{ + return lpc32xx_timer(); +} + +void bsp_start(void) +{ + rtems_counter_initialize_converter(LPC32XX_PERIPH_CLK); + bsp_interrupt_initialize(); +} diff --git a/bsps/arm/lpc32xx/start/bspstarthooks.c b/bsps/arm/lpc32xx/start/bspstarthooks.c new file mode 100644 index 0000000000..1df21b4343 --- /dev/null +++ b/bsps/arm/lpc32xx/start/bspstarthooks.c @@ -0,0 +1,240 @@ +/** + * @file + * + * @ingroup arm_lpc32xx + * + * @brief Startup code. + */ + +/* + * Copyright (c) 2009-2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 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.org/license/LICENSE. + */ + +#define ARM_CP15_TEXT_SECTION BSP_START_TEXT_SECTION + +#include <bsp.h> +#include <bsp/start.h> +#include <bsp/lpc32xx.h> +#include <bsp/mmu.h> +#include <bsp/arm-cp15-start.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 + +#ifndef LPC32XX_DISABLE_MMU + static const BSP_START_DATA_SECTION arm_cp15_start_section_config + lpc32xx_mmu_config_table [] = { + { + .begin = (uint32_t) bsp_section_fast_text_begin, + .end = (uint32_t) bsp_section_fast_text_end, + .flags = LPC32XX_MMU_CODE + }, { + .begin = (uint32_t) bsp_section_fast_data_begin, + .end = (uint32_t) bsp_section_fast_data_end, + .flags = LPC32XX_MMU_READ_WRITE_DATA +#ifdef LPC32XX_SCRATCH_AREA_SIZE + }, { + .begin = (uint32_t) &lpc32xx_scratch_area [0], + .end = (uint32_t) &lpc32xx_scratch_area [LPC32XX_SCRATCH_AREA_SIZE], + .flags = LPC32XX_MMU_READ_ONLY_DATA +#endif + }, { + .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_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 + }, { + .begin = (uint32_t) lpc32xx_magic_zero_begin, + .end = (uint32_t) lpc32xx_magic_zero_end, + .flags = LPC32XX_MMU_READ_WRITE_DATA + } + }; +#endif + +static BSP_START_TEXT_SECTION void setup_mmu_and_cache(void) +{ + uint32_t ctrl = arm_cp15_start_setup_mmu_and_cache( + ARM_CP15_CTRL_I | ARM_CP15_CTRL_R | ARM_CP15_CTRL_C + | ARM_CP15_CTRL_V | ARM_CP15_CTRL_M, + ARM_CP15_CTRL_S | ARM_CP15_CTRL_A + ); + + arm_cp15_cache_invalidate(); + + #ifndef LPC32XX_DISABLE_MMU + arm_cp15_start_setup_translation_table_and_enable_mmu_and_cache( + ctrl, + (uint32_t *) bsp_translation_table_base, + LPC32XX_MMU_CLIENT_DOMAIN, + &lpc32xx_mmu_config_table [0], + RTEMS_ARRAY_SIZE(lpc32xx_mmu_config_table) + ); + #endif +} + +BSP_START_TEXT_SECTION bool lpc32xx_start_pll_setup( + uint32_t hclkpll_ctrl, + uint32_t hclkdiv_ctrl, + bool force +) +{ + uint32_t pwr_ctrl = LPC32XX_PWR_CTRL; + bool settings_ok = + ((LPC32XX_HCLKPLL_CTRL ^ hclkpll_ctrl) & BSP_MSK32(1, 16)) == 0 + && ((LPC32XX_HCLKDIV_CTRL ^ hclkdiv_ctrl) & BSP_MSK32(0, 8)) == 0; + + if ((pwr_ctrl & PWR_NORMAL_RUN_MODE) == 0 || (!settings_ok && force)) { + /* Disable HCLK PLL output */ + LPC32XX_PWR_CTRL = pwr_ctrl & ~PWR_NORMAL_RUN_MODE; + + /* Configure HCLK PLL */ + LPC32XX_HCLKPLL_CTRL = hclkpll_ctrl; + while ((LPC32XX_HCLKPLL_CTRL & HCLK_PLL_LOCK) == 0) { + /* Wait */ + } + + /* Setup HCLK divider */ + LPC32XX_HCLKDIV_CTRL = hclkdiv_ctrl; + + /* Enable HCLK PLL output */ + LPC32XX_PWR_CTRL = pwr_ctrl | PWR_NORMAL_RUN_MODE; + } + + return settings_ok; +} + +#if LPC32XX_OSCILLATOR_MAIN != 13000000U + #error "unexpected main oscillator frequency" +#endif + +static BSP_START_TEXT_SECTION void setup_pll(void) +{ + uint32_t hclkpll_ctrl = LPC32XX_HCLKPLL_CTRL_INIT_VALUE; + uint32_t hclkdiv_ctrl = LPC32XX_HCLKDIV_CTRL_INIT_VALUE; + + lpc32xx_start_pll_setup(hclkpll_ctrl, hclkdiv_ctrl, false); +} + +BSP_START_TEXT_SECTION void bsp_start_hook_0(void) +{ + setup_pll(); +} + +static BSP_START_TEXT_SECTION void stop_dma_activities(void) +{ + #ifdef LPC32XX_STOP_GPDMA + LPC32XX_DO_STOP_GPDMA; + #endif + + #ifdef LPC32XX_STOP_ETHERNET + LPC32XX_DO_STOP_ETHERNET; + #endif + + #ifdef LPC32XX_STOP_USB + LPC32XX_DO_STOP_USB; + #endif +} + +static BSP_START_TEXT_SECTION void setup_uarts(void) +{ + LPC32XX_UART_CTRL = 0x0; + LPC32XX_UART_LOOP = 0x0; + + #ifdef LPC32XX_UART_5_BAUD + LPC32XX_UARTCLK_CTRL |= 1U << 2; + LPC32XX_U5CLK = LPC32XX_CONFIG_U5CLK; + LPC32XX_UART_CLKMODE = BSP_FLD32SET(LPC32XX_UART_CLKMODE, 0x2, 8, 9); + BSP_CONSOLE_UART_INIT(0x01); + #endif +} + +static BSP_START_TEXT_SECTION void setup_timer(void) +{ + volatile lpc_timer *timer = LPC32XX_STANDARD_TIMER; + + LPC32XX_TIMCLK_CTRL1 = (1U << 2) | (1U << 3); + + timer->tcr = LPC_TIMER_TCR_RST; + timer->ctcr = 0x0; + timer->pr = 0x0; + timer->ir = 0xff; + timer->mcr = 0x0; + timer->ccr = 0x0; + timer->tcr = LPC_TIMER_TCR_EN; +} + +BSP_START_TEXT_SECTION void bsp_start_hook_1(void) +{ + stop_dma_activities(); + bsp_start_copy_sections(); + setup_mmu_and_cache(); + setup_uarts(); + setup_timer(); + bsp_start_clear_bss(); +} diff --git a/bsps/arm/lpc32xx/start/linkcmds.lpc32xx b/bsps/arm/lpc32xx/start/linkcmds.lpc32xx new file mode 100644 index 0000000000..200e7f3e04 --- /dev/null +++ b/bsps/arm/lpc32xx/start/linkcmds.lpc32xx @@ -0,0 +1,17 @@ +/** + * @file + * + * @ingroup lpc32xx_linker + * + * @brief Linker support. + */ + +bsp_translation_table_base = ORIGIN (RAM_MMU); + +lpc32xx = 0x20020000; + +lpc32xx_magic_zero_begin = 0x05000000; +lpc32xx_magic_zero_end = 0x07000000; +lpc32xx_magic_zero_size = lpc32xx_magic_zero_end - lpc32xx_magic_zero_end; + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/lpc32xx/start/linkcmds.lpc32xx_mzx b/bsps/arm/lpc32xx/start/linkcmds.lpc32xx_mzx new file mode 100644 index 0000000000..127a82f79a --- /dev/null +++ b/bsps/arm/lpc32xx/start/linkcmds.lpc32xx_mzx @@ -0,0 +1,69 @@ +/** + * @file + * + * @ingroup lpc32xx_linker_mzx + * + * @brief Memory map. + */ + +/** + * @defgroup lpc32xx_linker_mzx MZX Application Memory Map + * + * @ingroup bsp_linker + * + * @brief MZX application memory map. + * + * <table> + * <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr> + * <tr><td>RAM_INT</td><td>0x08000000</td><td>256k</td></tr> + * <tr><td>RAM_MMU</td><td>0x80000000</td><td>16k</td></tr> + * <tr><td>RAM_EXT</td><td>0x80004000</td><td>32M - 16k</td></tr> + * </table> + * + * <table> + * <tr><th>Section Name</th><th>Section Runtime Region</th><th>Section Load Region</th></tr> + * <tr><td>.start</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.vector</td><td>RAM_INT</td><td></td></tr> + * <tr><td>.text</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.rodata</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.data</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.fast</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.bss</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.work</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.stack</td><td>RAM_INT</td><td></td></tr> + * </table> + */ + +MEMORY { + RAM_INT : ORIGIN = 0x08000000, LENGTH = 256k + RAM_MMU : ORIGIN = 0x80000000, LENGTH = 16k /* SDRAM on DYCS0 */ + RAM_SCRATCH : ORIGIN = 0x80004000, LENGTH = 4k /* SDRAM on DYCS0 */ + RAM_EXT : ORIGIN = 0x80005000, LENGTH = 32M - 20k /* SDRAM on DYCS0 */ +} + +REGION_ALIAS ("REGION_START", RAM_EXT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", RAM_EXT); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_RODATA", RAM_EXT); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_DATA", RAM_EXT); +REGION_ALIAS ("REGION_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_EXT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_EXT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +lpc32xx_scratch_area = ORIGIN (RAM_SCRATCH); + +bsp_stack_irq_size = DEFINED (bsp_stack_irq_size) ? bsp_stack_irq_size : 4096; +bsp_stack_abt_size = DEFINED (bsp_stack_abt_size) ? bsp_stack_abt_size : 1024; + +bsp_section_rwbarrier_align = DEFINED (bsp_section_rwbarrier_align) ? bsp_section_rwbarrier_align : 1M; + +INCLUDE linkcmds.lpc32xx diff --git a/bsps/arm/lpc32xx/start/linkcmds.lpc32xx_mzx_stage_1 b/bsps/arm/lpc32xx/start/linkcmds.lpc32xx_mzx_stage_1 new file mode 100644 index 0000000000..eae076e235 --- /dev/null +++ b/bsps/arm/lpc32xx/start/linkcmds.lpc32xx_mzx_stage_1 @@ -0,0 +1,68 @@ +/** + * @file + * + * @ingroup lpc32xx_linker_mzx_stage_1 + * + * @brief Memory map. + */ + +/** + * @defgroup lpc32xx_linker_mzx_stage_1 MZX Stage-1 Program Memory Map + * + * @ingroup bsp_linker + * + * @brief MZX stage-1 program memory map. + * + * <table> + * <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr> + * <tr><td>RAM_INT</td><td>0x08000000</td><td>232k</td></tr> + * <tr><td>RAM_MMU</td><td>0x0803a000</td><td>16k</td></tr> + * <tr><td>RAM_VEC</td><td>0x0803d000</td><td>8k</td></tr> + * </table> + * + * <table> + * <tr><th>Section Name</th><th>Section Runtime Region</th><th>Section Load Region</th></tr> + * <tr><td>.start</td><td>RAM_INT</td><td></td></tr> + * <tr><td>.vector</td><td>RAM_INT</td><td></td></tr> + * <tr><td>.text</td><td>RAM_INT</td><td>RAM_INT</td></tr> + * <tr><td>.rodata</td><td>RAM_INT</td><td>RAM_INT</td></tr> + * <tr><td>.data</td><td>RAM_INT</td><td>RAM_INT</td></tr> + * <tr><td>.fast</td><td>RAM_INT</td><td>RAM_INT</td></tr> + * <tr><td>.bss</td><td>RAM_INT</td><td></td></tr> + * <tr><td>.work</td><td>RAM_INT</td><td></td></tr> + * <tr><td>.stack</td><td>RAM_INT</td><td></td></tr> + * </table> + */ + +MEMORY { + RAM_INT : ORIGIN = 0x08000000, LENGTH = 232k + RAM_VEC : ORIGIN = 0x0803a000, LENGTH = 8k + RAM_MMU : ORIGIN = 0x0803c000, LENGTH = 16k + RAM_SCRATCH : ORIGIN = 0x80004000, LENGTH = 4k /* SDRAM on DYCS0 */ +} + +REGION_ALIAS ("REGION_START", RAM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_VEC); +REGION_ALIAS ("REGION_TEXT", RAM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM_INT); +REGION_ALIAS ("REGION_RODATA", RAM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM_INT); +REGION_ALIAS ("REGION_DATA", RAM_INT); +REGION_ALIAS ("REGION_DATA_LOAD", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM_INT); +REGION_ALIAS ("REGION_BSS", RAM_INT); +REGION_ALIAS ("REGION_WORK", RAM_INT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +lpc32xx_scratch_area = ORIGIN (RAM_SCRATCH); + +bsp_stack_svc_size = DEFINED (bsp_stack_svc_size) ? bsp_stack_svc_size : 7168; + +bsp_vector_table_in_start_section = 1; + +INCLUDE linkcmds.lpc32xx diff --git a/bsps/arm/lpc32xx/start/linkcmds.lpc32xx_mzx_stage_2 b/bsps/arm/lpc32xx/start/linkcmds.lpc32xx_mzx_stage_2 new file mode 100644 index 0000000000..2aa8c34091 --- /dev/null +++ b/bsps/arm/lpc32xx/start/linkcmds.lpc32xx_mzx_stage_2 @@ -0,0 +1,67 @@ +/** + * @file + * + * @ingroup lpc32xx_linker_mzx_stage_2 + * + * @brief Memory map. + */ + +/** + * @defgroup lpc32xx_linker_mzx_stage_2 MZX Stage-2 Program Memory Map + * + * @ingroup bsp_linker + * + * @brief MZX stage-2 program memory map. + * + * <table> + * <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr> + * <tr><td>RAM_INT</td><td>0x08000000</td><td>256k</td></tr> + * <tr><td>RAM_MMU</td><td>0x81c00000</td><td>16k</td></tr> + * <tr><td>RAM_EXT</td><td>0x81c04000</td><td>4M - 16k</td></tr> + * </table> + * + * <table> + * <tr><th>Section Name</th><th>Section Runtime Region</th><th>Section Load Region</th></tr> + * <tr><td>.start</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.vector</td><td>RAM_INT</td><td></td></tr> + * <tr><td>.text</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.rodata</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.data</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.fast</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.bss</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.work</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.stack</td><td>RAM_INT</td><td></td></tr> + * </table> + */ + +MEMORY { + RAM_INT : ORIGIN = 0x08000000, LENGTH = 240k + RAM_FAST : ORIGIN = 0x0803c000, LENGTH = 16k + RAM_MMU : ORIGIN = 0x80000000, LENGTH = 16k /* SDRAM on DYCS0 */ + RAM_SCRATCH : ORIGIN = 0x80004000, LENGTH = 4k /* SDRAM on DYCS0 */ + RAM_EXT : ORIGIN = 0x81c00000, LENGTH = 4M /* SDRAM on DYCS0 */ +} + +REGION_ALIAS ("REGION_START", RAM_EXT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", RAM_EXT); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_RODATA", RAM_EXT); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_DATA", RAM_EXT); +REGION_ALIAS ("REGION_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_FAST); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_FAST); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +lpc32xx_scratch_area = ORIGIN (RAM_SCRATCH); + +bsp_stack_svc_size = DEFINED (bsp_stack_svc_size) ? bsp_stack_svc_size : 8192; + +INCLUDE linkcmds.lpc32xx diff --git a/bsps/arm/lpc32xx/start/linkcmds.lpc32xx_phycore b/bsps/arm/lpc32xx/start/linkcmds.lpc32xx_phycore new file mode 100644 index 0000000000..d874c46152 --- /dev/null +++ b/bsps/arm/lpc32xx/start/linkcmds.lpc32xx_phycore @@ -0,0 +1,68 @@ +/** + * @file + * + * @ingroup lpc32xx_linker_phycore + * + * @brief Memory map. + */ + +/** + * @defgroup lpc32xx_linker_phycore phyCORE-LPC3250 Memory Map + * + * @ingroup bsp_linker + * + * @brief phyCORE-LPC3250 memory map. + * + * <table> + * <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr> + * <tr><td>RAM_INT</td><td>0x08000000</td><td>256k</td></tr> + * <tr><td>RAM_MMU</td><td>0x80000000</td><td>16k</td></tr> + * <tr><td>RAM_EXT</td><td>0x80004000</td><td>64M - 16k</td></tr> + * <tr><td>ROM_EXT</td><td>0xe0000000</td><td>2M</td></tr> + * </table> + * + * <table> + * <tr><th>Section Name</th><th>Section Runtime Region</th><th>Section Load Region</th></tr> + * <tr><td>.start</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.vector</td><td>RAM_INT</td><td></td></tr> + * <tr><td>.text</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.rodata</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.data</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.fast</td><td>RAM_EXT</td><td>RAM_EXT</td></tr> + * <tr><td>.bss</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.work</td><td>RAM_EXT</td><td></td></tr> + * <tr><td>.stack</td><td>RAM_INT</td><td></td></tr> + * </table> + */ + +MEMORY { + RAM_INT : ORIGIN = 0x08000000, LENGTH = 256k + RAM_MMU : ORIGIN = 0x80000000, LENGTH = 16k /* SDRAM on DYCS0 */ + RAM_EXT : ORIGIN = 0x80004000, LENGTH = 64M - 16k /* SDRAM on DYCS0 */ + ROM_EXT : ORIGIN = 0xe0000000, LENGTH = 2M /* NOR flash on CS0 */ +} + +REGION_ALIAS ("REGION_START", RAM_EXT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", RAM_EXT); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_RODATA", RAM_EXT); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_DATA", RAM_EXT); +REGION_ALIAS ("REGION_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_EXT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_EXT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +bsp_stack_irq_size = DEFINED (bsp_stack_irq_size) ? bsp_stack_irq_size : 4096; +bsp_stack_abt_size = DEFINED (bsp_stack_abt_size) ? bsp_stack_abt_size : 1024; + +bsp_section_rwbarrier_align = DEFINED (bsp_section_rwbarrier_align) ? bsp_section_rwbarrier_align : 1M; + +INCLUDE linkcmds.lpc32xx diff --git a/bsps/arm/raspberrypi/start/bsp_specs b/bsps/arm/raspberrypi/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/raspberrypi/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/raspberrypi/start/bspgetworkarea.c b/bsps/arm/raspberrypi/start/bspgetworkarea.c new file mode 100644 index 0000000000..6a43e3c437 --- /dev/null +++ b/bsps/arm/raspberrypi/start/bspgetworkarea.c @@ -0,0 +1,78 @@ +/** + * @file + * + * @ingroup arm_start + * + * @brief Raspberry pi workarea initialization. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * Copyright (c) 2011-2012 embedded brains GmbH. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + * + * Copyright (c) 2015 YANG Qiao + * + * Code is based on c/src/lib/libbsp/shared/bspgetworkarea.c + */ + +#include <string.h> +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/vc.h> +#ifdef BSP_INTERRUPT_STACK_AT_WORK_AREA_BEGIN + #include <rtems/config.h> +#endif + +#if defined(HAS_UBOOT) && !defined(BSP_DISABLE_UBOOT_WORK_AREA_CONFIG) + #define USE_UBOOT +#endif + +/* + * These are provided by the linkcmds for ALL of the BSPs which use this file. + */ +extern char WorkAreaBase[]; + +/* + * We may get the size information from U-Boot or the linker scripts. + */ +#ifdef USE_UBOOT + #include <bsp/u-boot.h> +#else + extern char RamBase[]; + extern char RamSize[]; +#endif + +void bsp_work_area_initialize(void) +{ + uintptr_t work_base = (uintptr_t) WorkAreaBase; + uintptr_t ram_end; + bcm2835_get_vc_memory_entries vc_entry; + /* + * bcm2835_get_arm_memory_entries arm_entry; + * is another alternative how to obtain usable memory size + */ + + #ifdef USE_UBOOT + ram_end = (uintptr_t) bsp_uboot_board_info.bi_memstart + + bsp_uboot_board_info.bi_memsize; + #else + ram_end = (uintptr_t)RamBase + (uintptr_t)RamSize; + #endif + + #ifdef BSP_INTERRUPT_STACK_AT_WORK_AREA_BEGIN + work_base += rtems_configuration_get_interrupt_stack_size(); + #endif + + memset( &vc_entry, 0, sizeof(vc_entry) ); + if (bcm2835_mailbox_get_vc_memory( &vc_entry ) >= 0) { + if (vc_entry.base > 10 * 1024 *1024) + ram_end = ram_end > vc_entry.base? vc_entry.base: ram_end; + } + bsp_work_area_initialize_default( (void *) work_base, ram_end - work_base ); +} diff --git a/bsps/arm/raspberrypi/start/bspreset.c b/bsps/arm/raspberrypi/start/bspreset.c new file mode 100644 index 0000000000..98c28bea9d --- /dev/null +++ b/bsps/arm/raspberrypi/start/bspreset.c @@ -0,0 +1,26 @@ +/** + * @file + * + * @ingroup raspberrypi + * + * @brief Raspberry pi restart chip function + */ + +#include <bsp/bootcard.h> +#include <bsp/raspberrypi.h> +#include <bsp.h> +#include <rtems.h> + +void bsp_reset(void) +{ + uint32_t rstc; + + BCM2835_REG(BCM2835_PM_WDOG) = BCM2835_PM_PASSWD_MAGIC | 20; + rstc = BCM2835_REG(BCM2835_PM_RSTC); + rstc &= ~BCM2835_PM_RSTC_WRCFG; + rstc |= BCM2835_PM_PASSWD_MAGIC | BCM2835_PM_RSTC_WRCFG_FULL; + BCM2835_REG(BCM2835_PM_RSTC) = rstc; + BCM2835_REG(BCM2835_PM_WDOG) = BCM2835_PM_PASSWD_MAGIC | 1; + + while (1) ; +} diff --git a/bsps/arm/raspberrypi/start/bspsmp.c b/bsps/arm/raspberrypi/start/bspsmp.c new file mode 100644 index 0000000000..c3e5451442 --- /dev/null +++ b/bsps/arm/raspberrypi/start/bspsmp.c @@ -0,0 +1,83 @@ +/** + * @file + * + * @ingroup raspberrypi + * + * @brief Raspberry pi SMP management functions provided to SuperCore + */ + +/* + * Copyright (c) 2016 Pavel Pisa <pisa@cmp.felk.cvut.cz> + * + * Czech Technical University in Prague + * Zikova 1903/4 + * 166 36 Praha 6 + * Czech Republic + * + * Reuses some ideas from Rohini Kulkarni <krohini1593@gmail.com> + * GSoC 2015 project and Altera Cyclone-V SMP code + * by embedded brains GmbH + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/score/smpimpl.h> + +#include <bsp/start.h> +#include <bsp/raspberrypi.h> +#include <bsp.h> +#include <bsp/arm-cp15-start.h> +#include <libcpu/arm-cp15.h> +#include <rtems.h> +#include <bsp/irq-generic.h> +#include <assert.h> + +bool _CPU_SMP_Start_processor( uint32_t cpu_index ) +{ + bool started; + uint32_t cpu_index_self = _SMP_Get_current_processor(); + + if (cpu_index != cpu_index_self) { + + BCM2835_REG(BCM2836_MAILBOX_3_WRITE_SET_BASE + 0x10 * cpu_index) = (uint32_t)_start; + + /* + * Wait for secondary processor to complete its basic initialization so + * that we can enable the unified L2 cache. + */ + started = _Per_CPU_State_wait_for_non_initial_state(cpu_index, 0); + } else { + started = false; + } + + return started; +} + +uint32_t _CPU_SMP_Initialize(void) +{ + uint32_t cpu_count = (uint32_t)bsp_processor_count; + + if ( cpu_count > 4 ) + cpu_count = 4; + + return cpu_count; +} + +void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ) +{ + /* Do nothing */ +} + +void _CPU_SMP_Prepare_start_multitasking( void ) +{ + /* Do nothing */ +} + +void _CPU_SMP_Send_interrupt( uint32_t target_cpu_index ) +{ + /* Generates IPI */ + BCM2835_REG(BCM2836_MAILBOX_3_WRITE_SET_BASE + + 0x10 * target_cpu_index) = 0x1; +} diff --git a/bsps/arm/raspberrypi/start/bspsmp_init.c b/bsps/arm/raspberrypi/start/bspsmp_init.c new file mode 100644 index 0000000000..8c8cd74712 --- /dev/null +++ b/bsps/arm/raspberrypi/start/bspsmp_init.c @@ -0,0 +1,81 @@ +/** + * @file + * + * @ingroup raspberrypi + * + * @brief Raspberry pi secondary CPU and IPI HW initialization + */ + +/* + * Copyright (c) 2016 Pavel Pisa <pisa@cmp.felk.cvut.cz> + * + * Czech Technical University in Prague + * Zikova 1903/4 + * 166 36 Praha 6 + * Czech Republic + * + * Reuses some ideas from Rohini Kulkarni <krohini1593@gmail.com> + * GSoC 2015 project and Altera Cyclone-V SMP code + * by embedded brains GmbH + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/score/smpimpl.h> + +#include <bsp/start.h> +#include <bsp/raspberrypi.h> +#include <bsp.h> +#include <bsp/arm-cp15-start.h> +#include <libcpu/arm-cp15.h> +#include <rtems.h> +#include <bsp/irq-generic.h> +#include <assert.h> + +void rpi_ipi_initialize(void) +{ + uint32_t cpu_index_self = _SMP_Get_current_processor(); + + /* + * Includes support only for mailbox 3 interrupt. + * Further interrupt support has to be added. This will have to be integrated + * with existing interrupt support for Raspberry Pi + */ + + /* reset mailbox 3 contents to zero */ + BCM2835_REG(BCM2836_MAILBOX_3_READ_CLEAR_BASE + 0x10 * cpu_index_self) = 0xffffffff; + + BCM2835_REG(BCM2836_MAILBOX_IRQ_CTRL(cpu_index_self)) = + BCM2836_MAILBOX_IRQ_CTRL_MBOX3_IRQ; +} + +void rpi_start_rtems_on_secondary_processor(void) +{ + uint32_t ctrl; + + ctrl = arm_cp15_start_setup_mmu_and_cache( + 0, + ARM_CP15_CTRL_AFE | ARM_CP15_CTRL_Z + ); + + rpi_ipi_initialize(); + + arm_cp15_set_domain_access_control( + ARM_CP15_DAC_DOMAIN(ARM_MMU_DEFAULT_CLIENT_DOMAIN, ARM_CP15_DAC_CLIENT) + ); + + /* FIXME: Sharing the translation table between processors is brittle */ + arm_cp15_set_translation_table_base( + (uint32_t *) bsp_translation_table_base + ); + + arm_cp15_tlb_invalidate(); + + ctrl |= ARM_CP15_CTRL_I | ARM_CP15_CTRL_C | ARM_CP15_CTRL_M; + ctrl &= ~ARM_CP15_CTRL_V; + arm_cp15_set_control(ctrl); + + _SMP_Start_multitasking_on_secondary_processor(); +} diff --git a/bsps/arm/raspberrypi/start/bspstart.c b/bsps/arm/raspberrypi/start/bspstart.c new file mode 100644 index 0000000000..c5786bfa4a --- /dev/null +++ b/bsps/arm/raspberrypi/start/bspstart.c @@ -0,0 +1,29 @@ +/** + * @file + * + * @ingroup arm_start + * + * @brief Raspberry pi startup code. + */ + +/* + * Copyright (c) 2013 by Alan Cudmore + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * + * http://www.rtems.org/license/LICENSE + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> +#include <bsp/irq.h> +#include <bsp/linker-symbols.h> +#include <bsp/stackalloc.h> +#include <bsp/raspberrypi.h> + +void bsp_start(void) +{ + bsp_interrupt_initialize(); +} diff --git a/bsps/arm/raspberrypi/start/bspstarthooks.c b/bsps/arm/raspberrypi/start/bspstarthooks.c new file mode 100644 index 0000000000..165a555880 --- /dev/null +++ b/bsps/arm/raspberrypi/start/bspstarthooks.c @@ -0,0 +1,107 @@ +/** + * @file + * + * @ingroup arm_start + * + * @brief Rasberry Pi startup code. + */ + +/* + * Copyright (c) 2013. Hesham AL-Matary + * Copyright (c) 2013 by Alan Cudmore + * based on work by: + * 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.org/license/LICENSE + */ + +#include <bspopts.h> +#include <bsp/start.h> +#include <bsp/raspberrypi.h> +#include <bsp/mm.h> +#include <libcpu/arm-cp15.h> +#include <bsp.h> + +#ifdef RTEMS_SMP +#include <rtems/score/smp.h> +#endif + +void BSP_START_TEXT_SECTION bsp_start_hook_0(void) +{ + uint32_t sctlr_val; +#ifdef RTEMS_SMP + uint32_t cpu_index_self = _SMP_Get_current_processor(); +#endif /* RTEMS_SMP */ + + sctlr_val = arm_cp15_get_control(); + + /* + * Current U-boot loader seems to start kernel image + * with I and D caches on and MMU enabled. + * If RTEMS application image finds that cache is on + * during startup then disable caches. + */ + if (sctlr_val & (ARM_CP15_CTRL_I | ARM_CP15_CTRL_C | ARM_CP15_CTRL_M)) { + if (sctlr_val & (ARM_CP15_CTRL_C | ARM_CP15_CTRL_M)) { + /* + * If the data cache is on then ensure that it is clean + * before switching off to be extra carefull. + */ +#ifdef RTEMS_SMP + if (cpu_index_self != 0) { + arm_cp15_data_cache_clean_level(0); + arm_cp15_cache_invalidate_level(0, 0); + } else +#endif /* RTEMS_SMP */ + { + rtems_cache_flush_entire_data(); + rtems_cache_invalidate_entire_data(); + } + } + arm_cp15_flush_prefetch_buffer(); + sctlr_val &= ~(ARM_CP15_CTRL_I | ARM_CP15_CTRL_C | ARM_CP15_CTRL_M | ARM_CP15_CTRL_A); + arm_cp15_set_control(sctlr_val); + } +#ifdef RTEMS_SMP + if (cpu_index_self != 0) { + arm_cp15_cache_invalidate_level(0, 0); + } else +#endif /* RTEMS_SMP */ + { + rtems_cache_invalidate_entire_data(); + } + rtems_cache_invalidate_entire_instruction(); + arm_cp15_branch_predictor_invalidate_all(); + arm_cp15_tlb_invalidate(); + arm_cp15_flush_prefetch_buffer(); + + /* Clear Translation Table Base Control Register */ + arm_cp15_set_translation_table_base_control_register(0); + + /* Clear Secure or Non-secure Vector Base Address Register */ + arm_cp15_set_vector_base_address(0); + +#ifdef RTEMS_SMP + if (cpu_index_self == 0) { + rpi_ipi_initialize(); + } else { + rpi_start_rtems_on_secondary_processor(); + } +#endif +} + +void BSP_START_TEXT_SECTION bsp_start_hook_1(void) +{ + bsp_start_copy_sections(); + bsp_memory_management_initialize(); + bsp_start_clear_bss(); + + rpi_video_init(); +} diff --git a/bsps/arm/raspberrypi/start/cmdline.c b/bsps/arm/raspberrypi/start/cmdline.c new file mode 100644 index 0000000000..222b21eb63 --- /dev/null +++ b/bsps/arm/raspberrypi/start/cmdline.c @@ -0,0 +1,55 @@ +/** + * @file + * + * @ingroup raspberrypi + * + * @brief mailbox support. + */ +/* + * Copyright (c) 2015 Yang Qiao + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * + * http://www.rtems.org/license/LICENSE + * + */ + +#include <bsp.h> +#include <bsp/vc.h> + +#include <string.h> + +#define MAX_CMDLINE_LENGTH 1024 +static int rpi_cmdline_ready = -1; +static char rpi_cmdline_cached[MAX_CMDLINE_LENGTH] = "force .data placement"; +static bcm2835_get_cmdline_entries rpi_cmdline_entries; + +const char *rpi_cmdline_get_raw(void) +{ + memset(&rpi_cmdline_entries, 0, sizeof(rpi_cmdline_entries)); + if (bcm2835_mailbox_get_cmdline(&rpi_cmdline_entries) < 0) + return NULL; + return rpi_cmdline_entries.cmdline; +} + +const char *rpi_cmdline_get_cached(void) +{ + if (rpi_cmdline_ready <= 0) { + const char *line = rpi_cmdline_get_raw(); + if (line != NULL) + strncpy(rpi_cmdline_cached, line, MAX_CMDLINE_LENGTH - 1); + rpi_cmdline_cached[MAX_CMDLINE_LENGTH - 1] = 0; + rpi_cmdline_ready = 1; + } + return rpi_cmdline_cached; +} + +const char *rpi_cmdline_get_arg(const char* arg) +{ + const char *opt_data; + opt_data = strstr(rpi_cmdline_get_cached(), arg); + if (opt_data) + opt_data += strlen(arg); + return opt_data; +} diff --git a/bsps/arm/raspberrypi/start/linkcmds.in b/bsps/arm/raspberrypi/start/linkcmds.in new file mode 100644 index 0000000000..829716c11c --- /dev/null +++ b/bsps/arm/raspberrypi/start/linkcmds.in @@ -0,0 +1,70 @@ +/** + * @file + * + * @ingroup raspberrypi_linker + * + * @brief Memory map + */ + +/** + * @defgroup raspberrypi_linker Raspberry Pi Memory Map + * + * @ingroup bsp_linker + * + * @brief Raspberry Pi memory map. + */ + +/** + * <table> + * <tr><th>Region Name</th><th>Region Begin</th><th>Region Size</th></tr> + * <tr><td>VECTOR_RAM</td><td>0x08000000</td><td>8k</td></tr> + * <tr><td>RAM</td><td>0x80008000</td><td>128M</td></tr> + * </table> + * + * <table> + * <tr><th>Section Name</th><th>Section Runtime Region</th><th>Section Load Region</th></tr> + * <tr><td>.start</td><td>RAM</td><td></td></tr> + * <tr><td>.vector</td><td>VECTOR_RAM</td><td></td></tr> + * <tr><td>.text</td><td>RAM</td><td>RAM_EXT</td></tr> + * <tr><td>.rodata</td><td>RAM</td><td>RAM_EXT</td></tr> + * <tr><td>.data</td><td>RAM</td><td>RAM_EXT</td></tr> + * <tr><td>.fast</td><td>RAM</td><td>RAM_EXT</td></tr> + * <tr><td>.bss</td><td>RAM</td><td></td></tr> + * <tr><td>.work</td><td>RAM</td><td></td></tr> + * <tr><td>.stack</td><td>RAM</td><td></td></tr> + * </table> + */ + +MEMORY { + VECTOR_RAM (AIW) : ORIGIN = 0x0 , LENGTH = 16k + RAM_MMU (AIW) : ORIGIN = 0x00004000, LENGTH = 16k + RAM (AIW) : ORIGIN = 0x00008000, LENGTH = 128M - 32k +} + +bsp_processor_count = DEFINED (bsp_processor_count) ? bsp_processor_count : @RASPBERRYPI_CPUS@; + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_VECTOR", VECTOR_RAM); +REGION_ALIAS ("REGION_TEXT", RAM); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_RODATA", RAM); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", RAM); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM); + +bsp_stack_irq_size = DEFINED (bsp_stack_irq_size) ? bsp_stack_irq_size : 3008; +bsp_stack_abt_size = DEFINED (bsp_stack_abt_size) ? bsp_stack_abt_size : 1024; + +bsp_section_robarrier_align = DEFINED (bsp_section_robarrier_align) ? bsp_section_robarrier_align : 1M; +bsp_translation_table_base = ORIGIN (RAM_MMU); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/raspberrypi/start/mm_config_table.c b/bsps/arm/raspberrypi/start/mm_config_table.c new file mode 100644 index 0000000000..27fa76b355 --- /dev/null +++ b/bsps/arm/raspberrypi/start/mm_config_table.c @@ -0,0 +1,96 @@ +/** + * @file + * + * @ingroup arm_start + * + * @brief Raspberry Pi low level start + */ + +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/arm-cp15-start.h> + +/* + * Pagetable initialization data + * + * Keep all read-only sections before read-write ones. + * This ensures that write is allowed if one page/region + * is partially filled by read-only section contentent + * and rest is used for writeable section + */ + +const arm_cp15_start_section_config arm_cp15_start_mmu_config_table[] = { + { + .begin = (uint32_t) bsp_section_fast_text_begin, + .end = (uint32_t) bsp_section_fast_text_end, + .flags = ARMV7_MMU_CODE_CACHED + }, { + .begin = (uint32_t) bsp_section_start_begin, + .end = (uint32_t) bsp_section_start_end, + .flags = ARMV7_MMU_CODE_CACHED + }, { + .begin = (uint32_t) bsp_section_text_begin, + .end = (uint32_t) bsp_section_text_end, + .flags = ARMV7_MMU_CODE_CACHED + }, { + .begin = (uint32_t) bsp_section_rodata_begin, + .end = (uint32_t) bsp_section_rodata_end, + .flags = ARMV7_MMU_DATA_READ_ONLY_CACHED + }, { + .begin = (uint32_t) bsp_translation_table_base, + .end = (uint32_t) bsp_translation_table_base + 0x4000, + .flags = ARMV7_MMU_DATA_READ_WRITE_CACHED + }, { + .begin = (uint32_t) bsp_section_fast_data_begin, + .end = (uint32_t) bsp_section_fast_data_end, + .flags = ARMV7_MMU_DATA_READ_WRITE_CACHED + }, { + .begin = (uint32_t) bsp_section_vector_begin, + .end = (uint32_t) bsp_section_vector_end, + .flags = ARMV7_MMU_DATA_READ_WRITE_CACHED + }, { + .begin = (uint32_t) bsp_section_data_begin, + .end = (uint32_t) bsp_section_data_end, + .flags = ARMV7_MMU_DATA_READ_WRITE_CACHED + }, { + .begin = (uint32_t) bsp_section_bss_begin, + .end = (uint32_t) bsp_section_bss_end, + .flags = ARMV7_MMU_DATA_READ_WRITE_CACHED + }, { + .begin = (uint32_t) bsp_section_work_begin, + .end = (uint32_t) bsp_section_work_end, + .flags = ARMV7_MMU_DATA_READ_WRITE_CACHED + }, { + .begin = (uint32_t) bsp_section_stack_begin, + .end = (uint32_t) bsp_section_stack_end, + .flags = ARMV7_MMU_DATA_READ_WRITE_CACHED + }, { + .begin = RPI_PERIPHERAL_BASE, + .end = RPI_PERIPHERAL_BASE + RPI_PERIPHERAL_SIZE, + .flags = ARMV7_MMU_DEVICE + } +#if (BSP_IS_RPI2 == 1) + /* Core local peripherals area - timer, mailboxes */ + , { + .begin = BCM2836_CORE_LOCAL_PERIPH_BASE, + .end = BCM2836_CORE_LOCAL_PERIPH_BASE + BCM2836_CORE_LOCAL_PERIPH_SIZE, + .flags = ARMV7_MMU_DEVICE + } +#endif +}; + +const size_t arm_cp15_start_mmu_config_table_size = + RTEMS_ARRAY_SIZE(arm_cp15_start_mmu_config_table); diff --git a/bsps/arm/realview-pbx-a9/start/bsp_specs b/bsps/arm/realview-pbx-a9/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/realview-pbx-a9/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/realview-pbx-a9/start/bspreset.c b/bsps/arm/realview-pbx-a9/start/bspreset.c new file mode 100644 index 0000000000..15ff7193f1 --- /dev/null +++ b/bsps/arm/realview-pbx-a9/start/bspreset.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <bsp/bootcard.h> + +void bsp_reset(void) +{ + volatile uint32_t *sys_lock = (volatile uint32_t *) 0x10000020; + volatile uint32_t *sys_resetctl = (volatile uint32_t *) 0x10000040; + + while (true) { + *sys_lock = 0xa05f; + *sys_resetctl = 0xf4; + } +} diff --git a/bsps/arm/realview-pbx-a9/start/bspsmp.c b/bsps/arm/realview-pbx-a9/start/bspsmp.c new file mode 100644 index 0000000000..471e7e5f29 --- /dev/null +++ b/bsps/arm/realview-pbx-a9/start/bspsmp.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <rtems/score/smpimpl.h> + +bool _CPU_SMP_Start_processor(uint32_t cpu_index) +{ + (void) cpu_index; + + /* Nothing to do */ + + return true; +} diff --git a/bsps/arm/realview-pbx-a9/start/bspstart.c b/bsps/arm/realview-pbx-a9/start/bspstart.c new file mode 100644 index 0000000000..0be515c057 --- /dev/null +++ b/bsps/arm/realview-pbx-a9/start/bspstart.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/arm-a9mpcore-clock.h> +#include <bsp/irq-generic.h> + +void bsp_start(void) +{ + a9mpcore_clock_initialize_early(); + bsp_interrupt_initialize(); +} diff --git a/bsps/arm/realview-pbx-a9/start/bspstarthooks.c b/bsps/arm/realview-pbx-a9/start/bspstarthooks.c new file mode 100644 index 0000000000..ab766e8626 --- /dev/null +++ b/bsps/arm/realview-pbx-a9/start/bspstarthooks.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#define ARM_CP15_TEXT_SECTION BSP_START_TEXT_SECTION + +#include <bsp.h> +#include <bsp/start.h> +#include <bsp/arm-cp15-start.h> +#include <bsp/arm-a9mpcore-start.h> + +BSP_START_DATA_SECTION static const arm_cp15_start_section_config +rvpbxa9_mmu_config_table[] = { + ARMV7_CP15_START_DEFAULT_SECTIONS, + { + .begin = 0x10000000U, + .end = 0x10020000U, + .flags = ARMV7_MMU_DEVICE + }, { + .begin = 0x1f000000U, + .end = 0x20000000U, + .flags = ARMV7_MMU_DEVICE + }, { + .begin = 0x4e000000U, + .end = 0x4f000000U, + .flags = ARMV7_MMU_DEVICE + } +}; + +BSP_START_TEXT_SECTION static void setup_mmu_and_cache(void) +{ + uint32_t ctrl = arm_cp15_start_setup_mmu_and_cache( + ARM_CP15_CTRL_A, + ARM_CP15_CTRL_AFE | ARM_CP15_CTRL_Z + ); + + arm_cp15_start_setup_translation_table_and_enable_mmu_and_cache( + ctrl, + (uint32_t *) bsp_translation_table_base, + ARM_MMU_DEFAULT_CLIENT_DOMAIN, + &rvpbxa9_mmu_config_table[0], + RTEMS_ARRAY_SIZE(rvpbxa9_mmu_config_table) + ); +} + +BSP_START_TEXT_SECTION void bsp_start_hook_0(void) +{ +#ifdef RTEMS_SMP + uint32_t cpu_id = arm_cortex_a9_get_multiprocessor_cpu_id(); + + /* + * QEMU jumps to the entry point of the ELF file on all processors. Prevent + * a SMP_FATAL_MULTITASKING_START_ON_INVALID_PROCESSOR this way. + */ + if ( cpu_id >= rtems_configuration_get_maximum_processors() ) { + while (true) { + _ARM_Wait_for_event(); + } + } +#endif + + arm_a9mpcore_start_hook_0(); +} + +BSP_START_TEXT_SECTION void bsp_start_hook_1(void) +{ + arm_a9mpcore_start_hook_1(); + bsp_start_copy_sections(); + setup_mmu_and_cache(); + bsp_start_clear_bss(); +} diff --git a/bsps/arm/realview-pbx-a9/start/fb-config.c b/bsps/arm/realview-pbx-a9/start/fb-config.c new file mode 100644 index 0000000000..a756c9ab22 --- /dev/null +++ b/bsps/arm/realview-pbx-a9/start/fb-config.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <bsp/arm-pl111-fb.h> +#include <bsp.h> + +static void fb_set_up(const pl111_fb_config *cfg) +{ + /* TODO */ +} + +static void fb_pins_set_up(const pl111_fb_config *cfg) +{ + /* TODO */ +} + +static void fb_pins_tear_down(const pl111_fb_config *cfg) +{ + /* TODO */ +} + +static void fb_tear_down(const pl111_fb_config *cfg) +{ + /* TODO */ +} + +static const pl111_fb_config fb_config = { + .regs = (volatile pl111 *) 0x10020000, + + /* + * Values obtained from "RealView Platform Baseboard Explore for Cortex-A9 + * User Guide" section 4.6.1 "Display resolutions and display memory + * organization". + */ + .timing0 = 0x3f1f3f9c, + .timing1 = 0x090b61df, + .timing2 = 0x067f1800, + + .timing3 = 0x0, + .control = PL111_LCD_CONTROL_LCD_TFT + | PL111_LCD_CONTROL_LCD_BPP(PL111_LCD_CONTROL_LCD_BPP_16) + | PL111_LCD_CONTROL_BGR, + .power_delay_in_us = 100000, + .set_up = fb_set_up, + .pins_set_up = fb_pins_set_up, + .pins_tear_down = fb_pins_tear_down, + .tear_down = fb_tear_down +}; + +const pl111_fb_config *arm_pl111_fb_get_config(void) +{ + return &fb_config; +} diff --git a/bsps/arm/realview-pbx-a9/start/linkcmds.realview_pbx_a9_qemu b/bsps/arm/realview-pbx-a9/start/linkcmds.realview_pbx_a9_qemu new file mode 100644 index 0000000000..e3b5b471b4 --- /dev/null +++ b/bsps/arm/realview-pbx-a9/start/linkcmds.realview_pbx_a9_qemu @@ -0,0 +1,35 @@ +MEMORY { + /* Waste the first 1MiB for NULL pointer protection */ + RAM : ORIGIN = 0x00100000, LENGTH = 255M - 16k + RAM_MMU : ORIGIN = 0x0fffc000, LENGTH = 16k +} + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_VECTOR", RAM); +REGION_ALIAS ("REGION_TEXT", RAM); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_RODATA", RAM); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", RAM); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM); + +bsp_stack_irq_size = DEFINED (bsp_stack_irq_size) ? bsp_stack_irq_size : 4096; +bsp_stack_abt_size = DEFINED (bsp_stack_abt_size) ? bsp_stack_abt_size : 1024; + +bsp_section_rwbarrier_align = DEFINED (bsp_section_rwbarrier_align) ? bsp_section_rwbarrier_align : 1M; + +bsp_vector_table_in_start_section = 1; + +bsp_translation_table_base = ORIGIN (RAM_MMU); +bsp_translation_table_end = ORIGIN (RAM_MMU) + LENGTH (RAM_MMU); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/realview-pbx-a9/start/linkcmds.realview_pbx_a9_qemu_smp b/bsps/arm/realview-pbx-a9/start/linkcmds.realview_pbx_a9_qemu_smp new file mode 100644 index 0000000000..d31c4f08ae --- /dev/null +++ b/bsps/arm/realview-pbx-a9/start/linkcmds.realview_pbx_a9_qemu_smp @@ -0,0 +1,3 @@ +bsp_processor_count = DEFINED (bsp_processor_count) ? bsp_processor_count : 8; + +INCLUDE linkcmds.realview_pbx_a9_qemu diff --git a/bsps/arm/rtl22xx/start/bsp_specs b/bsps/arm/rtl22xx/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/rtl22xx/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/rtl22xx/start/bspreset.c b/bsps/arm/rtl22xx/start/bspreset.c new file mode 100644 index 0000000000..573b4a2aa8 --- /dev/null +++ b/bsps/arm/rtl22xx/start/bspreset.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2007 by Ray Xu <rayx.cn@gmail.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <lpc22xx.h> + +void bsp_reset(void) +{ +#if ON_SKYEYE == 1 + #define SKYEYE_MAGIC_ADDRESS (*(volatile unsigned int *)(0xb0000000)) + + SKYEYE_MAGIC_ADDRESS = 0xff; +#else + rtems_interrupt_level level; + + (void) level; + rtems_interrupt_disable(level); + + #ifdef __thumb__ + int tmp; + __asm__ volatile (" .code 16 \n" \ + "ldr %[tmp], =_start \n" \ + "bx %[tmp] \n" \ + "nop \n" \ + : [tmp]"=&r" (tmp) ); + #else + __asm__ volatile ("b _start"); + #endif + while(1); +#endif +} diff --git a/bsps/arm/rtl22xx/start/bspstart.c b/bsps/arm/rtl22xx/start/bspstart.c new file mode 100644 index 0000000000..fa128d9054 --- /dev/null +++ b/bsps/arm/rtl22xx/start/bspstart.c @@ -0,0 +1,84 @@ +/* + * LPC22XX/LPC21xx Startup code + */ + +/* + * Copyright (c) 2007 by Ray Xu <rayx.cn@gmail.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/irq-generic.h> +#include <lpc22xx.h> + +/* + * bsp_start_default - BSP initialization function + * + * This function is called before RTEMS is initialized and used + * adjust the kernel's configuration. + * + * This function also configures the CPU's memory protection unit. + * + * RESTRICTIONS/LIMITATIONS: + * Since RTEMS is not configured, no RTEMS functions can be called. + */ +static void bsp_start_default( void ) +{ + PINSEL2 =0x0f814914; + BCFG0 = 0x1000ffef; + BCFG1 = 0x1000ffef; + + MEMMAP = 0x2; //debug and excute outside chip + + PLLCON = 1; + #if (Fpclk / (Fcclk / 4)) == 1 + VPBDIV = 0; + #endif + #if (Fpclk / (Fcclk / 4)) == 2 + VPBDIV = 2; + #endif + #if (Fpclk / (Fcclk / 4)) == 4 + VPBDIV = 1; + #endif + + #if (Fcco / Fcclk) == 2 + PLLCFG = ((Fcclk / Fosc) - 1) | (0 << 5); + #endif + #if (Fcco / Fcclk) == 4 + PLLCFG = ((Fcclk / Fosc) - 1) | (1 << 5); + #endif + #if (Fcco / Fcclk) == 8 + PLLCFG = ((Fcclk / Fosc) - 1) | (2 << 5); + #endif + #if (Fcco / Fcclk) == 16 + PLLCFG = ((Fcclk / Fosc) - 1) | (3 << 5); + #endif + PLLFEED = 0xaa; + PLLFEED = 0x55; + while((PLLSTAT & (1 << 10)) == 0); + PLLCON = 3; + PLLFEED = 0xaa; + PLLFEED = 0x55; + + /* memory configure */ + /* it is not needed in my formatter board */ + //MAMCR = 0; + // MAMTIM = 3; + //MAMCR = 2; + + UART0_Ini(); + + /* + * Init rtems interrupt management + */ + bsp_interrupt_initialize(); +} /* bsp_start */ + +/* + * By making this a weak alias for bsp_start_default, a brave soul + * can override the actual bsp_start routine used. + */ +void bsp_start (void) __attribute__ ((weak, alias("bsp_start_default"))); diff --git a/bsps/arm/rtl22xx/start/linkcmds b/bsps/arm/rtl22xx/start/linkcmds new file mode 100644 index 0000000000..d39dcb12bd --- /dev/null +++ b/bsps/arm/rtl22xx/start/linkcmds @@ -0,0 +1,24 @@ +MEMORY { + SDRAM : ORIGIN = 0x81000000, LENGTH = 512k + SRAM : ORIGIN = 0x40000000, LENGTH = 16k +} + +REGION_ALIAS ("REGION_START", SDRAM); +REGION_ALIAS ("REGION_VECTOR", SRAM); +REGION_ALIAS ("REGION_TEXT", SDRAM); +REGION_ALIAS ("REGION_TEXT_LOAD", SDRAM); +REGION_ALIAS ("REGION_RODATA", SDRAM); +REGION_ALIAS ("REGION_RODATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_DATA", SDRAM); +REGION_ALIAS ("REGION_DATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_FAST_TEXT", SDRAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", SDRAM); +REGION_ALIAS ("REGION_FAST_DATA", SDRAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_BSS", SDRAM); +REGION_ALIAS ("REGION_WORK", SDRAM); +REGION_ALIAS ("REGION_STACK", SDRAM); +REGION_ALIAS ("REGION_NOCACHE", SDRAM); +REGION_ALIAS ("REGION_NOCACHE_LOAD", SDRAM); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/shared/start/bsp-start-in-hyp-support.S b/bsps/arm/shared/start/bsp-start-in-hyp-support.S new file mode 100644 index 0000000000..b608c59fa8 --- /dev/null +++ b/bsps/arm/shared/start/bsp-start-in-hyp-support.S @@ -0,0 +1,77 @@ +/** + * @file + * + * @brief Boot and system start code. + */ + + /* + * Copyright (c) 2016 Pavel Pisa <pisa@cmp.felk.cvut.cz> + * + * Czech Technical University in Prague + * Zikova 1903/4 + * 166 36 Praha 6 + * Czech Republic + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/asm.h> +#include <rtems/system.h> +#include <rtems/score/cpu.h> + +#include <bspopts.h> +#include <bsp/irq.h> +#include <bsp/linker-symbols.h> + + .extern bsp_start_hyp_vector_table_begin + .globl bsp_start_arm_drop_hyp_mode + .globl bsp_arm_drop_hyp_mode_only + +.arm + +/* + * The routine is called from startup code and it should + * preserve all registers except r2 and r3. r0 can be used + * as pass though argument in some cases, a1 is used for + * CPU stack offset during startup and r4 to r6 to preserve + * booloader arguments + */ + +bsp_start_arm_drop_hyp_mode: + ldr r2, bsp_start_hyp_vector_table_begin_addr + mcr p15, 4, r2, c12, c0, 0 + + mov r2, #0 + mcr p15, 4, r2, c1, c1, 0 + mcr p15, 4, r2, c1, c1, 2 + mcr p15, 4, r2, c1, c1, 3 +/* + * HSCTLR.TE + * optional start of hypervisor handlers in Thumb mode + * orr r0, #(1 << 30) + */ + mcr p15, 4, r2, c1, c0, 0 /* HSCTLR */ + mrc p15, 4, r2, c1, c1, 1 /* HDCR */ + and r2, #0x1f /* Preserve HPMN */ + mcr p15, 4, r2, c1, c1, 1 /* HDCR */ + +bsp_arm_drop_hyp_mode_only: + /* Prepare SVC mode for eret */ + mrs r2, cpsr + bic r2, r2, #ARM_PSR_M_MASK + orr r2, r2, #ARM_PSR_M_SVC + msr spsr_cxsf, r2 + + adr r2, 1f + .inst 0xe12ef302 /* msr ELR_hyp, r2 */ + mov r2, sp + mov r3, lr + .inst 0xe160006e /* eret */ +1: mov sp, r2 + mov lr, r3 + bx lr + +bsp_start_hyp_vector_table_begin_addr: + .word bsp_start_hyp_vector_table_begin diff --git a/bsps/arm/shared/start/bsp-start-init-registers.S b/bsps/arm/shared/start/bsp-start-init-registers.S new file mode 100644 index 0000000000..2e308ce5de --- /dev/null +++ b/bsps/arm/shared/start/bsp-start-init-registers.S @@ -0,0 +1,105 @@ +/** + * @file bsp-start-init-registers.S + * + * @brief ARM register initialization routines. + */ + +/* + * Copyright (c) 2015 Taller Technologies. All rights reserved. + * + * @author Martin Galvan <martin.galvan@tallertechnologies.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +/* + * These routines initialize the core and VFP registers of ARM CPUs. + * This is necessary for boards that operate in a 1oo1D fashion, + * such as the TMS570. + */ + +#include <rtems/asm.h> + +.section .text +.syntax unified +.cpu cortex-r4 +.arm + +/* Initialization of the ARM core registers. */ +FUNCTION_ENTRY(bsp_start_init_registers_core) + mov r0, #0 + mov r1, #0 + mov r2, #0 + mov r3, #0 + mov r4, #0 + mov r5, #0 + mov r6, #0 + mov r7, #0 + mov r8, #0 + mov r9, #0 + mov r10, #0 + mov r11, #0 + mov r12, #0 + mov r13, #0 + + bx lr +FUNCTION_END(bsp_start_init_registers_core) + +/* Initialization of the FIQ mode banked registers. */ +FUNCTION_ENTRY(bsp_start_init_registers_banked_fiq) + mov r8, #0 + mov r9, #0 + mov r10, #0 + mov r11, #0 + mov r12, #0 + + bx lr +FUNCTION_END(bsp_start_init_registers_banked_fiq) + +#ifdef ARM_MULTILIB_VFP + +/* Initialization of the FPU registers. */ +FUNCTION_ENTRY(bsp_start_init_registers_vfp) + mov r0, #0 + vmov d0, r0, r0 + vmov d1, r0, r0 + vmov d2, r0, r0 + vmov d3, r0, r0 + vmov d4, r0, r0 + vmov d5, r0, r0 + vmov d6, r0, r0 + vmov d7, r0, r0 + vmov d8, r0, r0 + vmov d9, r0, r0 + vmov d10, r0, r0 + vmov d11, r0, r0 + vmov d12, r0, r0 + vmov d13, r0, r0 + vmov d14, r0, r0 + vmov d15, r0, r0 + +#ifdef ARM_MULTILIB_VFP_D32 + vmov d16, r0, r0 + vmov d17, r0, r0 + vmov d18, r0, r0 + vmov d19, r0, r0 + vmov d20, r0, r0 + vmov d21, r0, r0 + vmov d22, r0, r0 + vmov d23, r0, r0 + vmov d24, r0, r0 + vmov d25, r0, r0 + vmov d26, r0, r0 + vmov d27, r0, r0 + vmov d28, r0, r0 + vmov d29, r0, r0 + vmov d30, r0, r0 + vmov d31, r0, r0 +#endif /* ARM_MULTILIB_VFP_D32 */ + + bx lr +FUNCTION_END(bsp_start_init_registers_vfp) + +#endif /* ARM_MULTILIB_VFP */ diff --git a/bsps/arm/shared/start/bsp-start-memcpy.S b/bsps/arm/shared/start/bsp-start-memcpy.S new file mode 100644 index 0000000000..cb97eb47f8 --- /dev/null +++ b/bsps/arm/shared/start/bsp-start-memcpy.S @@ -0,0 +1,147 @@ +/** + * @file + * + * @brief bsp_start_memcpy() implementation. + */ + +/* + * Copyright (c) 2008-2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <rtems/asm.h> +#include <rtems/system.h> +#include <rtems/score/cpu.h> + + .section ".bsp_start_text", "ax" + +#if defined(ARM_MULTILIB_ARCH_V4) + +DEFINE_FUNCTION_ARM(bsp_start_memcpy) + + /* Return if dest == src */ + cmp r0, r1 +#ifdef __thumb__ + bxeq lr +#else + moveq pc, lr +#endif + + /* Return if length is zero */ + mov r3, #0 + cmp r3, r2 +#ifdef __thumb__ + bxeq lr +#else + moveq pc, lr +#endif + + /* Save non-volatile registers */ + push {r4-r8, lr} + + /* Copy worker routine to stack */ + adr ip, worker_begin + ldm ip, {r3-r8} + push {r3-r8} + + /* Execute worker routine */ + mov r3, #0 + mov ip, sp + mov lr, pc +#ifdef __thumb__ + bx ip +#else + mov pc, ip +#endif + + /* Restore stack and non-volatile registers */ + add sp, sp, #24 + pop {r4-r8, lr} + + /* Return */ +#ifdef __thumb__ + bx lr +#else + mov pc, lr +#endif + +worker_begin: + + /* Worker routine */ + ldr ip, [r1, r3] + str ip, [r0, r3] + add r3, r3, #4 + cmp r3, r2 + bcc worker_begin +#ifdef __thumb__ + bx lr +#else + mov pc, lr +#endif + +#elif defined(ARM_MULTILIB_ARCH_V7M) + + .syntax unified + + .align 2 + .globl bsp_start_memcpy + .thumb + .thumb_func + .type bsp_start_memcpy, %function + +bsp_start_memcpy: + + /* Return if dest == src */ + cmp r0, r1 + beq return + + /* Return if length is zero */ + movs r3, #0 + cmp r3, r2 + beq return + + /* Save non-volatile registers */ + push {r4-r7, lr} + + /* Copy worker routine to stack */ + adr r3, worker_begin + ldm r3, {r4-r7} + push {r4-r7} + + /* Execute worker routine */ + add r3, sp, #1 + adds r2, r2, #3 + bic r2, r2, #3 + adds r2, r2, r1 + blx r3 + + /* Restore stack and non-volatile registers */ + add sp, sp, #16 + pop {r4-r7, lr} + +return: + + /* Return */ + bx lr + + .align 2 + +worker_begin: + + /* Worker routine */ + ldr r3, [r1], #4 + cmp r2, r1 + str r3, [r0], #4 + bne worker_begin + bx lr + +#endif /* defined(ARM_MULTILIB_ARCH_V7M) */ diff --git a/bsps/arm/shared/start/linkcmds.armv4 b/bsps/arm/shared/start/linkcmds.armv4 new file mode 100644 index 0000000000..33e419f5be --- /dev/null +++ b/bsps/arm/shared/start/linkcmds.armv4 @@ -0,0 +1,26 @@ +/** + * @file + * + * @ingroup bsp_linker + * + * @brief Linker command file for ARMv4T architecture. + */ + +/* + * Copyright (c) 2010-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +bsp_stack_irq_size = DEFINED (bsp_stack_irq_size) ? bsp_stack_irq_size : 1024; +bsp_stack_irq_size = ALIGN (bsp_stack_irq_size, bsp_stack_align); + +INCLUDE linkcmds.base diff --git a/bsps/arm/shared/start/linkcmds.armv7m b/bsps/arm/shared/start/linkcmds.armv7m new file mode 100644 index 0000000000..f0fb2cde1f --- /dev/null +++ b/bsps/arm/shared/start/linkcmds.armv7m @@ -0,0 +1,26 @@ +/** + * @file + * + * @ingroup bsp_linker + * + * @brief Linker command file for ARMv7 architecture. + */ + +/* + * Copyright (c) 2010 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +bsp_stack_main_size = DEFINED (bsp_stack_main_size) ? bsp_stack_main_size : 4096; +bsp_stack_main_size = ALIGN (bsp_stack_main_size, bsp_stack_align); + +INCLUDE linkcmds.base diff --git a/bsps/arm/shared/start/linkcmds.base b/bsps/arm/shared/start/linkcmds.base new file mode 100644 index 0000000000..c6314547eb --- /dev/null +++ b/bsps/arm/shared/start/linkcmds.base @@ -0,0 +1,487 @@ +/** + * @file + * + * @ingroup bsp_linker + * + * @brief Linker command base file. + */ + +/* + * Copyright (c) 2008, 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 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.org/license/LICENSE. + */ + +OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") + +OUTPUT_ARCH (arm) + +ENTRY (_start) +STARTUP (start.o) + +/* + * Global symbols that may be defined externally + */ + +bsp_vector_table_size = DEFINED (bsp_vector_table_size) ? bsp_vector_table_size : 64; + +bsp_section_xbarrier_align = DEFINED (bsp_section_xbarrier_align) ? bsp_section_xbarrier_align : 1; +bsp_section_robarrier_align = DEFINED (bsp_section_robarrier_align) ? bsp_section_robarrier_align : 1; +bsp_section_rwbarrier_align = DEFINED (bsp_section_rwbarrier_align) ? bsp_section_rwbarrier_align : 1; + +bsp_stack_align = DEFINED (bsp_stack_align) ? bsp_stack_align : 8; + +bsp_stack_abt_size = DEFINED (bsp_stack_abt_size) ? bsp_stack_abt_size : 0; +bsp_stack_abt_size = ALIGN (bsp_stack_abt_size, bsp_stack_align); + +bsp_stack_fiq_size = DEFINED (bsp_stack_fiq_size) ? bsp_stack_fiq_size : 0; +bsp_stack_fiq_size = ALIGN (bsp_stack_fiq_size, bsp_stack_align); + +bsp_stack_irq_size = DEFINED (bsp_stack_irq_size) ? bsp_stack_irq_size : 0; +bsp_stack_irq_size = ALIGN (bsp_stack_irq_size, bsp_stack_align); + +bsp_stack_svc_size = DEFINED (bsp_stack_svc_size) ? bsp_stack_svc_size : 0; +bsp_stack_svc_size = ALIGN (bsp_stack_svc_size, bsp_stack_align); + +bsp_stack_und_size = DEFINED (bsp_stack_und_size) ? bsp_stack_und_size : 0; +bsp_stack_und_size = ALIGN (bsp_stack_und_size, bsp_stack_align); + +bsp_stack_hyp_size = DEFINED (bsp_stack_hyp_size) ? bsp_stack_hyp_size : 0; +bsp_stack_hyp_size = ALIGN (bsp_stack_hyp_size, bsp_stack_align); + +bsp_stack_main_size = DEFINED (bsp_stack_main_size) ? bsp_stack_main_size : 0; +bsp_stack_main_size = ALIGN (bsp_stack_main_size, bsp_stack_align); + +bsp_stack_all_size = bsp_stack_abt_size + bsp_stack_fiq_size + bsp_stack_irq_size + bsp_stack_svc_size + bsp_stack_und_size + bsp_stack_hyp_size + bsp_stack_main_size; + +bsp_processor_count = DEFINED (bsp_processor_count) ? bsp_processor_count : 1; + +MEMORY { + UNEXPECTED_SECTIONS : ORIGIN = 0xffffffff, LENGTH = 0 +} + +SECTIONS { + .start : ALIGN_WITH_INPUT { + bsp_section_start_begin = .; + KEEP (*(.bsp_start_text)) + KEEP (*(.bsp_start_data)) + bsp_section_start_end = .; + } > REGION_START AT > REGION_START + bsp_section_start_size = bsp_section_start_end - bsp_section_start_begin; + + .xbarrier : ALIGN_WITH_INPUT { + . = ALIGN (bsp_section_xbarrier_align); + } > REGION_VECTOR AT > REGION_VECTOR + + .text : ALIGN_WITH_INPUT { + bsp_section_text_begin = .; + *(.text.unlikely .text.*_unlikely) + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .init : ALIGN_WITH_INPUT { + KEEP (*(.init)) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .fini : ALIGN_WITH_INPUT { + KEEP (*(.fini)) + bsp_section_text_end = .; + } > REGION_TEXT AT > REGION_TEXT_LOAD + bsp_section_text_size = bsp_section_text_end - bsp_section_text_begin; + bsp_section_text_load_begin = LOADADDR (.text); + bsp_section_text_load_end = bsp_section_text_load_begin + bsp_section_text_size; + + .robarrier : ALIGN_WITH_INPUT { + . = ALIGN (bsp_section_robarrier_align); + } > REGION_RODATA AT > REGION_RODATA + + .rodata : ALIGN_WITH_INPUT { + bsp_section_rodata_begin = .; + *(.rodata .rodata.* .gnu.linkonce.r.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rodata1 : ALIGN_WITH_INPUT { + *(.rodata1) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .ARM.extab : ALIGN_WITH_INPUT { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .ARM.exidx : ALIGN_WITH_INPUT { + __exidx_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __exidx_end = .; + } > REGION_RODATA AT > REGION_RODATA_LOAD + .eh_frame : ALIGN_WITH_INPUT { + KEEP (*(.eh_frame)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gcc_except_table : ALIGN_WITH_INPUT { + *(.gcc_except_table .gcc_except_table.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .tdata : ALIGN_WITH_INPUT { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > REGION_RODATA AT > REGION_RODATA_LOAD + .tbss : ALIGN_WITH_INPUT { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } > REGION_RODATA AT > REGION_RODATA_LOAD + _TLS_Data_size = _TLS_Data_end - _TLS_Data_begin; + _TLS_Data_begin = _TLS_Data_size != 0 ? _TLS_Data_begin : _TLS_BSS_begin; + _TLS_Data_end = _TLS_Data_size != 0 ? _TLS_Data_end : _TLS_BSS_begin; + _TLS_BSS_size = _TLS_BSS_end - _TLS_BSS_begin; + _TLS_Size = _TLS_BSS_end - _TLS_Data_begin; + _TLS_Alignment = MAX (ALIGNOF (.tdata), ALIGNOF (.tbss)); + .preinit_array : ALIGN_WITH_INPUT { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .init_array : ALIGN_WITH_INPUT { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .fini_array : ALIGN_WITH_INPUT { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .ctors : ALIGN_WITH_INPUT { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dtors : ALIGN_WITH_INPUT { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .data.rel.ro : ALIGN_WITH_INPUT { + *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) + *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .jcr : ALIGN_WITH_INPUT { + KEEP (*(.jcr)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .interp : ALIGN_WITH_INPUT { + *(.interp) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .note.gnu.build-id : ALIGN_WITH_INPUT { + *(.note.gnu.build-id) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .hash : ALIGN_WITH_INPUT { + *(.hash) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.hash : ALIGN_WITH_INPUT { + *(.gnu.hash) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynsym : ALIGN_WITH_INPUT { + *(.dynsym) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynstr : ALIGN_WITH_INPUT { + *(.dynstr) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version : ALIGN_WITH_INPUT { + *(.gnu.version) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version_d : ALIGN_WITH_INPUT { + *(.gnu.version_d) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version_r : ALIGN_WITH_INPUT { + *(.gnu.version_r) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rel.dyn : ALIGN_WITH_INPUT { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + PROVIDE_HIDDEN (__rel_iplt_start = .); + *(.rel.iplt) + PROVIDE_HIDDEN (__rel_iplt_end = .); + PROVIDE_HIDDEN (__rela_iplt_start = .); + PROVIDE_HIDDEN (__rela_iplt_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rela.dyn : ALIGN_WITH_INPUT { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rela.rtemsroset*) + *(.rela.rtemsrwset*) + PROVIDE_HIDDEN (__rel_iplt_start = .); + PROVIDE_HIDDEN (__rel_iplt_end = .); + PROVIDE_HIDDEN (__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN (__rela_iplt_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rel.plt : ALIGN_WITH_INPUT { + *(.rel.plt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rela.plt : ALIGN_WITH_INPUT { + *(.rela.plt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .plt : ALIGN_WITH_INPUT { + *(.plt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .iplt : ALIGN_WITH_INPUT { + *(.iplt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynamic : ALIGN_WITH_INPUT { + *(.dynamic) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .got : ALIGN_WITH_INPUT { + *(.got.plt) *(.igot.plt) *(.got) *(.igot) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rtemsroset : ALIGN_WITH_INPUT { + /* Special FreeBSD linker set sections */ + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = .; + *(set_domain_*); + *(set_pseudo_*); + + KEEP (*(SORT(.rtemsroset.*))) + bsp_section_rodata_end = .; + } > REGION_RODATA AT > REGION_RODATA_LOAD + bsp_section_rodata_size = bsp_section_rodata_end - bsp_section_rodata_begin; + bsp_section_rodata_load_begin = LOADADDR (.rodata); + bsp_section_rodata_load_end = bsp_section_rodata_load_begin + bsp_section_rodata_size; + + .rwbarrier : ALIGN_WITH_INPUT { + . = ALIGN (bsp_section_rwbarrier_align); + } > REGION_DATA AT > REGION_DATA + + .vector : ALIGN_WITH_INPUT { + bsp_section_vector_begin = .; + + . = . + DEFINED (bsp_vector_table_in_start_section) ? 0 : bsp_vector_table_size; + + . = ALIGN (bsp_stack_align); + + bsp_stack_irq_begin = .; + . = . + bsp_stack_irq_size; + bsp_stack_irq_end = .; + + bsp_stack_svc_begin = .; + . = . + bsp_stack_svc_size; + bsp_stack_svc_end = .; + + bsp_stack_fiq_begin = .; + . = . + bsp_stack_fiq_size; + bsp_stack_fiq_end = .; + + bsp_stack_und_begin = .; + . = . + bsp_stack_und_size; + bsp_stack_und_end = .; + + bsp_stack_hyp_begin = .; + . = . + bsp_stack_hyp_size; + bsp_stack_hyp_end = .; + + bsp_stack_abt_begin = .; + . = . + bsp_stack_abt_size; + bsp_stack_abt_end = .; + + bsp_stack_main_begin = .; + . = . + bsp_stack_main_size; + bsp_stack_main_end = .; + + bsp_stack_secondary_processors_begin = .; + . = . + (bsp_processor_count - 1) * bsp_stack_all_size; + bsp_stack_secondary_processors_end = .; + + *(.bsp_vector) + bsp_section_vector_end = .; + } > REGION_VECTOR AT > REGION_VECTOR + bsp_section_vector_size = bsp_section_vector_end - bsp_section_vector_begin; + bsp_vector_table_begin = DEFINED (bsp_vector_table_in_start_section) ? bsp_section_start_begin : bsp_section_vector_begin; + bsp_vector_table_end = bsp_vector_table_begin + bsp_vector_table_size; + + .fast_text : ALIGN_WITH_INPUT { + bsp_section_fast_text_begin = .; + *(.bsp_fast_text) + bsp_section_fast_text_end = .; + } > REGION_FAST_TEXT AT > REGION_FAST_TEXT_LOAD + bsp_section_fast_text_size = bsp_section_fast_text_end - bsp_section_fast_text_begin; + bsp_section_fast_text_load_begin = LOADADDR (.fast_text); + bsp_section_fast_text_load_end = bsp_section_fast_text_load_begin + bsp_section_fast_text_size; + + .fast_data : ALIGN_WITH_INPUT { + bsp_section_fast_data_begin = .; + *(.bsp_fast_data) + bsp_section_fast_data_end = .; + } > REGION_FAST_DATA AT > REGION_FAST_DATA_LOAD + bsp_section_fast_data_size = bsp_section_fast_data_end - bsp_section_fast_data_begin; + bsp_section_fast_data_load_begin = LOADADDR (.fast_data); + bsp_section_fast_data_load_end = bsp_section_fast_data_load_begin + bsp_section_fast_data_size; + + .data : ALIGN_WITH_INPUT { + bsp_section_data_begin = .; + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } > REGION_DATA AT > REGION_DATA_LOAD + .data1 : ALIGN_WITH_INPUT { + *(.data1) + } > REGION_DATA AT > REGION_DATA_LOAD + .rtemsrwset : ALIGN_WITH_INPUT { + KEEP (*(SORT(.rtemsrwset.*))) + bsp_section_data_end = .; + } > REGION_DATA AT > REGION_DATA_LOAD + bsp_section_data_size = bsp_section_data_end - bsp_section_data_begin; + bsp_section_data_load_begin = LOADADDR (.data); + bsp_section_data_load_end = bsp_section_data_load_begin + bsp_section_data_size; + + .bss : ALIGN_WITH_INPUT { + bsp_section_bss_begin = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + bsp_section_bss_end = .; + } > REGION_BSS AT > REGION_BSS + bsp_section_bss_size = bsp_section_bss_end - bsp_section_bss_begin; + + .work : ALIGN_WITH_INPUT { + /* + * The work section will occupy the remaining REGION_WORK region and + * contains the RTEMS work space and heap. + */ + bsp_section_work_begin = .; + . += ORIGIN (REGION_WORK) + LENGTH (REGION_WORK) - ABSOLUTE (.); + bsp_section_work_end = .; + } > REGION_WORK AT > REGION_WORK + bsp_section_work_size = bsp_section_work_end - bsp_section_work_begin; + + .stack : ALIGN_WITH_INPUT { + /* + * The stack section will occupy the remaining REGION_STACK region and may + * contain the task stacks. Depending on the region distribution this + * section may be of zero size. + */ + bsp_section_stack_begin = .; + . += ORIGIN (REGION_STACK) + LENGTH (REGION_STACK) - ABSOLUTE (.); + bsp_section_stack_end = .; + } > REGION_STACK AT > REGION_STACK + bsp_section_stack_size = bsp_section_stack_end - bsp_section_stack_begin; + + .nocache : ALIGN_WITH_INPUT { + bsp_section_nocache_begin = .; + *(SORT_BY_ALIGNMENT (SORT_BY_NAME (.bsp_nocache*))) + bsp_section_nocache_end = .; + } > REGION_NOCACHE AT > REGION_NOCACHE_LOAD + bsp_section_nocache_size = bsp_section_nocache_end - bsp_section_nocache_begin; + bsp_section_nocache_load_begin = LOADADDR (.nocache); + bsp_section_nocache_load_end = bsp_section_nocache_load_begin + bsp_section_nocache_size; + + .nocachenoload (NOLOAD) : ALIGN_WITH_INPUT { + bsp_section_nocachenoload_begin = .; + *(SORT_BY_ALIGNMENT (SORT_BY_NAME (.bsp_noload_nocache*))) + bsp_section_nocacheheap_begin = .; + . += ORIGIN (REGION_NOCACHE) + LENGTH (REGION_NOCACHE) - ABSOLUTE (.); + bsp_section_nocacheheap_end = .; + bsp_section_nocachenoload_end = .; + } > REGION_NOCACHE AT > REGION_NOCACHE + bsp_section_nocacheheap_size = bsp_section_nocacheheap_end - bsp_section_nocacheheap_begin; + bsp_section_nocachenoload_size = bsp_section_nocachenoload_end - bsp_section_nocachenoload_begin; + + /* FIXME */ + RamBase = ORIGIN (REGION_WORK); + RamSize = LENGTH (REGION_WORK); + WorkAreaBase = bsp_section_work_begin; + HeapSize = 0; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF extension */ + .debug_macro 0 : { *(.debug_macro) } + .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) } + .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } + + /* + * This is a RTEMS specific section to catch all unexpected input + * sections. In case you get an error like + * "section `.unexpected_sections' will not fit in region + * `UNEXPECTED_SECTIONS'" + * you have to figure out the offending input section and add it to the + * appropriate output section definition above. + */ + .unexpected_sections : { *(*) } > UNEXPECTED_SECTIONS +} diff --git a/bsps/arm/smdk2410/start/bsp_specs b/bsps/arm/smdk2410/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/smdk2410/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/smdk2410/start/bspidle.c b/bsps/arm/smdk2410/start/bspidle.c new file mode 100644 index 0000000000..0f96f1f09b --- /dev/null +++ b/bsps/arm/smdk2410/start/bspidle.c @@ -0,0 +1,23 @@ +/* + * BSP specific Idle thread + */ + +/* + * Copyright (c) 2000 Canon Research Centre France SA. + * Emmanuel Raguet, mailto:raguet@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> + +void *bsp_idle_thread(uintptr_t ignored) +{ + while(1) { + __asm__ volatile ("MCR p15,0,r0,c7,c0,4 \n"); + } + return NULL; +} + diff --git a/bsps/arm/smdk2410/start/bspreset.c b/bsps/arm/smdk2410/start/bspreset.c new file mode 100644 index 0000000000..365a22f14f --- /dev/null +++ b/bsps/arm/smdk2410/start/bspreset.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002 by Jay Monkman <jtm@smoothsmoothie.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +void bsp_reset(void) +{ +#if ON_SKYEYE == 1 + #define SKYEYE_MAGIC_ADDRESS (*(volatile unsigned int *)(0xb0000000)) + + SKYEYE_MAGIC_ADDRESS = 0xff; +#else + /* TODO: This code was initially copied from the gp32 BSP. That BSP has + * been obsoleted and removed but this code may still benefit from being + * in a shared place. + */ + rtems_interrupt_level level; + + (void) level; + rtems_interrupt_disable(level); + /* disable mmu, invalide i-cache and call swi #4 */ + __asm__ volatile("" + "mrc p15,0,r0,c1,c0,0 \n" + "bic r0,r0,#1 \n" + "mcr p15,0,r0,c1,c0,0 \n" + "nop \n" + "nop \n" + "nop \n" + "nop \n" + "nop \n" + "mov r0,#0 \n" + "MCR p15,0,r0,c7,c5,0 \n" + "nop \n" + "nop \n" + "nop \n" + "nop \n" + "nop \n" + "swi #4 " + : + : + : "r0" + ); + /* we should be back in bios now */ +#endif +} diff --git a/bsps/arm/smdk2410/start/bspstart.c b/bsps/arm/smdk2410/start/bspstart.c new file mode 100644 index 0000000000..c70de1f291 --- /dev/null +++ b/bsps/arm/smdk2410/start/bspstart.c @@ -0,0 +1,83 @@ +/* + * This file contains the ARM BSP startup package. It includes application, + * board, and monitor specific initialization and configuration. The generic CPU + * dependent initialization has been performed before this routine is invoked. + */ + +/* + * Copyright (c) 2000 Canon Research Centre France SA. + * Emmanuel Raguet, mailto:raguet@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/irq-generic.h> +#include <rtems/bspIo.h> +#include <s3c24xx.h> + +/* + * BSP Specific Initialization in C + */ +static void bsp_start_default( void ) +{ + uint32_t cr; + uint32_t pend,last; + uint32_t REFCNT; + int i; + + /* stop RTC */ + #ifdef CPU_S3C2400 + rTICINT = 0x0; + #else + rTICNT = 0x0; + #endif + /* stop watchdog,ADC and timers */ + rWTCON = 0x0; + rTCON = 0x0; + rADCCON = 0x0; + + /* disable interrupts */ + rINTMOD = 0x0; + rINTMSK = BIT_ALLMSK; /* unmasked by drivers */ + + last = 0; + for(i=0; i<4; i++) { + pend = rSRCPND; + if(pend == 0 || pend == last) + break; + rSRCPND = pend; + rINTPND = pend; + last = pend; + } + + /* setup clocks */ + rCLKDIVN = M_CLKDIVN; + rMPLLCON = ((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV); + /* setup rREFRESH + * period = 15.6 us, HCLK=66Mhz, (2048+1-15.6*66) + */ + REFCNT = 2048+1-(15.6*get_HCLK()/1000000); + rREFRESH = ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT); + + /* set prescaler for timers 2,3,4 to 16(15+1) */ + cr = rTCFG0 & 0xFFFF00FF; + rTCFG0 = (cr | (15<<8)); + + /* set prescaler for timers 0,1 to 1(0+1) */ + cr = rTCFG0 & 0xFFFFFF00; + rTCFG0 = (cr | (0<<0)); + + /* + * Init rtems interrupt management + */ + bsp_interrupt_initialize(); +} + +/* + * By making this a weak alias for bsp_start_default, a brave soul + * can override the actual bsp_start routine used. + */ +void bsp_start (void) __attribute__ ((weak, alias("bsp_start_default"))); diff --git a/bsps/arm/smdk2410/start/linkcmds b/bsps/arm/smdk2410/start/linkcmds new file mode 100644 index 0000000000..9cd68886a7 --- /dev/null +++ b/bsps/arm/smdk2410/start/linkcmds @@ -0,0 +1,26 @@ +MEMORY { + SDRAM_MMU : ORIGIN = 0x30000000, LENGTH = 16k + SDRAM : ORIGIN = 0x30004000, LENGTH = 64M - 16k +} + +REGION_ALIAS ("REGION_START", SDRAM); +REGION_ALIAS ("REGION_VECTOR", SDRAM); +REGION_ALIAS ("REGION_TEXT", SDRAM); +REGION_ALIAS ("REGION_TEXT_LOAD", SDRAM); +REGION_ALIAS ("REGION_RODATA", SDRAM); +REGION_ALIAS ("REGION_RODATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_DATA", SDRAM); +REGION_ALIAS ("REGION_DATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_FAST_TEXT", SDRAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", SDRAM); +REGION_ALIAS ("REGION_FAST_DATA", SDRAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", SDRAM); +REGION_ALIAS ("REGION_BSS", SDRAM); +REGION_ALIAS ("REGION_WORK", SDRAM); +REGION_ALIAS ("REGION_STACK", SDRAM); +REGION_ALIAS ("REGION_NOCACHE", SDRAM); +REGION_ALIAS ("REGION_NOCACHE_LOAD", SDRAM); + +_ttbl_base = ORIGIN (SDRAM_MMU); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/smdk2410/start/memmap.c b/bsps/arm/smdk2410/start/memmap.c new file mode 100644 index 0000000000..21ba35b21b --- /dev/null +++ b/bsps/arm/smdk2410/start/memmap.c @@ -0,0 +1,27 @@ +/* + * SMDK2410 Memory Map + */ + +/* + * Copyright (c) 2004 by Cogent Computer Systems + * Written by Jay Monkman <jtm@lopingdog.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ +#include <rtems.h> +#include <libcpu/mmu.h> + +/* Remember, the ARM920 has 64 TLBs. If you have more 1MB sections than + * that, you'll have TLB lookups, which could hurt performance. + */ +mmu_sect_map_t mem_map[] = { +/* <phys addr> <virt addr> <size> <flags> */ + {0x30000000, 0x00000000, 1, MMU_CACHE_NONE}, /* SDRAM for vectors */ + {0x30000000, 0x30000000, 32, MMU_CACHE_WTHROUGH}, /* SDRAM W cache */ + {0x32000000, 0x32000000, 32, MMU_CACHE_NONE}, /* SDRAM W/O cache */ + {0x48000000, 0x48000000, 256, MMU_CACHE_NONE}, /* Internals Regs - */ + {0x50000000, 0x50000000, 256, MMU_CACHE_NONE}, /* Internal Regs - */ + {0x00000000, 0x00000000, 0, 0} /* The end */ +}; diff --git a/bsps/arm/stm32f4/start/bsp_specs b/bsps/arm/stm32f4/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/stm32f4/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/stm32f4/start/bspreset.c b/bsps/arm/stm32f4/start/bspreset.c new file mode 100644 index 0000000000..ff46d4f86b --- /dev/null +++ b/bsps/arm/stm32f4/start/bspreset.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012 Sebastian Huber. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <rtems.h> + +#include <bsp/bootcard.h> + +void bsp_reset(void) +{ + rtems_interrupt_level level; + + (void) level; + rtems_interrupt_disable(level); + + while (1); +} diff --git a/bsps/arm/stm32f4/start/bspstart.c b/bsps/arm/stm32f4/start/bspstart.c new file mode 100644 index 0000000000..8d4bf6b82b --- /dev/null +++ b/bsps/arm/stm32f4/start/bspstart.c @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2012 Sebastian Huber. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/io.h> +#include <bsp/irq.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> +#include <assert.h> +#include <bsp/stm32f4.h> + +#ifdef STM32F4_FAMILY_F4XXXX + +#include <bsp/stm32f4xxxx_rcc.h> +#include <bsp/stm32f4xxxx_flash.h> + +static rtems_status_code set_system_clk( + uint32_t sys_clk, + uint32_t hse_clk, + uint32_t hse_flag +); + +static void init_main_osc( void ) +{ + volatile stm32f4_rcc *rcc = STM32F4_RCC; + rtems_status_code status; + + /* Revert to reset values */ + rcc->cr |= RCC_CR_HSION; /* turn on HSI */ + + while ( !( rcc->cr & RCC_CR_HSIRDY ) ) ; + + rcc->cfgr &= 0x00000300; /* all prescalers to 0, clock source to HSI */ + + rcc->cr &= 0xF0F0FFFD; /* turn off all clocks and PLL except HSI */ + + status = set_system_clk( STM32F4_SYSCLK / 1000000L, + STM32F4_HSE_OSCILLATOR / 1000000L, + 1 ); + + assert( rtems_is_status_successful( status ) ); +} + +/** + * @brief Sets up clocks configuration. + * + * Set up clocks configuration to achieve desired system clock + * as close as possible with simple math. + * + * Limitations: + * It is assumed that 1MHz resolution is enough. + * Best fits for the clocks are achieved with multiplies of 42MHz. + * Even though APB1, APB2 and AHB are calculated user is still required + * to provide correct values for the bsp configuration for the: + * STM32F4_PCLK1 + * STM32F4_PCLK2 + * STM32F4_HCLK + * as those are used for the peripheral clocking calculations. + * + * @param sys_clk Desired system clock in MHz. + * @param hse_clk External clock speed in MHz. + * @param hse_flag Flag determining which clock source to use, 1 for HSE, + * 0 for HSI. + * + * @retval RTEMS_SUCCESSFUL Configuration has been succesfully aplied for the + * requested clock speed. + * @retval RTEMS_TIMEOUT HSE clock didn't start or PLL didn't lock. + * @retval RTEMS_INVALID_NUMBER Requested clock speed is out of range. + */ +static rtems_status_code set_system_clk( + uint32_t sys_clk, + uint32_t hse_clk, + uint32_t hse_flag +) +{ + volatile stm32f4_rcc *rcc = STM32F4_RCC; + volatile stm32f4_flash *flash = STM32F4_FLASH; + long timeout = 0; + + int src_clk = 0; + + uint32_t pll_m = 0; + uint32_t pll_n = 0; + uint32_t pll_p = 0; + uint32_t pll_q = 0; + + uint32_t ahbpre = 0; + uint32_t apbpre1 = 0; + uint32_t apbpre2 = 0; + + if ( sys_clk == 16 && hse_clk != 16 ) { + /* Revert to reset values */ + rcc->cr |= RCC_CR_HSION; /* turn on HSI */ + + while ( !( rcc->cr & RCC_CR_HSIRDY ) ) ; + + /* all prescalers to 0, clock source to HSI */ + rcc->cfgr &= 0x00000300 | RCC_CFGR_SW_HSI; + rcc->cr &= 0xF0F0FFFD; /* turn off all clocks and PLL except HSI */ + flash->acr = 0; /* slow clock so no cache, no prefetch, no latency */ + + return RTEMS_SUCCESSFUL; + } + + if ( sys_clk == hse_clk ) { + /* Revert to reset values */ + rcc->cr |= RCC_CR_HSEON; /* turn on HSE */ + timeout = 400; + + while ( !( rcc->cr & RCC_CR_HSERDY ) && --timeout ) ; + + assert( timeout != 0 ); + + if ( timeout == 0 ) { + return RTEMS_TIMEOUT; + } + + /* all prescalers to 0, clock source to HSE */ + rcc->cfgr &= 0x00000300; + rcc->cfgr |= RCC_CFGR_SW_HSE; + /* turn off all clocks and PLL except HSE */ + rcc->cr &= 0xF0F0FFFC | RCC_CR_HSEON; + flash->acr = 0; /* slow clock so no cache, no prefetch, no latency */ + + return RTEMS_SUCCESSFUL; + } + + /* + * Lets use 1MHz input for PLL so we get higher VCO output + * this way we get better value for the PLL_Q divader for the USB + * + * Though you might want to use 2MHz as per CPU specification: + * + * Caution:The software has to set these bits correctly to ensure + * that the VCO input frequency ranges from 1 to 2 MHz. + * It is recommended to select a frequency of 2 MHz to limit PLL jitter. + */ + + if ( sys_clk > 180 ) { + return RTEMS_INVALID_NUMBER; + } else if ( sys_clk >= 96 ) { + pll_n = sys_clk << 1; + pll_p = RCC_PLLCFGR_PLLP_BY_2; + } else if ( sys_clk >= 48 ) { + pll_n = sys_clk << 2; + pll_p = RCC_PLLCFGR_PLLP_BY_4; + } else if ( sys_clk >= 24 ) { + pll_n = sys_clk << 3; + pll_p = RCC_PLLCFGR_PLLP_BY_8; + } else { + return RTEMS_INVALID_NUMBER; + } + + if ( hse_clk == 0 || hse_flag == 0 ) { + src_clk = 16; + hse_flag = 0; + } else { + src_clk = hse_clk; + } + + pll_m = src_clk; /* divide by the oscilator speed in MHz */ + + /* pll_q is a prescaler from VCO for the USB OTG FS, SDIO and RNG, + * best if results in the 48MHz for the USB + */ + pll_q = ( (long) ( src_clk * pll_n ) ) / pll_m / 48; + + if ( pll_q < 2 ) { + pll_q = 2; + } + + /* APB1 prescaler, APB1 clock must be < 42MHz */ + apbpre1 = ( sys_clk * 100 ) / 42; + + if ( apbpre1 <= 100 ) { + apbpre1 = RCC_CFGR_PPRE1_BY_1; + } else if ( apbpre1 <= 200 ) { + apbpre1 = RCC_CFGR_PPRE1_BY_2; + } else if ( apbpre1 <= 400 ) { + apbpre1 = RCC_CFGR_PPRE1_BY_4; + } else if ( apbpre1 <= 800 ) { + apbpre1 = RCC_CFGR_PPRE1_BY_8; + } else if ( apbpre1 ) { + apbpre1 = RCC_CFGR_PPRE1_BY_16; + } + + /* APB2 prescaler, APB2 clock must be < 84MHz */ + apbpre2 = ( sys_clk * 100 ) / 84; + + if ( apbpre2 <= 100 ) { + apbpre2 = RCC_CFGR_PPRE2_BY_1; + } else if ( apbpre2 <= 200 ) { + apbpre2 = RCC_CFGR_PPRE2_BY_2; + } else if ( apbpre2 <= 400 ) { + apbpre2 = RCC_CFGR_PPRE2_BY_4; + } else if ( apbpre2 <= 800 ) { + apbpre2 = RCC_CFGR_PPRE2_BY_8; + } else { + apbpre2 = RCC_CFGR_PPRE2_BY_16; + } + + rcc->cr |= RCC_CR_HSION; /* turn on HSI */ + + while ( ( !( rcc->cr & RCC_CR_HSIRDY ) ) ) ; + + /* all prescalers to 0, clock source to HSI */ + rcc->cfgr &= 0x00000300; + rcc->cfgr |= RCC_CFGR_SW_HSI; + + while ( ( ( rcc->cfgr & RCC_CFGR_SWS_MSK ) != RCC_CFGR_SWS_HSI ) ) ; + + /* turn off PLL */ + rcc->cr &= ~( RCC_CR_PLLON | RCC_CR_PLLRDY ); + + /* turn on HSE */ + if ( hse_flag ) { + rcc->cr |= RCC_CR_HSEON; + timeout = 400; + + while ( ( !( rcc->cr & RCC_CR_HSERDY ) ) && timeout-- ) ; + + assert( timeout != 0 ); + + if ( timeout == 0 ) { + return RTEMS_TIMEOUT; + } + } + + rcc->pllcfgr &= 0xF0BC8000; /* clear PLL prescalers */ + + /* set pll parameters */ + rcc->pllcfgr |= RCC_PLLCFGR_PLLM( pll_m ) | /* input divider */ + RCC_PLLCFGR_PLLN( pll_n ) | /* multiplier */ + pll_p | /* output divider from table */ + /* HSE v HSI */ + ( hse_flag ? RCC_PLLCFGR_PLLSRC_HSE : RCC_PLLCFGR_PLLSRC_HSI ) + | + RCC_PLLCFGR_PLLQ( pll_q ); /* PLLQ divider */ + + /* set prescalers for the internal busses */ + rcc->cfgr |= apbpre1 | + apbpre2 | + ahbpre; + + /* + * Set flash parameters, hard coded for now for fast system clocks. + * TODO implement some math to use flash on as low latancy as possible + */ + flash->acr = STM32F4_FLASH_ACR_LATENCY( 5 ) | /* latency */ + STM32F4_FLASH_ACR_ICEN | /* instruction cache */ + STM32F4_FLASH_ACR_DCEN | /* data cache */ + STM32F4_FLASH_ACR_PRFTEN; + + /* turn on PLL */ + rcc->cr |= RCC_CR_PLLON; + timeout = 40000; + + while ( ( !( rcc->cr & RCC_CR_PLLRDY ) ) && --timeout ) ; + + assert( timeout != 0 ); + + if ( timeout == 0 ) { + return RTEMS_TIMEOUT; + } + + /* clock source to PLL */ + rcc->cfgr = ( rcc->cfgr & ~RCC_CFGR_SW_MSK ) | RCC_CFGR_SW_PLL; + + while ( ( ( rcc->cfgr & RCC_CFGR_SWS_MSK ) != RCC_CFGR_SWS_PLL ) ) ; + + return RTEMS_SUCCESSFUL; +} + +#endif /* STM32F4_FAMILY_F4XXXX */ + +#ifdef STM32F4_FAMILY_F10XXX + +static void init_main_osc( void ) +{ + +} + +#endif /* STM32F4_FAMILY_F10XXX */ + +void bsp_start( void ) +{ + init_main_osc(); + + stm32f4_gpio_set_config_array( &stm32f4_start_config_gpio[ 0 ] ); + + bsp_interrupt_initialize(); +} diff --git a/bsps/arm/stm32f4/start/bspstarthook.c b/bsps/arm/stm32f4/start/bspstarthook.c new file mode 100644 index 0000000000..8e9295b853 --- /dev/null +++ b/bsps/arm/stm32f4/start/bspstarthook.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2012 Sebastian Huber. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/start.h> + +void BSP_START_TEXT_SECTION bsp_start_hook_0(void) +{ + /* Do nothing */ +} + +void BSP_START_TEXT_SECTION bsp_start_hook_1(void) +{ + bsp_start_copy_sections(); + bsp_start_clear_bss(); + + /* At this point we can use objects outside the .start section */ +} diff --git a/bsps/arm/stm32f4/start/io.c b/bsps/arm/stm32f4/start/io.c new file mode 100644 index 0000000000..dcbdb70ff5 --- /dev/null +++ b/bsps/arm/stm32f4/start/io.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2012 Sebastian Huber. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <bsp/io.h> +#include <bsp/rcc.h> +#include <bsp/stm32f4.h> + +#include <rtems.h> + +RTEMS_STATIC_ASSERT(sizeof(stm32f4_gpio_config) == 4, size_of_config); + +void stm32f4_gpio_set_clock(int pin, bool set) +{ + int port = STM32F4_GPIO_PORT_OF_PIN(pin); + stm32f4_rcc_index index = STM32F4_RCC_GPIOA + port; + + stm32f4_rcc_set_clock(index, set); +} + +static void clear_and_set( + volatile uint32_t *reg, + unsigned index, + unsigned width, + uint32_t set +) +{ + uint32_t mask = (1U << width) - 1U; + unsigned shift = width * index; + uint32_t val = *reg; + + val &= ~(mask << shift); + val |= set << shift; + + *reg = val; +} + +#ifdef STM32F4_FAMILY_F10XXX +#define STM32F4_AFIO_REMAP_ENTRY(mod, afio_reg_v, start_v, width_v, value_v) \ + [mod] = { \ + .afio_reg = afio_reg_v, \ + .start = start_v, \ + .width = width_v, \ + .value = value_v, \ + .reserved = 0 \ + } + +typedef struct { + uint16_t afio_reg : 3; + uint16_t start : 5; + uint16_t width : 2; + uint16_t value : 3; + uint16_t reserved : 3; +} stm32f4_afio_remap_entry; + +static const stm32f4_afio_remap_entry stm32f4_afio_remap_table [] = { + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_DONT_CHANGE, 0, 0, 0, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_SPI1_0, 1, 0, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_SPI1_1, 1, 0, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_I2C1_0, 1, 1, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_I2C1_1, 1, 1, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_USART1_0, 1, 2, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_USART1_1, 1, 2, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_USART2_0, 1, 3, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_USART2_1, 1, 3, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_USART3_0, 1, 4, 2, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_USART3_1, 1, 4, 2, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_USART3_3, 1, 4, 2, 3), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM1_0, 1, 6, 2, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM1_1, 1, 6, 2, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM1_3, 1, 6, 2, 3), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM2_0, 1, 8, 2, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM2_1, 1, 8, 2, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM2_2, 1, 8, 2, 2), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM2_3, 1, 8, 2, 3), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM3_0, 1, 10, 2, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM3_2, 1, 10, 2, 2), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM3_3, 1, 10, 2, 3), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM4_0, 1, 12, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM4_1, 1, 12, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_CAN1_0, 1, 13, 2, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_CAN1_2, 1, 13, 2, 2), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_CAN1_3, 1, 13, 2, 3), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_PD01_0, 1, 15, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_PD01_1, 1, 15, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM5CH4_0, 1, 16, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM5CH4_1, 1, 16, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ADC1_ETRGINJ_0, 1, 17, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ADC1_ETRGINJ_1, 1, 17, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ADC1_ETRGREG_0, 1, 18, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ADC1_ETRGREG_1, 1, 18, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ADC2_ETRGINJ_0, 1, 19, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ADC2_ETRGINJ_1, 1, 19, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ADC2_ETRGREG_0, 1, 20, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ADC2_ETRGREG_1, 1, 20, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ETH_0, 1, 21, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ETH_1, 1, 21, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_CAN2_0, 1, 22, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_CAN2_1, 1, 22, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_MII_RMII_0, 1, 23, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_MII_RMII_1, 1, 23, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_SWJ_0, 1, 24, 3, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_SWJ_1, 1, 24, 3, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_SWJ_2, 1, 24, 3, 2), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_SWJ_4, 1, 24, 3, 4), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_SPI3_0, 1, 28, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_SPI3_1, 1, 28, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM2ITR1_0, 1, 29, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM2ITR1_1, 1, 29, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_PTP_PPS_0, 1, 30, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_PTP_PPS_1, 1, 30, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM15_0, 6, 0, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM15_1, 6, 0, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM16_0, 6, 1, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM16_1, 6, 1, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM17_0, 6, 2, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM17_1, 6, 2, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_CEC_0, 6, 3, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_CEC_1, 6, 3, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM1_DMA_0, 6, 4, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM1_DMA_1, 6, 4, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM9_0, 6, 5, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM9_1, 6, 5, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM10_0, 6, 6, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM10_1, 6, 6, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM11_0, 6, 7, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM11_1, 6, 7, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM13_0, 6, 8, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM13_1, 6, 8, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM14_0, 6, 9, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM14_1, 6, 9, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_FSMC_0, 6, 10, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_FSMC_1, 6, 10, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM67_DAC_DMA_0, 6, 11, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM67_DAC_DMA_1, 6, 11, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM12_0, 6, 12, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM12_1, 6, 12, 1, 1), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_MISC_0, 6, 13, 1, 0), + STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_MISC_1, 6, 13, 1, 1), +}; + +static void set_remap_config(stm32f4_gpio_remap remap) +{ + if(remap != STM32F4_GPIO_REMAP_DONT_CHANGE) + { + stm32f4_afio_remap_entry entry = stm32f4_afio_remap_table[remap]; + volatile stm32f4_afio *afio = STM32F4_AFIO; + volatile uint32_t *reg = ((uint32_t*) afio) + entry.afio_reg; + uint32_t mask = (1 << entry.width) - 1; + uint32_t value = *reg; + + value &= mask << entry.start; + value |= entry.value << entry.start; + + *reg = value; + } +} + +#endif /* STM32F4_FAMILY_F10XXX */ + +static void set_config(unsigned pin, const stm32f4_gpio_config *config) +{ + unsigned port = STM32F4_GPIO_PORT_OF_PIN(pin); + volatile stm32f4_gpio *gpio = STM32F4_GPIO(port); + unsigned index = STM32F4_GPIO_INDEX_OF_PIN(pin); + rtems_interrupt_level level; + int set_or_clear_offset = config->fields.output ? 0 : 16; +#ifdef STM32F4_FAMILY_F4XXXX + unsigned af_reg = index >> 3; + unsigned af_index = index & 0x7; + + rtems_interrupt_disable(level); + gpio->bsrr = 1U << (index + set_or_clear_offset); + clear_and_set(&gpio->pupdr, index, 2, config->fields.pupd); + clear_and_set(&gpio->otyper, index, 1, config->fields.otype); + clear_and_set(&gpio->ospeedr, index, 2, config->fields.ospeed); + clear_and_set(&gpio->afr [af_reg], af_index, 4, config->fields.af); + clear_and_set(&gpio->moder, index, 2, config->fields.mode); + rtems_interrupt_enable(level); + +#endif /* STM32F4_FAMILY_F4XXXX */ +#ifdef STM32F4_FAMILY_F10XXX + unsigned cr_reg = index >> 3; + unsigned cr_index = index & 0x7; + + rtems_interrupt_disable(level); + gpio->bsrr = 1U << (index + set_or_clear_offset); + clear_and_set(&gpio->cr[cr_reg], cr_index, 4, + (config->fields.cnf << 2) | config->fields.mode); + set_remap_config(config->fields.remap); + rtems_interrupt_enable(level); + +#endif /* STM32F4_FAMILY_F10XXX */ +} + +void stm32f4_gpio_set_config(const stm32f4_gpio_config *config) +{ + int current = config->fields.pin_first; + int last = config->fields.pin_last; + +#ifdef STM32F4_FAMILY_F10XXX + stm32f4_rcc_set_clock(STM32F4_RCC_AFIO, true); +#endif /* STM32F4_FAMILY_F10XXX */ + + while (current <= last) { + stm32f4_gpio_set_clock(current, true); + set_config(current, config); + ++current; + } +} + +void stm32f4_gpio_set_config_array(const stm32f4_gpio_config *configs) +{ + stm32f4_gpio_config terminal = STM32F4_GPIO_CONFIG_TERMINAL; + + while (configs->value != terminal.value) { + stm32f4_gpio_set_config(configs); + ++configs; + } +} + +void stm32f4_gpio_set_output(int pin, bool set) +{ + int port = STM32F4_GPIO_PORT_OF_PIN(pin); + volatile stm32f4_gpio *gpio = STM32F4_GPIO(port); + int index = STM32F4_GPIO_INDEX_OF_PIN(pin); + int set_or_clear_offset = set ? 0 : 16; + + gpio->bsrr = 1U << (index + set_or_clear_offset); +} + +bool stm32f4_gpio_get_input(int pin) +{ + int port = STM32F4_GPIO_PORT_OF_PIN(pin); + volatile stm32f4_gpio *gpio = STM32F4_GPIO(port); + int index = STM32F4_GPIO_INDEX_OF_PIN(pin); + + return (gpio->idr & (1U << index)) != 0; +} diff --git a/bsps/arm/stm32f4/start/linkcmds.stm32f105rc b/bsps/arm/stm32f4/start/linkcmds.stm32f105rc new file mode 100644 index 0000000000..d3ea200f2b --- /dev/null +++ b/bsps/arm/stm32f4/start/linkcmds.stm32f105rc @@ -0,0 +1,24 @@ +MEMORY { + RAM_INT : ORIGIN = 0x20000000, LENGTH = 64k + ROM_INT : ORIGIN = 0x00000000, LENGTH = 256k +} + +REGION_ALIAS ("REGION_START", ROM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_INT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_INT); +REGION_ALIAS ("REGION_WORK", RAM_INT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/stm32f4/start/linkcmds.stm32f4 b/bsps/arm/stm32f4/start/linkcmds.stm32f4 new file mode 100644 index 0000000000..1d16cfdde9 --- /dev/null +++ b/bsps/arm/stm32f4/start/linkcmds.stm32f4 @@ -0,0 +1,24 @@ +MEMORY { + RAM_INT : ORIGIN = 0x20000000, LENGTH = 128k + ROM_INT : ORIGIN = 0x00000000, LENGTH = 1M +} + +REGION_ALIAS ("REGION_START", ROM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_INT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_INT); +REGION_ALIAS ("REGION_WORK", RAM_INT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +INCLUDE linkcmds.armv7m diff --git a/bsps/arm/stm32f4/start/rcc.c b/bsps/arm/stm32f4/start/rcc.c new file mode 100644 index 0000000000..ed0b2f1610 --- /dev/null +++ b/bsps/arm/stm32f4/start/rcc.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2012 Sebastian Huber. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <bsp/rcc.h> +#include <bsp/stm32f4.h> + +#include <rtems.h> + +static void rcc_set( + stm32f4_rcc_index index, + bool set, + volatile uint32_t *regs +) +{ + int reg = index >> 5; + uint32_t one = 1; + uint32_t bit = one << (index & 0x1f); + rtems_interrupt_level level; + uint32_t val; + + rtems_interrupt_disable(level); + val = regs [reg]; + if (set) { + val |= bit; + } else { + val &= ~bit; + } + regs [reg] = val; + rtems_interrupt_enable(level); +} + +void stm32f4_rcc_reset(stm32f4_rcc_index index) +{ + stm32f4_rcc_set_reset(index, true); + stm32f4_rcc_set_reset(index, false); +} + +void stm32f4_rcc_set_reset(stm32f4_rcc_index index, bool set) +{ + volatile stm32f4_rcc *rcc = STM32F4_RCC; + +#ifdef STM32F4_FAMILY_F4XXXX + rcc_set(index, set, &rcc->ahbrstr [0]); +#endif/* STM32F4_FAMILY_F4XXXX */ +#ifdef STM32F4_FAMILY_F10XXX + /* The first register is missing for the reset-block */ + rcc_set(index, set, &rcc->cir); +#endif /* STM32F4_FAMILY_F10XXX */ +} + +void stm32f4_rcc_set_clock(stm32f4_rcc_index index, bool set) +{ + volatile stm32f4_rcc *rcc = STM32F4_RCC; + + rcc_set(index, set, &rcc->ahbenr [0]); +} + +#ifdef STM32F4_FAMILY_F4XXXX +void stm32f4_rcc_set_low_power_clock(stm32f4_rcc_index index, bool set) +{ + volatile stm32f4_rcc *rcc = STM32F4_RCC; + + rcc_set(index, set, &rcc->ahblpenr [0]); +} +#endif /* STM32F4_FAMILY_F4XXXX */ diff --git a/bsps/arm/stm32f4/start/start-config-io.c b/bsps/arm/stm32f4/start/start-config-io.c new file mode 100644 index 0000000000..712fd0705b --- /dev/null +++ b/bsps/arm/stm32f4/start/start-config-io.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2012 Sebastian Huber. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 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.org/license/LICENSE. + */ + +#include <bsp/io.h> +#include <bsp.h> + +const stm32f4_gpio_config stm32f4_start_config_gpio [] = { +#ifdef STM32F4_FAMILY_F4XXXX + #ifdef STM32F4_ENABLE_USART_1 + STM32F4_PIN_USART1_TX_PA9, + STM32F4_PIN_USART1_RX_PA10, + #endif + #ifdef STM32F4_ENABLE_USART_2 + STM32F4_PIN_USART2_TX_PA2, + STM32F4_PIN_USART2_RX_PA3, + #endif + #ifdef STM32F4_ENABLE_USART_3 + STM32F4_PIN_USART3_TX_PD8, + STM32F4_PIN_USART3_RX_PD9, + #endif + #ifdef STM32F4_ENABLE_UART_4 + STM32F4_PIN_UART4_TX_PA0, + STM32F4_PIN_UART4_RX_PA1, + #endif + #ifdef STM32F4_ENABLE_UART_5 + STM32F4_PIN_UART5_TX_PC12, + STM32F4_PIN_UART5_RX_PD2, + #endif + #ifdef STM32F4_ENABLE_USART_6 + STM32F4_PIN_USART6_TX_PC6, + STM32F4_PIN_USART6_RX_PC7, + #endif + #ifdef STM32F4_ENABLE_I2C1 + #error Not implemented. + #endif + #ifdef STM32F4_ENABLE_I2C2 + #error Not implemented. + #endif +#endif /* STM32F4_FAMILY_F4XXXX */ +#ifdef STM32F4_FAMILY_F10XXX + #ifdef STM32F4_ENABLE_USART_1 + STM32F4_PIN_USART1_TX_MAP_0, + STM32F4_PIN_USART1_RX_MAP_0, + #endif + #ifdef STM32F4_ENABLE_USART_2 + STM32F4_PIN_USART2_TX_MAP_0, + STM32F4_PIN_USART2_RX_MAP_0, + #endif + #ifdef STM32F4_ENABLE_USART_3 + STM32F4_PIN_USART3_TX_MAP_0, + STM32F4_PIN_USART3_RX_MAP_0, + #endif + #ifdef STM32F4_ENABLE_UART_4 + STM32F4_PIN_UART4_TX, + STM32F4_PIN_UART4_RX, + #endif + #ifdef STM32F4_ENABLE_UART_5 + STM32F4_PIN_UART5_TX, + STM32F4_PIN_UART5_RX, + #endif + #ifdef STM32F4_ENABLE_USART_6 + #error STM32F10XXX has no USART 6 + #endif + #ifdef STM32F4_ENABLE_I2C1 + STM32F4_PIN_I2C1_SCL_MAP0, + STM32F4_PIN_I2C1_SDA_MAP0, + #endif + #ifdef STM32F4_ENABLE_I2C2 + STM32F4_PIN_I2C2_SCL, + STM32F4_PIN_I2C2_SDA, + #endif +#endif /* STM32F4_FAMILY_F10XXX */ + STM32F4_GPIO_CONFIG_TERMINAL +}; diff --git a/bsps/arm/tms570/start/bsp_specs b/bsps/arm/tms570/start/bsp_specs new file mode 100644 index 0000000000..9c4b57c578 --- /dev/null +++ b/bsps/arm/tms570/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s } diff --git a/bsps/arm/tms570/start/bspreset.c b/bsps/arm/tms570/start/bspreset.c new file mode 100644 index 0000000000..f6bdee27e1 --- /dev/null +++ b/bsps/arm/tms570/start/bspreset.c @@ -0,0 +1,47 @@ +/** + * @file bspreset.c + * + * @ingroup tms570 + * + * @brief Reset code. + */ + +/* + * Copyright (c) 2015 Taller Technologies. + * + * @author Martin Galvan <martin.galvan@tallertechnologies.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/tms570.h> +#include <bsp/start.h> + +static void handle_esm_errors(uint32_t esm_irq_channel) +{ + /* ESMR3 errors don't generate interrupts. */ + if (esm_irq_channel < 0x20u) { + TMS570_ESM.SR[0] = 1 << esm_irq_channel; + } else if (esm_irq_channel < 0x40u) { + TMS570_ESM.SR[1] = 1 << (esm_irq_channel - 32u); + } else if (esm_irq_channel < 0x60u) { + TMS570_ESM.SR4 = 1 << (esm_irq_channel - 64u); + } +} + +void bsp_reset(void) +{ + uint32_t esm_irq_channel = TMS570_ESM.IOFFHR - 1; + + if (esm_irq_channel) { + handle_esm_errors(esm_irq_channel); + } + + /* Reset the board */ + /* write of value other than 1 cause system reset */ + TMS570_SYS1.SYSECR = TMS570_SYS1_SYSECR_RESET(2); +} diff --git a/bsps/arm/tms570/start/bspstart.c b/bsps/arm/tms570/start/bspstart.c new file mode 100644 index 0000000000..025bb741d2 --- /dev/null +++ b/bsps/arm/tms570/start/bspstart.c @@ -0,0 +1,75 @@ +/** + * @file bspstart.c + * + * @ingroup tms570 + * + * @brief Startup code. + */ + +/* + * Copyright (c) 2014 Premysl Houdek <kom541000@gmail.com> + * + * Google Summer of Code 2014 at + * Czech Technical University in Prague + * Zikova 1903/4 + * 166 36 Praha 6 + * Czech Republic + * + * Based on LPC24xx and LPC1768 BSP + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/tms570-pom.h> +#include <bsp/irq-generic.h> +#include <bsp/start.h> +#include <bsp/bootcard.h> +#include <bsp/linker-symbols.h> +#include <rtems/endian.h> + +void bsp_start( void ) +{ + void *need_remap_ptr; + unsigned int need_remap_int; + + tms570_initialize_and_clear(); + + /* + * If RTEMS image does not start at address 0x00000000 + * then first level exception table at memory begin has + * to be replaced to point to RTEMS handlers addresses. + * + * There is no VBAR or other option because Cortex-R + * does provides only fixed address 0x00000000 for exceptions + * (0xFFFF0000-0xFFFF001C alternative SCTLR.V = 1 cannot + * be used because target area corersponds to PMM peripheral + * registers on TMS570). + * + * Alternative is to use jumps over SRAM based trampolines + * but that is not compatible with + * Check TCRAM1 ECC error detection logic + * which intentionally introduces data abort during startup + * to check SRAM and if exception processing goes through + * SRAM then it leads to CPU error halt. + * + * So use of POM to replace jumps to vectors target + * addresses seems to be the best option for now. + * + * The passing of linker symbol (represented as start address + * of global array) through dummy asm block ensures that C compiler + * cannot optimize comparison out on premise that reference cannot + * evaluate to NULL definition in standard. + */ + need_remap_ptr = bsp_start_vector_table_begin; + asm volatile ("\n": "=r" (need_remap_int): "0" (need_remap_ptr)); + if ( need_remap_int != 0 ) { + tms570_pom_remap(); + } + + /* Interrupts */ + bsp_interrupt_initialize(); + +} diff --git a/bsps/arm/tms570/start/bspstarthooks.c b/bsps/arm/tms570/start/bspstarthooks.c new file mode 100644 index 0000000000..a9e189b6b8 --- /dev/null +++ b/bsps/arm/tms570/start/bspstarthooks.c @@ -0,0 +1,41 @@ +/** + * @file bspstarthooks.c + * + * @ingroup tms570 + * + * @brief First configurations and initializations to the correct + * functionality of the board. + */ + +/* + * Copyright (c) 2014 Premysl Houdek <kom541000@gmail.com> + * + * Google Summer of Code 2014 at + * Czech Technical University in Prague + * Zikova 1903/4 + * 166 36 Praha 6 + * Czech Republic + * + * Based on LPC24xx and LPC1768 BSP + * by embedded brains GmbH and others + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/start.h> + +BSP_START_TEXT_SECTION void bsp_start_hook_0( void ) +{ + ; +} + +BSP_START_TEXT_SECTION void bsp_start_hook_1( void ) +{ + bsp_start_copy_sections(); + bsp_start_clear_bss(); + + /* At this point we can use objects outside the .start section */ +} diff --git a/bsps/arm/tms570/start/linkcmds.tms570ls3137_hdk b/bsps/arm/tms570/start/linkcmds.tms570ls3137_hdk new file mode 100644 index 0000000000..a32562fc6b --- /dev/null +++ b/bsps/arm/tms570/start/linkcmds.tms570ls3137_hdk @@ -0,0 +1,32 @@ + +MEMORY { + ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 3M + RAM_INT_VEC : ORIGIN = 0x08000000, LENGTH = 256 + RAM_INT (AIWX) : ORIGIN = 0x08000100, LENGTH = 256k - 256 + RAM_EXT (AIWX) : ORIGIN = 0x80000000, LENGTH = 8M +} + +REGION_ALIAS ("REGION_START", ROM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_INT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_INT); +REGION_ALIAS ("REGION_WORK", RAM_INT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +bsp_stack_main_size = DEFINED (bsp_stack_main_size) ? bsp_stack_main_size : 1024; +bsp_stack_main_size = ALIGN (bsp_stack_main_size, bsp_stack_align); + +bsp_int_vec_overlay_start = ORIGIN(RAM_INT_VEC); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/tms570/start/linkcmds.tms570ls3137_hdk_intram b/bsps/arm/tms570/start/linkcmds.tms570ls3137_hdk_intram new file mode 100644 index 0000000000..7cb683de3d --- /dev/null +++ b/bsps/arm/tms570/start/linkcmds.tms570ls3137_hdk_intram @@ -0,0 +1,32 @@ + +MEMORY { + ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 3M + RAM_INT_VEC : ORIGIN = 0x08000000, LENGTH = 256 + RAM_INT (AIWX) : ORIGIN = 0x08000100, LENGTH = 256k - 256 + RAM_EXT (AIW) : ORIGIN = 0x80000000, LENGTH = 8M +} + +REGION_ALIAS ("REGION_START", RAM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", RAM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM_INT); +REGION_ALIAS ("REGION_RODATA", RAM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM_INT); +REGION_ALIAS ("REGION_DATA", RAM_INT); +REGION_ALIAS ("REGION_DATA_LOAD", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM_INT); +REGION_ALIAS ("REGION_BSS", RAM_INT); +REGION_ALIAS ("REGION_WORK", RAM_INT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +bsp_stack_main_size = DEFINED (bsp_stack_main_size) ? bsp_stack_main_size : 1024; +bsp_stack_main_size = ALIGN (bsp_stack_main_size, bsp_stack_align); + +bsp_int_vec_overlay_start = ORIGIN(RAM_INT_VEC); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/tms570/start/linkcmds.tms570ls3137_hdk_sdram b/bsps/arm/tms570/start/linkcmds.tms570ls3137_hdk_sdram new file mode 100644 index 0000000000..0117410467 --- /dev/null +++ b/bsps/arm/tms570/start/linkcmds.tms570ls3137_hdk_sdram @@ -0,0 +1,32 @@ + +MEMORY { + ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 3M + RAM_INT_VEC : ORIGIN = 0x08000000, LENGTH = 256 + RAM_INT (AIWX) : ORIGIN = 0x08000100, LENGTH = 256k - 256 + RAM_EXT (AIWX) : ORIGIN = 0x80000000, LENGTH = 8M +} + +REGION_ALIAS ("REGION_START", RAM_EXT); +REGION_ALIAS ("REGION_VECTOR", RAM_EXT); +REGION_ALIAS ("REGION_TEXT", RAM_EXT); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_RODATA", RAM_EXT); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_DATA", RAM_EXT); +REGION_ALIAS ("REGION_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_EXT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_EXT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM_EXT); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM_EXT); +REGION_ALIAS ("REGION_NOCACHE", RAM_EXT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_EXT); + +bsp_stack_main_size = DEFINED (bsp_stack_main_size) ? bsp_stack_main_size : 1024; +bsp_stack_main_size = ALIGN (bsp_stack_main_size, bsp_stack_align); + +bsp_int_vec_overlay_start = ORIGIN(RAM_INT_VEC); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/tms570/start/linkcmds.tms570ls3137_hdk_with_loader b/bsps/arm/tms570/start/linkcmds.tms570ls3137_hdk_with_loader new file mode 100644 index 0000000000..940f303030 --- /dev/null +++ b/bsps/arm/tms570/start/linkcmds.tms570ls3137_hdk_with_loader @@ -0,0 +1,33 @@ + +MEMORY { + ROM_BOOT(RX) : ORIGIN = 0x00000000, LENGTH = 256k + ROM_INT (RX) : ORIGIN = 0x00040000, LENGTH = 3M-256k + RAM_INT_VEC : ORIGIN = 0x08000000, LENGTH = 256 + RAM_INT (AIWX) : ORIGIN = 0x08000100, LENGTH = 256k - 256 + RAM_EXT (AIWX) : ORIGIN = 0x80000000, LENGTH = 8M +} + +REGION_ALIAS ("REGION_START", ROM_INT); +REGION_ALIAS ("REGION_VECTOR", RAM_INT); +REGION_ALIAS ("REGION_TEXT", ROM_INT); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_RODATA", ROM_INT); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_DATA", RAM_INT); +REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT); +REGION_ALIAS ("REGION_FAST_DATA", RAM_INT); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT); +REGION_ALIAS ("REGION_BSS", RAM_INT); +REGION_ALIAS ("REGION_WORK", RAM_INT); +REGION_ALIAS ("REGION_STACK", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE", RAM_INT); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT); + +bsp_stack_main_size = DEFINED (bsp_stack_main_size) ? bsp_stack_main_size : 1024; +bsp_stack_main_size = ALIGN (bsp_stack_main_size, bsp_stack_align); + +bsp_int_vec_overlay_start = ORIGIN(RAM_INT_VEC); + +INCLUDE linkcmds.armv4 diff --git a/bsps/arm/xilinx-zynq/start/bsp_specs b/bsps/arm/xilinx-zynq/start/bsp_specs new file mode 100644 index 0000000000..47dd31d46b --- /dev/null +++ b/bsps/arm/xilinx-zynq/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/arm/xilinx-zynq/start/bspreset.c b/bsps/arm/xilinx-zynq/start/bspreset.c new file mode 100644 index 0000000000..b57354c9e2 --- /dev/null +++ b/bsps/arm/xilinx-zynq/start/bspreset.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013, 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/zynq-uart.h> + +void bsp_reset(void) +{ + volatile uint32_t *slcr_unlock = (volatile uint32_t *) 0xf8000008; + volatile uint32_t *pss_rst_ctrl = (volatile uint32_t *) 0xf8000200; + + zynq_uart_reset_tx_flush(&zynq_uart_instances[BSP_CONSOLE_MINOR]); + + while (true) { + *slcr_unlock = 0xdf0d; + *pss_rst_ctrl = 0x1; + } +} diff --git a/bsps/arm/xilinx-zynq/start/bspsmp.c b/bsps/arm/xilinx-zynq/start/bspsmp.c new file mode 100644 index 0000000000..b516823243 --- /dev/null +++ b/bsps/arm/xilinx-zynq/start/bspsmp.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <rtems/score/smpimpl.h> + +#include <bsp/start.h> + +bool _CPU_SMP_Start_processor(uint32_t cpu_index) +{ + /* + * Enable the second CPU. + */ + if (cpu_index != 0) { + volatile uint32_t* const kick_address = (uint32_t*) 0xfffffff0UL; + _ARM_Data_synchronization_barrier(); + _ARM_Instruction_synchronization_barrier(); + *kick_address = (uint32_t) _start; + _ARM_Data_synchronization_barrier(); + _ARM_Instruction_synchronization_barrier(); + _ARM_Send_event(); + } + + /* + * Wait for secondary processor to complete its basic initialization so that + * we can enable the unified L2 cache. + */ + return _Per_CPU_State_wait_for_non_initial_state(cpu_index, 0); +} diff --git a/bsps/arm/xilinx-zynq/start/bspstart.c b/bsps/arm/xilinx-zynq/start/bspstart.c new file mode 100644 index 0000000000..14a20df7ef --- /dev/null +++ b/bsps/arm/xilinx-zynq/start/bspstart.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013-2015 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/arm-a9mpcore-clock.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> + +__attribute__ ((weak)) uint32_t zynq_clock_cpu_1x(void) +{ + return ZYNQ_CLOCK_CPU_1X; +} + +void bsp_start(void) +{ + a9mpcore_clock_initialize_early(); + bsp_interrupt_initialize(); + rtems_cache_coherent_add_area( + bsp_section_nocacheheap_begin, + (uintptr_t) bsp_section_nocacheheap_size + ); +} diff --git a/bsps/arm/xilinx-zynq/start/bspstarthooks.c b/bsps/arm/xilinx-zynq/start/bspstarthooks.c new file mode 100644 index 0000000000..5372380c24 --- /dev/null +++ b/bsps/arm/xilinx-zynq/start/bspstarthooks.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#define ARM_CP15_TEXT_SECTION BSP_START_TEXT_SECTION + +#include <bsp.h> +#include <bsp/start.h> +#include <bsp/arm-cp15-start.h> +#include <bsp/arm-a9mpcore-start.h> + +BSP_START_TEXT_SECTION void bsp_start_hook_0(void) +{ + uint32_t sctlr_val; + + sctlr_val = arm_cp15_get_control(); + + /* + * Current U-boot loader seems to start kernel image + * with I and D caches on and MMU enabled. + * If RTEMS application image finds that cache is on + * during startup then disable caches. + */ + if ( sctlr_val & (ARM_CP15_CTRL_I | ARM_CP15_CTRL_C | ARM_CP15_CTRL_M ) ) { + if ( sctlr_val & (ARM_CP15_CTRL_C | ARM_CP15_CTRL_M ) ) { + /* + * If the data cache is on then ensure that it is clean + * before switching off to be extra carefull. + */ + arm_cp15_data_cache_clean_all_levels(); + } + arm_cp15_flush_prefetch_buffer(); + sctlr_val &= ~ ( ARM_CP15_CTRL_I | ARM_CP15_CTRL_C | ARM_CP15_CTRL_M | ARM_CP15_CTRL_A ); + arm_cp15_set_control( sctlr_val ); + } + arm_cp15_instruction_cache_invalidate(); + /* + * The care should be taken there that no shared levels + * are invalidated by secondary CPUs in SMP case. + * It is not problem on Zynq because level of coherency + * is L1 only and higher level is not maintained and seen + * by CP15. So no special care to limit levels on the secondary + * are required there. + */ + arm_cp15_data_cache_invalidate_all_levels(); + arm_cp15_branch_predictor_invalidate_all(); + arm_cp15_tlb_invalidate(); + arm_cp15_flush_prefetch_buffer(); + arm_a9mpcore_start_hook_0(); +} + +BSP_START_TEXT_SECTION void bsp_start_hook_1(void) +{ + arm_a9mpcore_start_hook_1(); + bsp_start_copy_sections(); + zynq_setup_mmu_and_cache(); + +#if !defined(RTEMS_SMP) \ + && (defined(BSP_DATA_CACHE_ENABLED) \ + || defined(BSP_INSTRUCTION_CACHE_ENABLED)) + /* Enable unified L2 cache */ + rtems_cache_enable_data(); +#endif + + bsp_start_clear_bss(); +} diff --git a/bsps/arm/xilinx-zynq/start/bspstartmmu.c b/bsps/arm/xilinx-zynq/start/bspstartmmu.c new file mode 100644 index 0000000000..e0a7743e57 --- /dev/null +++ b/bsps/arm/xilinx-zynq/start/bspstartmmu.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@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.org/license/LICENSE. + */ + +#define ARM_CP15_TEXT_SECTION BSP_START_TEXT_SECTION + +#include <bsp.h> +#include <bsp/start.h> +#include <bsp/arm-cp15-start.h> +#include <bsp/arm-a9mpcore-start.h> + +BSP_START_DATA_SECTION static const arm_cp15_start_section_config +zynq_mmu_config_table[] = { + ARMV7_CP15_START_DEFAULT_SECTIONS, +#if defined(RTEMS_SMP) + { + .begin = 0xffff0000U, + .end = 0xffffffffU, + .flags = ARMV7_MMU_DEVICE + }, +#endif + { + .begin = 0xe0000000U, + .end = 0xe0200000U, + .flags = ARMV7_MMU_DEVICE + }, { + .begin = 0xf8000000U, + .end = 0xf9000000U, + .flags = ARMV7_MMU_DEVICE + } +}; + +/* + * Make weak and let the user override. + */ +BSP_START_TEXT_SECTION void zynq_setup_mmu_and_cache(void) __attribute__ ((weak)); + +BSP_START_TEXT_SECTION void zynq_setup_mmu_and_cache(void) +{ + uint32_t ctrl = arm_cp15_start_setup_mmu_and_cache( + ARM_CP15_CTRL_A, + ARM_CP15_CTRL_AFE | ARM_CP15_CTRL_Z + ); + + arm_cp15_start_setup_translation_table_and_enable_mmu_and_cache( + ctrl, + (uint32_t *) bsp_translation_table_base, + ARM_MMU_DEFAULT_CLIENT_DOMAIN, + &zynq_mmu_config_table[0], + RTEMS_ARRAY_SIZE(zynq_mmu_config_table) + ); +} diff --git a/bsps/arm/xilinx-zynq/start/linkcmds.in b/bsps/arm/xilinx-zynq/start/linkcmds.in new file mode 100644 index 0000000000..7fd6e2772d --- /dev/null +++ b/bsps/arm/xilinx-zynq/start/linkcmds.in @@ -0,0 +1,39 @@ +MEMORY { + RAM_INT_0 : ORIGIN = @ZYNQ_RAM_INT_0_ORIGIN@, LENGTH = @ZYNQ_RAM_INT_0_LENGTH@ + RAM_INT_1 : ORIGIN = @ZYNQ_RAM_INT_1_ORIGIN@, LENGTH = @ZYNQ_RAM_INT_1_LENGTH@ + RAM_MMU : ORIGIN = @ZYNQ_RAM_MMU@, LENGTH = @ZYNQ_RAM_MMU_LENGTH@ + RAM : ORIGIN = @ZYNQ_RAM_ORIGIN_AVAILABLE@, LENGTH = @ZYNQ_RAM_LENGTH_AVAILABLE@ - @ZYNQ_RAM_NOCACHE_LENGTH@ + NOCACHE : ORIGIN = @ZYNQ_RAM_ORIGIN_AVAILABLE@ + @ZYNQ_RAM_LENGTH_AVAILABLE@ - @ZYNQ_RAM_NOCACHE_LENGTH@, LENGTH = @ZYNQ_RAM_NOCACHE_LENGTH@ +} + +bsp_processor_count = DEFINED (bsp_processor_count) ? bsp_processor_count : @ZYNQ_CPUS@; + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_VECTOR", RAM); +REGION_ALIAS ("REGION_TEXT", RAM); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_RODATA", RAM); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", NOCACHE); + +bsp_stack_irq_size = DEFINED (bsp_stack_irq_size) ? bsp_stack_irq_size : 4096; +bsp_stack_abt_size = DEFINED (bsp_stack_abt_size) ? bsp_stack_abt_size : 1024; + +bsp_section_rwbarrier_align = DEFINED (bsp_section_rwbarrier_align) ? bsp_section_rwbarrier_align : 1M; + +bsp_vector_table_in_start_section = 1; + +bsp_translation_table_base = ORIGIN (RAM_MMU); +bsp_translation_table_end = ORIGIN (RAM_MMU) + LENGTH (RAM_MMU); + +INCLUDE linkcmds.armv4 |