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 | |
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')
560 files changed, 51305 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 diff --git a/bsps/bfin/TLL6527M/start/bsp_specs b/bsps/bfin/TLL6527M/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/bfin/TLL6527M/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/bfin/TLL6527M/start/bspstart.c b/bsps/bfin/TLL6527M/start/bspstart.c new file mode 100644 index 0000000000..4c8302a7ba --- /dev/null +++ b/bsps/bfin/TLL6527M/start/bspstart.c @@ -0,0 +1,152 @@ +/* bspstart.c for TLL6527M + * + * This routine does the bulk of the system initialization. + */ + +/* + * COPYRIGHT (c) 2010 by ECE Northeastern University. + * + * 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 + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <cplb.h> +#include <bsp/interrupt.h> +#include <libcpu/ebiuRegs.h> +#include <rtems/sysinit.h> + +const unsigned int dcplbs_table[16][2] = { + { 0xFFA00000, (PAGE_SIZE_1MB | CPLB_D_PAGE_MGMT | CPLB_WT) }, + { 0xFF900000, (PAGE_SIZE_1MB | CPLB_D_PAGE_MGMT | CPLB_WT) },/* L1 Data B */ + { 0xFF800000, (PAGE_SIZE_1MB | CPLB_D_PAGE_MGMT | CPLB_WT) },/* L1 Data A */ + { 0xFFB00000, (PAGE_SIZE_1MB | CPLB_DNOCACHE) }, + + { 0x20300000, (PAGE_SIZE_1MB | CPLB_DNOCACHE) },/* Async Memory Bank 3 */ + { 0x20200000, (PAGE_SIZE_1MB | CPLB_DNOCACHE) },/* Async Memory Bank 2 */ + { 0x20100000, (PAGE_SIZE_1MB | CPLB_DNOCACHE) },/* Async Memory Bank 1 */ + { 0x20000000, (PAGE_SIZE_1MB | CPLB_DNOCACHE) }, /* Async Memory Bank 0 */ + + { 0x02400000, (PAGE_SIZE_4MB | CPLB_DNOCACHE) }, + { 0x02000000, (PAGE_SIZE_4MB | CPLB_DNOCACHE) }, + { 0x00C00000, (PAGE_SIZE_4MB | CPLB_DNOCACHE) }, + { 0x00800000, (PAGE_SIZE_4MB | CPLB_DNOCACHE) }, + { 0x00400000, (PAGE_SIZE_4MB | CPLB_DNOCACHE) }, + { 0x00000000, (PAGE_SIZE_4MB | CPLB_DNOCACHE) }, + + { 0xffffffff, 0xffffffff }/* end of section - termination */ +}; + + +const unsigned int _icplbs_table[16][2] = { + { 0xFFA00000, (PAGE_SIZE_1MB | CPLB_I_PAGE_MGMT | CPLB_I_PAGE_MGMT | 0x4) }, + /* L1 Code */ + { 0xEF000000, (PAGE_SIZE_1MB | CPLB_INOCACHE) }, /* AREA DE BOOT */ + { 0xFFB00000, (PAGE_SIZE_1MB | CPLB_INOCACHE) }, + + { 0x20300000, (PAGE_SIZE_1MB | CPLB_INOCACHE) },/* Async Memory Bank 3 */ + { 0x20200000, (PAGE_SIZE_1MB | CPLB_INOCACHE) },/* Async Bank 2 (Secnd) */ + { 0x20100000, (PAGE_SIZE_1MB | CPLB_INOCACHE) },/* Async Bank 1 (Prim B) */ + { 0x20000000, (PAGE_SIZE_1MB | CPLB_INOCACHE) },/* Async Bank 0 (Prim A) */ + + { 0x02400000, (PAGE_SIZE_4MB | CPLB_INOCACHE) }, + { 0x02000000, (PAGE_SIZE_4MB | CPLB_INOCACHE) }, + { 0x00C00000, (PAGE_SIZE_4MB | CPLB_INOCACHE) }, + { 0x00800000, (PAGE_SIZE_4MB | CPLB_INOCACHE) }, + { 0x00400000, (PAGE_SIZE_4MB | CPLB_INOCACHE) }, + { 0x00000000, (PAGE_SIZE_4MB | CPLB_INOCACHE) }, + + { 0xffffffff, 0xffffffff }/* end of section - termination */ +}; + +/* + * Init_PLL + * + * Routine to initialize the PLL. The TLL6527M uses a 25 Mhz XTAL. + */ +static void Init_PLL (void) +{ + unsigned short msel = 0; + unsigned short ssel = 0; + + msel = (unsigned short)( (float)CCLK/(float)CLKIN ); + ssel = (unsigned short)( (float)(CLKIN*msel)/(float)SCLK); + + asm("cli r0;"); + + *((uint32_t*)SIC_IWR) = 0x1; + + /* Configure PLL registers */ + *((uint16_t*)PLL_DIV) = ssel; + msel = msel<<9; + *((uint16_t*)PLL_CTL) = msel; + + /* Commands to set PLL values */ + asm("idle;"); + asm("sti r0;"); +} + +/* + * Init_EBIU + * + * Configure extern memory + */ +static void Init_EBIU (void) +{ + /* Check if SDRAM is already enabled */ + if ( 0 != (*(uint16_t *)EBIU_SDSTAT & EBIU_SDSTAT_SDRS) ){ + asm("ssync;"); + /* RDIV = (100MHz*64ms)/8192-(6+3)=0x406 cycles */ + *(uint16_t *)EBIU_SDRRC = 0x3F6; /* SHould have been 0x306*/ + *(uint16_t *)EBIU_SDBCTL = EBIU_SDBCTL_EBCAW_10 | EBIU_SDBCTL_EBSZ_64M | + EBIU_SDBCTL_EBE; + *(uint32_t *)EBIU_SDGCTL = 0x8491998d; + asm("ssync;"); + } else { + /* SDRAm is already programmed */ + } +} + +/* + * Init_Flags + * + * Enable LEDs port + */ +static void Init_Flags(void) +{ + *((uint16_t*)PORTH_FER) = 0x0; + *((uint16_t*)PORTH_MUX) = 0x0; + *((uint16_t*)PORTHIO_DIR) = 0x1<<15; + *((uint16_t*)PORTHIO_SET) = 0x1<<15; +} + +RTEMS_SYSINIT_ITEM( + bfin_interrupt_init, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); + +void bsp_start( void ) +{ + int i; + + /* BSP Hardware Initialization*/ + Init_RTC(); /* Blackfin Real Time Clock initialization */ + Init_PLL(); /* PLL initialization */ + Init_EBIU(); /* EBIU initialization */ + Init_Flags(); /* GPIO initialization */ + + /* + * Allocate the memory for the RTEMS Work Space. This can come from + * a variety of places: hard coded address, malloc'ed from outside + * RTEMS world (e.g. simulator or primitive memory manager), or (as + * typically done by stock BSPs) by subtracting the required amount + * of work space from the last physical address on the CPU board. + */ + for (i=5;i<16;i++) { + set_vector((rtems_isr_entry)bfin_null_isr, i, 1); + } + +} diff --git a/bsps/bfin/TLL6527M/start/linkcmds b/bsps/bfin/TLL6527M/start/linkcmds new file mode 100644 index 0000000000..93d2a85d82 --- /dev/null +++ b/bsps/bfin/TLL6527M/start/linkcmds @@ -0,0 +1,176 @@ +OUTPUT_FORMAT("elf32-bfin", "elf32-bfin", + "elf32-bfin") + +OUTPUT_ARCH(bfin) +ENTRY(__start) +STARTUP(start.o) + +/* + * Declare some sizes. + */ +_RamBase = DEFINED(_RamBase) ? _RamBase : 0x0; +_RamSize = DEFINED(_RamSize) ? _RamSize : 0x04000000; +_HeapSize = DEFINED(_HeapSize) ? _HeapSize : 0x10000; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x10000; + +MEMORY +{ + sdram(rwx) : ORIGIN = 0x00000100, LENGTH = 0x04000000 + + l1dataA(rwx) : ORIGIN = 0xff800000, LENGTH = 0x00004000 + l1dataAC(rwx) : ORIGIN = 0xff804000, LENGTH = 0x00004000 + l1dataB(rwx) : ORIGIN = 0xff900000, LENGTH = 0x00004000 + l1dataBC(rwx) : ORIGIN = 0xff904000, LENGTH = 0x00004000 + + l1code(rwx) : ORIGIN = 0xffa00000, LENGTH = 0x0000C000 + l1codeC(rwx) : ORIGIN = 0xffa10000, LENGTH = 0x00004000 + scratchpad(rwx) : ORIGIN = 0xffb00000, LENGTH = 0x00001000 +} + +SECTIONS +{ + + .init : + { + *(.l1code) + KEEP (*(.init)) + } > sdram /*=0*/ + + .text : + { + CREATE_OBJECT_SYMBOLS + *(.text) + *(.rodata*) + *(.gnu.linkonce.r*) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + ___start_set_sysctl_set = .; + *(set_sysctl_*); + ___stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + _etext = .; + + ___CTOR_LIST__ = .; + LONG((___CTOR_END__ - ___CTOR_LIST__) / 4 - 2) + *(.ctors) + LONG(0) + ___CTOR_END__ = .; + ___DTOR_LIST__ = .; + LONG((___DTOR_END__ - ___DTOR_LIST__) / 4 - 2) + *(.dtors) + LONG(0) + ___DTOR_END__ = .; + } > sdram + + .tdata : { + __TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + __TLS_Data_end = .; + } > sdram + + .tbss : { + __TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + __TLS_BSS_end = .; + } > sdram + + __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)); + + .fini : + { + KEEP (*(.fini)) + } > sdram /*=0*/ + + .data : + { + *(.data) + KEEP (*(SORT(.rtemsrwset.*))) + *(.jcr) + *(.gnu.linkonce.d*) + CONSTRUCTORS + _edata = .; + } > sdram + + .eh_frame : { *(.eh_frame) } > sdram + .data1 : { *(.data1) } > sdram + .eh_frame : { *(.eh_frame) } > sdram + .gcc_except_table : { *(.gcc_except_table*) } > sdram + + .rodata : + { + *(.rodata) + *(.rodata.*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + } > sdram + + + .bss : + { + _bss_start = .; + _clear_start = .; + *(.bss) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (64); + _stack_init = .; + . += _StackSize; + _clear_end = .; + _WorkAreaBase = .; + _end = .; + __end = .; + } > sdram + +/* Debugging stuff follows */ + + /* 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) } + .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) } + /*.stack 0x80000 : { _stack = .; *(.stack) }*/ + /* These must appear regardless of . */ +} + +__HeapSize = _HeapSize; +__edata = _edata; +__etext = _etext; + diff --git a/bsps/bfin/bf537Stamp/start/bsp_specs b/bsps/bfin/bf537Stamp/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/bfin/bf537Stamp/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/bfin/bf537Stamp/start/bspstart.c b/bsps/bfin/bf537Stamp/start/bspstart.c new file mode 100644 index 0000000000..ffc2d950c7 --- /dev/null +++ b/bsps/bfin/bf537Stamp/start/bspstart.c @@ -0,0 +1,229 @@ +/* bspstart.c for bf537Stamp + * + * This routine does the bulk of the system initialisation. + */ + +/* + * Copyright (c) 2006 by Atos Automacao Industrial Ltda. + * written by Alain Schaefer <alain.schaefer@easc.ch> + * and Antonio Giovanini <antonio@atos.com.br> + * + * 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 <libcpu/bf537.h> +#include <libcpu/ebiuRegs.h> +#include <libcpu/gpioRegs.h> +#include <libcpu/mmu.h> +#include <libcpu/mmuRegs.h> +#include <libcpu/interrupt.h> +#include <rtems/sysinit.h> + +static bfin_mmu_config_t mmuRegions = { + /* instruction */ + { + {(void *) 0x00000000, ICPLB_DATA_PAGE_SIZE_4MB | INSTR_CACHEABLE}, + {(void *) 0x00400000, ICPLB_DATA_PAGE_SIZE_4MB | INSTR_CACHEABLE}, + {(void *) 0x00800000, ICPLB_DATA_PAGE_SIZE_4MB | INSTR_CACHEABLE}, + {(void *) 0x00c00000, ICPLB_DATA_PAGE_SIZE_4MB | INSTR_CACHEABLE}, + {(void *) 0x01000000, ICPLB_DATA_PAGE_SIZE_4MB | INSTR_CACHEABLE}, + {(void *) 0x01400000, ICPLB_DATA_PAGE_SIZE_4MB | INSTR_CACHEABLE}, + {(void *) 0x01800000, ICPLB_DATA_PAGE_SIZE_4MB | INSTR_CACHEABLE}, + {(void *) 0x01c00000, ICPLB_DATA_PAGE_SIZE_4MB | INSTR_CACHEABLE}, + {(void *) 0x02000000, ICPLB_DATA_PAGE_SIZE_4MB | INSTR_CACHEABLE}, + {(void *) 0x02400000, ICPLB_DATA_PAGE_SIZE_4MB | INSTR_CACHEABLE}, + {(void *) 0x02800000, ICPLB_DATA_PAGE_SIZE_4MB | INSTR_CACHEABLE}, + {(void *) 0x02c00000, ICPLB_DATA_PAGE_SIZE_4MB | INSTR_CACHEABLE}, + {(void *) 0x03000000, ICPLB_DATA_PAGE_SIZE_4MB | INSTR_CACHEABLE}, + {(void *) 0x20000000, ICPLB_DATA_PAGE_SIZE_4MB | INSTR_CACHEABLE}, + {(void *) 0xff800000, ICPLB_DATA_PAGE_SIZE_4MB | INSTR_NOCACHE}, + {(void *) 0xffc00000, ICPLB_DATA_PAGE_SIZE_4MB | INSTR_NOCACHE} + }, + /* data */ + { + {(void *) 0x00000000, DCPLB_DATA_PAGE_SIZE_4MB | DATA_WRITEBACK}, + {(void *) 0x00400000, DCPLB_DATA_PAGE_SIZE_4MB | DATA_WRITEBACK}, + {(void *) 0x00800000, DCPLB_DATA_PAGE_SIZE_4MB | DATA_WRITEBACK}, + {(void *) 0x00c00000, DCPLB_DATA_PAGE_SIZE_4MB | DATA_WRITEBACK}, + {(void *) 0x01000000, DCPLB_DATA_PAGE_SIZE_4MB | DATA_WRITEBACK}, + {(void *) 0x01400000, DCPLB_DATA_PAGE_SIZE_4MB | DATA_WRITEBACK}, + {(void *) 0x01800000, DCPLB_DATA_PAGE_SIZE_4MB | DATA_WRITEBACK}, + {(void *) 0x01c00000, DCPLB_DATA_PAGE_SIZE_4MB | DATA_WRITEBACK}, + {(void *) 0x02000000, DCPLB_DATA_PAGE_SIZE_4MB | DATA_WRITEBACK}, + {(void *) 0x02400000, DCPLB_DATA_PAGE_SIZE_4MB | DATA_WRITEBACK}, + {(void *) 0x02800000, DCPLB_DATA_PAGE_SIZE_4MB | DATA_WRITEBACK}, + {(void *) 0x02c00000, DCPLB_DATA_PAGE_SIZE_4MB | DATA_WRITEBACK}, + {(void *) 0x03000000, DCPLB_DATA_PAGE_SIZE_4MB | DATA_WRITEBACK}, + {(void *) 0x20000000, DCPLB_DATA_PAGE_SIZE_4MB | DATA_WRITEBACK}, + {(void *) 0xff800000, DCPLB_DATA_PAGE_SIZE_4MB | DATA_NOCACHE}, + {(void *) 0xffc00000, DCPLB_DATA_PAGE_SIZE_4MB | DATA_NOCACHE} + } +}; + +static void initPLL(void); +static void initEBIU(void); +static void initGPIO(void); + +RTEMS_SYSINIT_ITEM( + bfin_interrupt_init, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); + +void bsp_start(void) +{ + /* BSP Hardware Initialization*/ + + *(uint32_t volatile *) DMEM_CONTROL |= DMEM_CONTROL_PORT_PREF0; + *(uint32_t volatile *) DMEM_CONTROL &= ~DMEM_CONTROL_PORT_PREF1; + bfin_mmu_init(&mmuRegions); + rtems_cache_enable_instruction(); + rtems_cache_enable_data(); + + Init_RTC(); /* Blackfin Real Time Clock initialization */ + + initPLL(); /* PLL initialization */ + initEBIU(); /* EBIU initialization */ + initGPIO(); /* GPIO initialization */ +} + + /* + * initPLL + * + * Routine to initialize the PLL. The BF537 Stamp uses a 27 Mhz XTAL. BISON + * See "../bf537Stamp/include/bsp.h" for more information. + */ + +static void initPLL(void) { + +#ifdef BISON + unsigned int n; + + /* Configure PLL registers */ + *((uint16_t*)PLL_LOCKCNT) = 0x1000; + *((uint16_t*)PLL_DIV) = PLL_CSEL|PLL_SSEL; + *((uint16_t*)PLL_CTL) = PLL_MSEL|PLL_DF; + + /* Commands to set PLL values */ + __asm__ ("cli r0;"); + __asm__ ("idle;"); + __asm__ ("sti r0;"); + + /* Delay for PLL stabilization */ + for (n=0; n<200; n++) {} +#endif + +} + + /* + * initEBIU + * + * Configure extern memory + */ + +static void initEBIU(void) { + + /* by default the processor has priority over dma channels for access to + external memory. this has been seen to result in dma unerruns on + ethernet transmit; it seems likely it could cause dma overruns on + ethernet receive as well. setting the following bit gives the dma + channels priority over the cpu, fixing that problem. unfortunately + we don't have finer grain control than that; all dma channels now + have priority over the cpu. */ + *(uint16_t volatile *) EBIU_AMGCTL |= EBIU_AMGCTL_CDPRIO; + +#ifdef BISON + /* Configure FLASH */ + *((uint32_t*)EBIU_AMBCTL0) = 0x7bb07bb0L; + *((uint32_t*)EBIU_AMBCTL1) = 0x7bb07bb0L; + *((uint16_t*)EBIU_AMGCTL) = 0x000f; + + /* Configure SDRAM + *((uint32_t*)EBIU_SDGCTL) = 0x0091998d; + *((uint16_t*)EBIU_SDBCTL) = 0x0013; + *((uint16_t*)EBIU_SDRRC) = 0x0817; + */ +#endif +} + + /* + * initGPIO + * + * Enable LEDs port + */ +static void initGPIO(void) { +#if (!BFIN_ON_SKYEYE) + *(uint16_t volatile *) PORT_MUX = 0; + + /* port f bits 0, 1: uart0 tx, rx */ + /* bits 2 - 5: buttons */ + /* bits 6 - 11: leds */ + *(uint16_t volatile *) PORTF_FER = 0x0003; + *(uint16_t volatile *) (PORTFIO_BASE_ADDRESS + PORTIO_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTFIO_BASE_ADDRESS + PORTIO_INEN_OFFSET) = 0x003c; + *(uint16_t volatile *) (PORTFIO_BASE_ADDRESS + PORTIO_POLAR_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTFIO_BASE_ADDRESS + PORTIO_EDGE_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTFIO_BASE_ADDRESS + PORTIO_BOTH_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTFIO_BASE_ADDRESS + PORTIO_MASKA_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTFIO_BASE_ADDRESS + PORTIO_MASKB_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTFIO_BASE_ADDRESS + PORTIO_DIR_OFFSET) = 0x0fc0; + + *(uint16_t volatile *) PORTG_FER = 0x0000; + *(uint16_t volatile *) (PORTGIO_BASE_ADDRESS + PORTIO_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTGIO_BASE_ADDRESS + PORTIO_INEN_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTGIO_BASE_ADDRESS + PORTIO_POLAR_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTGIO_BASE_ADDRESS + PORTIO_EDGE_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTGIO_BASE_ADDRESS + PORTIO_BOTH_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTGIO_BASE_ADDRESS + PORTIO_MASKA_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTGIO_BASE_ADDRESS + PORTIO_MASKB_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTGIO_BASE_ADDRESS + PORTIO_DIR_OFFSET) = 0x0000; + + /* port h bits 0 - 15: ethernet */ + *(uint16_t volatile *) PORTH_FER = 0xffff; + *(uint16_t volatile *) (PORTHIO_BASE_ADDRESS + PORTIO_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTHIO_BASE_ADDRESS + PORTIO_INEN_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTHIO_BASE_ADDRESS + PORTIO_POLAR_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTHIO_BASE_ADDRESS + PORTIO_EDGE_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTHIO_BASE_ADDRESS + PORTIO_BOTH_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTHIO_BASE_ADDRESS + PORTIO_MASKA_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTHIO_BASE_ADDRESS + PORTIO_MASKB_OFFSET) = 0x0000; + *(uint16_t volatile *) (PORTHIO_BASE_ADDRESS + PORTIO_DIR_OFFSET) = 0x0000; +#endif +} + +/* + * Helper Function to use the EzKits LEDS. + * Can be used by the Application. + */ +void setLEDs(uint8_t value) { + + *(uint16_t volatile *) (PORTFIO_BASE_ADDRESS + PORTIO_CLEAR_OFFSET) = + (uint16_t) (~value & 0x3f) << 6; + *(uint16_t volatile *) (PORTFIO_BASE_ADDRESS + PORTIO_SET_OFFSET) = + (uint16_t) (value & 0x3f) << 6; +} + +/* + * Helper Function to use the EzKits LEDS + */ +uint8_t getLEDs(void) { + uint16_t r; + + r = *(uint16_t volatile *) (PORTFIO_BASE_ADDRESS + PORTIO_OFFSET); + return (uint8_t) ((r >> 6) & 0x3f); +} + +uint8_t getButtons(void) { + uint16_t r; + + r = *(uint16_t volatile *) (PORTFIO_BASE_ADDRESS + PORTIO_OFFSET); + + return (uint8_t) ((r >> 2) & 0x0f); +} + + diff --git a/bsps/bfin/bf537Stamp/start/linkcmds b/bsps/bfin/bf537Stamp/start/linkcmds new file mode 100644 index 0000000000..47888ff798 --- /dev/null +++ b/bsps/bfin/bf537Stamp/start/linkcmds @@ -0,0 +1,184 @@ +OUTPUT_FORMAT("elf32-bfin", "elf32-bfin", + "elf32-bfin") + +OUTPUT_ARCH(bfin) +ENTRY(__start) +STARTUP(start.o) + +/* + * Declare some sizes. + */ +_RamBase = DEFINED(_RamBase) ? _RamBase : 0x0; +/* bf537stamp has 64MB ram, but dynamic mmu tables have not yet been + implemented. there are not enough static entries to support 64MB + along with banks for io and flash, so waste some RAM at the end + to free up mmu entries. */ +_RamSize = DEFINED(_RamSize) ? _RamSize : 0x03400000; +_HeapSize = DEFINED(_HeapSize) ? _HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x1000; + +MEMORY +{ + sdram(rwx) : ORIGIN = 0x00001000, LENGTH = 0x03fff000 +/* + l1code(rwx) : ORIGIN = 0xffa08000, LENGTH = 0x00008000 + l1data(rwx) : ORIGIN = 0xff804000, LENGTH = 0x00004000 +*/ +} + +SECTIONS +{ + +/* + .l1code : + { +*/ + /*jump.o (.text)*/ +/* + } > l1code +*/ + + .init : + { + *(.start) + KEEP (*(.init)) + } > sdram /*=0*/ + + .text : + { + CREATE_OBJECT_SYMBOLS + *(.text) + *(.rodata*) + *(.gnu.linkonce.r*) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + ___start_set_sysctl_set = .; + *(set_sysctl_*); + ___stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + _etext = .; + + ___CTOR_LIST__ = .; + LONG((___CTOR_END__ - ___CTOR_LIST__) / 4 - 2) + *(.ctors) + LONG(0) + ___CTOR_END__ = .; + ___DTOR_LIST__ = .; + LONG((___DTOR_END__ - ___DTOR_LIST__) / 4 - 2) + *(.dtors) + LONG(0) + ___DTOR_END__ = .; + } > sdram + + .tdata : { + __TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + __TLS_Data_end = .; + } > sdram + + .tbss : { + __TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + __TLS_BSS_end = .; + } > sdram + + __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)); + + .fini : + { + KEEP (*(.fini)) + } > sdram /*=0*/ + + .data : + { + *(.data) + KEEP (*(SORT(.rtemsrwset.*))) + *(.jcr) + *(.gnu.linkonce.d*) + CONSTRUCTORS + _edata = .; + } > sdram + + .eh_frame : { *(.eh_frame) } > sdram + .data1 : { *(.data1) } > sdram + .eh_frame : { *(.eh_frame) } > sdram + .gcc_except_table : { *(.gcc_except_table*) } > sdram + + .rodata : + { + *(.rodata) + *(.rodata.*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + } > sdram + + + .bss : + { + _bss_start = .; + _clear_start = .; + *(.bss) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (64); + _stack_init = .; + . += _StackSize; + _clear_end = .; + _WorkAreaBase = .; + _end = .; + __end = .; + } > sdram + +/* Debugging stuff follows */ + + /* 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) } + .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) } + /*.stack 0x80000 : { _stack = .; *(.stack) }*/ + /* These must appear regardless of . */ +} + +__RamBase = _RamBase; +__RamSize = _RamSize; +__edata = _edata; +__etext = _etext; diff --git a/bsps/bfin/eZKit533/start/bsp_specs b/bsps/bfin/eZKit533/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/bfin/eZKit533/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/bfin/eZKit533/start/bspstart.c b/bsps/bfin/eZKit533/start/bspstart.c new file mode 100644 index 0000000000..3579dd7766 --- /dev/null +++ b/bsps/bfin/eZKit533/start/bspstart.c @@ -0,0 +1,156 @@ +/* bspstart.c for eZKit533 + * + * This routine does the bulk of the system initialisation. + */ + +/* + * Copyright (c) 2006 by Atos Automacao Industrial Ltda. + * written by Alain Schaefer <alain.schaefer@easc.ch> + * and Antonio Giovanini <antonio@atos.com.br> + * + * 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 <cplb.h> +#include <libcpu/interrupt.h> +#include <rtems/sysinit.h> + +const unsigned int dcplbs_table[16][2] = { + { 0xFFA00000, (PAGE_SIZE_1MB | CPLB_D_PAGE_MGMT | CPLB_WT) }, + { 0xFF900000, (PAGE_SIZE_1MB | CPLB_D_PAGE_MGMT | CPLB_WT) }, /* L1 Data B */ + { 0xFF800000, (PAGE_SIZE_1MB | CPLB_D_PAGE_MGMT | CPLB_WT) }, /* L1 Data A */ + { 0xFFB00000, (PAGE_SIZE_1MB | CPLB_DNOCACHE) }, + { 0x20300000, (PAGE_SIZE_1MB | CPLB_DNOCACHE) }, /* Async Memory Bank 3 */ + { 0x20200000, (PAGE_SIZE_1MB | CPLB_DNOCACHE) }, /* Async Memory Bank 2 (Secnd) */ + { 0x20100000, (PAGE_SIZE_1MB | CPLB_DNOCACHE) }, /* Async Memory Bank 1 (Prim B) */ + { 0x20000000, (PAGE_SIZE_1MB | CPLB_DNOCACHE) }, /* Async Memory Bank 0 (Prim A) */ + + { 0x02400000, (PAGE_SIZE_4MB | CPLB_DNOCACHE) }, + { 0x02000000, (PAGE_SIZE_4MB | CPLB_DNOCACHE) }, + { 0x00C00000, (PAGE_SIZE_4MB | CPLB_DNOCACHE) }, + { 0x00800000, (PAGE_SIZE_4MB | CPLB_DNOCACHE) }, + { 0x00400000, (PAGE_SIZE_4MB | CPLB_DNOCACHE) }, + { 0x00000000, (PAGE_SIZE_4MB | CPLB_DNOCACHE) }, + { 0xffffffff, 0xffffffff } /* end of section - termination */ + +}; + + +const unsigned int _icplbs_table[16][2] = { + { 0xFFA00000, (PAGE_SIZE_1MB | CPLB_I_PAGE_MGMT | CPLB_I_PAGE_MGMT | 0x4) }, /* L1 Code */ + { 0xEF000000, (PAGE_SIZE_1MB | CPLB_INOCACHE) }, /* AREA DE BOOT */ + { 0xFFB00000, (PAGE_SIZE_1MB | CPLB_INOCACHE) }, + { 0x20300000, (PAGE_SIZE_1MB | CPLB_INOCACHE) }, /* Async Memory Bank 3 */ + { 0x20200000, (PAGE_SIZE_1MB | CPLB_INOCACHE) }, /* Async Memory Bank 2 (Secnd) */ + { 0x20100000, (PAGE_SIZE_1MB | CPLB_INOCACHE) }, /* Async Memory Bank 1 (Prim B) */ + { 0x20000000, (PAGE_SIZE_1MB | CPLB_INOCACHE) }, /* Async Memory Bank 0 (Prim A) */ + + { 0x02400000, (PAGE_SIZE_4MB | CPLB_INOCACHE) }, + { 0x02000000, (PAGE_SIZE_4MB | CPLB_INOCACHE) }, + { 0x00C00000, (PAGE_SIZE_4MB | CPLB_INOCACHE) }, + { 0x00800000, (PAGE_SIZE_4MB | CPLB_INOCACHE) }, + { 0x00400000, (PAGE_SIZE_4MB | CPLB_INOCACHE) }, + { 0x00000000, (PAGE_SIZE_4MB | CPLB_INOCACHE) }, + { 0xffffffff, 0xffffffff } /* end of section - termination */ + +}; + +/* + * Init_PLL + * + * Routine to initialize the PLL. The Ezkit uses a 27 Mhz XTAL. + * See "../eZKit533/include/bsp.h" for more information. + */ +static void Init_PLL (void) +{ + unsigned int n; + + /* Configure PLL registers */ + *((uint16_t*)PLL_LOCKCNT) = 0x1000; + *((uint16_t*)PLL_DIV) = PLL_CSEL|PLL_SSEL; + *((uint16_t*)PLL_CTL) = PLL_MSEL|PLL_DF; + + /* Commands to set PLL values */ + __asm__ ("cli r0;"); + __asm__ ("idle;"); + __asm__ ("sti r0;"); + + /* Delay for PLL stabilization */ + for (n=0; n<200; n++) {} +} + +/* + * Init_EBIU + * + * Configure extern memory + */ +static void Init_EBIU (void) +{ + /* Configure FLASH */ + *((uint32_t*)EBIU_AMBCTL0) = 0x7bb07bb0L; + *((uint32_t*)EBIU_AMBCTL1) = 0x7bb07bb0L; + *((uint16_t*)EBIU_AMGCTL) = 0x000f; + + /* Configure SDRAM + *((uint32_t*)EBIU_SDGCTL) = 0x0091998d; + *((uint16_t*)EBIU_SDBCTL) = 0x0013; + *((uint16_t*)EBIU_SDRRC) = 0x0817; + */ +} + +/* + * Init_Flags + * + * Enable LEDs port + */ +static void Init_Flags(void) +{ + *((uint16_t*)FIO_INEN) = 0x0100; + *((uint16_t*)FIO_DIR) = 0x0000; + *((uint16_t*)FIO_EDGE) = 0x0100; + *((uint16_t*)FIO_MASKA_D) = 0x0100; + + *((uint8_t*)FlashA_PortB_Dir) = 0x3f; + *((uint8_t*)FlashA_PortB_Data) = 0x00; +} + +RTEMS_SYSINIT_ITEM( + bfin_interrupt_init, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); + +void bsp_start( void ) +{ + /* BSP Hardware Initialization*/ + Init_RTC(); /* Blackfin Real Time Clock initialization */ + Init_PLL(); /* PLL initialization */ + Init_EBIU(); /* EBIU initialization */ + Init_Flags(); /* GPIO initialization */ + + int i=0; + for (i=5;i<16;i++) { + set_vector((rtems_isr_entry)bfin_null_isr, i, 1); + } +} + +/* + * Helper Function to use the EzKits LEDS. + * Can be used by the Application. + */ +void setLED (uint8_t value) +{ + *((uint8_t*)FlashA_PortB_Data) = value; +} + +/* + * Helper Function to use the EzKits LEDS + */ +uint8_t getLED (void) +{ + return *((uint8_t*)FlashA_PortB_Data); +} diff --git a/bsps/bfin/eZKit533/start/linkcmds b/bsps/bfin/eZKit533/start/linkcmds new file mode 100644 index 0000000000..e66a599e1f --- /dev/null +++ b/bsps/bfin/eZKit533/start/linkcmds @@ -0,0 +1,172 @@ +OUTPUT_FORMAT("elf32-bfin", "elf32-bfin", + "elf32-bfin") + +OUTPUT_ARCH(bfin) +ENTRY(__start) +STARTUP(start.o) + +/* + * Declare some sizes. + */ +_RamBase = DEFINED(_RamBase) ? _RamBase : 0x0; +_RamSize = DEFINED(_RamSize) ? _RamSize : 0x01000000; +_HeapSize = DEFINED(_HeapSize) ? _HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x1000; + +MEMORY +{ + sdram(rwx) : ORIGIN = 0x00001000, LENGTH = 0x01000000 + l1code(rwx) : ORIGIN = 0xffa08000, LENGTH = 0x00008000 + l1data(rwx) : ORIGIN = 0xff804000, LENGTH = 0x00004000 +} + +SECTIONS +{ + + .l1code : + { + /*jump.o (.text)*/ + } > l1code + + .init : + { + KEEP (*(.init)) + } > sdram /*=0*/ + + .text : + { + CREATE_OBJECT_SYMBOLS + *(.text) + *(.rodata*) + *(.gnu.linkonce.r*) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + ___start_set_sysctl_set = .; + *(set_sysctl_*); + ___stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + _etext = .; + + ___CTOR_LIST__ = .; + LONG((___CTOR_END__ - ___CTOR_LIST__) / 4 - 2) + *(.ctors) + LONG(0) + ___CTOR_END__ = .; + ___DTOR_LIST__ = .; + LONG((___DTOR_END__ - ___DTOR_LIST__) / 4 - 2) + *(.dtors) + LONG(0) + ___DTOR_END__ = .; + } > sdram + + .tdata : { + __TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + __TLS_Data_end = .; + } > sdram + + .tbss : { + __TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + __TLS_BSS_end = .; + } > sdram + + __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)); + + .fini : + { + KEEP (*(.fini)) + } > sdram /*=0*/ + + .data : + { + *(.data) + KEEP (*(SORT(.rtemsrwset.*))) + *(.jcr) + *(.gnu.linkonce.d*) + CONSTRUCTORS + _edata = .; + } > sdram + + .eh_frame : { *(.eh_frame) } > sdram + .data1 : { *(.data1) } > sdram + .eh_frame : { *(.eh_frame) } > sdram + .gcc_except_table : { *(.gcc_except_table*) } > sdram + + .rodata : + { + *(.rodata) + *(.rodata.*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + } > sdram + + + .bss : + { + _bss_start = .; + _clear_start = .; + *(.bss) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (64); + _stack_init = .; + . += _StackSize; + _clear_end = .; + _WorkAreaBase = .; + _end = .; + __end = .; + } > sdram + +/* Debugging stuff follows */ + + /* 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) } + .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) } + /*.stack 0x80000 : { _stack = .; *(.stack) }*/ + /* These must appear regardless of . */ +} + +__HeapSize = _HeapSize; +__edata = _edata; +__etext = _etext; diff --git a/bsps/epiphany/epiphany_sim/start/bsp_specs b/bsps/epiphany/epiphany_sim/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/epiphany/epiphany_sim/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/epiphany/epiphany_sim/start/linkcmds b/bsps/epiphany/epiphany_sim/start/linkcmds new file mode 100644 index 0000000000..07a4c29a32 --- /dev/null +++ b/bsps/epiphany/epiphany_sim/start/linkcmds @@ -0,0 +1,370 @@ +/** + * @file + * + * @ingroup bsp_linker + * + * @brief Memory map + */ + +/* + * + * Copyright (c) 2015 University of York. + * Hesham ALMatary <hmka501@york.ac.uk> + * + * 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. + */ + +OUTPUT_FORMAT("elf32-epiphany", "elf32-epiphany", "elf32-epiphany") +OUTPUT_ARCH (epiphany) + +ENTRY (_start) +STARTUP (start.o) + +MEMORY +{ + VECTOR_RAM (AIW) : ORIGIN = 0x00000000, LENGTH = 0xB0 + LOCAL_MEM (AIW) : ORIGIN = 0x000000B0, LENGTH = 0x00007FC0 /* 32KiB Local memory */ + RAM : ORIGIN = 0x8E000000, LENGTH = 0x01000000 /* 16MiB external RAM */ +} + +REGION_ALIAS ("REGION_START", LOCAL_MEM); +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_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); + +/* The following address is used for text output */ +bsp_section_outbut_buffer = 0x8F800000; +bsp_section_vector_begin = 0x00000000; + +/* + * 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_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_processor_count = DEFINED (_bsp_processor_count) ? _bsp_processor_count : 1; + +SECTIONS { + + .vector : + { + *(.vector) + . = ALIGN(bsp_vector_table_size); + 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 = bsp_section_vector_begin; + bsp_vector_table_end = bsp_vector_table_begin + bsp_vector_table_size; + + .start : + { + . = ALIGN(8); + 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 (bsp_section_xbarrier_align); + } > REGION_VECTOR AT > REGION_VECTOR + +.text : { + . = ALIGN(8); + 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 : { + KEEP (*(.init)) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .fini : { + KEEP (*(.fini)) + . = ALIGN(8); + 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 (bsp_section_robarrier_align); + } > REGION_RODATA AT > REGION_RODATA + +.rodata : { + . = ALIGN(8); + bsp_section_rodata_begin = .; + *(.rodata .rodata.* .gnu.linkonce.r.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD +.eh_frame : { + KEEP (*(.eh_frame)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gcc_except_table : { + *(.gcc_except_table .gcc_except_table.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > REGION_RODATA AT > REGION_RODATA_LOAD + .tbss : { + _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 : { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .init_array : { + 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 : { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .ctors : { + /* 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 : { + 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 : { + *(.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 : { + KEEP (*(.jcr)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .interp : { + *(.interp) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .note.gnu.build-id : { + *(.note.gnu.build-id) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .hash : { + *(.hash) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.hash : { + *(.gnu.hash) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynsym : { + *(.dynsym) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynstr : { + *(.dynstr) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version : { + *(.gnu.version) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version_d : { + *(.gnu.version_d) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version_r : { + *(.gnu.version_r) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rel.dyn : { + *(.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 : { + *(.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.*) + 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 : { + *(.rel.plt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rela.plt : { + *(.rela.plt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .plt : { + *(.plt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .iplt : { + *(.iplt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynamic : { + *(.dynamic) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .got : { + *(.got.plt) *(.igot.plt) *(.got) *(.igot) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rtemsroset : { + /* Special FreeBSD linker set sections */ + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = .; + *(set_domain_*); + *(set_pseudo_*); + + KEEP (*(SORT(.rtemsroset.*))) + . = ALIGN(8); + 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(8); + . = ALIGN (bsp_section_rwbarrier_align); + } > REGION_DATA AT > REGION_DATA + +.data : { + . = ALIGN(8); + bsp_section_data_begin = .; + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } > REGION_DATA AT > REGION_DATA_LOAD + .data1 : { + *(.data1) + } > REGION_DATA AT > REGION_DATA_LOAD + .rtemsrwset : { + KEEP (*(SORT(.rtemsrwset.*))) + . = ALIGN(8); + 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(8); + bsp_section_bss_begin = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(8); + bsp_section_bss_end = .; + } > REGION_BSS AT > REGION_BSS + bsp_section_bss_size = bsp_section_bss_end - bsp_section_bss_begin; + +.work : { + /* + * The work section will occupy the remaining REGION_WORK region and + * contains the RTEMS work space and heap. + */ + . = ALIGN(8); + bsp_section_work_begin = .; + . += ORIGIN (REGION_WORK) + LENGTH (REGION_WORK) - ABSOLUTE (.); + . = ALIGN(8); + bsp_section_work_end = .; + } > REGION_WORK AT > REGION_WORK + bsp_section_work_size = bsp_section_work_end - bsp_section_work_begin; + + .stack : { + . = ALIGN(8); + bsp_section_stack_begin = .; + . += ORIGIN (REGION_STACK) + LENGTH (REGION_STACK) - ABSOLUTE (.); + . = ALIGN(8); + bsp_section_stack_end = .; + } > REGION_STACK AT > REGION_STACK + bsp_section_stack_size = bsp_section_stack_begin - bsp_section_stack_end; + + RamBase = ORIGIN (REGION_WORK); + RamSize = LENGTH (REGION_WORK); + WorkAreaBase = bsp_section_work_begin; + HeapSize = 0; +} diff --git a/bsps/i386/pc386/start/bsp_fatal_halt.c b/bsps/i386/pc386/start/bsp_fatal_halt.c new file mode 100644 index 0000000000..07bbd793e0 --- /dev/null +++ b/bsps/i386/pc386/start/bsp_fatal_halt.c @@ -0,0 +1,24 @@ +/** + * COPYRIGHT (c) 2016. + * 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> + +void _CPU_Fatal_halt(uint32_t source, uint32_t error) +{ + __asm__ volatile ( + "cli\n\t" + "movl %0,%%eax\n\t" + "hlt\n\t" + : "=r" ((error)) + : "0" ((error)) + ); + #ifdef __GNUC__ + __builtin_unreachable(); + #endif +} diff --git a/bsps/i386/pc386/start/bsp_specs b/bsps/i386/pc386/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/i386/pc386/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/i386/pc386/start/bspcmdline.c b/bsps/i386/pc386/start/bspcmdline.c new file mode 100644 index 0000000000..d617863198 --- /dev/null +++ b/bsps/i386/pc386/start/bspcmdline.c @@ -0,0 +1,60 @@ +/*-------------------------------------------------------------------------+ +| This file contains the PC386 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. ++--------------------------------------------------------------------------+ +| (C) Copyright 2009 RTEMS Project +| Chris Johns (chrisj@rtems.org) ++--------------------------------------------------------------------------+ +| Disclaimer: +| +| This file is provided "AS IS" without warranty of any kind, either +| expressed or implied. ++--------------------------------------------------------------------------+ +| This code is based on: +| common sense +| With the following copyright notice: +| ************************************************************************** +| * COPYRIGHT (c) 1989-2008. +| * 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 <rtems/pci.h> +#include <libcpu/cpuModel.h> + +/* + * External data + */ +extern uint32_t _boot_multiboot_flags; +extern uint32_t _boot_multiboot_memory[2]; +extern const char _boot_multiboot_cmdline[256]; + +/*-------------------------------------------------------------------------+ +| Function: bsp_cmdline +| Description: Call when you want the command line. +| Global Variables: The multiboot values copied from the loader. +| Arguments: None. +| Returns: The whole command line. ++--------------------------------------------------------------------------*/ +const char* bsp_cmdline( void ) +{ + return _boot_multiboot_cmdline; +} + +/*-------------------------------------------------------------------------+ +| Function: bsp_cmdline_arg +| Description: Call to search for an argument. +| Global Variables: The multiboot values copied from the loader. +| Arguments: The option start. +| Returns: The option if found or nothing. ++--------------------------------------------------------------------------*/ +const char* bsp_cmdline_arg( const char* arg ) +{ + return strstr (bsp_cmdline (), arg); +} diff --git a/bsps/i386/pc386/start/bspgetworkarea.c b/bsps/i386/pc386/start/bspgetworkarea.c new file mode 100644 index 0000000000..21cb472607 --- /dev/null +++ b/bsps/i386/pc386/start/bspgetworkarea.c @@ -0,0 +1,135 @@ +/* + * This routine is an implementation of the bsp_work_area_initialize() + * that can be used by all m68k BSPs following linkcmds conventions + * regarding heap, stack, and workspace allocation. + * + * COPYRIGHT (c) 1989-2008. + * 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. + */ + +/* #define BSP_GET_WORK_AREA_DEBUG */ +#include <bsp.h> +#include <bsp/bootcard.h> + +#ifdef BSP_GET_WORK_AREA_DEBUG + #include <rtems/bspIo.h> +#endif + +/* + * These are provided by the linkcmds. + */ +extern char WorkAreaBase[]; +extern char HeapSize[]; +extern char RamSize[]; + +/* rudimentary multiboot info */ +struct multiboot_info { + uint32_t flags; /* start.S only raises flags for items actually */ + /* saved; this allows us to check for the size */ + /* of the data structure. */ + uint32_t mem_lower; /* avail kB in lower memory */ + uint32_t mem_upper; /* avail kB in lower memory */ + /* ... (unimplemented) */ +}; + +extern struct multiboot_info _boot_multiboot_info; + +/* + * This is the first address of the memory we can use for the RTEMS + * Work Area. + */ +static uintptr_t rtemsWorkAreaStart; + +/* + * Board's memory size easily be overridden by application. + */ +uint32_t bsp_mem_size = 0; + +/* Size of stack used during initialization. Defined in 'start.s'. */ +extern uint32_t _stack_size; + +static void bsp_size_memory(void) +{ + uintptr_t topAddr; + + /* Set the value of start of free memory. */ + rtemsWorkAreaStart = (uint32_t)WorkAreaBase + _stack_size; + + /* Align the RTEMS Work Area at beginning of free memory. */ + if (rtemsWorkAreaStart & (CPU_ALIGNMENT - 1)) /* not aligned => align it */ + rtemsWorkAreaStart = (rtemsWorkAreaStart+CPU_ALIGNMENT) & ~(CPU_ALIGNMENT-1); + + /* The memory detection algorithm is very crude; try + * to use multiboot info, if possible (set from start.S) + */ + if ( ((uintptr_t)RamSize == (uintptr_t) 0xFFFFFFFF) && + (_boot_multiboot_info.flags & 1) && + _boot_multiboot_info.mem_upper ) { + topAddr = _boot_multiboot_info.mem_upper * 1024; + #ifdef BSP_GET_WORK_AREA_DEBUG + printk( "Multiboot info says we have 0x%08x\n", topAddr ); + #endif + } else if ( (uintptr_t) RamSize == (uintptr_t) 0xFFFFFFFF ) { + uintptr_t lowest; + uint32_t val; + int i; + + /* + * We have to dynamically size memory. Memory size can be anything + * between no less than 2M and 2048M. If we can write a value to + * an address and read the same value back, then the memory is there. + * + * WARNING: This can detect memory which should be reserved for + * graphics controllers which share the CPU's RAM. + */ + + /* find the lowest 1M boundary to probe */ + lowest = ((rtemsWorkAreaStart + (1<<20)) >> 20) + 1; + if ( lowest < 2 ) + lowest = 2; + + for (i=2048; i>=lowest; i--) { + topAddr = i*1024*1024 - 4; + *(volatile uint32_t*)topAddr = topAddr; + } + + for(i=lowest; i<=2048; i++) { + topAddr = i*1024*1024 - 4; + val = *(volatile uint32_t*)topAddr; + if (val != topAddr) { + break; + } + } + + topAddr = (i-1)*1024*1024; + #ifdef BSP_GET_WORK_AREA_DEBUG + printk( "Dynamically sized to 0x%08x\n", topAddr ); + #endif + } else { + topAddr = (uintptr_t) RamSize; + #ifdef BSP_GET_WORK_AREA_DEBUG + printk( "hardcoded to 0x%08x\n", topAddr ); + #endif + } + + bsp_mem_size = topAddr; +} + +void bsp_work_area_initialize(void) +{ + void *area_start; + uintptr_t area_size; + + /* + * We need to determine how much memory there is in the system. + */ + bsp_size_memory(); + + area_start = (void *) rtemsWorkAreaStart; + area_size = (uintptr_t) bsp_mem_size - (uintptr_t) rtemsWorkAreaStart; + bsp_work_area_initialize_default( area_start, area_size ); +} diff --git a/bsps/i386/pc386/start/bspidle.S b/bsps/i386/pc386/start/bspidle.S new file mode 100644 index 0000000000..740671afc1 --- /dev/null +++ b/bsps/i386/pc386/start/bspidle.S @@ -0,0 +1,19 @@ +/* + * Idle Thread Body + * + * COPYRIGHT (c) 2016. + * 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/asm.h> + +.p2align 4 + +PUBLIC(bsp_idle_thread) +SYM(bsp_idle_thread): +hltloop: hlt + jmp hltloop diff --git a/bsps/i386/pc386/start/bspreset.c b/bsps/i386/pc386/start/bspreset.c new file mode 100644 index 0000000000..0fbcd0f201 --- /dev/null +++ b/bsps/i386/pc386/start/bspreset.c @@ -0,0 +1,18 @@ +/* + * COPYRIGHT (c) 1989-2017. + * 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.h> +#include <bsp/bootcard.h> + +void bsp_reset(void) +{ + /* shutdown and reboot */ + outport_byte(0x64, 0xFE); /* use keyboard controller */ +} diff --git a/bsps/i386/pc386/start/bspstart.c b/bsps/i386/pc386/start/bspstart.c new file mode 100644 index 0000000000..db1ca90cf4 --- /dev/null +++ b/bsps/i386/pc386/start/bspstart.c @@ -0,0 +1,141 @@ +/** + * @file + * + * This file contains the PC386 BSP startup package. It includes application, + * board, and monitor specific initialization and configuration. + */ + +/* + * This file was initially written by Joel Sherrill as part of the go32 BSP. + * It was subsequently adapted as part of the pc386 BSP by developers from + * the NavIST Group in 1997. + * + * Copyright (c) 2016. + * Chris Johns <chrisj@rtems.org> + * + * COPYRIGHT (c) 1989-2008, 2016. + * 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. + * + * (C) Copyright 1997 - + * - NavIST Group - Real-Time Distributed Systems and Industrial Automation + * Instituto Superior Tecnico * Lisboa * PORTUGAL (http://pandora.ist.utl.pt) + * + * NavISY Disclaimer: + * This file is provided "AS IS" without warranty of any kind, either + * expressed or implied. + */ + +#include <bsp.h> +#include <bsp/bspimpl.h> +#include <bsp/irq.h> +#include <rtems/pci.h> +#include <libcpu/cpuModel.h> + +/* + * PCI Bus Configuration + */ +rtems_pci_config_t BSP_pci_configuration = { + (volatile unsigned char*)0, + (volatile unsigned char*)0, + NULL +}; + +/* + * Helper to initialize the PCI Bus + */ +static void bsp_pci_initialize_helper(void) +{ + const pci_config_access_functions *pci_accessors; + + pci_accessors = pci_bios_initialize(); + if (pci_accessors != NULL) { + printk("PCI bus: using PCI BIOS interface\n"); + BSP_pci_configuration.pci_functions = pci_accessors; + return; + } + + pci_accessors = pci_io_initialize(); + if (pci_accessors != NULL) { + printk("PCI bus: using PCI I/O interface\n"); + BSP_pci_configuration.pci_functions = pci_accessors; + return; + } + + printk("PCI bus: could not initialize PCI BIOS interface\n"); +} + +/*-------------------------------------------------------------------------+ +| Function: bsp_start +| Description: Called before main is invoked. +| Global Variables: None. +| Arguments: None. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +static void bsp_start_default( void ) +{ + /* + * Turn off watchdog + */ + /* + * Calibrate variable for 1ms-loop (see timer.c) + */ + Calibrate_loop_1ms(); + + /* + * Init rtems interrupt management + */ + rtems_irq_mngt_init(); + + /* + * Init rtems exceptions management + */ + rtems_exception_init_mngt(); + + /* + * init PCI Bios interface... + */ + bsp_pci_initialize_helper(); + + /* + * Probe for legacy UARTs. + */ + legacy_uart_probe(); + + /* + * Probe for UARTs on PCI. + */ + pci_uart_probe(); + + /* + * Parse the GDB arguments and flag a serial port as not valid. This stops + * the console from claming the port. + */ +#if BSP_GDB_STUB + pc386_parse_gdb_arguments(); +#endif + + /* + * Figure out where printk() and console IO is to be directed. Do this after + * the legacy and PCI bus probes so we have a chance for those devices to be + * added to the set in the console driver. In general, do it as early as + * possible so printk() has a chance to work early on devices found via PCI + * probe. + */ + pc386_parse_console_arguments(); + + Clock_driver_install_handler(); + +#if BSP_ENABLE_IDE + bsp_ide_cmdline_init(); +#endif +} /* bsp_start_default */ + +/* + * 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/i386/pc386/start/ldsegs.S b/bsps/i386/pc386/start/ldsegs.S new file mode 100644 index 0000000000..b56bf836f0 --- /dev/null +++ b/bsps/i386/pc386/start/ldsegs.S @@ -0,0 +1,238 @@ +/*-------------------------------------------------------------------------+ +| ldsegs.s v1.1 - PC386 BSP - 1997/08/07 ++--------------------------------------------------------------------------+ +| This file assists the board independent startup code by loading the proper +| segment register values. The values loaded are board dependent. In addition +| it contains code to enable the A20 line and to reprogram the PIC to relocate +| the IRQ interrupt vectors to 0x20 -> 0x2f. +| NOTE: No stack has been established when this routine is invoked. +| It returns by jumping back to bspentry. ++--------------------------------------------------------------------------+ +| (C) Copyright 1997 - +| - NavIST Group - Real-Time Distributed Systems and Industrial Automation +| +| http://pandora.ist.utl.pt +| +| Instituto Superior Tecnico * Lisboa * PORTUGAL ++--------------------------------------------------------------------------+ +| Disclaimer: +| +| This file is provided "AS IS" without warranty of any kind, either +| expressed or implied. ++--------------------------------------------------------------------------+ +| This code is base on: +| ldsegs.s,v 1.4 1996/04/20 16:48:30 joel Exp - go32 BSP +| With the following copyright notice: +| ************************************************************************** +| * COPYRIGHT (c) 1989-1999. +| * 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/asm.h> +#include <bsp/tblsizes.h> /* contains sizes of GDT and IDT */ +#include <bspopts.h> + +/*----------------------------------------------------------------------------+ +| CODE section ++----------------------------------------------------------------------------*/ +EXTERN (rtems_i8259_masks) + +BEGIN_CODE + + EXTERN (_establish_stack) + EXTERN (Timer_exit) + EXTERN (clockOff) + +/*----------------------------------------------------------------------------+ +| pc386_delay ++------------------------------------------------------------------------------ +| Delay is needed after doing I/O. +| +| The outb version is OK on most machines BUT the loop version ... +| +| will delay for 1us on 1Gz machine, it will take a little bit +| longer on slower machines, however, it does not matter because we +| are going to call this function only a few times + ++----------------------------------------------------------------------------*/ +#define DELAY_USE_OUTB + + .p2align 4 + .globl _pc386_delay + .globl pc386_delay +pc386_delay: +_pc386_delay: +#ifdef DELAY_USE_OUTB + outb al, $0x80 # about 1uS delay on most machines +#else + movl $0x200, eax +pc386_delay1: + dec eax + jnz pc386_delay1 +#endif + ret + +/*-------------------------------------------------------------------------+ +| Function: _load_segments +| Description: Current environment is standard PC booted by grub. +| So, there is no value in saving current GDT and IDT +| settings we have to set it up ourseves. (Naturally +| it will be not so in case we are booted by some +| boot monitor, however, then it will be different +| BSP). After that we have to load board segment registers +| with apropriate values + reprogram PIC. +| Global Variables: None. +| Arguments: None. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ + .p2align 4 + + PUBLIC (_load_segments) +SYM (_load_segments): + + lgdt SYM(gdtdesc) + lidt SYM(IDT_Descriptor) + + /* Load CS, flush prefetched queue */ + ljmp $0x8, $next_step + +next_step: + /* Load segment registers */ + movw $0x10, ax + movw ax, ss + movw ax, ds + movw ax, es + movw ax, fs + movw ax, gs + +/*---------------------------------------------------------------------+ +| Now we have to reprogram the interrupts :-(. We put them right after +| the intel-reserved hardware interrupts, at int 0x20-0x2F. There they +| won't mess up anything. Sadly IBM really messed this up with the +| original PC, and they haven't been able to rectify it afterwards. Thus +| the bios puts interrupts at 0x08-0x0f, which is used for the internal +| hardware interrupts as well. We just have to reprogram the 8259's, and +| it isn't fun. ++---------------------------------------------------------------------*/ + + movb $0x11, al /* initialization sequence */ + outb al, $0x20 /* send it to 8259A-1 */ + call SYM(pc386_delay) + outb al, $0xA0 /* and to 8259A-2 */ + call SYM(pc386_delay) + + movb $0x20, al /* start of hardware int's (0x20) */ + outb al, $0x21 + call SYM(pc386_delay) + movb $0x28, al /* start of hardware int's 2 (0x28) */ + outb al, $0xA1 + call SYM(pc386_delay) + + movb $0x04, al /* 8259-1 is master */ + outb al, $0x21 + call SYM(pc386_delay) + movb $0x02, al /* 8259-2 is slave */ + outb al, $0xA1 + call SYM(pc386_delay) + + movb $0x01, al /* 8086 mode for both */ + outb al, $0x21 + call SYM(pc386_delay) + outb al, $0xA1 + call SYM(pc386_delay) + + /* + * The IMR values must correspond to the initial value of i8259s_cache. + */ + movb $0xFF, al /* mask off all interrupts for now */ + outb al, $0xA1 + call SYM(pc386_delay) + movb $0xFB, al /* mask all irq's but irq2 which */ + outb al, $0x21 /* is cascaded */ + call SYM(pc386_delay) + jmp SYM (_establish_stack) # return to the bsp entry code + +/*-------------------------------------------------------------------------+ +| Function: _default_int_handler +| Description: default interrupt handler +| Global Variables: None. +| Arguments: None. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ + .p2align 4 + +/*---------------------------------------------------------------------------+ +| GDT itself ++--------------------------------------------------------------------------*/ +#if GDT_SIZE < NUM_SYSTEM_GDT_DESCRIPTORS +#error "GDT_SIZE must be at least NUM_SYSTEM_GDT_DESCRIPTORS" +#endif + +BEGIN_DATA + .p2align 4 + + PUBLIC (_Global_descriptor_table) +SYM (_Global_descriptor_table): + + /* NULL segment */ + .word 0, 0 + .byte 0, 0, 0, 0 + + /* code segment */ + .word 0xffff, 0 + .byte 0, 0x9e, 0xcf, 0 + + /* data segment */ + .word 0xffff, 0 + .byte 0, 0x92, 0xcf, 0 + + /* gs segment */ + .word 0xffff, 0 + .byte 0, 0x92, 0xcf, 0 + + /* allocated space for user segments */ + .rept (GDT_SIZE - NUM_SYSTEM_GDT_DESCRIPTORS) + .word 0,0,0,0 + .endr + +/*---------------------------------------------------------------------------+ +| Descriptor of GDT ++--------------------------------------------------------------------------*/ + PUBLIC(gdtdesc) +SYM(gdtdesc): + .word (GDT_SIZE*8 - 1) + .long SYM (_Global_descriptor_table) + +/*---------------------------------------------------------------------------+ +| IDT itself ++---------------------------------------------------------------------------*/ + .p2align 4 + + PUBLIC(Interrupt_descriptor_table) +SYM(Interrupt_descriptor_table): + .rept IDT_SIZE + .word 0,0,0,0 + .endr + +/*---------------------------------------------------------------------------+ +| Descriptor of IDT ++--------------------------------------------------------------------------*/ + + .p2align 4 + PUBLIC(IDT_Descriptor) +SYM(IDT_Descriptor): + .word (IDT_SIZE*8 - 1) + .long SYM (Interrupt_descriptor_table) + +END_DATA + + .section .m_hdr + .long 0x1BADB002 + .long 0 + .long 0xE4524FFE +END diff --git a/bsps/i386/pc386/start/linkcmds b/bsps/i386/pc386/start/linkcmds new file mode 100644 index 0000000000..5fc3444c9e --- /dev/null +++ b/bsps/i386/pc386/start/linkcmds @@ -0,0 +1,253 @@ +/* + * Copy of default "default linker script, for normal executables" + * provided with binutils 2.18 with minor modifications for use + * as pc386 linkcmds. These changes include: + * + * + sections commented out marked with "XXX commented out --joel" + * + addition of m_hdr section + * + addition of FreeBSD sysctl sections + */ + +/* + * XXX commented out --joel +OUTPUT_FORMAT("elf32-i386", "elf32-i386", + "elf32-i386") +OUTPUT_ARCH(i386) +*/ +STARTUP(start.o) +ENTRY(start) +HeapSize = DEFINED(HeapSize) ? HeapSize : + DEFINED(_HeapSize) ? _HeapSize : 0x0; +RamSize = DEFINED(RamSize) ? RamSize : + DEFINED(_RamSize) ? _RamSize : 0xFFFFFFFF; + +SECTIONS +{ + /* Read-only sections, merged into text segment: */ +/* + * XXX commented out --joel + PROVIDE (__executable_start = 0x08048000); . = 0x08048000 + SIZEOF_HEADERS; +*/ + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } + .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } + .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } + .rel.data.rel.ro : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) } + .rela.data.rel.ro : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) } + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } + .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } + .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } + .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } + .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } + .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .plt : { *(.plt) } + .text : + { + *(.m_hdr) + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + + } =0x90909090 + + .rtemsroset : { + /* for pre rtems-libbsd FreeBSD code */ + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = .; + *(set_domain_*); + *(set_pseudo_*); + + KEEP (*(SORT(.rtemsroset.*))) + } =0x90909090 + + .init : + { + KEEP (*(.init)) + } =0x90909090 + .fini : + { + KEEP (*(.fini)) + } =0x90909090 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } + _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)); + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* 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)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got) } + . = DATA_SEGMENT_RELRO_END (12, .); + .got.plt : { *(.got.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + .rtemsrwset : { KEEP (*(SORT(.rtemsrwset.*))) } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + _end = .; PROVIDE (end = .); + . = ALIGN(0x10); + WorkAreaBase = .; + . = DATA_SEGMENT_END (.); + + /* 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) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) } +} diff --git a/bsps/lm32/lm32_evr/start/bsp_specs b/bsps/lm32/lm32_evr/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/lm32/lm32_evr/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/lm32/lm32_evr/start/linkcmds b/bsps/lm32/lm32_evr/start/linkcmds new file mode 100644 index 0000000000..63747f33dc --- /dev/null +++ b/bsps/lm32/lm32_evr/start/linkcmds @@ -0,0 +1,309 @@ +OUTPUT_FORMAT("elf32-lm32", "elf32-lm32", + "elf32-lm32") +OUTPUT_ARCH(lm32) +ENTRY(start) +STARTUP(start.o) +/* Do we need any of these for elf? + __DYNAMIC = 0; */ + +/* + * Declare some sizes. Heap is sized at whatever ram space is left. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x08000000; +RamSize = DEFINED(RamSize) ? RamSize : 32M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 2M; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x2000; + +PROVIDE (__stack = 0); +MEMORY { + ebr : ORIGIN = 0x04000000 , LENGTH = 32k + sdram : ORIGIN = 0x08000000 , LENGTH = 32M +} +SECTIONS +{ + .boot : + { + KEEP (*(.boot)) + } > ebr + + /* Read-only sections, merged into text segment: */ + .interp : { *(.interp) } > sdram + .hash : { *(.hash) } > sdram + .dynsym : { *(.dynsym) } > sdram + .dynstr : { *(.dynstr) } > sdram + .gnu.version : { *(.gnu.version) } > sdram + .gnu.version_d : { *(.gnu.version_d) } > sdram + .gnu.version_r : { *(.gnu.version_r) } > sdram + .rela.text : + { *(.rela.text) *(.rela.gnu.linkonce.t*) } > sdram + .rela.data : + { *(.rela.data) *(.rela.gnu.linkonce.d*) } > sdram + .rela.rodata : + { *(.rela.rodata*) *(.rela.gnu.linkonce.r*) } > sdram + .rela.got : { *(.rela.got) } > sdram + .rela.got1 : { *(.rela.got1) } > sdram + .rela.got2 : { *(.rela.got2) } > sdram + .rela.ctors : { *(.rela.ctors) } > sdram + .rela.dtors : { *(.rela.dtors) } > sdram + .rela.init : { *(.rela.init) } > sdram + .rela.fini : { *(.rela.fini) } > sdram + .rela.bss : { *(.rela.bss) } > sdram + .rela.plt : { *(.rela.plt) } > sdram + .rela.sdata : { *(.rela.sdata) } > sdram + .rela.sbss : { *(.rela.sbss) } > sdram + .rela.sdata2 : { *(.rela.sdata2) } > sdram + .rela.sbss2 : { *(.rela.sbss2) } > sdram + .rela.dyn : { *(.rela.dyn) } > sdram + + .init : { KEEP(*(.init)) } > sdram + + .text : + { + *(.text*) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } > sdram + + .fini : { _fini = .; KEEP(*(.fini)) } > sdram + + .rodata : { *(.rodata*) KEEP (*(SORT(.rtemsroset.*))) *(.gnu.linkonce.r*) } > sdram + .rodata1 : { *(.rodata1) } > sdram + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > sdram + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } > sdram + _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)); + + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(0x10000) + (. & (0x10000 - 1)); + /* Ensure the __preinit_array_start label is properly aligned. We + could instead move the label definition inside the section, but + the linker would then create the section even if it turns out to + be empty, which isn't pretty. */ + . = ALIGN(32 / 8); + PROVIDE (__preinit_array_start = .); + .preinit_array : { *(.preinit_array) } >sdram + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + .init_array : { *(.init_array) } >sdram + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + .fini_array : { *(.fini_array) } >sdram + PROVIDE (__fini_array_end = .); + +/* _SDA2_BASE_ = __SDATA2_START__ + 0x8000; */ + .sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } >sdram + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + /* avoid empty sdata2/sbss2 area -- __eabi would not set up r2 + * which may be important if run-time loading is used + */ + . += 1; + } >sdram + .eh_frame : { *.(eh_frame) } >sdram + + /* NOTE: if the BSP uses page tables, the correctness of + * '_etext' (and __DATA_START__) is CRUCIAL - otherwise, + * an invalid mapping may result!!! + */ + _etext = .; + PROVIDE (etext = .); + + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. It would + be more correct to do this: + . = ALIGN(0x40000) + (ALIGN(8) & (0x40000 - 1)); + The current expression does not correctly handle the case of a + text segment ending precisely at the end of a page; it causes the + data segment to skip a page. The above expression does not have + this problem, but it will currently (2/95) cause BFD to allocate + a single segment, combining both text and data, for this case. + This will prevent the text segment from being shared among + multiple executions of the program; I think that is more + important than losing a page of the virtual address space (note + that no actual memory is lost; the page which is skipped can not + be referenced). */ + . = ALIGN(0x1000); + .data ALIGN(0x1000) : + { + /* NOTE: if the BSP uses page tables, the correctness of + * '__DATA_START__' (and _etext) is CRUCIAL - otherwise, + * an invalid mapping may result!!! + */ + PROVIDE(__DATA_START__ = ABSOLUTE(.) ); + *(.data .data.* .gnu.linkonce.d*) + KEEP (*(SORT(.rtemsrwset.*))) + SORT(CONSTRUCTORS) + } > sdram + .data1 : { *(.data1) } > sdram + PROVIDE (__EXCEPT_START__ = .); + .gcc_except_table : { + *(.gcc_except_table) + *(.gcc_except_table.*) + } > sdram + PROVIDE (__EXCEPT_END__ = .); + .got1 : { *(.got1) } > sdram + /* Put .ctors and .dtors next to the .got2 section, so that the pointers + get relocated with -mrelocatable. Also put in the .fixup pointers. + The current compiler no longer needs this, but keep it around for 2.7.2 */ + PROVIDE (_GOT2_START_ = .); + .got2 : { *(.got2) } > sdram + .dynamic : { *(.dynamic) } > sdram + + .ctors : + { + /* 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)) + /* We don't want to include the .ctor section from + 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 ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } > sdram + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } > sdram + + + PROVIDE (_FIXUP_START_ = .); + .fixup : { *(.fixup) } > sdram + PROVIDE (_FIXUP_END_ = .); + PROVIDE (_GOT2_END_ = .); + PROVIDE (_GOT_START_ = .); + + .got : { *(.got) } > sdram + .got.plt : { *(.got.plt) } > sdram + + PROVIDE (_GOT_END_ = .); + + .jcr : { KEEP (*(.jcr)) } > sdram + + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ +/* _SDA_BASE_ = __SDATA_START__ + 0x8000; */ + .sdata : { *(.sdata*) *(.gnu.linkonce.s.*) } >sdram + _edata = .; + _gp = .; + PROVIDE (edata = .); + .sbss : + { + _clear_start = .; + PROVIDE (__sbss_start = .); + *(.dynsbss) + *(.sbss* .gnu.linkonce.sb.*) + *(.scommon) + /* avoid empty sdata/sbss area -- __eabi would not set up r13 + * which may be important if run-time loading is used + */ + . += 1; + . = ALIGN(16); + PROVIDE (__sbss_end = .); + } > sdram + .plt : { *(.plt) } > sdram + .bss : + { + PROVIDE (__bss_start = .); + *(.dynbss) + *(.bss .bss* .gnu.linkonce.b*) + *(COMMON) + . = ALIGN(16); + _end = . ; + __rtems_end = . ; + PROVIDE (end = .); + + . += _StackSize; + _fstack = .; + + WorkAreaBase = .; + + . = ALIGN (16); + _stack_init = .; + _clear_end = .; + + } > sdram + + + /DISCARD/ : + { + *(.comment) + } + + + /* 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) } + .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) } + /* These must appear regardless of . */ +} diff --git a/bsps/lm32/milkymist/start/bsp_specs b/bsps/lm32/milkymist/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/lm32/milkymist/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/lm32/milkymist/start/bspclean.c b/bsps/lm32/milkymist/start/bspclean.c new file mode 100644 index 0000000000..b010292d06 --- /dev/null +++ b/bsps/lm32/milkymist/start/bspclean.c @@ -0,0 +1,61 @@ +/* + * Milkymist shutdown routine + */ + +/* + * COPYRIGHT (c) 2010 Sebastien Bourdeauducq + * + * 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 "../include/system_conf.h" + +static void reboot(void) +{ + /* Writing to CSR_SYSTEM_ID causes a system reset */ + MM_WRITE(MM_SYSTEM_ID, 1); +} + +static void icap_write(int val, unsigned int w) +{ + while (!(MM_READ(MM_ICAP) & ICAP_READY)); + if (!val) + w |= ICAP_CE|ICAP_WRITE; + MM_WRITE(MM_ICAP, w); +} + +static void reconf(void) +{ + icap_write(0, 0xffff); /* dummy word */ + icap_write(0, 0xffff); /* dummy word */ + icap_write(0, 0xffff); /* dummy word */ + icap_write(0, 0xffff); /* dummy word */ + icap_write(1, 0xaa99); /* sync word part 1 */ + icap_write(1, 0x5566); /* sync word part 2 */ + icap_write(1, 0x30a1); /* write to command register */ + icap_write(1, 0x0000); /* null command */ + icap_write(1, 0x30a1); /* write to command register */ + icap_write(1, 0x000e); /* reboot command */ + icap_write(1, 0x2000); /* NOP */ + icap_write(1, 0x2000); /* NOP */ + icap_write(1, 0x2000); /* NOP */ + icap_write(1, 0x2000); /* NOP */ + icap_write(0, 0x1111); /* NULL */ + icap_write(0, 0xffff); /* dummy word */ +} + +void bsp_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code error +) +{ + if (source == RTEMS_FATAL_SOURCE_EXIT && error) + reconf(); + else + reboot(); +} diff --git a/bsps/lm32/milkymist/start/linkcmds b/bsps/lm32/milkymist/start/linkcmds new file mode 100644 index 0000000000..9c38414238 --- /dev/null +++ b/bsps/lm32/milkymist/start/linkcmds @@ -0,0 +1,308 @@ +OUTPUT_FORMAT("elf32-lm32", "elf32-lm32", + "elf32-lm32") +OUTPUT_ARCH(lm32) +ENTRY(start) +STARTUP(start.o) +/* Do we need any of these for elf? + __DYNAMIC = 0; */ + +/* + * Declare some sizes. Heap is sized at whatever ram space is left. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x40000000; +RamSize = DEFINED(RamSize) ? RamSize : 128M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 92M; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x2000; + +PROVIDE (__stack = 0); +MEMORY { + sdram : ORIGIN = 0x40000000 , LENGTH = 128M +} +SECTIONS +{ + .boot : + { + KEEP (*(.boot)) + } > sdram + + /* Read-only sections, merged into text segment: */ + .interp : { *(.interp) } > sdram + .hash : { *(.hash) } > sdram + .dynsym : { *(.dynsym) } > sdram + .dynstr : { *(.dynstr) } > sdram + .gnu.version : { *(.gnu.version) } > sdram + .gnu.version_d : { *(.gnu.version_d) } > sdram + .gnu.version_r : { *(.gnu.version_r) } > sdram + .rela.text : + { *(.rela.text) *(.rela.gnu.linkonce.t*) } > sdram + .rela.data : + { *(.rela.data) *(.rela.gnu.linkonce.d*) } > sdram + .rela.rodata : + { *(.rela.rodata*) *(.rela.gnu.linkonce.r*) } > sdram + .rela.got : { *(.rela.got) } > sdram + .rela.got1 : { *(.rela.got1) } > sdram + .rela.got2 : { *(.rela.got2) } > sdram + .rela.ctors : { *(.rela.ctors) } > sdram + .rela.dtors : { *(.rela.dtors) } > sdram + .rela.init : { *(.rela.init) } > sdram + .rela.fini : { *(.rela.fini) } > sdram + .rela.bss : { *(.rela.bss) } > sdram + .rela.plt : { *(.rela.plt) } > sdram + .rela.sdata : { *(.rela.sdata) } > sdram + .rela.sbss : { *(.rela.sbss) } > sdram + .rela.sdata2 : { *(.rela.sdata2) } > sdram + .rela.sbss2 : { *(.rela.sbss2) } > sdram + .rela.dyn : { *(.rela.dyn) } > sdram + + .init : { KEEP(*(.init)) } > sdram + + .text : + { + *(.text*) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } > sdram + + .fini : { _fini = .; KEEP(*(.fini)) } > sdram + + .rodata : { *(.rodata*) KEEP (*(SORT(.rtemsroset.*))) *(.gnu.linkonce.r*) } > sdram + .rodata1 : { *(.rodata1) } > sdram + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > sdram + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } > sdram + _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)); + + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(0x10000) + (. & (0x10000 - 1)); + /* Ensure the __preinit_array_start label is properly aligned. We + could instead move the label definition inside the section, but + the linker would then create the section even if it turns out to + be empty, which isn't pretty. */ + . = ALIGN(32 / 8); + PROVIDE (__preinit_array_start = .); + .preinit_array : { *(.preinit_array) } >sdram + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + .init_array : { *(.init_array) } >sdram + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + .fini_array : { *(.fini_array) } >sdram + PROVIDE (__fini_array_end = .); + +/* _SDA2_BASE_ = __SDATA2_START__ + 0xe000; */ + .sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } >sdram + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + /* avoid empty sdata2/sbss2 area -- __eabi would not set up r2 + * which may be important if run-time loading is used + */ + . += 1; + } >sdram + .eh_frame : { *.(eh_frame) } >sdram + + /* NOTE: if the BSP uses page tables, the correctness of + * '_etext' (and __DATA_START__) is CRUCIAL - otherwise, + * an invalid mapping may result!!! + */ + _etext = .; + PROVIDE (etext = .); + + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. It would + be more correct to do this: + . = ALIGN(0x40000) + (ALIGN(8) & (0x40000 - 1)); + The current expression does not correctly handle the case of a + text segment ending precisely at the end of a page; it causes the + data segment to skip a page. The above expression does not have + this problem, but it will currently (2/95) cause BFD to allocate + a single segment, combining both text and data, for this case. + This will prevent the text segment from being shared among + multiple executions of the program; I think that is more + important than losing a page of the virtual address space (note + that no actual memory is lost; the page which is skipped can not + be referenced). */ + . = ALIGN(0x1000); + .data ALIGN(0x1000) : + { + /* NOTE: if the BSP uses page tables, the correctness of + * '__DATA_START__' (and _etext) is CRUCIAL - otherwise, + * an invalid mapping may result!!! + */ + PROVIDE(__DATA_START__ = ABSOLUTE(.) ); + *(.data .data.* .gnu.linkonce.d*) + KEEP (*(SORT(.rtemsrwset.*))) + SORT(CONSTRUCTORS) + } > sdram + .data1 : { *(.data1) } > sdram + PROVIDE (__EXCEPT_START__ = .); + .gcc_except_table : { + *(.gcc_except_table) + *(.gcc_except_table.*) + } > sdram + PROVIDE (__EXCEPT_END__ = .); + .got1 : { *(.got1) } > sdram + /* Put .ctors and .dtors next to the .got2 section, so that the pointers + get relocated with -mrelocatable. Also put in the .fixup pointers. + The current compiler no longer needs this, but keep it around for 2.7.2 */ + PROVIDE (_GOT2_START_ = .); + .got2 : { *(.got2) } > sdram + .dynamic : { *(.dynamic) } > sdram + + .ctors : + { + /* 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)) + /* We don't want to include the .ctor section from + 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 ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } > sdram + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } > sdram + + + PROVIDE (_FIXUP_START_ = .); + .fixup : { *(.fixup) } > sdram + PROVIDE (_FIXUP_END_ = .); + PROVIDE (_GOT2_END_ = .); + PROVIDE (_GOT_START_ = .); + + .got : { *(.got) } > sdram + .got.plt : { *(.got.plt) } > sdram + + PROVIDE (_GOT_END_ = .); + + .jcr : { KEEP (*(.jcr)) } > sdram + + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ +/* _SDA_BASE_ = __SDATA_START__ + 0xe000; */ + .sdata : { *(.sdata*) *(.gnu.linkonce.s.*) } >sdram + _edata = .; + _gp = .; + PROVIDE (edata = .); + .sbss : + { + _clear_start = .; + PROVIDE (__sbss_start = .); + *(.dynsbss) + *(.sbss* .gnu.linkonce.sb.*) + *(.scommon) + /* avoid empty sdata/sbss area -- __eabi would not set up r13 + * which may be important if run-time loading is used + */ + . += 1; + . = ALIGN(16); + PROVIDE (__sbss_end = .); + } > sdram + .plt : { *(.plt) } > sdram + .bss : + { + PROVIDE (__bss_start = .); + *(.dynbss) + *(.bss .bss* .gnu.linkonce.b*) + *(COMMON) + . = ALIGN(16); + _end = . ; + __rtems_end = . ; + PROVIDE (end = .); + + . += _StackSize; + _fstack = .; + + WorkAreaBase = .; + + . = ALIGN (16); + _stack_init = .; + _clear_end = .; + + } > sdram + + + /DISCARD/ : + { + *(.comment) + } + + + /* 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) } + .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) } + /* These must appear regardless of . */ +} diff --git a/bsps/lm32/shared/start/bspreset.c b/bsps/lm32/shared/start/bspreset.c new file mode 100644 index 0000000000..0c41dc6f41 --- /dev/null +++ b/bsps/lm32/shared/start/bspreset.c @@ -0,0 +1,28 @@ +/** + * @file + * + * Default bsp_reset() for LM32 BSPs which can run on the GDB simulator + */ + +/* + * COPYRIGHT (c) 1989-2015. + * 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 bsp_reset( void ) +{ + /* + * If on the GDB simulator, trap to it and exit. + */ + #if LM32_ON_SIMULATOR + __asm__ volatile ( "mvi r8, 1" ); /* 1 is SYS_exit */ + __asm__ volatile ( "scall" ); + #endif +} diff --git a/bsps/lm32/shared/start/bspstart.c b/bsps/lm32/shared/start/bspstart.c new file mode 100644 index 0000000000..6a419e869e --- /dev/null +++ b/bsps/lm32/shared/start/bspstart.c @@ -0,0 +1,35 @@ +/* + * This routine starts the application. 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) 1989-1999. + * 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. + * + * Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008, + * Micro-Research Finland Oy + */ + +#include <string.h> + +#include <bsp.h> +#include <bsp/bootcard.h> +#include "../include/system_conf.h" +#include "../console/uart.h" + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ + +void bsp_start(void) +{ + /* Setup console baud rate */ + BSP_uart_init(UART_BAUD_RATE); +} diff --git a/bsps/m32c/m32cbsp/start/bsp_specs b/bsps/m32c/m32cbsp/start/bsp_specs new file mode 100644 index 0000000000..afa9f6badb --- /dev/null +++ b/bsps/m32c/m32cbsp/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{!nostdlib: %{qrtems: crtend.o%s}} diff --git a/bsps/m32c/m32cbsp/start/bspstart.c b/bsps/m32c/m32cbsp/start/bspstart.c new file mode 100644 index 0000000000..7fdd598ccf --- /dev/null +++ b/bsps/m32c/m32cbsp/start/bspstart.c @@ -0,0 +1,24 @@ +/* + * COPYRIGHT (c) 1989-2008. + * 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> + +extern void sys_sbrk(int); + +/* + * 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 ) +{ + /* Tell the simulator not to test for heap/stack collision */ + sys_sbrk(0); +} diff --git a/bsps/m32c/m32cbsp/start/crtn.S b/bsps/m32c/m32cbsp/start/crtn.S new file mode 100644 index 0000000000..6004f28e05 --- /dev/null +++ b/bsps/m32c/m32cbsp/start/crtn.S @@ -0,0 +1,58 @@ +/* + +Copyright (c) 2005 Red Hat Incorporated. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 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. + + The name of Red Hat Incorporated may not be used to endorse + or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 RED HAT INCORPORATED 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. + +*/ + + +#if defined(__r8c_cpu__) || defined(__m16c_cpu__) +#define A16 +#define A(n,w) n +#define W w +#else +#define A24 +#define A(n,w) w +#define W l +#endif + + .section .init,"ax",@progbits + jsr.a _m32c_run_preinit_array + jsr.a _m32c_run_init_array + exitd + .global __m32c_init_end +__m32c_init_end: + + .section .fini,"ax",@progbits + + exitd + .global __m32c_fini_end +__m32c_fini_end: + + .text + diff --git a/bsps/m32c/m32cbsp/start/linkcmds b/bsps/m32c/m32cbsp/start/linkcmds new file mode 100644 index 0000000000..48cc27e7ae --- /dev/null +++ b/bsps/m32c/m32cbsp/start/linkcmds @@ -0,0 +1,216 @@ +/* + * Declare some sizes. + */ +_RamBase = DEFINED(_RamBase) ? _RamBase : 0x200000; +_RamSize = DEFINED(_RamSize) ? _RamSize : 0x800000; +_HeapSize = DEFINED(_HeapSize) ? _HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x1000; + + +/* Default linker script, for normal executables */ +OUTPUT_FORMAT("elf32-m32c", "elf32-m32c", + "elf32-m32c") +OUTPUT_ARCH(m32c) +ENTRY(_start) +STARTUP(start.o) +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +MEMORY { + RAM (w) : ORIGIN = 0x200000, LENGTH = 0x800000 + VEC (r) : ORIGIN = 0xffffdc, LENGTH = 32 + RESETVEC (r) : ORIGIN = 0xfffffc, LENGTH = 4 +} +SECTIONS +{ + /* There are three cases we care about: First, RW data that must be + in the low 64k. This will always be copied from ROM. Second, RO + data that must be in the low 64k. This may be copied from ROM if + the ROM is above 64k. Third, anything that does not need to be + in the first 64k. Chips normally only have two memory regions; + low ram and either high or low rom. We map the low rom needs + into one of the actual regions. */ + + /* .text goes first so the rom image of ram data will follow it. */ + .text : + { + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.interp .hash .dynsym .dynstr .gnu.version*) + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + . = ALIGN(2); + } > RAM =0 + + /* rodata will either be part of data, or will be in low rom. So we + might be spanning it, or we might not. This lets us include it + in our calculations when appropriate. */ + + .rodata : { + . = ALIGN(2); + *(.plt) + KEEP (*(.init)) + KEEP (*(.fini)) + *(.rodata .rodata.* .gnu.linkonce.r.*) + KEEP (*(SORT(.rtemsroset.*))) + *(.rodata1) + *(.eh_frame_hdr) + KEEP (*(.eh_frame)) + KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) + . = ALIGN(2); + PROVIDE(__romdatastart = .); /* IF_ROROM */ + } > RAM + + .tdata : { + __TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + __TLS_Data_end = .; + } > RAM + .tbss : { + __TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + __TLS_BSS_end = .; + } > RAM + __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)); + + .data : { + . = ALIGN(32 / 8); + PROVIDE (__datastart = .); /* IF_ROROM */ + PROVIDE (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + KEEP (*(.init_array)) + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + KEEP (*(.fini_array)) + PROVIDE (__fini_array_end = .); + + /* 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)) + /* We don't want to include the .ctor section from + 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 ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + + KEEP (*crtbegin*.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + + KEEP (*(.jcr)) + *(.data.rel.ro.local) *(.data.rel.ro*) + *(.dynamic) + + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(SORT(.rtemsrwset.*))) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + *(.got.plt) *(.got) + + . = ALIGN(2); + _edata = .; + PROVIDE (edata = .); + PROVIDE (__dataend = .); + } > RAM + + /* Note that __romdatacopysize may be ZERO for the simulator, which + knows how to intialize RAM directly. It should ONLY be used for + copying data from ROM to RAM; if you need to know the size of the + data section, subtract the end symbol from the start symbol. */ + /* Note that crt0 assumes this is even; all the start/stop symbols + are also assumed word-aligned. */ + PROVIDE (__romdatacopysize = 0); + + .bss : { + . = ALIGN(2); + PROVIDE (__bssstart = .); + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(2); + PROVIDE (__bssend = .); + _end = .; + PROVIDE (end = .); + } > RAM + PROVIDE (__bsssize = 0); + . = ALIGN(16); + + . += _StackSize; + PROVIDE (__stack = .); + PROVIDE (_WorkAreaBase = .); + . = 0xa00000; + PROVIDE (_WorkAreaEnd = .); + PROVIDE (_WorkAreaSize = _WorkAreaEnd - _WorkAreaBase); + +/* + .stack (0x200000 + 0x800000 - 2) : + { + PROVIDE (__stack = .); + *(.stack) + } +*/ + + .vec : { + *(.vec) + } > VEC + .resetvec : { + *(.resetvec) + } > RESETVEC + + /* The rest are all not normally part of the runtime image. */ + + /* 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) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/bsps/m68k/av5282/start/bsp_specs b/bsps/m68k/av5282/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/m68k/av5282/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/m68k/av5282/start/bspstart.c b/bsps/m68k/av5282/start/bspstart.c new file mode 100644 index 0000000000..c2dd362a6d --- /dev/null +++ b/bsps/m68k/av5282/start/bspstart.c @@ -0,0 +1,65 @@ +/* + * This routine does the bulk of the system initialisation. + */ + +/* + * Author: + * David Fiddes, D.J@fiddes.surfaid.org + * http://www.calm.hw.ac.uk/davidf/coldfire/ + * + * COPYRIGHT (c) 1989-1998. + * 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> +#include <string.h> + +/* + * Cacheable areas + */ +#define SDRAM_BASE 0 +#define SDRAM_SIZE (16*1024*1024) +#define FLASH_BASE 0xFF800000 +#define FLASH_SIZE (8*1024*1024) + +void bsp_start( void ) +{ + /* + * Invalidate the cache and disable it + */ + m68k_set_acr0(0); + m68k_set_acr1(0); + m68k_set_cacr(MCF5XXX_CACR_CINV); + + /* + * Cache SDRAM and FLASH + */ + m68k_set_acr0( + MCF5XXX_ACR_AB(SDRAM_BASE) | + MCF5XXX_ACR_AM(SDRAM_SIZE-1) | + MCF5XXX_ACR_EN | + MCF5XXX_ACR_BWE | + MCF5XXX_ACR_SM_IGNORE + ); + + /* + * Enable the cache + */ + mcf5xxx_initialize_cacr( + MCF5XXX_CACR_CENB | + MCF5XXX_CACR_DBWE | + MCF5XXX_CACR_DCM + ); +} + +extern char _CPUClockSpeed[]; + +uint32_t get_CPU_clock_speed(void) +{ + return( (uint32_t)_CPUClockSpeed); +} diff --git a/bsps/m68k/av5282/start/init5282.c b/bsps/m68k/av5282/start/init5282.c new file mode 100644 index 0000000000..df5eedb2fd --- /dev/null +++ b/bsps/m68k/av5282/start/init5282.c @@ -0,0 +1,88 @@ +/* + * This is where the real hardware setup is done. A minimal stack + * has been provided by the start.S code. No normal C or RTEMS + * functions can be called from here. + * + * This routine is pretty simple for the uC5282 because all the hard + * work has been done by the bootstrap dBUG code. + */ + +#include <bsp.h> + +#define m68k_set_cacr(_cacr) \ + __asm__ volatile ("movec %0,%%cacr" : : "d" (_cacr)) +#define m68k_set_acr0(_acr0) \ + __asm__ volatile ("movec %0,%%acr0" : : "d" (_acr0)) +#define m68k_set_acr1(_acr1) \ + __asm__ volatile ("movec %0,%%acr1" : : "d" (_acr1)) +#define MM_SDRAM_BASE (0x00000000) + +/* + * External methods used by this file + */ +extern void CopyDataClearBSSAndStart (void); +extern void INTERRUPT_VECTOR(void); + +void Init5282 (void) +{ + int x; + int temp = 0; + + /*Setup the GPIO Registers */ + MCF5282_GPIO_PBCDPAR = 0x80; + MCF5282_GPIO_PEPAR = 0x5100; + MCF5282_GPIO_PJPAR = 0xFF; + MCF5282_GPIO_PASPAR = 0x0000; + MCF5282_GPIO_PEHLPAR = 0xC0; + MCF5282_GPIO_PUAPAR = 0x0F; + MCF5282_QADC_DDRQB = 0x07; + MCF5282_GPTA_GPTDDR = 0x0C; + MCF5282_GPTA_GPTPORT = 0x4; + + /*Setup the Chip Selects so CS0 is flash */ + MCF5282_CS0_CSAR =(0xff800000 & 0xffff0000)>>16; + MCF5282_CS0_CSMR = 0x007f0001; + MCF5282_CS0_CSCR =(((0xf)&0x0F)<<10)|(1<<8)|(0x80); + + /*Setup the SDRAM */ + for(x=0; x<20000; x++) { + temp +=1; + } + MCF5282_SDRAMC_DCR = 0x00000239; + MCF5282_SDRAMC_DACR0 = 0x00001320; + MCF5282_SDRAMC_DMR0 = (0x00FC0000) | (0x00000001); + for(x=0; x<20000; x++) { + temp +=1; + } + /* set ip ( bit 3 ) in dacr */ + MCF5282_SDRAMC_DACR0 |= (0x00000008) ; + /* init precharge */ + *((short *)MM_SDRAM_BASE) = 0; + /* set RE in dacr */ + MCF5282_SDRAMC_DACR0 |= (0x00008000); + /* wait */ + for(x=0; x<20000; x++) { + temp +=1; + } + /* issue IMRS */ + MCF5282_SDRAMC_DACR0 |= (0x00000040); + *((short *)MM_SDRAM_BASE) = 0x0000; + for(x=0; x<60000; x++) { + temp +=1; + } + *((unsigned long*)MM_SDRAM_BASE)=0x12345678; + + /* Copy the interrupt vector table to address 0x0 in SDRAM */ + { + uint32_t *inttab = (uint32_t *)&INTERRUPT_VECTOR; + uint32_t *intvec = (uint32_t *)0x0; + register int i; + for (i = 0; i < 256; i++) { + *(intvec++) = *(inttab++); + } + } + /* + * Copy data, clear BSS and call boot_card() + */ + CopyDataClearBSSAndStart (); +} diff --git a/bsps/m68k/av5282/start/linkcmds b/bsps/m68k/av5282/start/linkcmds new file mode 100644 index 0000000000..ff0fdda163 --- /dev/null +++ b/bsps/m68k/av5282/start/linkcmds @@ -0,0 +1,196 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Arcturus uC DIMM ColdFire 5282 + * + * COPYRIGHT (c) 1989-2007. + * 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. + */ + +/* + * Declare some sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamSize : 16M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0; +_VBR = 0x0; + +/* + * System clock speed + */ +_CPUClockSpeed = DEFINED(_CPUClockSpeed) ? _CPUClockSpeed : 58976000 ; + +/* + * Location of on-chip devicesa + */ +__IPSBAR = DEFINED(__IPSBAR) ? __IPSBAR : 0x40000000 ; +__SRAMBASE = DEFINED(__SRAMBASE) ? __SRAMBASE : 0x20000000 ; + + +ENTRY(start) +STARTUP(start.o) + +MEMORY +{ + ram : ORIGIN = 0, LENGTH = 16M + sram : ORIGIN = 0x20000000, LENGTH = 64K + flash : ORIGIN = 0xFF800000, LENGTH = 8M +} + +SECTIONS +{ + + _header_offset = 0; + + /* + * Text, data and bss segments + */ + .text 0x40000 : { + + *(.text*) + *(.ram_code) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + * + * Various files can provide initialization and finalization + * functions. crtbegin.o and crtend.o are two instances. The + * body of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues + * from crti.o and function epilogues from crtn.o. crti.o must + * be linked first; crtn.o must be linked last. Because these + * are wildcards, it doesn't matter if the user does not + * actually link against crti.o and crtn.o; the linker won't + * look for a file to match a wildcard. The wildcard also + * means that it doesn't matter which directory crti.o and + * crtn.o are in. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + + /* + * C++ constructors/destructors + * + * gcc uses crtbegin.o to find the start of the constructors + * and destructors 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. The + * constructor and destructor list are terminated in + * crtend.o. The same comments apply to it. + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + + *(.console_gdb_xfer) + *(.bootstrap_data) + . = ALIGN(16); + _estuff = .; + PROVIDE (_etext = .); + } >ram + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >ram + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >ram + + _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)); + + .data : { + PROVIDE( _data_dest_start = . ); + PROVIDE( _copy_start = .); + *(.data*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (16); + PROVIDE (_edata = .); + PROVIDE (_copy_end = .); + PROVIDE (_data_dest_end = . ); + } >ram + + _data_src_start = _estuff; + _data_src_end = _data_dest_start + SIZEOF(.data); + + .bss : { + _clear_start = .; + *(.bss*) + *(COMMON) + . = ALIGN (16); + PROVIDE (end = .); + _clear_end = .; + + WorkAreaBase = .; + } >ram + /* 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) } + +PROVIDE (end_of_all = .); +} diff --git a/bsps/m68k/av5282/start/linkcmdsflash b/bsps/m68k/av5282/start/linkcmdsflash new file mode 100644 index 0000000000..e194add7b8 --- /dev/null +++ b/bsps/m68k/av5282/start/linkcmdsflash @@ -0,0 +1,196 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Arcturus uC DIMM ColdFire 5282 + * + * COPYRIGHT (c) 1989-1999. + * 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. + */ + +/* + * Declare some sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamSize : 16M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0; +_VBR = 0x0; + +/* + * System clock speed + */ +_CPUClockSpeed = DEFINED(_CPUClockSpeed) ? _CPUClockSpeed : 58976000 ; + +/* + * Location of on-chip devicesa + */ +__IPSBAR = DEFINED(__IPSBAR) ? __IPSBAR : 0x40000000 ; +__SRAMBASE = DEFINED(__SRAMBASE) ? __SRAMBASE : 0x20000000 ; + +ENTRY(start) +STARTUP(start.o) + +MEMORY +{ + ram : ORIGIN = 0, LENGTH = 16M + sram : ORIGIN = 0x20000000, LENGTH = 64K + flash : ORIGIN = 0xFF800000, LENGTH = 8M +} + +SECTIONS +{ + + _header_offset = 0; + + /* + * Text, data and bss segments + */ + .text : { + + *(.text*) + *(.ram_code) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + * + * Various files can provide initialization and finalization + * functions. crtbegin.o and crtend.o are two instances. The + * body of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues + * from crti.o and function epilogues from crtn.o. crti.o must + * be linked first; crtn.o must be linked last. Because these + * are wildcards, it doesn't matter if the user does not + * actually link against crti.o and crtn.o; the linker won't + * look for a file to match a wildcard. The wildcard also + * means that it doesn't matter which directory crti.o and + * crtn.o are in. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + + /* + * C++ constructors/destructors + * + * gcc uses crtbegin.o to find the start of the constructors + * and destructors 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. The + * constructor and destructor list are terminated in + * crtend.o. The same comments apply to it. + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + + *(.console_gdb_xfer) + *(.bootstrap_data) + . = ALIGN(16); + _estuff = .; + PROVIDE (_etext = .); + } >flash + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >flash + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >flash + + _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)); + + .data 0x1000 : AT ( ADDR(.tdata) + SIZEOF ( .tdata ) ) + { + PROVIDE( _data_dest_start = . ); + PROVIDE( _copy_start = .); + *(.data) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (16); + PROVIDE (_edata = .); + PROVIDE (_copy_end = .); + PROVIDE (_data_dest_end = . ); + } + + _data_src_start = _estuff; + _data_src_end = _data_dest_start + SIZEOF(.data); + + .bss : { + _clear_start = .; + *(.bss*) + *(COMMON) + . = ALIGN (16); + PROVIDE (end = .); + _clear_end = .; + + WorkAreaBase = .; + } + /* 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) } + +PROVIDE (end_of_all = .); +} diff --git a/bsps/m68k/av5282/start/linkcmdsram b/bsps/m68k/av5282/start/linkcmdsram new file mode 100644 index 0000000000..976c08a308 --- /dev/null +++ b/bsps/m68k/av5282/start/linkcmdsram @@ -0,0 +1,195 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Arcturus uC DIMM ColdFire 5282 + * + * COPYRIGHT (c) 1989-1999. + * 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. + */ + +/* + * Declare some sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamSize : 16M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0; +_VBR = 0x0; + +/* + * System clock speed + */ +_CPUClockSpeed = DEFINED(_CPUClockSpeed) ? _CPUClockSpeed : 58976000 ; + +/* + * Location of on-chip devicesa + */ +__IPSBAR = DEFINED(__IPSBAR) ? __IPSBAR : 0x40000000 ; +__SRAMBASE = DEFINED(__SRAMBASE) ? __SRAMBASE : 0x20000000 ; + +ENTRY(start) +STARTUP(start.o) + +MEMORY +{ + ram : ORIGIN = 0, LENGTH = 16M + sram : ORIGIN = 0x20000000, LENGTH = 64K + flash : ORIGIN = 0xFF800000, LENGTH = 8M +} + +SECTIONS +{ + + _header_offset = 0; + + /* + * Text, data and bss segments + */ + .text 0x40000 : { + + *(.text*) + *(.ram_code) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + * + * Various files can provide initialization and finalization + * functions. crtbegin.o and crtend.o are two instances. The + * body of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues + * from crti.o and function epilogues from crtn.o. crti.o must + * be linked first; crtn.o must be linked last. Because these + * are wildcards, it doesn't matter if the user does not + * actually link against crti.o and crtn.o; the linker won't + * look for a file to match a wildcard. The wildcard also + * means that it doesn't matter which directory crti.o and + * crtn.o are in. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + + /* + * C++ constructors/destructors + * + * gcc uses crtbegin.o to find the start of the constructors + * and destructors 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. The + * constructor and destructor list are terminated in + * crtend.o. The same comments apply to it. + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + + *(.console_gdb_xfer) + *(.bootstrap_data) + . = ALIGN(16); + _estuff = .; + PROVIDE (_etext = .); + } >ram + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >ram + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >ram + + _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)); + + .data : { + PROVIDE( _data_dest_start = . ); + PROVIDE( _copy_start = .); + *(.data) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (16); + PROVIDE (_edata = .); + PROVIDE (_copy_end = .); + PROVIDE (_data_dest_end = . ); + } >ram + + _data_src_start = _estuff; + _data_src_end = _data_dest_start + SIZEOF(.data); + + .bss : { + _clear_start = .; + *(.bss*) + *(COMMON) + . = ALIGN (16); + PROVIDE (end = .); + _clear_end = .; + + WorkAreaBase = .; + } >ram + /* 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) } + +PROVIDE (end_of_all = .); +} diff --git a/bsps/m68k/csb360/start/bsp_specs b/bsps/m68k/csb360/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/m68k/csb360/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/m68k/csb360/start/init5272.c b/bsps/m68k/csb360/start/init5272.c new file mode 100644 index 0000000000..267fd551b4 --- /dev/null +++ b/bsps/m68k/csb360/start/init5272.c @@ -0,0 +1,146 @@ +/* + * CSB360 hardware startup routines + * + * This is where the real hardware setup is done. A minimal stack + * has been provided by the start.S code. No normal C or RTEMS + * functions can be called from here. + * + * This initialization code based on hardware settings of dBUG + * monitor. This must be changed if you like to run it immediately + * after reset. + */ + +/* + * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russia + * Author: Victor V. Vengerov <vvv@oktet.ru> + * + * Based on work: + * Author: + * David Fiddes, D.J@fiddes.surfaid.org + * http://www.calm.hw.ac.uk/davidf/coldfire/ + * + * COPYRIGHT (c) 1989-1998. + * 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 <mcf5272/mcf5272.h> + +/* externs */ +extern void clear_bss(void); +extern void start_csb360(void); +extern void INTERRUPT_VECTOR(void); + +/* Set the pointers to the modules */ +sim_regs_t *g_sim_regs = (void *) MCF5272_SIM_BASE(BSP_MBAR); +intctrl_regs_t *g_intctrl_regs = (void *) MCF5272_INT_BASE(BSP_MBAR); +chipsel_regs_t *g_chipsel_regs = (void *) MCF5272_CS_BASE(BSP_MBAR); +gpio_regs_t *g_gpio_regs = (void *) MCF5272_GPIO_BASE(BSP_MBAR); +qspi_regs_t *g_qspi_regs = (void *) MCF5272_QSPI_BASE(BSP_MBAR); +pwm_regs_t *g_pwm_regs = (void *) MCF5272_PWM_BASE(BSP_MBAR); +dma_regs_t *g_dma_regs = (void *) MCF5272_DMAC_BASE(BSP_MBAR); +uart_regs_t *g_uart0_regs = (void *) MCF5272_UART0_BASE(BSP_MBAR); +uart_regs_t *g_uart1_regs = (void *) MCF5272_UART1_BASE(BSP_MBAR); +timer_regs_t *g_timer_regs = (void *) MCF5272_TIMER_BASE(BSP_MBAR); +plic_regs_t *g_plic_regs = (void *) MCF5272_PLIC_BASE(BSP_MBAR); +enet_regs_t *g_enet_regs = (void *) MCF5272_ENET_BASE(BSP_MBAR); +usb_regs_t *g_usb_regs = (void *) MCF5272_USB_BASE(BSP_MBAR); + +#define m68k_set_srambar( _rambar0 ) \ + __asm__ volatile ( "movec %0,%%rambar0\n\t" \ + "nop\n\t" \ + : : "d" (_rambar0) ) + +#define m68k_set_mbar( _mbar ) \ + __asm__ volatile ( "movec %0,%%mbar\n\t" \ + "nop\n\t" \ + : : "d" (_mbar) ) + +#define mcf5272_enable_cache() \ + m68k_set_cacr( MCF5272_CACR_CENB ) + + +#define mcf5272_disable_cache() \ + __asm__ volatile ( "nop\n\t" \ + "movec %0,%%cacr\n\t" \ + "nop\n\t" \ + "movec %0,%%cacr\n\t" \ + "nop\n\t" \ + : : "d" (MCF5272_CACR_CINV) ) + +/* + * Initialize MCF5272 on-chip modules + */ +void init5272(void) +{ + /* Invalidate the cache - WARNING: It won't complete for 64 clocks */ + m68k_set_cacr(MCF5272_CACR_CINV); + + /* Set Module Base Address register */ + m68k_set_mbar((BSP_MBAR & MCF5272_MBAR_BA) | MCF5272_MBAR_V); + + /* Set RAM Base Address register */ + m68k_set_srambar((BSP_RAMBAR & MCF5272_RAMBAR_BA) | MCF5272_RAMBAR_V); + + /* Set System Control Register: + * Enet has highest priority, 16384 bus cycles before timeout + */ + g_sim_regs->scr = (MCF5272_SCR_HWR_16384); + + /* System Protection Register: + * Enable Hardware watchdog timer. + */ + g_sim_regs->spr = MCF5272_SPR_HWTEN; + + /* Clear and mask all interrupts */ + g_intctrl_regs->icr1 = 0x88888888; + g_intctrl_regs->icr2 = 0x88888888; + g_intctrl_regs->icr3 = 0x88888888; + g_intctrl_regs->icr4 = 0x88880000; + + /* Copy the interrupt vector table to SRAM */ + { + uint32_t *inttab = (uint32_t *)&INTERRUPT_VECTOR; + uint32_t *intvec = (uint32_t *)BSP_RAMBAR; + register int i; + for (i = 0; i < 256; i++) { + *(intvec++) = *(inttab++); + } + } + m68k_set_vbr(BSP_RAMBAR); + + + /* + * Setup ACRs so that if cache turned on, periphal accesses + * are not messed up. (Non-cacheable, serialized) + */ + m68k_set_acr0(MCF5272_ACR_BASE(BSP_MEM_ADDR_SDRAM) | + MCF5272_ACR_MASK(BSP_MEM_MASK_SDRAM) | + MCF5272_ACR_EN | + MCF5272_ACR_SM_ANY); + +/* + m68k_set_acr1 (MCF5206E_ACR_BASE(BSP_MEM_ADDR_FLASH) | + MCF5206E_ACR_MASK(BSP_MEM_MASK_FLASH) | + MCF5206E_ACR_EN | + MCF5206E_ACR_SM_ANY); +*/ + + /* Enable the caches */ + m68k_set_cacr(MCF5272_CACR_CENB | + MCF5272_CACR_DCM); /* Default is not cached */ + +/* + * Copy data, clear BSS, switch stacks and call boot_card() + */ +/* +CopyDataClearBSSAndStart(BSP_MEM_SIZE_ESRAM - 0x400); +*/ + clear_bss(); + start_csb360(); + +} diff --git a/bsps/m68k/csb360/start/linkcmds b/bsps/m68k/csb360/start/linkcmds new file mode 100644 index 0000000000..09670c156d --- /dev/null +++ b/bsps/m68k/csb360/start/linkcmds @@ -0,0 +1,174 @@ +/* + * This file contains GNU linker directives for the Cogent + * CSB360 development board. + * + * Copyright (C) 2004 Cogent Computer Systems + * Author: Jay Monkman <jtm@lopingdog.com> + */ + +/* + * Declare size of heap. + * A heap size of 0 means "Use all available memory for the heap". + * Initial stack located in on-chip SRAM and not declared there. + */ +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +RamBase = DEFINED(RamBase) ? RamBase : 0x00100000; +RamSize = DEFINED(RamSize) ? RamSize : 31M; + +/* This is needed for _CPU_ISR_install_vector - +* WARNING: it MUST match BSP_RAMBAR !!!!!!!!!!! */ +_VBR = 0x20000000; + +ENTRY(start) +STARTUP(start.o) + +/* + * Setup the memory map of the CSB360 board + * + * The "ram" section is placed in RAM after the space used by umon. + * + */ +MEMORY +{ + ram : ORIGIN = 0x00100000, LENGTH = 31M +} + +SECTIONS +{ + + /* + * Text, data and bss segments + */ + .text : + { + RamBase = .; + RamBase = .; + CREATE_OBJECT_SYMBOLS + *(.text*) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + */ + . = ALIGN (16); + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + . = ALIGN (16); + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * C++ constructors/destructors + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = .; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + PROVIDE (etext = .); + + } > ram + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >ram + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >ram + + _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)); + + + .data : + { + copy_start = .; + *(.shdata) + . = ALIGN (0x10); + *(.data*) + KEEP (*(SORT(.rtemsrwset.*))) + . = ALIGN (0x10); + *(.gcc_exc) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (0x10); + *(.gnu.linkonce.d*) + . = ALIGN (0x10); + _edata = .; + copy_end = .; + } > ram + + .bss : + { + clear_start = . ; + *(.shbss) + *(.dynbss) + *(.bss* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(0x10); + _end = .; + + clear_end = .; + + WorkAreaBase = .; + WorkAreaBase = .; + + } > ram + + .stab 0 (NOLOAD) : + { + *(.stab) + } + + .stabstr 0 (NOLOAD) : + { + *(.stabstr) + } + +} diff --git a/bsps/m68k/gen68340/start/bsp_specs b/bsps/m68k/gen68340/start/bsp_specs new file mode 100644 index 0000000000..3a20757667 --- /dev/null +++ b/bsps/m68k/gen68340/start/bsp_specs @@ -0,0 +1,10 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s crtn.o%s} + diff --git a/bsps/m68k/gen68340/start/dumpanic.c b/bsps/m68k/gen68340/start/dumpanic.c new file mode 100644 index 0000000000..7f82ab3a77 --- /dev/null +++ b/bsps/m68k/gen68340/start/dumpanic.c @@ -0,0 +1,190 @@ +/* + * M68340/349 registers and stack dump if an exception is raised + */ + +/* + * Author: + * Pascal Cadic + * France Telecom - CNET/DSM/TAM/CAT + * 4, rue du Clos Courtel + * 35512 CESSON-SEVIGNE + * FRANCE + * + * COPYRIGHT (c) 1989-1999. + * 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 <rtems/bspIo.h> + +const char *exceptionName[] = { + "INITIAL STACK POINTER", + "INITIAL PROGRAM COUNTER", + "BUS ERROR", + "ADDRESS ERROR", + "ILLEGAL INSTRUCTION", + "DIVISION BY ZERO", + "CHK, CHK2", + "TRAPcc, TRAPv", + "PRIVILEGE VIOLATION", + "TRACE", + "LINE A EMULATOR", + "LINE F EMULATOR", + "HARDWARE BREAK", + "COPROCESSOR PROTOCOL VIOLATION", + "FORMAT ERROR", + "UNINITIALIZED INTERRUPT", + "RESERVED 16", + "RESERVED 17", + "RESERVED 18", + "RESERVED 19", + "RESERVED 20", + "RESERVED 21", + "RESERVED 22", + "RESERVED 23", + "SPURIOUS INTERRUPT", + "LEVEL 1 AUTOVECTOR", + "LEVEL 2 AUTOVECTOR", + "LEVEL 3 AUTOVECTOR", + "LEVEL 4 AUTOVECTOR", + "LEVEL 5 AUTOVECTOR", + "LEVEL 6 AUTOVECTOR", + "LEVEL 7 AUTOVECTOR", + "TRAP 1", + "TRAP 2", + "TRAP 3", + "TRAP 4", + "TRAP 5", + "TRAP 6", + "TRAP 7", + "TRAP 8", + "TRAP 9", + "TRAP 10", + "TRAP 11", + "TRAP 12", + "TRAP 13", + "TRAP 14", + "TRAP 15", + "VECTOR 48", + "VECTOR 49", + "VECTOR 50", + "VECTOR 51", + "VECTOR 52", + "VECTOR 53", + "VECTOR 54", + "VECTOR 55", + "VECTOR 56", + "VECTOR 57", + "VECTOR 58", + "VECTOR 59", + "VECTOR 60", + "VECTOR 61", + "VECTOR 62", + "VECTOR 63", + }; + +typedef struct { + unsigned long pc; + unsigned short sr; + unsigned short format_id; + unsigned long d0, d1, d2, d3, d4, d5, d6, d7; + unsigned long a0, a1, a2, a3, a4, a5, a6, a7; + unsigned long sfc, dfc, vbr; +} boot_panic_registers_t; + +boot_panic_registers_t _boot_panic_registers; + +/****************************************************** + Name: _dbug_dump + Input parameters: sr, pc, stack pointer, + size to display + Output parameters: - + Description: display the supervisor stack + *****************************************************/ +static void _dbug_dump( + unsigned short sr, + void* pc, + unsigned short *stack, + int size +) +{ + int i; + + printk("%x : %x \t%x",0,sr,(unsigned short)(((unsigned)pc)>>16)); + for (i=2; i<size; i++) { + if ((i%8)==0) printk("\n%x :",i/8); + printk(" %x\t",stack[i-2]); + } + printk("\n"); +} + +/****************************************************** + Name: _dbug_dump + Input parameters: - + Output parameters: - + Description: display microcontroler state. Registers + values are stored in _boot_panic_registers + which is filled in _uhoh ASM routine + *****************************************************/ +void _dbug_dumpanic(void) +{ + int c; + void *faultedAddr, *pc; + unsigned short vector, status; + unsigned char frametype, *stack; + #define ESCAPE 27 + + stack = (unsigned char*)(_boot_panic_registers.a7); + do { + status = _boot_panic_registers.sr; + pc = (void*)_boot_panic_registers.pc; + faultedAddr = *(void**)(stack+4); + vector = (_boot_panic_registers.format_id&0x0FFF)>>2; + frametype = (_boot_panic_registers.format_id&0xF000)>>12; + + printk("\n---------------------------------------------\n"); + if (vector<64) + printk("%s",exceptionName[vector]); + else { + printk("RESERVED USER"); + } + printk(" exception (vector %x, type %x)\n",vector,frametype); + printk("---------------------------------------------\n"); + printk("PC : %p ",pc); + printk("A7 : 0x%lx ",_boot_panic_registers.a7); + printk("SR : 0x%x\n",status); + if (frametype==0x0c) { + printk("\nfaulted address = %p\n",faultedAddr); + } + printk("---------------------------------------------\n"); + printk(" panic regs\n"); + printk("---------------------------------------------\n"); + printk("D[0..3] : %lx \t%lx \t%lx \t%lx\n", + _boot_panic_registers.d0,_boot_panic_registers.d1, + _boot_panic_registers.d2,_boot_panic_registers.d3); + printk("D[4..7] : %lx \t%lx \t%lx \t%lx\n", + _boot_panic_registers.d4,_boot_panic_registers.d5, + _boot_panic_registers.d6,_boot_panic_registers.d7); + printk("A[0..3] : %lx \t%lx \t%lx \t%lx\n", + _boot_panic_registers.a0,_boot_panic_registers.a1, + _boot_panic_registers.a2,_boot_panic_registers.a3); + printk("A[4..7] : %lx \t%lx \t%lx \t%lx\n", + _boot_panic_registers.a4,_boot_panic_registers.a5, + _boot_panic_registers.a6,_boot_panic_registers.a7); + + printk(" SFC : %lx",_boot_panic_registers.sfc); + printk(" DFC : %lx\n",_boot_panic_registers.dfc); + printk(" VBR : %lx\n",_boot_panic_registers.vbr); + printk("---------------------------------------------\n"); + printk(" panic stack\n"); + printk("---------------------------------------------\n"); + _dbug_dump(status, pc, (unsigned short*)stack,64*2); + + printk("---------------------------------------------\n"); + printk("press escape to reboot\n"); + } while ((c=getchark())!=ESCAPE); +} diff --git a/bsps/m68k/gen68340/start/init68340.c b/bsps/m68k/gen68340/start/init68340.c new file mode 100644 index 0000000000..ee30f415e9 --- /dev/null +++ b/bsps/m68k/gen68340/start/init68340.c @@ -0,0 +1,38 @@ +/* + * MC68340/349 support routines + * + * Geoffroy Montel + * France Telecom - CNET/DSM/TAM/CAT + * 4, rue du Clos Courtel + * 35512 CESSON-SEVIGNE + * FRANCE + * + * e-mail: g_montel@yahoo.com + */ + +#include <rtems.h> +#include <bsp.h> + +extern void _CopyDataClearBSSAndStart (void); + +/* + * Initialize MC68340 + */ +void _Init68340 (void) +{ + rtems_isr_entry *vbr; + int i; + + /* + * Copy the exception vector table to system RAM + */ + m68k_get_vbr (vbr); + for (i = 0; i < 256; ++i) + M68Kvec[i] = vbr[i]; + m68k_set_vbr (M68Kvec); + + /* + * Copy data, clear BSS, switch stacks and call main() + */ + _CopyDataClearBSSAndStart (); +} diff --git a/bsps/m68k/gen68340/start/linkcmds b/bsps/m68k/gen68340/start/linkcmds new file mode 100644 index 0000000000..860115930e --- /dev/null +++ b/bsps/m68k/gen68340/start/linkcmds @@ -0,0 +1,248 @@ +/* + * This file contains GNU linker directives for a generic MC68340/349 board. + * Variations in hardware type and dynamic memory size can be made + * by overriding some values with linker command-line arguments. + * + * ATTENTION: RAM and ROM placement must accord those in start340.S!! + * (next time I'll use some shared variables :) ) + * + * Geoffroy Montel + * France Telecom - CNET/DSM/TAM/CAT + * 4, rue du Clos Courtel + * 35512 CESSON-SEVIGNE + * FRANCE + * + * e-mail: g_montel@yahoo.com + */ + +/* + * Declare some sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x10000000; +RamSize = DEFINED(RamSize) ? RamSize : 4M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x1000; + +/* + * Declare on-board memory. + * It would be nice if the ram length could be given as + * LENGTH=RamSize, but gld doesn't allow non-constant + * values in the LENGTH expression. + */ +MEMORY { + ram : ORIGIN = 0x10000000, LENGTH = 4M + rom : ORIGIN = 0x01000000, LENGTH = 4M +/* dpram : ORIGIN = 0xFE000000, LENGTH = 8k */ +} + +ENTRY(start) +STARTUP(start.o) + +/* + * Declare low-order three octets of Ethernet address. + */ +ETHERNET_ADDRESS = DEFINED(ETHERNET_ADDRESS) ? ETHERNET_ADDRESS : 0xDEAD12; + +/* + * Load objects + */ +SECTIONS { + + /* + * Boot PROM + */ + rom : { + _RomBase = .; + __RomBase = .; + } >rom + + /* + * Dynamic RAM + */ + ram : { + . = .; + } >ram + + /* + * Text, data and bss segments + */ + .text : { + *(.text*) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + * + * Various files can provide initialization and finalization + * functions. crtbegin.o and crtend.o are two instances. The + * body of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues + * from crti.o and function epilogues from crtn.o. crti.o must + * be linked first; crtn.o must be linked last. Because these + * are wildcards, it doesn't matter if the user does not + * actually link against crti.o and crtn.o; the linker won't + * look for a file to match a wildcard. The wildcard also + * means that it doesn't matter which directory crti.o and + * crtn.o are in. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * C++ constructors/destructors + * + * gcc uses crtbegin.o to find the start of the constructors + * and destructors 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. The + * constructor and destructor list are terminated in + * crtend.o. The same comments apply to it. + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + PROVIDE (_etext = .); + } >ram + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >ram + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >ram + + _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)); + + .data : { + PROVIDE (_copy_start = .); + *(.data*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (16); + PROVIDE (_edata = .); + PROVIDE (_copy_end = .); + } >ram + .bss : { + M68Kvec = .; + . += (256 * 4); + _clear_start = .; + *(.dynbss) + *(.bss* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (16); + PROVIDE (end = .); + + . += _StackSize; + . = ALIGN (16); + _stack_init = .; + _clear_end = .; + + WorkAreaBase = .; + } >ram + + /* + * On-chip memory/peripherals + * + */ + dpram : { + m340 = .; + _m340 = .; + . += (8 * 1024); + } >ram + + + /* 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) } + .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) } + /* These must appear regardless of . */ +} diff --git a/bsps/m68k/gen68360/start/alloc360.c b/bsps/m68k/gen68360/start/alloc360.c new file mode 100644 index 0000000000..53f90876e4 --- /dev/null +++ b/bsps/m68k/gen68360/start/alloc360.c @@ -0,0 +1,94 @@ +/* + * MC68360 buffer descriptor allocation routines + * + * W. Eric Norum + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * Saskatoon, Saskatchewan, CANADA + * eric@skatter.usask.ca + */ + +#include <rtems.h> +#include <bsp.h> +#include <rtems/m68k/m68360.h> +#include <rtems/error.h> + +/* + * Allocation order: + * - Dual-Port RAM section 1 + * - Dual-Port RAM section 3 + * - Dual-Port RAM section 0 + * - Dual-Port RAM section 2 + */ +static struct { + uint8_t *base; + uint32_t size; + uint32_t used; +} bdregions[] = { + { (uint8_t *)&m360.dpram1[0], sizeof m360.dpram1, 0 }, + { (uint8_t *)&m360.dpram3[0], sizeof m360.dpram3, 0 }, + { (uint8_t *)&m360.dpram0[0], sizeof m360.dpram0, 0 }, + { (uint8_t *)&m360.dpram2[0], sizeof m360.dpram2, 0 }, +}; + +/* + * Send a command to the CPM RISC processer + */ +void * +M360AllocateBufferDescriptors (int count) +{ + unsigned int i; + ISR_Level level; + void *bdp = NULL; + unsigned int want = count * sizeof(m360BufferDescriptor_t); + + /* + * Running with interrupts disabled is usually considered bad + * form, but this routine is probably being run as part of an + * initialization sequence so the effect shouldn't be too severe. + */ + _ISR_Local_disable (level); + for (i = 0 ; i < sizeof(bdregions) / sizeof(bdregions[0]) ; i++) { + /* + * Verify that the region exists. + * This test is necessary since some chips have + * less dual-port RAM. + */ + if (bdregions[i].used == 0) { + volatile uint8_t *cp = bdregions[i].base; + *cp = 0xAA; + if (*cp != 0xAA) { + bdregions[i].used = bdregions[i].size; + continue; + } + *cp = 0x55; + if (*cp != 0x55) { + bdregions[i].used = bdregions[i].size; + continue; + } + *cp = 0x0; + } + if (bdregions[i].size - bdregions[i].used >= want) { + bdp = bdregions[i].base + bdregions[i].used; + bdregions[i].used += want; + break; + } + } + _ISR_Local_enable (level); + if (bdp == NULL) + rtems_panic ("Can't allocate %d buffer descriptor(s).\n", count); + return bdp; +} + +void * +M360AllocateRiscTimers (int count) +{ + /* + * Convert the count to the number of buffer descriptors + * of equal or larger size. This ensures that all buffer + * descriptors are allocated with appropriate alignment. + */ + return M360AllocateBufferDescriptors (((count * 4) + + sizeof(m360BufferDescriptor_t) - 1) / + sizeof(m360BufferDescriptor_t)); +} diff --git a/bsps/m68k/gen68360/start/bsp_specs b/bsps/m68k/gen68360/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/m68k/gen68360/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/m68k/gen68360/start/init68360.c b/bsps/m68k/gen68360/start/init68360.c new file mode 100644 index 0000000000..67fed27a3b --- /dev/null +++ b/bsps/m68k/gen68360/start/init68360.c @@ -0,0 +1,846 @@ +/* + * MC68360 support routines + */ + +/* + * W. Eric Norum + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * Saskatoon, Saskatchewan, CANADA + * eric@skatter.usask.ca + */ + +#include <bsp.h> +#include <rtems/m68k/m68360.h> + +extern void _CopyDataClearBSSAndStart (unsigned long ramSize); +extern void *RamBase; +extern void *_RomBase; /* From linkcmds */ + +/* + * Declare the m360 structure here for the benefit of the debugger + */ + +volatile m360_t m360; + +/* + * Send a command to the CPM RISC processer + */ + +void M360ExecuteRISC(uint16_t command) +{ + uint16_t sr; + + m68k_disable_interrupts (sr); + while (m360.cr & M360_CR_FLG) + continue; + m360.cr = command | M360_CR_FLG; + m68k_enable_interrupts (sr); +} + +/* + * Initialize MC68360 + */ +void _Init68360 (void) +{ + int i; + rtems_isr_entry *vbr; + unsigned long ramSize; + +#if (defined (__mc68040__)) + volatile unsigned long *RamBase_p; + + RamBase_p = (volatile unsigned long *)&RamBase; + + /* + ******************************************* + * Motorola 68040 and companion-mode 68360 * + ******************************************* + */ + + /* + * Step 6: Is this a power-up reset? + * For now we just ignore this and do *all* the steps + * Someday we might want to: + * if (Hard, Loss of Clock, Power-up) + * Do all steps + * else if (Double bus fault, watchdog or soft reset) + * Skip to step 12 + * else (must be a reset command) + * Skip to step 14 + */ + + /* + * Step 7: Deal with clock synthesizer + * HARDWARE: + * Change if you're not using an external 25 MHz oscillator. + */ + m360.clkocr = 0x83; /* No more writes, full-power CLKO2 */ + m360.pllcr = 0xD000; /* PLL, no writes, no prescale, + no LPSTOP slowdown, PLL X1 */ + m360.cdvcr = 0x8000; /* No more writes, no clock division */ + + /* + * Step 8: Initialize system protection + * Enable watchdog + * Watchdog causes system reset + * Next-to-slowest watchdog timeout (21 seconds with 25 MHz oscillator) + * Enable double bus fault monitor + * Enable bus monitor for external cycles + * 1024 clocks for external timeout + */ + m360.sypcr = 0xEC; + + /* + * Step 9: Clear parameter RAM and reset communication processor module + */ + for (i = 0 ; i < 192 ; i += sizeof (long)) { + *((long *)((char *)&m360 + 0xC00 + i)) = 0; + *((long *)((char *)&m360 + 0xD00 + i)) = 0; + *((long *)((char *)&m360 + 0xE00 + i)) = 0; + *((long *)((char *)&m360 + 0xF00 + i)) = 0; + } + M360ExecuteRISC (M360_CR_RST); + + /* + * Step 10: Write PEPAR + * SINTOUT standard M68000 family interrupt level encoding + * CF1MODE=10 (BCLRO* output) + * No RAS1* double drive + * A31 - A28 + * AMUX output + * CAS2* - CAS3* + * CAS0* - CAS1* + * CS7* + * AVEC* + */ + m360.pepar = 0x3440; + + /* + * Step 11: Remap Chip Select 0 (CS0*), set up GMR + */ + /* + * 512 addresses per DRAM page (256K DRAM chips) + * 70 nsec DRAM + * 180 nsec ROM (3 wait states) + */ + m360.gmr = M360_GMR_RCNT(23) | M360_GMR_RFEN | + M360_GMR_RCYC(0) | M360_GMR_PGS(1) | + M360_GMR_DPS_32BIT | M360_GMR_NCS | + M360_GMR_TSS40; + m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP | + M360_MEMC_BR_V; + m360.memc[0].or = M360_MEMC_OR_WAITS(3) | M360_MEMC_OR_1MB | + M360_MEMC_OR_32BIT; + + /* + * Step 12: Initialize the system RAM + */ + /* + * Set up option/base registers + * 1M DRAM + * 70 nsec DRAM + * Enable burst mode + * No parity checking + * Wait for chips to power up + * Perform 8 read cycles + */ + ramSize = 1 * 1024 * 1024; + m360.memc[1].or = M360_MEMC_OR_TCYC(0) | + M360_MEMC_OR_1MB | + M360_MEMC_OR_DRAM; + m360.memc[1].br = (unsigned long)&RamBase | + M360_MEMC_BR_BACK40 | + M360_MEMC_BR_V; + for (i = 0; i < 50000; i++) + continue; + for (i = 0; i < 8; ++i) { + unsigned long rambase_value; + rambase_value = *RamBase_p; + (void) rambase_value; /* avoid set but not used warning */ + } + + /* + * Step 13: Copy the exception vector table to system RAM + */ + m68k_get_vbr (vbr); + for (i = 0; i < 256; ++i) + M68Kvec[i] = vbr[i]; + m68k_set_vbr (M68Kvec); + + /* + * Step 14: More system initialization + * SDCR (Serial DMA configuration register) + * Enable SDMA during FREEZE + * Give SDMA priority over all interrupt handlers + * Set DMA arbiration level to 4 + * CICR (CPM interrupt configuration register): + * SCC1 requests at SCCa position + * SCC2 requests at SCCb position + * SCC3 requests at SCCc position + * SCC4 requests at SCCd position + * Interrupt request level 4 + * Maintain original priority order + * Vector base 128 + * SCCs priority grouped at top of table + */ + m360.sdcr = M360_SDMA_SISM_7 | M360_SDMA_SAID_4; + m360.cicr = (3 << 22) | (2 << 20) | (1 << 18) | (0 << 16) | + (4 << 13) | (0x1F << 8) | (128); + + /* + * Step 15: Set module configuration register + * Bus request MC68040 Arbitration ID 3 + * Bus asynchronous timing mode (work around bug in Rev. B) + * Arbitration asynchronous timing mode + * Disable timers during FREEZE + * Disable bus monitor during FREEZE + * BCLRO* arbitration level 3 + * No show cycles + * User/supervisor access + * Bus clear in arbitration ID level 3 + * SIM60 interrupt sources higher priority than CPM + */ + m360.mcr = 0x6000EC3F; + +#elif (defined (M68360_ATLAS_HSB)) + /* + ****************************************** + * Standalone Motorola 68360 -- ATLAS HSB * + ****************************************** + */ + + /* + * Step 6: Is this a power-up reset? + * For now we just ignore this and do *all* the steps + * Someday we might want to: + * if (Hard, Loss of Clock, Power-up) + * Do all steps + * else if (Double bus fault, watchdog or soft reset) + * Skip to step 12 + * else (must be a CPU32+ reset command) + * Skip to step 14 + */ + + /* + * Step 7: Deal with clock synthesizer + * HARDWARE: + * Change if you're not using an external 25 MHz oscillator. + */ + m360.clkocr = 0x8F; /* No more writes, no clock outputs */ + m360.pllcr = 0xD000; /* PLL, no writes, no prescale, + no LPSTOP slowdown, PLL X1 */ + m360.cdvcr = 0x8000; /* No more writes, no clock division */ + + /* + * Step 8: Initialize system protection + * Enable watchdog + * Watchdog causes system reset + * Next-to-slowest watchdog timeout (21 seconds with 25 MHz oscillator) + * Enable double bus fault monitor + * Enable bus monitor for external cycles + * 1024 clocks for external timeout + */ + m360.sypcr = 0xEC; + + /* + * Step 9: Clear parameter RAM and reset communication processor module + */ + for (i = 0 ; i < 192 ; i += sizeof (long)) { + *((long *)((char *)&m360 + 0xC00 + i)) = 0; + *((long *)((char *)&m360 + 0xD00 + i)) = 0; + *((long *)((char *)&m360 + 0xE00 + i)) = 0; + *((long *)((char *)&m360 + 0xF00 + i)) = 0; + } + M360ExecuteRISC (M360_CR_RST); + + /* + * Step 10: Write PEPAR + * SINTOUT not used (CPU32+ mode) + * CF1MODE=00 (CONFIG1 input) + * RAS1* double drive + * WE0* - WE3* + * OE* output + * CAS2* - CAS3* + * CAS0* - CAS1* + * CS7* + * AVEC* + * HARDWARE: + * Change if you are using a different memory configuration + * (static RAM, external address multiplexing, etc). + */ + m360.pepar = 0x0180; + + /* + * Step 11: Remap Chip Select 0 (CS0*), set up GMR + */ + m360.gmr = M360_GMR_RCNT(12) | M360_GMR_RFEN | + M360_GMR_RCYC(0) | M360_GMR_PGS(1) | + M360_GMR_DPS_32BIT | M360_GMR_DWQ | + M360_GMR_GAMX; + m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP | + M360_MEMC_BR_V; + m360.memc[0].or = M360_MEMC_OR_WAITS(3) | M360_MEMC_OR_1MB | + M360_MEMC_OR_8BIT; + + /* + * Step 12: Initialize the system RAM + */ + ramSize = 2 * 1024 * 1024; + /* first bank 1MByte DRAM */ + m360.memc[1].or = M360_MEMC_OR_TCYC(2) | M360_MEMC_OR_1MB | + M360_MEMC_OR_PGME | M360_MEMC_OR_DRAM; + m360.memc[1].br = (unsigned long)&RamBase | M360_MEMC_BR_V; + + /* second bank 1MByte DRAM */ + m360.memc[2].or = M360_MEMC_OR_TCYC(2) | M360_MEMC_OR_1MB | + M360_MEMC_OR_PGME | M360_MEMC_OR_DRAM; + m360.memc[2].br = ((unsigned long)&RamBase + 0x100000) | + M360_MEMC_BR_V; + + /* flash rom socket U6 on CS5 */ + m360.memc[5].br = (unsigned long)ATLASHSB_ROM_U6 | M360_MEMC_BR_WP | + M360_MEMC_BR_V; + m360.memc[5].or = M360_MEMC_OR_WAITS(2) | M360_MEMC_OR_512KB | + M360_MEMC_OR_8BIT; + + /* CSRs on CS7 */ + m360.memc[7].or = M360_MEMC_OR_TCYC(4) | M360_MEMC_OR_64KB | + M360_MEMC_OR_8BIT; + m360.memc[7].br = ATLASHSB_ESR | 0x01; + for (i = 0; i < 50000; i++) + continue; + for (i = 0; i < 8; ++i) + *((volatile unsigned long *)(unsigned long)&RamBase); + + /* + * Step 13: Copy the exception vector table to system RAM + */ + m68k_get_vbr (vbr); + for (i = 0; i < 256; ++i) + M68Kvec[i] = vbr[i]; + m68k_set_vbr (M68Kvec); + + /* + * Step 14: More system initialization + * SDCR (Serial DMA configuration register) + * Enable SDMA during FREEZE + * Give SDMA priority over all interrupt handlers + * Set DMA arbiration level to 4 + * CICR (CPM interrupt configuration register): + * SCC1 requests at SCCa position + * SCC2 requests at SCCb position + * SCC3 requests at SCCc position + * SCC4 requests at SCCd position + * Interrupt request level 4 + * Maintain original priority order + * Vector base 128 + * SCCs priority grouped at top of table + */ + m360.sdcr = M360_SDMA_SISM_7 | M360_SDMA_SAID_4; + m360.cicr = (3 << 22) | (2 << 20) | (1 << 18) | (0 << 16) | + (4 << 13) | (0x1F << 8) | (128); + + /* + * Step 15: Set module configuration register + * Disable timers during FREEZE + * Enable bus monitor during FREEZE + * BCLRO* arbitration level 3 + */ + +#elif defined(PGH360) + /* + * Step 6: Is this a power-up reset? + * For now we just ignore this and do *all* the steps + * Someday we might want to: + * if (Hard, Loss of Clock, Power-up) + * Do all steps + * else if (Double bus fault, watchdog or soft reset) + * Skip to step 12 + * else (must be a CPU32+ reset command) + * Skip to step 14 + */ + + /* + * Step 7: Deal with clock synthesizer + * HARDWARE: + * Change if you're not using an external 25 MHz oscillator. + */ + m360.clkocr = 0x8e; /* No more writes, CLKO1=1/3, CLKO2=off */ + /* + * adjust crystal to average between 4.19 MHz and 4.00 MHz + * reprogram pll + */ + m360.pllcr = 0xA000+(24576000/((4000000+4194304)/2/128))-1; + /* LPSTOP slowdown, PLL /128*??? */ + m360.cdvcr = 0x8000; /* No more writes, no clock division */ + + /* + * Step 8: Initialize system protection + * Enable watchdog + * Watchdog causes system reset + * 128 sec. watchdog timeout + * Enable double bus fault monitor + * Enable bus monitor external + * 128 clocks for external timeout + */ + m360.sypcr = 0xEF; + /* + * also initialize the SWP bit in PITR to 1 + */ + m360.pitr |= 0x0200; + /* + * and trigger SWSR twice to ensure, that interval starts right now + */ + m360.swsr = 0x55; + m360.swsr = 0xAA; + m360.swsr = 0x55; + m360.swsr = 0xAA; + /* + * Step 9: Clear parameter RAM and reset communication processor module + */ + for (i = 0 ; i < 192 ; i += sizeof (long)) { + *((long *)((char *)&m360 + 0xC00 + i)) = 0; + *((long *)((char *)&m360 + 0xD00 + i)) = 0; + *((long *)((char *)&m360 + 0xE00 + i)) = 0; + *((long *)((char *)&m360 + 0xF00 + i)) = 0; + } + M360ExecuteRISC (M360_CR_RST); + + /* + * Step 10: Write PEPAR + * SINTOUT not used (CPU32+ mode) + * CF1MODE=00 (CONFIG1 input) + * IPIPE1 + * WE0-3 + * OE* output + * CAS2* / CAS3* + * CAS0* / CAS1* + * CS7* + * AVEC* + * HARDWARE: + * Change if you are using a different memory configuration + * (static RAM, external address multiplexing, etc). + */ + m360.pepar = 0x0080; + /* + * Step 11: Remap Chip Select 0 (CS0*), set up GMR + * no DRAM support + * HARDWARE: + * Change if you are using a different memory configuration + */ + m360.gmr = M360_GMR_RCNT(23) | M360_GMR_RFEN | M360_GMR_RCYC(0) | + M360_GMR_PGS(6) | M360_GMR_DPS_32BIT | M360_GMR_DWQ | + M360_GMR_GAMX; + + m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP | + M360_MEMC_BR_V; + m360.memc[0].or = M360_MEMC_OR_WAITS(3) | M360_MEMC_OR_512KB | + M360_MEMC_OR_8BIT; + + /* + * Step 12: Initialize the system RAM + * Set up option/base registers + * 16 MB DRAM + * 1 wait state + * HARDWARE: + * Change if you are using a different memory configuration + * NOTE: no Page mode possible for EDO RAMs (?) + */ + ramSize = 16 * 1024 * 1024; + m360.memc[7].or = M360_MEMC_OR_TCYC(1) | M360_MEMC_OR_16MB | + M360_MEMC_OR_FCMC(0) | /* M360_MEMC_OR_PGME | */ + M360_MEMC_OR_32BIT | M360_MEMC_OR_DRAM; + m360.memc[7].br = (unsigned long)&RamBase | M360_MEMC_BR_V; + + /* + * FIXME: here we should wait for 8 refresh cycles... + */ + /* + * Step 12a: test the ram, if wanted + * FIXME: when do we call this? + * -> only during firmware execution + * -> perform intesive test only on request + * -> ensure, that results are stored properly + */ +#if 0 /* FIXME: activate RAM tests again */ + { + void *ram_base, *ram_end, *code_loc; + extern char ramtest_start,ramtest_end; + ram_base = &ramtest_start; + ram_end = &ramtest_end; + code_loc = (void *)ramtest_exec; + if ((ram_base < ram_end) && + !((ram_base <= code_loc) && (code_loc < ram_end))) { + ramtest_exec(ram_base,ram_end); + } + } +#endif + /* + * Step 13: Copy the exception vector table to system RAM + */ + m68k_get_vbr (vbr); + for (i = 0; i < 256; ++i) + M68Kvec[i] = vbr[i]; + m68k_set_vbr (M68Kvec); + + /* + * Step 14: More system initialization + * SDCR (Serial DMA configuration register) + * Disable SDMA during FREEZE + * Give SDMA priority over all interrupt handlers + * Set DMA arbiration level to 4 + * CICR (CPM interrupt configuration register): + * SCC1 requests at SCCa position + * SCC2 requests at SCCb position + * SCC3 requests at SCCc position + * SCC4 requests at SCCd position + * Interrupt request level 4 + * Maintain original priority order + * Vector base 128 + * SCCs priority grouped at top of table + */ + m360.sdcr = M360_SDMA_SISM_7 | M360_SDMA_SAID_4; + m360.cicr = (3 << 22) | (2 << 20) | (1 << 18) | (0 << 16) | + (4 << 13) | (0x1F << 8) | (128); + + /* + * Step 15: Set module configuration register + * Disable timers during FREEZE + * Enable bus monitor during FREEZE + * BCLRO* arbitration level 3 + * No show cycles + * User/supervisor access + * Bus clear interupt service level 7 + * SIM60 interrupt sources higher priority than CPM + */ + m360.mcr = 0x4C7F; + +#elif (defined (GEN68360_WITH_SRAM)) + /* + *************************************************** + * Generic Standalone Motorola 68360 * + * As described in MC68360 User's Manual * + * But uses SRAM instead of DRAM * + * CS0* - 512kx8 flash memory * + * CS1* - 512kx32 static RAM * + * CS2* - 512kx32 static RAM * + *************************************************** + */ + + /* + * Step 7: Deal with clock synthesizer + * HARDWARE: + * Change if you're not using an external oscillator which + * oscillates at the system clock rate. + */ + m360.clkocr = 0x8F; /* No more writes, no clock outputs */ + m360.pllcr = 0xD000; /* PLL, no writes, no prescale, + no LPSTOP slowdown, PLL X1 */ + m360.cdvcr = 0x8000; /* No more writes, no clock division */ + + /* + * Step 8: Initialize system protection + * Enable watchdog + * Watchdog causes system reset + * Next-to-slowest watchdog timeout (21 seconds with 25 MHz oscillator) + * Enable double bus fault monitor + * Enable bus monitor for external cycles + * 1024 clocks for external timeout + */ + m360.sypcr = 0xEC; + + /* + * Step 9: Clear parameter RAM and reset communication processor module + */ + for (i = 0 ; i < 192 ; i += sizeof (long)) { + *((long *)((char *)&m360 + 0xC00 + i)) = 0; + *((long *)((char *)&m360 + 0xD00 + i)) = 0; + *((long *)((char *)&m360 + 0xE00 + i)) = 0; + *((long *)((char *)&m360 + 0xF00 + i)) = 0; + } + M360ExecuteRISC (M360_CR_RST); + + /* + * Step 10: Write PEPAR + * SINTOUT not used (CPU32+ mode) + * CF1MODE=00 (CONFIG1 input) + * IPIPE1* + * WE0* - WE3* + * OE* output + * CAS2* - CAS3* + * CAS0* - CAS1* + * CS7* + * AVEC* + * HARDWARE: + * Change if you are using a different memory configuration + * (static RAM, external address multiplexing, etc). + */ + m360.pepar = 0x0080; + + /* + * Step 11: Set up GMR + * + */ + m360.gmr = 0x0; + + /* + * Step 11a: Remap 512Kx8 flash memory on CS0* + * 2 wait states + * Make it read-only for now + */ + m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP | + M360_MEMC_BR_V; + m360.memc[0].or = M360_MEMC_OR_WAITS(2) | M360_MEMC_OR_512KB | + M360_MEMC_OR_8BIT; + /* + * Step 12: Set up main memory + * 512Kx32 SRAM on CS1* + * 512Kx32 SRAM on CS2* + * 0 wait states + */ + ramSize = 4 * 1024 * 1024; + m360.memc[1].br = (unsigned long)&RamBase | M360_MEMC_BR_V; + m360.memc[1].or = M360_MEMC_OR_WAITS(0) | M360_MEMC_OR_2MB | + M360_MEMC_OR_32BIT; + m360.memc[2].br = ((unsigned long)&RamBase + 0x200000) | M360_MEMC_BR_V; + m360.memc[2].or = M360_MEMC_OR_WAITS(0) | M360_MEMC_OR_2MB | + M360_MEMC_OR_32BIT; + /* + * Step 13: Copy the exception vector table to system RAM + */ + m68k_get_vbr (vbr); + for (i = 0; i < 256; ++i) + M68Kvec[i] = vbr[i]; + m68k_set_vbr (M68Kvec); + + /* + * Step 14: More system initialization + * SDCR (Serial DMA configuration register) + * Enable SDMA during FREEZE + * Give SDMA priority over all interrupt handlers + * Set DMA arbiration level to 4 + * CICR (CPM interrupt configuration register): + * SCC1 requests at SCCa position + * SCC2 requests at SCCb position + * SCC3 requests at SCCc position + * SCC4 requests at SCCd position + * Interrupt request level 4 + * Maintain original priority order + * Vector base 128 + * SCCs priority grouped at top of table + */ + m360.sdcr = M360_SDMA_SISM_7 | M360_SDMA_SAID_4; + m360.cicr = (3 << 22) | (2 << 20) | (1 << 18) | (0 << 16) | + (4 << 13) | (0x1F << 8) | (128); + + /* + * Step 15: Set module configuration register + * Disable timers during FREEZE + * Enable bus monitor during FREEZE + * BCLRO* arbitration level 3 + * No show cycles + * User/supervisor access + * Bus clear interrupt service level 7 + * SIM60 interrupt sources higher priority than CPM + */ + m360.mcr = 0x4C7F; + +#else + volatile unsigned long *RamBase_p; + + RamBase_p = (volatile unsigned long *)&RamBase; + /* + *************************************************** + * Generic Standalone Motorola 68360 * + * As described in MC68360 User's Manual * + * Atlas ACE360 * + *************************************************** + */ + + /* + * Step 6: Is this a power-up reset? + * For now we just ignore this and do *all* the steps + * Someday we might want to: + * if (Hard, Loss of Clock, Power-up) + * Do all steps + * else if (Double bus fault, watchdog or soft reset) + * Skip to step 12 + * else (must be a CPU32+ reset command) + * Skip to step 14 + */ + + /* + * Step 7: Deal with clock synthesizer + * HARDWARE: + * Change if you're not using an external 25 MHz oscillator. + */ + m360.clkocr = 0x8F; /* No more writes, no clock outputs */ + m360.pllcr = 0xD000; /* PLL, no writes, no prescale, + no LPSTOP slowdown, PLL X1 */ + m360.cdvcr = 0x8000; /* No more writes, no clock division */ + + /* + * Step 8: Initialize system protection + * Enable watchdog + * Watchdog causes system reset + * Next-to-slowest watchdog timeout (21 seconds with 25 MHz oscillator) + * Enable double bus fault monitor + * Enable bus monitor for external cycles + * 1024 clocks for external timeout + */ + m360.sypcr = 0xEC; + + /* + * Step 9: Clear parameter RAM and reset communication processor module + */ + for (i = 0 ; i < 192 ; i += sizeof (long)) { + *((long *)((char *)&m360 + 0xC00 + i)) = 0; + *((long *)((char *)&m360 + 0xD00 + i)) = 0; + *((long *)((char *)&m360 + 0xE00 + i)) = 0; + *((long *)((char *)&m360 + 0xF00 + i)) = 0; + } + M360ExecuteRISC (M360_CR_RST); + + /* + * Step 10: Write PEPAR + * SINTOUT not used (CPU32+ mode) + * CF1MODE=00 (CONFIG1 input) + * RAS1* double drive + * WE0* - WE3* + * OE* output + * CAS2* - CAS3* + * CAS0* - CAS1* + * CS7* + * AVEC* + * HARDWARE: + * Change if you are using a different memory configuration + * (static RAM, external address multiplexing, etc). + */ + m360.pepar = 0x0180; + + /* + * Step 11: Remap Chip Select 0 (CS0*), set up GMR + * 32-bit DRAM + * Internal DRAM address multiplexing + * 60 nsec DRAM + * 180 nsec ROM (3 wait states) + * 15.36 usec DRAM refresh interval + * The DRAM page size selection is not modified since this + * startup code may be running in a bootstrap PROM or in + * a program downloaded by the bootstrap PROM. + */ + m360.gmr = (m360.gmr & 0x001C0000) | M360_GMR_RCNT(23) | + M360_GMR_RFEN | M360_GMR_RCYC(0) | + M360_GMR_DPS_32BIT | M360_GMR_NCS | + M360_GMR_GAMX; + m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP | + M360_MEMC_BR_V; + m360.memc[0].or = M360_MEMC_OR_WAITS(3) | M360_MEMC_OR_1MB | + M360_MEMC_OR_8BIT; + + /* + * Step 12: Initialize the system RAM + * Do this only if the DRAM has not already been set up + */ + if ((m360.memc[1].br & M360_MEMC_BR_V) == 0) { + /* + * Set up GMR DRAM page size, option and base registers + * Assume 16Mbytes of DRAM + * 60 nsec DRAM + */ + m360.gmr = (m360.gmr & ~0x001C0000) | M360_GMR_PGS(5); + m360.memc[1].or = M360_MEMC_OR_TCYC(0) | + M360_MEMC_OR_16MB | + M360_MEMC_OR_DRAM; + m360.memc[1].br = (unsigned long)&RamBase | M360_MEMC_BR_V; + + /* + * Wait for chips to power up + * Perform 8 read cycles + */ + for (i = 0; i < 50000; i++) + continue; + for (i = 0; i < 8; ++i) + *RamBase_p; + + /* + * Determine memory size (1, 4, or 16 Mbytes) + * Set GMR DRAM page size appropriately. + * The OR is left at 16 Mbytes. The bootstrap PROM places its + * .data and .bss segments at the top of the 16 Mbyte space. + * A 1 Mbyte or 4 Mbyte DRAM will show up several times in + * the memory map, but will work with the same bootstrap PROM. + */ + *(volatile char *)&RamBase = 0; + *((volatile char *)&RamBase+0x00C01800) = 1; + if (*(volatile char *)&RamBase) { + m360.gmr = (m360.gmr & ~0x001C0000) | M360_GMR_PGS(1); + } + else { + *((volatile char *)&RamBase+0x00801000) = 1; + if (*(volatile char *)&RamBase) { + m360.gmr = (m360.gmr & ~0x001C0000) | M360_GMR_PGS(3); + } + } + + /* + * Enable parity checking + */ + m360.memc[1].br |= M360_MEMC_BR_PAREN; + } + switch (m360.gmr & 0x001C0000) { + default: ramSize = 4 * 1024 * 1024; break; + case M360_GMR_PGS(1): ramSize = 1 * 1024 * 1024; break; + case M360_GMR_PGS(3): ramSize = 4 * 1024 * 1024; break; + case M360_GMR_PGS(5): ramSize = 16 * 1024 * 1024; break; + } + + /* + * Step 13: Copy the exception vector table to system RAM + */ + m68k_get_vbr (vbr); + for (i = 0; i < 256; ++i) + M68Kvec[i] = vbr[i]; + m68k_set_vbr (M68Kvec); + + /* + * Step 14: More system initialization + * SDCR (Serial DMA configuration register) + * Enable SDMA during FREEZE + * Give SDMA priority over all interrupt handlers + * Set DMA arbiration level to 4 + * CICR (CPM interrupt configuration register): + * SCC1 requests at SCCa position + * SCC2 requests at SCCb position + * SCC3 requests at SCCc position + * SCC4 requests at SCCd position + * Interrupt request level 4 + * Maintain original priority order + * Vector base 128 + * SCCs priority grouped at top of table + */ + m360.sdcr = M360_SDMA_SISM_7 | M360_SDMA_SAID_4; + m360.cicr = (3 << 22) | (2 << 20) | (1 << 18) | (0 << 16) | + (4 << 13) | (0x1F << 8) | (128); + + /* + * Step 15: Set module configuration register + * Disable timers during FREEZE + * Enable bus monitor during FREEZE + * BCLRO* arbitration level 3 + * No show cycles + * User/supervisor access + * Bus clear interrupt service level 7 + * SIM60 interrupt sources higher priority than CPM + */ + m360.mcr = 0x4C7F; +#endif + + /* + * Copy data, clear BSS, switch stacks and call main() + * Must pass ramSize as argument since the data/bss segment + * may be overwritten. + */ + _CopyDataClearBSSAndStart (ramSize); +} diff --git a/bsps/m68k/gen68360/start/linkcmds b/bsps/m68k/gen68360/start/linkcmds new file mode 100644 index 0000000000..4ffc8bb57a --- /dev/null +++ b/bsps/m68k/gen68360/start/linkcmds @@ -0,0 +1,209 @@ +/* + * This file contains GNU linker directives for a generic MC68360 board. + * Variations in memory size and allocation can be made by + * overriding some values with linker command-line arguments. + * + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * Saskatoon, Saskatchewan, CANADA + * eric@skatter.usask.ca + */ + +/* + * Declare some sizes. + * A heap size of 0 means `use all available memory for the heap'. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamSize : 64M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x1000; + +/* + * Declare on-board memory. + */ +MEMORY { + ram : ORIGIN = 0x00000000, LENGTH = 64M + rom : ORIGIN = 0x0F000000, LENGTH = 1M + dpram : ORIGIN = 0x0E000000, LENGTH = 8k +} + +ENTRY(start) +STARTUP(start.o) + +/* + * Load objects + */ +SECTIONS { + /* + * Boot PROM + */ + rom : { + _RomBase = .; + } >rom + + /* + * Dynamic RAM + */ + ram : { + RamBase = .; + } >ram + + /* + * Text, data and bss segments + */ + .text : { + *(.text*) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * C++ constructors/destructors + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + PROVIDE (etext = .); + } >ram + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >ram + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >ram + + _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)); + + .data : { + _copy_start = .; + *(.data*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (16); + PROVIDE (edata = .); + _copy_end = .; + } >ram + .bss : { + M68Kvec = .; + . += (256 * 4); + _clear_start = .; + *(.dynbss) + *(.bss* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (16); + PROVIDE (end = .); + + . += _StackSize; + . = ALIGN (16); + _stack_init = .; + _clear_end = .; + + WorkAreaBase = .; + } >ram + + /* + * On-chip memory/peripherals + */ + dpram : { + m360 = .; + . += (8 * 1024); + } >dpram + + /* 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) } + .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) } + /* These must appear regardless of . */ +} diff --git a/bsps/m68k/gen68360/start/linkcmds.bootp b/bsps/m68k/gen68360/start/linkcmds.bootp new file mode 100644 index 0000000000..ccd08a14a2 --- /dev/null +++ b/bsps/m68k/gen68360/start/linkcmds.bootp @@ -0,0 +1,171 @@ +/* + * This file contains GNU linker directives for a generic MC68360 board. + * Variations in memory size and allocation can be made by + * overriding some values with linker command-line arguments. + * + * These linker directives are for producing a bootstrap PROM version. + * The data segment is placed at the end of the text segment in the PROM. + * The start-up code takes care of copying this region to RAM. + * + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * Saskatoon, Saskatchewan, CANADA + * eric@skatter.usask.ca + */ + +/* + * Declare some sizes. + * A heap size of 0 means `use all available memory for the heap'. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamSize : 64M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x1000; + +/* + * Declare on-board memory. + */ +MEMORY { + ram : ORIGIN = 0x00000000, LENGTH = 64M + myram : ORIGIN = 16M-400k, LENGTH = 400k + rom : ORIGIN = 0x0F000000, LENGTH = 1M + dpram : ORIGIN = 0x0E000000, LENGTH = 8k +} + +/* + * Load objects + */ +SECTIONS { + /* + * Boot PROM + */ + rom : { + _RomBase = .; + } >rom + + /* + * Dynamic RAM + */ + ram : { + RamBase = .; + } >ram + + /* + * Text, data and bss segments + */ + .text : AT(0x0) { + *(.text*) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * C++ constructors/destructors + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + PROVIDE (etext = .); + } >rom + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >rom + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >rom + + _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)); + + .data : AT(SIZEOF(.text)) { + _copy_start = .; + *(.data) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + *(.jcr) + *(.gcc_except_table*) + . = ALIGN (16); + PROVIDE (edata = .); + _copy_end = .; + } >myram + .bss : { + M68Kvec = .; + . += (256 * 4); + _clear_start = .; + *(.dynbss) + *(.bss* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (16); + PROVIDE (end = .); + + . += _StackSize; + . = ALIGN (16); + _stack_init = .; + _clear_end = .; + + WorkAreaBase = .; + } >myram + + /* + * On-chip memory/peripherals + */ + dpram : { + m360 = .; + . += (8 * 1024); + } >dpram +} diff --git a/bsps/m68k/gen68360/start/linkcmds.prom b/bsps/m68k/gen68360/start/linkcmds.prom new file mode 100644 index 0000000000..777700e6a1 --- /dev/null +++ b/bsps/m68k/gen68360/start/linkcmds.prom @@ -0,0 +1,169 @@ +/* + * This file contains GNU linker directives for a generic MC68360 board. + * Variations in memory size and allocation can be made by + * overriding some values with linker command-line arguments. + * + * These linker directives are for producing a PROM version. + * The data segment is placed at the end of the text segment in the PROM. + * The start-up code takes care of copying this region to RAM. + * + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * Saskatoon, Saskatchewan, CANADA + * eric@skatter.usask.ca + */ + +/* + * Declare some sizes. + * A heap size of 0 means `use all available memory for the heap'. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamSize : 64M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x1000; + +/* + * Declare on-board memory. + */ +MEMORY { + ram : ORIGIN = 0x00000000, LENGTH = 64M + rom : ORIGIN = 0x0F000000, LENGTH = 1M + dpram : ORIGIN = 0x0E000000, LENGTH = 8k +} + +/* + * Load objects + */ +SECTIONS { + /* + * Boot PROM + */ + rom : { + _RomBase = .; + } >rom + + /* + * Dynamic RAM + */ + ram : { + RamBase = .; + } >ram + + /* + * Text, data and bss segments + */ + .text : AT(0x0) { + *(.text*) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * C++ constructors/destructors + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + PROVIDE (etext = .); + } >rom + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >rom + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >rom + + _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)); + + .data : AT(SIZEOF(.text)) { + _copy_start = .; + *(.data) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + *(.jcr) + *(.gcc_except_table*) + . = ALIGN (16); + PROVIDE (edata = .); + _copy_end = .; + } >ram + .bss : { + M68Kvec = .; + . += (256 * 4); + *(.dynbss) + *(.bss* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (16); + PROVIDE (end = .); + + . += _StackSize; + . = ALIGN (16); + _stack_init = .; + _clear_end = .; + + WorkAreaBase = .; + } >ram + + /* + * On-chip memory/peripherals + */ + dpram : { + m360 = .; + . += (8 * 1024); + } >dpram +} diff --git a/bsps/m68k/genmcf548x/start/bsp_specs b/bsps/m68k/genmcf548x/start/bsp_specs new file mode 100644 index 0000000000..3a20757667 --- /dev/null +++ b/bsps/m68k/genmcf548x/start/bsp_specs @@ -0,0 +1,10 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s crtn.o%s} + diff --git a/bsps/m68k/genmcf548x/start/bspstart.c b/bsps/m68k/genmcf548x/start/bspstart.c new file mode 100644 index 0000000000..6c1da2a738 --- /dev/null +++ b/bsps/m68k/genmcf548x/start/bspstart.c @@ -0,0 +1,206 @@ +/*===============================================================*\ +| Project: RTEMS generic mcf548x BSP | ++-----------------------------------------------------------------+ +| File: bspstart.c | ++-----------------------------------------------------------------+ +| The file contains the startup code of generic MCF548x BSP | ++-----------------------------------------------------------------+ +| Copyright (c) 2007 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| | +| Parts of the code has been derived from the "dBUG source code" | +| package Freescale is providing for M548X EVBs. The usage of | +| the modified or unmodified code and it's integration into the | +| generic mcf548x BSP has been done according to the Freescale | +| license terms. | +| | +| The Freescale license terms can be reviewed in the file | +| | +| Freescale_license.txt | +| | ++-----------------------------------------------------------------+ +| | +| The generic mcf548x BSP has been developed on the basic | +| structures and modules of the av5282 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. | +| | ++-----------------------------------------------------------------+ +| | +| date history ID | +| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | +| 12.11.07 1.0 ras | +| | +\*===============================================================*/ + +#include <bsp.h> +#include <bsp/bootcard.h> + +extern uint32_t _CPU_cacr_shadow; + +/* +* These labels (!) are defined in the linker command file or when the linker is +* invoked. +* NOTE: The information (size) is the address of the object, not the object +* itself. +*/ + +extern char _SdramBase[]; +extern char _BootFlashBase[]; +extern char _CodeFlashBase[]; +extern char _SdramSize[]; +extern char _BootFlashSize[]; +extern char _CodeFlashSize[]; +extern char _TopRamReserved []; +extern char WorkAreaBase []; + +/* + * CPU-space access + */ +#define m68k_set_acr2(_acr2) __asm__ volatile ("movec %0,#0x0005" : : "d" (_acr2)) +#define m68k_set_acr3(_acr3) __asm__ volatile ("movec %0,#0x0007" : : "d" (_acr3)) + +/* + * Set initial CACR mode, mainly enables branch/instruction/data cache. The + * FPU must be switched on in the BSP startup code since the + * _Thread_Start_multitasking() will restore the floating-point context of the + * initialization task if necessary. + */ +static const uint32_t BSP_CACR_INIT = MCF548X_CACR_DEC /* enable data cache */ + | MCF548X_CACR_BEC /* enable branch cache */ + | MCF548X_CACR_IEC /* enable instruction cache */ + | MCF548X_CACR_DDCM(DCACHE_ON_WRIGHTTHROUGH) + /* set data cache mode to write-through */ + | MCF548X_CACR_DESB /* enable data store buffer */ + | MCF548X_CACR_DDSP /* data access only in supv. mode */ + | MCF548X_CACR_IDSP; /* instr. access only in supv. mode */ + +/* + * CACR maintenance functions + */ + +void bsp_cacr_set_flags( uint32_t flags) +{ + rtems_interrupt_level level; + + rtems_interrupt_disable( level); + _CPU_cacr_shadow |= flags; + m68k_set_cacr( _CPU_cacr_shadow); + rtems_interrupt_enable( level); +} + +void bsp_cacr_set_self_clear_flags( uint32_t flags) +{ + rtems_interrupt_level level; + uint32_t cacr = 0; + + rtems_interrupt_disable( level); + cacr = _CPU_cacr_shadow | flags; + m68k_set_cacr( cacr); + rtems_interrupt_enable( level); +} + +void bsp_cacr_clear_flags( uint32_t flags) +{ + rtems_interrupt_level level; + + rtems_interrupt_disable( level); + _CPU_cacr_shadow &= ~flags; + m68k_set_cacr( _CPU_cacr_shadow); + rtems_interrupt_enable( level); +} + +/* + * Coldfire acr and mmu settings + */ + static void acr_mmu_mapping(void) + { + + /* + * Cache disabled for internal register area (256 kB). + * Choose the smallest maskable size of 1MB. + */ + m68k_set_acr0(MCF548X_ACR_BA((uint32_t)(__MBAR)) | + MCF548X_ACR_ADMSK_AMM((uint32_t)(0xFFFFF)) | + MCF548X_ACR_E | + MCF548X_ACR_SP /* supervisor protection */ | + MCF548X_ACR_S(S_ACCESS_SUPV) /* always in supervisor mode */ | + MCF548X_ACR_CM(CM_OFF_PRECISE)); + +#ifdef M5484FIREENGINE + + + /* + * Cache enabled for entire SDRAM (64 MB) + */ + m68k_set_acr1(MCF548X_ACR_BA((uint32_t)(_SdramBase)) | + MCF548X_ACR_ADMSK_AMM((uint32_t)(_SdramSize - 1)) | + MCF548X_ACR_E | + MCF548X_ACR_SP /* supervisor protection */ | + MCF548X_ACR_S(S_ACCESS_SUPV) /* always in supervisor mode */ | + MCF548X_ACR_CM(CM_ON_WRIGHTTHROUGH)); + + /* + * Cache enabled for entire boot flash (2 MB) + */ + m68k_set_acr2(MCF548X_ACR_BA((uint32_t)(_BootFlashBase)) | + MCF548X_ACR_ADMSK_AMM((uint32_t)(_BootFlashSize - 1)) | + MCF548X_ACR_E | + MCF548X_ACR_SP /* supervisor protection */ | + MCF548X_ACR_S(S_ACCESS_SUPV) /* always in supervisor mode */ | + MCF548X_ACR_CM(CM_ON_COPYBACK)); + + /* + * Cache enabled for entire code flash (16 MB) + */ + m68k_set_acr3(MCF548X_ACR_BA((uint32_t)(_CodeFlashBase)) | + MCF548X_ACR_ADMSK_AMM((uint32_t)(_CodeFlashSize - 1)) | + MCF548X_ACR_E | + MCF548X_ACR_SP /* supervisor protection */ | + MCF548X_ACR_S(S_ACCESS_SUPV) /* always in supervisor mode */ | + MCF548X_ACR_CM(CM_ON_COPYBACK)); +#endif + + } + +/* + * bsp_start + * + * This routine does the bulk of the system initialisation. + */ +void bsp_start( void ) +{ + /* Initialize CACR shadow register */ + _CPU_cacr_shadow = BSP_CACR_INIT; + + /* + * Load the shadow variable of CACR with initial mode and write it to the + * CACR. Interrupts are still disabled, so there is no need for surrounding + * rtems_interrupt_enable() / rtems_interrupt_disable(). + */ + m68k_set_cacr( _CPU_cacr_shadow); + + /* + * do mapping of acr's and/or mmu + */ + acr_mmu_mapping(); +} + + +/* + * Get the XLB clock speed + */ +uint32_t get_CPU_clock_speed(void) +{ + return (uint32_t)BSP_CPU_CLOCK_SPEED; +} diff --git a/bsps/m68k/genmcf548x/start/init548x.c b/bsps/m68k/genmcf548x/start/init548x.c new file mode 100644 index 0000000000..c83c061f31 --- /dev/null +++ b/bsps/m68k/genmcf548x/start/init548x.c @@ -0,0 +1,321 @@ +/*===============================================================*\ +| Project: RTEMS generic mcf548x BSP | ++-----------------------------------------------------------------+ +| File: init548x.c | ++-----------------------------------------------------------------+ +| The file contains the c part of MCF548x init code | ++-----------------------------------------------------------------+ +| Copyright (c) 2007 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| | +| Parts of the code has been derived from the "dBUG source code" | +| package Freescale is providing for M548X EVBs. The usage of | +| the modified or unmodified code and it's integration into the | +| generic mcf548x BSP has been done according to the Freescale | +| license terms. | +| | +| The Freescale license terms can be reviewed in the file | +| | +| Freescale_license.txt | +| | ++-----------------------------------------------------------------+ +| | +| The generic mcf548x BSP has been developed on the basic | +| structures and modules of the av5282 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. | +| | ++-----------------------------------------------------------------+ +| | +| date history ID | +| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | +| 12.11.07 1.0 ras | +| | +\*===============================================================*/ + +#include <bsp.h> + +#include <string.h> + +#include <bsp/linker-symbols.h> + +#if defined(HAS_LOW_LEVEL_INIT) +#define SYSTEM_PERIOD 10 /* system bus period in ns */ + +/* SDRAM Timing Parameters */ +#define SDRAM_TWR 2 /* in clocks */ +#define SDRAM_CASL 2.5 /* in clocks */ +#define SDRAM_TRCD 20 /* in ns */ +#define SDRAM_TRP 20 /* in ns */ +#define SDRAM_TRFC 75 /* in ns */ +#define SDRAM_TREFI 7800 /* in ns */ +#endif /* defined(HAS_LOW_LEVEL_INIT) */ + +extern uint8_t _DataRom[]; +extern uint8_t _DataRam[]; +extern uint8_t _DataEnd[]; +extern uint8_t _BssStart[]; +extern uint8_t _BssEnd[]; +extern uint8_t _BootFlashBase[]; +extern uint8_t _CodeFlashBase[]; +extern uint8_t RamBase[]; + +void gpio_init(void); +void fbcs_init(void); +void sdramc_init(void); +void mcf548x_init(void); + + +void mcf548x_init(void) +{ + size_t i; + +#if defined(HAS_LOW_LEVEL_INIT) + /* set XLB arbiter timeouts */ + MCF548X_XLB_ADRTO = 0x00000100; + MCF548X_XLB_DATTO = 0x00000100; + MCF548X_XLB_BUSTO = 0x00000100; +#endif + + gpio_init(); +#if defined(HAS_LOW_LEVEL_INIT) + fbcs_init(); + sdramc_init(); +#endif /* defined(HAS_LOW_LEVEL_INIT) */ + + /* Copy the vector table to RAM if necessary */ + if (bsp_vector0_size == bsp_vector1_size) { + memcpy(bsp_vector1_begin, bsp_vector0_begin, (size_t) bsp_vector1_size); + m68k_set_vbr((uint32_t)bsp_vector1_begin); + } + + /* Move initialized data from ROM to RAM. */ + if (bsp_section_data_begin != bsp_section_data_load_begin) { + memcpy( + bsp_section_data_begin, + bsp_section_data_load_begin, + (size_t) bsp_section_data_size + ); + } + + /* Zero uninitialized data */ + memset(bsp_section_bss_begin, 0, (size_t) bsp_section_bss_size); + + for (i = 8; i < RTEMS_ARRAY_SIZE(mcf548x_intc_icr_init_values); ++i) { + volatile uint8_t *icr = &MCF548X_INTC_ICR0; + + icr[i] = mcf548x_intc_icr_init_values[i]; + } +} +/********************************************************************/ +#if defined(HAS_LOW_LEVEL_INIT) +void +fbcs_init (void) +{ +#ifdef M5484FIREENGINE + +volatile uint32_t cscr, clk_ratio, fb_period, ws; + +/* boot flash already valid ? */ +if(!(MCF548X_FBCS_CSMR0 & MCF548X_FBCS_CSMR_V)) + { + + /* + * Boot Flash + */ + MCF548X_FBCS_CSAR0 = MCF548X_FBCS_CSAR_BA((uint32_t)(_BootFlashBase)); + + cscr = (0 + | MCF548X_FBCS_CSCR_ASET(1) + | MCF548X_FBCS_CSCR_WRAH(0) + | MCF548X_FBCS_CSCR_RDAH(0) + | MCF548X_FBCS_CSCR_AA + | MCF548X_FBCS_CSCR_PS_16); + + /* + * Determine the necessary wait states based on the defined system + * period (XLB clock period) and the CLKIN to XLB ratio. + * The boot flash has a max access time of 110ns. + */ + clk_ratio = (MCF548X_PCI_PCIGSCR >> 24) & 0x7; + fb_period = SYSTEM_PERIOD * clk_ratio; + ws = 110 / fb_period; + + MCF548X_FBCS_CSCR0 = cscr | MCF548X_FBCS_CSCR_WS(ws); + MCF548X_FBCS_CSMR0 = (0 + | MCF548X_FBCS_CSMR_BAM_2M + | MCF548X_FBCS_CSMR_V); + + } + +/* code flash already valid ? */ +if(!(MCF548X_FBCS_CSMR1 & MCF548X_FBCS_CSMR_V)) + { + + /* + * Code Flash + */ + MCF548X_FBCS_CSAR1 = MCF548X_FBCS_CSAR_BA((uint32_t)(_CodeFlashBase)); + + /* + * Determine the necessary wait states based on the defined system + * period (XLB clock period) and the CLKIN to XLB ratio. + * The user/code flash has a max access time of 120ns. + */ + ws = 120 / fb_period; + MCF548X_FBCS_CSCR1 = cscr | MCF548X_FBCS_CSCR_WS(ws); + MCF548X_FBCS_CSMR1 = (0 + | MCF548X_FBCS_CSMR_BAM_16M + | MCF548X_FBCS_CSMR_V); + } + +#endif +} +#endif /* defined(HAS_LOW_LEVEL_INIT) */ + +/********************************************************************/ +#if defined(HAS_LOW_LEVEL_INIT) +void +sdramc_init (void) +{ + + /* + * Check to see if the SDRAM has already been initialized + * by a run control tool + */ + if (!(MCF548X_SDRAMC_SDCR & MCF548X_SDRAMC_SDCR_REF)) + { + /* + * Basic configuration and initialization + */ + MCF548X_SDRAMC_SDRAMDS = (0 + | MCF548X_SDRAMC_SDRAMDS_SB_E(MCF548X_SDRAMC_SDRAMDS_DRIVE_8MA) + | MCF548X_SDRAMC_SDRAMDS_SB_C(MCF548X_SDRAMC_SDRAMDS_DRIVE_8MA) + | MCF548X_SDRAMC_SDRAMDS_SB_A(MCF548X_SDRAMC_SDRAMDS_DRIVE_8MA) + | MCF548X_SDRAMC_SDRAMDS_SB_S(MCF548X_SDRAMC_SDRAMDS_DRIVE_8MA) + | MCF548X_SDRAMC_SDRAMDS_SB_D(MCF548X_SDRAMC_SDRAMDS_DRIVE_8MA) + ); + MCF548X_SDRAMC_CS0CFG = (0 + | MCF548X_SDRAMC_CSnCFG_CSBA((uint32_t)(RamBase)) + | MCF548X_SDRAMC_CSnCFG_CSSZ(MCF548X_SDRAMC_CSnCFG_CSSZ_64MBYTE) + ); + MCF548X_SDRAMC_SDCFG1 = (0 + | MCF548X_SDRAMC_SDCFG1_SRD2RW(7) + | MCF548X_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1) + | MCF548X_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2)) + | MCF548X_SDRAMC_SDCFG1_ACT2RW((int)(((SDRAM_TRCD/SYSTEM_PERIOD) - 1) + 0.5)) + | MCF548X_SDRAMC_SDCFG1_PRE2ACT((int)(((SDRAM_TRP/SYSTEM_PERIOD) - 1) + 0.5)) + | MCF548X_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC/SYSTEM_PERIOD) - 1) + 0.5)) + | MCF548X_SDRAMC_SDCFG1_WTLAT(3) + ); + MCF548X_SDRAMC_SDCFG2 = (0 + | MCF548X_SDRAMC_SDCFG2_BRD2PRE(4) + | MCF548X_SDRAMC_SDCFG2_BWT2RW(6) + | MCF548X_SDRAMC_SDCFG2_BRD2WT(7) + | MCF548X_SDRAMC_SDCFG2_BL(7) + ); + + /* + * Precharge and enable write to SDMR + */ + MCF548X_SDRAMC_SDCR = (0 + | MCF548X_SDRAMC_SDCR_MODE_EN + | MCF548X_SDRAMC_SDCR_CKE + | MCF548X_SDRAMC_SDCR_DDR + | MCF548X_SDRAMC_SDCR_MUX(1) + | MCF548X_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5)) + | MCF548X_SDRAMC_SDCR_IPALL + ); + + /* + * Write extended mode register + */ + MCF548X_SDRAMC_SDMR = (0 + | MCF548X_SDRAMC_SDMR_BNKAD_LEMR + | MCF548X_SDRAMC_SDMR_AD(0x0) + | MCF548X_SDRAMC_SDMR_CMD + ); + + /* + * Write mode register and reset DLL + */ + MCF548X_SDRAMC_SDMR = (0 + | MCF548X_SDRAMC_SDMR_BNKAD_LMR + | MCF548X_SDRAMC_SDMR_AD(0x163) + | MCF548X_SDRAMC_SDMR_CMD + ); + + /* + * Execute a PALL command + */ + MCF548X_SDRAMC_SDCR |=MCF548X_SDRAMC_SDCR_IPALL; + + /* + * Perform two REF cycles + */ + MCF548X_SDRAMC_SDCR |= MCF548X_SDRAMC_SDCR_IREF; + MCF548X_SDRAMC_SDCR |= MCF548X_SDRAMC_SDCR_IREF; + + /* + * Write mode register and clear reset DLL + */ + MCF548X_SDRAMC_SDMR = (0 + | MCF548X_SDRAMC_SDMR_BNKAD_LMR + | MCF548X_SDRAMC_SDMR_AD(0x063) + | MCF548X_SDRAMC_SDMR_CMD + ); + + /* + * Enable auto refresh and lock SDMR + */ + MCF548X_SDRAMC_SDCR &= ~MCF548X_SDRAMC_SDCR_MODE_EN; + MCF548X_SDRAMC_SDCR |= (0 + | MCF548X_SDRAMC_SDCR_REF + | MCF548X_SDRAMC_SDCR_DQS_OE(0xF) + ); + } + +} +#endif /* defined(HAS_LOW_LEVEL_INIT) */ + +/********************************************************************/ +void +gpio_init(void) +{ + +#ifdef M5484FIREENGINE + + /* + * Enable Ethernet signals so that, if a cable is plugged into + * the ports, the lines won't be floating and potentially cause + * erroneous transmissions + */ + MCF548X_GPIO_PAR_FECI2CIRQ = (0 + + | MCF548X_GPIO_PAR_FECI2CIRQ_PAR_E1MDC_EMDC + | MCF548X_GPIO_PAR_FECI2CIRQ_PAR_E1MDIO_EMDIO + | MCF548X_GPIO_PAR_FECI2CIRQ_PAR_E1MII + | MCF548X_GPIO_PAR_FECI2CIRQ_PAR_E17 + + | MCF548X_GPIO_PAR_FECI2CIRQ_PAR_E0MDC + | MCF548X_GPIO_PAR_FECI2CIRQ_PAR_E0MDIO + | MCF548X_GPIO_PAR_FECI2CIRQ_PAR_E0MII + | MCF548X_GPIO_PAR_FECI2CIRQ_PAR_E07 + ); + +#endif + /* + * make sure the "edge port" has all interrupts disabled + */ + MCF548X_EPORT_EPIER = 0; +} diff --git a/bsps/m68k/genmcf548x/start/linkcmds.COBRA5475 b/bsps/m68k/genmcf548x/start/linkcmds.COBRA5475 new file mode 100644 index 0000000000..52bca8d018 --- /dev/null +++ b/bsps/m68k/genmcf548x/start/linkcmds.COBRA5475 @@ -0,0 +1,82 @@ +/*===============================================================*\ +| Project: RTEMS generic mcf548x BSP | ++-----------------------------------------------------------------+ +| File: linkcmds.COBRA5475 | ++-----------------------------------------------------------------+ +| The file contains the linker directives for the generic MCF548x | +| BSP to be used with an COBRA5475 board to load and execute | +| code in the RAM. | ++-----------------------------------------------------------------+ +| Copyright (c) 2007 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| | +| Parts of the code has been derived from the "dBUG source code" | +| package Freescale is providing for M548X EVBs. The usage of | +| the modified or unmodified code and it's integration into the | +| generic mcf548x BSP has been done according to the Freescale | +| license terms. | +| | +| The Freescale license terms can be reviewed in the file | +| | +| Freescale_license.txt | +| | ++-----------------------------------------------------------------+ +| | +| The generic mcf548x BSP has been developed on the basic | +| structures and modules of the av5282 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. | +| | ++-----------------------------------------------------------------+ +| | +| date history ID | +| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | +| 12.11.07 1.0 ras | +| 15.10.09 1.1, adapted to COBRA5475 doe | +| | +\*===============================================================*/ + +/* + * Location and size of on-chip devices + */ +_SdramBase = DEFINED(_SdramBase) ? _SdramBase : 0xf0000000; +_SdramSize = DEFINED(_SdramSize) ? _SdramSize : (128 * 1024*1024); +_SysSramBase = DEFINED(_SysSramBase) ? _SysSramBase : __MBAR + 0x00010000; +_SysSramSize = DEFINED(_SysSramSize) ? _SysSramSize : (32 * 1024); +_McdapiBase = DEFINED(_McdapiBase) ? _McdapiBase : _SysSramBase; +_McdapiSize = DEFINED(_McdapiSize) ? _McdapiSize : (12 * 1024); +_CoreSramBase0 = DEFINED(_CoreSramBase0) ? _CoreSramBase0 : 0xFF000000; +_CoreSramBase1 = DEFINED(_CoreSramBase1) ? _CoreSramBase1 : 0xFF001000; +_CoreSramSize0 = DEFINED(_CoreSramSize0) ? _CoreSramSize0 : (4 * 1024); +_CoreSramSize1 = DEFINED(_CoreSramSize1) ? _CoreSramSize1 : (4 * 1024); +_BootFlashBase = DEFINED(_BootFlashBase) ? _BootFlashBase : 0xFC000000; +_BootFlashSize = DEFINED(_BootFlashSize) ? _BootFlashSize : (32 * 1024*1024); + +bsp_initstack_size = DEFINED(StackSize) ? StackSize : 0x800; /* 2 kB */ + +_VBR = DEFINED(_VBR) ? _VBR : _SdramBase; + +__MBAR = DEFINED(__MBAR) ? __MBAR : 0xFE000000; + +MEMORY +{ + sdram : ORIGIN = 0xF0000000, LENGTH = 128M + boot_flash : ORIGIN = 0xFC000000, LENGTH = 32M +} + +REGION_ALIAS ("REGION_TEXT", sdram); +REGION_ALIAS ("REGION_TEXT_LOAD", sdram); +REGION_ALIAS ("REGION_DATA", sdram); +REGION_ALIAS ("REGION_DATA_LOAD", sdram); + +INCLUDE linkcmds.base diff --git a/bsps/m68k/genmcf548x/start/linkcmds.m5484FireEngine b/bsps/m68k/genmcf548x/start/linkcmds.m5484FireEngine new file mode 100644 index 0000000000..be746af7ff --- /dev/null +++ b/bsps/m68k/genmcf548x/start/linkcmds.m5484FireEngine @@ -0,0 +1,84 @@ +/*===============================================================*\ +| Project: RTEMS generic mcf548x BSP | ++-----------------------------------------------------------------+ +| File: linkcmd | ++-----------------------------------------------------------------+ +| The file contains the linker directives for the generic MCF548x | +| BSP to be used with an m5484FireEngine EVB to load and execute | +| code in the RAM. | ++-----------------------------------------------------------------+ +| Copyright (c) 2007 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| | +| Parts of the code has been derived from the "dBUG source code" | +| package Freescale is providing for M548X EVBs. The usage of | +| the modified or unmodified code and it's integration into the | +| generic mcf548x BSP has been done according to the Freescale | +| license terms. | +| | +| The Freescale license terms can be reviewed in the file | +| | +| Freescale_license.txt | +| | ++-----------------------------------------------------------------+ +| | +| The generic mcf548x BSP has been developed on the basic | +| structures and modules of the av5282 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. | +| | ++-----------------------------------------------------------------+ +| | +| date history ID | +| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | +| 12.11.07 1.0 ras | +| | +\*===============================================================*/ + +/* + * Location and size of on-chip devices + */ +_SdramBase = DEFINED(_SdramBase) ? _SdramBase : 0x00000000; +_SdramSize = DEFINED(_SdramSize) ? _SdramSize : (64 * 1024*1024); +_SysSramBase = DEFINED(_SysSramBase) ? _SysSramBase : __MBAR + 0x00010000; +_SysSramSize = DEFINED(_SysSramSize) ? _SysSramSize : (32 * 1024); +_McdapiBase = DEFINED(_McdapiBase) ? _McdapiBase : _SysSramBase; +_McdapiSize = DEFINED(_McdapiSize) ? _McdapiSize : (12 * 1024); +_CoreSramBase0 = DEFINED(_CoreSramBase0) ? _CoreSramBase0 : 0x20000000; +_CoreSramBase1 = DEFINED(_CoreSramBase1) ? _CoreSramBase1 : 0x20001000; +_CoreSramSize0 = DEFINED(_CoreSramSize0) ? _CoreSramSize0 : (4 * 1024); +_CoreSramSize1 = DEFINED(_CoreSramSize1) ? _CoreSramSize1 : (4 * 1024); +_BootFlashBase = DEFINED(_BootFlashBase) ? _BootFlashBase : 0xFF800000; +_BootFlashSize = DEFINED(_BootFlashSize) ? _BootFlashSize : (2 * 1024*1024); +_CodeFlashBase = DEFINED(_CodeFlashBase) ? _CodeFlashBase : 0xE0000000; +_CodeFlashSize = DEFINED(_CodeFlashSize) ? _CodeFlashSize : (16 * 1024*1024); + +bsp_initstack_size = DEFINED(StackSize) ? StackSize : 0x800; /* 2 kB */ + +_VBR = DEFINED(_VBR) ? _VBR : _SdramBase; + +__MBAR = DEFINED(__MBAR) ? __MBAR : 0x10000000; + +MEMORY +{ + sdram : ORIGIN = 0x00000000, LENGTH = 64M + code_flash : ORIGIN = 0xE0000000, LENGTH = 16M + boot_flash : ORIGIN = 0xFF800000, LENGTH = 2M +} + +REGION_ALIAS ("REGION_TEXT", sdram); +REGION_ALIAS ("REGION_TEXT_LOAD", sdram); +REGION_ALIAS ("REGION_DATA", sdram); +REGION_ALIAS ("REGION_DATA_LOAD", sdram); + +INCLUDE linkcmds.base diff --git a/bsps/m68k/genmcf548x/start/linkcmds.m5484FireEngine.flash b/bsps/m68k/genmcf548x/start/linkcmds.m5484FireEngine.flash new file mode 100644 index 0000000000..4db960f111 --- /dev/null +++ b/bsps/m68k/genmcf548x/start/linkcmds.m5484FireEngine.flash @@ -0,0 +1,84 @@ +/*===============================================================*\ +| Project: RTEMS generic mcf548x BSP | ++-----------------------------------------------------------------+ +| File: linkcmd.m5484FireEngine.flash | ++-----------------------------------------------------------------+ +| The file contains the linker directives for the generic MCF548x | +| BSP to be used with an m5484FireEngine EVB to load and execute | +| code in the boot FLASH. | ++-----------------------------------------------------------------+ +| Copyright (c) 2007 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| | +| Parts of the code has been derived from the "dBUG source code" | +| package Freescale is providing for M548X EVBs. The usage of | +| the modified or unmodified code and it's integration into the | +| generic mcf548x BSP has been done according to the Freescale | +| license terms. | +| | +| The Freescale license terms can be reviewed in the file | +| | +| Freescale_license.txt | +| | ++-----------------------------------------------------------------+ +| | +| The generic mcf548x BSP has been developed on the basic | +| structures and modules of the av5282 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. | +| | ++-----------------------------------------------------------------+ +| | +| date history ID | +| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | +| 12.11.07 1.0 ras | +| | +\*===============================================================*/ + +/* + * Location and size of on-chip devices + */ +_SdramBase = DEFINED(_SdramBase) ? _SdramBase : 0x00000000; +_SdramSize = DEFINED(_SdramSize) ? _SdramSize : (64 * 1024 * 1024); +_SysSramBase = DEFINED(_SysSramBase) ? _SysSramBase : __MBAR + 0x00010000; +_SysSramSize = DEFINED(_SysSramSize) ? _SysSramSize : (32 * 1024); +_McdapiBase = DEFINED(_McdapiBase) ? _McdapiBase : _SysSramBase; +_McdapiSize = DEFINED(_McdapiSize) ? _McdapiSize : (12 * 1024); +_CoreSramBase0 = DEFINED(_CoreSramBase0) ? _CoreSramBase0 : 0x20000000; +_CoreSramBase1 = DEFINED(_CoreSramBase1) ? _CoreSramBase1 : 0x20001000; +_CoreSramSize0 = DEFINED(_CoreSramSize0) ? _CoreSramSize0 : (4 * 1024); +_CoreSramSize1 = DEFINED(_CoreSramSize1) ? _CoreSramSize1 : (4 * 1024); +_BootFlashBase = DEFINED(_BootFlashBase) ? _BootFlashBase : 0xFF800000; +_BootFlashSize = DEFINED(_BootFlashSize) ? _BootFlashSize : (2 * 1024 * 1024); +_CodeFlashBase = DEFINED(_CodeFlashBase) ? _CodeFlashBase : 0xE0000000; +_CodeFlashSize = DEFINED(_CodeFlashSize) ? _CodeFlashSize : (16 * 1024 * 1024); + +bsp_initstack_size = DEFINED(StackSize) ? StackSize : 0x800; /* 2 kB */ + +_VBR = DEFINED(_VBR) ? _VBR : _SdramBase; + +__MBAR = DEFINED(__MBAR) ? __MBAR : 0x10000000; + +MEMORY +{ + sdram : ORIGIN = 0x00000000, LENGTH = 64M + code_flash : ORIGIN = 0xE0000000, LENGTH = 16M + boot_flash : ORIGIN = 0xFF800000, LENGTH = 2M +} + +REGION_ALIAS ("REGION_TEXT", boot_flash); +REGION_ALIAS ("REGION_TEXT_LOAD", boot_flash); +REGION_ALIAS ("REGION_DATA", sdram); +REGION_ALIAS ("REGION_DATA_LOAD", boot_flash); + +INCLUDE linkcmds.base diff --git a/bsps/m68k/mcf5206elite/start/bsp_specs b/bsps/m68k/mcf5206elite/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/m68k/mcf5206elite/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/m68k/mcf5206elite/start/gdbinit b/bsps/m68k/mcf5206elite/start/gdbinit new file mode 100644 index 0000000000..9954b8cb9a --- /dev/null +++ b/bsps/m68k/mcf5206elite/start/gdbinit @@ -0,0 +1,217 @@ +# +# GDB Init script for the Coldfire 5206e processor. +# +# The main purpose of this script is to perform minimum initialization of +# processor so code can be loaded. Also, exception handling is performed. +# +# Copyright (C) OKTET Ltd., St.-Petersburg, Russia +# Author: Victor V. Vengerov <vvv@oktet.ru> +# +# This script partially based on gdb scripts written by +# Eric Norum, <eric@skatter.usask.ca> +# +# +# 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 addresses + +set $mbar = 0x10000001 +set $simr = $mbar - 1 + 0x003 +set $icr1 = $mbar - 1 + 0x014 +set $icr2 = $mbar - 1 + 0x015 +set $icr3 = $mbar - 1 + 0x016 +set $icr4 = $mbar - 1 + 0x017 +set $icr5 = $mbar - 1 + 0x018 +set $icr6 = $mbar - 1 + 0x019 +set $icr7 = $mbar - 1 + 0x01A +set $icr8 = $mbar - 1 + 0x01B +set $icr9 = $mbar - 1 + 0x01C +set $icr10 = $mbar - 1 + 0x01D +set $icr11 = $mbar - 1 + 0x01E +set $icr12 = $mbar - 1 + 0x01F +set $icr13 = $mbar - 1 + 0x020 +set $imr = $mbar - 1 + 0x036 +set $ipr = $mbar - 1 + 0x03A +set $rsr = $mbar - 1 + 0x040 +set $sypcr = $mbar - 1 + 0x041 +set $swivr = $mbar - 1 + 0x042 +set $swsr = $mbar - 1 + 0x043 +set $dcrr = $mbar - 1 + 0x046 +set $dctr = $mbar - 1 + 0x04A +set $dcar0 = $mbar - 1 + 0x04C +set $dcmr0 = $mbar - 1 + 0x050 +set $dccr0 = $mbar - 1 + 0x057 +set $dcar1 = $mbar - 1 + 0x058 +set $dcmr1 = $mbar - 1 + 0x05C +set $dccr1 = $mbar - 1 + 0x063 +set $csar0 = $mbar - 1 + 0x064 +set $csmr0 = $mbar - 1 + 0x068 +set $cscr0 = $mbar - 1 + 0x06E +set $csar1 = $mbar - 1 + 0x070 +set $csmr1 = $mbar - 1 + 0x074 +set $cscr1 = $mbar - 1 + 0x07A +set $csar2 = $mbar - 1 + 0x07C +set $csmr2 = $mbar - 1 + 0x080 +set $cscr2 = $mbar - 1 + 0x086 +set $csar3 = $mbar - 1 + 0x088 +set $csmr3 = $mbar - 1 + 0x08C +set $cscr3 = $mbar - 1 + 0x092 +set $csar4 = $mbar - 1 + 0x094 +set $csmr4 = $mbar - 1 + 0x098 +set $cscr4 = $mbar - 1 + 0x09E +set $csar5 = $mbar - 1 + 0x0A0 +set $csmr5 = $mbar - 1 + 0x0A4 +set $cscr5 = $mbar - 1 + 0x0AA +set $csar6 = $mbar - 1 + 0x0AC +set $csmr6 = $mbar - 1 + 0x0B0 +set $cscr6 = $mbar - 1 + 0x0B6 +set $csar7 = $mbar - 1 + 0x0B8 +set $csmr7 = $mbar - 1 + 0x0BC +set $cscr7 = $mbar - 1 + 0x0C2 +set $dmcr = $mbar - 1 + 0x0C6 +set $par = $mbar - 1 + 0x0CA +set $tmr1 = $mbar - 1 + 0x100 +set $trr1 = $mbar - 1 + 0x104 +set $tcr1 = $mbar - 1 + 0x108 +set $tcn1 = $mbar - 1 + 0x10C +set $ter1 = $mbar - 1 + 0x111 +set $tmr2 = $mbar - 1 + 0x120 +set $trr2 = $mbar - 1 + 0x124 +set $tcr2 = $mbar - 1 + 0x128 +set $tcn2 = $mbar - 1 + 0x12C +set $ter2 = $mbar - 1 + 0x131 + +end + +# +# Setup CSAR0 for the FLASH ROM. +# + +define setup-cs + +set *((short*) $csar0) = 0xffe0 +set *((int*) $csmr0) = 0x000f0000 +set *((short*) $cscr0) = 0x1da3 +set *((short*) $csar1) = 0x5000 +set *((int*) $csmr1) = 0x00000000 +set *((short*) $cscr1) = 0x3d43 +set *((short*) $csar2) = 0x3000 +set *((int*) $csmr2) = 0x000f0000 +set *((short*) $cscr2) = 0x1903 +set *((short*) $csar3) = 0x4000 +set *((int*) $csmr3) = 0x000f0000 +set *((short*) $cscr3) = 0x0083 + +end + +# +# Setup the DRAM controller. +# + +define setup-dram + +set *((short*) $dcrr) = 24 +set *((short*) $dctr) = 0x0000 +set *((short*) $dcar0) = 0x0000 +set *((long*) $dcmr0) = 0x000e0000 +set *((char*) $dccr0) = 0x07 +set *((short*) $dcar1) = 0x0000 +set *((long*) $dcmr1) = 0x00000000 +set *((char*) $dccr1) = 0x00 + +end + + +# +# Wake up the board +# + +define initboard + +addresses +setup-cs +# setup-dram + +end + +define ss +si +x/i $pc +end + +# +# Display exception information +# +define exception-info +set $excpc = *(unsigned int *)($sp+4) +set $excfmt = (*(unsigned int *)$sp >> 28) & 0x0f +set $excfs = ((*(unsigned int *)$sp >> 24) & 0x0c) | \ + ((*(unsigned int *)$sp >> 16) & 0x03) +set $excvec = (*(unsigned int *)$sp >> 18) & 0xff +set $excsr = *(unsigned int *)$sp & 0xffff + +printf "EXCEPTION -- SR:0x%X PC:0x%X FRAME:0x%X VECTOR:%d\n", \ + $excsr, $excpc, $sp, $excvec +if $excvec == 2 + printf "Access error exception" +end +if $excvec == 3 + printf "Address error exception" +end +if $excvec == 4 + printf "Illegal instruction exception" +end +if $excvec == 8 + printf "Privelege violation exception" +end +if $excvec == 9 + printf "Trace exception" +end +if $excvec == 10 + printf "Unimplemented LINE-A opcode exception" +end +if $excvec == 11 + printf "Unimplemented LINE-F opcode exception" +end +if $excvec == 12 + printf "Debug interrupt" +end +if $excvec == 14 + printf "Format error exception" +end +if $excfs == 0x04 + printf " on instruction fetch" +end +if $excfs == 0x08 + printf " on operand write" +end +if $excfs == 0x09 + printf " on write to write-protected space" +end +if $excfs == 0x0c + printf " on operand read" +end +printf "\n" +x/4i $excpc +set $pc=$excpc +set $sp=$sp+8 +end + +target bdm /dev/bdmcf0 +initboard +load +set $pc=start +set $sp=0x20001ffc +b bsp_cleanup +b _stop +b _unexp_exception +commands +silent +exception-info +end +b _unexp_int +b _reserved_int +b _spurious_int diff --git a/bsps/m68k/mcf5206elite/start/init5206e.c b/bsps/m68k/mcf5206elite/start/init5206e.c new file mode 100644 index 0000000000..a128b81fd7 --- /dev/null +++ b/bsps/m68k/mcf5206elite/start/init5206e.c @@ -0,0 +1,229 @@ +/* + * MCF5206e hardware startup routines + * + * This is where the real hardware setup is done. A minimal stack + * has been provided by the start.S code. No normal C or RTEMS + * functions can be called from here. + * + * This initialization code based on hardware settings of dBUG + * monitor. This must be changed if you like to run it immediately + * after reset. + */ + +/* + * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russia + * Author: Victor V. Vengerov <vvv@oktet.ru> + * + * Based on work: + * Author: + * David Fiddes, D.J@fiddes.surfaid.org + * http://www.calm.hw.ac.uk/davidf/coldfire/ + * + * COPYRIGHT (c) 1989-1998. + * 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.h> +#include "mcf5206/mcf5206e.h" + +extern void CopyDataClearBSSAndStart(unsigned long ramsize); +extern void INTERRUPT_VECTOR(void); + +#define m68k_set_srambar( _rambar0 ) \ + __asm__ volatile ( "movec %0,%%rambar0\n\t" \ + "nop\n\t" \ + : : "d" (_rambar0) ) + +#define m68k_set_mbar( _mbar ) \ + __asm__ volatile ( "movec %0,%%mbar\n\t" \ + "nop\n\t" \ + : : "d" (_mbar) ) + +#define mcf5206e_enable_cache() \ + m68k_set_cacr( MCF5206E_CACR_CENB ) + +#define mcf5206e_disable_cache() \ + __asm__ volatile ( "nop\n\t" \ + "movec %0,%%cacr\n\t" \ + "nop\n\t" \ + "movec %0,%%cacr\n\t" \ + "nop\n\t" \ + : : "d" (MCF5206E_CACR_CINV) ) + +/* + * Initialize MCF5206e on-chip modules + */ +void Init5206e(void) +{ + /* Set Module Base Address register */ + m68k_set_mbar((MBAR & MCF5206E_MBAR_BA) | MCF5206E_MBAR_V); + + /* Set System Protection Control Register (SYPCR): + * Bus Monitor Enable, Bus Monitor Timing = 1024 clocks, + * Software watchdog disabled + */ + *MCF5206E_SYPCR(MBAR) = MCF5206E_SYPCR_BME | + MCF5206E_SYPCR_BMT_1024; + + /* Set Pin Assignment Register (PAR): + * Output Timer 0 (not DREQ) on *TOUT[0] / *DREQ[1] + * Input Timer 0 (not DREQ) on *TIN[0] / *DREQ[0] + * IRQ, not IPL + * UART2 RTS signal (not \RSTO) + * PST/DDATA (not PPIO) + * *WE (not CS/A) + */ + *MCF5206E_PAR(MBAR) = MCF5206E_PAR_PAR9_TOUT | + MCF5206E_PAR_PAR8_TIN0 | + MCF5206E_PAR_PAR7_UART2 | + MCF5206E_PAR_PAR6_IRQ | + MCF5206E_PAR_PAR5_PST | + MCF5206E_PAR_PAR4_DDATA | + MCF5206E_PAR_WE0_WE1_WE2_WE3; + + /* Set SIM Configuration Register (SIMR): + * Disable software watchdog timer and bus timeout monitor when + * internal freeze signal is asserted. + */ + *MCF5206E_SIMR(MBAR) = MCF5206E_SIMR_FRZ0 | MCF5206E_SIMR_FRZ1; + + /* Set Interrupt Mask Register: Disable all interrupts */ + *MCF5206E_IMR(MBAR) = 0xFFFF; + + /* Assign Interrupt Control Registers as it is defined in bsp.h */ + *MCF5206E_ICR(MBAR,MCF5206E_INTR_EXT_IPL1) = + (BSP_INTLVL_AVEC1 << MCF5206E_ICR_IL_S) | + (BSP_INTPRIO_AVEC1 << MCF5206E_ICR_IP_S) | + MCF5206E_ICR_AVEC; + *MCF5206E_ICR(MBAR,MCF5206E_INTR_EXT_IPL2) = + (BSP_INTLVL_AVEC2 << MCF5206E_ICR_IL_S) | + (BSP_INTPRIO_AVEC2 << MCF5206E_ICR_IP_S) | + MCF5206E_ICR_AVEC; + *MCF5206E_ICR(MBAR,MCF5206E_INTR_EXT_IPL3) = + (BSP_INTLVL_AVEC3 << MCF5206E_ICR_IL_S) | + (BSP_INTPRIO_AVEC3 << MCF5206E_ICR_IP_S) | + MCF5206E_ICR_AVEC; + *MCF5206E_ICR(MBAR,MCF5206E_INTR_EXT_IPL4) = + (BSP_INTLVL_AVEC4 << MCF5206E_ICR_IL_S) | + (BSP_INTPRIO_AVEC4 << MCF5206E_ICR_IP_S) | + MCF5206E_ICR_AVEC; + *MCF5206E_ICR(MBAR,MCF5206E_INTR_EXT_IPL5) = + (BSP_INTLVL_AVEC5 << MCF5206E_ICR_IL_S) | + (BSP_INTPRIO_AVEC5 << MCF5206E_ICR_IP_S) | + MCF5206E_ICR_AVEC; + *MCF5206E_ICR(MBAR,MCF5206E_INTR_EXT_IPL6) = + (BSP_INTLVL_AVEC6 << MCF5206E_ICR_IL_S) | + (BSP_INTPRIO_AVEC6 << MCF5206E_ICR_IP_S) | + MCF5206E_ICR_AVEC; + *MCF5206E_ICR(MBAR,MCF5206E_INTR_EXT_IPL7) = + (BSP_INTLVL_AVEC7 << MCF5206E_ICR_IL_S) | + (BSP_INTPRIO_AVEC7 << MCF5206E_ICR_IP_S) | + MCF5206E_ICR_AVEC; + *MCF5206E_ICR(MBAR,MCF5206E_INTR_TIMER_1) = + (BSP_INTLVL_TIMER1 << MCF5206E_ICR_IL_S) | + (BSP_INTPRIO_TIMER1 << MCF5206E_ICR_IP_S) | + MCF5206E_ICR_AVEC; + *MCF5206E_ICR(MBAR,MCF5206E_INTR_TIMER_2) = + (BSP_INTLVL_TIMER2 << MCF5206E_ICR_IL_S) | + (BSP_INTPRIO_TIMER2 << MCF5206E_ICR_IP_S) | + MCF5206E_ICR_AVEC; + *MCF5206E_ICR(MBAR,MCF5206E_INTR_MBUS) = + (BSP_INTLVL_MBUS << MCF5206E_ICR_IL_S) | + (BSP_INTPRIO_MBUS << MCF5206E_ICR_IP_S) | + MCF5206E_ICR_AVEC; + *MCF5206E_ICR(MBAR,MCF5206E_INTR_UART_1) = + (BSP_INTLVL_UART1 << MCF5206E_ICR_IL_S) | + (BSP_INTPRIO_UART1 << MCF5206E_ICR_IP_S); + *MCF5206E_ICR(MBAR,MCF5206E_INTR_UART_2) = + (BSP_INTLVL_UART2 << MCF5206E_ICR_IL_S) | + (BSP_INTPRIO_UART2 << MCF5206E_ICR_IP_S); + *MCF5206E_ICR(MBAR,MCF5206E_INTR_DMA_0) = + (BSP_INTLVL_DMA0 << MCF5206E_ICR_IL_S) | + (BSP_INTPRIO_DMA0 << MCF5206E_ICR_IP_S) | + MCF5206E_ICR_AVEC; + *MCF5206E_ICR(MBAR,MCF5206E_INTR_DMA_1) = + (BSP_INTLVL_DMA1 << MCF5206E_ICR_IL_S) | + (BSP_INTPRIO_DMA1 << MCF5206E_ICR_IP_S) | + MCF5206E_ICR_AVEC; + + /* Software Watchdog timer (not used now) */ + *MCF5206E_SWIVR(MBAR) = 0x0F; /* Uninitialized interrupt */ + *MCF5206E_SWSR(MBAR) = MCF5206E_SWSR_KEY1; + *MCF5206E_SWSR(MBAR) = MCF5206E_SWSR_KEY2; + + /* Configuring Chip Selects */ + /* CS2: SRAM memory */ + *MCF5206E_CSAR(MBAR,2) = BSP_MEM_ADDR_ESRAM >> 16; + *MCF5206E_CSMR(MBAR,2) = BSP_MEM_MASK_ESRAM; + *MCF5206E_CSCR(MBAR,2) = MCF5206E_CSCR_WS1 | + MCF5206E_CSCR_PS_32 | + MCF5206E_CSCR_AA | + MCF5206E_CSCR_EMAA | + MCF5206E_CSCR_WR | + MCF5206E_CSCR_RD; + + /* CS3: GPIO on eLITE board */ + *MCF5206E_CSAR(MBAR,3) = BSP_MEM_ADDR_GPIO >> 16; + *MCF5206E_CSMR(MBAR,3) = BSP_MEM_MASK_GPIO; + *MCF5206E_CSCR(MBAR,3) = MCF5206E_CSCR_WS15 | + MCF5206E_CSCR_PS_16 | + MCF5206E_CSCR_AA | + MCF5206E_CSCR_EMAA | + MCF5206E_CSCR_WR | + MCF5206E_CSCR_RD; + + { + uint32_t *inttab = (uint32_t*)&INTERRUPT_VECTOR; + uint32_t *intvec = (uint32_t*)BSP_MEM_ADDR_ESRAM; + register int i; + + for (i = 0; i < 256; i++) { + *(intvec++) = *(inttab++); + } + } + m68k_set_vbr(BSP_MEM_ADDR_ESRAM); + + /* CS0: Flash EEPROM */ + *MCF5206E_CSAR(MBAR,0) = BSP_MEM_ADDR_FLASH >> 16; + *MCF5206E_CSCR(MBAR,0) = MCF5206E_CSCR_WS3 | + MCF5206E_CSCR_AA | + MCF5206E_CSCR_PS_16 | + MCF5206E_CSCR_EMAA | + MCF5206E_CSCR_WR | + MCF5206E_CSCR_RD; + *MCF5206E_CSMR(MBAR,0) = BSP_MEM_MASK_FLASH; + + /* + * Invalidate the cache and disable it + */ + mcf5206e_disable_cache(); + + /* + * Setup ACRs so that if cache turned on, periphal accesses + * are not messed up. (Non-cacheable, serialized) + */ + m68k_set_acr0 ( 0 + | MCF5206E_ACR_BASE(BSP_MEM_ADDR_ESRAM) + | MCF5206E_ACR_MASK(BSP_MEM_MASK_ESRAM) + | MCF5206E_ACR_EN + | MCF5206E_ACR_SM_ANY + ); + m68k_set_acr1 ( 0 + | MCF5206E_ACR_BASE(BSP_MEM_ADDR_FLASH) + | MCF5206E_ACR_MASK(BSP_MEM_MASK_FLASH) + | MCF5206E_ACR_EN + | MCF5206E_ACR_SM_ANY + ); + + mcf5206e_enable_cache(); + + /* + * Copy data, clear BSS, switch stacks and call boot_card() + */ + CopyDataClearBSSAndStart (BSP_MEM_SIZE_ESRAM - 0x400); +} diff --git a/bsps/m68k/mcf5206elite/start/linkcmds b/bsps/m68k/mcf5206elite/start/linkcmds new file mode 100644 index 0000000000..817c80e298 --- /dev/null +++ b/bsps/m68k/mcf5206elite/start/linkcmds @@ -0,0 +1,207 @@ +/* + * This file contains GNU linker directives for an MCF5206eLITE + * evaluation board. + * + * Variations in memory size and allocation can be made by + * overriding some values with linker command-line arguments. + * + * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russia + * Author: Victor V. Vengerov <vvv@oktet.ru> + * + * This file based on work: + * David Fiddes, D.J.Fiddes@hw.ac.uk + * http://www.calm.hw.ac.uk/davidf/coldfire/ + * + * 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. + */ + +/* + * Declare some sizes. + * XXX: The assignment of ". += XyzSize;" fails in older gld's if the + * number used there is not constant. If this happens to you, edit + * the lines marked XXX below to use a constant value. + */ + +/* + * Declare system clock frequency. + */ +_SYS_CLOCK_FREQUENCY = DEFINED(_SYS_CLOCK_FREQUENCY) ? + _SYS_CLOCK_FREQUENCY : 54000000; + +/* + * Declare size of heap. + * A heap size of 0 means "Use all available memory for the heap". + * Initial stack located in on-chip SRAM and not declared there. + */ +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +RamBase = DEFINED(RamBase) ? RamBase : 0x30000000; +RamSize = DEFINED(RamSize) ? RamSize : 0x00100000; + +/* + * Setup the memory map of the MCF5206eLITE evaluation board + * + * The "rom" section is in USER Flash on the board + * The "ram" section is placed in USER RAM starting at 10000h + * + */ +MEMORY +{ + ram : ORIGIN = 0x30000000, LENGTH = 0x00100000 + rom : ORIGIN = 0xFFE20000, LENGTH = 128k +} + +MBase = 0x10000000; + +ENTRY(start) +STARTUP(start.o) + +/* Interrupt Vector table located at start of external static RAM */ +_VBR = 0x30000000; + +SECTIONS +{ + + /* + * Dynamic RAM + */ + ram : { + RamBase = .; + RamBase = .; + /* Reserve space for interrupt table */ + . += 0x400; + } >ram + + /* + * Text, data and bss segments + */ + .text : { + CREATE_OBJECT_SYMBOLS + *(.text*) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + */ + . = ALIGN (16); + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + . = ALIGN (16); + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * C++ constructors/destructors + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = .; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + PROVIDE (etext = .); + + } > ram + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >ram + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >ram + + _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)); + + .data BLOCK (0x4) : { + copy_start = .; + *(.shdata) + . = ALIGN (0x10); + *(.data*) + KEEP (*(SORT(.rtemsrwset.*))) + . = ALIGN (0x10); + *(.gcc_exc) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (0x10); + *(.gnu.linkonce.d*) + . = ALIGN (0x10); + _edata = .; + copy_end = .; + } > ram + + .bss BLOCK (0x4) : + { + clear_start = . ; + *(.shbss) + *(.dynbss) + *(.bss* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(0x10); + _end = .; + + clear_end = .; + + WorkAreaBase = .; + WorkAreaBase = .; + + } > ram + + .stab 0 (NOLOAD) : + { + *(.stab) + } + + .stabstr 0 (NOLOAD) : + { + *(.stabstr) + } + +} diff --git a/bsps/m68k/mcf5206elite/start/linkcmds.flash b/bsps/m68k/mcf5206elite/start/linkcmds.flash new file mode 100644 index 0000000000..8d429ab209 --- /dev/null +++ b/bsps/m68k/mcf5206elite/start/linkcmds.flash @@ -0,0 +1,207 @@ +/* + * This file contains GNU linker directives for an MCF5206eLITE + * evaluation board. + * + * Variations in memory size and allocation can be made by + * overriding some values with linker command-line arguments. + * + * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russia + * Author: Victor V. Vengerov <vvv@oktet.ru> + * + * This file based on work: + * David Fiddes, D.J.Fiddes@hw.ac.uk + * http://www.calm.hw.ac.uk/davidf/coldfire/ + * + * 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. + */ + +/* + * Declare some sizes. + * XXX: The assignment of ". += XyzSize;" fails in older gld's if the + * number used there is not constant. If this happens to you, edit + * the lines marked XXX below to use a constant value. + */ +/* + * Declare size of heap. + * A heap size of 0 means "Use all available memory for the heap". + * Initial stack located in on-chip SRAM and not declared there. + */ +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; + +/* + * Declare system clock frequency. + */ +_SYS_CLOCK_FREQUENCY = DEFINED(_SYS_CLOCK_FREQUENCY) ? _SYS_CLOCK_FREQUENCY : 54000000; + +/* + * Setup the memory map of the MCF5206eLITE evaluation board + * + * The "rom" section is in USER Flash on the board + * The "ram" section is placed in USER RAM starting at 10000h + * + */ +MEMORY +{ + ram : ORIGIN = 0x30000000, LENGTH = 0x00100000 + rom : ORIGIN = 0xFFE00000, LENGTH = 0x00100000 +} + +MBase = 0x10000000; + +ENTRY(start) +STARTUP(start.o) + +/* Interrupt Vector table located at start of external static RAM */ +_VBR = 0x30000000; + +SECTIONS +{ + /* + * Flash ROM + */ + rom : { + _RomBase = .; + } >rom + + /* + * Dynamic RAM + */ + ram : { + RamBase = .; + RamBase = .; + } >ram + + /* + * Text, data and bss segments + */ + .text : AT(0x30020000) { + CREATE_OBJECT_SYMBOLS + *(.text*) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + */ + . = ALIGN (16); + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + . = ALIGN (16); + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * C++ constructors/destructors + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + PROVIDE (etext = .); + + } >rom + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >rom + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >rom + + _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)); + + .data 0x30000400 : AT(LOADADDR(.text) + SIZEOF(.text)) { + copy_start = .; + . = ALIGN (0x10); + *(.shdata) + . = ALIGN (0x10); + *(.data) + KEEP (*(SORT(.rtemsrwset.*))) + . = ALIGN (0x10); + *(.gcc_exc) + *(.gcc_except_table*) + . = ALIGN (0x10); + *(.gnu.linkonce.d*) + . = ALIGN (0x10); + _edata = .; + copy_end = .; + } >ram + + .bss BLOCK (0x4) : + { + clear_start = . ; + *(.shbss) + *(.dynbss) + *(.bss* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(0x10); + _end = .; + + clear_end = .; + + WorkAreaBase = .; + WorkAreaBase = .; + + } > ram + + .stab 0 (NOLOAD) : + { + *(.stab) + } + + .stabstr 0 (NOLOAD) : + { + *(.stabstr) + } + +} diff --git a/bsps/m68k/mcf52235/start/bsp_specs b/bsps/m68k/mcf52235/start/bsp_specs new file mode 100644 index 0000000000..3a20757667 --- /dev/null +++ b/bsps/m68k/mcf52235/start/bsp_specs @@ -0,0 +1,10 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s crtn.o%s} + diff --git a/bsps/m68k/mcf52235/start/bspgetcpuclockspeed.c b/bsps/m68k/mcf52235/start/bspgetcpuclockspeed.c new file mode 100644 index 0000000000..563044394a --- /dev/null +++ b/bsps/m68k/mcf52235/start/bspgetcpuclockspeed.c @@ -0,0 +1,15 @@ +/* + * COPYRIGHT (c) 1989-2008. + * 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> + +uint32_t bsp_get_CPU_clock_speed(void) +{ + return 60000000; +} diff --git a/bsps/m68k/mcf52235/start/cfinit.c b/bsps/m68k/mcf52235/start/cfinit.c new file mode 100644 index 0000000000..0007f9a449 --- /dev/null +++ b/bsps/m68k/mcf52235/start/cfinit.c @@ -0,0 +1,554 @@ +/********************************************************************* +* Initialisation Code for ColdFire MCF52235 Processor * +********************************************************************** + Generated by ColdFire Initialisation Utility 2.10.8 + Fri May 23 14:39:00 2008 + + MicroAPL Ltd makes no warranties in respect of the suitability + of this code for any particular purpose, and accepts + no liability for any loss arising out of its use. The person or + persons making use of this file must make the final evaluation + as to its suitability and correctness for a particular application. + +*/ + +/* Processor/internal bus clocked at 60.00 MHz */ + +#include <bsp.h> + +/* Additional register read/write macros (missing in headers) */ +#define MCF_CIM_CCON (*(vuint16*)(void*)(&__IPSBAR[0x00110004])) + +/* Bit definitions and macros for MCF_CIM_CCON */ +#define MCF_CIM_CCON_SZEN (0x00000040) +#define MCF_CIM_CCON_PSTEN (0x00000020) +#define MCF_CIM_CCON_BME (0x00000008) +#define MCF_CIM_CCON_BMT(x) (((x)&0x00000007)<<0) + +/* Function prototypes */ +void init_main(void); +static void disable_interrupts(void); +static void disable_watchdog_timer(void); +static void init_ipsbar(void); +static void init_clock_config(void); +static void init_sram(void); +static void init_flash_controller(void); +static void init_eport(void); +static void init_flexcan(void); +static void init_bus_config(void); +static void init_power_management(void); +static void init_dma_timers(void); +static void init_gp_timer(void); +static void init_interrupt_timers(void); +static void init_real_time_clock(void); +static void init_watchdog_timer(void); +static void init_pin_assignments(void); +static void init_interrupt_controller(void); + +/********************************************************************* +* init_main - Main entry point for initialisation code * +**********************************************************************/ +void init_main(void) +{ + /* Mask all interrupts */ + __asm__ ("move.w #0x2700,%sr"); + + /* Initialise base address of peripherals, VBR, etc */ + init_ipsbar(); + init_clock_config(); + + /* Disable interrupts and watchdog timer */ + disable_interrupts(); + disable_watchdog_timer(); + + /* Initialise individual modules */ + init_sram(); + init_flash_controller(); + init_eport(); + init_flexcan(); + init_bus_config(); + init_power_management(); + init_dma_timers(); + init_gp_timer(); + init_interrupt_timers(); + init_real_time_clock(); + init_watchdog_timer(); + init_pin_assignments(); + + /* Initialise interrupt controller */ + init_interrupt_controller(); +} + +/********************************************************************* +* disable_interrupts - Disable all interrupt sources * +**********************************************************************/ +static void disable_interrupts(void) +{ + vuint8 *p; + int i; + + /* Set ICR008-ICR063 to 0x0 */ + p = (vuint8 *) & MCF_INTC0_ICR8; + for (i = 8; i <= 63; i++) + *p++ = 0x0; + + /* Set ICR108-ICR139 to 0x0 */ + p = (vuint8 *) & MCF_INTC1_ICR8; + for (i = 108; i <= 139; i++) + *p++ = 0x0; +} + +/********************************************************************* +* disable_watchdog_timer - Disable system watchdog timer * +**********************************************************************/ +static void disable_watchdog_timer(void) +{ + /* Disable Core Watchdog Timer */ + MCF_SCM_CWCR = 0; +} + +/********************************************************************* +* init_clock_config - Clock Module * +**********************************************************************/ +static void init_clock_config(void) +{ + /* Clock source is 25.0000 MHz external crystal + Clock mode: Normal PLL mode + Processor/Bus clock frequency = 60.00 MHz + Loss of clock detection disabled + Reset on loss of lock disabled + */ + + /* Divide 25.0000 MHz clock to get 5.00 MHz PLL input clock */ + MCF_CLOCK_CCHR = MCF_CLOCK_CCHR_PFD(0x4); + + /* Set RFD+1 to avoid frequency overshoot and wait for PLL to lock */ + MCF_CLOCK_SYNCR = 0x4103; + while ((MCF_CLOCK_SYNSR & 0x08) == 0) ; + + /* Set desired RFD=0 and MFD=4 and wait for PLL to lock */ + MCF_CLOCK_SYNCR = 0x4003; + while ((MCF_CLOCK_SYNSR & 0x08) == 0) ; + MCF_CLOCK_SYNCR = 0x4007; /* Switch to using PLL */ +} + +/********************************************************************* +* init_ipsbar - Internal Peripheral System Base Address (IPSBAR) * +**********************************************************************/ +static void init_ipsbar(void) +{ + /* Base address of internal peripherals (IPSBAR) = 0x40000000 + + Note: Processor powers up with IPS base address = 0x40000000 + Write to IPS base + 0x00000000 to set new value + */ + *(vuint32 *) 0x40000000 = (vuint32) __IPSBAR + 1; /* +1 for Enable */ +} + +/********************************************************************* +* init_flash_controller - Flash Module * +**********************************************************************/ +static void init_flash_controller(void) +{ + /* Internal Flash module enabled, address = $00000000 + Flash state machine clock = 197.37 kHz + All access types except CPU space/interrupt acknowledge cycle allowed + Flash is Write-Protected + All interrupts disabled + */ + MCF_CFM_CFMCLKD = MCF_CFM_CFMCLKD_PRDIV8 | MCF_CFM_CFMCLKD_DIV(0x12); + MCF_CFM_CFMMCR = 0; + + /* WARNING: Setting FLASHBAR[6]=1 in order to turn off address speculation + This is a workaround for a hardware problem whereby a speculative + access to the Flash occuring at the same time as an SRAM access + can return corrupt data. + + This workaround can result in a 4% - 9% performance penalty. Other workarounds + are possible for certain applications. + + For example, if you know that you will not be using the top 32 KB of the Flash + you can place the SRAM base address at 0x20038000 + + See Device Errata for further details + */ + __asm__ ("move.l #0x00000161,%d0"); + __asm__ ("movec %d0,%FLASHBAR"); +} + +/********************************************************************* +* init_eport - Edge Port Module (EPORT) * +**********************************************************************/ +static void init_eport(void) +{ + /* Pins 1-15 configured as GPIO inputs */ + MCF_EPORT_EPDDR0 = 0; + MCF_EPORT_EPDDR1 = 0; + MCF_EPORT_EPPAR0 = 0; + MCF_EPORT_EPPAR1 = 0; + MCF_EPORT_EPIER0 = 0; + MCF_EPORT_EPIER1 = 0; +} + +/********************************************************************* +* init_flexcan - FlexCAN Module * +**********************************************************************/ +static void init_flexcan(void) +{ + /* FlexCAN controller disabled (CANMCR0[MDIS]=1) */ + MCF_CAN_IMASK = 0; + MCF_CAN_RXGMASK = MCF_CAN_RXGMASK_MI(0x1fffffff); + MCF_CAN_RX14MASK = MCF_CAN_RX14MASK_MI(0x1fffffff); + MCF_CAN_RX15MASK = MCF_CAN_RX15MASK_MI(0x1fffffff); + MCF_CAN_CANCTRL = 0; + MCF_CAN_CANMCR = MCF_CAN_CANMCR_MDIS | + MCF_CAN_CANMCR_FRZ | + MCF_CAN_CANMCR_HALT | MCF_CAN_CANMCR_SUPV | MCF_CAN_CANMCR_MAXMB(0xf); +} + +/********************************************************************* +* init_bus_config - Internal Bus Arbitration * +**********************************************************************/ +static void init_bus_config(void) +{ + /* Use round robin arbitration scheme + Assigned priorities (highest first): + Ethernet + DMA Controller + ColdFire Core + DMA bandwidth control disabled + Park on last active bus master + */ + MCF_SCM_MPARK = MCF_SCM_MPARK_M3PRTY(0x3) | + MCF_SCM_MPARK_M2PRTY(0x2) | (0x1 << 16); +} + +/********************************************************************* +* init_sram - On-chip SRAM * +**********************************************************************/ +static void init_sram(void) +{ + /* Internal SRAM module enabled, address = $20000000 + DMA access to SRAM block disabled + All access types (supervisor and user) allowed + */ + __asm__ ("move.l #0x20000001,%d0"); + __asm__ ("movec %d0,%RAMBAR"); +} + +/********************************************************************* +* init_power_management - Power Management * +**********************************************************************/ +static void init_power_management(void) +{ + /* On executing STOP instruction, processor enters RUN mode + Mode is exited when an interrupt of level 1 or higher is received + */ + MCF_PMM_LPICR = MCF_PMM_LPICR_ENBSTOP; + MCF_PMM_LPCR = MCF_PMM_LPCR_LPMD_RUN; +} + +/********************************************************************* +* init_dma_timers - DMA Timer Modules * +**********************************************************************/ +static void init_dma_timers(void) +{ + /* DMA Timer 0 disabled (DTMR0[RST] = 0) */ + MCF_DTIM0_DTMR = MCF_DTIM_DTMR_CLK(0x1); + MCF_DTIM0_DTXMR = 0; + MCF_DTIM0_DTRR = MCF_DTIM_DTRR_REF(0xffffffff); + + /* DMA Timer 1 disabled (DTMR1[RST] = 0) */ + MCF_DTIM1_DTMR = 0; + MCF_DTIM1_DTXMR = 0; + MCF_DTIM1_DTRR = MCF_DTIM_DTRR_REF(0xffffffff); + + /* DMA Timer 2 disabled (DTMR2[RST] = 0) */ + MCF_DTIM2_DTMR = 0; + MCF_DTIM2_DTXMR = 0; + MCF_DTIM2_DTRR = MCF_DTIM_DTRR_REF(0xffffffff); + + /* DMA Timer 3 disabled (DTMR3[RST] = 0) */ + MCF_DTIM3_DTMR = MCF_DTIM_DTMR_CLK(0x1); + MCF_DTIM3_DTXMR = 0; + MCF_DTIM3_DTRR = MCF_DTIM_DTRR_REF(0xffffffff); +} + +/********************************************************************* +* init_gp_timer - General Purpose Timer (GPT) Module * +**********************************************************************/ +static void init_gp_timer(void) +{ + /* + GPT disabled (GPTASCR1[GPTEN] = 0) + Channel 0 configured as GPIO input + Channel 1 configured as GPIO input + Channel 2 configured as GPIO input + Channel 3 configured as GPIO input + */ + MCF_GPT_GPTSCR1 = 0; + MCF_GPT_GPTDDR = 0; +} + +/********************************************************************** +* init_interrupt_timers - Programmable Interrupt Timer (PIT) Modules * +***********************************************************************/ +static void init_interrupt_timers(void) +{ + /* PIT0 disabled (PCSR0[EN]=0) */ + MCF_PIT0_PCSR = 0; + + /* PIT1 disabled (PCSR1[EN]=0) */ + MCF_PIT1_PCSR = 0; +} + +/********************************************************************* +* init_real_time_clock - Real-Time Clock (RTC) * +**********************************************************************/ +static void init_real_time_clock(void) +{ + /* Disable the RTC */ + MCF_RTC_CR = 0; +} + +/********************************************************************* +* init_watchdog_timer - Watchdog Timer * +**********************************************************************/ +static void init_watchdog_timer(void) +{ + /* Core Watchdog Timer disabled (CWCR[CWE]=0) */ + MCF_SCM_CWCR = 0; +} + +/********************************************************************* +* init_interrupt_controller - Interrupt Controller * +**********************************************************************/ +static void init_interrupt_controller(void) +{ + /* Configured interrupt sources in order of priority... + Level 7: External interrupt /IRQ7, (initially masked) + Level 6: External interrupt /IRQ6, (initially masked) + Level 5: External interrupt /IRQ5, (initially masked) + Level 4: External interrupt /IRQ4, (initially masked) + Level 3: External interrupt /IRQ3, (initially masked) + Level 2: External interrupt /IRQ2, (initially masked) + Level 1: External interrupt /IRQ1, (initially masked) + */ + MCF_INTC0_ICR1 = 0; + MCF_INTC0_ICR2 = 0; + MCF_INTC0_ICR3 = 0; + MCF_INTC0_ICR4 = 0; + MCF_INTC0_ICR5 = 0; + MCF_INTC0_ICR6 = 0; + MCF_INTC0_ICR7 = 0; + MCF_INTC0_ICR8 = 0; + MCF_INTC0_ICR9 = 0; + MCF_INTC0_ICR10 = 0; + MCF_INTC0_ICR11 = 0; + MCF_INTC0_ICR12 = 0; + MCF_INTC0_ICR13 = 0; + MCF_INTC0_ICR14 = 0; + MCF_INTC0_ICR15 = 0; + MCF_INTC0_ICR17 = 0; + MCF_INTC0_ICR18 = 0; + MCF_INTC0_ICR19 = 0; + MCF_INTC0_ICR20 = 0; + MCF_INTC0_ICR21 = 0; + MCF_INTC0_ICR22 = 0; + MCF_INTC0_ICR23 = 0; + MCF_INTC0_ICR24 = 0; + MCF_INTC0_ICR25 = 0; + MCF_INTC0_ICR26 = 0; + MCF_INTC0_ICR27 = 0; + MCF_INTC0_ICR28 = 0; + MCF_INTC0_ICR29 = 0; + MCF_INTC0_ICR30 = 0; + MCF_INTC0_ICR31 = 0; + MCF_INTC0_ICR32 = 0; + MCF_INTC0_ICR33 = 0; + MCF_INTC0_ICR34 = 0; + MCF_INTC0_ICR35 = 0; + MCF_INTC0_ICR36 = 0; + MCF_INTC0_ICR41 = 0; + MCF_INTC0_ICR42 = 0; + MCF_INTC0_ICR43 = 0; + MCF_INTC0_ICR44 = 0; + MCF_INTC0_ICR45 = 0; + MCF_INTC0_ICR46 = 0; + MCF_INTC0_ICR47 = 0; + MCF_INTC0_ICR48 = 0; + MCF_INTC0_ICR49 = 0; + MCF_INTC0_ICR50 = 0; + MCF_INTC0_ICR51 = 0; + MCF_INTC0_ICR52 = 0; + MCF_INTC0_ICR53 = 0; + MCF_INTC0_ICR55 = 0; + MCF_INTC0_ICR56 = 0; + MCF_INTC0_ICR59 = 0; + MCF_INTC0_ICR60 = 0; + MCF_INTC0_ICR61 = 0; + MCF_INTC0_ICR62 = 0; + MCF_INTC0_ICR63 = 0; + MCF_INTC1_ICR8 = 0; + MCF_INTC1_ICR9 = 0; + MCF_INTC1_ICR10 = 0; + MCF_INTC1_ICR11 = 0; + MCF_INTC1_ICR12 = 0; + MCF_INTC1_ICR13 = 0; + MCF_INTC1_ICR14 = 0; + MCF_INTC1_ICR15 = 0; + MCF_INTC1_ICR16 = 0; + MCF_INTC1_ICR17 = 0; + MCF_INTC1_ICR18 = 0; + MCF_INTC1_ICR19 = 0; + MCF_INTC1_ICR20 = 0; + MCF_INTC1_ICR21 = 0; + MCF_INTC1_ICR22 = 0; + MCF_INTC1_ICR23 = 0; + MCF_INTC1_ICR24 = 0; + MCF_INTC1_ICR25 = 0; + MCF_INTC1_ICR32 = 0; + MCF_INTC1_ICR33 = 0; + MCF_INTC1_ICR34 = 0; + MCF_INTC1_ICR35 = 0; + MCF_INTC1_ICR36 = 0; + MCF_INTC1_ICR37 = 0; + MCF_INTC1_ICR38 = 0; + MCF_INTC1_ICR39 = 0; + MCF_INTC0_IMRH = 0xffffffff; + MCF_INTC0_IMRL = 0xfffffffe; + MCF_INTC1_IMRH = 0xffffffff; + MCF_INTC1_IMRL = 0xfffffffe; +} + +/********************************************************************* +* init_pin_assignments - Pin Assignment and General Purpose I/O * +**********************************************************************/ +static void init_pin_assignments(void) +{ + /* Pin assignments for port NQ + Pins NQ7-NQ1 : EdgePort GPIO/IRQ + */ + MCF_GPIO_DDRNQ = 0; + MCF_GPIO_PNQPAR = MCF_GPIO_PNQPAR_PNQPAR7(0x1) | + MCF_GPIO_PNQPAR_PNQPAR6(0x1) | + MCF_GPIO_PNQPAR_PNQPAR5(0x1) | + MCF_GPIO_PNQPAR_PNQPAR4(0x1) | + MCF_GPIO_PNQPAR_PNQPAR3(0x1) | + MCF_GPIO_PNQPAR_PNQPAR2(0x1) | MCF_GPIO_PNQPAR_PNQPAR1(0x1); + + /* Pin assignments for port GP + Pins PG7-PG0 : EdgePort GPIO/IRQ + */ + MCF_GPIO_DDRGP = 0; + MCF_GPIO_PGPPAR = MCF_GPIO_PGPPAR_PGPPAR7 | + MCF_GPIO_PGPPAR_PGPPAR6 | + MCF_GPIO_PGPPAR_PGPPAR5 | + MCF_GPIO_PGPPAR_PGPPAR4 | + MCF_GPIO_PGPPAR_PGPPAR3 | + MCF_GPIO_PGPPAR_PGPPAR2 | + MCF_GPIO_PGPPAR_PGPPAR1 | MCF_GPIO_PGPPAR_PGPPAR0; + + /* Pin assignments for port DD + Pin DD7 : DDATA[3] + Pin DD6 : DDATA[2] + Pin DD5 : DDATA[1] + Pin DD4 : DDATA[0] + Pin DD3 : PST[3] + Pin DD2 : PST[2] + Pin DD1 : PST[1] + Pin DD0 : PST[0] + CCON[PSTEN] = 1 to enable PST/DDATA function + */ + MCF_GPIO_DDRDD = 0; + MCF_GPIO_PDDPAR = MCF_GPIO_PDDPAR_PDDPAR7 | + MCF_GPIO_PDDPAR_PDDPAR6 | + MCF_GPIO_PDDPAR_PDDPAR5 | + MCF_GPIO_PDDPAR_PDDPAR4 | + MCF_GPIO_PDDPAR_PDDPAR3 | + MCF_GPIO_PDDPAR_PDDPAR2 | + MCF_GPIO_PDDPAR_PDDPAR1 | MCF_GPIO_PDDPAR_PDDPAR0; + MCF_CIM_CCON = 0x0021; + + /* Pin assignments for port AN + Pins are all GPIO inputs + */ + MCF_GPIO_DDRAN = 0; + MCF_GPIO_PANPAR = 0; + + /* Pin assignments for port AS + Pins are all GPIO inputs + */ + MCF_GPIO_DDRAS = 0; + MCF_GPIO_PASPAR = 0; + + /* Pin assignments for port LD + Pins are all GPIO inputs + */ + MCF_GPIO_DDRLD = 0; + MCF_GPIO_PLDPAR = 0; + + /* Pin assignments for port QS + Pins are all GPIO inputs + */ + MCF_GPIO_DDRQS = 0; + MCF_GPIO_PQSPAR = 0; + + /* Pin assignments for port TA + Pins are all GPIO inputs + */ + MCF_GPIO_DDRTA = 0; + MCF_GPIO_PTAPAR = 0; + + /* Pin assignments for port TC + Pins are all GPIO inputs + */ + MCF_GPIO_DDRTC = 0; + MCF_GPIO_PTCPAR = 0; + + /* Pin assignments for port TD + Pins are all GPIO inputs + */ + MCF_GPIO_DDRTD = 0; + MCF_GPIO_PTDPAR = 0; + + /* Pin assignments for port UA + Pin UA3 : UART 0 clear-to-send, UCTS0 + Pin UA2 : UART 0 request-to-send, URTS0 + Pin UA1 : UART 0 receive data, URXD0 + Pin UA0 : UART 0 transmit data, UTXD0 + */ + MCF_GPIO_DDRUA = 0; + MCF_GPIO_PUAPAR = MCF_GPIO_PUAPAR_PUAPAR3(0x1) | + MCF_GPIO_PUAPAR_PUAPAR2(0x1) | + MCF_GPIO_PUAPAR_PUAPAR1(0x1) | MCF_GPIO_PUAPAR_PUAPAR0(0x1); + + /* Pin assignments for port UB + Pin UB3 : UART 1 clear-to-send, UCTS1 + Pin UB2 : UART 1 request-to-send, URTS1 + Pin UB1 : UART 1 receive data, URXD1 + Pin UB0 : UART 1 transmit data, UTXD1 + */ + MCF_GPIO_DDRUB = 0; + MCF_GPIO_PUBPAR = MCF_GPIO_PUBPAR_PUBPAR3(0x1) | + MCF_GPIO_PUBPAR_PUBPAR2(0x1) | + MCF_GPIO_PUBPAR_PUBPAR1(0x1) | MCF_GPIO_PUBPAR_PUBPAR0(0x1); + + /* Pin assignments for port UC + Pin UC3 : UART 2 clear-to-send, UCTS2 + Pin UC2 : UART 2 request-to-send, URTS2 + Pin UC1 : UART 2 receive data, URXD2 + Pin UC0 : UART 2 transmit data, UTXD2 + */ + MCF_GPIO_DDRUC = 0; + MCF_GPIO_PUCPAR = MCF_GPIO_PUCPAR_PUCPAR3 | + MCF_GPIO_PUCPAR_PUCPAR2 | + MCF_GPIO_PUCPAR_PUCPAR1 | MCF_GPIO_PUCPAR_PUCPAR0; + + /* Configure drive strengths */ + MCF_GPIO_PDSRH = 0; + MCF_GPIO_PDSRL = 0; + + /* Configure Wired-OR register */ + MCF_GPIO_PWOR = 0; +}
\ No newline at end of file diff --git a/bsps/m68k/mcf52235/start/init52235.c b/bsps/m68k/mcf52235/start/init52235.c new file mode 100644 index 0000000000..d54b624fdd --- /dev/null +++ b/bsps/m68k/mcf52235/start/init52235.c @@ -0,0 +1,79 @@ +/* + * This is where the real hardware setup is done. A minimal stack + * has been provided by the start.S code. No normal C or RTEMS + * functions can be called from here. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +extern void _wr_vbr(uint32_t); +extern void init_main(void); + +/* + * From linkcmds + */ + +extern uint8_t _INTERRUPT_VECTOR[]; + +extern uint8_t _clear_start[]; +extern uint8_t _clear_end[]; + +extern uint8_t _data_src_start[]; +extern uint8_t _data_dest_start[]; +extern uint8_t _data_dest_end[]; + +void Init52235(void) +{ + register uint32_t i; + register uint32_t *dp, *sp; + register uint8_t *dbp, *sbp; + + /* + * Initialize the hardware + */ + init_main(); + + /* + * Copy the vector table to RAM + */ + if (&_VBR != (void *) _INTERRUPT_VECTOR) { + sp = (uint32_t *) _INTERRUPT_VECTOR; + dp = (uint32_t *) &_VBR; + for (i = 0; i < 256; i++) { + *dp++ = *sp++; + } + } + + _wr_vbr((uint32_t) &_VBR); + + /* + * Move initialized data from ROM to RAM. + */ + if (_data_src_start != _data_dest_start) { + dbp = (uint8_t *) _data_dest_start; + sbp = (uint8_t *) _data_src_start; + i = _data_dest_end - _data_dest_start; + while (i--) + *dbp++ = *sbp++; + } + + /* + * Zero uninitialized data + */ + + if (_clear_start != _clear_end) { + sbp = _clear_start; + dbp = _clear_end; + i = dbp - sbp; + while (i--) + *sbp++ = 0; + } + + /* + * We have to call some kind of RTEMS function here! + */ + + boot_card(0); + for (;;) ; +} diff --git a/bsps/m68k/mcf52235/start/linkcmds b/bsps/m68k/mcf52235/start/linkcmds new file mode 100644 index 0000000000..7c7755cc21 --- /dev/null +++ b/bsps/m68k/mcf52235/start/linkcmds @@ -0,0 +1,195 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Freescale ColdFire mcf52235 + * + * COPYRIGHT (c) 1989-1999. + * 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.e + */ + +/* + * Declare some sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x20000000; +RamSize = DEFINED(RamSize) ? RamSize : 32K; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x400; +_FlashBase = DEFINED(_FlashBase) ? _FlashBase : 0x00000000; + +_VBR = 0x20000000; + +ENTRY(start) +STARTUP(start.o) + +MEMORY +{ + sram : ORIGIN = 0x20000000, LENGTH = 32K + flash : ORIGIN = 0x00000000, LENGTH = 256K +} + +SECTIONS +{ + /* + * Text, data and bss segments + */ + .text : { + + *(.text*) + *(.ram_code) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + * + * Various files can provide initialization and finalization + * functions. crtbegin.o and crtend.o are two instances. The + * body of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues + * from crti.o and function epilogues from crtn.o. crti.o must + * be linked first; crtn.o must be linked last. Because these + * are wildcards, it doesn't matter if the user does not + * actually link against crti.o and crtn.o; the linker won't + * look for a file to match a wildcard. The wildcard also + * means that it doesn't matter which directory crti.o and + * crtn.o are in. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * C++ constructors/destructors + * + * gcc uses crtbegin.o to find the start of the constructors + * and destructors 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. The + * constructor and destructor list are terminated in + * crtend.o. The same comments apply to it. + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + + *(.console_gdb_xfer) + *(.bootstrap_data) + } >flash + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + . = ALIGN(16); + _estuff = .; + PROVIDE (_etext = .); + } >flash + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >flash + + _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)); + + .data 0x20000400 : AT (_estuff) + { + PROVIDE( _data_dest_start = . ); + PROVIDE( _copy_start = .); + *(.data) + *(.data.*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (16); + PROVIDE (_edata = .); + PROVIDE (_copy_end = .); + PROVIDE (_data_dest_end = . ); + } >sram + + _data_src_start = _estuff; + _data_src_end = _data_dest_start + SIZEOF(.data); + + .bss : + { + PROVIDE (_clear_start = .); + *(.bss*) + *(COMMON) + . = ALIGN (16); + PROVIDE (_end = .); + PROVIDE (_clear_end = .); + } >sram + + .stack : + { + /* + * Starting Stack + */ + . += _StackSize; + . = ALIGN (16); + PROVIDE(_StackInit = .); + PROVIDE(WorkAreaBase = .); + } >sram + + /* 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) } + + PROVIDE (end_of_all = .); +} diff --git a/bsps/m68k/mcf5225x/start/bsp_specs b/bsps/m68k/mcf5225x/start/bsp_specs new file mode 100644 index 0000000000..3a20757667 --- /dev/null +++ b/bsps/m68k/mcf5225x/start/bsp_specs @@ -0,0 +1,10 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s crtn.o%s} + diff --git a/bsps/m68k/mcf5225x/start/bspclean.c b/bsps/m68k/mcf5225x/start/bspclean.c new file mode 100644 index 0000000000..5cd1aed1e9 --- /dev/null +++ b/bsps/m68k/mcf5225x/start/bspclean.c @@ -0,0 +1,27 @@ +/* + * This routine returns control from RTEMS to the monitor. + * + * Author: + * David Fiddes, D.J@fiddes.surfaid.org + * http://www.calm.hw.ac.uk/davidf/coldfire/ + * + * COPYRIGHT (c) 1989-1998. + * 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> +#include <rtems/bspIo.h> + +void bsp_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code error +) +{ + printk("\nRTEMS exited!\n"); +} diff --git a/bsps/m68k/mcf5225x/start/bspstart.c b/bsps/m68k/mcf5225x/start/bspstart.c new file mode 100644 index 0000000000..d5e0f37dc8 --- /dev/null +++ b/bsps/m68k/mcf5225x/start/bspstart.c @@ -0,0 +1,35 @@ +/* + * This routine does the bulk of the system initialisation. + */ + +/* + * Author: + * David Fiddes, D.J@fiddes.surfaid.org + * http://www.calm.hw.ac.uk/davidf/coldfire/ + * + * COPYRIGHT (c) 1989-1998. + * 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 __attribute__((weak)) bsp_start(void) +{ +} + +uint32_t __attribute__((weak)) bsp_get_CPU_clock_speed(void) +{ + #define DEF_CLOCK_SPEED 8000000.0F //8.0 MHz + #define MCF_MFD0_2_MASK 0x7000U + #define MCF_RFD0_2_MASK 0x0700U + #define MCF_MFD0_2_OFFSET 4U + + #define SPEED_BIAS ((((MCF_CLOCK_SYNCR & MCF_MFD0_2_MASK) >> 11) + MCF_MFD0_2_OFFSET) / (float)(((MCF_CLOCK_SYNCR & MCF_RFD0_2_MASK)>>7) ? : 1.0F)) + + return MCF_CLOCK_SYNCR & MCF_CLOCK_SYNCR_PLLEN ? SPEED_BIAS * DEF_CLOCK_SPEED : DEF_CLOCK_SPEED; +} diff --git a/bsps/m68k/mcf5225x/start/init5225x.c b/bsps/m68k/mcf5225x/start/init5225x.c new file mode 100644 index 0000000000..caf7db1953 --- /dev/null +++ b/bsps/m68k/mcf5225x/start/init5225x.c @@ -0,0 +1,84 @@ +/* + * 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. + * + * This is where the real hardware setup is done. A minimal stack + * has been provided by the start.S code. No normal C or RTEMS + * functions can be called from here. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +extern void _wr_vbr(uint32_t); + +extern long _d0_reset,_d1_reset,_M68kSpuriousInterruptCount; + +/* + * From linkcmds + */ + +extern uint8_t _INTERRUPT_VECTOR[]; + +extern uint8_t _clear_start[]; +extern uint8_t _clear_end[]; + +extern uint8_t _data_src_start[]; +extern uint8_t _data_dest_start[]; +extern uint8_t _data_dest_end[]; + +void Init5225x(void) +{ + register uint32_t i; + register uint32_t *dp, *sp; + register uint8_t *dbp, *sbp; + + /* + * Copy the vector table to RAM + */ + + if (&_VBR != (void *)_INTERRUPT_VECTOR) { + sp = (uint32_t *) _INTERRUPT_VECTOR; + dp = (uint32_t *) &_VBR; + for (i = 0; i < 256; i++) { + *dp++ = *sp++; + } + } + + /* + * Move initialized data from ROM to RAM. + */ + if (_data_src_start != _data_dest_start) { + dbp = (uint8_t *) _data_dest_start; + sbp = (uint8_t *) _data_src_start; + i = _data_dest_end - _data_dest_start; + while (i--) + *dbp++ = *sbp++; + } + + asm __volatile__ ("move.l %%d5,%0\n\t":"=r" (_d0_reset)); + asm __volatile__ ("move.l %%d6,%0\n\t":"=r" (_d1_reset)); + + /* + * Zero uninitialized data + */ + + if (_clear_start != _clear_end) { + sbp = _clear_start; + dbp = _clear_end; + i = dbp - sbp; + while (i--) + *sbp++ = 0; + } + +//_wr_vbr((uint32_t) &_VBR); + asm volatile("move.l %0,%%d7;movec %%d7,%%vbr\n\t"::"i"(&_VBR): "cc"); + + /* + * We have to call some kind of RTEMS function here! + */ + + boot_card(0); + for (;;) ; +} diff --git a/bsps/m68k/mcf5225x/start/linkcmds b/bsps/m68k/mcf5225x/start/linkcmds new file mode 100644 index 0000000000..81d2058872 --- /dev/null +++ b/bsps/m68k/mcf5225x/start/linkcmds @@ -0,0 +1,195 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Freescale ColdFire mcf52258 + * + * COPYRIGHT (c) 1989-1999. + * 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.e + */ + +/* + * Declare some sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x20000000; +RamSize = DEFINED(RamSize) ? RamSize : 64K; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x400; +_FlashBase = DEFINED(_FlashBase) ? _FlashBase : 0x00000000; + +_VBR = 0x20000000; + +ENTRY(start) +STARTUP(start.o) + + +MEMORY +{ + sram : ORIGIN = 0x20000000, LENGTH = 64K + flash : ORIGIN = 0x00000000, LENGTH = 512K +} + +SECTIONS +{ + /* + * Text, data and bss segments + */ + .text : { + + *(.text*) + *(.ram_code) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + * + * Various files can provide initialization and finalization + * functions. crtbegin.o and crtend.o are two instances. The + * body of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues + * from crti.o and function epilogues from crtn.o. crti.o must + * be linked first; crtn.o must be linked last. Because these + * are wildcards, it doesn't matter if the user does not + * actually link against crti.o and crtn.o; the linker won't + * look for a file to match a wildcard. The wildcard also + * means that it doesn't matter which directory crti.o and + * crtn.o are in. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * C++ constructors/destructors + * + * gcc uses crtbegin.o to find the start of the constructors + * and destructors 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. The + * constructor and destructor list are terminated in + * crtend.o. The same comments apply to it. + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + + *(.console_gdb_xfer) + *(.bootstrap_data) + } >flash + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + . = ALIGN(16); + _estuff = .; + PROVIDE (_etext = .); + } >flash + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >flash + + _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)); + + .data 0x20000400 : AT (_estuff) + { + PROVIDE( _data_dest_start = . ); + PROVIDE( _copy_start = .); + *(.data*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (16); + PROVIDE (_edata = .); + PROVIDE (_copy_end = .); + PROVIDE (_data_dest_end = . ); + } >sram + + _data_src_start = _estuff; + _data_src_end = _data_dest_start + SIZEOF(.data); + + .bss : + { + PROVIDE (_clear_start = .); + *(.bss*) + *(COMMON) + . = ALIGN (16); + PROVIDE (_end = .); + PROVIDE (_clear_end = .); + } >sram + + .stack : + { + /* + * Starting Stack + */ + . += _StackSize; + . = ALIGN (16); + PROVIDE(_StackInit = .); + PROVIDE(WorkAreaBase = .); + } >sram + + /* 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) } + + PROVIDE (end_of_all = .); +} diff --git a/bsps/m68k/mcf5235/start/bsp_specs b/bsps/m68k/mcf5235/start/bsp_specs new file mode 100644 index 0000000000..3a20757667 --- /dev/null +++ b/bsps/m68k/mcf5235/start/bsp_specs @@ -0,0 +1,10 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s crtn.o%s} + diff --git a/bsps/m68k/mcf5235/start/bspgetcpuclockspeed.c b/bsps/m68k/mcf5235/start/bspgetcpuclockspeed.c new file mode 100644 index 0000000000..548caaa9b8 --- /dev/null +++ b/bsps/m68k/mcf5235/start/bspgetcpuclockspeed.c @@ -0,0 +1,17 @@ +/* + * COPYRIGHT (c) 1989-2008. + * 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> + +extern char _CPUClockSpeed[]; + +uint32_t get_CPU_clock_speed(void) +{ + return( (uint32_t)_CPUClockSpeed); +} diff --git a/bsps/m68k/mcf5235/start/bspstart.c b/bsps/m68k/mcf5235/start/bspstart.c new file mode 100644 index 0000000000..744d4c9142 --- /dev/null +++ b/bsps/m68k/mcf5235/start/bspstart.c @@ -0,0 +1,60 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * 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> + +/* + * Read/write copy of common cache + * Split I/D cache + * Allow CPUSHL to invalidate a cache line + * Enable buffered writes + * No burst transfers on non-cacheable accesses + * Default cache mode is *disabled* (cache only ACRx areas) + */ +uint32_t cacr_mode = MCF5XXX_CACR_CENB | MCF5XXX_CACR_DBWE | MCF5XXX_CACR_DCM; + +/* + * Cacheable areas + */ +extern char RamBase[]; +extern char RamSize[]; + +/* + * bsp_start + * + * This routine does the bulk of the system initialisation. + */ +void bsp_start( void ) +{ + /* + * Invalidate the cache and disable it + */ + m68k_set_acr0(0); + m68k_set_acr1(0); + m68k_set_cacr(MCF5XXX_CACR_CINV); + + /* + * Cache SDRAM + */ + m68k_set_acr0(MCF5XXX_ACR_AB((uintptr_t)RamBase) | + MCF5XXX_ACR_AM((uintptr_t)RamSize-1) | + MCF5XXX_ACR_EN | + MCF5XXX_ACR_BWE | + MCF5XXX_ACR_SM_IGNORE); + + /* + * Enable the cache + */ + m68k_set_cacr(cacr_mode); +} diff --git a/bsps/m68k/mcf5235/start/copyvectors.c b/bsps/m68k/mcf5235/start/copyvectors.c new file mode 100644 index 0000000000..2c54c31a44 --- /dev/null +++ b/bsps/m68k/mcf5235/start/copyvectors.c @@ -0,0 +1,19 @@ +/* + * Move the copy out of the Init5235 file because gcc is broken. + */ + +#include <stdint.h> + +void CopyVectors(const uint32_t* old, uint32_t* new); + +void CopyVectors(const uint32_t* old, uint32_t* new) +{ + int v = 0; + while (v < 256) + { + *new = *old; + ++v; + ++new; + ++old; + } +} diff --git a/bsps/m68k/mcf5235/start/init5235.c b/bsps/m68k/mcf5235/start/init5235.c new file mode 100644 index 0000000000..5066941be0 --- /dev/null +++ b/bsps/m68k/mcf5235/start/init5235.c @@ -0,0 +1,89 @@ +/* + * This is where the real hardware setup is done. A minimal stack + * has been provided by the start.S code. No normal C or RTEMS + * functions can be called from here. + * + * This routine is pretty simple for the uC5235 because all the hard + * work has been done by the bootstrap dBUG code. + */ + +#include <rtems.h> +#include <bsp.h> + +#define MM_SDRAM_BASE (0x00000000) + +/* + * MCF5235_BSP_START_FROM_FLASH comes from the linker script + * If it is set to 0 then it is assumed that the motorola debug monitor + * is present and we do not need to re-initialize the SDRAM. Otherwise, + * if it is set to 1 then we want to boot our own code from flash and we + * do need to initialize the SDRAM. + */ + +extern uint32_t MCF5235_BSP_START_FROM_FLASH; +extern void CopyDataClearBSSAndStart (void); +extern void INTERRUPT_VECTOR(void); + +extern void CopyVectors(const uint32_t* old, uint32_t* new); + +void Init5235 (void) +{ + int x; + volatile int temp = 0; + int *address_of_MCF5235_BSP_START_FROM_FLASH; + + /*Setup the GPIO Registers */ + MCF5235_GPIO_UART=0x3FFF; + MCF5235_GPIO_PAR_AD=0xE1; + + /*Setup the Chip Selects so CS0 is flash */ + MCF5235_CS_CSAR0 =(0xFFE00000 & 0xffff0000)>>16; + MCF5235_CS_CSMR0 = 0x001f0001; + MCF5235_CS_CSCR0 = 0x1980; + + address_of_MCF5235_BSP_START_FROM_FLASH = (int *) & MCF5235_BSP_START_FROM_FLASH; + if ( (int)address_of_MCF5235_BSP_START_FROM_FLASH == 1) { + /*Setup the SDRAM */ + for(x=0; x<20000; x++) + { + temp +=1; + } + MCF5235_SDRAMC_DCR = 0x042E; + MCF5235_SDRAMC_DACR0 = 0x00001300; + MCF5235_SDRAMC_DMR0 = (0x00FC0000) | (0x00000001); + for(x=0; x<20000; x++) + { + temp +=1; + } + /* set ip ( bit 3 ) in dacr */ + MCF5235_SDRAMC_DACR0 |= (0x00000008) ; + /* init precharge */ + *((unsigned long *)MM_SDRAM_BASE) = 0xDEADBEEF; + /* set RE in dacr */ + MCF5235_SDRAMC_DACR0 |= (0x00008000); + /* wait */ + for(x=0; x<20000; x++) + { + temp +=1; + } + /* issue IMRS */ + MCF5235_SDRAMC_DACR0 |= (0x00000040); + *((short *)MM_SDRAM_BASE) = 0; + for(x=0; x<60000; x++) + { + temp +=1; + } + *((unsigned long*)MM_SDRAM_BASE)=0x12345678; + } /* we have finished setting up the sdram */ + + /* Copy the interrupt vector table to address 0x0 in SDRAM */ + CopyVectors((const uint32_t *)&INTERRUPT_VECTOR, (uint32_t*)0); + + m68k_set_vbr(0); + + /* + * Copy data, clear BSS and call boot_card() + */ + CopyDataClearBSSAndStart (); + +} diff --git a/bsps/m68k/mcf5235/start/linkcmds b/bsps/m68k/mcf5235/start/linkcmds new file mode 100644 index 0000000000..660c931e26 --- /dev/null +++ b/bsps/m68k/mcf5235/start/linkcmds @@ -0,0 +1,203 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Freescale ColdFire mcf5235 + * + * COPYRIGHT (c) 1989-1999. + * 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. + */ + +/* + * declare for the MCF5235_BSP_START_FROM_FLASH + * 0 - use debug monitor to load to ram + * 1 - load everything from flash from scratch + */ +MCF5235_BSP_START_FROM_FLASH = 0; + +/* + * Declare some sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamSize : 16M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0; + + +/* + * System clock speed + */ +_CPUClockSpeed = DEFINED(_CPUClockSpeed) ? _CPUClockSpeed : 150000000 ; + +/* + * Location of on-chip devices + */ +__IPSBAR = DEFINED(__IPSBAR) ? __IPSBAR : 0x40000000 ; +__SRAMBASE = DEFINED(__SRAMBASE) ? __SRAMBASE : 0x20000000 ; +_VBR = 0x0; + +ENTRY(start) +STARTUP(start.o) + +MEMORY +{ + dram : ORIGIN = 0, LENGTH = 16M + sram : ORIGIN = 0x20000000, LENGTH = 64K + flash : ORIGIN = 0xFFE00000, LENGTH = 2M +} + +SECTIONS +{ + + _header_offset = 0; + + /* + * Text, data and bss segments + */ + .text 0x40000 : { + + *(.text*) + *(.ram_code) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + * + * Various files can provide initialization and finalization + * functions. crtbegin.o and crtend.o are two instances. The + * body of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues + * from crti.o and function epilogues from crtn.o. crti.o must + * be linked first; crtn.o must be linked last. Because these + * are wildcards, it doesn't matter if the user does not + * actually link against crti.o and crtn.o; the linker won't + * look for a file to match a wildcard. The wildcard also + * means that it doesn't matter which directory crti.o and + * crtn.o are in. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + + /* + * C++ constructors/destructors + * + * gcc uses crtbegin.o to find the start of the constructors + * and destructors 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. The + * constructor and destructor list are terminated in + * crtend.o. The same comments apply to it. + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + + *(.console_gdb_xfer) + *(.bootstrap_data) + . = ALIGN(16); + _estuff = .; + PROVIDE (_etext = .); + } > dram + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > dram + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } > dram + + _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)); + + .data : { + PROVIDE( _data_dest_start = . ); + PROVIDE( _copy_start = .); + *(.data*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (16); + PROVIDE (_edata = .); + PROVIDE (_copy_end = .); + PROVIDE (_data_dest_end = . ); + } > dram + + _data_src_start = _estuff; + _data_src_end = _data_dest_start + SIZEOF(.data); + + .bss : { + _clear_start = .; + *(.bss*) + *(COMMON) + . = ALIGN (16); + PROVIDE (end = .); + _clear_end = .; + + WorkAreaBase = .; + } > dram + /* 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) } + +PROVIDE (end_of_all = .); +} diff --git a/bsps/m68k/mcf5235/start/linkcmdsflash b/bsps/m68k/mcf5235/start/linkcmdsflash new file mode 100644 index 0000000000..832424a2d9 --- /dev/null +++ b/bsps/m68k/mcf5235/start/linkcmdsflash @@ -0,0 +1,208 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Freescale ColdFire mcf5235 + * + * COPYRIGHT (c) 1989-1999. + * 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. + */ + +/* + * declare for the MCF5235_BSP_START_FROM_FLASH + * 0 - use debug monitor to load to ram + * 1 - load everything from flash from scratch + */ +MCF5235_BSP_START_FROM_FLASH = 1; + +/* + * Declare some sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamSize : 16M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0; + + +/* + * System clock speed + */ +_CPUClockSpeed = DEFINED(_CPUClockSpeed) ? _CPUClockSpeed : 150000000 ; + +/* + * Location of on-chip devices + */ +__IPSBAR = DEFINED(__IPSBAR) ? __IPSBAR : 0x40000000 ; +__SRAMBASE = DEFINED(__SRAMBASE) ? __SRAMBASE : 0x20000000 ; +_VBR = 0x0; + +ENTRY(start) +STARTUP(start.o) + +/* + * NOTE: If loading to flash with dBUG remember to change the origin to 0xFFF00000 because that's where user flash is + * located. + */ +MEMORY +{ + ram : ORIGIN = 0, LENGTH = 16M + sram : ORIGIN = 0x20000000, LENGTH = 64K + flash : ORIGIN = 0xFFE00000, LENGTH = 2M +} + +SECTIONS +{ + + _header_offset = 0; + + /* + * Text, data and bss segments + */ + .text : { + + *(.text*) + *(.ram_code) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + * + * Various files can provide initialization and finalization + * functions. crtbegin.o and crtend.o are two instances. The + * body of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues + * from crti.o and function epilogues from crtn.o. crti.o must + * be linked first; crtn.o must be linked last. Because these + * are wildcards, it doesn't matter if the user does not + * actually link against crti.o and crtn.o; the linker won't + * look for a file to match a wildcard. The wildcard also + * means that it doesn't matter which directory crti.o and + * crtn.o are in. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + + /* + * C++ constructors/destructors + * + * gcc uses crtbegin.o to find the start of the constructors + * and destructors 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. The + * constructor and destructor list are terminated in + * crtend.o. The same comments apply to it. + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + + *(.console_gdb_xfer) + *(.bootstrap_data) + . = ALIGN(16); + _estuff = .; + PROVIDE (_etext = .); + } >flash + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >flash + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >flash + + _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)); + + .data 0x4000 : AT ( ADDR(.tdata) + SIZEOF ( .tdata ) ) + { + PROVIDE( _data_dest_start = . ); + PROVIDE( _copy_start = .); + *(.data) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (16); + PROVIDE (_edata = .); + PROVIDE (_copy_end = .); + PROVIDE (_data_dest_end = . ); + } >ram + + _data_src_start = _estuff; + _data_src_end = _data_dest_start + SIZEOF(.data); + + .bss : { + _clear_start = .; + *(.bss*) + *(COMMON) + . = ALIGN (16); + PROVIDE (end = .); + _clear_end = .; + + WorkAreaBase = .; + } >ram + /* 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) } + +PROVIDE (end_of_all = .); +} diff --git a/bsps/m68k/mcf5235/start/linkcmdsram b/bsps/m68k/mcf5235/start/linkcmdsram new file mode 100644 index 0000000000..ec7483001e --- /dev/null +++ b/bsps/m68k/mcf5235/start/linkcmdsram @@ -0,0 +1,203 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Freescale ColdFire mcf5235 + * + * COPYRIGHT (c) 1989-1999. + * 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. + */ + +/* + * declare for the MCF5235_BSP_START_FROM_FLASH + * 0 - use debug monitor to load to ram + * 1 - load everything from flash from scratch + */ +MCF5235_BSP_START_FROM_FLASH = 0; + +/* + * Declare some sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamSize : 16M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0; + + +/* + * System clock speed + */ +_CPUClockSpeed = DEFINED(_CPUClockSpeed) ? _CPUClockSpeed : 150000000 ; + +/* + * Location of on-chip devices + */ +__IPSBAR = DEFINED(__IPSBAR) ? __IPSBAR : 0x40000000 ; +__SRAMBASE = DEFINED(__SRAMBASE) ? __SRAMBASE : 0x20000000 ; +_VBR = 0x0; + +ENTRY(start) +STARTUP(start.o) + +MEMORY +{ + ram : ORIGIN = 0, LENGTH = 16M + sram : ORIGIN = 0x20000000, LENGTH = 64K + flash : ORIGIN = 0xFFE00000, LENGTH = 2M +} + +SECTIONS +{ + + _header_offset = 0; + + /* + * Text, data and bss segments + */ + .text 0x40000 : { + + *(.text*) + *(.ram_code) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + * + * Various files can provide initialization and finalization + * functions. crtbegin.o and crtend.o are two instances. The + * body of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues + * from crti.o and function epilogues from crtn.o. crti.o must + * be linked first; crtn.o must be linked last. Because these + * are wildcards, it doesn't matter if the user does not + * actually link against crti.o and crtn.o; the linker won't + * look for a file to match a wildcard. The wildcard also + * means that it doesn't matter which directory crti.o and + * crtn.o are in. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + + /* + * C++ constructors/destructors + * + * gcc uses crtbegin.o to find the start of the constructors + * and destructors 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. The + * constructor and destructor list are terminated in + * crtend.o. The same comments apply to it. + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + + *(.console_gdb_xfer) + *(.bootstrap_data) + . = ALIGN(16); + _estuff = .; + PROVIDE (_etext = .); + } >ram + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >ram + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >ram + + _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)); + + .data : { + PROVIDE( _data_dest_start = . ); + PROVIDE( _copy_start = .); + *(.data) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (16); + PROVIDE (_edata = .); + PROVIDE (_copy_end = .); + PROVIDE (_data_dest_end = . ); + } >ram + + _data_src_start = _estuff; + _data_src_end = _data_dest_start + SIZEOF(.data); + + .bss : { + _clear_start = .; + *(.bss*) + *(COMMON) + . = ALIGN (16); + PROVIDE (end = .); + _clear_end = .; + + WorkAreaBase = .; + } >ram + /* 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) } + +PROVIDE (end_of_all = .); +} diff --git a/bsps/m68k/mcf5329/start/bsp_specs b/bsps/m68k/mcf5329/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/m68k/mcf5329/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/m68k/mcf5329/start/bspstart.c b/bsps/m68k/mcf5329/start/bspstart.c new file mode 100644 index 0000000000..d5a258da47 --- /dev/null +++ b/bsps/m68k/mcf5329/start/bspstart.c @@ -0,0 +1,41 @@ +/* + * This routine does the bulk of the system initialisation. + */ + +/* + * Author: + * David Fiddes, D.J@fiddes.surfaid.org + * http://www.calm.hw.ac.uk/davidf/coldfire/ + * + * COPYRIGHT (c) 1989-1998. + * 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> +#include <rtems/rtems/cache.h> + +void bsp_start(void) +{ + /* cfinit invalidates cache and sets acr registers */ + + /* + * Enable the cache, we only need to enable the instruction cache as the + * 532x has a unified data and instruction cache. + */ + rtems_cache_enable_instruction(); +} + +uint32_t bsp_get_CPU_clock_speed(void) +{ + return 240000000; +} + +uint32_t bsp_get_BUS_clock_speed(void) +{ + return 80000000; +} diff --git a/bsps/m68k/mcf5329/start/cfinit.c b/bsps/m68k/mcf5329/start/cfinit.c new file mode 100644 index 0000000000..1fe9015449 --- /dev/null +++ b/bsps/m68k/mcf5329/start/cfinit.c @@ -0,0 +1,707 @@ +/********************************************************************* +* Initialisation Code for ColdFire MCF5329 Processor * +********************************************************************** + Generated by ColdFire Initialisation Utility 2.10.8 + Wed Jul 02 14:26:25 2008 + + MicroAPL Ltd makes no warranties in respect of the suitability + of this code for any particular purpose, and accepts + no liability for any loss arising out of its use. The person or + persons making use of this file must make the final evaluation + as to its suitability and correctness for a particular application. + +*/ + +/* External reference frequency is 16.0000 MHz + Internal bus clock frequency = 80.00 MHz + Processor core frequency = 240.00 MHz +*/ + +#include <bsp.h> + +/* eDMA Transfer Control Descriptor definitions */ +#define MCF_EDMA_TCD_W0(channel) (*(vuint32 *)(0xFC045000+((channel)*0x20))) /* Transfer Control Descriptor Word 0 */ +#define MCF_EDMA_TCD_W1(channel) (*(vuint32 *)(0xFC045004+((channel)*0x20))) /* Transfer Control Descriptor Word 1 */ +#define MCF_EDMA_TCD_W2(channel) (*(vuint32 *)(0xFC045008+((channel)*0x20))) /* Transfer Control Descriptor Word 2 */ +#define MCF_EDMA_TCD_W3(channel) (*(vuint32 *)(0xFC04500C+((channel)*0x20))) /* Transfer Control Descriptor Word 3 */ +#define MCF_EDMA_TCD_W4(channel) (*(vuint32 *)(0xFC045010+((channel)*0x20))) /* Transfer Control Descriptor Word 4 */ +#define MCF_EDMA_TCD_W5(channel) (*(vuint32 *)(0xFC045014+((channel)*0x20))) /* Transfer Control Descriptor Word 5 */ +#define MCF_EDMA_TCD_W6(channel) (*(vuint32 *)(0xFC045018+((channel)*0x20))) /* Transfer Control Descriptor Word 6 */ +#define MCF_EDMA_TCD_W7(channel) (*(vuint32 *)(0xFC04501C+((channel)*0x20))) /* Transfer Control Descriptor Word 7 */ + +/* Function prototypes */ +void init_main(void); +static void disable_interrupts(void); +static void disable_watchdog_timer(void); +static void disable_cache(void); +extern void init_clock_config(void) __attribute__ ((section(".ram_code"))); +static void init_cache(void); +static void init_crossbar(void); +extern void init_chip_selects(void) __attribute__ ((section(".ram_code"))); +static void init_eport(void); +static void init_flexcan(void); +static void init_dma_timers(void); +static void init_interrupt_timers(void); +static void init_real_time_clock(void); +static void init_watchdog_timers(void); +static void init_edma(void); +static void init_pin_assignments(void); +extern void init_sdram_controller(void) + __attribute__ ((section(".ram_code"))); +static void init_interrupt_controller(void); + +/********************************************************************* +* init_main - Main entry point for initialisation code * +**********************************************************************/ +void init_main(void) +{ + init_clock_config(); + + /* Disable interrupts, watchdog timer, cache */ + disable_interrupts(); + disable_watchdog_timer(); + disable_cache(); + + /* Initialise individual modules */ + init_cache(); + init_crossbar(); + init_chip_selects(); + init_eport(); + init_flexcan(); + init_dma_timers(); + init_interrupt_timers(); + init_real_time_clock(); + init_watchdog_timers(); + init_edma(); + init_pin_assignments(); + + /* Initialise SDRAM controller (must be done after pin assignments) */ + init_sdram_controller(); + + /* Initialise interrupt controller */ + init_interrupt_controller(); +} + +/********************************************************************* +* disable_interrupts - Disable all interrupt sources * +**********************************************************************/ +static void disable_interrupts(void) +{ + vuint8 *p; + int i; + + /* Set ICR001-ICR063 to 0x0 */ + p = (vuint8 *) & MCF_INTC0_ICR1; + for (i = 1; i <= 63; i++) + *p++ = 0x0; + + /* Set ICR100-ICR163 to 0x0 */ + p = (vuint8 *) & MCF_INTC1_ICR0; + for (i = 100; i <= 163; i++) + *p++ = 0x0; +} + +/********************************************************************* +* disable_watchdog_timer - Disable system watchdog timer * +**********************************************************************/ +static void disable_watchdog_timer(void) +{ + /* Disable Core Watchdog Timer */ + MCF_SCM_CWCR = 0; +} + +/********************************************************************* +* disable_cache - Disable and invalidate cache * +**********************************************************************/ +static void disable_cache(void) +{ + __asm__ ("move.l #0x01000000,%d0"); + __asm__ ("movec %d0,%CACR"); +} + +/********************************************************************* +* init_clock_config - Clock Module * +**********************************************************************/ +void init_clock_config(void) +{ + /* Clock module uses normal PLL mode with 16.0000 MHz external reference + Bus clock frequency = 80.00 MHz + Processor clock frequency = 3 x bus clock = 240.00 MHz + Dithering disabled + */ + + /* Check to see if the SDRAM has already been initialized + by a run control tool. If it has, put SDRAM into self-refresh mode before + initializing the PLL + */ + if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF) + MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE; + + /* Temporarily switch to LIMP mode + NOTE: Ensure that this code is not executing from SDRAM, since the + SDRAM Controller is disabled in LIMP mode + */ + MCF_CCM_CDR = (MCF_CCM_CDR & 0xf0ff) | MCF_CCM_CDR_LPDIV(0x2); + MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP; + + /* Configure the PLL settings */ + MCF_PLL_PODR = MCF_PLL_PODR_CPUDIV(0x2) | MCF_PLL_PODR_BUSDIV(0x6); + MCF_PLL_PFDR = MCF_PLL_PFDR_MFD(0x78); + MCF_PLL_PLLCR = 0; + MCF_PLL_PMDR = 0; + + /* Enable PLL and wait for lock */ + MCF_CCM_MISCCR &= ~MCF_CCM_MISCCR_LIMP; + while ((MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK) == 0) ; + + /* From the Device Errata: + + "After exiting LIMP mode, the value of 0x40000000 should be written + to address 0xFC0B8080 before attempting to initialize the SDRAMC + or exit the SDRAM from self-refresh mode." + */ + *(vuint32 *) 0xfc0b8080 = 0x40000000; + + /* If we put the SDRAM into self-refresh mode earlier, restore mode now */ + if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF) + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE; +} + +/********************************************************************* +* init_cache - Unified (Instruction and Data) Cache * +**********************************************************************/ +static void init_cache(void) +{ + /* ACR0: Cache accesses to 32 MB memory region at address $40000000 + CACR: Don't cache accesses to the rest of memory + */ + /* + * Cache is enabled in bspstart.c + */ +#if 0 + __asm__ ("move.l #0xa0000600,%d0"); + __asm__ ("movec %d0,%CACR"); +#endif + __asm__ ("move.l #0x4001c020,%d0"); + __asm__ ("movec %d0,%ACR0"); + __asm__ ("move.l #0x00000000,%d0"); + __asm__ ("movec %d0,%ACR1"); +} + +/********************************************************************* +* init_crossbar - Cross-Bar Switch (XBS) Module * +**********************************************************************/ +static void init_crossbar(void) +{ + /* XBS settings for FlexBus/SDRAM Controller slave: + Fixed priority (Core, LCD, eDMA, FEC, USB Host, USB OTG), park on ColdFire Core + */ + MCF_XBS_PRS1 = MCF_XBS_PRS_M6(0x5) | + MCF_XBS_PRS_M5(0x4) | + MCF_XBS_PRS_M4(0x1) | MCF_XBS_PRS_M2(0x3) | MCF_XBS_PRS_M1(0x2); + MCF_XBS_CRS1 = 0; + + /* XBS settings for SRAM Backdoor slave: + Fixed priority (Core, eDMA, FEC, LCD, USB Host, USB OTG), park on ColdFire Core + */ + MCF_XBS_PRS4 = MCF_XBS_PRS_M6(0x5) | + MCF_XBS_PRS_M5(0x4) | + MCF_XBS_PRS_M4(0x3) | MCF_XBS_PRS_M2(0x2) | MCF_XBS_PRS_M1(0x1); + MCF_XBS_CRS4 = 0; + + /* XBS settings for Cryptography Modules slave: + Fixed priority (Core, eDMA, FEC, LCD, USB Host, USB OTG), park on ColdFire Core + */ + MCF_XBS_PRS6 = MCF_XBS_PRS_M6(0x5) | + MCF_XBS_PRS_M5(0x4) | + MCF_XBS_PRS_M4(0x3) | MCF_XBS_PRS_M2(0x2) | MCF_XBS_PRS_M1(0x1); + MCF_XBS_CRS6 = 0; + + /* XBS settings for On-chip Peripherals slave: + Fixed priority (Core, eDMA, FEC, LCD, USB Host, USB OTG), park on ColdFire Core + */ + MCF_XBS_PRS7 = MCF_XBS_PRS_M6(0x5) | + MCF_XBS_PRS_M5(0x4) | + MCF_XBS_PRS_M4(0x3) | MCF_XBS_PRS_M2(0x2) | MCF_XBS_PRS_M1(0x1); + MCF_XBS_CRS7 = 0; +} + +/********************************************************************* +* init_chip_selects - Chip Select Module (FlexBus) * +**********************************************************************/ +void init_chip_selects(void) +{ + /* Chip Select 1 disabled (CSMR1[V] = 0) */ + MCF_FBCS1_CSMR = 0; + + /* Chip Select 2 disabled (CSMR2[V] = 0) */ + MCF_FBCS2_CSMR = 0; + + /* Chip Select 3 disabled (CSMR3[V] = 0) */ + MCF_FBCS3_CSMR = 0; + + /* Chip Select 4 disabled (CSMR4[V] = 0) */ + MCF_FBCS4_CSMR = 0; + + /* Chip Select 5 disabled (CSMR5[V] = 0) */ + MCF_FBCS5_CSMR = 0; + + /* Chip Select 0: 2 MB of Flash at base address $00000000 + Port size = 16 bits + Assert chip select on first rising clock edge after address is asserted + Generate internal transfer acknowledge after 7 wait states + Address is held for 1 clock at end of read and write cycles + */ + MCF_FBCS0_CSAR = 0; + MCF_FBCS0_CSCR = MCF_FBCS_CSCR_WS(0x7) | + (0x1 << 9) | MCF_FBCS_CSCR_AA | MCF_FBCS_CSCR_PS(0x2) | MCF_FBCS_CSCR_BEM; + MCF_FBCS0_CSMR = MCF_FBCS_CSMR_BAM(0x1f) | MCF_FBCS_CSMR_V; +} + +/********************************************************************* +* init_eport - Edge Port Module (EPORT) * +**********************************************************************/ +static void init_eport(void) +{ + /* Pins 1-7 configured as GPIO inputs */ + MCF_EPORT_EPPAR = 0; + MCF_EPORT_EPDDR = 0; + MCF_EPORT_EPIER = 0; +} + +/********************************************************************* +* init_flexcan - FlexCAN Module * +**********************************************************************/ +static void init_flexcan(void) +{ + /* FlexCAN controller disabled (CANMCR0[MDIS]=1) */ + MCF_CAN_IMASK = 0; + MCF_CAN_RXGMASK = MCF_CAN_RXGMASK_MI(0x1fffffff); + MCF_CAN_RX14MASK = MCF_CAN_RX14MASK_MI(0x1fffffff); + MCF_CAN_RX15MASK = MCF_CAN_RX15MASK_MI(0x1fffffff); + MCF_CAN_CANCTRL = 0; + MCF_CAN_CANMCR = MCF_CAN_CANMCR_MDIS | + MCF_CAN_CANMCR_FRZ | + MCF_CAN_CANMCR_HALT | MCF_CAN_CANMCR_SUPV | MCF_CAN_CANMCR_MAXMB(0xf); +} + +/********************************************************************* +* init_sdram_controller - SDRAM Controller * +**********************************************************************/ +void init_sdram_controller(void) +{ + /* Check to see if the SDRAM has already been initialized + by a run control tool and skip if so + */ + if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF) + return; + + /* Ensure that there is a delay from processor reset of the time recommended in + the SDRAM data sheet (typically 100-200 microseconds) until the following + code so that the SDRAM is ready for commands... + */ + + /* SDRAM controller configured for Double-data rate (DDR) SDRAM + Bus width = 16 bits + SDRAM specification: + SDRAM clock frequency = 80.00 MHz + CASL = 2.5 + ACTV-to-read/write delay, tRCD = 20.0 nanoseconds + Write recovery time, tWR = 15.0 nanoseconds + Precharge comand to ACTV command, tRP = 20.0 nanoseconds + Auto refresh command period, tRFC = 75.0 nanoseconds + Average periodic refresh interval, tREFI = 7.8 microseconds + */ + + /* Memory block 0 enabled - 32 MBytes at address $40000000 + Block consists of 1 device x 256 MBits (13 rows x 9 columns x 4 banks) + */ + MCF_SDRAMC_SDCS0 = MCF_SDRAMC_SDCS_BASE(0x400) | MCF_SDRAMC_SDCS_CSSZ(0x18); + + /* Memory block 1 disabled */ + MCF_SDRAMC_SDCS1 = 0; + + /* Initialise SDCFG1 register with delay and timing values + SRD2RWP = 4, SWT2RWP = 3, RD_LAT = 7, ACT2RW = 2 + PRE2ACT = 2, REF2ACT = 6, WT_LAT = 3 + */ + MCF_SDRAMC_SDCFG1 = MCF_SDRAMC_SDCFG1_SRD2RW(0x4) | + MCF_SDRAMC_SDCFG1_SWT2RD(0x3) | + MCF_SDRAMC_SDCFG1_RDLAT(0x7) | + MCF_SDRAMC_SDCFG1_ACT2RW(0x2) | + MCF_SDRAMC_SDCFG1_PRE2ACT(0x2) | + MCF_SDRAMC_SDCFG1_REF2ACT(0x6) | MCF_SDRAMC_SDCFG1_WTLAT(0x3); + + /* Initialise SDCFG2 register with delay and timing values + BRD2RP = 5, BWT2RWP = 6, BRD2W = 6, BL = 7 + */ + MCF_SDRAMC_SDCFG2 = MCF_SDRAMC_SDCFG2_BRD2PRE(0x5) | + MCF_SDRAMC_SDCFG2_BWT2RW(0x6) | + MCF_SDRAMC_SDCFG2_BRD2WT(0x6) | MCF_SDRAMC_SDCFG2_BL(0x7); + + /* Issue a Precharge All command */ + MCF_SDRAMC_SDCR = MCF_SDRAMC_SDCR_MODE_EN | + MCF_SDRAMC_SDCR_CKE | + MCF_SDRAMC_SDCR_DDR | + MCF_SDRAMC_SDCR_MUX(0x1) | + MCF_SDRAMC_SDCR_RCNT(0x8) | MCF_SDRAMC_SDCR_PS_16 | MCF_SDRAMC_SDCR_IPALL; + + /* Write Extended Mode Register */ + MCF_SDRAMC_SDMR = MCF_SDRAMC_SDMR_BNKAD_LEMR | MCF_SDRAMC_SDMR_CMD; + + /* Write Mode Register and Reset DLL */ + MCF_SDRAMC_SDMR = MCF_SDRAMC_SDMR_BNKAD_LMR | + MCF_SDRAMC_SDMR_AD(0x163) | MCF_SDRAMC_SDMR_CMD; + + /* Insert code here to pause for DLL lock time specified by memory... */ + + /* Issue a second Precharge All command */ + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL; + + /* Refresh sequence... + (check the number of refreshes required by the SDRAM manufacturer) + */ + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF; + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF; + + /* Write Mode Register and clear the Reset DLL bit */ + MCF_SDRAMC_SDMR = MCF_SDRAMC_SDMR_BNKAD_LMR | + MCF_SDRAMC_SDMR_AD(0x63) | MCF_SDRAMC_SDMR_CMD; + + /* Enable automatic refresh and lock SDMR */ + MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN; + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_REF | + MCF_SDRAMC_SDCR_DQS_OE(0x8) | MCF_SDRAMC_SDCR_DQS_OE(0x4); + +} + +/********************************************************************* +* init_dma_timers - DMA Timers * +**********************************************************************/ +static void init_dma_timers(void) +{ + /* DMA Timer 0 disabled (DTMR0[RST] = 0) */ + MCF_DTIM0_DTMR = 0; + MCF_DTIM0_DTXMR = 0; + MCF_DTIM0_DTRR = MCF_DTIM_DTRR_REF(0xffffffff); + + /* DMA Timer 1 disabled (DTMR1[RST] = 0) */ + MCF_DTIM1_DTMR = 0; + MCF_DTIM1_DTXMR = 0; + MCF_DTIM1_DTRR = MCF_DTIM_DTRR_REF(0xffffffff); + + /* DMA Timer 2 disabled (DTMR2[RST] = 0) */ + MCF_DTIM2_DTMR = 0; + MCF_DTIM2_DTXMR = 0; + MCF_DTIM2_DTRR = MCF_DTIM_DTRR_REF(0xffffffff); + + /* DMA Timer 3 disabled (DTMR3[RST] = 0) */ + MCF_DTIM3_DTMR = 0; + MCF_DTIM3_DTXMR = 0; + MCF_DTIM3_DTRR = MCF_DTIM_DTRR_REF(0xffffffff); +} + +/********************************************************************* +* init_interrupt_timers - Programmable Interrupt Timers (PIT) * +**********************************************************************/ +static void init_interrupt_timers(void) +{ + /* PIT0 disabled (PCSR0[EN]=0) */ + MCF_PIT0_PCSR = 0; + + /* PIT1 disabled (PCSR1[EN]=0) */ + MCF_PIT1_PCSR = 0; + + /* PIT2 disabled (PCSR2[EN]=0) */ + MCF_PIT2_PCSR = 0; + + /* PIT3 disabled (PCSR3[EN]=0) */ + MCF_PIT3_PCSR = 0; +} + +/********************************************************************* +* init_real_time_clock - Real-Time Clock (RTC) * +**********************************************************************/ +static void init_real_time_clock(void) +{ + /* Disable the RTC */ + MCF_RTC_CR = 0; +} + +/********************************************************************* +* init_watchdog_timers - Watchdog Timers * +**********************************************************************/ +static void init_watchdog_timers(void) +{ + /* Watchdog Timer disabled (WCR[EN]=0) + NOTE: WCR and WMR cannot be written again until after the + processor is reset. + */ + MCF_WTM_WCR = MCF_WTM_WCR_WAIT | MCF_WTM_WCR_DOZE | MCF_WTM_WCR_HALTED; + MCF_WTM_WMR = MCF_WTM_WMR_WM(0xffff); + + /* Core watchdog timer disabled */ + MCF_SCM_CWCR = MCF_SCM_CWCR_CWT(0x8); +} + +/********************************************************************* +* init_edma - eDMA Controller * +**********************************************************************/ +static void init_edma(void) +{ + /* Associate eDMA channels 9-12 with SSI signals */ + MCF_CCM_MISCCR &= ~MCF_CCM_MISCCR_TIM_DMA; + + /* Configured for round-robin arbitration mode */ + MCF_EDMA_CR = MCF_EDMA_CR_ERCA; + + /* All error interrupts are disabled */ + MCF_EDMA_EEI = 0; + + /* All DMA requests from peripherals are masked */ + MCF_EDMA_ERQ = 0; +} + +/********************************************************************* +* init_interrupt_controller - Interrupt Controller * +**********************************************************************/ +static void init_interrupt_controller(void) +{ + /* No interrupt sources configured */ + MCF_INTC1_ICR0 = 0; + MCF_INTC1_ICR1 = 0; + MCF_INTC1_ICR3 = 0; + MCF_INTC1_ICR4 = 0; + MCF_INTC1_ICR5 = 0; + MCF_INTC1_ICR6 = 0; + MCF_INTC1_ICR7 = 0; + MCF_INTC1_ICR8 = 0; + MCF_INTC1_ICR9 = 0; + MCF_INTC1_ICR10 = 0; + MCF_INTC1_ICR11 = 0; + MCF_INTC1_ICR12 = 0; + MCF_INTC1_ICR13 = 0; + MCF_INTC1_ICR14 = 0; + MCF_INTC1_ICR15 = 0; + MCF_INTC1_ICR16 = 0; + MCF_INTC1_ICR17 = 0; + MCF_INTC1_ICR18 = 0; + MCF_INTC1_ICR19 = 0; + MCF_INTC1_ICR40 = 0; + MCF_INTC1_ICR41 = 0; + MCF_INTC1_ICR42 = 0; + MCF_INTC1_ICR43 = 0; + MCF_INTC1_ICR44 = 0; + MCF_INTC1_ICR45 = 0; + MCF_INTC1_ICR46 = 0; + MCF_INTC1_ICR47 = 0; + MCF_INTC1_ICR48 = 0; + MCF_INTC1_ICR49 = 0; + MCF_INTC1_ICR50 = 0; + MCF_INTC1_ICR51 = 0; + MCF_INTC1_ICR52 = 0; + MCF_INTC1_ICR53 = 0; + MCF_INTC0_ICR1 = 0; + MCF_INTC0_ICR2 = 0; + MCF_INTC0_ICR3 = 0; + MCF_INTC0_ICR4 = 0; + MCF_INTC0_ICR5 = 0; + MCF_INTC0_ICR6 = 0; + MCF_INTC0_ICR7 = 0; + MCF_INTC0_ICR8 = 0; + MCF_INTC0_ICR9 = 0; + MCF_INTC0_ICR10 = 0; + MCF_INTC0_ICR11 = 0; + MCF_INTC0_ICR12 = 0; + MCF_INTC0_ICR13 = 0; + MCF_INTC0_ICR14 = 0; + MCF_INTC0_ICR15 = 0; + MCF_INTC0_ICR16 = 0; + MCF_INTC0_ICR17 = 0; + MCF_INTC0_ICR18 = 0; + MCF_INTC0_ICR19 = 0; + MCF_INTC0_ICR20 = 0; + MCF_INTC0_ICR21 = 0; + MCF_INTC0_ICR22 = 0; + MCF_INTC0_ICR23 = 0; + MCF_INTC0_ICR24 = 0; + MCF_INTC0_ICR25 = 0; + MCF_INTC0_ICR26 = 0; + MCF_INTC0_ICR27 = 0; + MCF_INTC0_ICR28 = 0; + MCF_INTC0_ICR30 = 0; + MCF_INTC0_ICR31 = 0; + MCF_INTC0_ICR32 = 0; + MCF_INTC0_ICR33 = 0; + MCF_INTC0_ICR34 = 0; + MCF_INTC0_ICR35 = 0; + MCF_INTC0_ICR36 = 0; + MCF_INTC0_ICR37 = 0; + MCF_INTC0_ICR38 = 0; + MCF_INTC0_ICR39 = 0; + MCF_INTC0_ICR40 = 0; + MCF_INTC0_ICR41 = 0; + MCF_INTC0_ICR42 = 0; + MCF_INTC0_ICR43 = 0; + MCF_INTC0_ICR44 = 0; + MCF_INTC0_ICR45 = 0; + MCF_INTC0_ICR46 = 0; + MCF_INTC0_ICR47 = 0; + MCF_INTC0_ICR48 = 0; + MCF_INTC0_ICR62 = 0; + MCF_INTC0_IMRH = 0xffffffff; + MCF_INTC0_IMRL = 0xffffffff; + MCF_INTC1_IMRH = 0xffffffff; + MCF_INTC1_IMRL = 0xffffffff; +} + +/********************************************************************* +* init_pin_assignments - Pin Assignment and General Purpose I/O * +**********************************************************************/ +static void init_pin_assignments(void) +{ + /* Pin assignments for port BUSCTL + Pin BUSCTL3 : External bus output enable, /OE + Pin BUSCTL2 : External bus transfer acknowledge, /TA + Pin BUSCTL1 : External bus read/write, R/W + Pin BUSCTL0 : External bus transfer start, /TS + */ + MCF_GPIO_PDDR_BUSCTL = 0; + MCF_GPIO_PAR_BUSCTL = MCF_GPIO_PAR_BUSCTL_PAR_OE | + MCF_GPIO_PAR_BUSCTL_PAR_TA | + MCF_GPIO_PAR_BUSCTL_PAR_RWB | MCF_GPIO_PAR_BUSCTL_PAR_TS(0x3); + + /* Pin assignments for port BE + Pin BE3 : External bus byte enable BW/BWE3 + Pin BE2 : External bus byte enable BW/BWE2 + Pin BE1 : External bus byte enable BW/BWE1 + Pin BE0 : External bus byte enable BW/BWE0 + */ + MCF_GPIO_PDDR_BE = 0; + MCF_GPIO_PAR_BE = MCF_GPIO_PAR_BE_PAR_BE3 | + MCF_GPIO_PAR_BE_PAR_BE2 | + MCF_GPIO_PAR_BE_PAR_BE1 | MCF_GPIO_PAR_BE_PAR_BE0; + + /* Pin assignments for port CS + Pin CS5 : Flex bus chip select /FB_CS5 + Pin CS4 : Flex bus chip select /FB_CS4 + Pin CS3 : Flex bus chip select /FB_CS3 + Pin CS2 : Flex bus chip select /FB_CS2 + Pin CS1 : Flex bus chip select /FB_CS1 + */ + MCF_GPIO_PDDR_CS = 0; + MCF_GPIO_PAR_CS = MCF_GPIO_PAR_CS_PAR_CS5 | + MCF_GPIO_PAR_CS_PAR_CS4 | + MCF_GPIO_PAR_CS_PAR_CS3 | + MCF_GPIO_PAR_CS_PAR_CS2 | MCF_GPIO_PAR_CS_PAR_CS1; + + /* Pin assignments for port FECI2C + Pin FECI2C3 : FEC management data clock, FEC_MDC + Pin FECI2C2 : FEC management data, FEC_MDIO + Pin FECI2C1 : GPIO input + Pin FECI2C0 : GPIO input + */ + MCF_GPIO_PDDR_FECI2C = 0; + MCF_GPIO_PAR_FECI2C = MCF_GPIO_PAR_FECI2C_PAR_MDC(0x3) | + MCF_GPIO_PAR_FECI2C_PAR_MDIO(0x3); + + /* Pin assignments for ports FECH and FECL + Pin FECH7 : FEC transmit clock, FEC_TXCLK + Pin FECH6 : FEC transmit enable, FEC_TXEN + Pin FECH5 : FEC transmit data 0, FEC_TXD0 + Pin FECH4 : FEC collision, FEC_COL + Pin FECH3 : FEC receive clock, FEC_RXCLK + Pin FECH2 : FEC receive data valid, FEC_RXDV + Pin FECH1 : FEC receive data 0, FEC_RXD0 + Pin FECH0 : FEC carrier receive sense, FEC_CRS + Pin FECL7 : FEC transmit data 3, FEC_TXD3 + Pin FECL6 : FEC transmit data 2, FEC_TXD2 + Pin FECL5 : FEC transmit data 1, FEC_TXD1 + Pin FECL4 : FEC transmit error, FEC_TXER + Pin FECL3 : FEC receive data 3, FEX_RXD3 + Pin FECL2 : FEC receive data 2, FEX_RXD2 + Pin FECL1 : FEC receive data 1, FEX_RXD1 + Pin FECL0 : FEC receive error, FEC_RXER + */ + MCF_GPIO_PDDR_FECH = 0; + MCF_GPIO_PDDR_FECL = 0; + MCF_GPIO_PAR_FEC = MCF_GPIO_PAR_FEC_PAR_FEC_7W(0x3) | + MCF_GPIO_PAR_FEC_PAR_FEC_MII(0x3); + + /* Pin assignments for port IRQ + Pins are all used for EdgePort GPIO/IRQ + */ + MCF_GPIO_PAR_IRQ = 0; + + /* Pin assignments for port LCDDATAH + Pins are all GPIO inputs + */ + MCF_GPIO_PDDR_LCDDATAH = 0; + MCF_GPIO_PAR_LCDDATA = 0; + + /* Pin assignments for port LCDDATAM + Port LCDDATAM pins are all GPIO inputs + */ + MCF_GPIO_PDDR_LCDDATAM = 0; + + /* Pin assignments for port LCDDATAL + Port LCDDATAL pins are all GPIO inputs + */ + MCF_GPIO_PDDR_LCDDATAL = 0; + + /* Pin assignments for port LCDCTLH + Pins are all GPIO inputs + */ + MCF_GPIO_PDDR_LCDCTLH = 0; + MCF_GPIO_PAR_LCDCTL = 0; + + /* Pin assignments for port LCDCTLL + Pins are all GPIO inputs + */ + MCF_GPIO_PDDR_LCDCTLL = 0; + + /* Pin assignments for port PWM + Pins are all GPIO inputs + */ + MCF_GPIO_PDDR_PWM = 0; + MCF_GPIO_PAR_PWM = 0; + + /* Pin assignments for port QSPI + Pins are all GPIO inputs + */ + MCF_GPIO_PDDR_QSPI = 0; + MCF_GPIO_PAR_QSPI = 0; + + /* Pin assignments for port SSI + Pins are all GPIO inputs + */ + MCF_GPIO_PDDR_SSI = 0; + MCF_GPIO_PAR_SSI = 0; + + /* Pin assignments for port TIMER + Pins are all GPIO outputs + */ + MCF_GPIO_PDDR_TIMER = MCF_GPIO_PDDR_TIMER_PDDR_TIMER3 | + MCF_GPIO_PDDR_TIMER_PDDR_TIMER2 | + MCF_GPIO_PDDR_TIMER_PDDR_TIMER1 | MCF_GPIO_PDDR_TIMER_PDDR_TIMER0; + MCF_GPIO_PAR_TIMER = 0; + + /* Pin assignments for port UART + Pin UART7 : UART 1 clear-to-send, /U1CTS + Pin UART6 : UART 1 request-to-send, /U1RTS + Pin UART5 : UART 1 transmit data, U1TXD + Pin UART4 : UART 1 receive data, U1RXD + Pin UART3 : UART 0 clear-to-send, /U0CTS + Pin UART2 : UART 0 request-to-send, /U0RTS + Pin UART1 : UART 0 transmit data, U0TXD + Pin UART0 : UART 0 receive data, U0RXD + */ + MCF_GPIO_PDDR_UART = 0; + MCF_GPIO_PAR_UART = MCF_GPIO_PAR_UART_PAR_UCTS1(0x3) | + MCF_GPIO_PAR_UART_PAR_URTS1(0x3) | + MCF_GPIO_PAR_UART_PAR_URXD1(0x3) | + MCF_GPIO_PAR_UART_PAR_UTXD1(0x3) | + MCF_GPIO_PAR_UART_PAR_UCTS0 | + MCF_GPIO_PAR_UART_PAR_URTS0 | + MCF_GPIO_PAR_UART_PAR_URXD0 | MCF_GPIO_PAR_UART_PAR_UTXD0; +} diff --git a/bsps/m68k/mcf5329/start/init5329.c b/bsps/m68k/mcf5329/start/init5329.c new file mode 100644 index 0000000000..8719514736 --- /dev/null +++ b/bsps/m68k/mcf5329/start/init5329.c @@ -0,0 +1,79 @@ +/* + * This is where the real hardware setup is done. A minimal stack + * has been provided by the start.S code. No normal C or RTEMS + * functions can be called from here. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +extern void _wr_vbr(uint32_t); +extern void init_main(void); + +/* + * From linkcmds + */ + +extern uint8_t _INTERRUPT_VECTOR[]; + +extern uint8_t _clear_start[]; +extern uint8_t _clear_end[]; + +extern uint8_t _data_src_start[]; +extern uint8_t _data_dest_start[]; +extern uint8_t _data_dest_end[]; + +void Init5329(void) +{ + register uint32_t i; + register uint8_t *dbp, *sbp; + register uint32_t *dp, *sp; + + /* + * Initialize the hardware + */ + init_main(); + + /* + * Copy the vector table to RAM + */ + if (&_VBR != (void *) _INTERRUPT_VECTOR) { + sp = (uint32_t *) _INTERRUPT_VECTOR; + dp = (uint32_t *) &_VBR; + for (i = 0; i < 256; i++) { + *dp++ = *sp++; + } + } + + _wr_vbr((uint32_t) &_VBR); + + /* + * Move initialized data from ROM to RAM. + */ + if (_data_src_start != _data_dest_start) { + dbp = (uint8_t *) _data_dest_start; + sbp = (uint8_t *) _data_src_start; + i = _data_dest_end - _data_dest_start; + while (i--) + *dbp++ = *sbp++; + } + + /* + * Zero uninitialized data + */ + + if (_clear_start != _clear_end) { + sbp = _clear_start; + dbp = _clear_end; + i = dbp - sbp; + while (i--) + *sbp++ = 0; + } + + /* + * We have to call some kind of RTEMS function here! + */ + + boot_card(0); + for (;;) ; +} diff --git a/bsps/m68k/mcf5329/start/linkcmds b/bsps/m68k/mcf5329/start/linkcmds new file mode 100644 index 0000000000..1982a91f7b --- /dev/null +++ b/bsps/m68k/mcf5329/start/linkcmds @@ -0,0 +1,206 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Freescale ColdFire mcf52235 + * + * COPYRIGHT (c) 1989-1999. + * 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.e + */ + +/* + * Declare some sizes. + */ +_CoreSRamBase = DEFINED(RamBase) ? RamBase : 0x80000000; +_CoreSRamSize = DEFINED(RamSize) ? RamSize : 32K; + +RamBase = DEFINED(RamBase) ? RamBase : 0x40000000; +RamSize = DEFINED(RamSize) ? RamSize : 32M; + +_BootFlashBase = DEFINED(_FlashBase) ? _FlashBase : 0x00000000; +_BootFlashSize = DEFINED(_FlashBase) ? _FlashBase : 2M; + +HeapSize = DEFINED(HeapSize) ? HeapSize : 0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x400; + +_VBR = 0x40000000; + +ENTRY(start) +STARTUP(start.o) + +MEMORY +{ + core_sram : ORIGIN = 0x80000000, LENGTH = 32K + boot_flash : ORIGIN = 0x00000000, LENGTH = 2M + dram : ORIGIN = 0x40000000, LENGTH = 32M +} + +SECTIONS +{ + .ram_code : + { + *(.ram_code) + } > core_sram + + /* + * Text, data and bss segments + */ + .text 0x40000500 : { + + *(.text*) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + * + * Various files can provide initialization and finalization + * functions. crtbegin.o and crtend.o are two instances. The + * body of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues + * from crti.o and function epilogues from crtn.o. crti.o must + * be linked first; crtn.o must be linked last. Because these + * are wildcards, it doesn't matter if the user does not + * actually link against crti.o and crtn.o; the linker won't + * look for a file to match a wildcard. The wildcard also + * means that it doesn't matter which directory crti.o and + * crtn.o are in. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * C++ constructors/destructors + * + * gcc uses crtbegin.o to find the start of the constructors + * and destructors 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. The + * constructor and destructor list are terminated in + * crtend.o. The same comments apply to it. + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + + *(.console_gdb_xfer) + *(.bootstrap_data) + . = ALIGN(16); + _estuff = .; + PROVIDE (_etext = .); + } > dram + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > dram + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } > dram + + _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)); + + .data : + { + PROVIDE( _data_dest_start = . ); + PROVIDE( _copy_start = .); + *(.data*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (16); + PROVIDE (_edata = .); + PROVIDE (_copy_end = .); + PROVIDE (_data_dest_end = . ); + } > dram + + _data_src_start = _estuff; + _data_src_end = _data_dest_start + SIZEOF(.data); + + .bss : + { + _clear_start = .; + *(.bss*) + *(COMMON) + . = ALIGN (16); + PROVIDE (_end = .); + + _clear_end = .; + WorkAreaBase = .; + } > dram + + .start_stack : + { + /* + * Starting Stack + */ + . += _StackSize; + . = ALIGN (16); + PROVIDE(_StackInit = .); + } > core_sram + + /* 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) } + + PROVIDE (end_of_all = .); +} diff --git a/bsps/m68k/mcf5329/start/linkcmdsflash b/bsps/m68k/mcf5329/start/linkcmdsflash new file mode 100644 index 0000000000..af0cc4ee01 --- /dev/null +++ b/bsps/m68k/mcf5329/start/linkcmdsflash @@ -0,0 +1,202 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Freescale ColdFire mcf52235 + * + * COPYRIGHT (c) 1989-1999. + * 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.e + */ + +/* + * Declare some sizes. + */ +_CoreSRamBase = DEFINED(RamBase) ? RamBase : 0x80000000; +_CoreSRamSize = DEFINED(RamSize) ? RamSize : 32K; + +RamBase = DEFINED(RamBase) ? RamBase : 0x40000000; +RamSize = DEFINED(RamSize) ? RamSize : 32M; + +_BootFlashBase = DEFINED(_FlashBase) ? _FlashBase : 0x00000000; +_BootFlashSize = DEFINED(_FlashBase) ? _FlashBase : 2M; + +HeapSize = DEFINED(HeapSize) ? HeapSize : 0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x400; + +_VBR = 0x40000000; + +ENTRY(start) +STARTUP(start.o) + +MEMORY +{ + core_sram : ORIGIN = 0x80000000, LENGTH = 32K + boot_flash : ORIGIN = 0x00000000, LENGTH = 2M + dram : ORIGIN = 0x40000000, LENGTH = 32M +} + +SECTIONS +{ + /* + * Text, data and bss segments + */ + .text : { + + *(.text*) + *(.ram_code) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + * + * Various files can provide initialization and finalization + * functions. crtbegin.o and crtend.o are two instances. The + * body of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues + * from crti.o and function epilogues from crtn.o. crti.o must + * be linked first; crtn.o must be linked last. Because these + * are wildcards, it doesn't matter if the user does not + * actually link against crti.o and crtn.o; the linker won't + * look for a file to match a wildcard. The wildcard also + * means that it doesn't matter which directory crti.o and + * crtn.o are in. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * C++ constructors/destructors + * + * gcc uses crtbegin.o to find the start of the constructors + * and destructors 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. The + * constructor and destructor list are terminated in + * crtend.o. The same comments apply to it. + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + + *(.console_gdb_xfer) + *(.bootstrap_data) + } > boot_flash + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + . = ALIGN(16); + _estuff = .; + PROVIDE (_etext = .); + } > boot_flash + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } > boot_flash + + _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)); + + .data 0x40000500 : AT (_estuff) + { + PROVIDE( _data_dest_start = . ); + PROVIDE( _copy_start = .); + *(.data*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (16); + PROVIDE (_edata = .); + PROVIDE (_copy_end = .); + PROVIDE (_data_dest_end = . ); + } > dram + + _data_src_start = _estuff; + _data_src_end = _data_dest_start + SIZEOF(.data); + + .bss : + { + _clear_start = .; + *(.bss*) + *(COMMON) + . = ALIGN (16); + PROVIDE (_end = .); + + _clear_end = .; + WorkAreaBase = .; + } > dram + + .start_stack : + { + /* + * Starting Stack + */ + . += _StackSize; + . = ALIGN (16); + PROVIDE(_StackInit = .); + } > core_sram + + /* 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) } + + PROVIDE (end_of_all = .); +} diff --git a/bsps/m68k/mrm332/start/bsp_specs b/bsps/m68k/mrm332/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/m68k/mrm332/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/m68k/mrm332/start/linkcmds b/bsps/m68k/mrm332/start/linkcmds new file mode 100644 index 0000000000..1ee7117d6b --- /dev/null +++ b/bsps/m68k/mrm332/start/linkcmds @@ -0,0 +1,212 @@ +/* linkcmds + */ + +OUTPUT_ARCH(m68k) +ENTRY(start) +STARTUP(start.o) +__DYNAMIC = 0; + +/* + * ROM: + * +--------------------+ <- low memory + * | .text | + * | etext | + * | ctor list | the ctor and dtor lists are for + * | dtor list | C++ support + * | _endtext | + * | temporary .data | .data is moved to RAM by crt0 + * | | + * +--------------------+ <- high memory + * + * + * RAM: + * +--------------------+ <- low memory + * | .data | initialized data goes here + * | _sdata | + * | _edata | + * +--------------------+ + * | .bss | + * | __bss_start | start of bss, cleared by crt0 + * | _end | start of heap, used by sbrk() + * +--------------------+ + * | heap space | + * | _ENDHEAP | + * | stack space | + * | __stack | top of stack + * +--------------------+ <- high memory + */ + +/* + * Declare some sizes. + */ +RomBase = DEFINED(RomBase) ? RomBase : 0x90000; +RamBase = DEFINED(RamBase) ? RamBase : 0x03000; +RamSize = DEFINED(RamSize) ? RamSize : 0x7d000; +_RamEnd = RamBase + RamSize; + +MEMORY +{ + rom : ORIGIN = 0x90000, LENGTH = 0x70000 + ram : ORIGIN = 0x03000, LENGTH = 0x7d000 +} + +_copy_data_from_rom = 1; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x2000; + + +/* + * + */ +SECTIONS +{ + .text : + { + . = .; + text_start = .; + _text_start = .; + *(.text*) + . = ALIGN (16); + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + * + * Various files can provide initialization and finalization + * functions. crtbegin.o and crtend.o are two instances. The + * body of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues + * from crti.o and function epilogues from crtn.o. crti.o must + * be linked first; crtn.o must be linked last. Because these + * are wildcards, it doesn't matter if the user does not + * actually link against crti.o and crtn.o; the linker won't + * look for a file to match a wildcard. The wildcard also + * means that it doesn't matter which directory crti.o and + * crtn.o are in. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * C++ constructors/destructors + * + * gcc uses crtbegin.o to find the start of the constructors + * and destructors 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. The + * constructor and destructor list are terminated in + * crtend.o. The same comments apply to it. + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + PROVIDE (_etext = .); + _endtext = .; + __data_start_rom = .; + } > rom + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > rom + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } > rom + _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)); + .gcc_exc : + AT ( ADDR(.tdata) + SIZEOF( .tdata ) ) + { + *(.gcc_exc) + } > ram + .data : AT(__data_start_rom) + { + PROVIDE (_copy_start = .); + *(.data*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (16); + PROVIDE (_edata = .); + PROVIDE (_copy_end = .); + } > ram + .shbss : + { + *(.shbss) + } > ram + .bss : + { + M68Kvec = .; + . += (256 * 4); + _clear_start = .; + *(.dynbss) + *(.bss* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (16); + PROVIDE (end = .); + . += _StackSize; + . = ALIGN (16); + _stack_init = .; + _clear_end = .; + + WorkAreaBase = .; + } > ram + .stab . (NOLOAD) : + { + [ .stab ] + } + .stabstr . (NOLOAD) : + { + [ .stabstr ] + } +} diff --git a/bsps/m68k/mrm332/start/start_c.c b/bsps/m68k/mrm332/start/start_c.c new file mode 100644 index 0000000000..060c96b004 --- /dev/null +++ b/bsps/m68k/mrm332/start/start_c.c @@ -0,0 +1,130 @@ +/** + * @file + * + * MRM332 C Start Up Code + */ + +/* + * COPYRIGHT (c) 2000. + * Matt Cross <profesor@gweep.net> + * + * 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 <mrm332.h> +#include <rtems/m68k/sim.h> +#define __START_C__ + +/* + * This prototype really should have the noreturn attribute but + * that causes a warning. Not sure how to fix that. + */ +/* void dumby_start () __attribute__ ((noreturn)); */ +void start_c(void); + +void start_c(void) { + +#ifdef SET_EDIV +#define OPTIONAL_EDIV EDIV +#else +#define OPTIONAL_EDIV 0 +#endif + + /* Synthesizer Control Register */ + /* see section(s) 4.8 */ + /* end include in ram_init.S */ + *SYNCR = (unsigned short int) (SAM(MRM_W, 15, VCO) | SAM(0x0, 14, PRESCALE) + | SAM(MRM_Y, 8, COUNTER) | OPTIONAL_EDIV); + while (!(*SYNCR & SLOCK)) + ; /* protect from clock overshoot */ + /* include in ram_init.S */ + *SYNCR = (unsigned short int) (SAM(MRM_W, 15, VCO) | SAM(MRM_X, 14, + PRESCALE) | SAM(MRM_Y, 8, COUNTER) | OPTIONAL_EDIV); + + /* System Protection Control Register */ + /* !!! can only write to once after reset !!! */ + /* see section 3.8.4 of the SIM Reference Manual */ + *SYPCR = (unsigned char) (HME | BME); + + /* Periodic Interrupr Control Register */ + /* see section 3.8.2 of the SIM Reference Manual */ + *PICR = (unsigned short int) (SAM(0, 8, PIRQL) | SAM(MRM_PIV, 0, PIV)); + /* ^^^ zero disables interrupt, don't enable here or ram_init will + be wrong. It's enabled below. */ + + /* Periodic Interrupt Timer Register */ + /* see section 3.8.3 of the SIM Reference Manual */ + *PITR = (unsigned short int) (SAM(0x09, 0, PITM)); + /* 1.098mS interrupt, assuming 32.768 KHz input clock */ + + /* Port C Data */ + /* load values before enabled */ + *PORTC = (unsigned char) 0x0; + + /* Port E and F Data Register */ + /* see section 9 of the SIM Reference Manual */ + *PORTE0 = (unsigned char) 0; + *PORTF0 = (unsigned char) 0; + + /* Port E and F Data Direction Register */ + /* see section 9 of the SIM Reference Manual */ + *DDRE = (unsigned char) 0xff; + *DDRF = (unsigned char) 0xfd; + + /* Port E and F Pin Assignment Register. Set up Port E and F as I/O */ + /* see section 9 of the SIM Reference Manual */ + *PEPAR = (unsigned char) 0; + *PFPAR = (unsigned char) 0; + + /* end of SIM initalization code */ + /* end include in ram_init.S */ + + /* + * Initialize RAM by copying the .data section out of ROM (if + * needed) and "zero-ing" the .bss section. + */ + { + register char *src = _etext; + register char *dst = _copy_start; + + if (_copy_data_from_rom) { + /* ROM has data at end of text; copy it. */ + while (dst < _edata) + *dst++ = *src++; + } + /* Zero bss */ + for (dst = _clear_start; dst < end; dst++) { + *dst = 0; + } + } + + /* + * Initialize vector table. + */ + { + rtems_isr_entry *monitors_vector_table; + + m68k_get_vbr(monitors_vector_table); + + M68Kvec[4] = monitors_vector_table[4]; /* breakpoints vector */ + M68Kvec[9] = monitors_vector_table[9]; /* trace vector */ + M68Kvec[31] = monitors_vector_table[31]; /* level 7 interrupt */ + M68Kvec[47] = monitors_vector_table[47]; /* system call vector */ + M68Kvec[66] = monitors_vector_table[66]; /* user defined */ + + m68k_set_vbr(&M68Kvec); + } + + + /* + * Execute main with arguments argc and agrv. + */ + boot_card((void*)0); + reboot(); + +} diff --git a/bsps/m68k/mvme147/start/bsp_specs b/bsps/m68k/mvme147/start/bsp_specs new file mode 100644 index 0000000000..3a20757667 --- /dev/null +++ b/bsps/m68k/mvme147/start/bsp_specs @@ -0,0 +1,10 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s crtn.o%s} + diff --git a/bsps/m68k/mvme147/start/bspclean.c b/bsps/m68k/mvme147/start/bspclean.c new file mode 100644 index 0000000000..6606b9a249 --- /dev/null +++ b/bsps/m68k/mvme147/start/bspclean.c @@ -0,0 +1,49 @@ +/* + * This routine returns control to 147Bug. + */ + +/* + * COPYRIGHT (c) 1989-2014. + * 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. + * + * MVME147 port for TNI - Telecom Bretagne + * by Dominique LE CAMPION (Dominique.LECAMPION@enst-bretagne.fr) + * May 1996 + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +extern void start(void); + +static rtems_isr bsp_return_to_monitor_trap( + rtems_vector_number vector +) +{ + register volatile void *start_addr; + + m68k_set_vbr( 0 ); /* restore 147Bug vectors */ + __asm__ volatile( "trap #15" ); /* trap to 147Bug */ + __asm__ volatile( ".short 0x63" ); /* return to 147Bug (.RETURN) */ + /* restart program */ + start_addr = start; + + __asm__ volatile ( "jmp %0@" : "=a" (start_addr) : "0" (start_addr) ); +} + +void bsp_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code error +) +{ + pcc->timer1_int_control = 0; /* Disable Timer 1 */ + pcc->timer2_int_control = 0; /* Disable Timer 2 */ + + M68Kvec[ 45 ] = bsp_return_to_monitor_trap; /* install handler */ + __asm__ volatile( "trap #13" ); /* ensures SUPV mode */ +} diff --git a/bsps/m68k/mvme147/start/bspstart.c b/bsps/m68k/mvme147/start/bspstart.c new file mode 100644 index 0000000000..cb5f84a075 --- /dev/null +++ b/bsps/m68k/mvme147/start/bspstart.c @@ -0,0 +1,45 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * COPYRIGHT (c) 1989-1999. + * 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. + * + * MVME147 port for TNI - Telecom Bretagne + * by Dominique LE CAMPION (Dominique.LECAMPION@enst-bretagne.fr) + * May 1996 + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +void bsp_start( void ) +{ + rtems_isr_entry *monitors_vector_table; + int index; + + monitors_vector_table = (rtems_isr_entry *)0; /* 135Bug Vectors are at 0 */ + m68k_set_vbr( monitors_vector_table ); + + for ( index=2 ; index<=255 ; index++ ) + M68Kvec[ index ] = monitors_vector_table[ 32 ]; + + M68Kvec[ 2 ] = monitors_vector_table[ 2 ]; /* bus error vector */ + M68Kvec[ 4 ] = monitors_vector_table[ 4 ]; /* breakpoints vector */ + M68Kvec[ 9 ] = monitors_vector_table[ 9 ]; /* trace vector */ + M68Kvec[ 47 ] = monitors_vector_table[ 47 ]; /* system call vector */ + + m68k_set_vbr( &M68Kvec ); + + pcc->int_base_vector = PCC_BASE_VECTOR; /* Set the PCC int vectors base */ + + (*(uint8_t*)0xfffe2001) = 0x08; /* make VME access round-robin */ + + rtems_cache_enable_instruction(); + rtems_cache_enable_data(); +} diff --git a/bsps/m68k/mvme147/start/linkcmds b/bsps/m68k/mvme147/start/linkcmds new file mode 100644 index 0000000000..6603a438f1 --- /dev/null +++ b/bsps/m68k/mvme147/start/linkcmds @@ -0,0 +1,30 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Motorola MVME147 boards. + */ + +/* + * COPYRIGHT (c) 1989-2007,2016. + * 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. + * + * MVME147 port for TNI - Telecom Bretagne + * by Dominique LE CAMPION (Dominique.LECAMPION@enst-bretagne.fr) + * May 1996 + */ + +MEMORY +{ + bootrom_reserved : ORIGIN = 0x00000000, LENGTH = 0x5000 + ram : ORIGIN = 0x00005000, LENGTH = 4M - 0x5000 +} + +REGION_ALIAS ("REGION_TEXT", ram); +REGION_ALIAS ("REGION_TEXT_LOAD", ram); +REGION_ALIAS ("REGION_DATA", ram); +REGION_ALIAS ("REGION_DATA_LOAD", ram); + +INCLUDE linkcmds.base diff --git a/bsps/m68k/mvme147s/start/bsp_specs b/bsps/m68k/mvme147s/start/bsp_specs new file mode 100644 index 0000000000..3a20757667 --- /dev/null +++ b/bsps/m68k/mvme147s/start/bsp_specs @@ -0,0 +1,10 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s crtn.o%s} + diff --git a/bsps/m68k/mvme147s/start/bspstart.c b/bsps/m68k/mvme147s/start/bspstart.c new file mode 100644 index 0000000000..497b644150 --- /dev/null +++ b/bsps/m68k/mvme147s/start/bspstart.c @@ -0,0 +1,108 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * COPYRIGHT (c) 1989-1999. + * 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. + * + * MVME147 port for TNI - Telecom Bretagne + * by Dominique LE CAMPION (Dominique.LECAMPION@enst-bretagne.fr) + * May 1996 + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +void bsp_start( void ) +{ + rtems_isr_entry *monitors_vector_table; + int index; + uint8_t node_number; + + monitors_vector_table = (rtems_isr_entry *)0; /* 147Bug Vectors are at 0 */ + m68k_set_vbr( monitors_vector_table ); + + for ( index=2 ; index<=255 ; index++ ) + M68Kvec[ index ] = monitors_vector_table[ 32 ]; + + M68Kvec[ 2 ] = monitors_vector_table[ 2 ]; /* bus error vector */ + M68Kvec[ 4 ] = monitors_vector_table[ 4 ]; /* breakpoints vector */ + M68Kvec[ 9 ] = monitors_vector_table[ 9 ]; /* trace vector */ + M68Kvec[ 47 ] = monitors_vector_table[ 47 ]; /* system call vector */ + + m68k_set_vbr( &M68Kvec ); + + pcc->int_base_vector = PCC_BASE_VECTOR & 0xF0; + /* Set the PCC int vectors base */ + + /* VME shared memory configuration */ + /* Only the first node shares its top 128k DRAM */ + + vme_lcsr->utility_interrupt_vector = VME_BASE_VECTOR & 0xF8; + /* Set VMEchip base interrupt vector */ + vme_lcsr->utility_interrupt_mask |= 0x02; + /* Enable SIGLP interruption (see shm support) */ + pcc->general_purpose_control &= 0x10; + /* Enable VME master interruptions */ + + if (vme_lcsr->system_controller & 0x01) { + /* the board is system controller */ + vme_lcsr->system_controller = 0x08; + /* Make VME access round-robin */ + } + +#if defined(RTEMS_MULTIPROCESSING) + node_number = (uint8_t) + (rtems_configuration_get_user_multiprocessing_table()->node - 1) & 0xF; +#else + node_number = 1; +#endif + /* Get and store node ID, first node_number = 0 */ + vme_gcsr->board_identification = node_number; + + vme_lcsr->gcsr_base_address = node_number; + /* Setup the base address of this board's gcsr */ + vme_lcsr->timer_configuration = 0x6a; + /* Enable VME time outs, maximum periods */ + + if (node_number == 0) { + pcc->slave_base_address = 0x01; + /* Set local DRAM base address on the VME bus to the DRAM size */ + + vme_lcsr->vme_bus_requester = 0x80; + while (! (vme_lcsr->vme_bus_requester & 0x40)); + /* Get VMEbus mastership */ + vme_lcsr->slave_address_modifier = 0xfb; + /* Share everything */ + vme_lcsr->slave_configuration = 0x80; + /* Share local DRAM */ + vme_lcsr->vme_bus_requester = 0x0; + /* release bus */ + } else { + pcc->slave_base_address = 0; + /* Set local DRAM base address on the VME bus to 0 */ + + vme_lcsr->vme_bus_requester = 0x80; + while (! (vme_lcsr->vme_bus_requester & 0x40)); + /* Get VMEbus mastership */ + vme_lcsr->slave_address_modifier = 0x08; + /* Share only the short adress range */ + vme_lcsr->slave_configuration = 0; + /* Don't share local DRAM */ + vme_lcsr->vme_bus_requester = 0x0; + /* release bus */ + } + + vme_lcsr->master_address_modifier = 0; + /* Automatically set the address modifier */ + vme_lcsr->master_configuration = 1; + /* Disable D32 transfers : they don't work on my VMEbus rack */ + + rtems_cache_enable_instruction(); + rtems_cache_enable_data(); +} diff --git a/bsps/m68k/mvme147s/start/linkcmds b/bsps/m68k/mvme147s/start/linkcmds new file mode 100644 index 0000000000..01be6d93b2 --- /dev/null +++ b/bsps/m68k/mvme147s/start/linkcmds @@ -0,0 +1,30 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Motorola MVME147s boards. + */ + +/* + * COPYRIGHT (c) 1989-2007,2016. + * 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. + * + * MVME147 port for TNI - Telecom Bretagne + * by Dominique LE CAMPION (Dominique.LECAMPION@enst-bretagne.fr) + * May 1996 + */ + +MEMORY +{ + bootrom_reserved : ORIGIN = 0x00000000, LENGTH = 0x7000 + ram : ORIGIN = 0x00007000, LENGTH = 4M - 0x7000 +} + +REGION_ALIAS ("REGION_TEXT", ram); +REGION_ALIAS ("REGION_TEXT_LOAD", ram); +REGION_ALIAS ("REGION_DATA", ram); +REGION_ALIAS ("REGION_DATA_LOAD", ram); + +INCLUDE linkcmds.base diff --git a/bsps/m68k/mvme162/start/bsp_specs b/bsps/m68k/mvme162/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/m68k/mvme162/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/m68k/mvme162/start/bspclean.c b/bsps/m68k/mvme162/start/bspclean.c new file mode 100644 index 0000000000..dd91f96b1a --- /dev/null +++ b/bsps/m68k/mvme162/start/bspclean.c @@ -0,0 +1,47 @@ +/* + * This routine returns control to 162Bug. + */ + +/* + * COPYRIGHT (c) 1989-2014. + * 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. + * + * Modifications of respective RTEMS file: COPYRIGHT (c) 1994. + * EISCAT Scientific Association. M.Savitski + * + * This material is a part of the MVME162 Board Support Package + * for the RTEMS executive. Its licensing policies are those of the + * RTEMS above. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <rtems/zilog/z8036.h> +#include <page_table.h> + +static rtems_isr bsp_return_to_monitor_trap( + rtems_vector_number vector +) +{ + page_table_teardown(); + + lcsr->intr_ena = 0; /* disable interrupts */ + m68k_set_vbr(MOT_162BUG_VEC_ADDRESS); /* restore 162Bug vectors */ + + __asm__ volatile( "trap #15" ); /* trap to 162Bug */ + __asm__ volatile( ".short 0x63" ); /* return to 162Bug (.RETURN) */ +} + +void bsp_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code error +) +{ + M68Kvec[ 45 ] = bsp_return_to_monitor_trap; /* install handler */ + __asm__ volatile( "trap #13" ); /* ensures SUPV mode */ +} diff --git a/bsps/m68k/mvme162/start/bspstart.c b/bsps/m68k/mvme162/start/bspstart.c new file mode 100644 index 0000000000..29e56e35ea --- /dev/null +++ b/bsps/m68k/mvme162/start/bspstart.c @@ -0,0 +1,58 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * COPYRIGHT (c) 1989-1999. + * 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. + * + * Modifications of respective RTEMS file: COPYRIGHT (c) 1994. + * EISCAT Scientific Association. M.Savitski + * + * This material is a part of the MVME162 Board Support Package + * for the RTEMS executive. Its licensing policies are those of the + * RTEMS above. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <page_table.h> + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ +void bsp_start( void ) +{ + rtems_isr_entry *monitors_vector_table; + int index; + + monitors_vector_table = (rtems_isr_entry *)MOT_162BUG_VEC_ADDRESS; + m68k_set_vbr( monitors_vector_table ); + + for ( index=2 ; index<=255 ; index++ ) + M68Kvec[ index ] = monitors_vector_table[ 32 ]; + + M68Kvec[ 2 ] = monitors_vector_table[ 2 ]; /* bus error vector */ + M68Kvec[ 4 ] = monitors_vector_table[ 4 ]; /* breakpoints vector */ + M68Kvec[ 9 ] = monitors_vector_table[ 9 ]; /* trace vector */ + M68Kvec[ 47 ] = monitors_vector_table[ 47 ]; /* system call vector */ + + m68k_set_vbr( &M68Kvec ); + + /* + * You may wish to make the VME arbitration round-robin here, currently + * we leave it as it is. + */ + + /* set the Interrupt Base Vectors */ + + lcsr->vector_base = (VBR0 << 28) | (VBR1 << 24); + + page_table_init(); +} diff --git a/bsps/m68k/mvme162/start/linkcmds b/bsps/m68k/mvme162/start/linkcmds new file mode 100644 index 0000000000..fd77dcf147 --- /dev/null +++ b/bsps/m68k/mvme162/start/linkcmds @@ -0,0 +1,32 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Motorola MVME162 boards. + */ + +/* + * COPYRIGHT (c) 1989-2007,2016. + * 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. + * + * MVME147 port for TNI - Telecom Bretagne + * by Dominique LE CAMPION (Dominique.LECAMPION@enst-bretagne.fr) + * May 1996 + */ + +RamSize = DEFINED(RamSize) ? RamSize : 1M; + +MEMORY +{ + bootrom_reserved : ORIGIN = 0x00000000, LENGTH = 0x20000 + ram : ORIGIN = 0x00020000, LENGTH = RamSize - 0x20000 +} + +REGION_ALIAS ("REGION_TEXT", ram); +REGION_ALIAS ("REGION_TEXT_LOAD", ram); +REGION_ALIAS ("REGION_DATA", ram); +REGION_ALIAS ("REGION_DATA_LOAD", ram); + +INCLUDE linkcmds.base diff --git a/bsps/m68k/mvme162/start/page_table.c b/bsps/m68k/mvme162/start/page_table.c new file mode 100644 index 0000000000..3dbd05a56f --- /dev/null +++ b/bsps/m68k/mvme162/start/page_table.c @@ -0,0 +1,196 @@ +/* + * This file was submitted by Eric Vaitl <vaitl@viasat.com>. + * The manipulation of the page table has a very positive impact on + * the performance of the MVME162. + * + * The following history is included verbatim from the submitter. + * + * Revision 1.8 1995/11/18 00:07:25 vaitl + * Modified asm-statements to get rid of the register hard-codes. + * + * Revision 1.7 1995/10/27 21:00:32 vaitl + * Modified page table routines so application code can map + * VME space. + * + * Revision 1.6 1995/10/26 17:40:01 vaitl + * Two cache changes after reading the mvme162 users manual. + * + * 1) The users manual says that the MPU can act as a source for the + * VME2 chip, so I made the VME accessable memory copy-back instead + * of write through. I have't changed the comments yet. If this + * causes problems, I'll change it back. + * + * 2) The 162 book also says that IO space should be serialized as well as + * non-cacheable. I flipped the appropriate dttr0 and ittr0 registers. I + * don't think this is really necessary because we don't recover from any + * exceptions. If it slows down IO addresses too much, I'll change it back + * and see what happens. + * + * Revision 1.5 1995/10/25 19:32:38 vaitl + * Got it. Three problems: + * 1) Must cpusha instead of cinva. + * 2) On page descriptors the PDT field of 1 or 3 is resident. On pointer + * descriptors resident is 2 or 3. I was using 2 for everything. + * Changed it to 3 for everything. + * 3) Forgot to do a pflusha. + * + * Revision 1.4 1995/10/25 17:47:11 vaitl + * Still working on it. + * + * Revision 1.3 1995/10/25 17:16:05 vaitl + * Working on page table. Caching partially set up, but can't currently + * set tc register. + * + */ + +#include <string.h> +#include <page_table.h> + +/* All page table must fit between BASE_TABLE_ADDR and + MAX_TABLE_ADDR. */ + +#define BASE_TABLE_ADDR 0x10000 +#define MAX_TABLE_ADDR 0x20000 +#define ROOT_TABLE_SIZE 512 +#define POINTER_TABLE_SIZE 512 +#define PAGE_TABLE_SIZE 256 + +static unsigned long *root_table; +static unsigned long *next_avail; + +/* Returns a zeroed out table. */ +static unsigned long *table_alloc(int size){ + unsigned long *addr=next_avail; + if(((unsigned long)next_avail + size) > MAX_TABLE_ADDR){ + return 0; + } + memset((void *)addr,0, size); + next_avail =(unsigned long *)((unsigned long)next_avail + size); + return addr; +} + +/* + void page_table_init(); + + This should transparently map the first 4 Meg of ram. Caching is + turned off from 0x00000000 to 0x00020000 (this region is used by + 162Bug and contains the page tables). From 0x00020000 to 0x00400000 + we are using copy back caching. DTTR0 and ITTR0 are set up to + directly translate from 0x80000000-0xffffffff with caching turned + off and serialized. Addresses between 0x400000 and 0x80000000 are + illegal. +*/ +void page_table_init(){ + + /* put everything in a known state */ + page_table_teardown(); + + root_table=table_alloc(ROOT_TABLE_SIZE); + + /* First set up TTR. + base address = 0x80000000 + address mask = 0x7f + Ignore FC2 for match. + Noncachable. + Not write protected.*/ + __asm__ volatile ("movec %0,%%dtt0\n\ + movec %0,%%itt0" + :: "d" (0x807fc040)); + + /* Point urp and srp at root page table. */ + __asm__ volatile ("movec %0,%%urp\n\ + movec %0,%%srp" + :: "d" (BASE_TABLE_ADDR)); + + page_table_map((void *)0,0x20000, CACHE_NONE); + page_table_map((void *)0x20000,0x400000-0x20000,CACHE_COPYBACK); + + /* Turn on paging with a 4 k page size.*/ + __asm__ volatile ("movec %0,%%tc" + :: "d" (0x8000)); + + /* Turn on the cache. */ + __asm__ volatile ("movec %0,%%cacr" + :: "d" (0x80008000)); +} + +void page_table_teardown(){ + next_avail=(unsigned long *)BASE_TABLE_ADDR; + /* Turn off paging. Turn off the cache. Flush the cache. Tear down + the transparent translations. */ + __asm__ volatile ("movec %0,%%tc\n\ + movec %0,%%cacr\n\ + cpusha %%bc\n\ + movec %0,%%dtt0\n\ + movec %0,%%itt0\n\ + movec %0,%%dtt1\n\ + movec %0,%%itt1" + :: "d" (0) ); +} + +/* Identity maps addr to addr+size with caching cache_type. */ +int page_table_map(void *addr, unsigned long size, int cache_type){ + unsigned long *pointer_table; + unsigned long *page_table; + unsigned long root_index, pointer_index, page_index; + /* addr must be a multiple of 4k */ + if((unsigned long)addr & 0xfff){ + return PTM_BAD_ADDR; + } + /* size must also be a multiple of 4k */ + if(size & 0xfff){ + return PTM_BAD_SIZE; + } + /* check for valid cache type */ + if( (cache_type>CACHE_NONE) || (cache_type<CACHE_WRITE_THROUGH)){ + return PTM_BAD_CACHE; + } + + while(size){ + root_index=(unsigned long)addr; + root_index >>= 25; + root_index &= 0x7f; + + if(root_table[root_index]){ + pointer_table = + (unsigned long *) (root_table[root_index] & 0xfffffe00); + }else{ + if(!(pointer_table=table_alloc(POINTER_TABLE_SIZE))){ + return PTM_NO_TABLE_SPACE; + } + root_table[root_index]=((unsigned long)pointer_table) + 0x03; + } + + pointer_index=(unsigned long)addr; + pointer_index >>=18; + pointer_index &= 0x7f; + + if(pointer_table[pointer_index]){ + page_table = + (unsigned long *) (pointer_table[pointer_index] & + 0xffffff00); + }else{ + if(!(page_table=table_alloc(PAGE_TABLE_SIZE))){ + return PTM_NO_TABLE_SPACE; + } + pointer_table[pointer_index]= + ((unsigned long)page_table) + 0x03; + } + + page_index=(unsigned long)addr; + page_index >>=12; + page_index &= 0x3f; + + page_table[page_index] = + ((unsigned long) addr & 0xfffff000) + 0x03 + (cache_type << 5); + + size -= 4096; + addr = (void *) ((unsigned long)addr + 4096); + } + + /* Flush the ATC. Push and invalidate the cache. */ + __asm__ volatile ("pflusha\n\ + cpusha %bc"); + + return PTM_SUCCESS; +} diff --git a/bsps/m68k/mvme167/start/bsp_specs b/bsps/m68k/mvme167/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/m68k/mvme167/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/m68k/mvme167/start/bspclean.c b/bsps/m68k/mvme167/start/bspclean.c new file mode 100644 index 0000000000..2dd980fdb4 --- /dev/null +++ b/bsps/m68k/mvme167/start/bspclean.c @@ -0,0 +1,70 @@ +/** + * @file + * + * These routines return control to 167Bug after a normal exit from the + * application. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * 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. + * + * Modifications of respective RTEMS files: + * Copyright (c) 1998, National Research Council of Canada + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <page_table.h> + +extern void start( void ); +extern void page_table_teardown( void ); + +/** + * @brief bsp_return_to_monitor_trap + * + * Switch the VBR back to ROM and make a .RETURN syscall to return control to + * 167 Bug. If 167Bug ever returns, restart the application. + */ +static void bsp_return_to_monitor_trap( void ) +{ + register volatile void *start_addr; + + page_table_teardown(); + + lcsr->intr_ena = 0; /* disable interrupts */ + m68k_set_vbr(0xFFE00000); /* restore 167Bug vectors */ + __asm__ volatile( "trap #15\n\t" /* trap to 167Bug */ + ".short 0x63" ); /* return to 167Bug (.RETURN) */ + + /* restart program */ + start_addr = start; + __asm__ volatile( "jmp %0@" : "=a" (start_addr) : "0" (start_addr) ); +} + +/* + * This code was copied from other MC680x0 MVME BSPs. + * Our guess is that someone was concerned about the CPU no longer being in + * supervisor mode when they got here. This function forces the CPU back to + * supervisor mode so the VBR may be changed. It places the address of the + * function that makes a 167Bug .RETURN syscall in the trap 13 entry in the + * exception vector, and then issues a trap 13 call. It is also possible that + * the code was copied from some other OS that does run tasks in user mode. + * In any case, it appears to be a bit of paranoia, and could lead to + * problems if 167Bug is invoked before we get to switch the VBR back to + * 167Bug because trap 13 is documented as being reserved for the internal + * use of the debugger. + */ +void bsp_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code error +) +{ + M68Kvec[ 45 ] = bsp_return_to_monitor_trap; + __asm__ volatile( "trap #13" ); +} diff --git a/bsps/m68k/mvme167/start/bspstart.c b/bsps/m68k/mvme167/start/bspstart.c new file mode 100644 index 0000000000..7ff6d2b118 --- /dev/null +++ b/bsps/m68k/mvme167/start/bspstart.c @@ -0,0 +1,80 @@ +/** + * @file + * + * Board-specific initialization code. Called from the generic boot_card() + * function defined in rtems/c/src/lib/libbsp/shared/main.c. That function + * does some of the board independent initialization. It is called from the + * generic MC680x0 entry point _start() defined in + * rtems/c/src/lib/start/m68k/start.s + * + * _start() has set up a stack, has zeroed the .bss section, has turned off + * interrupts, and placed the processor in the supervisor mode. boot_card() + * has left the processor in that state when bsp_start() was called. + * + * RUNS WITH ADDRESS TRANSLATION AND CACHING TURNED OFF! + * ASSUMES THAT THE VIRTUAL ADDRESSES WILL BE IDENTICAL TO THE PHYSICAL + * ADDRESSES. Software-controlled address translation would be required + * otherwise. + * + * ASSUMES THAT 167BUG IS PRESENT TO CATCH ANY EXCEPTIONS DURING + * INITIALIZATION. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * 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. + * + * Modifications of respective RTEMS files: + * Copyright (c) 1998, National Research Council of Canada + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <page_table.h> + +void M68KFPSPInstallExceptionHandlers (void); + +void bsp_start( void ) +{ + void **rom_monitor_vector_table; + int index; + + /* + * 167Bug Vectors are at 0xFFE00000 + */ + rom_monitor_vector_table = (void **)0xFFE00000; + m68k_set_vbr( rom_monitor_vector_table ); + + /* + * Copy 167Bug Bus Error handler into our exception vector. All 167Bug + * exception vectors are the same and point to the generalized exception + * handler. The bus error handler is the one that Motorola says to copy + * (p. 2-13, Debugging Package for Motorola 68K CISC CPUs User's Manual + * 68KBUG/D1A3, October 1993). + */ + for ( index=2 ; index<=255 ; index++ ) + M68Kvec[ index ] = rom_monitor_vector_table[ 2 ]; + + /* Any exceptions during initialization should be trapped by 167Bug */ + m68k_set_vbr( &M68Kvec ); + + /* Install the 68040 FPSP here */ + M68KFPSPInstallExceptionHandlers(); + + /* + * You may wish to make the VME arbitration round-robin here, currently + * we leave it as it is. + */ + + /* Set the Interrupt Base Vectors */ + lcsr->vector_base = (VBR0 << 28) | (VBR1 << 24); + + /* + * Initialize address translation + */ + page_table_init(); +} diff --git a/bsps/m68k/mvme167/start/linkcmds b/bsps/m68k/mvme167/start/linkcmds new file mode 100644 index 0000000000..dc50449b29 --- /dev/null +++ b/bsps/m68k/mvme167/start/linkcmds @@ -0,0 +1,35 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Motorola MVME167 board. + * + * Copyright (c) 1999, National Research Council of Canada. + * Some of this material was copied from binutils-2.9.4 linker scripts, + * and is therefore likely to be copyrighted by the Free Software + * Foundation, even though explicit copyright notices did not appear in + * those files. + * + * 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. + */ + +RamBase = DEFINED(RamBase) ? RamBase : 0x00800000; +RamSize = DEFINED(RamSize) ? RamSize : 4M; + +MEMORY +{ + /* The location of RAM is the address space is configurable. + This is where we put one board. The base address should be + passed as a parameter when building multiprocessor images + where each board resides at a different address. */ + ram : org = RamBase, l = RamSize + rom : org = 0xFF800000, l = 4M + sram : org = 0xFFE00000, l = 128K +} + +REGION_ALIAS ("REGION_TEXT", ram); +REGION_ALIAS ("REGION_TEXT_LOAD", ram); +REGION_ALIAS ("REGION_DATA", ram); +REGION_ALIAS ("REGION_DATA_LOAD", ram); + +INCLUDE linkcmds.base diff --git a/bsps/m68k/mvme167/start/page_table.c b/bsps/m68k/mvme167/start/page_table.c new file mode 100644 index 0000000000..da50e511b0 --- /dev/null +++ b/bsps/m68k/mvme167/start/page_table.c @@ -0,0 +1,149 @@ +/* page_table.c + * + * The code submitted by Eric Vaitl <vaitl@viasat.com> for the MVME162 appears + * to be for a uniprocessor implementation. The function that sets up the + * page tables, page_table_init(), is not data driven. For all processors, it + * sets up page tables to map virtual addresses from 0x20000 to 0x3FFFFF to + * physical addresses 0x20000 to 0x3FFFFF. This presumably maps a subset of + * a local 4 MB space, which is probably the amount of RAM on Eric Vailt's + * MVME162. + * + * It is possible to set up the various bus bridges in the MVME167s to create + * a flat physical address space across multiple boards, i.e., it is possible + * for each MVME167 in a multiprocessor system to access a given memory + * location using the same physical address, whether that location is in local + * or VME space. Addres translation can be set up so that each virtual address + * maps to its corresponding physical address, e.g. virtual address 0x12345678 + * is mapped to physical address 0x12345678. With this mapping, the MMU is + * only used to control the caching modes for the various regions of memory. + * Mapping the virtual addresses to their corresponding physical address makes + * it unnecessary to map addresses under software control during the + * initialization of RTEMS, before address translation is turned on. + * + * With the above approach, address translation may be set up either with the + * transparent address translation registers, or with page tables. If page + * tables are used, a more efficient use of page table space can be achieved + * by sharing the page tables between processors. The entire page table tree + * can be shared, or each processor can hold a private copy of the top nodes + * which point to leaf nodes stored on individual processors. + * + * In this port, only the transparent address translation registers are used. + * We map the entire virtual range from 0x0 to 0x7FFFFFFF to the identical + * physical range 0x0 to 0x7FFFFFFF. We rely on the hardware to signal bus + * errors if we address non-existent memory within this range. Our two + * MVME167s are configured to exist at physical addresses 0x00800000 to + * 0x00BFFFFF and 0x00C00000 to 0x00FFFFFF respectively. If jumper J1-4 is + * installed, memory and cache control can be done by providing parameters + * in NVRAM and jumpers J1-[5-7] are ignored. See the README for details. + * If J1-4 is removed, behaviour defaults to the following. We map the space + * from 0x0 to 0x7FFFFFFF as copyback, unless jumper J1-5 is removed, in which + * case we map as writethrough. If jumper J1-7 is removed, the data cache is + * NOT enabled. If jumper J1-6 is removed, the instruction cache is not enabled. + * + * Copyright (c) 1998, National Research Council of Canada + */ + +#include <bsp.h> +#include <page_table.h> /* Nothing in here for us */ + +/* + * page_table_init + * + * Map the virtual range 0x00000000--0x7FFFFFFF to the physical range + * 0x00000000--0x7FFFFFFF. Rely on the hardware to raise exceptions when + * addressing non-existent memory. Use only the transparent translation + * registers (for now). + * + * On all processors, the local virtual address range 0xFF000000--0xFFFFFFFF + * is mapped to the physical address range 0xFF000000--0xFFFFFFFF as + * caching disabled, serialized access. + * + * Output parameters: NONE + * + * Return values: NONE + */ +void page_table_init( void ) +{ + unsigned char j1; /* State of J1 jumpers */ + register unsigned long dtt0; /* Content of dtt0 */ + register unsigned long cacr; /* Content of cacr */ + + /* + * Logical base addr = 0x00 map starting at 0x00000000 + * Logical address mask = 0x7F map up to 0x7FFFFFFF + * E = 0b1 enable address translation + * S-Field = 0b1X ignore FC2 when matching + * U1, U0 = 0b00 user page attributes not used + * CM = 0b01 cachable, copyback + * W = 0b0 read/write access allowed + */ + dtt0 = 0x007FC020; + + cacr = 0x00000000; /* Data and instruction cache off */ + + /* Read the J1 header */ + j1 = (unsigned char)(lcsr->vector_base & 0xFF); + + if ( !(j1 & 0x10) ) { + /* Jumper J1-4 is on, configure from NVRAM */ + + if ( nvram->cache_mode & 0x01 ) + cacr |= 0x80000000; + + if ( nvram->cache_mode & 0x02 ) + cacr |= 0x00008000; + + if ( nvram->cache_mode ) + dtt0 = ((nvram->cache_mode & 0x0C) << 3) | (dtt0 & 0xFFFFFF9F); + } + else { + /* Configure according to other jumper settings */ + + if ( !(j1 & 0x80) ) + /* Jumper J1-7 if on, enable data caching */ + cacr |= 0x80000000; + + if ( !(j1 & 0x40) ) + /* Jumper J1-6 if on, enable instruction caching */ + cacr |= 0x00008000; + + if ( j1 & 0x20 ) + /* Jumper J1-5 is off, enable writethrough caching */ + dtt0 &= 0xFFFFFF9F; + } + + /* do it ! */ + __asm__ volatile("movec %0, %%tc\n\t" /* turn off paged address translation */ + "movec %0, %%cacr\n\t" /* disable both caches */ + "cinva %%bc\n\t" /* clear both caches */ + "movec %1,%%dtt0\n\t" /* block address translation on */ + "movec %1,%%itt0\n\t" + "movec %2,%%dtt1\n\t" + "movec %2,%%itt1\n\t" + "movec %3,%%cacr" /* data cache on */ + :: "d" (0), "d" (dtt0), "d" (0xFF00C040), "d" (cacr)); +} + +/* + * page_table_teardown + * + * Turn off paging. Turn off the cache. Flush the cache. Tear down + * the transparent translations. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + */ +void page_table_teardown( void ) +{ + __asm__ volatile ("movec %0,%%tc\n\t" + "movec %0,%%cacr\n\t" + "cpusha %%bc\n\t" + "movec %0,%%dtt0\n\t" + "movec %0,%%itt0\n\t" + "movec %0,%%dtt1\n\t" + "movec %0,%%itt1" + :: "d" (0) ); +} diff --git a/bsps/m68k/shared/start/linkcmds.base b/bsps/m68k/shared/start/linkcmds.base new file mode 100644 index 0000000000..56af70d1da --- /dev/null +++ b/bsps/m68k/shared/start/linkcmds.base @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2008-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. + */ + +OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k") + +OUTPUT_ARCH(m68k) + +ENTRY(start) +STARTUP(start.o) + +bsp_initstack_size = DEFINED (bsp_initstack_size) ? bsp_initstack_size : 2048; + +MEMORY { + UNEXPECTED_SECTIONS : ORIGIN = 0xffffffff, LENGTH = 0 +} + +SECTIONS { + .vector0 : ALIGN_WITH_INPUT { + bsp_vector0_begin = .; + KEEP (*(.vectors*)) + bsp_vector0_end = .; + } > REGION_TEXT AT > REGION_TEXT + bsp_vector0_size = bsp_vector0_end - bsp_vector0_begin; + + .text : ALIGN_WITH_INPUT { + *(.text.unlikely .text.*_unlikely) + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .init : ALIGN_WITH_INPUT { + KEEP (*(.init)) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .fini : ALIGN_WITH_INPUT { + KEEP (*(.fini)) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .rodata : ALIGN_WITH_INPUT { + *(.rodata .rodata.* .gnu.linkonce.r.*) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .rodata1 : ALIGN_WITH_INPUT { + *(.rodata1) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .eh_frame : ALIGN_WITH_INPUT { + KEEP (*(.eh_frame)) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .gcc_except_table : ALIGN_WITH_INPUT { + *(.gcc_except_table .gcc_except_table.*) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .tdata : ALIGN_WITH_INPUT { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > REGION_TEXT AT > REGION_TEXT_LOAD + .tbss : ALIGN_WITH_INPUT { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } > REGION_TEXT AT > REGION_TEXT_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_TEXT AT > REGION_TEXT_LOAD + .init_array : ALIGN_WITH_INPUT { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } > REGION_TEXT AT > REGION_TEXT_LOAD + .fini_array : ALIGN_WITH_INPUT { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } > REGION_TEXT AT > REGION_TEXT_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_TEXT AT > REGION_TEXT_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_TEXT AT > REGION_TEXT_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_TEXT AT > REGION_TEXT_LOAD + .jcr : ALIGN_WITH_INPUT { + KEEP (*(.jcr)) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .interp : ALIGN_WITH_INPUT { + *(.interp) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .note.gnu.build-id : ALIGN_WITH_INPUT { + *(.note.gnu.build-id) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .hash : ALIGN_WITH_INPUT { + *(.hash) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .gnu.hash : ALIGN_WITH_INPUT { + *(.gnu.hash) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .dynsym : ALIGN_WITH_INPUT { + *(.dynsym) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .dynstr : ALIGN_WITH_INPUT { + *(.dynstr) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .gnu.version : ALIGN_WITH_INPUT { + *(.gnu.version) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .gnu.version_d : ALIGN_WITH_INPUT { + *(.gnu.version_d) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .gnu.version_r : ALIGN_WITH_INPUT { + *(.gnu.version_r) + } > REGION_TEXT AT > REGION_TEXT_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_TEXT AT > REGION_TEXT_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_TEXT AT > REGION_TEXT_LOAD + .rel.plt : ALIGN_WITH_INPUT { + *(.rel.plt) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .rela.plt : ALIGN_WITH_INPUT { + *(.rela.plt) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .plt : ALIGN_WITH_INPUT { + *(.plt) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .iplt : ALIGN_WITH_INPUT { + *(.iplt) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .dynamic : ALIGN_WITH_INPUT { + *(.dynamic) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .got : ALIGN_WITH_INPUT { + *(.got.plt) *(.igot.plt) *(.got) *(.igot) + } > REGION_TEXT AT > REGION_TEXT_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.*))) + } > REGION_TEXT AT > REGION_TEXT_LOAD + + .vector1 : ALIGN_WITH_INPUT { + bsp_vector1_begin = .; + . = . + (ORIGIN (REGION_TEXT) == ORIGIN (REGION_DATA) ? 0 : bsp_vector0_size); + bsp_vector1_end = .; + } > REGION_DATA AT > REGION_DATA + bsp_vector1_size = bsp_vector1_end - bsp_vector1_begin; + + .initstack : ALIGN_WITH_INPUT { + bsp_initstack_begin = .; + . = . + bsp_initstack_size; + bsp_initstack_end = .; + } > REGION_DATA AT > REGION_DATA + + .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_DATA AT > REGION_DATA + bsp_section_bss_size = bsp_section_bss_end - bsp_section_bss_begin; + + .work : ALIGN_WITH_INPUT { + /* + * The work section will occupy the remaining REGION_DATA region and + * contains the RTEMS work space and heap. + */ + bsp_section_work_begin = .; + . += ORIGIN (REGION_DATA) + LENGTH (REGION_DATA) - ABSOLUTE (.); + bsp_section_work_end = .; + } > REGION_DATA AT > REGION_DATA + bsp_section_work_size = bsp_section_work_end - bsp_section_work_begin; + + /* FIXME */ + RamBase = ORIGIN (REGION_DATA); + RamSize = LENGTH (REGION_DATA); + 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) } + /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/m68k/uC5282/start/bsp_specs b/bsps/m68k/uC5282/start/bsp_specs new file mode 100644 index 0000000000..3a20757667 --- /dev/null +++ b/bsps/m68k/uC5282/start/bsp_specs @@ -0,0 +1,10 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s crtn.o%s} + diff --git a/bsps/m68k/uC5282/start/bspclean.c b/bsps/m68k/uC5282/start/bspclean.c new file mode 100644 index 0000000000..a344efd7bb --- /dev/null +++ b/bsps/m68k/uC5282/start/bspclean.c @@ -0,0 +1,24 @@ +/* + * This routine returns control from RTEMS to the monitor. + * + * Author: W. Eric Norum <norume@aps.anl.gov> + * + * COPYRIGHT (c) 2005. + * 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 bsp_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code error +) +{ + bsp_reset(); +} diff --git a/bsps/m68k/uC5282/start/bspreset.c b/bsps/m68k/uC5282/start/bspreset.c new file mode 100644 index 0000000000..b93fbb409f --- /dev/null +++ b/bsps/m68k/uC5282/start/bspreset.c @@ -0,0 +1,17 @@ +/* + * COPYRIGHT (c) 1989-2008. + * 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.h> +#include <bsp/bootcard.h> + +void bsp_reset(void) +{ + bsp_sysReset(0); +} diff --git a/bsps/m68k/uC5282/start/bspstart.c b/bsps/m68k/uC5282/start/bspstart.c new file mode 100644 index 0000000000..33ce737ceb --- /dev/null +++ b/bsps/m68k/uC5282/start/bspstart.c @@ -0,0 +1,673 @@ +/* + * This routine does the bulk of the system initialisation. + */ + +/* + * Author: W. Eric Norum <norume@aps.anl.gov> + * + * COPYRIGHT (c) 2005. + * 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> +#include <rtems/error.h> +#include <errno.h> +#include <stdio.h> +#include <inttypes.h> +#include <mcf5282/mcf5282.h> + +/* + * Location of 'VME' access + */ +#define VME_ONE_BASE 0x30000000 +#define VME_TWO_BASE 0x31000000 + +/* + * Linker Script Defined Variables + */ +extern char RamSize[]; +extern char RamBase[]; +extern char _CPUClockSpeed[]; +extern char _PLLRefClockSpeed[]; + +uint32_t BSP_sys_clk_speed = (uint32_t)_CPUClockSpeed; +uint32_t BSP_pll_ref_clock = (uint32_t)_PLLRefClockSpeed; + +/* + * CPU-space access + * The NOP after writing the CACR is there to address the following issue as + * described in "Device Errata MCF5282DE", Rev. 1.7, 09/2004: + * + * 6 Possible Cache Corruption after Setting CACR[CINV] + * 6.1 Description + * The cache on the MCF5282 was enhanced to function as a unified data and + * instruction cache, an instruction cache, or an operand cache. The cache + * function and organization is controlled by the cache control register (CACR). + * The CINV (Bit 24 = cache invalidate) bit in the CACR causes a cache clear. + * If the cache is configured as a unified cache and the CINV bit is set, the + * scope of the cache clear is controlled by two other bits in the CACR, + * INVI (BIT 21 = CINV instruction cache only) and INVD (BIT 20 = CINV data + * cache only). These bits allow the entire cache, just the instruction + * portion of the cache, or just the data portion of the cache to be cleared. + * If a write to the CACR is performed to clear the cache (CINV = BIT 24 set) + * and only a partial clear will be done (INVI = BIT 21 or INVD = BIT 20 set), + * then cache corruption may occur. + * + * 6.2 Workaround + * All loads of the CACR that perform a cache clear operation (CINV = BIT 24) + * should be followed immediately by a NOP instruction. This avoids the cache + * corruption problem. + * DATECODES AFFECTED: All + * + * + * Buffered writes must be disabled as described in "MCF5282 Chip Errata", + * MCF5282DE, Rev. 6, 5/2009: + * SECF124: Buffered Write May Be Executed Twice + * Errata type: Silicon + * Affected component: Cache + * Description: If buffered writes are enabled using the CACR or ACR + * registers, the imprecise write transaction generated + * by a buffered write may be executed twice. + * Workaround: Do not enable buffered writes in the CACR or ACR registers: + * CACR[8] = DBWE (default buffered write enable) must be 0 + * ACRn[5] = BUFW (buffered write enable) must be 0 + * Fix plan: Currently, there are no plans to fix this. + */ +#define m68k_set_cacr_nop(_cacr) \ + __asm__ volatile ("movec %0,%%cacr\n\tnop" : : "d" (_cacr)) +#define m68k_set_cacr(_cacr) \ + __asm__ volatile ("movec %0,%%cacr" : : "d" (_cacr)) +#define m68k_set_acr0(_acr0) \ + __asm__ volatile ("movec %0,%%acr0" : : "d" (_acr0)) +#define m68k_set_acr1(_acr1) \ + __asm__ volatile ("movec %0,%%acr1" : : "d" (_acr1)) + +uint32_t mcf5282_acr0_mode = 0; +uint32_t mcf5282_acr1_mode = 0; + +extern void bsp_fake_syscall(int); + +/* + * The Arcturus boot ROM prints exception information improperly + * so use this default exception handler instead. This one also + * prints a call backtrace + */ +static void handler(int pc) +{ + int level; + static volatile int reent; + + rtems_interrupt_disable(level); + if (reent++) bsp_sysReset(0); + { + int *p = &pc; + int info = p[-1]; + int pc = p[0]; + int format = (info >> 28) & 0xF; + int faultStatus = ((info >> 24) & 0xC) | ((info >> 16) & 0x3); + int vector = (info >> 18) & 0xFF; + int statusRegister = info & 0xFFFF; + int *fp; + + printk("\n\nPC:%x SR:%x VEC:%x FORMAT:%x STATUS:%x\n", pc, + statusRegister, + vector, + format, + faultStatus); + fp = &p[-2]; + for(;;) { + int *nfp = (int *)*fp; + if ((nfp <= fp) + || ((char *)nfp >= RamSize) + || ((char *)(nfp[1]) >= RamSize)) + break; + printk("FP:%p -> %p PC:%x\n", fp, nfp, nfp[1]); + fp = nfp; + } + } + rtems_task_suspend(0); + rtems_panic("done"); +} + +void bsp_start( void ) +{ + int i; + const char *clk_speed_str; + uint32_t clk_speed, mfd, rfd; + uint8_t byte; + + /* + * Make sure UART TX is running - necessary for + * early printk to work. The firmware monitor + * usually enables this anyways but qemu doesn't! + */ + MCF5282_UART_UCR(CONSOLE_PORT) = MCF5282_UART_UCR_TX_ENABLED; + + /* + * Set up default exception handler + */ + for (i = 2 ; i < 256 ; i++) + if (i != (32+2)) /* Catch all but bootrom system calls */ + *((void (**)(int))(i * 4)) = handler; + + /* + * Invalidate the cache and disable it + */ + m68k_set_acr0(mcf5282_acr0_mode); + m68k_set_acr1(mcf5282_acr1_mode); + m68k_set_cacr_nop(MCF5XXX_CACR_CINV); + + /* + * Cache SDRAM + * Enable buffered writes + * As Device Errata SECF124 notes this may cause double writes, + * but that's not really a big problem and benchmarking tests have + * shown that buffered writes do gain some performance. + */ + mcf5282_acr0_mode = MCF5XXX_ACR_AB((uint32_t)RamBase) | + MCF5XXX_ACR_AM((uint32_t)RamSize-1) | + MCF5XXX_ACR_EN | + MCF5XXX_ACR_SM_IGNORE | + MCF5XXX_ACR_BWE; + m68k_set_acr0(mcf5282_acr0_mode); + + /* + * Qemu has no trap handler; install our fake syscall + * implementation if there is no existing handler. + */ + if ( 0 == *((void (**)(int))((32+2) * 4)) ) + *((void (**)(int))((32+2) * 4)) = bsp_fake_syscall; + + /* + * Read/write copy of cache registers + * Split instruction/data or instruction-only + * Allow CPUSHL to invalidate a cache line + * Disable buffered writes + * No burst transfers on non-cacheable accesses + * Default cache mode is *disabled* (cache only ACRx areas) + */ + mcf5xxx_initialize_cacr( + MCF5XXX_CACR_CENB | + #ifndef RTEMS_MCF5282_BSP_ENABLE_DATA_CACHE + MCF5XXX_CACR_DISD | + #endif + MCF5XXX_CACR_DCM + ); + + /* + * Set up CS* space (fake 'VME') + * Two A24/D16 spaces, supervisor data acces + */ + MCF5282_CS1_CSAR = MCF5282_CS_CSAR_BA(VME_ONE_BASE); + MCF5282_CS1_CSMR = MCF5282_CS_CSMR_BAM_16M | + MCF5282_CS_CSMR_CI | + MCF5282_CS_CSMR_SC | + MCF5282_CS_CSMR_UC | + MCF5282_CS_CSMR_UD | + MCF5282_CS_CSMR_V; + MCF5282_CS1_CSCR = MCF5282_CS_CSCR_PS_16; + MCF5282_CS2_CSAR = MCF5282_CS_CSAR_BA(VME_TWO_BASE); + MCF5282_CS2_CSMR = MCF5282_CS_CSMR_BAM_16M | + MCF5282_CS_CSMR_CI | + MCF5282_CS_CSMR_SC | + MCF5282_CS_CSMR_UC | + MCF5282_CS_CSMR_UD | + MCF5282_CS_CSMR_V; + MCF5282_CS2_CSCR = MCF5282_CS_CSCR_PS_16; + MCF5282_GPIO_PJPAR |= 0x06; + + /* + * Hopefully, the UART clock is still correctly set up + * so they can see the printk() output... + */ + clk_speed = 0; + printk("Trying to figure out the system clock\n"); + printk("Checking ENV variable SYS_CLOCK_SPEED:\n"); + if ( (clk_speed_str = bsp_getbenv("SYS_CLOCK_SPEED")) ) { + printk("Found: %s\n", clk_speed_str); + for ( clk_speed = 0, i=0; + clk_speed_str[i] >= '0' && clk_speed_str[i] <= '9'; + i++ ) { + clk_speed = 10*clk_speed + clk_speed_str[i] - '0'; + } + if ( 0 != clk_speed_str[i] ) { + printk("Not a decimal number; I'm not using this setting\n"); + clk_speed = 0; + } + } else { + printk("Not set.\n"); + } + + if ( 0 == clk_speed ) + clk_speed = BSP_sys_clk_speed; + + if ( 0 == clk_speed ) { + printk("Using some heuristics to determine clock speed...\n"); + byte = MCF5282_CLOCK_SYNSR; + if ( 0 == byte ) { + printk("SYNSR == 0; assuming QEMU at 66MHz\n"); + BSP_pll_ref_clock = 8250000; + mfd = ( 0 << 8 ) | ( 2 << 12 ); + } else { + if ( 0xf8 != byte ) { + printk("FATAL ERROR: Unexpected SYNSR contents (0x%02x), can't proceed\n", byte); + bsp_sysReset(0); + } + mfd = MCF5282_CLOCK_SYNCR; + } + printk("Assuming %" PRIu32 "Hz PLL ref. clock\n", BSP_pll_ref_clock); + rfd = (mfd >> 8) & 7; + mfd = (mfd >> 12) & 7; + /* Check against 'known' cases */ + if ( 0 != rfd || (2 != mfd && 3 != mfd) ) { + printk("WARNING: Pll divisor/multiplier has unknown value; \n"); + printk(" either your board is not 64MHz or 80Mhz or\n"); + printk(" it uses a PLL reference other than 8MHz.\n"); + printk(" I'll proceed anyways but you might have to\n"); + printk(" reset the board and set uCbootloader ENV\n"); + printk(" variable \"SYS_CLOCK_SPEED\".\n"); + } + mfd = 2 * (mfd + 2); + /* sysclk = pll_ref * 2 * (MFD + 2) / 2^(rfd) */ + printk( + "PLL multiplier: %" PRIu32", output divisor: %" PRIu32 "\n", + mfd, + rfd + ); + clk_speed = (BSP_pll_ref_clock * mfd) >> rfd; + } + + if ( 0 == clk_speed ) { + printk("FATAL ERROR: Unable to determine system clock speed\n"); + bsp_sysReset(0); + } else { + BSP_sys_clk_speed = clk_speed; + printk( + "System clock speed: %" PRIu32 "Hz\n", bsp_get_CPU_clock_speed()); + } +} + +uint32_t bsp_get_CPU_clock_speed(void) +{ + return( BSP_sys_clk_speed ); +} + +/* + * Interrupt controller allocation + */ +rtems_status_code +bsp_allocate_interrupt(int level, int priority) +{ + static char used[7]; + rtems_interrupt_level l; + rtems_status_code ret = RTEMS_RESOURCE_IN_USE; + + if ((level < 1) || (level > 7) || (priority < 0) || (priority > 7)) + return RTEMS_INVALID_NUMBER; + rtems_interrupt_disable(l); + if ((used[level-1] & (1 << priority)) == 0) { + used[level-1] |= (1 << priority); + ret = RTEMS_SUCCESSFUL; + } + rtems_interrupt_enable(l); + return ret; +} + +/* + * Arcturus bootloader system calls + */ +#define syscall_return(type, ret) \ +do { \ + if ((unsigned long)(ret) >= (unsigned long)(-64)) { \ + errno = -(ret); \ + ret = -1; \ + } \ + return (type)(ret); \ +} while (0) + +#define syscall_1(type,name,d1type,d1) \ +type bsp_##name(d1type d1); \ +type bsp_##name(d1type d1) \ +{ \ + long ret; \ + register long __d1 __asm__ ("%d1") = (long)d1; \ + __asm__ __volatile__ ("move.l %1,%%d0\n\t" \ + "trap #2\n\t" \ + "move.l %%d0,%0" \ + : "=g" (ret) \ + : "i" (SysCode_##name), "d" (__d1) \ + : "d0" ); \ + syscall_return(type,ret); \ +} + +#define syscall_2(type,name,d1type,d1,d2type,d2) \ +type bsp_##name(d1type d1, d2type d2); \ +type bsp_##name(d1type d1, d2type d2) \ +{ \ + long ret; \ + register long __d1 __asm__ ("%d1") = (long)d1; \ + register long __d2 __asm__ ("%d2") = (long)d2; \ + __asm__ __volatile__ ("move.l %1,%%d0\n\t" \ + "trap #2\n\t" \ + "move.l %%d0,%0" \ + : "=g" (ret) \ + : "i" (SysCode_##name), "d" (__d1),\ + "d" (__d2) \ + : "d0" ); \ + syscall_return(type,ret); \ +} + +#define syscall_3(type,name,d1type,d1,d2type,d2,d3type,d3) \ +type bsp_##name(d1type d1, d2type d2, d3type d3); \ +type bsp_##name(d1type d1, d2type d2, d3type d3) \ +{ \ + long ret; \ + register long __d1 __asm__ ("%d1") = (long)d1; \ + register long __d2 __asm__ ("%d2") = (long)d2; \ + register long __d3 __asm__ ("%d3") = (long)d3; \ + __asm__ __volatile__ ("move.l %1,%%d0\n\t" \ + "trap #2\n\t" \ + "move.l %%d0,%0" \ + : "=g" (ret) \ + : "i" (SysCode_##name), "d" (__d1),\ + "d" (__d2),\ + "d" (__d3) \ + : "d0" ); \ + syscall_return(type,ret); \ +} + +#define SysCode_sysReset 0 /* system reset */ +#define SysCode_program 5 /* program flash memory */ +#define SysCode_gethwaddr 12 /* get hardware address */ +#define SysCode_getbenv 14 /* get bootloader environment variable */ +#define SysCode_setbenv 15 /* set bootloader environment variable */ +#define SysCode_flash_erase_range 19 /* erase a section of flash */ +#define SysCode_flash_write_range 20 /* write a section of flash */ +syscall_1(int, sysReset, int, flags) +syscall_1(unsigned const char *, gethwaddr, int, a) +syscall_1(const char *, getbenv, const char *, a) +syscall_1(int, setbenv, const char *, a) +syscall_2(int, program, bsp_mnode_t *, chain, int, flags) +syscall_3(int, flash_erase_range, volatile unsigned short *, flashptr, int, start, int, end); +syscall_3(int, flash_write_range, volatile unsigned short *, flashptr, bsp_mnode_t *, chain, int, offset); + +/* Provide a dummy-implementation of these syscalls + * for qemu (which lacks the firmware). + */ + +#define __STR(x) #x +#define __STRSTR(x) __STR(x) +#define ERRVAL __STRSTR(EACCES) + +/* reset-control register */ +#define RCR "__IPSBAR + 0x110000" + +__asm__ ( + "bsp_fake_syscall: \n" + " cmpl #0, %d0 \n" /* sysreset */ + " bne 1f \n" + " moveb #0x80, %d0 \n" + " moveb %d0, "RCR" \n" /* reset-controller */ + /* should never get here - but we'd return -EACCESS if we do */ + "1: \n" + " cmpl #12, %d0 \n" /* gethwaddr */ + " beq 2f \n" + " cmpl #14, %d0 \n" /* getbenv */ + " beq 2f \n" + " movel #-"ERRVAL", %d0 \n" /* return -EACCESS */ + " rte \n" + "2: \n" + " movel #0, %d0 \n" /* return NULL */ + " rte \n" +); + + +/* + * 'Extended BSP' routines + * Should move to cpukit/score/cpu/m68k/cpu.c someday. + */ + +rtems_status_code bspExtInit(void) { return RTEMS_SUCCESSFUL; } +int BSP_enableVME_int_lvl(unsigned int level) { return 0; } +int BSP_disableVME_int_lvl(unsigned int level) { return 0; } + +/* + * 'VME' interrupt support + * Interrupt vectors 192-255 are set aside for use by external logic which + * drives IRQ1*. The actual interrupt source is read from the external + * logic at FPGA_IRQ_INFO. The most-significant bit of the least-significant + * byte read from this location is set as long as the external logic has + * interrupts to be serviced. The least-significant six bits indicate the + * interrupt source within the external logic and are used to select the + * specified interupt handler. + */ +#define NVECTOR 256 +#define FPGA_VECTOR (64+1) /* IRQ1* pin connected to external FPGA */ +#define FPGA_IRQ_INFO *((vuint16 *)(0x31000000 + 0xfffffe)) + +static struct handlerTab { + BSP_VME_ISR_t func; + void *arg; +} handlerTab[NVECTOR]; + +BSP_VME_ISR_t +BSP_getVME_isr(unsigned long vector, void **pusrArg) +{ + if (vector >= NVECTOR) + return (BSP_VME_ISR_t)NULL; + if (pusrArg) + *pusrArg = handlerTab[vector].arg; + return handlerTab[vector].func; +} + +static rtems_isr +fpga_trampoline (rtems_vector_number v) +{ + /* + * Handle FPGA interrupts until all have been consumed + */ + int loopcount = 0; + while (((v = FPGA_IRQ_INFO) & 0x80) != 0) { + v = 192 + (v & 0x3f); + if (++loopcount >= 50) { + rtems_interrupt_level level; + rtems_interrupt_disable(level); + printk( + "\nTOO MANY FPGA INTERRUPTS (LAST WAS 0x%lx) -- " + "DISABLING ALL FPGA INTERRUPTS.\n", + v & 0x3f + ); + MCF5282_INTC0_IMRL |= MCF5282_INTC_IMRL_INT1; + rtems_interrupt_enable(level); + return; + } + if (handlerTab[v].func) { + (*handlerTab[v].func)(handlerTab[v].arg, (unsigned long)v); + } + else { + rtems_interrupt_level level; + rtems_vector_number nv; + rtems_interrupt_disable(level); + printk("\nSPURIOUS FPGA INTERRUPT (0x%lx).\n", v & 0x3f); + if ((((nv = FPGA_IRQ_INFO) & 0x80) != 0) + && ((nv & 0x3f) == (v & 0x3f))) { + printk("DISABLING ALL FPGA INTERRUPTS.\n"); + MCF5282_INTC0_IMRL |= MCF5282_INTC_IMRL_INT1; + } + rtems_interrupt_enable(level); + return; + } + } +} + +static rtems_isr +trampoline (rtems_vector_number v) +{ + if (handlerTab[v].func) + (*handlerTab[v].func)(handlerTab[v].arg, (unsigned long)v); +} + +static void +enable_irq(unsigned source) +{ +rtems_interrupt_level level; + rtems_interrupt_disable(level); + if (source >= 32) + MCF5282_INTC0_IMRH &= ~(1 << (source - 32)); + else + MCF5282_INTC0_IMRL &= ~((1 << source) | + MCF5282_INTC_IMRL_MASKALL); + rtems_interrupt_enable(level); +} + +static int +init_intc0_bit(unsigned long vector) +{ +rtems_interrupt_level level; + + /* + * Find an unused level/priority if this is an on-chip (INTC0) + * source and this is the first time the source is being used. + * Interrupt sources 1 through 7 are fixed level/priority + */ + + if ((vector >= 65) && (vector <= 127)) { + int l, p; + int source = vector - 64; + static unsigned char installed[8]; + + rtems_interrupt_disable(level); + if (installed[source/8] & (1 << (source % 8))) { + rtems_interrupt_enable(level); + return 0; + } + installed[source/8] |= (1 << (source % 8)); + rtems_interrupt_enable(level); + for (l = 1 ; l < 7 ; l++) { + for (p = 0 ; p < 8 ; p++) { + if ((source < 8) + || (bsp_allocate_interrupt(l,p) == RTEMS_SUCCESSFUL)) { + if (source < 8) + MCF5282_EPORT_EPIER |= 1 << source; + else + *(&MCF5282_INTC0_ICR1 + (source - 1)) = + MCF5282_INTC_ICR_IL(l) | + MCF5282_INTC_ICR_IP(p); + enable_irq(source); + return 0; + } + } + } + return -1; + } + return 0; +} + +int +BSP_installVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *usrArg) +{ + rtems_isr_entry old_handler; + rtems_interrupt_level level; + + /* + * Register the handler information + */ + if (vector >= NVECTOR) + return -1; + handlerTab[vector].func = handler; + handlerTab[vector].arg = usrArg; + + /* + * If this is an external FPGA ('VME') vector set up the real IRQ. + */ + if ((vector >= 192) && (vector <= 255)) { + int i; + static volatile int setupDone; + rtems_interrupt_disable(level); + if (setupDone) { + rtems_interrupt_enable(level); + return 0; + } + setupDone = 1; + rtems_interrupt_catch(fpga_trampoline, FPGA_VECTOR, &old_handler); + i = init_intc0_bit(FPGA_VECTOR); + rtems_interrupt_enable(level); + return i; + } + + /* + * Make the connection between the interrupt and the local handler + */ + rtems_interrupt_catch(trampoline, vector, &old_handler); + + return init_intc0_bit(vector); +} + +int +BSP_removeVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *usrArg) +{ + if (vector >= NVECTOR) + return -1; + if ((handlerTab[vector].func != handler) + || (handlerTab[vector].arg != usrArg)) + return -1; + handlerTab[vector].func = (BSP_VME_ISR_t)NULL; + return 0; +} + +int +BSP_vme2local_adrs(unsigned am, unsigned long vmeaddr, unsigned long *plocaladdr) +{ + unsigned long offset; + + switch (am) { + default: return -1; + case VME_AM_SUP_SHORT_IO: offset = 0x31FF0000; break; /* A16/D16 */ + case VME_AM_STD_SUP_DATA: offset = 0x30000000; break; /* A24/D16 */ + case VME_AM_EXT_SUP_DATA: offset = 0x31000000; break; /* A32/D32 */ + } + *plocaladdr = vmeaddr + offset; + return 0; +} + +void +bsp_reset_cause(char *buf, size_t capacity) +{ + int bit, rsr; + size_t i; + const char *cp; + + if (buf == NULL) + return; + if (capacity) + buf[0] = '\0'; + rsr = MCF5282_RESET_RSR; + for (i = 0, bit = 0x80 ; bit != 0 ; bit >>= 1) { + if (rsr & bit) { + switch (bit) { + case MCF5282_RESET_RSR_LVD: cp = "Low voltage"; break; + case MCF5282_RESET_RSR_SOFT: cp = "Software reset"; break; + case MCF5282_RESET_RSR_WDR: cp = "Watchdog reset"; break; + case MCF5282_RESET_RSR_POR: cp = "Power-on reset"; break; + case MCF5282_RESET_RSR_EXT: cp = "External reset"; break; + case MCF5282_RESET_RSR_LOC: cp = "Loss of clock"; break; + case MCF5282_RESET_RSR_LOL: cp = "Loss of lock"; break; + default: cp = "??"; break; + } + i += snprintf(buf+i, capacity-i, cp); + if (i >= capacity) + break; + rsr &= ~bit; + if (rsr == 0) + break; + i += snprintf(buf+i, capacity-i, ", "); + if (i >= capacity) + break; + } + } +} diff --git a/bsps/m68k/uC5282/start/init5282.c b/bsps/m68k/uC5282/start/init5282.c new file mode 100644 index 0000000000..201ee58c8e --- /dev/null +++ b/bsps/m68k/uC5282/start/init5282.c @@ -0,0 +1,44 @@ +/* + * This is where the real hardware setup is done. A minimal stack + * has been provided by the start.S code. No normal C or RTEMS + * functions can be called from here. + * + * This routine is pretty simple for the uC5282 because all the hard + * work has been done by the bootstrap dBUG code. + */ + +/* + * Author: W. Eric Norum <norume@aps.anl.gov> + * + * COPYRIGHT (c) 2005. + * 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.h> + +#define m68k_set_cacr(_cacr) __asm__ volatile ("movec %0,%%cacr" : : "d" (_cacr)) +#define m68k_set_acr0(_acr0) __asm__ volatile ("movec %0,%%acr0" : : "d" (_acr0)) +#define m68k_set_acr1(_acr1) __asm__ volatile ("movec %0,%%acr1" : : "d" (_acr1)) + +/* + * This method is implemented in start.S. + */ +extern void CopyDataClearBSSAndStart (void); + +/* + * This method cannot be static because it is called from start.S. + */ +void Init5282 (void); + +void Init5282 (void) +{ + /* + * Copy data, clear BSS and call boot_card() + */ + CopyDataClearBSSAndStart (); +} diff --git a/bsps/m68k/uC5282/start/linkcmds b/bsps/m68k/uC5282/start/linkcmds new file mode 100644 index 0000000000..a3b84294e3 --- /dev/null +++ b/bsps/m68k/uC5282/start/linkcmds @@ -0,0 +1,243 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the Arcturus uC DIMM ColdFire 5282 + * + * Author: W. Eric Norum <norume@aps.anl.gov> + * + * COPYRIGHT (c) 2005-2007. + * 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. + */ + +/* + * Declare some locations and sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamSize : 16M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0; +_FlashBase = DEFINED(_FlashBase) ? _FlashBase : 0x10000000; +_FlashSize = DEFINED(_FlashSize) ? _FlashSize : 4M ; + +/* + * Location of downloaded (from TFTP or flash) file + */ +_DownloadLocation = 0x40000; + +/* + * System clock speed + * + * If autodetection of the system clock pased on the PLL ref. clock + * (AFAIK 8MHz for both 64MHz and 80MHz boards) doesn't work then + * you can: + * - define (nonzero) system clock speed from app- linkflags (or here) + * - use a uCbootloader env. var: SYS_CLOCK_SPEED to define it. + * You can also redefine the PLL reference clock speed from linkflags + * or here... + */ +_CPUClockSpeed = DEFINED(_CPUClockSpeed) ? _CPUClockSpeed : 0 ; +_PLLRefClockSpeed = DEFINED(_PLLRefClockSpeed) ? _PLLRefClockSpeed : 8000000; + +/* + * Location of on-chip devices + */ +__IPSBAR = DEFINED(__IPSBAR) ? __IPSBAR : 0x40000000 ; +__SRAMBASE = DEFINED(__SRAMBASE) ? __SRAMBASE : 0x20000000 ; +_VBR = 0x0; + +ENTRY(start) +STARTUP(start.o) + +MEMORY +{ + ram : ORIGIN = 0, LENGTH = 16M + sram : ORIGIN = 0x20000000, LENGTH = 64k +} + +SECTIONS +{ + + _header_offset = 0; + + /* + * Text, data and bss segments + */ + .text _DownloadLocation : { + + *(.text*) + *(.ram_code) + + /* + * C++ constructors/destructors + */ + *(.gnu.linkonce.t.*) + + /* + * Initialization and finalization code. + * + * Various files can provide initialization and finalization + * functions. crtbegin.o and crtend.o are two instances. The + * body of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues + * from crti.o and function epilogues from crtn.o. crti.o must + * be linked first; crtn.o must be linked last. Because these + * are wildcards, it doesn't matter if the user does not + * actually link against crti.o and crtn.o; the linker won't + * look for a file to match a wildcard. The wildcard also + * means that it doesn't matter which directory crti.o and + * crtn.o are in. + */ + PROVIDE (_init = .); + *crti.o(.init) + *(.init) + *crtn.o(.init) + PROVIDE (_fini = .); + *crti.o(.fini) + *(.fini) + *crtn.o(.fini) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * C++ constructors/destructors + * + * gcc uses crtbegin.o to find the start of the constructors + * and destructors 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. The + * constructor and destructor list are terminated in + * crtend.o. The same comments apply to it. + */ + . = ALIGN (16); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + + /* + * Exception frame info + */ + . = ALIGN (16); + *(.eh_frame) + + /* + * Read-only data + */ + . = ALIGN (16); + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + + . = ALIGN (16); + + *(.console_gdb_xfer) + *(.bootstrap_data) + . = ALIGN(16); + _estuff = .; + PROVIDE (_etext = .); + } >ram + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > ram + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } > ram + + _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)); + + .data : { + PROVIDE( _data_dest_start = . ); + PROVIDE( _copy_start = .); + *(.data*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + *(.gcc_except_table*) + *(.jcr) + . = ALIGN (16); + PROVIDE (_edata = .); + PROVIDE (_copy_end = .); + PROVIDE (_data_dest_end = . ); + } >ram + + _data_src_start = LOADADDR(.data); + _data_src_end = _data_src_start + SIZEOF(.data); + + .bss : { + _clear_start = .; + *(.bss*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (16); + PROVIDE (end = .); + _clear_end = .; + WorkAreaBase = .; + } >ram + + /* 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) } + .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) } + /* These must appear regardless of . */ + +PROVIDE (end_of_all = .); +} diff --git a/bsps/mips/csb350/start/bsp_specs b/bsps/mips/csb350/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/mips/csb350/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/mips/csb350/start/bspreset.c b/bsps/mips/csb350/start/bspreset.c new file mode 100644 index 0000000000..811a6f96c7 --- /dev/null +++ b/bsps/mips/csb350/start/bspreset.c @@ -0,0 +1,24 @@ +/* + * COPYRIGHT (c) 1989-2008. + * 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 <libcpu/au1x00.h> + +void bsp_reset(void) +{ + void (*reset_func)(void); + + reset_func = (void *)0xbfc00000; + + mips_set_sr( 0x00200000 ); /* all interrupts off, boot exception vectors */ + + /* Try to restart bootloader */ + reset_func(); +} diff --git a/bsps/mips/csb350/start/bspstart.c b/bsps/mips/csb350/start/bspstart.c new file mode 100644 index 0000000000..5b9a6aed82 --- /dev/null +++ b/bsps/mips/csb350/start/bspstart.c @@ -0,0 +1,44 @@ +/** + * @file + * + * This routine starts the application. 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) 1989-2012. + * 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 <string.h> + +#include <bsp.h> +#include <libcpu/au1x00.h> +#include <libcpu/isr_entries.h> +#include <bsp/irq-generic.h> + +void bsp_start( void ); + +au1x00_uart_t *uart0 = (au1x00_uart_t *)AU1X00_UART0_ADDR; +au1x00_uart_t *uart3 = (au1x00_uart_t *)AU1X00_UART3_ADDR; + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ +void bsp_start( void ) +{ + unsigned int compare = 0; + + mips_set_sr( 0x7f00 ); /* all interrupts unmasked but globally off */ + /* depend on the IRC to take care of things */ + __asm__ volatile ("mtc0 %0, $11\n" :: "r" (compare)); + bsp_interrupt_initialize(); +} diff --git a/bsps/mips/csb350/start/linkcmds b/bsps/mips/csb350/start/linkcmds new file mode 100644 index 0000000000..b11b73bf42 --- /dev/null +++ b/bsps/mips/csb350/start/linkcmds @@ -0,0 +1,235 @@ +/* + * Linker script for CSB350 AU1100 based board + */ + +/* . = 0x80020000; */ + +/* + * Declare some sizes. + */ + +_sdram_base = DEFINED(_sdram_base) ? _sdram_base : 0x80400000; +_sdram_size = DEFINED(_sdram_size) ? _sdram_size : 12M; + +/* standard items provided by RTEMS linkcmds files */ +RamBase = _sdram_base; +RamSize = _sdram_size; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x4000; + +ENTRY(_start) +STARTUP(start.o) + +MEMORY +{ + ram : ORIGIN = 0x80400000, LENGTH = 12M +} + +SECTIONS +{ + .text : + { + _ftext = . ; + + */start.o(.text) + + *(.text*) + *(.gnu.linkonce.t*) + *(.mips16.fn.*) + *(.mips16.call.*) + *(.reginfo*) + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + *(.rel.dyn) + PROVIDE (__runtime_reloc_stop = .); + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + *(.gcc_except_table*) + *(.eh_frame_hdr) + *(.eh_frame) + } >ram + + .init : + { + KEEP(*(.init)) + + } > ram + + .fini : + { + KEEP(*(.fini)) + + } >ram + + + .ctors : + { + /* 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)) + + /* We don't want to include the .ctor section from + 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) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >ram + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + + etext = .; + _etext = .; + } >ram + + + + .rdata : + { + *(.rdata) + *(.rodata) + *(.rodata.*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + } >ram + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >ram + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >ram + + _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)); + + .data : + { + _fdata = ALIGN(16); + + *(.data) + *(.data.*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + } >ram + + .jcr : + { + . = ALIGN(8); + KEEP (*(.jcr)) + + _gp = ALIGN(16) + 0x7440; + __global = _gp; + } >ram + + .lit8 : + { + *(.lit8) + } >ram + + .lit4 : + { + *(.lit4) + } >ram + + .sdata : + { + *(.sdata*) + *(.gnu.linkonce.s*) + } >ram + + .sbss : + { + edata = .; + _edata = .; + _fbss = .; + *(.sbss*) + *(.scommon) + } >ram + + + .bss : + { + _bss_start = . ; + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (64); + _stack_limit = .; + . += _StackSize; + __stack = .; + _stack_init = .; + _clear_end = .; + end = .; + _end = .; + . = ALIGN (1024); + WorkAreaBase = .; + + } >ram + + +/* +** 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) } + .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) } +} diff --git a/bsps/mips/hurricane/start/bsp_specs b/bsps/mips/hurricane/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/mips/hurricane/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/mips/hurricane/start/bspstart.c b/bsps/mips/hurricane/start/bspstart.c new file mode 100644 index 0000000000..8b36b58628 --- /dev/null +++ b/bsps/mips/hurricane/start/bspstart.c @@ -0,0 +1,39 @@ +/** + * @file + * + * This routine starts the application. 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) 1989-2012. + * 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 <string.h> + +#include <bsp.h> +#include <libcpu/isr_entries.h> +#include <bsp/irq-generic.h> + +void bsp_start( void ); +uint32_t bsp_clicks_per_microsecond; + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ +void bsp_start( void ) +{ + + bsp_clicks_per_microsecond = CPU_CLOCK_RATE_MHZ; + + bsp_interrupt_initialize(); +} diff --git a/bsps/mips/hurricane/start/ghlinkcmds b/bsps/mips/hurricane/start/ghlinkcmds new file mode 100644 index 0000000000..9b6c6dce87 --- /dev/null +++ b/bsps/mips/hurricane/start/ghlinkcmds @@ -0,0 +1,19 @@ +# +# ghlinkcmds +# + +-map +-sec +{ + .text 0x80010000 : + .data align(16) : + .rodata : + .fini : +# .sdata : + .symtab : + .strtab : + .debug : +# .sbss : + .bss align(8) : + .init 0xbfc00000 : +} diff --git a/bsps/mips/hurricane/start/inittlb.c b/bsps/mips/hurricane/start/inittlb.c new file mode 100644 index 0000000000..800cf3d23c --- /dev/null +++ b/bsps/mips/hurricane/start/inittlb.c @@ -0,0 +1,10 @@ +#include <bsp.h> +#include <rtems/mips/idtcpu.h> + +void init_tlb(void) +{ + int i; + + for (i = 0; i < N_TLB_ENTRIES; i++ ) + resettlb(i); +} diff --git a/bsps/mips/hurricane/start/linkcmds b/bsps/mips/hurricane/start/linkcmds new file mode 100644 index 0000000000..4e10c29f6e --- /dev/null +++ b/bsps/mips/hurricane/start/linkcmds @@ -0,0 +1,188 @@ +/* + * linkcmds + */ + +/* + * Declare some sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x80000000; +RamSize = DEFINED(RamSize) ? RamSize : 4M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x1000; + +ENTRY(start) +STARTUP(start.o) + +SECTIONS +{ + /* 0x80000000 - 0x8001FFFF used by PMON (with 0x80010000 - 0x8001FFFF as heap for symbol storage) + 0x80020000 - 0x8002FFFF reserved for shared memory + 0x80030000 beginning of text (code) section + */ + .text 0x80030000 : + { + _ftext = . ; + eprol = .; + *(.text) + *(.text.*) + *(.gnu.linkonce.t*) + *(.mips16.fn.*) + *(.mips16.call.*) + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + *(.gcc_except_table*) + *(.eh_frame_hdr) + *(.eh_frame) + } + + .init : + { + KEEP(*crti.o(.init)) + KEEP(*(.init)) + KEEP(*crtn.o(.init)) + } + + .fini : + { + KEEP(*crti.o(.fini)) + KEEP(*(.fini)) + KEEP(*crtn.o(.fini)) + } + + .ctors : + { + /* 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)) + + /* We don't want to include the .ctor section from + 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) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + + etext = .; + _etext = .; + } + + .rdata : { + *(.rdata) + *(.rodata) + *(.rodata.*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + } + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } + + _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)); + + _fdata = ALIGN(16); + + .data : { + *(.data) + *(.data.*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + } + . = ALIGN(8); + + .jcr : { + KEEP (*(.jcr)) + } + + _gp = ALIGN(16) + 0x8000; + __global = _gp; + + .sdata : { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s*) + } + .lit8 : { + *(.lit8) + } + .lit4 : { + *(.lit4) + } + + edata = .; + _edata = .; + _fbss = .; + + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + _bss_start = . ; + *(.bss) + *(COMMON) + . = ALIGN (64); + _stack_limit = .; + . += _StackSize; + __stack = .; + _stack_init = .; + end = .; + _end = .; + WorkAreaBase = .; + } + + + /* Debug sections. These should never be loadable, but they must have + zero addresses for the debuggers to work correctly. */ + .line 0 : { *(.line) } + .debug 0 : { *(.debug) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/bsps/mips/hurricane/start/usc.S b/bsps/mips/hurricane/start/usc.S new file mode 100644 index 0000000000..887290e2a9 --- /dev/null +++ b/bsps/mips/hurricane/start/usc.S @@ -0,0 +1,180 @@ +/* usc.S + * + * COPYRIGHT (c) 1989-2010. + * 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 <bspopts.h> +#include <rtems/asm.h> +#include <rtems/mips/iregdef.h> +#include <rtems/mips/idtcpu.h> +#if BSP_HAS_USC320 + #include <usc.h> +#endif + + +/*************************************************************************** +** +** The following code was added to support boards using V3 USC320 +** system controller chip. +** +****************************************************************************/ + +/************************************************************* +* init_hbt() +* Initialize the heartbeat timer +*/ +FRAME(init_hbt,sp,0,ra) + .set noreorder + la t0,SYSTEM # Unlock USC registers + li t1,0xA5 + sb t1,(t0) + + la t0,WD_HBI # Initialize heatbeat and watchdog timers + + # (1 / 64 MHz) * 4000 * (63 + 1) = 4000.0 microseconds + # Watchdog period is heartbeat period times watchdog timer constant (bits 7 - 0) + # Watchdog period = 4000 * 5 = 20000 microseconds + li t1,(WD_EN | HBI_4000_PS | 0x00003F00 | 0x5) + + # (1 / 64 MHz) * 4000 * (15 + 1) = 1000.0 microseconds + # Watchdog period is heartbeat period times watchdog timer constant (bits 7 - 0) + # Watchdog period = 1000 * 20 = 20000 microseconds + li t1,(WD_EN | HBI_4000_PS | 0x00000F00 | 0x14) + + # (1 / 64 MHz) * 40000 * (15 + 1) = 10000.0 microseconds + # Watchdog period is heartbeat period times watchdog timer constant (bits 7 - 0) + # Watchdog period = 10000 * 20 = 200000 microseconds + li t1,(WD_EN | HBI_4000_PS | 0x00009600 | 0x14) + + sw t1,(t0) + + la t0,SYSTEM # Lock USC registers + li t1,0x60 + sb t1,(t0) + + .set reorder + j ra + nop + .set reorder +ENDFRAME(init_hbt) + +/************************************************************* +* reset_wdt() +* Reset the watchdog timer +*/ +FRAME(reset_wdt,sp,0,ra) + .set noreorder + + la t0,WD_HBI+2 # Load address watchdog timer reset byte + li t1,WD_INIT + sb t1,(t0) + + .set reorder + j ra + nop + .set reorder +ENDFRAME(reset_wdt) + +/************************************************************* +* disable_wdt() +* Disable watchdog timer +*/ +FRAME(disable_wdt,sp,0,ra) + .set noreorder + la t0,WD_HBI # Clear watchdog enable bit in control register + lw t1,(t0) + li t2,~WD_EN + and t1,t1,t2 + sw t1,(t0) + + .set reorder + j ra + nop + .set reorder +ENDFRAME(disable_wdt) + +/************************************************************* +* enable_hbi(ints) +* Enable the heartbeat interrupt +*/ +FRAME(enable_hbi,sp,0,ra) + .set noreorder + + la t0,INT_CFG3 # Enable heartbeat interrupt in USC320 + lw t1,(t0) + li t2,(HBI_MASK | MODE_TOTEM_POLE) + or t1,t1,t2 + sw t1,(t0) + + .set reorder + j ra + nop + .set reorder +ENDFRAME(enable_hbi) + +/************************************************************* +* disable_hbi(ints) +* Disable the heartbeat interrupt +*/ +FRAME(disable_hbi,sp,0,ra) + .set noreorder + la t0,INT_CFG3 # Disable heartbeat interrupt in USC320 + lw t1,(t0) + li t2,~HBI_MASK + and t1,t1,t2 + sw t1,(t0) + + .set reorder + j ra + nop + .set reorder +ENDFRAME(disable_hbi) + + +/************************************************************* +* enable_wdi() +* Enable the watchdog interrupt +*/ +FRAME(enable_wdi,sp,0,ra) + .set noreorder + + la t0,INT_CFG1 # Enable watchdog interrupt in USC320 + lw t1,(t0) + li t2,(WDI_MASK | MODE_TOTEM_POLE) + or t1,t1,t2 + sw t1,(t0) + + .set reorder + j ra + nop + .set reorder +ENDFRAME(enable_wdi) + +/************************************************************* +* disable_wdi(ints) +* Disable the watchdog interrupt +*/ +FRAME(disable_wdi,sp,0,ra) + .set noreorder + + la t0,INT_CFG1 # Disable watchdog interrupt in USC320 + lw t1,(t0) + li t2,~(WDI_MASK | MODE_TOTEM_POLE) + and t1,t1,t2 + sw t1,(t0) + + la t0,INT_STAT # Clear watchdog interrupt status bit + li t1,WDI_MASK + sw t1,(t0) + + .set reorder + j ra + nop + .set reorder +ENDFRAME(disable_wdi) + diff --git a/bsps/mips/jmr3904/start/bsp_specs b/bsps/mips/jmr3904/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/mips/jmr3904/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/mips/jmr3904/start/bspstart.c b/bsps/mips/jmr3904/start/bspstart.c new file mode 100644 index 0000000000..829c8400d8 --- /dev/null +++ b/bsps/mips/jmr3904/start/bspstart.c @@ -0,0 +1,65 @@ +/** + * @file + * + * This routine starts the application. 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) 1989-2012. + * 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 <libcpu/isr_entries.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> + +/* Structure filled in by get_mem_info. Only the size field is + * actually used (to clear bss), so the others aren't even filled in. + */ +struct s_mem +{ + unsigned int size; + unsigned int icsize; + unsigned int dcsize; +}; + +void bsp_start( void ); +void clear_cache( void *address, size_t n ); +void get_mem_info( struct s_mem *mem ); + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ +void bsp_start( void ) +{ + mips_set_sr( 0xff00 ); /* all interrupts unmasked but globally off */ + /* depend on the IRC to take care of things */ + bsp_interrupt_initialize(); +} + +/* + * Required routine by some gcc run-times. + */ +void clear_cache( void *address, size_t n ) +{ +} + + +void get_mem_info( + struct s_mem *mem +) +{ + mem->size = 0x1000000; /* XXX figure out something here */ +} diff --git a/bsps/mips/jmr3904/start/linkcmds b/bsps/mips/jmr3904/start/linkcmds new file mode 100644 index 0000000000..12a8a65b09 --- /dev/null +++ b/bsps/mips/jmr3904/start/linkcmds @@ -0,0 +1,212 @@ +/* + * Based on jmr3904app-dram.ld from newlib 1.8.2 + */ + +/* + * Declare some sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x88000000; +RamSize = DEFINED(RamSize) ? RamSize : 4M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x1000; + +ENTRY(_start) +STARTUP(start.o) + +SECTIONS +{ + . = 0x88000000; + .text : + { + _ftext = . ; + eprol = .; + *(.text*) + *(.gnu.linkonce.t*) + *(.mips16.fn.*) + *(.mips16.call.*) + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + + *(.gcc_except_table*) + *(.eh_frame_hdr) + *(.eh_frame) + } + + .rtemsroset : { + /* for pre rtems-libbsd FreeBSD code */ + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = .; + *(set_domain_*); + *(set_pseudo_*); + + KEEP (*(SORT(.rtemsroset.*))) + + . = ALIGN (16); + _endtext = .; + } + + .init : + { + KEEP(*(.init)) + } + + .fini : + { + KEEP(*(.fini)) + } + + .ctors : + { + /* 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)) + + /* We don't want to include the .ctor section from + 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) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + + etext = .; + _etext = .; + } + + .rdata : { + *(.rdata) + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r*) + } + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } + + _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)); + + _fdata = ALIGN(16); + + .data : { + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + } + + .rtemsrwset : { + KEEP (*(SORT(.rtemsrwset.*))) + } + . = ALIGN(8); + + .jcr : { + KEEP (*(.jcr)) + } + + _gp = ALIGN(16) + 0x7440; + __global = _gp; + + .sdata : { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s*) + } + .lit8 : { + *(.lit8) + } + .lit4 : { + *(.lit4) + } + + edata = .; + _edata = .; + _fbss = .; + + .sbss : { + *(.sbss*) + *(.scommon) + } + .bss : { + _bss_start = . ; + *(.bss*) + *(COMMON) + . = ALIGN (64); + _stack_limit = .; + . += _StackSize; + __stack = .; + _stack_init = .; + WorkAreaBase = .; + _clear_end = .; + } + . = 0x88400000; /* reserve some memory for Work Area */ + end = .; + _end = .; + + +/* Put starting stack in SRAM (8 Kb); this size is the same as the stack from + the original script (when everything was in SRAM). */ + /* __stack = 0x8000A000; */ + /* 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) } + .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) } +} diff --git a/bsps/mips/malta/start/bsp_specs b/bsps/mips/malta/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/mips/malta/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/mips/malta/start/bspreset.c b/bsps/mips/malta/start/bspreset.c new file mode 100644 index 0000000000..6d406ea943 --- /dev/null +++ b/bsps/mips/malta/start/bspreset.c @@ -0,0 +1,34 @@ +/** + * @file + * + * This file contains the code necessary to reset the Malta board. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * 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> + +void bsp_reset(void) +{ + uint32_t *reset; + + reset= (uint32_t *)0x9F000500; + /* + * Qemu understands 0x42 to reset simulated machine. + * We added code to recognize 0xFF to exit simulator. + * + * TBD: Qemu PC simulation has option to exit on reset. + * find processing of that command line option and + * use it to change behaviour of 0x42. + */ + // *reset = 0x42; + *reset = 0xFF; +} diff --git a/bsps/mips/malta/start/bspstart.c b/bsps/mips/malta/start/bspstart.c new file mode 100644 index 0000000000..58eee11027 --- /dev/null +++ b/bsps/mips/malta/start/bspstart.c @@ -0,0 +1,113 @@ +/** + * @file + * + * This file contains the bsp_start() method and support. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * 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 <libcpu/isr_entries.h> +#include <bsp/bootcard.h> +#include <rtems/pci.h> +#include <bsp/irq-generic.h> +#include <bsp/i8259.h> + +/* + * STRUCTURES + */ + +/* Structure filled in by get_mem_info. Only the size field is + * actually used (to clear bss), so the others aren't even filled in. + */ +struct s_mem +{ + unsigned int size; + unsigned int icsize; + unsigned int dcsize; +}; + + +/* + * GLOBALS + */ +uint32_t bsp_clicks_per_microsecond; + + +/* + * PROTOTYPES + */ +void clear_cache( void *address, size_t n ); +void get_mem_info( struct s_mem *mem ); + +/* + * EXTERNs + */ +extern int RamSize; + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ +void bsp_start( void ) +{ + /* uint32_t board_ID = 0x420; */ + static int j = 1; + int pci_init_retval; + + /* + * Note: This is the value that works for qemu, and it was + * unable to be validated on the actual hardware. + */ + mips_set_sr( 0x04100000 ); + + bsp_interrupt_initialize(); + + /* + * XXX need to figure out a real value. :) + * This works for the qemu simulation, but timeing may + * be off for the actual hardware. + */ + bsp_clicks_per_microsecond = 100; + + #if 1 + while ( j != 1 ) { + int i; + printk ("."); + for (i=0; i<1000; i++); + } + #endif + + /* + * init PCI Bios interface... + */ + pci_init_retval = pci_initialize(); + if (pci_init_retval != PCIB_ERR_SUCCESS) { + printk("PCI bus: could not initialize PCI BIOS interface\n"); + } + + BSP_i8259s_init(); + +} + +/* + * Required routine by some gcc run-times. + */ +void clear_cache( void *address, size_t n ) +{ +} + +void get_mem_info( + struct s_mem *mem +) +{ + mem->size = (int) (&RamSize); /* Normally 128 or 256 MB */ +} diff --git a/bsps/mips/malta/start/inittlb.c b/bsps/mips/malta/start/inittlb.c new file mode 100644 index 0000000000..0088b98483 --- /dev/null +++ b/bsps/mips/malta/start/inittlb.c @@ -0,0 +1,27 @@ +/** + * @file + */ + +/* + * COPYRIGHT (c) 1989-2012. + * 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 <rtems/mips/idtcpu.h> + +extern void resettlb( int i ); + +void init_tlb(void); + +void init_tlb(void) +{ + int i; + + for (i = 0; i < N_TLB_ENTRIES; i++ ) + resettlb(i); +} diff --git a/bsps/mips/malta/start/linkcmds b/bsps/mips/malta/start/linkcmds new file mode 100644 index 0000000000..3a71c5af8b --- /dev/null +++ b/bsps/mips/malta/start/linkcmds @@ -0,0 +1,213 @@ +/* + * MIPS Malta Linker Script + */ + +/* + * Declare some sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x80000000; +RamSize = DEFINED(RamSize) ? RamSize : 128M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x2000; + +ENTRY(_start) +STARTUP(start.o) + +SECTIONS +{ + . = 0x80010000; + .text : + { + _ftext = . ; + eprol = .; + *(.text*) + *(.gnu.linkonce.t*) + *(.mips16.fn.*) + *(.mips16.call.*) + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + + *(.gcc_except_table*) + *(.eh_frame_hdr) + *(.eh_frame) + } + + .init : + { + KEEP(*(.init)) + } + + .fini : + { + KEEP(*(.fini)) + } + + .ctors : + { + /* 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)) + + /* We don't want to include the .ctor section from + 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) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + + etext = .; + _etext = .; + } + + .rtemsroset : { + /* for pre rtems-libbsd FreeBSD code */ + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = .; + *(set_domain_*); + *(set_pseudo_*); + + KEEP (*(SORT(.rtemsroset.*))) + + . = ALIGN (16); + _endtext = .; + } + + .rdata : { + *(.rdata) + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r*) + } + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } + + _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)); + + _fdata = ALIGN(16); + + .data : { + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + } + + .rtemsrwset : { + KEEP (*(SORT(.rtemsrwset.*))) + } + + . = ALIGN(8); + + .jcr : { + KEEP (*(.jcr)) + } + + _gp = ALIGN(16) + 0x7440; + __global = _gp; + + .sdata : { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s*) + } + .lit8 : { + *(.lit8) + } + .lit4 : { + *(.lit4) + } + + edata = .; + _edata = .; + _fbss = .; + + .sbss : { + *(.sbss*) + *(.scommon) + } + .bss : { + _bss_start = . ; + *(.bss*) + *(COMMON) + . = ALIGN (64); + _stack_limit = .; + . += _StackSize; + __stack = .; + _stack_init = .; + WorkAreaBase = .; + _clear_end = .; + } + . = 0x88400000; /* reserve some memory for Work Area */ + end = .; + _end = .; + + +/* Put starting stack in SRAM (8 Kb); this size is the same as the stack from + the original script (when everything was in SRAM). */ + /* __stack = 0x8000A000; */ + /* 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) } + .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) } +} diff --git a/bsps/mips/malta/start/simple_access.c b/bsps/mips/malta/start/simple_access.c new file mode 100644 index 0000000000..cd15484b1c --- /dev/null +++ b/bsps/mips/malta/start/simple_access.c @@ -0,0 +1,133 @@ +/** + * @file + * + * This file contains the code to do simple memory and io accesses. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * 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.h> + +#include <bsp/pci.h> +#include <bsp/irq.h> +#include <rtems/bspIo.h> +#include <rtems/endian.h> +// #define DEBUG_ACCESSES 1 + +#ifdef DEBUG_ACCESSES + #define JPRINTK(fmt, ...) printk("%s: " fmt, __FUNCTION__, ##__VA_ARGS__) +#else + #define JPRINTK(fmt, ...) +#endif + +/* + * * Simple accesses + * */ +void simple_out_32(uint32_t base, uint32_t addr, uint32_t val) +{ + volatile uint32_t *ptr; + + ptr = (volatile uint32_t *) (base + addr); + *ptr = val; + + JPRINTK( "%p data: 0x%x\n", ptr, val); +} + +void simple_out_le32(uint32_t base, uint32_t addr, uint32_t val) +{ + volatile uint32_t *ptr; + uint32_t data = 0; + + ptr = (volatile uint32_t *) (base + addr); + rtems_uint32_to_little_endian( val, (uint8_t *) &data); + *ptr = data; + + JPRINTK( "%p data: 0x%x\n", ptr, data); +} + +uint8_t simple_in_8( uint32_t base, uint32_t addr ) { + volatile uint8_t *ptr; + uint8_t val; + + ptr = (volatile uint8_t *) (base + addr); + val = *ptr; + JPRINTK( "0x%x data: 0x%x\n", ptr, val); + + return val; +} + +int16_t simple_in_le16( uint32_t base, uint32_t addr ) { + volatile uint16_t *ptr; + uint16_t val; + uint16_t rval; + + ptr = (volatile uint16_t *) (base + addr); + val = *ptr; + rval = rtems_uint16_from_little_endian( (uint8_t *) &val); + JPRINTK( "0x%x data: 0x%x raw: 0x%x\n", ptr, rval, val); + return rval; +} + +int16_t simple_in_16( uint32_t base, uint32_t addr ) { + volatile uint16_t *ptr; + uint16_t val; + + ptr = (volatile uint16_t *) (base + addr); + val = *ptr; + JPRINTK( "0x%x data: 0x%x raw: 0x%x\n", ptr, val, val); + return val; +} + +uint32_t simple_in_le32( uint32_t base, uint32_t addr ) { + volatile uint32_t *ptr; + uint32_t val; + uint32_t rval; + + ptr = (volatile uint32_t *) (base + addr); + val = *ptr; + rval = rtems_uint32_from_little_endian( (uint8_t *) &val); + JPRINTK( "0x%x data: 0x%x raw: 0x%x\n", ptr, rval, val); + return rval; +} + +uint32_t simple_in_32( uint32_t base, uint32_t addr ) { + volatile uint32_t *ptr; + uint32_t val; + + ptr = (volatile uint32_t *) (base + addr); + val = *ptr; + JPRINTK( "0x%x data: 0x%x raw: 0x%x\n", ptr, val, val); + return val; +} + +void simple_out_8( uint32_t base, uint32_t addr, uint8_t val ) { + volatile uint8_t *ptr; + + ptr = (volatile uint8_t *) (base | addr); + JPRINTK( "0x%x data: 0x%x\n", ptr, val); + *ptr = val; +} + +void simple_out_le16( uint32_t base, uint32_t addr, uint16_t val ) { + volatile uint16_t *ptr; + uint16_t data; + ptr = (volatile uint16_t *) (base + addr); + rtems_uint16_to_little_endian( val, (uint8_t *) &data); + *ptr = data; + JPRINTK( "0x%x data: 0x%x\n", ptr, data); +} + +void simple_out_16( uint32_t base, uint32_t addr, uint16_t val ) { + volatile uint16_t *ptr; + ptr = (volatile uint16_t *) (base + addr); + *ptr = val; + JPRINTK( "0x%x data: 0x%x\n", ptr, val); +} diff --git a/bsps/mips/rbtx4925/start/bsp_specs b/bsps/mips/rbtx4925/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/mips/rbtx4925/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/mips/rbtx4925/start/bspstart.c b/bsps/mips/rbtx4925/start/bspstart.c new file mode 100644 index 0000000000..fc9fce1d94 --- /dev/null +++ b/bsps/mips/rbtx4925/start/bspstart.c @@ -0,0 +1,34 @@ +/** + * @file + * + * This routine starts the application. 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) 1989-2012. + * 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 <libcpu/isr_entries.h> +#include <bsp/irq-generic.h> + +void bsp_start( void ); + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ +void bsp_start( void ) +{ + bsp_interrupt_initialize(); +} + diff --git a/bsps/mips/rbtx4925/start/idttlb.S b/bsps/mips/rbtx4925/start/idttlb.S new file mode 100644 index 0000000000..2574027dc9 --- /dev/null +++ b/bsps/mips/rbtx4925/start/idttlb.S @@ -0,0 +1,388 @@ +/* + +Based upon IDT provided code with the following release: + +This source code has been made available to you by IDT on an AS-IS +basis. Anyone receiving this source is licensed under IDT copyrights +to use it in any way he or she deems fit, including copying it, +modifying it, compiling it, and redistributing it either with or +without modifications. No license under IDT patents or patent +applications is to be implied by the copyright license. + +Any user of this software should understand that IDT cannot provide +technical support for this software and will not be responsible for +any consequences resulting from the use of this software. + +Any person who transfers this source code or any derivative work must +include the IDT copyright notice, this paragraph, and the preceeding +two paragraphs in the transferred software. + +COPYRIGHT IDT CORPORATION 1996 +LICENSED MATERIAL - PROGRAM PROPERTY OF IDT +*/ + + +/* +** idttlb.s - fetch the registers associated with and the contents +** of the tlb. +** +*/ +/* 950308: Ketan patched a few tlb functions that would not have worked.*/ +#include <rtems/mips/iregdef.h> +#include <rtems/mips/idtcpu.h> +#include <rtems/asm.h> + + + .text + +#if __mips == 1 +/* +** ret_tlblo -- returns the 'entrylo' contents for the TLB +** 'c' callable - as ret_tlblo(index) - where index is the +** tlb entry to return the lo value for - if called from assembly +** language then index should be in register a0. +*/ +FRAME(ret_tlblo,sp,0,ra) + .set noreorder + mfc0 t0,C0_SR # save sr + nop + and t0,~SR_PE # dont inadvertantly clear PE + mtc0 zero,C0_SR # clear interrupts + mfc0 t1,C0_TLBHI # save pid + sll a0,TLBINX_INXSHIFT # position index + mtc0 a0,C0_INX # write to index register + nop + tlbr # put tlb entry in entrylo and hi + nop + mfc0 v0,C0_TLBLO # get the requested entry lo + mtc0 t1,C0_TLBHI # restore pid + mtc0 t0,C0_SR # restore status register + j ra + nop + .set reorder +ENDFRAME(ret_tlblo) +#endif +#if __mips == 3 +/* +** ret_tlblo[01] -- returns the 'entrylo' contents for the TLB +** 'c' callable - as ret_tlblo(index) - where index is the +** tlb entry to return the lo value for - if called from assembly +** language then index should be in register a0. +*/ +FRAME(ret_tlblo0,sp,0,ra) + mfc0 t0,C0_SR # save sr + mtc0 zero,C0_SR # clear interrupts + mfc0 t1,C0_TLBHI # save pid + mtc0 a0,C0_INX # write to index register + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + tlbr # put tlb entry in entrylo and hi + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + mfc0 v0,C0_TLBLO0 # get the requested entry lo + mtc0 t1,C0_TLBHI # restore pid + mtc0 t0,C0_SR # restore status register + j ra +ENDFRAME(ret_tlblo0) + +FRAME(ret_tlblo1,sp,0,ra) + mfc0 t0,C0_SR # save sr + mtc0 zero,C0_SR # clear interrupts + mfc0 t1,C0_TLBHI # save pid + mtc0 a0,C0_INX # write to index register + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + tlbr # put tlb entry in entrylo and hi + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + mfc0 v0,C0_TLBLO1 # get the requested entry lo + mtc0 t1,C0_TLBHI # restore pid + mtc0 t0,C0_SR # restore status register + j ra +ENDFRAME(ret_tlblo1) + +/* +** ret_pagemask(index) -- return pagemask contents of tlb entry "index" +*/ +FRAME(ret_pagemask,sp,0,ra) + mfc0 t0,C0_SR # save sr + mtc0 zero,C0_SR # disable interrupts + mfc0 t1,C0_TLBHI # save current pid + mtc0 a0,C0_INX # drop it in C0 register + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + tlbr # read entry to entry hi/lo + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + mfc0 v0,C0_PAGEMASK # to return value + mtc0 t1,C0_TLBHI # restore current pid + mtc0 t0,C0_SR # restore sr + j ra +ENDFRAME(ret_pagemask) + +/* +** ret_tlbwired(void) -- return wired register +*/ +FRAME(ret_tlbwired,sp,0,ra) + mfc0 v0,C0_WIRED + j ra +ENDFRAME(ret_tlbwired) +#endif + +/* +** ret_tlbhi -- return the tlb entry high content for tlb entry +** index +*/ +FRAME(ret_tlbhi,sp,0,ra) +#if __mips == 1 + .set noreorder + mfc0 t0,C0_SR # save sr + nop + and t0,~SR_PE + mtc0 zero,C0_SR # disable interrupts + mfc0 t1,C0_TLBHI # save current pid + sll a0,TLBINX_INXSHIFT # position index + mtc0 a0,C0_INX # drop it in C0 register + nop + tlbr # read entry to entry hi/lo + nop + mfc0 v0,C0_TLBHI # to return value + mtc0 t1,C0_TLBHI # restore current pid + mtc0 t0,C0_SR # restore sr + j ra + nop + .set reorder +#endif +#if __mips == 3 + mfc0 t0,C0_SR # save sr + mtc0 zero,C0_SR # disable interrupts + mfc0 t1,C0_TLBHI # save current pid + mtc0 a0,C0_INX # drop it in C0 register + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + tlbr # read entry to entry hi/lo0/lo1/mask + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + mfc0 v0,C0_TLBHI # to return value + mtc0 t1,C0_TLBHI # restore current pid + mtc0 t0,C0_SR # restore sr + j ra +#endif +ENDFRAME(ret_tlbhi) + +/* +** ret_tlbpid() -- return tlb pid contained in the current entry hi +*/ +FRAME(ret_tlbpid,sp,0,ra) +#if __mips == 1 + .set noreorder + mfc0 v0,C0_TLBHI # fetch tlb high + nop + and v0,TLBHI_PIDMASK # isolate and position + srl v0,TLBHI_PIDSHIFT + j ra + nop + .set reorder +#endif +#if __mips == 3 + mfc0 v0,C0_TLBHI # to return value + nop + and v0,TLBHI_PIDMASK + j ra +#endif +ENDFRAME(ret_tlbpid) + +/* +** tlbprobe(address, pid) -- probe the tlb to see if address is currently +** mapped +** a0 = vpn - virtual page numbers are 0=0 1=0x1000, 2=0x2000... +** virtual page numbers for the r3000 are in +** entry hi bits 31-12 +** a1 = pid - this is a process id ranging from 0 to 63 +** this process id is shifted left 6 bits and or'ed into +** the entry hi register +** returns an index value (0-63) if successful -1 -f not +*/ +FRAME(tlbprobe,sp,0,ra) +#if __mips == 1 + .set noreorder + mfc0 t0,C0_SR /* fetch status reg */ + and a0,TLBHI_VPNMASK /* isolate just the vpn */ + and t0,~SR_PE /* don't inadvertantly clear pe */ + mtc0 zero,C0_SR + mfc0 t1,C0_TLBHI + sll a1,TLBHI_PIDSHIFT /* possition the pid */ + and a1,TLBHI_PIDMASK + or a0,a1 /* build entry hi value */ + mtc0 a0,C0_TLBHI + nop + tlbp /* do the probe */ + nop + mfc0 v1,C0_INX + li v0,-1 + bltz v1,1f + nop + sra v0,v1,TLBINX_INXSHIFT /* get index positioned for return */ +1: + mtc0 t1,C0_TLBHI /* restore tlb hi */ + mtc0 t0,C0_SR /* restore the status reg */ + j ra + nop + .set reorder +#endif +#if __mips == 3 + mfc0 t0,C0_SR # save sr + mtc0 zero,C0_SR # disable interrupts + mfc0 t1,C0_TLBHI # save current pid + and a0,TLBHI_VPN2MASK # construct tlbhi for probe + and a1,TLBHI_PIDMASK + or a0,a1 + mtc0 a0,C0_TLBHI + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + tlbp # probe entry to entry hi/lo0/lo1/mask + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + mfc0 v1,C0_INX + li v0,-1 + bltz v1,1f + move v0,v1 +1: mtc0 t1,C0_TLBHI # restore current pid + mtc0 t0,C0_SR # restore sr + j ra +#endif +ENDFRAME(tlbprobe) + +/* +** resettlb(index) Invalidate the TLB entry specified by index +*/ +FRAME(resettlb,sp,0,ra) +#if __mips == 1 + .set noreorder + mfc0 t0,C0_TLBHI # fetch the current hi + mfc0 v0,C0_SR # fetch the status reg. + li t2,K0BASE&TLBHI_VPNMASK + and v0,~SR_PE # dont inadvertantly clear PE + mtc0 zero,C0_SR + mtc0 t2,C0_TLBHI # set up tlbhi + mtc0 zero,C0_TLBLO + sll a0,TLBINX_INXSHIFT + mtc0 a0,C0_INX + nop + tlbwi # do actual invalidate + nop + mtc0 t0,C0_TLBHI + mtc0 v0,C0_SR + j ra + nop + .set reorder +#endif +#if __mips == 3 + li t2,K0BASE&TLBHI_VPN2MASK + mfc0 t0,C0_TLBHI # save current TLBHI + mfc0 v0,C0_SR # save SR and disable interrupts + mtc0 zero,C0_SR + mtc0 t2,C0_TLBHI # invalidate entry + mtc0 zero,C0_TLBLO0 + mtc0 zero,C0_TLBLO1 + mtc0 a0,C0_INX + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + tlbwi + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + mtc0 t0,C0_TLBHI + mtc0 v0,C0_SR + j ra +#endif +ENDFRAME(resettlb) + +#if __mips == 1 +/* +** Setup TLB entry +** +** map_tlb(index, tlbhi, phypage) +** a0 = TLB entry index +** a1 = virtual page number and PID +** a2 = physical page +*/ +FRAME(map_tlb,sp,0,ra) + .set noreorder + sll a0,TLBINX_INXSHIFT + mfc0 v0,C0_SR # fetch the current status + mfc0 a3,C0_TLBHI # save the current hi + and v0,~SR_PE # dont inadvertantly clear parity + + mtc0 zero,C0_SR + mtc0 a1,C0_TLBHI # set the hi entry + mtc0 a2,C0_TLBLO # set the lo entry + mtc0 a0,C0_INX # load the index + nop + tlbwi # put the hi/lo in tlb entry indexed + nop + mtc0 a3,C0_TLBHI # put back the tlb hi reg + mtc0 v0,C0_SR # restore the status register + j ra + nop + .set reorder +ENDFRAME(map_tlb) +#endif +#if __mips == 3 +/* +** Setup R4000 TLB entry +** +** map_tlb4000(mask_index, tlbhi, pte_even, pte_odd) +** a0 = TLB entry index and page mask +** a1 = virtual page number and PID +** a2 = pte -- contents of even pte +** a3 = pte -- contents of odd pte +*/ +FRAME(map_tlb4000,sp,0,ra) + and t2,a0,TLBPGMASK_MASK + and a0,TLBINX_INXMASK + mfc0 t1,C0_TLBHI # save current TLBPID + mfc0 v0,C0_SR # save SR and disable interrupts + mtc0 zero,C0_SR + mtc0 t2,C0_PAGEMASK # set + mtc0 a1,C0_TLBHI # set VPN and TLBPID + mtc0 a2,C0_TLBLO0 # set PPN and access bits + mtc0 a3,C0_TLBLO1 # set PPN and access bits + mtc0 a0,C0_INX # set INDEX to wired entry + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + tlbwi # drop it in + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + mtc0 t1,C0_TLBHI # restore TLBPID + mtc0 v0,C0_SR # restore SR + j ra +ENDFRAME(map_tlb4000) +#endif + + +/* +** Set current TLBPID. This assumes PID is positioned correctly in reg. +** a0. +*/ +FRAME(set_tlbpid,sp,0,ra) + .set noreorder + mtc0 a0,C0_TLBHI + j ra + nop + .set reorder +ENDFRAME(set_tlbpid) + diff --git a/bsps/mips/rbtx4925/start/inittlb.c b/bsps/mips/rbtx4925/start/inittlb.c new file mode 100644 index 0000000000..ab09e9c854 --- /dev/null +++ b/bsps/mips/rbtx4925/start/inittlb.c @@ -0,0 +1,17 @@ +/* + * inittlb.c + */ + +#include <bsp.h> +#include <rtems/mips/idtcpu.h> + +extern void resettlb( int i ); + +void init_tlb(void) +{ + int i; + + for (i = 0; i < N_TLB_ENTRIES; i++ ) + resettlb(i); +} + diff --git a/bsps/mips/rbtx4925/start/linkcmds b/bsps/mips/rbtx4925/start/linkcmds new file mode 100644 index 0000000000..4f7de84115 --- /dev/null +++ b/bsps/mips/rbtx4925/start/linkcmds @@ -0,0 +1,188 @@ +/* + * linkcmds + */ + +/* + * Declare some sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x80000000; +RamSize = DEFINED(RamSize) ? RamSize : 4M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x1000; + +ENTRY(start) +STARTUP(start.o) + +SECTIONS +{ + /* 0x80000000 - 0x8001FFFF used by PMON (with 0x80010000 - 0x8001FFFF as heap for symbol storage) + 0x80020000 - 0x8002FFFF reserved for shared memory + 0x80030000 beginning of text (code) section + */ + .text 0x80030000 : + { + _ftext = . ; + eprol = .; + *(.text) + *(.text.*) + *(.gnu.linkonce.t*) + *(.mips16.fn.*) + *(.mips16.call.*) + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + *(.gcc_except_table*) + *(.eh_frame_hdr) + *(.eh_frame) + } + + .init : + { + KEEP(*crti.o(.init)) + KEEP(*(.init)) + KEEP(*crtn.o(.init)) + } + + .fini : + { + KEEP(*crti.o(.fini)) + KEEP(*(.fini)) + KEEP(*crtn.o(.fini)) + } + + .ctors : + { + /* 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)) + + /* We don't want to include the .ctor section from + 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) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + + etext = .; + _etext = .; + } + + .rdata : { + *(.rdata) + *(.rodata) + *(.rodata.*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + } + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } + + _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)); + + _fdata = ALIGN(16); + + .data : { + *(.data) + *(.data.*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + } + . = ALIGN(8); + + .jcr : { + KEEP (*(.jcr)) + } + + _gp = ALIGN(16) + 0x8000; + __global = _gp; + + .sdata : { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s*) + } + .lit8 : { + *(.lit8) + } + .lit4 : { + *(.lit4) + } + + edata = .; + _edata = .; + _fbss = .; + + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + _bss_start = . ; + *(.bss) + *(COMMON) + . = ALIGN (64); + _stack_limit = .; + . += _StackSize; + __stack = .; + _stack_init = .; + end = .; + _end = .; + WorkAreaBase = .; + } + + + /* Debug sections. These should never be loadable, but they must have + zero addresses for the debuggers to work correctly. */ + .line 0 : { *(.line) } + .debug 0 : { *(.debug) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/bsps/mips/rbtx4938/start/bsp_specs b/bsps/mips/rbtx4938/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/mips/rbtx4938/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/mips/rbtx4938/start/bspstart.c b/bsps/mips/rbtx4938/start/bspstart.c new file mode 100644 index 0000000000..4c7ffb0ca3 --- /dev/null +++ b/bsps/mips/rbtx4938/start/bspstart.c @@ -0,0 +1,33 @@ +/** + * @file + * + * This routine starts the application. 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) 1989-2012. + * 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 <libcpu/isr_entries.h> +#include <bsp/irq-generic.h> + +void bsp_start( void ); + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ +void bsp_start( void ) +{ + bsp_interrupt_initialize(); +} diff --git a/bsps/mips/rbtx4938/start/inittlb.c b/bsps/mips/rbtx4938/start/inittlb.c new file mode 100644 index 0000000000..ab09e9c854 --- /dev/null +++ b/bsps/mips/rbtx4938/start/inittlb.c @@ -0,0 +1,17 @@ +/* + * inittlb.c + */ + +#include <bsp.h> +#include <rtems/mips/idtcpu.h> + +extern void resettlb( int i ); + +void init_tlb(void) +{ + int i; + + for (i = 0; i < N_TLB_ENTRIES; i++ ) + resettlb(i); +} + diff --git a/bsps/mips/rbtx4938/start/linkcmds b/bsps/mips/rbtx4938/start/linkcmds new file mode 100644 index 0000000000..246e11debc --- /dev/null +++ b/bsps/mips/rbtx4938/start/linkcmds @@ -0,0 +1,188 @@ +/* + * linkcmds + */ + +/* + * Declare some sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x80000000; +RamSize = DEFINED(RamSize) ? RamSize : 4M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x1000; + +ENTRY(start) +STARTUP(start.o) + +SECTIONS +{ + /* 0x80000000 - 0x800FFFFF used by YAMON + 0x80120000 - 0x8012FFFF reserved for shared memory + 0x80130000 beginning of text (code) section + */ + .text 0x80130000 : + { + _ftext = . ; + eprol = .; + *(.text) + *(.text.*) + *(.gnu.linkonce.t*) + *(.mips16.fn.*) + *(.mips16.call.*) + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + *(.gcc_except_table*) + *(.eh_frame_hdr) + *(.eh_frame) + } + + .init : + { + KEEP(*crti.o(.init)) + KEEP(*(.init)) + KEEP(*crtn.o(.init)) + } + + .fini : + { + KEEP(*crti.o(.fini)) + KEEP(*(.fini)) + KEEP(*crtn.o(.fini)) + } + + .ctors : + { + /* 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)) + + /* We don't want to include the .ctor section from + 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) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + + etext = .; + _etext = .; + } + + .rdata : { + *(.rdata) + *(.rodata) + *(.rodata.*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + } + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } + + _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)); + + _fdata = ALIGN(16); + + .data : { + *(.data) + *(.data.*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + } + . = ALIGN(8); + + .jcr : { + KEEP (*(.jcr)) + } + + _gp = ALIGN(16) + 0x8000; + __global = _gp; + + .sdata : { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s*) + } + .lit8 : { + *(.lit8) + } + .lit4 : { + *(.lit4) + } + + edata = .; + _edata = .; + _fbss = .; + + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + _bss_start = . ; + *(.bss) + *(COMMON) + . = ALIGN (64); + _stack_limit = .; + . += _StackSize; + __stack = .; + _stack_init = .; + end = .; + _end = .; + WorkAreaBase = .; + } + + + /* Debug sections. These should never be loadable, but they must have + zero addresses for the debuggers to work correctly. */ + .line 0 : { *(.line) } + .debug 0 : { *(.debug) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/bsps/mips/shared/start/idtmem.S b/bsps/mips/shared/start/idtmem.S new file mode 100644 index 0000000000..ed51e67362 --- /dev/null +++ b/bsps/mips/shared/start/idtmem.S @@ -0,0 +1,920 @@ +/* + +Based upon IDT provided code with the following release: + +This source code has been made available to you by IDT on an AS-IS +basis. Anyone receiving this source is licensed under IDT copyrights +to use it in any way he or she deems fit, including copying it, +modifying it, compiling it, and redistributing it either with or +without modifications. No license under IDT patents or patent +applications is to be implied by the copyright license. + +Any user of this software should understand that IDT cannot provide +technical support for this software and will not be responsible for +any consequences resulting from the use of this software. + +Any person who transfers this source code or any derivative work must +include the IDT copyright notice, this paragraph, and the preceeding +two paragraphs in the transferred software. + +COPYRIGHT IDT CORPORATION 1996 +LICENSED MATERIAL - PROGRAM PROPERTY OF IDT + +*/ + +/************************************************************************ +** +** idtmem.s - memory and cache functions +** +** Copyright 1991 Integrated Device Technology, Inc. +** All Rights Reserved +** +**************************************************************************/ + +/* + * 950313: Ketan fixed bugs in mfc0/mtc0 hazards, and removed hack + * to set mem_size. + */ + +#include <rtems/mips/iregdef.h> +#include <rtems/mips/idtcpu.h> +#include <rtems/asm.h> + + .data +mem_size: + .word 0 +dcache_size: + .word 0 +icache_size: +#if __mips == 1 + .word MINCACHE +#endif +#if __mips == 3 + .word 0 +#endif + +#if __mips == 3 + .data +scache_size: + .word 0 +icache_linesize: + .word 0 +dcache_linesize: + .word 0 +scache_linesize: + .word 0 +#endif + + .text + +#if __mips == 1 +#define CONFIGFRM ((2*4)+4) + +/************************************************************************* +** +** Config_Dcache() -- determine size of Data cache +** +**************************************************************************/ + +FRAME(config_Dcache,sp, CONFIGFRM, ra) + .set noreorder + subu sp,CONFIGFRM + sw ra,CONFIGFRM-4(sp) /* save return address */ + sw s0,4*4(sp) /* save s0 in first regsave slot */ + mfc0 s0,C0_SR /* save SR */ + nop + mtc0 zero,C0_SR /* disable interrupts */ + .set reorder + jal _size_cache /* returns Data cache size in v0 */ + sw v0, dcache_size /* save it */ + and s0, ~SR_PE /* do not clear PE */ + .set noreorder + mtc0 s0,C0_SR /* restore SR */ + nop + .set reorder + lw s0, 4*4(sp) /* restore s0 */ + lw ra,CONFIGFRM-4(sp) /* restore ra */ + addu sp,CONFIGFRM /* pop stack */ + j ra +ENDFRAME(config_Dcache) + +/************************************************************************* +** +** Config_Icache() -- determine size of Instruction cache +** MUST be run in uncached mode/handled in idt_csu.s +** +**************************************************************************/ + +FRAME(config_Icache,sp, CONFIGFRM, ra) + .set noreorder + subu sp,CONFIGFRM + sw ra,CONFIGFRM-4(sp) /* save return address */ + sw s0,4*4(sp) /* save s0 in first regsave slot */ + mfc0 s0,C0_SR /* save SR */ + nop + mtc0 zero, C0_SR /* disable interrupts */ + li v0,SR_SWC /* swap caches/disable ints */ + mtc0 v0,C0_SR + nop + .set reorder + jal _size_cache /* returns instruction cache size */ + .set noreorder + mtc0 zero,C0_SR /* swap back caches */ + nop + and s0,~SR_PE /* do not inadvertantly clear PE */ + mtc0 s0,C0_SR /* restore SR */ + nop + .set reorder + sw v0, icache_size /* save it AFTER caches back */ + lw s0,4*4(sp) /* restore s0 */ + lw ra,CONFIGFRM-4(sp) /* restore ra */ + addu sp,CONFIGFRM /* pop stack */ + j ra +ENDFRAME(config_Icache) + +/************************************************************************ +** +** _size_cache() +** returns cache size in v0 +** +************************************************************************/ + +FRAME(_size_cache,sp,0,ra) + .set noreorder + mfc0 t0,C0_SR /* save current sr */ + nop + and t0,~SR_PE /* do not inadvertently clear PE */ + or v0,t0,SR_ISC /* isolate cache */ + mtc0 v0,C0_SR + /* + * First check if there is a cache there at all + */ + move v0,zero + li v1,0xa5a5a5a5 /* distinctive pattern */ + sw v1,K0BASE /* try to write into cache */ + lw t1,K0BASE /* try to read from cache */ + nop + mfc0 t2,C0_SR + nop + .set reorder + and t2,SR_CM + bne t2,zero,3f /* cache miss, must be no cache */ + bne v1,t1,3f /* data not equal -> no cache */ + /* + * Clear cache size boundries to known state. + */ + li v0,MINCACHE +1: + sw zero,K0BASE(v0) + sll v0,1 + ble v0,MAXCACHE,1b + + li v0,-1 + sw v0,K0BASE(zero) /* store marker in cache */ + li v0,MINCACHE /* MIN cache size */ + +2: lw v1,K0BASE(v0) /* Look for marker */ + bne v1,zero,3f /* found marker */ + sll v0,1 /* cache size * 2 */ + ble v0,MAXCACHE,2b /* keep looking */ + move v0,zero /* must be no cache */ + .set noreorder +3: mtc0 t0,C0_SR /* restore sr */ + j ra + nop +ENDFRAME(_size_cache) + .set reorder + +#define FLUSHFRM (2*4) + +/*************************************************************************** +** +** flush_Dcache() - flush entire Data cache +** +****************************************************************************/ +FRAME(flush_Dcache,sp,FLUSHFRM,ra) + lw t2, dcache_size + .set noreorder + mfc0 t3,C0_SR /* save SR */ + nop + and t3,~SR_PE /* dont inadvertently clear PE */ + beq t2,zero,_Dflush_done /* no D cache, get out! */ + nop + li v0, SR_ISC /* isolate cache */ + mtc0 v0, C0_SR + nop + .set reorder + li t0,K0BASE /* set loop registers */ + or t1,t0,t2 + +2: sb zero,0(t0) + sb zero,4(t0) + sb zero,8(t0) + sb zero,12(t0) + sb zero,16(t0) + sb zero,20(t0) + sb zero,24(t0) + addu t0,32 + sb zero,-4(t0) + bne t0,t1,2b + + .set noreorder +_Dflush_done: + mtc0 t3,C0_SR /* restore Status Register */ + .set reorder + j ra +ENDFRAME(flush_Dcache) + +/*************************************************************************** +** +** flush_Icache() - flush entire Instruction cache +** +** NOTE: Icache can only be flushed/cleared when uncached +** Code forces into uncached memory regardless of calling mode +** +****************************************************************************/ +FRAME(flush_Icache,sp,FLUSHFRM,ra) + lw t1,icache_size + .set noreorder + mfc0 t3,C0_SR /* save SR */ + nop + la v0,1f + li v1,K1BASE + or v0,v1 + j v0 /* force into non-cached space */ + nop +1: + and t3,~SR_PE /* dont inadvertently clear PE */ + beq t1,zero,_Iflush_done /* no i-cache get out */ + nop + li v0,SR_ISC|SR_SWC /* disable intr, isolate and swap */ + mtc0 v0,C0_SR + li t0,K0BASE + .set reorder + or t1,t0,t1 + +1: sb zero,0(t0) + sb zero,4(t0) + sb zero,8(t0) + sb zero,12(t0) + sb zero,16(t0) + sb zero,20(t0) + sb zero,24(t0) + addu t0,32 + sb zero,-4(t0) + bne t0,t1,1b + .set noreorder +_Iflush_done: + mtc0 t3,C0_SR /* un-isolate, enable interrupts */ + .set reorder + j ra +ENDFRAME(flush_Icache) + +/************************************************************************** +** +** clear_Dcache(base_addr, byte_count) - flush portion of Data cache +** +** a0 = base address of portion to be cleared +** a1 = byte count of length +** +***************************************************************************/ +FRAME(clear_Dcache,sp,0,ra) + + lw t2, dcache_size /* Data cache size */ + .set noreorder + mfc0 t3,C0_SR /* save SR */ + nop + and t3,~SR_PE /* dont inadvertently clear PE */ + nop + nop + .set reorder + /* + * flush data cache + */ + + .set noreorder + nop + li v0,SR_ISC /* isolate data cache */ + mtc0 v0,C0_SR + .set reorder + bltu t2,a1,1f /* cache is smaller than region */ + move t2,a1 +1: addu t2,a0 /* ending address + 1 */ + move t0,a0 + +1: sb zero,0(t0) + sb zero,4(t0) + sb zero,8(t0) + sb zero,12(t0) + sb zero,16(t0) + sb zero,20(t0) + sb zero,24(t0) + addu t0,32 + sb zero,-4(t0) + bltu t0,t2,1b + + .set noreorder + mtc0 t3,C0_SR /* un-isolate, enable interrupts */ + nop + .set reorder + j ra +ENDFRAME(clear_Dcache) + +/************************************************************************** +** +** clear_Icache(base_addr, byte_count) - flush portion of Instruction cache +** +** a0 = base address of portion to be cleared +** a1 = byte count of length +** +** NOTE: Icache can only be flushed/cleared when uncached +** Code forces into uncached memory regardless of calling mode +** +***************************************************************************/ +FRAME(clear_Icache,sp,0,ra) + + lw t1, icache_size /* Instruction cache size */ + /* + * flush text cache + */ + .set noreorder + mfc0 t3,C0_SR /* save SR */ + nop + la v0,1f + li v1,K1BASE + or v0,v1 + j v0 /* force into non-cached space */ + nop +1: + and t3,~SR_PE /* dont inadvertently clear PE */ + nop + nop + li v0,SR_ISC|SR_SWC /* disable intr, isolate and swap */ + mtc0 v0,C0_SR + .set reorder + bltu t1,a1,1f /* cache is smaller than region */ + move t1,a1 +1: addu t1,a0 /* ending address + 1 */ + move t0,a0 + + sb zero,0(t0) + sb zero,4(t0) + sb zero,8(t0) + sb zero,12(t0) + sb zero,16(t0) + sb zero,20(t0) + sb zero,24(t0) + addu t0,32 + sb zero,-4(t0) + bltu t0,t1,1b + .set noreorder + mtc0 t3,C0_SR /* un-isolate, enable interrupts */ + nop + nop + nop /* allow time for caches to swap */ + .set reorder + j ra +ENDFRAME(clear_Icache) + +/************************************************************************** +** +** get_mem_conf - get memory configuration +** +***************************************************************************/ + +FRAME(get_mem_conf,sp,0,ra) + + lw t6, mem_size + sw t6, 0(a0) + lw t7, icache_size + sw t7, 4(a0) + lw t8, dcache_size + sw t8, 8(a0) + j ra + +ENDFRAME(get_mem_conf) +#endif /* __mips == 1 */ + +#if __mips == 3 +#define LEAF(label) FRAME(label,sp,0,ra) +#define XLEAF(label) \ + .globl label ; \ +label: + +/* + * cacheop macro to automate cache operations + * first some helpers... + */ +#define _mincache(size, maxsize) \ + bltu size,maxsize,8f ; \ + move size,maxsize ; \ +8: + +#define _align(tmp, minaddr, maxaddr, linesize) \ + subu tmp,linesize,1 ; \ + not tmp ; \ + and minaddr,tmp ; \ + addu maxaddr,-1 ; \ + and maxaddr,tmp + +/* This is a bit of a hack really because it relies on minaddr=a0 */ +#define _doop1(op1) \ + cache op1,0(a0) + +#define _doop2(op1, op2) \ + cache op1,0(a0) ; \ + cache op2,0(a0) + +/* specials for cache initialisation */ +#define _doop1lw1(op1) \ + cache op1,0(a0) ; \ + lw zero,0(a0) ; \ + cache op1,0(a0) + +#define _doop121(op1,op2) \ + cache op1,0(a0) ; \ + nop; \ + cache op2,0(a0) ; \ + nop; \ + cache op1,0(a0) + +#define _oploopn(minaddr, maxaddr, linesize, tag, ops) \ + .set noreorder ; \ +7: _doop##tag##ops ; \ + bne minaddr,maxaddr,7b ; \ + addu minaddr,linesize ; \ + .set reorder + +/* finally the cache operation macros */ +#define icacheopn(kva, n, cache_size, cache_linesize, tag, ops) \ + _mincache(n, cache_size); \ + blez n,9f ; \ + addu n,kva ; \ + _align(t1, kva, n, cache_linesize) ; \ + _oploopn(kva, n, cache_linesize, tag, ops) ; \ +9: + +#define vcacheopn(kva, n, cache_size, cache_linesize, tag, ops) \ + blez n,9f ; \ + addu n,kva ; \ + _align(t1, kva, n, cache_linesize) ; \ + _oploopn(kva, n, cache_linesize, tag, ops) ; \ +9: + +#define icacheop(kva, n, cache_size, cache_linesize, op) \ + icacheopn(kva, n, cache_size, cache_linesize, 1, (op)) + +#define vcacheop(kva, n, cache_size, cache_linesize, op) \ + vcacheopn(kva, n, cache_size, cache_linesize, 1, (op)) + + .text + +/* + * static void _size_cache() R4000 + * + * Internal routine to determine cache sizes by looking at R4000 config + * register. Sizes are returned in registers, as follows: + * t2 icache size + * t3 dcache size + * t6 scache size + * t4 icache line size + * t5 dcache line size + * t7 scache line size + */ +LEAF(_size_cache) + mfc0 t0,C0_CONFIG + + and t1,t0,CFG_ICMASK + srl t1,CFG_ICSHIFT + li t2,0x1000 + sll t2,t1 + + and t1,t0,CFG_DCMASK + srl t1,CFG_DCSHIFT + li t3,0x1000 + sll t3,t1 + + li t4,32 + and t1,t0,CFG_IB + bnez t1,1f + li t4,16 +1: + + li t5,32 + and t1,t0,CFG_DB + bnez t1,1f + li t5,16 +1: + + move t6,zero # default to no scache + move t7,zero # + + and t1,t0,CFG_C_UNCACHED # test config register + bnez t1,1f # no scache if uncached/non-coherent + + li t6,0x100000 # assume 1Mb scache <<-NOTE + and t1,t0,CFG_SBMASK + srl t1,CFG_SBSHIFT + li t7,16 + sll t7,t1 +1: j ra +ENDFRAME(_size_cache) + +/* + * void config_cache() R4000 + * + * Work out size of I, D & S caches, assuming they are already initialised. + */ +LEAF(config_cache) + lw t0,icache_size + bgtz t0,8f # already known? + move v0,ra + bal _size_cache + move ra,v0 + + sw t2,icache_size + sw t3,dcache_size + sw t6,scache_size + sw t4,icache_linesize + sw t5,dcache_linesize + sw t7,scache_linesize +8: j ra +ENDFRAME(config_cache) + +/* + * void _init_cache() R4000 + */ +LEAF(_init_cache) + /* + * First work out the sizes + */ + move v0,ra + bal _size_cache + move ra,v0 + + /* + * The caches may be in an indeterminate state, + * so we force good parity into them by doing an + * invalidate, load/fill, invalidate for each line. + */ + + /* disable all i/u and cache exceptions */ + mfc0 v0,C0_SR + and v1,v0,~SR_IE + or v1,SR_DE + mtc0 v1,C0_SR + + mtc0 zero,C0_TAGLO + mtc0 zero,C0_TAGHI + + /* assume bottom of RAM will generate good parity for the cache */ + li a0,PHYS_TO_K0(0) + move a2,t2 # icache_size + move a3,t4 # icache_linesize + move a1,a2 + icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill_I)) + + li a0,PHYS_TO_K0(0) + move a2,t3 # dcache_size + move a3,t5 # dcache_linesize + move a1,a2 + icacheopn(a0,a1,a2,a3,1lw1,(Index_Store_Tag_D)) + + /* assume unified I & D in scache <<-NOTE */ + blez t6,1f + li a0,PHYS_TO_K0(0) + move a2,t6 + move a3,t7 + move a1,a2 + icacheopn(a0,a1,a2,a3,1lw1,(Index_Store_Tag_SD)) + +1: mtc0 v0,C0_SR + j ra +ENDFRAME(_init_cache) + +/* + * void flush_cache (void) R4000 + * + * Flush and invalidate all caches + */ +LEAF(flush_cache) + /* secondary cacheops do all the work if present */ + lw a2,scache_size + blez a2,1f + lw a3,scache_linesize + li a0,PHYS_TO_K0(0) + move a1,a2 + icacheop(a0,a1,a2,a3,Index_Writeback_Inv_SD) + b 2f + +1: + lw a2,icache_size + blez a2,2f + lw a3,icache_linesize + li a0,PHYS_TO_K0(0) + move a1,a2 + icacheop(a0,a1,a2,a3,Index_Invalidate_I) + + lw a2,dcache_size + lw a3,dcache_linesize + li a0,PHYS_TO_K0(0) + move a1,a2 + icacheop(a0,a1,a2,a3,Index_Writeback_Inv_D) + +2: j ra +ENDFRAME(flush_cache) + +/* + * void flush_cache_nowrite (void) R4000 + * + * Invalidate all caches + */ +LEAF(flush_cache_nowrite) + mfc0 v0,C0_SR + and v1,v0,~SR_IE + mtc0 v1,C0_SR + + mtc0 zero,C0_TAGLO + mtc0 zero,C0_TAGHI + + lw a2,icache_size + blez a2,2f + lw a3,icache_linesize + li a0,PHYS_TO_K0(0) + move a1,a2 + icacheop(a0,a1,a2,a3,Index_Invalidate_I) + + lw a2,dcache_size + lw a3,dcache_linesize + li a0,PHYS_TO_K0(0) + move a1,a2 + icacheop(a0,a1,a2,a3,Index_Store_Tag_D) + + lw a2,scache_size + blez a2,2f + lw a3,scache_linesize + li a0,PHYS_TO_K0(0) + move a1,a2 + icacheop(a0,a1,a2,a3,Index_Store_Tag_SD) + +2: mtc0 v0,C0_SR + j ra +ENDFRAME(flush_cache_nowrite) + +/* + * void clean_cache (unsigned kva, size_t n) R4000 + * + * Writeback and invalidate address range in all caches + */ +LEAF(clean_cache) +XLEAF(clear_cache) + + /* secondary cacheops do all the work (if fitted) */ + lw a2,scache_size + blez a2,1f + lw a3,scache_linesize + vcacheop(a0,a1,a2,a3,Hit_Writeback_Inv_SD) + b 2f + +1: lw a2,icache_size + blez a2,2f + lw a3,icache_linesize + /* save kva & n for subsequent loop */ + move t8,a0 + move t9,a1 + vcacheop(a0,a1,a2,a3,Hit_Invalidate_I) + + lw a2,dcache_size + lw a3,dcache_linesize + /* restore kva & n */ + move a0,t8 + move a1,t9 + vcacheop(a0,a1,a2,a3,Hit_Writeback_Inv_D) + +2: j ra +ENDFRAME(clean_cache) + +/* + * void clean_dcache (unsigned kva, size_t n) R4000 + * + * Writeback and invalidate address range in primary data cache + */ +LEAF(clean_dcache) + lw a2,dcache_size + blez a2,2f + lw a3,dcache_linesize + + vcacheop(a0,a1,a2,a3,Hit_Writeback_Inv_D) + +2: j ra +ENDFRAME(clean_dcache) + +/* + * void clean_dcache_indexed (unsigned kva, size_t n) R4000 + * + * Writeback and invalidate indexed range in primary data cache + */ +LEAF(clean_dcache_indexed) + lw a2,dcache_size + blez a2,2f + lw a3,dcache_linesize + +#ifdef CPU_ORION + srl a2,1 # do one set (half cache) at a time + move t8,a0 # save kva & n + move t9,a1 + icacheop(a0,a1,a2,a3,Index_Writeback_Inv_D) + + addu a0,t8,a2 # do next set + move a1,t9 # restore n +#endif + icacheop(a0,a1,a2,a3,Index_Writeback_Inv_D) + +2: j ra +ENDFRAME(clean_dcache_indexed) + +/* + * void clean_dcache_nowrite (unsigned kva, size_t n) R4000 + * + * Invalidate an address range in primary data cache + */ +LEAF(clean_dcache_nowrite) + lw a2,dcache_size + blez a2,2f + lw a3,dcache_linesize + + vcacheop(a0,a1,a2,a3,Hit_Invalidate_D) + +2: j ra +ENDFRAME(clean_dcache_nowrite) + +/* + * void clean_dcache_nowrite_indexed (unsigned kva, size_t n) R4000 + * + * Invalidate indexed range in primary data cache + */ +LEAF(clean_dcache_nowrite_indexed) + mfc0 v0,C0_SR + and v1,v0,~SR_IE + mtc0 v1,C0_SR + + mtc0 zero,C0_TAGLO + mtc0 zero,C0_TAGHI + + lw a2,dcache_size + blez a2,2f + lw a3,dcache_linesize + +#ifdef CPU_ORION + srl a2,1 # do one set (half cache) at a time + move t8,a0 # save kva & n + move t9,a1 + icacheop(a0,a1,a2,a3,Index_Store_Tag_D) + + addu a0,t8,a2 # do next set + move a1,t9 # restore n +#endif + icacheop(a0,a1,a2,a3,Index_Store_Tag_D) + +2: mtc0 v0,C0_SR + j ra +ENDFRAME(clean_dcache_nowrite_indexed) + +/* + * void clean_icache (unsigned kva, size_t n) R4000 + * + * Invalidate address range in primary instruction cache + */ +LEAF(clean_icache) + lw a2,icache_size + blez a2,2f + lw a3,icache_linesize + + vcacheop(a0,a1,a2,a3,Hit_Invalidate_I) + +2: j ra +ENDFRAME(clean_icache) + +/* + * void clean_icache_indexed (unsigned kva, size_t n) R4000 + * + * Invalidate indexed range in primary instruction cache + */ +LEAF(clean_icache_indexed) + lw a2,icache_size + blez a2,2f + lw a3,icache_linesize + +#ifdef CPU_ORION + srl a2,1 # do one set (half cache) at a time + move t8,a0 # save kva & n + move t9,a1 + icacheop(a0,a1,a2,a3,Index_Invalidate_I) + + addu a0,t8,a2 # do next set + move a1,t9 # restore n +#endif + icacheop(a0,a1,a2,a3,Index_Invalidate_I) + +2: j ra +ENDFRAME(clean_icache_indexed) + +/* + * void clean_scache (unsigned kva, size_t n) R4000 + * + * Writeback and invalidate address range in secondary cache + */ +LEAF(clean_scache) + lw a2,scache_size + blez a2,2f + lw a3,scache_linesize + vcacheop(a0,a1,a2,a3,Hit_Writeback_Inv_SD) + +2: j ra +ENDFRAME(clean_scache) + +/* + * void clean_scache_indexed (unsigned kva, size_t n) R4000 + * + * Writeback and invalidate indexed range in secondary cache + */ +LEAF(clean_scache_indexed) + lw a2,scache_size + blez a2,2f + lw a3,scache_linesize + + icacheop(a0,a1,a2,a3,Index_Writeback_Inv_SD) + +2: j ra +ENDFRAME(clean_scache_indexed) + +/* + * void clean_scache_nowrite (unsigned kva, size_t n) R4000 + * + * Invalidate an address range in secondary cache + */ +LEAF(clean_scache_nowrite) + lw a2,scache_size + blez a2,2f + lw a3,scache_linesize + + vcacheop(a0,a1,a2,a3,Hit_Invalidate_SD) + +2: j ra +ENDFRAME(clean_scache_nowrite) + +/* + * void clean_scache_nowrite_indexed (unsigned kva, size_t n) R4000 + * + * Invalidate indexed range in secondary cache + */ +LEAF(clean_scache_nowrite_indexed) + mfc0 v0,C0_SR + and v1,v0,~SR_IE + mtc0 v1,C0_SR + + mtc0 zero,C0_TAGLO + mtc0 zero,C0_TAGHI + + lw a2,scache_size + blez a2,2f + lw a3,scache_linesize + + icacheop(a0,a1,a2,a3,Index_Store_Tag_SD) + +2: mtc0 v0,C0_SR + j ra +ENDFRAME(clean_scache_nowrite_indexed) + +/************************************************************************** +** +** get_mem_conf - get memory configuration R4000 +** +***************************************************************************/ + +FRAME(get_mem_conf,sp,0,ra) + + lw t6, mem_size + sw t6, 0(a0) + lw t7, icache_size + sw t7, 4(a0) + lw t8, dcache_size + sw t8, 8(a0) + lw t7, scache_size + sw t7, 12(a0) + j ra + +ENDFRAME(get_mem_conf) + +#endif /* __mips == 3 */ + +/* + * void set_mem_size (mem_size) + * + * config_memory()'s memory size gets written into mem_size here. + * Now we don't need to call config_cache() with memory size - New to IDTC6.0 + */ +FRAME(set_memory_size,sp,0,ra) + sw a0, mem_size + j ra +ENDFRAME(set_memory_size) diff --git a/bsps/mips/shared/start/idttlb.S b/bsps/mips/shared/start/idttlb.S new file mode 100644 index 0000000000..2574027dc9 --- /dev/null +++ b/bsps/mips/shared/start/idttlb.S @@ -0,0 +1,388 @@ +/* + +Based upon IDT provided code with the following release: + +This source code has been made available to you by IDT on an AS-IS +basis. Anyone receiving this source is licensed under IDT copyrights +to use it in any way he or she deems fit, including copying it, +modifying it, compiling it, and redistributing it either with or +without modifications. No license under IDT patents or patent +applications is to be implied by the copyright license. + +Any user of this software should understand that IDT cannot provide +technical support for this software and will not be responsible for +any consequences resulting from the use of this software. + +Any person who transfers this source code or any derivative work must +include the IDT copyright notice, this paragraph, and the preceeding +two paragraphs in the transferred software. + +COPYRIGHT IDT CORPORATION 1996 +LICENSED MATERIAL - PROGRAM PROPERTY OF IDT +*/ + + +/* +** idttlb.s - fetch the registers associated with and the contents +** of the tlb. +** +*/ +/* 950308: Ketan patched a few tlb functions that would not have worked.*/ +#include <rtems/mips/iregdef.h> +#include <rtems/mips/idtcpu.h> +#include <rtems/asm.h> + + + .text + +#if __mips == 1 +/* +** ret_tlblo -- returns the 'entrylo' contents for the TLB +** 'c' callable - as ret_tlblo(index) - where index is the +** tlb entry to return the lo value for - if called from assembly +** language then index should be in register a0. +*/ +FRAME(ret_tlblo,sp,0,ra) + .set noreorder + mfc0 t0,C0_SR # save sr + nop + and t0,~SR_PE # dont inadvertantly clear PE + mtc0 zero,C0_SR # clear interrupts + mfc0 t1,C0_TLBHI # save pid + sll a0,TLBINX_INXSHIFT # position index + mtc0 a0,C0_INX # write to index register + nop + tlbr # put tlb entry in entrylo and hi + nop + mfc0 v0,C0_TLBLO # get the requested entry lo + mtc0 t1,C0_TLBHI # restore pid + mtc0 t0,C0_SR # restore status register + j ra + nop + .set reorder +ENDFRAME(ret_tlblo) +#endif +#if __mips == 3 +/* +** ret_tlblo[01] -- returns the 'entrylo' contents for the TLB +** 'c' callable - as ret_tlblo(index) - where index is the +** tlb entry to return the lo value for - if called from assembly +** language then index should be in register a0. +*/ +FRAME(ret_tlblo0,sp,0,ra) + mfc0 t0,C0_SR # save sr + mtc0 zero,C0_SR # clear interrupts + mfc0 t1,C0_TLBHI # save pid + mtc0 a0,C0_INX # write to index register + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + tlbr # put tlb entry in entrylo and hi + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + mfc0 v0,C0_TLBLO0 # get the requested entry lo + mtc0 t1,C0_TLBHI # restore pid + mtc0 t0,C0_SR # restore status register + j ra +ENDFRAME(ret_tlblo0) + +FRAME(ret_tlblo1,sp,0,ra) + mfc0 t0,C0_SR # save sr + mtc0 zero,C0_SR # clear interrupts + mfc0 t1,C0_TLBHI # save pid + mtc0 a0,C0_INX # write to index register + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + tlbr # put tlb entry in entrylo and hi + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + mfc0 v0,C0_TLBLO1 # get the requested entry lo + mtc0 t1,C0_TLBHI # restore pid + mtc0 t0,C0_SR # restore status register + j ra +ENDFRAME(ret_tlblo1) + +/* +** ret_pagemask(index) -- return pagemask contents of tlb entry "index" +*/ +FRAME(ret_pagemask,sp,0,ra) + mfc0 t0,C0_SR # save sr + mtc0 zero,C0_SR # disable interrupts + mfc0 t1,C0_TLBHI # save current pid + mtc0 a0,C0_INX # drop it in C0 register + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + tlbr # read entry to entry hi/lo + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + mfc0 v0,C0_PAGEMASK # to return value + mtc0 t1,C0_TLBHI # restore current pid + mtc0 t0,C0_SR # restore sr + j ra +ENDFRAME(ret_pagemask) + +/* +** ret_tlbwired(void) -- return wired register +*/ +FRAME(ret_tlbwired,sp,0,ra) + mfc0 v0,C0_WIRED + j ra +ENDFRAME(ret_tlbwired) +#endif + +/* +** ret_tlbhi -- return the tlb entry high content for tlb entry +** index +*/ +FRAME(ret_tlbhi,sp,0,ra) +#if __mips == 1 + .set noreorder + mfc0 t0,C0_SR # save sr + nop + and t0,~SR_PE + mtc0 zero,C0_SR # disable interrupts + mfc0 t1,C0_TLBHI # save current pid + sll a0,TLBINX_INXSHIFT # position index + mtc0 a0,C0_INX # drop it in C0 register + nop + tlbr # read entry to entry hi/lo + nop + mfc0 v0,C0_TLBHI # to return value + mtc0 t1,C0_TLBHI # restore current pid + mtc0 t0,C0_SR # restore sr + j ra + nop + .set reorder +#endif +#if __mips == 3 + mfc0 t0,C0_SR # save sr + mtc0 zero,C0_SR # disable interrupts + mfc0 t1,C0_TLBHI # save current pid + mtc0 a0,C0_INX # drop it in C0 register + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + tlbr # read entry to entry hi/lo0/lo1/mask + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + mfc0 v0,C0_TLBHI # to return value + mtc0 t1,C0_TLBHI # restore current pid + mtc0 t0,C0_SR # restore sr + j ra +#endif +ENDFRAME(ret_tlbhi) + +/* +** ret_tlbpid() -- return tlb pid contained in the current entry hi +*/ +FRAME(ret_tlbpid,sp,0,ra) +#if __mips == 1 + .set noreorder + mfc0 v0,C0_TLBHI # fetch tlb high + nop + and v0,TLBHI_PIDMASK # isolate and position + srl v0,TLBHI_PIDSHIFT + j ra + nop + .set reorder +#endif +#if __mips == 3 + mfc0 v0,C0_TLBHI # to return value + nop + and v0,TLBHI_PIDMASK + j ra +#endif +ENDFRAME(ret_tlbpid) + +/* +** tlbprobe(address, pid) -- probe the tlb to see if address is currently +** mapped +** a0 = vpn - virtual page numbers are 0=0 1=0x1000, 2=0x2000... +** virtual page numbers for the r3000 are in +** entry hi bits 31-12 +** a1 = pid - this is a process id ranging from 0 to 63 +** this process id is shifted left 6 bits and or'ed into +** the entry hi register +** returns an index value (0-63) if successful -1 -f not +*/ +FRAME(tlbprobe,sp,0,ra) +#if __mips == 1 + .set noreorder + mfc0 t0,C0_SR /* fetch status reg */ + and a0,TLBHI_VPNMASK /* isolate just the vpn */ + and t0,~SR_PE /* don't inadvertantly clear pe */ + mtc0 zero,C0_SR + mfc0 t1,C0_TLBHI + sll a1,TLBHI_PIDSHIFT /* possition the pid */ + and a1,TLBHI_PIDMASK + or a0,a1 /* build entry hi value */ + mtc0 a0,C0_TLBHI + nop + tlbp /* do the probe */ + nop + mfc0 v1,C0_INX + li v0,-1 + bltz v1,1f + nop + sra v0,v1,TLBINX_INXSHIFT /* get index positioned for return */ +1: + mtc0 t1,C0_TLBHI /* restore tlb hi */ + mtc0 t0,C0_SR /* restore the status reg */ + j ra + nop + .set reorder +#endif +#if __mips == 3 + mfc0 t0,C0_SR # save sr + mtc0 zero,C0_SR # disable interrupts + mfc0 t1,C0_TLBHI # save current pid + and a0,TLBHI_VPN2MASK # construct tlbhi for probe + and a1,TLBHI_PIDMASK + or a0,a1 + mtc0 a0,C0_TLBHI + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + tlbp # probe entry to entry hi/lo0/lo1/mask + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + mfc0 v1,C0_INX + li v0,-1 + bltz v1,1f + move v0,v1 +1: mtc0 t1,C0_TLBHI # restore current pid + mtc0 t0,C0_SR # restore sr + j ra +#endif +ENDFRAME(tlbprobe) + +/* +** resettlb(index) Invalidate the TLB entry specified by index +*/ +FRAME(resettlb,sp,0,ra) +#if __mips == 1 + .set noreorder + mfc0 t0,C0_TLBHI # fetch the current hi + mfc0 v0,C0_SR # fetch the status reg. + li t2,K0BASE&TLBHI_VPNMASK + and v0,~SR_PE # dont inadvertantly clear PE + mtc0 zero,C0_SR + mtc0 t2,C0_TLBHI # set up tlbhi + mtc0 zero,C0_TLBLO + sll a0,TLBINX_INXSHIFT + mtc0 a0,C0_INX + nop + tlbwi # do actual invalidate + nop + mtc0 t0,C0_TLBHI + mtc0 v0,C0_SR + j ra + nop + .set reorder +#endif +#if __mips == 3 + li t2,K0BASE&TLBHI_VPN2MASK + mfc0 t0,C0_TLBHI # save current TLBHI + mfc0 v0,C0_SR # save SR and disable interrupts + mtc0 zero,C0_SR + mtc0 t2,C0_TLBHI # invalidate entry + mtc0 zero,C0_TLBLO0 + mtc0 zero,C0_TLBLO1 + mtc0 a0,C0_INX + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + tlbwi + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + mtc0 t0,C0_TLBHI + mtc0 v0,C0_SR + j ra +#endif +ENDFRAME(resettlb) + +#if __mips == 1 +/* +** Setup TLB entry +** +** map_tlb(index, tlbhi, phypage) +** a0 = TLB entry index +** a1 = virtual page number and PID +** a2 = physical page +*/ +FRAME(map_tlb,sp,0,ra) + .set noreorder + sll a0,TLBINX_INXSHIFT + mfc0 v0,C0_SR # fetch the current status + mfc0 a3,C0_TLBHI # save the current hi + and v0,~SR_PE # dont inadvertantly clear parity + + mtc0 zero,C0_SR + mtc0 a1,C0_TLBHI # set the hi entry + mtc0 a2,C0_TLBLO # set the lo entry + mtc0 a0,C0_INX # load the index + nop + tlbwi # put the hi/lo in tlb entry indexed + nop + mtc0 a3,C0_TLBHI # put back the tlb hi reg + mtc0 v0,C0_SR # restore the status register + j ra + nop + .set reorder +ENDFRAME(map_tlb) +#endif +#if __mips == 3 +/* +** Setup R4000 TLB entry +** +** map_tlb4000(mask_index, tlbhi, pte_even, pte_odd) +** a0 = TLB entry index and page mask +** a1 = virtual page number and PID +** a2 = pte -- contents of even pte +** a3 = pte -- contents of odd pte +*/ +FRAME(map_tlb4000,sp,0,ra) + and t2,a0,TLBPGMASK_MASK + and a0,TLBINX_INXMASK + mfc0 t1,C0_TLBHI # save current TLBPID + mfc0 v0,C0_SR # save SR and disable interrupts + mtc0 zero,C0_SR + mtc0 t2,C0_PAGEMASK # set + mtc0 a1,C0_TLBHI # set VPN and TLBPID + mtc0 a2,C0_TLBLO0 # set PPN and access bits + mtc0 a3,C0_TLBLO1 # set PPN and access bits + mtc0 a0,C0_INX # set INDEX to wired entry + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + tlbwi # drop it in + .set noreorder + nop; nop; nop; nop; nop; nop; nop; nop + .set reorder + mtc0 t1,C0_TLBHI # restore TLBPID + mtc0 v0,C0_SR # restore SR + j ra +ENDFRAME(map_tlb4000) +#endif + + +/* +** Set current TLBPID. This assumes PID is positioned correctly in reg. +** a0. +*/ +FRAME(set_tlbpid,sp,0,ra) + .set noreorder + mtc0 a0,C0_TLBHI + j ra + nop + .set reorder +ENDFRAME(set_tlbpid) + diff --git a/bsps/moxie/moxiesim/start/bsp_specs b/bsps/moxie/moxiesim/start/bsp_specs new file mode 100644 index 0000000000..afa9f6badb --- /dev/null +++ b/bsps/moxie/moxiesim/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{!nostdlib: %{qrtems: crtend.o%s}} diff --git a/bsps/moxie/moxiesim/start/linkcmds b/bsps/moxie/moxiesim/start/linkcmds new file mode 100644 index 0000000000..a4d9edac11 --- /dev/null +++ b/bsps/moxie/moxiesim/start/linkcmds @@ -0,0 +1,269 @@ +/* + * The common part of the default linker scripts for standalone + * executables running on a Moxie processor. + * + * Copyright (C) 2008 Anthony Green + * + * The authors hereby grant permission to use, copy, modify, + * distribute, and license this software and its documentation for any + * purpose, provided that existing copyright notices are retained in + * all copies and that this notice is included verbatim in any + * distributions. No written agreement, license, or royalty fee is + * required for any of the authorized uses. Modifications to this + * software may be copyrighted by their authors and need not follow + * the licensing terms described here, provided that the new terms are + * clearly indicated on the first page of each file where they apply. + */ + +OUTPUT_FORMAT("elf32-bigmoxie") +OUTPUT_ARCH(moxie) +ENTRY(_start) +STARTUP(start.o) + +RamBase = DEFINED(RamBase) ? RamBase : 0x00000000; +RamSize = DEFINED(RamSize) ? RamSize : 16M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; + +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0x00001000; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.text : + { + *(.rel.text) + *(.rel.text.*) + *(.rel.gnu.linkonce.t*) + } + .rela.text : + { + *(.rela.text) + *(.rela.text.*) + *(.rela.gnu.linkonce.t*) + } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.rodata : + { + *(.rel.rodata) + *(.rel.rodata.*) + *(.rel.gnu.linkonce.r*) + } + .rela.rodata : + { + *(.rela.rodata) + *(.rela.rodata.*) + *(.rela.gnu.linkonce.r*) + } + .rel.data : + { + *(.rel.data) + *(.rel.data.*) + *(.rel.gnu.linkonce.d*) + } + .rela.data : + { + *(.rela.data) + *(.rela.data.*) + *(.rela.gnu.linkonce.d*) + } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.sdata : + { + *(.rel.sdata) + *(.rel.sdata.*) + *(.rel.gnu.linkonce.s*) + } + .rela.sdata : + { + *(.rela.sdata) + *(.rela.sdata.*) + *(.rela.gnu.linkonce.s*) + } + .rel.sbss : { *(.rel.sbss) } + .rela.sbss : { *(.rela.sbss) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .plt : { *(.plt) } + .text : + { + *(.text) + *(.text.*) + *(.stub) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + *(.glue_7t) *(.glue_7) + } =0 + .init : + { + KEEP (*(.init)) + } =0 + _etext = .; + PROVIDE (etext = .); + .fini : + { + KEEP (*(.fini)) + } =0 + .rodata : { *(.rodata) *(.rodata.*) KEEP (*(SORT(.rtemsroset.*))) *(.gnu.linkonce.r*) } + .rodata1 : { *(.rodata1) } + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } + _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)); + .eh_frame_hdr : { *(.eh_frame_hdr) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(256) + (. & (256 - 1)); + .data : + { + *(.data) + *(.data.*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table) } + .ctors : + { + /* 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)) + /* We don't want to include the .ctor section from + 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 ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .got : { *(.got.plt) *(.got) } + .dynamic : { *(.dynamic) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : + { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + __bss_start__ = .; + .sbss : + { + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.scommon) + } + .bss : + { + *(.dynbss) + *(.bss) + *(.bss.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(32 / 8); + } + . = ALIGN(32 / 8); + _end = .; + _bss_end__ = . ; __bss_end__ = . ; __end__ = . ; + PROVIDE (end = .); + WorkAreaBase = .; + /* 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) } + .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) } + .debug_ranges 0 : { *(.debug_ranges) } + /* 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) } + .stack 0x400000 : { _stack = .; *(.stack) } + /* These must appear regardless of . */ +} diff --git a/bsps/nios2/nios2_iss/start/bsp_specs b/bsps/nios2/nios2_iss/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/nios2/nios2_iss/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/nios2/nios2_iss/start/bspstart.c b/bsps/nios2/nios2_iss/start/bspstart.c new file mode 100644 index 0000000000..c619e583ae --- /dev/null +++ b/bsps/nios2/nios2_iss/start/bspstart.c @@ -0,0 +1,31 @@ +/* + * This routine starts the application. 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) 2005-2006 Kolja Waschk rtemsdev/ixo.de + * Derived from no_cpu/no_bsp/startup/bspstart.c 1.23. + * COPYRIGHT (c) 1989-1999. + * 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 <sys/cdefs.h> + +#include <bsp.h> +#include <rtems/score/nios2-utility.h> +#include <bsp/bootcard.h> + +void bsp_start( void ) +{ + __asm__ volatile ( + ".globl _Nios2_ISR_Status_mask\n" + ".globl _Nios2_ISR_Status_bits\n" + ".set _Nios2_ISR_Status_mask, " __XSTRING(NIOS2_ISR_STATUS_MASK_IIC) "\n" + ".set _Nios2_ISR_Status_bits, " __XSTRING(NIOS2_ISR_STATUS_BITS_IIC) + ); +} diff --git a/bsps/nios2/nios2_iss/start/linkcmds b/bsps/nios2/nios2_iss/start/linkcmds new file mode 100644 index 0000000000..c08c37628a --- /dev/null +++ b/bsps/nios2/nios2_iss/start/linkcmds @@ -0,0 +1,362 @@ +/* generated.x + * + * Machine generated for a CPU named "cpu_0" as defined in: + * D:\eb2_nios2\kawkos.ptf + * + * Generated: 2005-07-10 11:52:46.899 + * + */ + +/* + +DO NOT MODIFY THIS FILE + + Changing this file will have subtle consequences + which will almost certainly lead to a nonfunctioning + system. If you do modify this file, be aware that your + changes will be overwritten and lost when this file + is generated again. + +DO NOT MODIFY THIS FILE + +*/ + +RamBase = DEFINED(RamBase) ? RamBase : 0x00000000; +RamSize = DEFINED(RamSize) ? RamSize : 0x00800000; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +StackSize = DEFINED(StackSize) ? HeapSize : 1024; + +MEMORY +{ + reset : ORIGIN = 0x00000000, LENGTH = 0x00000600 + exceptions : ORIGIN = 0x00000600, LENGTH = 0x00000A00 + onchip_memory_0 : ORIGIN = 0x00001000, LENGTH = 0x007FF000 +} + + /* Define symbols for each memory base-address */ + __alt_mem_onchip_memory_0 = 0x00000000 ; + + __nios2_icache_size = 4096 ; + __nios2_icache_line_size = 32 ; + __nios2_dcache_size = 0 ; + __nios2_dcache_line_size = 4 ; + +OUTPUT_FORMAT( "elf32-littlenios2", + "elf32-littlenios2", + "elf32-littlenios2" ) +OUTPUT_ARCH( nios2 ) +ENTRY(start) +STARTUP(start.o) + +/* Do we need any of these for elf? + __DYNAMIC = 0; + */ + +SECTIONS +{ + .entry : + { + KEEP (*(.entry)) + } > reset + + .exceptions : + { + PROVIDE (__ram_exceptions_start = ABSOLUTE(.)); + . = ALIGN(0x20); + *(.irq) + KEEP (*(.exceptions.entry.label)); + KEEP (*(.exceptions.entry.user)); + KEEP (*(.exceptions.entry)); + KEEP (*(.exceptions.irqtest.user)); + KEEP (*(.exceptions.irqtest)); + KEEP (*(.exceptions.irqhandler.user)); + KEEP (*(.exceptions.irqhandler)); + KEEP (*(.exceptions.irqreturn.user)); + KEEP (*(.exceptions.irqreturn)); + KEEP (*(.exceptions.notirq.label)); + KEEP (*(.exceptions.notirq.user)); + KEEP (*(.exceptions.notirq)); + KEEP (*(.exceptions.soft.user)); + KEEP (*(.exceptions.soft)); + KEEP (*(.exceptions.unknown.user)); + KEEP (*(.exceptions.unknown)); + KEEP (*(.exceptions.exit.label)); + KEEP (*(.exceptions.exit.user)); + KEEP (*(.exceptions.exit)); + KEEP (*(.exceptions)); + PROVIDE (__ram_exceptions_end = ABSOLUTE(.)); + } > exceptions + + PROVIDE (__flash_exceptions_start = LOADADDR(.exceptions)); + + .text : + { + /* + * All code sections are merged into the text output section, along with + * the read only data sections. + * + */ + + PROVIDE (stext = ABSOLUTE(.)); + + *(.interp) + *(.hash) + *(.dynsym) + *(.dynstr) + *(.gnu.version) + *(.gnu.version_d) + *(.gnu.version_r) + *(.rel.init) + *(.rela.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rel.fini) + *(.rela.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rela.ctors) + *(.rel.dtors) + *(.rela.dtors) + *(.rel.got) + *(.rela.got) + *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rel.plt) + *(.rela.plt) + + KEEP (*(.init)) + *(.plt) + *(.text .stub .text.* .gnu.linkonce.t.*) + + /* Special FreeBSD sysctl sections. */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + +/* .gnu.warning sections are handled specially by elf32.em. */ + + *(.gnu.warning.*) + KEEP (*(.fini)) + PROVIDE (__etext = ABSOLUTE(.)); + PROVIDE (_etext = ABSOLUTE(.)); + PROVIDE (etext = ABSOLUTE(.)); + + *(.eh_frame_hdr) + /* Ensure the __preinit_array_start label is properly aligned. We + could instead move the label definition inside the section, but + the linker would then create the section even if it turns out to + be empty, which isn't pretty. */ + . = ALIGN(32 / 8); + PROVIDE (__preinit_array_start = ABSOLUTE(.)); + *(.preinit_array) + PROVIDE (__preinit_array_end = ABSOLUTE(.)); + PROVIDE (__init_array_start = ABSOLUTE(.)); + *(.init_array) + PROVIDE (__init_array_end = ABSOLUTE(.)); + PROVIDE (__fini_array_start = ABSOLUTE(.)); + *(.fini_array) + PROVIDE (__fini_array_end = ABSOLUTE(.)); + SORT(CONSTRUCTORS) + KEEP (*(.eh_frame)) + *(.gcc_except_table*) + *(.dynamic) + PROVIDE (__CTOR_LIST__ = ABSOLUTE(.)); + KEEP (*(.ctors)) + KEEP (*(SORT(.ctors.*))) + PROVIDE (__CTOR_END__ = ABSOLUTE(.)); + PROVIDE (__DTOR_LIST__ = ABSOLUTE(.)); + KEEP (*(.dtors)) + KEEP (*(SORT(.dtors.*))) + PROVIDE (__DTOR_END__ = ABSOLUTE(.)); + KEEP (*(.jcr)) + . = ALIGN(32 / 8); + } > onchip_memory_0 = 0x3a880100 /* NOP on Nios2 (big endian) */ + + .rodata : + { + PROVIDE (__ram_rodata_start = ABSOLUTE(.)); + . = ALIGN(32 / 8); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + KEEP (*(SORT(.rtemsroset.*))) + } > onchip_memory_0 + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > onchip_memory_0 + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + . = ALIGN(32 / 8); + PROVIDE (__ram_rodata_end = ABSOLUTE(.)); + } > onchip_memory_0 + + _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)); + + PROVIDE (__flash_rodata_start = LOADADDR(.rodata)); + + .rwdata : + { + PROVIDE (__ram_rwdata_start = ABSOLUTE(.)); + . = ALIGN(32 / 8); + *(.got.plt) *(.got) + *(.data1) + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(SORT(.rtemsrwset.*))) + + _gp = ABSOLUTE(. + 0x8000); + PROVIDE(gp = _gp); + + *(.sdata .sdata.* .gnu.linkonce.s.*) + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + + . = ALIGN(32 / 8); + _edata = ABSOLUTE(.); + PROVIDE (edata = ABSOLUTE(.)); + PROVIDE (__ram_rwdata_end = ABSOLUTE(.)); + } > onchip_memory_0 + + PROVIDE (__flash_rwdata_start = LOADADDR(.rwdata)); + + .bss : + { + __bss_start = ABSOLUTE(.); + PROVIDE (__sbss_start = ABSOLUTE(.)); + PROVIDE (___sbss_start = ABSOLUTE(.)); + + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + *(.scommon) + + PROVIDE (__sbss_end = ABSOLUTE(.)); + PROVIDE (___sbss_end = ABSOLUTE(.)); + + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + + . = ALIGN(32 / 8); + __bss_end = ABSOLUTE(.); + _stack_low = ABSOLUTE(.); + . += StackSize; + _stack_high = ABSOLUTE(.); + WorkAreaBase = .; + } > onchip_memory_0 + + /* + * One output section for each of the available partitions. These are not + * used by default, but can be used by users applications using the .section + * directive. + * + * The memory partition used for the heap is treated in special way, i.e. a + * symbol is added to point to the heap start. + * + * Note that when running from flash, these sections are not loaded by the + * HAL. + * + */ + + .onchip_memory_0 : + { + PROVIDE (_alt_partition_onchip_memory_0_start = ABSOLUTE(.)); + *(.onchip_memory_0 .onchip_memory_0.*) + . = ALIGN(32 / 8); + PROVIDE (_alt_partition_onchip_memory_0_end = ABSOLUTE(.)); + _end = ABSOLUTE(.); + end = ABSOLUTE(.); + + } > onchip_memory_0 + + PROVIDE (_alt_partition_onchip_memory_0_load_addr = LOADADDR(.onchip_memory_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) } + + /* Altera debug extensions */ + .debug_alt_sim_info 0 : { *(.debug_alt_sim_info) } +} +/* provide a pointer for the stack */ + +/* + * Don't override this, override the __alt_stack_* symbols instead. + */ +__alt_data_end = 0x00800000; + +/* + * The next two symbols define the location of the default stack. You can + * override them to move the stack to a different memory. + */ +PROVIDE( __alt_stack_pointer = _stack_high ); +PROVIDE( __alt_stack_limit = _stack_low ); + +/* + * This symbol controls where the start of the heap is. If the stack is + * contiguous with the heap then the stack will contract as memory is + * allocated to the heap. + * Override this symbol to put the heap in a different memory. + */ +PROVIDE( __alt_heap_start = end ); + diff --git a/bsps/nios2/nios2_iss/start/main.c b/bsps/nios2/nios2_iss/start/main.c new file mode 100644 index 0000000000..651b425b7c --- /dev/null +++ b/bsps/nios2/nios2_iss/start/main.c @@ -0,0 +1,37 @@ +/* main() + * + * This is the entry point for the application. It calls + * the bsp_start routine to the actual dirty work. + * + * COPYRIGHT (c) 2005-2006 Kolja Waschk rtemsdev/ixo.de + * Derived from no_cpu/no_bsp/startup/main.c 1.9, + * COPYRIGHT (c) 1989-1999. + * 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.h> + +int main( + int argc, + char **argv, + char **environp +) +{ + extern void bsp_start( int, char**, char ** ); + + bsp_start( argc, argv, environp ); + + /* + * May be able to return to the "crt/start.s" code but also + * may not be able to. Do something here which is board dependent. + */ + + rtems_fatal_error_occurred( 0 ); + + return 0; /* just to satisfy the native compiler */ +} diff --git a/bsps/nios2/nios2_iss/start/setvec.c b/bsps/nios2/nios2_iss/start/setvec.c new file mode 100644 index 0000000000..4a3056aee3 --- /dev/null +++ b/bsps/nios2/nios2_iss/start/setvec.c @@ -0,0 +1,42 @@ +/* set_vector + * + * This routine installs an interrupt vector on the target Board/CPU. + * This routine is allowed to be as board dependent as necessary. + * + * INPUT: + * handler - interrupt handler entry point + * vector - vector number + * type - 0 indicates raw hardware connect + * 1 indicates RTEMS interrupt connect + * + * RETURNS: + * address of previous interrupt handler + * + * COPYRIGHT (c) 2005-2006 Kolja Waschk rtemsdev/ixo.de + * Derived from no_cpu/no_bsp/startup/setvec.c 1.8, + * COPYRIGHT (c) 1989-1999. + * 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.h> + +rtems_isr_entry set_vector( /* returns old vector */ + rtems_isr_entry handler, /* isr routine */ + rtems_vector_number vector, /* vector number */ + int type /* RTEMS or RAW intr */ +) +{ + rtems_isr_entry previous_isr; + + if ( type ) + rtems_interrupt_catch( handler, vector, (rtems_isr_entry *) &previous_isr ); + else { + /* XXX: install non-RTEMS ISR as "raw" interupt */ + } + return previous_isr; +} diff --git a/bsps/no_cpu/no_bsp/start/bsp_specs b/bsps/no_cpu/no_bsp/start/bsp_specs new file mode 100644 index 0000000000..140802f2c0 --- /dev/null +++ b/bsps/no_cpu/no_bsp/start/bsp_specs @@ -0,0 +1,7 @@ +%rename lib old_lib + +*lib: +%{!qrtems: %(old_lib)} \ +%{!nostdlib: %{qrtems: --start-group -lrtemsbsp -lrtemscpu -lc -lgcc --end-group \ +%{!qnolinkcmds: -T linkcmds%s}}} + diff --git a/bsps/no_cpu/no_bsp/start/bspstart.c b/bsps/no_cpu/no_bsp/start/bspstart.c new file mode 100644 index 0000000000..b77b971ca1 --- /dev/null +++ b/bsps/no_cpu/no_bsp/start/bspstart.c @@ -0,0 +1,27 @@ +/* + * This routine starts the application. 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) 1989-1999. + * 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 <string.h> + +#include <bsp.h> + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ + +void bsp_start( void ) +{ +} diff --git a/bsps/no_cpu/no_bsp/start/linkcmds b/bsps/no_cpu/no_bsp/start/linkcmds new file mode 100644 index 0000000000..6f2fda7b41 --- /dev/null +++ b/bsps/no_cpu/no_bsp/start/linkcmds @@ -0,0 +1,71 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the NO_CPU NO_BSP BOARD. + * + * COPYRIGHT (c) 1989-1999. + * 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. + */ + +MEMORY + { + ram : org = 0x0, l = 1M + } + +SECTIONS +{ + .text 0x0 : + { + text_start = . ; + _text_start = . ; + *(.text) + . = ALIGN (16); + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + *(.eh_fram) + . = ALIGN (16); + + /* + * C++ constructors + */ + __CTOR_LIST__ = .; + LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) + *(.ctors) + LONG(0) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) + *(.dtors) + LONG(0) + __DTOR_END__ = .; + _etext = ALIGN( 0x10 ) ; + } + .data ADDR( .text ) + SIZEOF( .text ): + { + data_start = . ; + _data_start = . ; + *(.data) + _edata = ALIGN( 0x10 ) ; + } + .bss ADDR( .data ) + SIZEOF( .data ): + { + bss_start = . ; + _bss_start = . ; + *(.bss) + *(COMMON) + end = . ; + __end = . ; + } +} diff --git a/bsps/no_cpu/no_bsp/start/setvec.c b/bsps/no_cpu/no_bsp/start/setvec.c new file mode 100644 index 0000000000..270fa445ac --- /dev/null +++ b/bsps/no_cpu/no_bsp/start/setvec.c @@ -0,0 +1,40 @@ +/* set_vector + * + * This routine installs an interrupt vector on the target Board/CPU. + * This routine is allowed to be as board dependent as necessary. + * + * INPUT: + * handler - interrupt handler entry point + * vector - vector number + * type - 0 indicates raw hardware connect + * 1 indicates RTEMS interrupt connect + * + * RETURNS: + * address of previous interrupt handler + * + * COPYRIGHT (c) 1989-1999. + * 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.h> + +rtems_isr_entry set_vector( /* returns old vector */ + rtems_isr_entry handler, /* isr routine */ + rtems_vector_number vector, /* vector number */ + int type /* RTEMS or RAW intr */ +) +{ + rtems_isr_entry previous_isr; + + if ( type ) + rtems_interrupt_catch( handler, vector, (rtems_isr_entry *) &previous_isr ); + else { + /* XXX: install non-RTEMS ISR as "raw" interupt */ + } + return previous_isr; +} diff --git a/bsps/or1k/generic_or1k/start/bsp_specs b/bsps/or1k/generic_or1k/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/or1k/generic_or1k/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/or1k/generic_or1k/start/bspstart.c b/bsps/or1k/generic_or1k/start/bspstart.c new file mode 100644 index 0000000000..35a536ef0b --- /dev/null +++ b/bsps/or1k/generic_or1k/start/bspstart.c @@ -0,0 +1,24 @@ +/** + * @file + * + * @ingroup generic_or1k + * + * @brief Benchmark timer support. + */ + +/* + * Copyright (c) 2014-2015 by Hesham ALMatary + * + * 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_start( void ) +{ + rtems_cache_enable_instruction(); + rtems_cache_enable_data(); +} diff --git a/bsps/or1k/generic_or1k/start/linkcmds b/bsps/or1k/generic_or1k/start/linkcmds new file mode 100644 index 0000000000..cef99d36d0 --- /dev/null +++ b/bsps/or1k/generic_or1k/start/linkcmds @@ -0,0 +1,41 @@ +/** + * @file + * + * @ingroup bsp_linker + * + * @brief Memory map + */ + +/* + * COPYRIGHT (c) 2014 Hesham ALMatary <heshamelmatary@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 + */ + +MEMORY + { + VECTOR_RAM (AIW) : ORIGIN = 0x0 , LENGTH = 8260 + RAM : org = 0x00002048, l = 0x1FFDFB8 + UNEXPECTED_SECTIONS : ORIGIN = 0xffffffff, LENGTH = 0 + } + +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_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); + +bsp_section_vector_begin = 0; +bsp_section_stack_begin = 0x1FFDFB8; + +INCLUDE linkcmds.base diff --git a/bsps/or1k/shared/start/linkcmds.base b/bsps/or1k/shared/start/linkcmds.base new file mode 100644 index 0000000000..442042a9be --- /dev/null +++ b/bsps/or1k/shared/start/linkcmds.base @@ -0,0 +1,313 @@ +/** + * @file + * + * @ingroup bsp_linker + * + * @brief Linker command base file. + */ + +/* + * COPYRIGHT (c) 2014 Hesham ALMatary <heshamelmatary@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 + */ + +OUTPUT_ARCH (or1k) + +ENTRY (_start) +STARTUP (start.o) + +/* + * Global symbols that may be defined externally + */ + +bsp_start_vector_table_begin = 0x1F00; +bsp_vector_table_size = DEFINED (bsp_vector_table_size) ? bsp_vector_table_size +: 8260; +/* 8192 for raw vector table, and 17 * 4 for handlers vector. */ + +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_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_processor_count = DEFINED (bsp_processor_count) ? bsp_processor_count : 1; + +SECTIONS { + + .vector : ALIGN_WITH_INPUT { + *(.vector) + . = ALIGN(bsp_vector_table_size); + 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 = bsp_section_vector_begin; + bsp_vector_table_end = bsp_vector_table_begin + bsp_vector_table_size; + + .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 +.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 + +.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 { + bsp_section_stack_end = .; + } > REGION_STACK AT > REGION_STACK + bsp_section_stack_size = bsp_section_stack_begin - bsp_section_stack_end; + + RamBase = ORIGIN (REGION_WORK); + RamSize = LENGTH (REGION_WORK); + WorkAreaBase = bsp_section_work_begin; + HeapSize = 0; +} diff --git a/bsps/powerpc/beatnik/start/bsp_specs b/bsps/powerpc/beatnik/start/bsp_specs new file mode 100644 index 0000000000..99ca0adb61 --- /dev/null +++ b/bsps/powerpc/beatnik/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/beatnik/start/bspclean.c b/bsps/powerpc/beatnik/start/bspclean.c new file mode 100644 index 0000000000..251d47a46d --- /dev/null +++ b/bsps/powerpc/beatnik/start/bspclean.c @@ -0,0 +1,25 @@ +#include <bsp.h> +#include <bsp/bootcard.h> +#include <rtems/bspIo.h> + +void bsp_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code error +) +{ + printk("fatal source: %s\n", rtems_fatal_source_text(source)); + + if (source == RTEMS_FATAL_SOURCE_EXCEPTION) { + rtems_exception_frame_print((const rtems_exception_frame *) error); + } + + /* We can't go back to MotLoad since we blew it's memory area + * and vectors. Just pull the reset line... + */ + printk( + "bsp_fatal_extension(): RTEMS terminated -- no way back to MotLoad " + "so I reset the card\n" + ); + bsp_reset(); +} diff --git a/bsps/powerpc/beatnik/start/bspreset.c b/bsps/powerpc/beatnik/start/bspreset.c new file mode 100644 index 0000000000..68540847ee --- /dev/null +++ b/bsps/powerpc/beatnik/start/bspreset.c @@ -0,0 +1,18 @@ +#include <rtems.h> +#include <bsp.h> +#include <bsp/bootcard.h> +#include <rtems/bspIo.h> +#include <libcpu/io.h> +#include <libcpu/stackTrace.h> +#include <stdint.h> + +void bsp_reset() +{ + + printk("Printing a stack trace for your convenience :-)\n"); + CPU_print_stack(); + + printk("RTEMS terminated; Rebooting ...\n"); + /* Mvme5500 board reset : 2004 S. Kate Feng <feng1@bnl.gov> */ + out_8((volatile uint8_t*) (BSP_MV64x60_DEV1_BASE +2), 0x80); +} diff --git a/bsps/powerpc/beatnik/start/bspstart.c b/bsps/powerpc/beatnik/start/bspstart.c new file mode 100644 index 0000000000..c3f2c0ceda --- /dev/null +++ b/bsps/powerpc/beatnik/start/bspstart.c @@ -0,0 +1,387 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * COPYRIGHT (c) 1989-1998. + * 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.OARcorp.com/rtems/license.html. + * + * Modified to support the MCP750. + * Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr + * + * Modified to support the Synergy VGM & Motorola PowerPC boards. + * (C) by Till Straumann, <strauman@slac.stanford.edu>, 2002, 2004, 2005 + * + * Modified to support the mvme5500 BSP + * (C) by Kate Feng <feng1@bnl.gov>, 2003, 2004 + * under the contract DE-AC02-98CH10886 with the Deaprtment of Energy + * + * T. Straumann: 2005-2007; stolen again for 'beatnik'... + */ +#include <string.h> +#include <stdlib.h> +#include <ctype.h> + +#include <rtems/system.h> +#include <rtems/libio.h> +#include <rtems/libcsupport.h> +#include <rtems/bspIo.h> +#include <rtems/counter.h> +#include <rtems/powerpc/powerpc.h> +#include <rtems/sysinit.h> +/*#include <bsp/consoleIo.h>*/ +#include <libcpu/spr.h> /* registers.h is included here */ +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/uart.h> +#include <bsp/pci.h> +#include <bsp/gtreg.h> +#include <bsp/gt_timer.h> +#include <libcpu/bat.h> +#include <libcpu/pte121.h> +#include <libcpu/cpuIdent.h> +#include <bsp/vectors.h> +#include <bsp/VME.h> +#include <bsp/vpd.h> + +#define SHOW_MORE_INIT_SETTINGS + +BSP_output_char_function_type BSP_output_char = BSP_output_char_via_serial; +BSP_polling_getchar_function_type BSP_poll_char = NULL; + +extern Triv121PgTbl BSP_pgtbl_setup(unsigned int *); +extern void BSP_pgtbl_activate(Triv121PgTbl); +extern void BSP_motload_pci_fixup(void); + +extern unsigned long __rtems_end[]; + +/* We really shouldn't use these since MMUoff also sets IP; + * nevertheless, during early init I don't care for now + */ +extern void MMUoff(void); +extern void MMUon(void); + +extern uint32_t probeMemoryEnd(void); + +SPR_RW(SPRG0) +SPR_RW(SPRG1) +SPR_RO(HID1) + +/* Table of PLL multipliers for 7455/7457: +01000 2 00010 7.5 00000 11.5 00001 17 +10000 3 11000 8 10111 12 00101 18 +10100 4 01100 8.5 11111 12.5 00111 20 +10110 5 01111 9 01011 13 01001 21 +10010 5.5 01110 9.5 11100 13.5 01101 24 +11010 6 10101 10 11001 14 11101 28 +01010 6.5 10001 10.5 00011 15 00110 bypass +00100 7 10011 11 11011 16 11110 off +*/ + +/* Sorted according to CFG bits and multiplied by 2 it looks + * like this (note that this is in sequential order, not + * tabulated as above) + */ +signed char mpc7450PllMultByTwo[32] = { +23, 34, 15, 30, +14, 36, 2/*bypass*/, 40, +4, 42, 13, 26, +17, 48, 19, 18, +6, 21, 11, 22, +8, 20, 10, 24, +16, 28, 12, 32, +27, 56, 0/*off*/, 25, +}; + +uint32_t bsp_clicks_per_usec = 0; + +/* + * Total memory using probing. + */ +unsigned int BSP_mem_size; + +/* + * PCI Bus Frequency + */ +unsigned int BSP_bus_frequency = 0xdeadbeef; +/* + * processor clock frequency + */ +unsigned int BSP_processor_frequency = 0xdeadbeef; + +/* + * Time base divisior (bus freq / TB clock) + */ +unsigned int BSP_time_base_divisor = 4000; /* most 604+ CPUs seem to use this */ + +/* Board identification string */ +char BSP_productIdent[20] = {0}; +char BSP_serialNumber[20] = {0}; + +/* VPD appends an extra char -- what for ? */ +char BSP_enetAddr0[7] = {0}; +char BSP_enetAddr1[7] = {0}; + +char *rtems_progname; + +#define CMDLINE_BUF_SIZE 2048 + +static char cmdline_buf[CMDLINE_BUF_SIZE]; +char *BSP_commandline_string = cmdline_buf; + +/* this routine is called early and must be safe with a not properly + * aligned stack + */ +char *save_boot_params( + void *r3, + void *r4, + void *r5, + char *cmdline_start, + char *cmdline_end +) +{ +int i=cmdline_end-cmdline_start; + if ( i >= CMDLINE_BUF_SIZE ) + i = CMDLINE_BUF_SIZE-1; + else if ( i < 0 ) + i = 0; + memmove(cmdline_buf, cmdline_start, i); + cmdline_buf[i]=0; + return cmdline_buf; +} + +static BSP_BoardType board_type = Unknown; + +BSP_BoardType +BSP_getBoardType( void ) +{ + return board_type; +} + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ + +void bsp_start( void ) +{ + unsigned char *stack; + char *chpt; + uint32_t intrStackStart; + uint32_t intrStackSize; + + Triv121PgTbl pt=0; + + VpdBufRec vpdData [] = { + { key: ProductIdent, instance: 0, buf: BSP_productIdent, buflen: sizeof(BSP_productIdent) - 1 }, + { key: SerialNumber, instance: 0, buf: BSP_serialNumber, buflen: sizeof(BSP_serialNumber) - 1 }, + { key: CpuClockHz, instance: 0, buf: &BSP_processor_frequency, buflen: sizeof(BSP_processor_frequency) }, + { key: BusClockHz, instance: 0, buf: &BSP_bus_frequency, buflen: sizeof(BSP_bus_frequency) }, + { key: EthernetAddr, instance: 0, buf: BSP_enetAddr0, buflen: sizeof(BSP_enetAddr0) }, + { key: EthernetAddr, instance: 1, buf: BSP_enetAddr1, buflen: sizeof(BSP_enetAddr1) }, + VPD_END + }; + + /* T. Straumann: 4/2005 + * + * Need to map the system registers early, so we can printk... + * (otherwise we silently die) + */ + /* map the PCI 0, 1 Domain I/O space, GT64260B registers + * and the reserved area so that the size is the power of 2. + */ + setdbat(7, BSP_DEV_AND_PCI_IO_BASE, BSP_DEV_AND_PCI_IO_BASE, BSP_DEV_AND_PCI_IO_SIZE, IO_PAGE); + + /* Intersperse messages with actions to help locate problems */ + printk("-----------------------------------------\n"); + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() & friends functions + * store the result in global variables so that it can be used latter... + * This also verifies that we run on a known CPU. + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + /* Make sure we detect a known host bridge */ + BSP_getDiscoveryVersion(/* assert detection */ 1); + + printk("Welcome to RTEMS %s\n", _RTEMS_version ); + + /* Leave all caches as MotLoad left them. Seems to be fine */ + + /* + * the initial stack has aready been set to this value in start.S + * so there is no need to set it in r1 again... It is just for info + * so that it can be printed without accessing R1. + */ + __asm__ volatile("mr %0, 1":"=r"(stack)); + + /* tag the bottom (T. Straumann 6/36/2001 <strauman@slac.stanford.edu>) */ + + *((uint32_t *)stack) = 0; + + /* + * Initialize the interrupt related settings + * SPRG0 = interrupt nesting level count + * SPRG1 = software managed IRQ stack + * + * This could be done latter (e.g in IRQ_INIT) but it helps to understand + * some settings below... + */ + intrStackStart = (uint32_t)__rtems_end; + intrStackSize = rtems_configuration_get_interrupt_stack_size(); + + /* + * Initialize default raw exception handlers. See vectors/vectors_init.c + */ + ppc_exc_initialize(intrStackStart, intrStackSize); + + printk("CPU: %s\n", get_ppc_cpu_type_name(current_ppc_cpu)); + + /* + * Initialize RTEMS IRQ system + */ + BSP_rtems_irq_mng_init(0); + + BSP_vpdRetrieveFields(vpdData); + + if ( !strncmp(BSP_productIdent,"MVME5500",8) ) + board_type = MVME5500; + else if ( !strncmp(BSP_productIdent,"MVME6100",8) ) + board_type = MVME6100; + + printk("Board Type: %s (S/N %s)\n", + BSP_productIdent[0] ? BSP_productIdent : "n/a", + BSP_serialNumber[0] ? BSP_serialNumber : "n/a"); + + if ( 0xdeadbeef == BSP_bus_frequency ) { + BSP_bus_frequency = 133333333; + printk("Bus Clock Freq NOT FOUND in VPD; using %10u Hz\n", + BSP_bus_frequency); + } else { + printk("Bus Clock Freq: %10u Hz\n", + BSP_bus_frequency); + } + + if ( 0xdeadbeef == BSP_processor_frequency ) { + BSP_processor_frequency = BSP_bus_frequency/2; + BSP_processor_frequency *= mpc7450PllMultByTwo[ (_read_HID1() >> (31-19)) & 31 ]; + } + printk("CPU Clock Freq: %10u Hz\n", BSP_processor_frequency); + + /* probe real memory size; if it's more than 256M we can't currently access it + * since at this point only BAT-0 maps 0..256M + */ + BSP_mem_size = probeMemoryEnd(); + + if ( (chpt = strstr(BSP_commandline_string,"MEMSZ=")) ) { + char *endp; + uint32_t sz; + chpt+=6 /* strlen("MEMSZ=") */; + sz = strtoul(chpt, &endp, 0); + if ( endp != chpt ) + BSP_mem_size = sz; + } + + printk("Memory: %10u bytes\n", BSP_mem_size); + + if ( BSP_mem_size > 0x10000000 ) { + uint32_t s; + if ( BSP_mem_size > 0x80000000 ) { + BSP_mem_size = 0x80000000; + printk("Memory clipped to 0x%08x for now, sorry\n", BSP_mem_size); + } + for ( s = 0x20000000; s < BSP_mem_size ; s<<=1) + ; + MMUoff(); + /* since it's currently in use we must first surrender it */ + setdbat(0, 0, 0, 0, 0); + setdbat(0, 0, 0, s, _PAGE_RW); + MMUon(); + } + + printk("-----------------------------------------\n"); + + /* Maybe not setup yet because of the warning message */ + + /* Allocate and set up the page table mappings + * This is only available on >604 CPUs. + * + * NOTE: This setup routine may modify the available memory + * size. It is essential to call it before + * calculating the workspace etc. + */ + pt = BSP_pgtbl_setup(&BSP_mem_size); + if (!pt) + printk("WARNING: unable to setup page tables.\n"); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Now BSP_mem_size = 0x%x\n",BSP_mem_size); +#endif + + /* + * Set up our hooks + */ + + bsp_clicks_per_usec = BSP_bus_frequency/(BSP_time_base_divisor * 1000); + rtems_counter_initialize_converter( + BSP_bus_frequency / (BSP_time_base_divisor / 1000) + ); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk( + "Configuration.work_space_size = %x\n", + rtems_configuration_get_work_space_size() + ); +#endif + + /* Activate the page table mappings only after + * initializing interrupts because the irq_mng_init() + * routine needs to modify the text + */ + if ( pt ) { +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Page table setup finished; will activate it NOW...\n"); +#endif + BSP_pgtbl_activate(pt); + } + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Going to start PCI buses scanning and initialization\n"); +#endif + BSP_pci_initialize(); + + /* need to tweak the motload setup */ + BSP_motload_pci_fixup(); + + /* map 512M, 256 for PCI 256 for VME */ + setdbat(5,BSP_PCI_HOSE0_MEM_BASE, BSP_PCI_HOSE0_MEM_BASE, BSP_PCI_HOSE0_MEM_SIZE, IO_PAGE); + setdbat(6,BSP_PCI_HOSE1_MEM_BASE, BSP_PCI_HOSE1_MEM_BASE, 0x10000000, IO_PAGE); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Number of PCI buses found is : %d\n", pci_bus_count()); +#endif + + /* + * Initialize hardware timer facility (not used by BSP itself) + * Needs PCI to identify discovery version... + */ + BSP_timers_initialize(); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("MSR 0x%lx \n", _read_MSR()); + printk("Exit from bspstart\n"); +#endif +} + +RTEMS_SYSINIT_ITEM( + BSP_vme_config, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); diff --git a/bsps/powerpc/beatnik/start/i2c_init.c b/bsps/powerpc/beatnik/start/i2c_init.c new file mode 100644 index 0000000000..bc5c5ead02 --- /dev/null +++ b/bsps/powerpc/beatnik/start/i2c_init.c @@ -0,0 +1,131 @@ +#include <rtems.h> +#include <bsp.h> +#include <rtems/libi2c.h> +#include <libchip/i2c-2b-eeprom.h> +#include <libchip/i2c-ds1621.h> +#include <bsp/gti2c_busdrv.h> +#include <rtems/libio.h> + +#include <stdio.h> +#include <sys/stat.h> + +/* Register i2c bus driver & devices */ + +/* + * Authorship + * ---------- + * This software ('beatnik' RTEMS BSP for MVME6100 and MVME5500) was + * created by Till Straumann <strauman@slac.stanford.edu>, 2005-2007, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * The 'beatnik' BSP was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ + +int +BSP_i2c_initialize( void ) +{ +int busno; + /* Initialize the library */ + if ( rtems_libi2c_initialize() ) { + fprintf(stderr,"Initializing I2C library failed\n"); + return -1; + } + + /* Register our bus driver */ + if ( (busno=rtems_libi2c_register_bus( + BSP_I2C_BUS0_NAME, + BSP_I2C_BUS_DESCRIPTOR) ) < 0 ) { + perror("Registering gt64260 i2c bus driver"); + return -1; + } + + /* Now register higher level drivers; note that + * the i2c address in the manual is actually left-shifted + * by one bit, i.e., as it would go on the bus. + */ + + /* Use read-only driver for VPD */ + if ( rtems_libi2c_register_drv( + BSP_I2C_VPD_EEPROM_NAME, + i2c_2b_eeprom_ro_driver_descriptor, + busno, + BSP_VPD_I2C_ADDR) < 0 ) { + perror("Registering i2c VPD eeprom driver failed"); + return -1; + } + + /* Use read-write driver for user eeprom -- you still might + * have to disable HW write-protection on your board. + */ + if ( rtems_libi2c_register_drv( + BSP_I2C_USR_EEPROM_NAME, + i2c_2b_eeprom_driver_descriptor, + busno, + BSP_USR_I2C_ADDR) < 0 ) { + perror("Registering i2c USR eeprom driver failed"); + return -1; + } + + /* The thermostat */ + if ( rtems_libi2c_register_drv( + BSP_I2C_DS1621_NAME, + i2c_ds1621_driver_descriptor, + busno, + BSP_THM_I2C_ADDR) < 0 ) { + perror("Registering i2c ds1621 temp sensor. driver failed"); + return -1; + } + + /* Finally, as an example, register raw access to the + * ds1621. The driver above just reads the 8 msb of the + * temperature but doesn't support anything else. Using + * the raw device node you can write/read individual + * control bytes yourself and e.g., program the thermostat... + */ + + if ( mknod( + BSP_I2C_DS1621_RAW_DEV_NAME, + 0666 | S_IFCHR, + rtems_filesystem_make_dev_t(rtems_libi2c_major, + RTEMS_LIBI2C_MAKE_MINOR(busno,BSP_THM_I2C_ADDR))) ) { + perror("Creating device node for raw ds1621 access failed"); + return -1; + } + printf("I2C devices registered\n"); + return 0; +} diff --git a/bsps/powerpc/beatnik/start/linkcmds b/bsps/powerpc/beatnik/start/linkcmds new file mode 100644 index 0000000000..b30fb91277 --- /dev/null +++ b/bsps/powerpc/beatnik/start/linkcmds @@ -0,0 +1,5 @@ +STARTUP(motld_start.o) +ENTRY(__rtems_entry_point) +EXTERN(__vectors) + +INCLUDE linkcmds.share diff --git a/bsps/powerpc/gen5200/start/bestcomm.c b/bsps/powerpc/gen5200/start/bestcomm.c new file mode 100644 index 0000000000..ef59adcfd8 --- /dev/null +++ b/bsps/powerpc/gen5200/start/bestcomm.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2010-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 NDEBUG + +#include <bsp/bestcomm.h> + +#include <string.h> + +#include <bsp/mpc5200.h> + +static void bestcomm_irq_handler(void *arg) +{ + bestcomm_irq *self = arg; + + bestcomm_irq_clear(self); + bestcomm_irq_wakeup_event_task(self); +} + +void bestcomm_irq_create(bestcomm_irq *self, int task_index) +{ + assert(task_index >= 0 && task_index <= 15); + + self->task_index = task_index; + self->event_task_id = rtems_task_self(); + bestcomm_glue_irq_install(task_index, bestcomm_irq_handler, self); +} + +void bestcomm_irq_destroy(const bestcomm_irq *self) +{ + bestcomm_glue_irq_install(self->task_index, NULL, NULL); +} + +void bestcomm_task_create(bestcomm_task *self, TaskId task_index) +{ + self->task_control_register = &mpc5200.sdma.tcr[task_index]; + self->variable_table = BESTCOMM_TASK_ENTRY_TABLE[task_index].var_table; + self->task_index = task_index; + self->tdt_begin = NULL; + self->tdt_opcode_count = 0; + bestcomm_task_stop(self); + bestcomm_irq_create(&self->irq, task_index); +} + +void bestcomm_task_create_and_load( + bestcomm_task *self, + TaskId task_index, + const uint32_t *tdt_source_begin, + size_t tdt_size +) +{ + bestcomm_task_create(self, task_index); + bestcomm_task_load(self, tdt_source_begin, tdt_size); +} + +void bestcomm_task_destroy(bestcomm_task *self) +{ + bestcomm_task_stop(self); + bestcomm_task_free_tdt(self); +} + +void bestcomm_task_load(bestcomm_task *self, const uint32_t *tdt_source_begin, size_t tdt_size) +{ + assert(tdt_size % 4 == 0); + + bestcomm_task_irq_disable(self); + bestcomm_task_stop(self); + bestcomm_task_irq_clear(self); + bestcomm_task_irq_enable(self); + bestcomm_task_free_tdt(self); + bestcomm_task_clear_variables(self); + + self->tdt_opcode_count = tdt_size / 4; + + self->tdt_begin = bestcomm_malloc(tdt_size); + assert(self->tdt_begin != NULL); + uint32_t *tdt_last = self->tdt_begin + self->tdt_opcode_count - 1; + + memcpy(self->tdt_begin, tdt_source_begin, tdt_size); + + volatile bestcomm_task_entry *entry = bestcomm_task_get_task_entry(self); + entry->tdt_begin = self->tdt_begin; + entry->tdt_last = tdt_last; + + bestcomm_task_clear_pragmas(self); + bestcomm_task_set_priority(self, 0); +} + +void bestcomm_task_clear_variables(const bestcomm_task *self) +{ + int i; + + for (i = 0; i < 32; ++i) { + (*self->variable_table)[i] = 0; + } +} diff --git a/bsps/powerpc/gen5200/start/bsp_specs b/bsps/powerpc/gen5200/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/gen5200/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/gen5200/start/bspreset.c b/bsps/powerpc/gen5200/start/bspreset.c new file mode 100644 index 0000000000..232ebfeac0 --- /dev/null +++ b/bsps/powerpc/gen5200/start/bspreset.c @@ -0,0 +1,30 @@ +/* + * COPYRIGHT (c) 1989-2008. + * 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.h> +#include <bsp/mpc5200.h> +#include <bsp/bootcard.h> + +void bsp_reset( void ) +{ + #if (BENCHMARK_IRQ_PROCESSING == 1) + { + BSP_IRQ_Benchmarking_Report(); + } + #endif + + /* + * Now reset the CPU + */ + mpc5200.gpt[0].count_in = 0xf; + mpc5200.gpt[0].emsel = 0x9004; + + while(1) ; +} diff --git a/bsps/powerpc/gen5200/start/bspstart.c b/bsps/powerpc/gen5200/start/bspstart.c new file mode 100644 index 0000000000..209cc7738e --- /dev/null +++ b/bsps/powerpc/gen5200/start/bspstart.c @@ -0,0 +1,172 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC5200 BSP | ++-----------------------------------------------------------------+ +| Partially based on the code references which are named below. | +| Adaptions, modifications, enhancements and any recent parts of | +| the code are: | +| Copyright (c) 2005 | +| 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. | +| | ++-----------------------------------------------------------------+ +| this file contains the BSP initialization code | +\*===============================================================*/ +/***********************************************************************/ +/* */ +/* Module: bspstart.c */ +/* Date: 07/17/2003 */ +/* Purpose: RTEMS MPC5x00 C level startup code */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Description: This routine starts the application. It includes */ +/* application, board, and monitor specific */ +/* initialization and configuration. The generic CPU */ +/* dependent initialization has been performed before */ +/* this routine is invoked. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Code */ +/* References: MPC8260ads C level startup code */ +/* Module: bspstart.c */ +/* Project: RTEMS 4.6.0pre1 / MCF8260ads BSP */ +/* Version 1.2 */ +/* Date: 04/17/2002 */ +/* */ +/* Author(s) / Copyright(s): */ +/* */ +/* The MPC860 specific stuff was written by Jay Monkman */ +/* (jmonkman@frasca.com) */ +/* */ +/* Modified for the MPC8260ADS board by Andy Dachs */ +/* <a.dachs@sstl.co.uk> */ +/* Surrey Satellite Technology Limited, 2001 */ +/* A 40MHz system clock is assumed. */ +/* The PON. RST.CONF. Dip switches (DS1) are */ +/* 1 - Off */ +/* 2 - On */ +/* 3 - Off */ +/* 4 - On */ +/* 5 - Off */ +/* 6 - Off */ +/* 7 - Off */ +/* 8 - Off */ +/* Dip switches on DS2 and DS3 are all set to ON */ +/* The LEDs on the board are used to signal panic and fatal_error */ +/* conditions. */ +/* The mmu is unused at this time. */ +/* */ +/* COPYRIGHT (c) 1989-2007. */ +/* 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. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Partially based on the code references which are named above. */ +/* Adaptions, modifications, enhancements and any recent parts of */ +/* the code are under the right of */ +/* */ +/* IPR Engineering, Dachauer Straße 38, D-80335 München */ +/* Copyright(C) 2003 */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* IPR Engineering makes no representation or warranties with */ +/* respect to the performance of this computer program, and */ +/* specifically disclaims any responsibility for any damages, */ +/* special or consequential, connected with the use of this program. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Version history: 1.0 */ +/* */ +/***********************************************************************/ + +#include <rtems.h> +#include <rtems/counter.h> + +#include <libcpu/powerpc-utility.h> + +#include <bsp.h> +#include <bsp/vectors.h> +#include <bsp/bootcard.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> +#include <bsp/mpc5200.h> + +/* Configuration parameter for clock driver */ +uint32_t bsp_time_base_frequency; + +/* Legacy */ +uint32_t bsp_clicks_per_usec; + +void bsp_start(void) +{ + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function store the result in global variables so that it can be used + * later... + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + #if defined(HAS_UBOOT) && defined(SHOW_MORE_INIT_SETTINGS) + { + void dumpUBootBDInfo( bd_t * ); + dumpUBootBDInfo( &bsp_uboot_board_info ); + } + #endif + + cpu_init(); + + if(get_ppc_cpu_revision() >= 0x2014) { + /* Special settings for MPC5200B (B variant) */ + uint32_t xlb_cfg = mpc5200.config; + + /* XXX: The Freescale documentation for BSDIS seems to be wrong */ + xlb_cfg |= XLB_CFG_BSDIS; + + xlb_cfg &= ~XLB_CFG_PLDIS; + + mpc5200.config = xlb_cfg; + } + + bsp_time_base_frequency = XLB_CLOCK / 4; + bsp_clicks_per_usec = (XLB_CLOCK/4000000); + rtems_counter_initialize_converter(bsp_time_base_frequency); + + /* Initialize exception handler */ + ppc_exc_cache_wb_check = 0; + ppc_exc_initialize( + (uintptr_t) bsp_interrupt_stack_start, + (uintptr_t) bsp_interrupt_stack_size + ); + ppc_exc_set_handler(ASM_ALIGN_VECTOR, ppc_exc_alignment_handler); + + /* Initalize interrupt support */ + bsp_interrupt_initialize(); + + /* + * If the BSP was built with IRQ benchmarking enabled, + * then intialize it. + */ + #if (BENCHMARK_IRQ_PROCESSING == 1) + BSP_IRQ_Benchmarking_Reset(); + #endif + + #ifdef SHOW_MORE_INIT_SETTINGS + printk("Exit from bspstart\n"); + #endif +} diff --git a/bsps/powerpc/gen5200/start/cpuinit.c b/bsps/powerpc/gen5200/start/cpuinit.c new file mode 100644 index 0000000000..77787c4956 --- /dev/null +++ b/bsps/powerpc/gen5200/start/cpuinit.c @@ -0,0 +1,348 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC5200 BSP | ++-----------------------------------------------------------------+ +| Partially based on the code references which are named below. | +| Adaptions, modifications, enhancements and any recent parts of | +| the code are: | +| Copyright (c) 2005 | +| 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. | +| | ++-----------------------------------------------------------------+ +| this file contains the code to initialize the cpu | +\*===============================================================*/ +/***********************************************************************/ +/* */ +/* Module: cpuinit.c */ +/* Date: 07/17/2003 */ +/* Purpose: RTEMS MPC5x00 C level startup code */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Description: This file contains additional functions for */ +/* initializing the MPC5x00 CPU */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Code */ +/* References: MPC8260ads additional CPU initialization */ +/* Module: cpuinit.c */ +/* Project: RTEMS 4.6.0pre1 / MCF8260ads BSP */ +/* Version 1.1 */ +/* Date: 10/22/2002 */ +/* */ +/* Author(s) / Copyright(s): */ +/* */ +/* Written by Jay Monkman (jmonkman@frasca.com) */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Partially based on the code references which are named above. */ +/* Adaptions, modifications, enhancements and any recent parts of */ +/* the code are under the right of */ +/* */ +/* IPR Engineering, Dachauer Straße 38, D-80335 München */ +/* Copyright(C) 2003 */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* IPR Engineering makes no representation or warranties with */ +/* respect to the performance of this computer program, and */ +/* specifically disclaims any responsibility for any damages, */ +/* special or consequential, connected with the use of this program. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Version history: 1.0 */ +/* */ +/***********************************************************************/ + +#include <stdbool.h> +#include <string.h> + +#include <libcpu/powerpc-utility.h> +#include <libcpu/mmu.h> + +#include <bsp.h> +#include <bsp/mpc5200.h> + +#define SET_DBAT( n, uv, lv) \ + do { \ + PPC_SET_SPECIAL_PURPOSE_REGISTER( DBAT##n##L, lv); \ + PPC_SET_SPECIAL_PURPOSE_REGISTER( DBAT##n##U, uv); \ + } while (0) + +static void calc_dbat_regvals( + BAT *bat_ptr, + uint32_t base_addr, + uint32_t size, + bool flg_w, + bool flg_i, + bool flg_m, + bool flg_g, + uint32_t flg_bpp +) +{ + uint32_t block_mask = 0xffffffff; + uint32_t end_addr = base_addr + size - 1; + + /* Determine block mask, that overlaps the whole block */ + while ((end_addr & block_mask) != (base_addr & block_mask)) { + block_mask <<= 1; + } + + bat_ptr->batu.bepi = base_addr >> (32 - 15); + bat_ptr->batu.bl = ~(block_mask >> (28 - 11)); + bat_ptr->batu.vs = 1; + bat_ptr->batu.vp = 1; + + bat_ptr->batl.brpn = base_addr >> (32 - 15); + bat_ptr->batl.w = flg_w; + bat_ptr->batl.i = flg_i; + bat_ptr->batl.m = flg_m; + bat_ptr->batl.g = flg_g; + bat_ptr->batl.pp = flg_bpp; +} + +static inline void enable_bat_4_to_7(void) +{ + PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS(HID2, BSP_BBIT32(13)); +} + +static void cpu_init_bsp(void) +{ + BAT dbat; + +#if defined(MPC5200_BOARD_BRS5L) || defined(MPC5200_BOARD_BRS6L) + calc_dbat_regvals( + &dbat, + (uint32_t) bsp_ram_start, + (uint32_t) bsp_ram_size, + false, + false, + false, + false, + BPP_RW + ); + SET_DBAT(0,dbat.batu,dbat.batl); + + calc_dbat_regvals( + &dbat, + (uint32_t) bsp_rom_start, + (uint32_t) bsp_rom_size, + false, + false, + false, + false, + BPP_RX + ); + SET_DBAT(1,dbat.batu,dbat.batl); + + calc_dbat_regvals( + &dbat, + (uint32_t) MBAR, + 128 * 1024, + false, + true, + false, + true, + BPP_RW + ); + SET_DBAT(2,dbat.batu,dbat.batl); +#elif defined (HAS_UBOOT) + uint32_t start = 0; + + /* + * Accesses (also speculative accesses) outside of the RAM area are a + * disaster especially in combination with the BestComm. For safety reasons + * we make the available RAM a little bit smaller to have an unused area at + * the end. + */ + bsp_uboot_board_info.bi_memsize -= 4 * 1024; + + /* + * Program BAT0 for RAM + */ + calc_dbat_regvals( + &dbat, + bsp_uboot_board_info.bi_memstart, + bsp_uboot_board_info.bi_memsize, + false, + false, + false, + false, + BPP_RW + ); + SET_DBAT(0,dbat.batu,dbat.batl); + + /* + * Program BAT1 for Flash + * + * WARNING!! Some Freescale LITE5200B boards ship with a version of + * U-Boot that lies about the starting address of Flash. This check + * corrects that. + */ + if ((bsp_uboot_board_info.bi_flashstart + bsp_uboot_board_info.bi_flashsize) + < bsp_uboot_board_info.bi_flashstart) { + start = 0 - bsp_uboot_board_info.bi_flashsize; + } else { + start = bsp_uboot_board_info.bi_flashstart; + } + calc_dbat_regvals( + &dbat, + start, + bsp_uboot_board_info.bi_flashsize, + false, + false, + false, + false, + BPP_RX + ); + SET_DBAT(1,dbat.batu,dbat.batl); + + /* + * Program BAT2 for the MBAR + */ + calc_dbat_regvals( + &dbat, + (uint32_t) MBAR, + 128 * 1024, + false, + true, + false, + true, + BPP_RW + ); + SET_DBAT(2,dbat.batu,dbat.batl); + + /* + * If there is SRAM, program BAT3 for that memory + */ + if (bsp_uboot_board_info.bi_sramsize != 0) { + calc_dbat_regvals( + &dbat, + bsp_uboot_board_info.bi_sramstart, + bsp_uboot_board_info.bi_sramsize, + false, + true, + true, + true, + BPP_RW + ); + SET_DBAT(3,dbat.batu,dbat.batl); + } +#else +#warning "Using BAT register values set by environment" +#endif + +#if defined(MPC5200_BOARD_DP2) + enable_bat_4_to_7(); + + /* FPGA */ + calc_dbat_regvals( + &dbat, + 0xf0020000, + 128 * 1024, + false, + true, + false, + true, + BPP_RW + ); + SET_DBAT(4, dbat.batu, dbat.batl); +#elif defined(MPC5200_BOARD_PM520_ZE30) + enable_bat_4_to_7(); + + /* External CC770 CAN controller available in version 2 */ + calc_dbat_regvals( + &dbat, + 0xf2000000, + 128 * 1024, + false, + true, + false, + true, + BPP_RW + ); + SET_DBAT(4, dbat.batu, dbat.batl); +#elif defined(MPC5200_BOARD_BRS5L) + calc_dbat_regvals( + &dbat, + (uint32_t) bsp_dpram_start, + 128 * 1024, + false, + true, + false, + true, + BPP_RW + ); + SET_DBAT(3,dbat.batu,dbat.batl); +#elif defined(MPC5200_BOARD_BRS6L) + enable_bat_4_to_7(); + + /* FPGA */ + calc_dbat_regvals( + &dbat, + MPC5200_BRS6L_FPGA_BEGIN, + MPC5200_BRS6L_FPGA_SIZE, + false, + true, + false, + true, + BPP_RW + ); + SET_DBAT(3,dbat.batu,dbat.batl); + + /* MRAM */ + calc_dbat_regvals( + &dbat, + MPC5200_BRS6L_MRAM_BEGIN, + MPC5200_BRS6L_MRAM_SIZE, + true, + false, + false, + false, + BPP_RW + ); + SET_DBAT(4,dbat.batu,dbat.batl); +#endif +} + +void cpu_init(void) +{ + uint32_t msr; + + #if BSP_INSTRUCTION_CACHE_ENABLED + rtems_cache_enable_instruction(); + #endif + + /* Set up DBAT registers in MMU */ + cpu_init_bsp(); + + #if defined(SHOW_MORE_INIT_SETTINGS) + { extern void ShowBATS(void); + ShowBATS(); + } + #endif + + /* Read MSR */ + msr = ppc_machine_state_register(); + + /* Enable data MMU in MSR */ + msr |= MSR_DR; + + /* Update MSR */ + ppc_set_machine_state_register( msr); + + #if BSP_DATA_CACHE_ENABLED + rtems_cache_enable_data(); + #endif +} diff --git a/bsps/powerpc/gen5200/start/linkcmds.brs5l b/bsps/powerpc/gen5200/start/linkcmds.brs5l new file mode 100644 index 0000000000..58407e5f56 --- /dev/null +++ b/bsps/powerpc/gen5200/start/linkcmds.brs5l @@ -0,0 +1,15 @@ +/** + * @file + * + * Linker command file for the BRS5L board. + */ + +MEMORY { + /* For the 4k adjustment see cpuinit.c */ + RAM : ORIGIN = 0x0, LENGTH = 128M - 4k + ROM : ORIGIN = 0xffe00000, LENGTH = 2M + DPRAM : ORIGIN = 0xff000000, LENGTH = 1k + REGS : ORIGIN = 0xf0000000, LENGTH = 64k +} + +INCLUDE linkcmds.gen5200_base diff --git a/bsps/powerpc/gen5200/start/linkcmds.brs6l b/bsps/powerpc/gen5200/start/linkcmds.brs6l new file mode 100644 index 0000000000..ae80a72ad5 --- /dev/null +++ b/bsps/powerpc/gen5200/start/linkcmds.brs6l @@ -0,0 +1,15 @@ +/** + * @file + * + * Linker command file for the BRS6L board. + */ + +MEMORY { + /* For the 4k adjustment see cpuinit.c */ + RAM : ORIGIN = 0x0, LENGTH = 128M - 4k + ROM : ORIGIN = 0xff800000, LENGTH = 8M + DPRAM : ORIGIN = 0xff000000, LENGTH = 0 + REGS : ORIGIN = 0xf0000000, LENGTH = 64k +} + +INCLUDE linkcmds.gen5200_base diff --git a/bsps/powerpc/gen5200/start/linkcmds.dp2 b/bsps/powerpc/gen5200/start/linkcmds.dp2 new file mode 100644 index 0000000000..4ad76d6fce --- /dev/null +++ b/bsps/powerpc/gen5200/start/linkcmds.dp2 @@ -0,0 +1,15 @@ +/** + * @file + * + * Linker command file for the Direct Prototyping Data Processing board. + */ + +MEMORY { + /* For the 4k adjustment see cpuinit.c */ + RAM : ORIGIN = 0x0, LENGTH = 64M - 4k + ROM : ORIGIN = 0xffe00000, LENGTH = 2M + REGS : ORIGIN = 0xf0000000, LENGTH = 64k + DPRAM : ORIGIN = 0x0, LENGTH = 0 +} + +INCLUDE linkcmds.gen5200_base diff --git a/bsps/powerpc/gen5200/start/linkcmds.gen5200_base b/bsps/powerpc/gen5200/start/linkcmds.gen5200_base new file mode 100644 index 0000000000..1a92c7c9dd --- /dev/null +++ b/bsps/powerpc/gen5200/start/linkcmds.gen5200_base @@ -0,0 +1,357 @@ +/** + * @file + * + * Derived from internal linker script of GNU ld (GNU Binutils) 2.18 for elf32ppc emulation. + */ + +OUTPUT_FORMAT ("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") +OUTPUT_ARCH (powerpc) +ENTRY (start) +STARTUP (start.o) + +bsp_ram_start = ORIGIN (RAM); +bsp_ram_end = ORIGIN (RAM) + LENGTH (RAM); +bsp_ram_size = LENGTH (RAM); + +bsp_rom_start = ORIGIN (ROM); +bsp_rom_end = ORIGIN (ROM) + LENGTH (ROM); +bsp_rom_size = LENGTH (ROM); + +bsp_dpram_start = ORIGIN (DPRAM); +bsp_dpram_end = ORIGIN (DPRAM) + LENGTH (DPRAM); +bsp_dpram_size = LENGTH (DPRAM); + +bsp_section_align = 32; + +RamBase = bsp_ram_start; +RamSize = bsp_ram_size; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; + +MEMORY { + UNEXPECTED_SECTIONS : ORIGIN = 0xffffffff, LENGTH = 0 +} + +SECTIONS { + /* + * BSP: MPC5200 registers + */ + .regs (NOLOAD) : { + MBAR = .; + mpc5200 = .; + } > REGS + + /* + * BSP: Exception vectors + */ + .vectors 0x100 : { + *(.vectors) + } > RAM + + /* + * BSP: The initial stack will live in this area - between the vectors + * and the text section. + */ + + .text 0x10000 : { + /* + * BSP: Start of text section + */ + bsp_section_text_start = .; + + /* + * BSP: System startup entry + */ + KEEP (*(.entry)) + + /* + * BSP: Moved into .text from .init + */ + KEEP (*(.init)) + + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.glink) + + /* + * BSP: Special FreeBSD sysctl sections + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * BSP: Moved into .text from .* + */ + *(.rodata .rodata.* .gnu.linkonce.r.*) + KEEP (*(SORT(.rtemsroset.*))) + *(.rodata1) + *(.interp) + *(.note.gnu.build-id) + *(.hash) + *(.gnu.hash) + *(.dynsym) + *(.dynstr) + *(.gnu.version) + *(.gnu.version_d) + *(.gnu.version_r) + *(.eh_frame_hdr) + + /* + * BSP: Magic PPC stuff + */ + *(.PPC.*) + + /* + * BSP: Required by cpukit/score/src/threadhandler.c + */ + PROVIDE (_fini = .); + + /* + * BSP: Moved into .text from .fini + */ + KEEP (*(.fini)) + + . = ALIGN (bsp_section_align); + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + } > RAM + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > RAM + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } > RAM + _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)); + + .sdata2 : { + PROVIDE (_SDA2_BASE_ = 32768); + + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + + . = ALIGN (bsp_section_align); + } > RAM + + .sbss2 : { + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + + . = ALIGN (bsp_section_align); + + /* + * BSP: End of text section + */ + bsp_section_text_end = .; + } > RAM + + .data : { + /* + * BSP: Start of data section + */ + bsp_section_data_start = .; + + /* + * BSP: Moved into .data from .ctors + */ + /* 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)) + + /* + * BSP: Moved into .data from .dtors + */ + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + + /* + * BSP: Moved into .data from .* + */ + *(.tdata .tdata.* .gnu.linkonce.td.*) + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + *(.data1) + KEEP (*(.eh_frame)) + *(.gcc_except_table .gcc_except_table.*) + KEEP (*(.jcr)) + *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) + *(.fixup) + *(.got1) + *(.got2) + *(.dynamic) + *(.got) + *(.plt) + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(SORT(.rtemsrwset.*))) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + + . = ALIGN (bsp_section_align); + } > RAM + + .sdata : { + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + + . = ALIGN (bsp_section_align); + + _edata = .; + PROVIDE (edata = .); + + /* + * BSP: End of data section + */ + bsp_section_data_end = .; + } > RAM + + .sbss : { + /* + * BSP: Start of bss section + */ + bsp_section_bss_start = .; + + __bss_start = .; + + PROVIDE (__sbss_start = .); PROVIDE (___sbss_start = .); + *(.scommon) + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + PROVIDE (__sbss_end = .); PROVIDE (___sbss_end = .); + + . = ALIGN (bsp_section_align); + } > RAM + + .bss : { + *(COMMON) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + + . = ALIGN (bsp_section_align); + + __end = .; + _end = .; + PROVIDE (end = .); + + /* + * BSP: End of bss section + */ + bsp_section_bss_end = .; + } > RAM + + /* + * BSP: Section sizes + */ + bsp_section_text_size = bsp_section_text_end - bsp_section_text_start; + bsp_section_data_size = bsp_section_data_end - bsp_section_data_start; + bsp_section_bss_size = bsp_section_bss_end - bsp_section_bss_start; + + /* + * BSP: Interrupt stack + */ + bsp_interrupt_stack_start = bsp_section_bss_end; + bsp_interrupt_stack_end = bsp_interrupt_stack_start + 32k; + bsp_interrupt_stack_size = bsp_interrupt_stack_end - bsp_interrupt_stack_start; + + /* + * BSP: Work area start + */ + bsp_work_area_start = bsp_interrupt_stack_end; + WorkAreaBase = bsp_work_area_start; + + /* 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) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + + /DISCARD/ : { + *(.note.GNU-stack) *(.gnu_debuglink) + } + + /* + * 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/powerpc/gen5200/start/linkcmds.icecube b/bsps/powerpc/gen5200/start/linkcmds.icecube new file mode 100644 index 0000000000..c05d45a852 --- /dev/null +++ b/bsps/powerpc/gen5200/start/linkcmds.icecube @@ -0,0 +1,15 @@ +/** + * @file + * + * Linker command file for the IceCube board. + */ + +MEMORY { + /* For the 4k adjustment see cpuinit.c */ + RAM : ORIGIN = 0x0, LENGTH = 128M - 4k + ROM : ORIGIN = 0xffe00000, LENGTH = 2M + REGS : ORIGIN = 0xf0000000, LENGTH = 64k + DPRAM : ORIGIN = 0x0, LENGTH = 0 +} + +INCLUDE linkcmds.gen5200_base diff --git a/bsps/powerpc/gen5200/start/linkcmds.pm520_cr825 b/bsps/powerpc/gen5200/start/linkcmds.pm520_cr825 new file mode 100644 index 0000000000..49d596b577 --- /dev/null +++ b/bsps/powerpc/gen5200/start/linkcmds.pm520_cr825 @@ -0,0 +1,15 @@ +/** + * @file + * + * Linker command file for the MicroSys PM520 board. + */ + +MEMORY { + /* For the 4k adjustment see cpuinit.c */ + RAM : ORIGIN = 0x0, LENGTH = 64M - 4k + ROM : ORIGIN = 0xffe00000, LENGTH = 2M + REGS : ORIGIN = 0xf0000000, LENGTH = 64k + DPRAM : ORIGIN = 0xff000000, LENGTH = 1k +} + +INCLUDE linkcmds.gen5200_base diff --git a/bsps/powerpc/gen5200/start/linkcmds.pm520_ze30 b/bsps/powerpc/gen5200/start/linkcmds.pm520_ze30 new file mode 100644 index 0000000000..49d596b577 --- /dev/null +++ b/bsps/powerpc/gen5200/start/linkcmds.pm520_ze30 @@ -0,0 +1,15 @@ +/** + * @file + * + * Linker command file for the MicroSys PM520 board. + */ + +MEMORY { + /* For the 4k adjustment see cpuinit.c */ + RAM : ORIGIN = 0x0, LENGTH = 64M - 4k + ROM : ORIGIN = 0xffe00000, LENGTH = 2M + REGS : ORIGIN = 0xf0000000, LENGTH = 64k + DPRAM : ORIGIN = 0xff000000, LENGTH = 1k +} + +INCLUDE linkcmds.gen5200_base diff --git a/bsps/powerpc/gen5200/start/uboot_support.c b/bsps/powerpc/gen5200/start/uboot_support.c new file mode 100644 index 0000000000..f373f558e7 --- /dev/null +++ b/bsps/powerpc/gen5200/start/uboot_support.c @@ -0,0 +1,23 @@ +/* + * This file contains variables which assist the shared + * U-Boot code. + * + * COPYRIGHT (c) 1989-2008. + * 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 <stdint.h> + +#include <bsp.h> + +#if defined(HAS_UBOOT) +/* Base address of U-Boot environment variables */ +const uint8_t *uboot_environment = (const uint8_t *)0xfff40000; + +/* Length of area reserved for U-Boot environment variables */ +const size_t uboot_environment_size = 0x10000; +#endif diff --git a/bsps/powerpc/gen83xx/start/bsp_specs b/bsps/powerpc/gen83xx/start/bsp_specs new file mode 100644 index 0000000000..a37ec281c8 --- /dev/null +++ b/bsps/powerpc/gen83xx/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s -u __vectors}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/gen83xx/start/bspreset.c b/bsps/powerpc/gen83xx/start/bspreset.c new file mode 100644 index 0000000000..ebaf9f129f --- /dev/null +++ b/bsps/powerpc/gen83xx/start/bspreset.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2008 + * 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 <bsp.h> +#include <bsp/bootcard.h> + +#include <mpc83xx/mpc83xx.h> + +void bsp_reset(void) +{ + mpc83xx_reset(); +} diff --git a/bsps/powerpc/gen83xx/start/bsprestart.c b/bsps/powerpc/gen83xx/start/bsprestart.c new file mode 100644 index 0000000000..4a2d298de0 --- /dev/null +++ b/bsps/powerpc/gen83xx/start/bsprestart.c @@ -0,0 +1,47 @@ +/* + * 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 <bsp.h> +#include <bsp/u-boot.h> + +#include <libcpu/powerpc-utility.h> + +void bsp_restart(void *addr) +{ + rtems_interrupt_level level; + void (*start)(void) = addr; + #ifdef HAS_UBOOT + const void *mem_begin = (const void *) bsp_uboot_board_info.bi_memstart; + size_t mem_size = bsp_uboot_board_info.bi_memsize; + #else /* HAS_UBOOT */ + const void *mem_begin = bsp_ram_start; + size_t mem_size = (size_t) bsp_ram_size; + #endif /* HAS_UBOOT */ + uint32_t hid0; + + rtems_interrupt_disable(level); + (void) level; /* avoid set but not used warning */ + + hid0 = PPC_SPECIAL_PURPOSE_REGISTER(HID0); + + if ((hid0 & HID0_DCE) != 0) { + rtems_cache_flush_multiple_data_lines(mem_begin, mem_size); + } + + hid0 &= ~(HID0_DCE | HID0_ICE); + + PPC_SET_SPECIAL_PURPOSE_REGISTER(HID0, hid0); + + (*start)(); +} diff --git a/bsps/powerpc/gen83xx/start/bspstart.c b/bsps/powerpc/gen83xx/start/bspstart.c new file mode 100644 index 0000000000..cd729a8e17 --- /dev/null +++ b/bsps/powerpc/gen83xx/start/bspstart.c @@ -0,0 +1,129 @@ +/** + * @file + * + * @ingroup mpc83xx + * + * @brief Source for BSP startup code. + */ + +/* + * Copyright (c) 2008-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/counter.h> + +#include <libchip/ns16550.h> + +#include <libcpu/powerpc-utility.h> + +#include <bsp.h> +#include <bsp/vectors.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> +#include <bsp/u-boot.h> +#include <bsp/console-termios.h> + +/* Configuration parameters for console driver, ... */ +unsigned int BSP_bus_frequency; + +/* Configuration parameter for clock driver */ +uint32_t bsp_time_base_frequency; + +/* Legacy */ +uint32_t bsp_clicks_per_usec; + +/* Default decrementer exception handler */ +static int mpc83xx_decrementer_exception_handler( BSP_Exception_frame *frame, unsigned number) +{ + ppc_set_decrementer_register(UINT32_MAX); + + return 0; +} + +void bsp_start( void) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + unsigned long i = 0; + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() function + * store the result in global variables so that it can be used latter... + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + /* Basic CPU initialization */ + cpu_init(); + + /* + * Enable instruction and data caches. Do not force writethrough mode. + */ + +#ifdef BSP_INSTRUCTION_CACHE_ENABLED + rtems_cache_enable_instruction(); +#endif + +#ifdef BSP_DATA_CACHE_ENABLED + rtems_cache_enable_data(); +#endif + + /* + * This is evaluated during runtime, so it should be ok to set it + * before we initialize the drivers. + */ + + /* Initialize some device driver parameters */ + +#ifdef HAS_UBOOT + BSP_bus_frequency = bsp_uboot_board_info.bi_busfreq; +#else /* HAS_UBOOT */ + BSP_bus_frequency = BSP_CLKIN_FRQ * BSP_SYSPLL_MF / BSP_SYSPLL_CKID; +#endif /* HAS_UBOOT */ + bsp_time_base_frequency = BSP_bus_frequency / 4; + bsp_clicks_per_usec = bsp_time_base_frequency / 1000000; + rtems_counter_initialize_converter(bsp_time_base_frequency); + + /* Initialize some console parameters */ + for (i = 0; i < console_device_count; ++i) { + ns16550_context *ctx = (ns16550_context *) console_device_table[i].context; + + ctx->clock = BSP_bus_frequency; + + #ifdef HAS_UBOOT + ctx->initial_baud = bsp_uboot_board_info.bi_baudrate; + #endif + } + + /* Initialize exception handler */ +#ifndef BSP_DATA_CACHE_ENABLED + ppc_exc_cache_wb_check = 0; +#endif + ppc_exc_initialize( + (uintptr_t) bsp_section_work_begin, + rtems_configuration_get_interrupt_stack_size() + ); + + /* Install default handler for the decrementer exception */ + sc = ppc_exc_set_handler( ASM_DEC_VECTOR, mpc83xx_decrementer_exception_handler); + if (sc != RTEMS_SUCCESSFUL) { + rtems_panic("cannot install decrementer exception handler"); + } + + /* Initalize interrupt support */ + bsp_interrupt_initialize(); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Exit from bspstart\n"); +#endif +} diff --git a/bsps/powerpc/gen83xx/start/cpuinit.c b/bsps/powerpc/gen83xx/start/cpuinit.c new file mode 100644 index 0000000000..1b0fd1efef --- /dev/null +++ b/bsps/powerpc/gen83xx/start/cpuinit.c @@ -0,0 +1,329 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC83xx BSP | ++-----------------------------------------------------------------+ +| Partially based on the code references which are named below. | +| Adaptions, modifications, enhancements and any recent parts of | +| the code are: | +| Copyright (c) 2005 | +| 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. | +| | ++-----------------------------------------------------------------+ +| this file contains the code to initialize the cpu | +\*===============================================================*/ + + +/***********************************************************************/ +/* */ +/* Module: cpuinit.c */ +/* Date: 07/17/2003 */ +/* Purpose: RTEMS MPC5x00 C level startup code */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Description: This file contains additional functions for */ +/* initializing the MPC5x00 CPU */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Code */ +/* References: MPC8260ads additional CPU initialization */ +/* Module: cpuinit.c */ +/* Project: RTEMS 4.6.0pre1 / MCF8260ads BSP */ +/* Version 1.1 */ +/* Date: 10/22/2002 */ +/* */ +/* Author(s) / Copyright(s): */ +/* */ +/* Written by Jay Monkman (jmonkman@frasca.com) */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Partially based on the code references which are named above. */ +/* Adaptions, modifications, enhancements and any recent parts of */ +/* the code are under the right of */ +/* */ +/* IPR Engineering, Dachauer Straße 38, D-80335 München */ +/* Copyright(C) 2003 */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* IPR Engineering makes no representation or warranties with */ +/* respect to the performance of this computer program, and */ +/* specifically disclaims any responsibility for any damages, */ +/* special or consequential, connected with the use of this program. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Version history: 1.0 */ +/* */ +/***********************************************************************/ + +#include <stdbool.h> +#include <string.h> + +#include <libcpu/powerpc-utility.h> +#include <libcpu/mmu.h> + +#include <mpc83xx/mpc83xx.h> + +#include <bsp.h> +#include <bsp/u-boot.h> + +#define SET_DBAT( n, uv, lv) \ + do { \ + PPC_SET_SPECIAL_PURPOSE_REGISTER( DBAT##n##L, lv); \ + PPC_SET_SPECIAL_PURPOSE_REGISTER( DBAT##n##U, uv); \ + } while (0) + +#define SET_IBAT( n, uv, lv) \ + do { \ + PPC_SET_SPECIAL_PURPOSE_REGISTER( IBAT##n##L, lv); \ + PPC_SET_SPECIAL_PURPOSE_REGISTER( IBAT##n##U, uv); \ + } while (0) + +static void calc_dbat_regvals( + BAT *bat_ptr, + uint32_t base_addr, + uint32_t size, + bool flg_w, + bool flg_i, + bool flg_m, + bool flg_g, + uint32_t flg_bpp +) +{ + uint32_t block_mask = 0xffffffff; + uint32_t end_addr = base_addr + size - 1; + + /* Determine block mask, that overlaps the whole block */ + while ((end_addr & block_mask) != (base_addr & block_mask)) { + block_mask <<= 1; + } + + bat_ptr->batu.bepi = base_addr >> (32 - 15); + bat_ptr->batu.bl = ~(block_mask >> (28 - 11)); + bat_ptr->batu.vs = 1; + bat_ptr->batu.vp = 1; + + bat_ptr->batl.brpn = base_addr >> (32 - 15); + bat_ptr->batl.w = flg_w; + bat_ptr->batl.i = flg_i; + bat_ptr->batl.m = flg_m; + bat_ptr->batl.g = flg_g; + bat_ptr->batl.pp = flg_bpp; +} + +static void clear_mmu_regs( void) +{ + uint32_t i; + + /* Clear segment registers */ + for (i = 0;i < 16;i++) { + __asm__ volatile( "mtsrin %0, %1\n" : : "r" (i * 0x1000), "r" (i << (31 - 3))); + } + + /* Clear TLBs */ + for (i = 0;i < 32;i++) { + __asm__ volatile( "tlbie %0\n" : : "r" (i << (31 - 19))); + } +} + +void cpu_init( void) +{ + BAT dbat, ibat; + uint32_t msr; + uint32_t hid0; + + /* Clear MMU and segment registers */ + clear_mmu_regs(); + + /* Clear caches */ + hid0 = PPC_SPECIAL_PURPOSE_REGISTER(HID0); + if ((hid0 & (HID0_ICE | HID0_DCE)) == 0) { + hid0 &= ~(HID0_ILOCK | HID0_DLOCK | HID0_ICE | HID0_DCE); + PPC_SET_SPECIAL_PURPOSE_REGISTER(HID0, hid0); + hid0 |= HID0_ICFI | HID0_DCI; + PPC_SET_SPECIAL_PURPOSE_REGISTER(HID0, hid0); + hid0 &= ~(HID0_ICFI | HID0_DCI); + PPC_SET_SPECIAL_PURPOSE_REGISTER(HID0, hid0); + } + + /* + * Set up IBAT registers in MMU + */ + + memset(&ibat, 0, sizeof( ibat)); + SET_IBAT( 2, ibat.batu, ibat.batl); + SET_IBAT( 3, ibat.batu, ibat.batl); + SET_IBAT( 4, ibat.batu, ibat.batl); + SET_IBAT( 5, ibat.batu, ibat.batl); + SET_IBAT( 6, ibat.batu, ibat.batl); + SET_IBAT( 7, ibat.batu, ibat.batl); + + calc_dbat_regvals( + &ibat, + #ifdef HAS_UBOOT + bsp_uboot_board_info.bi_memstart, + bsp_uboot_board_info.bi_memsize, + #else /* HAS_UBOOT */ + (uint32_t) bsp_ram_start, + (uint32_t) bsp_ram_size, + #endif /* HAS_UBOOT */ + false, + false, + false, + false, + BPP_RX + ); + SET_IBAT( 0, ibat.batu, ibat.batl); + + calc_dbat_regvals( + &ibat, + #ifdef HAS_UBOOT + bsp_uboot_board_info.bi_flashstart, + bsp_uboot_board_info.bi_flashsize, + #else /* HAS_UBOOT */ + (uint32_t) bsp_rom_start, + (uint32_t) bsp_rom_size, + #endif /* HAS_UBOOT */ + false, + false, + false, + false, + BPP_RX + ); + SET_IBAT( 1, ibat.batu, ibat.batl); + + /* + * Set up DBAT registers in MMU + */ + + memset(&dbat, 0, sizeof( dbat)); + SET_DBAT( 3, dbat.batu, dbat.batl); + SET_DBAT( 4, dbat.batu, dbat.batl); + SET_DBAT( 5, dbat.batu, dbat.batl); + SET_DBAT( 6, dbat.batu, dbat.batl); + SET_DBAT( 7, dbat.batu, dbat.batl); + + calc_dbat_regvals( + &dbat, + #ifdef HAS_UBOOT + bsp_uboot_board_info.bi_memstart, + bsp_uboot_board_info.bi_memsize, + #else /* HAS_UBOOT */ + (uint32_t) bsp_ram_start, + (uint32_t) bsp_ram_size, + #endif /* HAS_UBOOT */ + false, + false, + false, + false, + BPP_RW + ); + SET_DBAT( 0, dbat.batu, dbat.batl); + + calc_dbat_regvals( + &dbat, + #ifdef HAS_UBOOT + bsp_uboot_board_info.bi_flashstart, + bsp_uboot_board_info.bi_flashsize, + #else /* HAS_UBOOT */ + (uint32_t) bsp_rom_start, + (uint32_t) bsp_rom_size, + #endif /* HAS_UBOOT */ + #ifdef MPC83XX_HAS_NAND_LP_FLASH_ON_CS0 + false, + true, + false, + true, + BPP_RW + #else + true, + false, + false, + false, + BPP_RX + #endif + ); + SET_DBAT( 1, dbat.batu, dbat.batl); + + calc_dbat_regvals( + &dbat, + #ifdef HAS_UBOOT + bsp_uboot_board_info.bi_immrbar, + #else /* HAS_UBOOT */ + (uint32_t) IMMRBAR, + #endif /* HAS_UBOOT */ + #if MPC83XX_CHIP_TYPE / 10 == 830 + 2 * 1024 * 1024, + #else + 1024 * 1024, + #endif + false, + true, + false, + true, + BPP_RW + ); + SET_DBAT( 2, dbat.batu, dbat.batl); + +#if defined(MPC83XX_BOARD_HSC_CM01) + calc_dbat_regvals( + &dbat, + FPGA_START, + FPGA_SIZE, + true, + true, + true, + false, + BPP_RW + ); + SET_DBAT(3,dbat.batu,dbat.batl); +#endif + +#ifdef MPC83XX_BOARD_MPC8313ERDB + /* Enhanced Local Bus Controller (eLBC) */ + calc_dbat_regvals( + &dbat, + 0xfa000000, + 128 * 1024, + false, + true, + false, + true, + BPP_RW + ); + SET_DBAT( 3, dbat.batu, dbat.batl); +#endif /* MPC83XX_BOARD_MPC8313ERDB */ + + /* Read MSR */ + msr = ppc_machine_state_register(); + + /* Enable data and instruction MMU in MSR */ + msr |= MSR_DR | MSR_IR; + + /* Enable FPU in MSR */ + msr |= MSR_FP; + + /* Update MSR */ + ppc_set_machine_state_register( msr); + + /* + * In HID0: + * - Enable dynamic power management + * - Enable machine check interrupts + */ + PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( HID0, HID0_EMCP | HID0_DPM); + + /* Enable timebase clock */ + mpc83xx.syscon.spcr |= M83xx_SYSCON_SPCR_TBEN; +} diff --git a/bsps/powerpc/gen83xx/start/linkcmds b/bsps/powerpc/gen83xx/start/linkcmds new file mode 100644 index 0000000000..094fdf51af --- /dev/null +++ b/bsps/powerpc/gen83xx/start/linkcmds @@ -0,0 +1,19 @@ +/** + * @file + * + * Default linker script -- copy of linkcmds.mpc8313erdb + * for MPC8313E Reference Design Board. + * + * This exists simply for consistency so autoconf tests will + * be able to compile against this BSP. + */ + +EXTERN (__vectors) + +MEMORY { + RAM : ORIGIN = 0x0, LENGTH = 128M + ROM : ORIGIN = 0xfe000000, LENGTH = 8M + MPC83XX_REGS : ORIGIN = 0xe0000000, LENGTH = 256k +} + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/gen83xx/start/linkcmds.br_uid b/bsps/powerpc/gen83xx/start/linkcmds.br_uid new file mode 100644 index 0000000000..3d8c3a154a --- /dev/null +++ b/bsps/powerpc/gen83xx/start/linkcmds.br_uid @@ -0,0 +1,10 @@ +MEMORY { + RESCONF : ORIGIN = 0x0, LENGTH = 0x100 + VECTORS : ORIGIN = 0x100, LENGTH = 0x10000 - 0x100 + WORK : ORIGIN = 0x10000, LENGTH = 256M - 0x10000 + ROM : ORIGIN = 0xfe000000, LENGTH = 2M +} + +REGION_ALIAS ("START", WORK); + +INCLUDE linkcmds.mpc83xx diff --git a/bsps/powerpc/gen83xx/start/linkcmds.hsc_cm01 b/bsps/powerpc/gen83xx/start/linkcmds.hsc_cm01 new file mode 100644 index 0000000000..d5b4b1e145 --- /dev/null +++ b/bsps/powerpc/gen83xx/start/linkcmds.hsc_cm01 @@ -0,0 +1,10 @@ +MEMORY { + RESCONF : ORIGIN = 0x0, LENGTH = 0x100 + VECTORS : ORIGIN = 0x100, LENGTH = 0x10000 - 0x100 + WORK : ORIGIN = 0x10000, LENGTH = 256M - 0x10000 + ROM : ORIGIN = 0xfe000000, LENGTH = 8M +} + +REGION_ALIAS ("START", WORK); + +INCLUDE linkcmds.mpc83xx diff --git a/bsps/powerpc/gen83xx/start/linkcmds.mpc8309som b/bsps/powerpc/gen83xx/start/linkcmds.mpc8309som new file mode 100644 index 0000000000..d5b4b1e145 --- /dev/null +++ b/bsps/powerpc/gen83xx/start/linkcmds.mpc8309som @@ -0,0 +1,10 @@ +MEMORY { + RESCONF : ORIGIN = 0x0, LENGTH = 0x100 + VECTORS : ORIGIN = 0x100, LENGTH = 0x10000 - 0x100 + WORK : ORIGIN = 0x10000, LENGTH = 256M - 0x10000 + ROM : ORIGIN = 0xfe000000, LENGTH = 8M +} + +REGION_ALIAS ("START", WORK); + +INCLUDE linkcmds.mpc83xx diff --git a/bsps/powerpc/gen83xx/start/linkcmds.mpc8313erdb b/bsps/powerpc/gen83xx/start/linkcmds.mpc8313erdb new file mode 100644 index 0000000000..717b3b4866 --- /dev/null +++ b/bsps/powerpc/gen83xx/start/linkcmds.mpc8313erdb @@ -0,0 +1,10 @@ +MEMORY { + RESCONF : ORIGIN = 0x0, LENGTH = 0x100 + VECTORS : ORIGIN = 0x100, LENGTH = 0x10000 - 0x100 + WORK : ORIGIN = 0x10000, LENGTH = 128M - 0x10000 + ROM : ORIGIN = 0xfe000000, LENGTH = 8M +} + +REGION_ALIAS ("START", WORK); + +INCLUDE linkcmds.mpc83xx diff --git a/bsps/powerpc/gen83xx/start/linkcmds.mpc8349eamds b/bsps/powerpc/gen83xx/start/linkcmds.mpc8349eamds new file mode 100644 index 0000000000..d5b4b1e145 --- /dev/null +++ b/bsps/powerpc/gen83xx/start/linkcmds.mpc8349eamds @@ -0,0 +1,10 @@ +MEMORY { + RESCONF : ORIGIN = 0x0, LENGTH = 0x100 + VECTORS : ORIGIN = 0x100, LENGTH = 0x10000 - 0x100 + WORK : ORIGIN = 0x10000, LENGTH = 256M - 0x10000 + ROM : ORIGIN = 0xfe000000, LENGTH = 8M +} + +REGION_ALIAS ("START", WORK); + +INCLUDE linkcmds.mpc83xx diff --git a/bsps/powerpc/gen83xx/start/linkcmds.mpc83xx b/bsps/powerpc/gen83xx/start/linkcmds.mpc83xx new file mode 100644 index 0000000000..4ddbcd6f76 --- /dev/null +++ b/bsps/powerpc/gen83xx/start/linkcmds.mpc83xx @@ -0,0 +1,47 @@ +bsp_ram_start = ORIGIN (RESCONF); +bsp_ram_end = ORIGIN (WORK) + LENGTH (WORK); +bsp_ram_size = bsp_ram_end - bsp_ram_start; + +bsp_rom_start = ORIGIN (ROM); +bsp_rom_size = LENGTH (ROM); +bsp_rom_end = bsp_rom_start + bsp_rom_size; + +IMMRBAR = 0xe0000000; +mpc83xx = IMMRBAR; + +EXTERN (__vectors) + +MEMORY { + EMPTY : ORIGIN = 0x0, LENGTH = 0 +} + +SECTIONS { + .resconf : { + *(.resconf) + } > RESCONF AT > RESCONF + + .vectors : { + *(.vectors) + } > VECTORS AT > VECTORS +} + +REGION_ALIAS ("REGION_START", START); +REGION_ALIAS ("REGION_FAST_TEXT", WORK); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", WORK); +REGION_ALIAS ("REGION_TEXT", WORK); +REGION_ALIAS ("REGION_TEXT_LOAD", WORK); +REGION_ALIAS ("REGION_RODATA", WORK); +REGION_ALIAS ("REGION_RODATA_LOAD", WORK); +REGION_ALIAS ("REGION_FAST_DATA", WORK); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", WORK); +REGION_ALIAS ("REGION_DATA", WORK); +REGION_ALIAS ("REGION_DATA_LOAD", WORK); +REGION_ALIAS ("REGION_BSS", WORK); +REGION_ALIAS ("REGION_RWEXTRA", WORK); +REGION_ALIAS ("REGION_WORK", WORK); +REGION_ALIAS ("REGION_STACK", WORK); +REGION_ALIAS ("REGION_NOCACHE", EMPTY); +REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/gen83xx/start/uboot_support.c b/bsps/powerpc/gen83xx/start/uboot_support.c new file mode 100644 index 0000000000..295059889d --- /dev/null +++ b/bsps/powerpc/gen83xx/start/uboot_support.c @@ -0,0 +1,24 @@ +/* + * This file contains variables which assist the shared + * U-Boot code. + * + * COPYRIGHT (c) 1989-2008. + * 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 <stdint.h> + +#include <bsp.h> + +#if defined(HAS_UBOOT) +/* XXX TODO fill in with real information */ +/* Base address of U-Boot environment variables */ +const uint8_t *uboot_environment = (const uint8_t *) 0x00000000; + +/* Length of area reserved for U-Boot environment variables */ +const size_t *uboot_environment_size = (const size_t *) 0x00010000; +#endif diff --git a/bsps/powerpc/haleakala/start/bsp_specs b/bsps/powerpc/haleakala/start/bsp_specs new file mode 100644 index 0000000000..5752caaca0 --- /dev/null +++ b/bsps/powerpc/haleakala/start/bsp_specs @@ -0,0 +1,10 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} + diff --git a/bsps/powerpc/haleakala/start/bspstart.c b/bsps/powerpc/haleakala/start/bspstart.c new file mode 100644 index 0000000000..18b45f33df --- /dev/null +++ b/bsps/powerpc/haleakala/start/bspstart.c @@ -0,0 +1,195 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * Author: Thomas Doerfler <td@imd.m.isar.de> + * IMD Ingenieurbuero fuer Microcomputertechnik + * + * COPYRIGHT (c) 1998 by IMD + * + * Changes from IMD are covered by the original distributions terms. + * This file has been derived from the papyrus BSP: + * + * Author: Andrew Bray <andy@i-cubed.co.uk> + * + * COPYRIGHT (c) 1995 by i-cubed ltd. + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of i-cubed limited not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * i-cubed limited makes no representations about the suitability + * of this software for any purpose. + * + * Modifications for spooling console driver and control of memory layout + * with linker command file by + * Thomas Doerfler <td@imd.m.isar.de> + * for these modifications: + * COPYRIGHT (c) 1997 by IMD, Puchheim, Germany. + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies. IMD makes no representations about the suitability + * of this software for any purpose. + * + * Derived from c/src/lib/libbsp/no_cpu/no_bsp/startup/bspstart.c: + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * + * Modifications for PPC405GP by Dennis Ehlin + * + * Further modified for the PPC405EX Haleakala board by + * Michael Hamel ADInstruments Ltd May 2008 + */ +#include <string.h> +#include <fcntl.h> + +#include <rtems/bspIo.h> +#include <rtems/counter.h> + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/uart.h> +#include <bsp/irq.h> +#include <libcpu/powerpc-utility.h> +#include <bsp/vectors.h> +#include <ppc4xx/ppc405gp.h> +#include <ppc4xx/ppc405ex.h> + +#include <stdio.h> + +LINKER_SYMBOL(intrStack_start); +LINKER_SYMBOL(intrStack_size); +/* + * Driver configuration parameters + */ + +/* Expected by clock.c */ +uint32_t bsp_clicks_per_usec; + +/*-------------------- Haleakala-specific UART setup -------------------------*/ + +static void +EarlyUARTInit(int baudRate) +{ + volatile uint8_t* up = (uint8_t*)(BSP_UART_IOBASE_COM1); + int divider = BSP_UART_BAUD_BASE / baudRate; + up[LCR] = DLAB; /* Access DLM/DLL */ + up[DLL] = divider & 0x0FF; + up[DLM] = divider >> 8; + up[LCR] = CHR_8_BITS; + up[MCR] = DTR | RTS; + up[FCR] = FIFO_EN | XMIT_RESET | RCV_RESET; + up[THR] = '+'; +} + + +static void +InitUARTClock(void) +{ + uint32_t reg; + mfsdr(SDR0_UART0,reg); + reg &= ~0x008000FF; + reg |= 0x00800001; /* Ext clock, div 1 */ + mtsdr(SDR0_UART0,reg); +} + +static void GPIO_AlternateSelect(int bitnum, int source) +/* PPC405EX: select a GPIO function for the specified pin */ +{ + int shift; + unsigned long value, mask; + GPIORegisters* gpioPtr = (GPIORegisters*)(GPIOAddress); + + shift = (31 - bitnum) & 0xF; + value = (source & 3) << (shift*2); + mask = 3 << (shift*2); + if (bitnum <= 15) { + gpioPtr->OSRL = (gpioPtr->OSRL & ~mask) | value; + gpioPtr->TSRL = (gpioPtr->TSRL & ~mask) | value; + } else { + gpioPtr->OSRH = (gpioPtr->OSRH & ~mask) | value; + gpioPtr->TSRH = (gpioPtr->TSRH & ~mask) | value; + } +} + +static void Init_FPGA(void) +{ + /* Have to write to the FPGA to enable the UART drivers */ + /* Have to enable CS2 as an output in GPIO to get the FPGA working */ + mtebc(EBC0_B2CR,0xF0018000); /* Set up CS2 at 0xF0000000 */ + mtebc(EBC0_B2AP,0x9400C800); + GPIO_AlternateSelect(9,1); /* GPIO9 = PerCS2 */ + { + unsigned long *fpgaPtr = (unsigned long*)(0xF0000000); + unsigned long n; + n = *(fpgaPtr); + n &= ~0x00100; /* User LEDs on */ + n |= 0x30000; /* UART 0 and 1 transcievers on! */ + *fpgaPtr = n; + } +} + +/*===================================================================*/ + +static void +DirectUARTWrite(const char c) +{ + volatile uint8_t* up = (uint8_t*)(BSP_UART_IOBASE_COM1); + while ((up[LSR] & THRE) == 0) { ; } + up[THR] = c; +} + +/* We will provide our own printk output function as it may get used early */ +BSP_output_char_function_type BSP_output_char = DirectUARTWrite; +BSP_polling_getchar_function_type BSP_poll_char = NULL; + +/*===================================================================*/ + +void bsp_start( void ) +{ + /* Get the UART clock initialized first in case we call printk */ + + InitUARTClock(); + Init_FPGA(); + EarlyUARTInit(115200); + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function store the result in global variables + * so that it can be used later... + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + /* + * initialize the device driver parameters + */ + + /* Set globals visible to clock.c */ + /* timebase register ticks/microsecond = CPU Clk in MHz */ + bsp_clicks_per_usec = 400; + rtems_counter_initialize_converter(bsp_clicks_per_usec * 1000000); + + /* + * Initialize default raw exception handlers. + */ + ppc_exc_initialize( + (uintptr_t) intrStack_start, + (uintptr_t) intrStack_size + ); + + /* + * Install our own set of exception vectors + */ + BSP_rtems_irq_mng_init(0); +} diff --git a/bsps/powerpc/haleakala/start/linkcmds b/bsps/powerpc/haleakala/start/linkcmds new file mode 100644 index 0000000000..8c06a5103b --- /dev/null +++ b/bsps/powerpc/haleakala/start/linkcmds @@ -0,0 +1,277 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the 405GP/EX + * This file is intended to be used together with dlentry.s + * it will generate downloadable code + * + * Modifications for gen405 by Dennis Ehlin + * Modifications for virtex by Keith, Greg, and Bob + * Modifications for 405GP/EX by Michael Hamel + */ + +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") +OUTPUT_ARCH(powerpc) +ENTRY(download_entry) +EXTERN(__vectors) + +kIntrStackSize = 16K; +kMainStackSize = 64K; + +RamBase = DEFINED(RamBase) ? RamBase : 0; +RamSize = DEFINED(RamSize) ? RamSize : 256M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; + +MEMORY { + RAM : ORIGIN = 0, LENGTH = 256M + /*FLASH : ORIGIN = 0xFFE00000, LENGTH = 16M*/ +} + + +SECTIONS +{ + /* First 16K is occupied by exception vectors and anything else we want to put there */ + .text 0x4000: + { + text.start = . ; + *(.entry) + *(.entry2) + *(.text*) + *(.rodata*) + *(.rodata1) + KEEP (*(SORT(.rtemsroset.*))) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* C++ constructors/destructors */ + *(.gnu.linkonce.t*) + + /* Initialization and finalization code. + * + * Various files can provide initialization and finalization functions. + * The bodies of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues from + * ecrti.o and function epilogues from ecrtn.o. ecrti.o must be linked + * first; ecrtn.o must be linked last. Because these are wildcards, it + * doesn't matter if the user does not actually link against ecrti.o and + * ecrtn.o; the linker won't look for a file to match a wildcard. The + * wildcard also means that it doesn't matter which directory ecrti.o + * and ecrtn.o are in. + */ + PROVIDE (_init = .); + *ecrti.o(.init) + *(.init) + *ecrtn.o(.init) + + PROVIDE (_fini = .); + *ecrti.o(.fini) + *(.fini) + *ecrtn.o(.init) + + /* + * C++ constructors and destructors for static objects. + * PowerPC EABI does not use crtstuff yet, so we build "old-style" + * constructor and destructor lists that begin with the list length + * end terminate with a NULL entry. + */ + + PROVIDE (__CTOR_LIST__ = .); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + LONG(0) + PROVIDE (__CTOR_END__ = .); + + PROVIDE (__DTOR_LIST__ = .); + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + LONG(0) + PROVIDE (__DTOR_END__ = .); + + /* Exception frame info */ + *(.eh_frame) + /* Miscellaneous read-only data */ + _rodata_start = . ; + *(.gnu.linkonce.r*) + *(.lit) + *(.shdata) + *(.rodata) + *(.rodata1) + *(.descriptors) + *(rom_ver) + _erodata = .; + + PROVIDE (__EXCEPT_START__ = .); + *(.gcc_except_table*) + PROVIDE (__EXCEPT_END__ = .); + __GOT_START__ = .; + s.got = .; + *(.got.plt) + *(.got) + *(.got1) + PROVIDE (__GOT2_START__ = .); + PROVIDE (_GOT2_START_ = .); + *(.got2) + PROVIDE (__GOT2_END__ = .); + PROVIDE (_GOT2_END_ = .); + + PROVIDE (__FIXUP_START__ = .); + PROVIDE (_FIXUP_START_ = .); + *(.fixup) + PROVIDE (_FIXUP_END_ = .); + PROVIDE (__FIXUP_END__ = .); + + + /* Various possible names for the end of the .text section */ + etext = ALIGN(0x10); + _etext = .; + + *(.lit) + *(.shdata) + _endtext = ALIGN(0x10); + text.end = .; + text.size = text.end - text.start; + } >RAM + + text.size = text.end - text.start; + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >RAM + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >RAM + + _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)); + + .jcr : { KEEP (*(.jcr)) } >RAM + + .rel.dyn : { + *(.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.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) + *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) + *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) + *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + } >RAM + .rela.dyn : { + *(.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.got1) + *(.rela.got2) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } >RAM + + + /* Initialised large data */ + .data ( . ) : + { + . = ALIGN (4); + data.start = .; + *(.data) + *(.data1) + KEEP (*(SORT(.rtemsrwset.*))) + *(.data.* .gnu.linkonce.d.*) + data.end = .; + } > RAM + + /* Initialised small data addressed as offsets from r13 */ + .sdata : { + . = ALIGN (4); + PROVIDE (__SDATA_START__ = .); + sdata.start = .; + *(.sdata*) + *(.gnu.linkonce.s.*) + sdata.end = .; + } > RAM + + /* Zeroed small data addressed as offsets from r13 */ + .sbss : { + . = ALIGN (4); + PROVIDE(__SBSS_START__ = .); + sbss.start = .; + *(.sbss .sbss.* *.gnu.linkonce.sb.*); + sbss.end = .; + } > RAM + PROVIDE(__SBSS_END__ = .); + + /* Zeroed large data */ + .bss : { + . = ALIGN (4); + bss.start = .; + *(.bss .bss* .gnu.linkonce.b*) + . = ALIGN(4); + bss.end = .; + } > RAM + + bss.size = bss.end - bss.start; + sbss.size = sbss.end - sbss.start; + + /* Interrupt stack: align to a cache-line boundary */ + IntrStack_start = ALIGN(0x20); + . += kIntrStackSize; + intrStack = .; + PROVIDE(intrStackPtr = intrStack); + PROVIDE(intrStack_start = IntrStack_start); + PROVIDE(intrStack_size = kIntrStackSize); + + /* Main stack: align to a cache-line boundary */ + stack.start = ALIGN(0x20); + . += kMainStackSize; + stack.end = .; + + /* RTEMS workspace: size specified by application */ + WorkAreaBase = ALIGN(0x20); + + /* Debugging information */ + .line 0 : { *(.line) } + .debug 0 : { *(.debug) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_aregion 0 : { *(.debug_aregion) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } +} diff --git a/bsps/powerpc/motorola_powerpc/start/bsp_specs b/bsps/powerpc/motorola_powerpc/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/motorola_powerpc/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/motorola_powerpc/start/bspreset.c b/bsps/powerpc/motorola_powerpc/start/bspreset.c new file mode 100644 index 0000000000..0931badae4 --- /dev/null +++ b/bsps/powerpc/motorola_powerpc/start/bspreset.c @@ -0,0 +1,28 @@ +#include <bsp.h> +#include <rtems/bspIo.h> +#include <libcpu/stackTrace.h> +#include <bsp/bootcard.h> + +/*-------------------------------------------------------------------------+ +| Function: bsp_reset +| Description: Reboot the PC. +| Global Variables: None. +| Arguments: None. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +void bsp_reset(void) +{ + printk("Printing a stack trace for your convenience :-)\n"); + CPU_print_stack(); + /* shutdown and reboot */ + +#if defined(mvme2100) + *(unsigned char*)0xffe00000 |= 0x80; +#else + /* Memory-mapped Port 92 PIB device access + *(unsigned char*)0x80000092 |= 0x01; + */ + outb(1, 0x92); + +#endif +} /* bsp_reset */ diff --git a/bsps/powerpc/motorola_powerpc/start/linkcmds b/bsps/powerpc/motorola_powerpc/start/linkcmds new file mode 100644 index 0000000000..ae44032d4f --- /dev/null +++ b/bsps/powerpc/motorola_powerpc/start/linkcmds @@ -0,0 +1,6 @@ +INPUT(vectors_entry.o) +STARTUP(start.o) +ENTRY(__rtems_entry_point) +EXTERN(_vectors) + +INCLUDE linkcmds.share diff --git a/bsps/powerpc/mpc55xxevb/start/bsp_specs b/bsps/powerpc/mpc55xxevb/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/mpc55xxevb/start/bspgetworkarea.c b/bsps/powerpc/mpc55xxevb/start/bspgetworkarea.c new file mode 100644 index 0000000000..e7d988cf87 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/bspgetworkarea.c @@ -0,0 +1,53 @@ +/** + * @file + * + * @ingroup mpc55xx + */ + +/* + * Copyright (c) 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/bootcard.h> +#include <bsp/linker-symbols.h> + +LINKER_SYMBOL(bsp_section_work_bonus_begin); +LINKER_SYMBOL(bsp_section_work_bonus_size); + +void bsp_work_area_initialize(void) +{ + Heap_Area areas [] = { + { + bsp_section_work_begin, + (uintptr_t) bsp_section_work_size + }, { + bsp_section_work_bonus_begin, + (uintptr_t) bsp_section_work_bonus_size + } + }; + + #ifdef BSP_INTERRUPT_STACK_AT_WORK_AREA_BEGIN + { + uint32_t stack_size = rtems_configuration_get_interrupt_stack_size(); + + areas [0].begin = (char *) areas [0].begin + stack_size; + areas [0].size -= stack_size; + } + #endif + + bsp_work_area_initialize_with_table( + areas, + sizeof(areas) / sizeof(areas [0]) + ); +} diff --git a/bsps/powerpc/mpc55xxevb/start/bspreset.c b/bsps/powerpc/mpc55xxevb/start/bspreset.c new file mode 100644 index 0000000000..a99b3856d3 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/bspreset.c @@ -0,0 +1,38 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief BSP reset. + */ + +/* + * 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 <stdbool.h> + +#include <bsp/bootcard.h> + +#include <mpc55xx/regs.h> + +void bsp_reset(void) +{ + while (true) { + #if MPC55XX_CHIP_FAMILY == 564 + /* TODO */ + #else + SIU.SRCR.R = 1U << (31 - 0); + #endif + } +} diff --git a/bsps/powerpc/mpc55xxevb/start/bspstart.c b/bsps/powerpc/mpc55xxevb/start/bspstart.c new file mode 100644 index 0000000000..9042fc3864 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/bspstart.c @@ -0,0 +1,104 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief BSP startup code. + */ + +/* + * Copyright (c) 2008-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. + */ + +#include <mpc55xx/mpc55xx.h> +#include <mpc55xx/regs.h> +#include <mpc55xx/edma.h> +#include <mpc55xx/emios.h> + +#include <string.h> + +#include <rtems.h> +#include <rtems/config.h> +#include <rtems/counter.h> + +#include <libcpu/powerpc-utility.h> +#include <bsp/vectors.h> + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> +#include <bsp/start.h> +#include <bsp/mpc55xx-config.h> + +/* Symbols defined in linker command file */ +LINKER_SYMBOL(mpc55xx_exc_vector_base); + +unsigned int bsp_clock_speed = 0; + +uint32_t bsp_clicks_per_usec = 0; + +static void null_pointer_protection(void) +{ +#ifdef MPC55XX_NULL_POINTER_PROTECTION + struct MMU_tag mmu = { .MAS0 = { .B = { .TLBSEL = 1, .ESEL = 1 } } }; + + PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS0, mmu.MAS0.R); + __asm__ volatile ("tlbre"); + mmu.MAS1.R = PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS1); + mmu.MAS1.B.VALID = 0; + PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS1, mmu.MAS1.R); + __asm__ volatile ("tlbwe"); +#endif +} + +void bsp_start(void) +{ + null_pointer_protection(); + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function store the result in global variables so that it can be used + * latter... + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + /* + * determine clock speed + */ + bsp_clock_speed = mpc55xx_get_system_clock() / MPC55XX_SYSTEM_CLOCK_DIVIDER; + + /* Time reference value */ + bsp_clicks_per_usec = bsp_clock_speed / 1000000; + rtems_counter_initialize_converter(bsp_clock_speed); + + /* Initialize exceptions */ + ppc_exc_initialize_with_vector_base( + (uintptr_t) bsp_section_work_begin, + rtems_configuration_get_interrupt_stack_size(), + mpc55xx_exc_vector_base + ); + + /* Initialize interrupts */ + bsp_interrupt_initialize(); + + #if MPC55XX_CHIP_FAMILY != 566 + mpc55xx_edma_init(); + #endif + + #ifdef MPC55XX_EMIOS_PRESCALER + mpc55xx_emios_initialize(MPC55XX_EMIOS_PRESCALER); + #endif +} diff --git a/bsps/powerpc/mpc55xxevb/start/exc-vector-base.S b/bsps/powerpc/mpc55xxevb/start/exc-vector-base.S new file mode 100644 index 0000000000..9d9e79f351 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/exc-vector-base.S @@ -0,0 +1,124 @@ +/** + * @file + * + * @ingroup mpc55xx_asm + * + * @brief Exception minimum prologues. + */ + +/* + * 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. + */ + +/** + * @defgroup mpc55xx_asm Assembler files + * + * @ingroup mpc55xx + */ + +#include <bspopts.h> + +#include <bsp/vectors.h> + + .globl mpc55xx_exc_vector_base + + .section ".bsp_text", "ax" + +#if 5510 <= MPC55XX_CHIP_TYPE && MPC55XX_CHIP_TYPE <= 5517 + .align 12 +#else + .align 16 +#endif + +mpc55xx_exc_vector_base: + + stw r1, ppc_exc_lock_crit@sdarel(r13) + stw r4, ppc_exc_vector_register_crit@sdarel(r13) + li r4, -32767 + b ppc_exc_wrap_bookE_crit + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 2 + b ppc_exc_wrap_nopush_bookE_crit + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 3 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 4 + b ppc_exc_wrap_nopush_std + stwu r1, -PPC_EXC_INTERRUPT_FRAME_SIZE(r1) + stw r3, GPR3_OFFSET(r1) + li r3, -32763 + b ppc_exc_interrupt + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 6 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 7 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 8 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 12 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 24 + b ppc_exc_wrap_nopush_std + stwu r1, -PPC_EXC_INTERRUPT_FRAME_SIZE(r1) + stw r3, GPR3_OFFSET(r1) + li r3, -32752 + b ppc_exc_interrupt + stwu r1, -PPC_EXC_INTERRUPT_FRAME_SIZE(r1) + stw r3, GPR3_OFFSET(r1) + li r3, -32749 + b ppc_exc_interrupt + stw r1, ppc_exc_lock_crit@sdarel(r13) + stw r4, ppc_exc_vector_register_crit@sdarel(r13) + li r4, -32748 + b ppc_exc_wrap_bookE_crit + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 18 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 17 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 13 + b ppc_exc_wrap_nopush_bookE_crit + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 10 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 25 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 26 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 15 + b ppc_exc_wrap_nopush_std diff --git a/bsps/powerpc/mpc55xxevb/start/get-system-clock.c b/bsps/powerpc/mpc55xxevb/start/get-system-clock.c new file mode 100644 index 0000000000..42e2b38327 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/get-system-clock.c @@ -0,0 +1,85 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief System clock calculation. + */ + +/* + * 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 <bsp.h> +#include <bsp/start.h> +#include <bsp/mpc55xx-config.h> + +uint32_t mpc55xx_get_system_clock(void) +{ + uint32_t system_clock = 0; + + #ifdef MPC55XX_HAS_FMPLL + volatile struct FMPLL_tag *fmpll = &FMPLL; + union FMPLL_SYNSR_tag synsr = { .R = fmpll->SYNSR.R }; + uint32_t reference_clock = MPC55XX_REFERENCE_CLOCK; + bool pll_clock_mode = synsr.B.MODE != 0; + bool crystal_or_external_reference_mode = synsr.B.PLLSEL != 0; + + if (pll_clock_mode) { + if (crystal_or_external_reference_mode) { + union FMPLL_SYNCR_tag syncr = { .R = fmpll->SYNCR.R }; + uint32_t prediv = syncr.B.PREDIV; + uint32_t mfd = syncr.B.MFD; + uint32_t rfd = syncr.B.RFD; + + system_clock = ((reference_clock * (mfd + 4)) >> rfd) / (prediv + 1); + } else { + system_clock = 2 * reference_clock; + } + } else { + system_clock = reference_clock; + } + #endif + + #ifdef MPC55XX_HAS_FMPLL_ENHANCED + volatile struct FMPLL_tag *fmpll = &FMPLL; + union FMPLL_ESYNCR1_tag esyncr1 = { .R = fmpll->ESYNCR1.R }; + uint32_t reference_clock = MPC55XX_REFERENCE_CLOCK; + bool normal_mode = (esyncr1.B.CLKCFG & 0x4U) != 0; + + if (normal_mode) { + union FMPLL_ESYNCR2_tag esyncr2 = { .R = fmpll->ESYNCR2.R }; + uint32_t eprediv = esyncr1.B.EPREDIV; + uint32_t emfd = esyncr1.B.EMFD; + uint32_t erfd = esyncr2.B.ERFD; + + system_clock = ((reference_clock / (eprediv + 1)) * (emfd + 16)) + / (erfd + 1); + } else { + system_clock = reference_clock; + } + #endif + + #ifdef MPC55XX_HAS_MODE_CONTROL + /* FIXME: Assumes normal mode and external oscillator */ + PLLD_CR_32B_tag cr = { . R = CGM.FMPLL [0].CR.R }; + uint32_t xosc = MPC55XX_REFERENCE_CLOCK; + uint32_t ldf = cr.B.NDIV; + uint32_t idf = cr.B.IDF + 1; + uint32_t odf = 2U << cr.B.ODF; + + system_clock = (xosc * ldf) / (idf * odf); + #endif + + return system_clock; +} diff --git a/bsps/powerpc/mpc55xxevb/start/idle-thread.c b/bsps/powerpc/mpc55xxevb/start/idle-thread.c new file mode 100644 index 0000000000..45bea8e418 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/idle-thread.c @@ -0,0 +1,34 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief bsp_idle_thread() implementation. + */ + +/* + * Copyright (c) 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 <mpc55xx/mpc55xx.h> + +void *bsp_idle_thread(uintptr_t arg) +{ + while (true) { + mpc55xx_wait_for_interrupt(); + } + + return NULL; +} diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds b/bsps/powerpc/mpc55xxevb/start/linkcmds new file mode 100644 index 0000000000..5c2161deba --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds @@ -0,0 +1 @@ +include linkcmds.mpc55xxevb diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.gwlcfm b/bsps/powerpc/mpc55xxevb/start/linkcmds.gwlcfm new file mode 100644 index 0000000000..cabaac2201 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.gwlcfm @@ -0,0 +1,27 @@ +MEMORY { + ROM : ORIGIN = 0x0, LENGTH = 1536K + RAM : ORIGIN = 0x40000000, LENGTH = 80K + RAM_EXT : ORIGIN = 0x20000000, LENGTH = 512K + NOCACHE : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", ROM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_RWEXTRA", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", NOCACHE); +REGION_ALIAS ("REGION_NVRAM", NOCACHE); + +INCLUDE linkcmds.mpc55xx diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5566evb b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5566evb new file mode 100644 index 0000000000..4f63fb0e0a --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5566evb @@ -0,0 +1,27 @@ +MEMORY { + ROM : ORIGIN = 0x0, LENGTH = 3M + RAM : ORIGIN = 0x40000000, LENGTH = 128K + RAM_EXT : ORIGIN = 0x20000000, LENGTH = 512K + NOCACHE : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", ROM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_RWEXTRA", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", NOCACHE); +REGION_ALIAS ("REGION_NVRAM", NOCACHE); + +INCLUDE linkcmds.mpc55xx diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5566evb_spe b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5566evb_spe new file mode 100644 index 0000000000..9255b15076 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5566evb_spe @@ -0,0 +1 @@ +INCLUDE linkcmds.mpc5566evb diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc55xx b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc55xx new file mode 100644 index 0000000000..2c4e1e3f7b --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc55xx @@ -0,0 +1,22 @@ +bsp_ram_start = ORIGIN (RAM); +bsp_ram_size = LENGTH (RAM) + LENGTH (NOCACHE); +bsp_ram_end = bsp_ram_start + bsp_ram_size; + +bsp_rom_start = ORIGIN (ROM); +bsp_rom_size = LENGTH (ROM); +bsp_rom_end = bsp_rom_start + bsp_rom_size; + +INCLUDE linkcmds.base + +SECTIONS { + .work_bonus : { + /* + * This section will occupy the remaining RAM_EXT region and may + * contain parts of the RTEMS work space and heap. + */ + bsp_section_work_bonus_begin = .; + . += ORIGIN (RAM_EXT) + LENGTH (RAM_EXT) - ABSOLUTE (.); + bsp_section_work_bonus_end = .; + } > RAM_EXT AT > RAM_EXT + bsp_section_work_bonus_size = bsp_section_work_bonus_end - bsp_section_work_bonus_begin; +} diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5643l_dpu b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5643l_dpu new file mode 100644 index 0000000000..2f7d80716d --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5643l_dpu @@ -0,0 +1 @@ +INCLUDE linkcmds.mpc5643l_evb diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5643l_evb b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5643l_evb new file mode 100644 index 0000000000..1977c92d59 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5643l_evb @@ -0,0 +1,33 @@ +MEMORY { + ROM : ORIGIN = 0x0, LENGTH = 1M + RAM : ORIGIN = 0x40000000, LENGTH = 64K + RAM_1 : ORIGIN = 0x50000000, LENGTH = 64K + NOCACHE : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("RAM_EXT", RAM); + +bsp_ram_1_start = ORIGIN (RAM_1); +bsp_ram_1_size = LENGTH (RAM_1); +bsp_ram_1_end = bsp_ram_1_start + bsp_ram_1_size; + +REGION_ALIAS ("REGION_START", ROM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM_1); +REGION_ALIAS ("REGION_STACK", RAM_1); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", NOCACHE); +REGION_ALIAS ("REGION_NVRAM", NOCACHE); + +INCLUDE linkcmds.mpc55xx diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5668g b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5668g new file mode 100644 index 0000000000..6c8e5a64f1 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5668g @@ -0,0 +1,29 @@ +MEMORY { + ROM : ORIGIN = 0x0, LENGTH = 2M + RAM : ORIGIN = 0x40000000, LENGTH = 256K - 16k + NOCACHE : ORIGIN = 0x4003c000, LENGTH = 16k + EMPTY : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("RAM_EXT", RAM); + +REGION_ALIAS ("REGION_START", ROM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", ROM); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +INCLUDE linkcmds.mpc55xx diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508 b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508 new file mode 100644 index 0000000000..1e52a3c6c3 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508 @@ -0,0 +1,51 @@ +MEMORY { + DSROM : ORIGIN = 0x00020000, LENGTH = 64k + SYSROM : ORIGIN = 0x00100000, LENGTH = 4k + RAM : ORIGIN = 0x40000000, LENGTH = 240k + NOCACHE : ORIGIN = 0x4003c000, LENGTH = 16k + DSRAM : ORIGIN = 0x20000000, LENGTH = 64k + RAM_EXT : ORIGIN = 0x20010000, LENGTH = 444k + SYSRAM : ORIGIN = 0x2007f000, LENGTH = 4k + NVRAM : ORIGIN = 0x3ffa0000, LENGTH = 128k +} + +REGION_ALIAS ("REGION_START", STARTROM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", ROM); +REGION_ALIAS ("REGION_NVRAM", NVRAM); + +SECTIONS { + .dsram (NOLOAD) : { + bsp_section_dsram_begin = .; + *(SORT(.bsp_dsram*)) + bsp_section_dsram_end = .; + } > DSRAM AT > DSROM + bsp_section_dsram_size = bsp_section_dsram_end - bsp_section_dsram_begin; + bsp_section_dsram_load_begin = LOADADDR (.dsram); + bsp_section_dsram_load_end = bsp_section_dsram_load_begin + bsp_section_dsram_size; + + .sysram : { + bsp_section_sysram_begin = .; + *(SORT(.bsp_sysram*)) + bsp_section_sysram_end = .; + } > SYSRAM AT > SYSROM + bsp_section_sysram_size = bsp_section_sysram_end - bsp_section_sysram_begin; + bsp_section_sysram_load_begin = LOADADDR (.sysram); + bsp_section_sysram_load_end = bsp_section_sysram_load_begin + bsp_section_sysram_size; +} + +INCLUDE linkcmds.mpc55xx diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508_app b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508_app new file mode 100644 index 0000000000..4b94ac50c4 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508_app @@ -0,0 +1,8 @@ +MEMORY { + /* Let space for the binary image library header */ + ROM : ORIGIN = 0x00101000, LENGTH = 3064k +} + +REGION_ALIAS ("STARTROM", ROM); + +INCLUDE linkcmds.mpc5674f_ecu508 diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508_boot b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508_boot new file mode 100644 index 0000000000..6dc5a7fcb0 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508_boot @@ -0,0 +1,6 @@ +MEMORY { + STARTROM : ORIGIN = 0x0, LENGTH = 32k + ROM : ORIGIN = 0x40000, LENGTH = 768k +} + +INCLUDE linkcmds.mpc5674f_ecu508 diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_rsm6 b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_rsm6 new file mode 100644 index 0000000000..c96f8b9078 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_rsm6 @@ -0,0 +1,6 @@ +MEMORY { + STARTROM : ORIGIN = 0x0, LENGTH = 32k + ROM : ORIGIN = 0x40000, LENGTH = 768k +} + +INCLUDE linkcmds.mpc5674f_rsm6_base diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_rsm6_base b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_rsm6_base new file mode 100644 index 0000000000..8f6a403ca8 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_rsm6_base @@ -0,0 +1,28 @@ +MEMORY { + RAM : ORIGIN = 0x40000000, LENGTH = 240k + NOCACHE : ORIGIN = 0x4003c000, LENGTH = 16k + MRAM : ORIGIN = 0x20000000, LENGTH = 4M +} + +REGION_ALIAS ("RAM_EXT", RAM); + +REGION_ALIAS ("REGION_START", STARTROM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", ROM); +REGION_ALIAS ("REGION_NVRAM", MRAM); + +INCLUDE linkcmds.mpc55xx diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674fevb b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674fevb new file mode 100644 index 0000000000..3113fb20b7 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674fevb @@ -0,0 +1,28 @@ +MEMORY { + ROM : ORIGIN = 0x0, LENGTH = 4M + RAM : ORIGIN = 0x40000000, LENGTH = 256K - 16k + RAM_EXT : ORIGIN = 0x20000000, LENGTH = 512K + NOCACHE : ORIGIN = 0x4003c000, LENGTH = 16k + EMPTY : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", ROM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", ROM); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +INCLUDE linkcmds.mpc55xx diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674fevb_spe b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674fevb_spe new file mode 100644 index 0000000000..eab0907009 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674fevb_spe @@ -0,0 +1 @@ +INCLUDE linkcmds.mpc5674fevb diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.phycore_mpc5554 b/bsps/powerpc/mpc55xxevb/start/linkcmds.phycore_mpc5554 new file mode 100644 index 0000000000..77b8abc5e0 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.phycore_mpc5554 @@ -0,0 +1,36 @@ +/* + * Debug RAM is the top 4MB of external RAM and is swapped with the + * FLASH for development. + */ +MEMORY { + ROM : ORIGIN = 0x00000000, LENGTH = 2M + RAM : ORIGIN = 0x40000000, LENGTH = 64K + RAM_EXT : ORIGIN = 0x21000000, LENGTH = 4M + DEBUG_RAM : ORIGIN = 0x21400000, LENGTH = 4M + NOCACHE : ORIGIN = 0x0, LENGTH = 0 +} + +bsp_debug_ram_start = ORIGIN (DEBUG_RAM); +bsp_debug_ram_end = ORIGIN (DEBUG_RAM) + LENGTH (DEBUG_RAM); +bsp_debug_ram_size = LENGTH (DEBUG_RAM); + +REGION_ALIAS ("REGION_START", ROM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_RWEXTRA", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", NOCACHE); +REGION_ALIAS ("REGION_NVRAM", NOCACHE); + +INCLUDE linkcmds.mpc55xx diff --git a/bsps/powerpc/mpc55xxevb/start/restart.c b/bsps/powerpc/mpc55xxevb/start/restart.c new file mode 100644 index 0000000000..495aa39a95 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/restart.c @@ -0,0 +1,25 @@ +/* + * 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> + +void bsp_restart(void *addr) +{ + rtems_interrupt_level level; + void (*start)(void) = addr; + + (void) level; + rtems_interrupt_disable(level); + (*start)(); +} diff --git a/bsps/powerpc/mpc55xxevb/start/sd-card-init.c b/bsps/powerpc/mpc55xxevb/start/sd-card-init.c new file mode 100644 index 0000000000..f6e0484122 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/sd-card-init.c @@ -0,0 +1,163 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief SD Card initialization code. + */ + +/* + * Copyright (c) 2008 + * 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 <stdio.h> + +#include <mpc55xx/mpc55xx.h> +#include <mpc55xx/regs.h> +#include <mpc55xx/dspi.h> + +#include <bsp.h> + +#include <rtems/status-checks.h> + +#ifdef MPC55XX_BOARD_MPC5566EVB + +static rtems_status_code mpc55xx_dspi_init(void) +{ + int rv = 0; + int i = 0; + char device_name [] = "/dev/spi0"; + union SIU_PCR_tag pcr = MPC55XX_ZERO_FLAGS; + + rv = rtems_libi2c_initialize(); + RTEMS_CHECK_RV_SC( rv, "rtems_libi2c_initialize"); + + /* DSPI D inputs are taken from DSPI C */ + SIU.DISR.R = 0x000000FC; + + /* DSPI A signals */ + pcr.B.PA = 1; + pcr.B.ODE = 0; + pcr.B.HYS = 0; + pcr.B.SRC = 3; + pcr.B.WPE = 1; + pcr.B.WPS = 1; + + /* SCK */ + pcr.B.OBE = 1; + pcr.B.IBE = 0; + SIU.PCR [93].R = pcr.R; + + /* SIN */ + pcr.B.OBE = 0; + pcr.B.IBE = 1; + SIU.PCR [94].R = pcr.R; + + /* SOUT */ + pcr.B.OBE = 1; + pcr.B.IBE = 0; + SIU.PCR [95].R = pcr.R; + + /* PCSx */ + pcr.B.OBE = 1; + pcr.B.IBE = 0; + SIU.PCR [96].R = pcr.R; + SIU.PCR [97].R = pcr.R; + SIU.PCR [98].R = pcr.R; + SIU.PCR [99].R = pcr.R; + SIU.PCR [100].R = pcr.R; + SIU.PCR [101].R = pcr.R; + + mpc55xx_dspi_bus_table [3].master = 0; + for (i = 0; i < MPC55XX_DSPI_NUMBER; ++i) { + device_name [8] = (char) ('0' + i); + rv = rtems_libi2c_register_bus( device_name, (rtems_libi2c_bus_t *) &mpc55xx_dspi_bus_table [i]); + RTEMS_CHECK_RV_SC( rv, device_name); + } + + return RTEMS_SUCCESSFUL; +} + +#include <stdio.h> +#include <rtems/fsmount.h> +#include <rtems/dosfs.h> +#include <rtems/bdpart.h> +#include <rtems/console.h> + +#include <libchip/spi-sd-card.h> + +#define MPC55XX_DEVICE "sd-card-a" +#define MPC55XX_DEVICE_FILE "/dev/" MPC55XX_DEVICE +#define MPC55XX_PARTITION "/dev/sd-card-a1" +#define MPC55XX_MOUNT_POINT "/mnt" + +static fstab_t mpc55xx_fs_table [] = { { + MPC55XX_PARTITION, MPC55XX_MOUNT_POINT, + "dosfs", RTEMS_FILESYSTEM_READ_WRITE, + FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED, + FSMOUNT_MNT_OK + }, { + MPC55XX_DEVICE_FILE, MPC55XX_MOUNT_POINT, + "dosfs", RTEMS_FILESYSTEM_READ_WRITE, + FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED, + 0 + } +}; + +sd_card_driver_entry sd_card_driver_table [] = { + { + .device_name = "/dev/sd-card-a", + .bus = 0, + .transfer_mode = SD_CARD_TRANSFER_MODE_DEFAULT, + .command = SD_CARD_COMMAND_DEFAULT, + /* response : whatever, */ + .response_index = SD_CARD_COMMAND_SIZE, + .n_ac_max = SD_CARD_N_AC_MAX_DEFAULT, + .block_number = 0, + .block_size = 0, + .block_size_shift = 0, + .busy = true, + .verbose = true, + .schedule_if_busy = false + } +}; + +size_t sd_card_driver_table_size = sizeof( sd_card_driver_table) / sizeof( sd_card_driver_table [0]); + +rtems_status_code mpc55xx_sd_card_init( bool mount) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + int rv = 0; + sd_card_driver_entry *e = &sd_card_driver_table [0]; + + RTEMS_DEBUG_PRINT( "Task started\n"); + + sc = mpc55xx_dspi_init(); + RTEMS_CHECK_SC( rv, "Intitalize DSPI bus"); + + e->bus = mpc55xx_dspi_bus_table [0].bus_number; + + sc = sd_card_register(); + RTEMS_CHECK_SC( sc, "Register SD Card"); + + if (mount) { + sc = rtems_bdpart_register_from_disk( MPC55XX_DEVICE_FILE); + RTEMS_CHECK_SC( sc, "Initialize IDE partition table"); + + rv = rtems_fsmount( mpc55xx_fs_table, sizeof( mpc55xx_fs_table) / sizeof( mpc55xx_fs_table [0]), NULL); + RTEMS_CHECK_RV_SC( rv, "Mount file systems"); + } + + return RTEMS_SUCCESSFUL; +} + +#endif /* MPC55XX_BOARD_MPC5566EVB */ diff --git a/bsps/powerpc/mpc55xxevb/start/start-cache.S b/bsps/powerpc/mpc55xxevb/start/start-cache.S new file mode 100644 index 0000000000..c30de57fc6 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-cache.S @@ -0,0 +1,114 @@ +/** + * @file + * + * @ingroup mpc55xx_asm + * + * @brief Cache initialization. + */ + +/* + * 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 <libcpu/powerpc-utility.h> + +#include <mpc55xx/regs.h> + + .globl mpc55xx_start_cache + + .section ".bsp_start_text", "ax" + +mpc55xx_start_cache: + +#ifdef MPC55XX_NEEDS_LOW_LEVEL_INIT + + /* Load zero, CINV, and CABT) */ + li r0, 0 + li r3, 0x2 + li r4, 0x4 + +#if defined(BSP_INSTRUCTION_CACHE_ENABLED) \ + && defined(MPC55XX_HAS_INSTRUCTION_CACHE) + +start_instruction_cache_invalidation: + + /* Clear instruction cache invalidation abort */ + mtspr FSL_EIS_L1CSR1, r0 + + /* Start instruction cache invalidation */ + mtspr FSL_EIS_L1CSR1, r3 + +get_instruction_cache_invalidation_status: + + /* Get instruction cache invalidation status */ + mfspr r5, FSL_EIS_L1CSR1 + + /* Check CABT */ + and. r6, r5, r4 + bne start_instruction_cache_invalidation + + /* Check CINV */ + and. r6, r5, r3 + bne get_instruction_cache_invalidation_status + + /* Save instruction cache settings */ + LWI r6, 0x00010001 + isync + msync + mtspr FSL_EIS_L1CSR1, r6 + +#endif + +#if (defined(BSP_DATA_CACHE_ENABLED) && defined(MPC55XX_HAS_DATA_CACHE)) \ + || ((defined(BSP_DATA_CACHE_ENABLED) \ + || defined(BSP_INSTRUCTION_CACHE_ENABLED)) \ + && defined(MPC55XX_HAS_UNIFIED_CACHE)) + +start_data_cache_invalidation: + + /* Clear data cache invalidation abort */ + mtspr FSL_EIS_L1CSR0, r0 + + /* Start data cache invalidation */ + mtspr FSL_EIS_L1CSR0, r3 + +get_data_cache_invalidation_status: + + /* Get data cache invalidation status */ + mfspr r5, FSL_EIS_L1CSR0 + + /* Check CABT */ + and. r6, r5, r4 + bne start_data_cache_invalidation + + /* Check CINV */ + and. r6, r5, r3 + bne get_data_cache_invalidation_status + + /* Save data cache settings */ +#if MPC55XX_CHIP_FAMILY != 567 + /* FIXME: CORG??? 0x00180011 */ + LWI r6, 0x00100001 +#else + LWI r6, 0x00190001 +#endif + isync + msync + mtspr FSL_EIS_L1CSR0, r6 + +#endif + +#endif /* MPC55XX_NEEDS_LOW_LEVEL_INIT */ + + /* Return */ + blr diff --git a/bsps/powerpc/mpc55xxevb/start/start-clock.c b/bsps/powerpc/mpc55xxevb/start/start-clock.c new file mode 100644 index 0000000000..85468d5cb0 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-clock.c @@ -0,0 +1,104 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief Clock and FMPLL initialization code. + */ + +/* + * 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 <bsp.h> +#include <bsp/fatal.h> +#include <bsp/start.h> +#include <bsp/bootcard.h> +#include <bsp/mpc55xx-config.h> + +#ifdef MPC55XX_NEEDS_LOW_LEVEL_INIT + #if defined(MPC55XX_HAS_FMPLL) || defined(MPC55XX_HAS_FMPLL_ENHANCED) + static BSP_START_TEXT_SECTION void fmpll_wait_for_lock(void) + { + int i = 0; + bool lock = false; + + while (!lock && i < 6000) { + lock = FMPLL.SYNSR.B.LOCK != 0; + ++i; + } + + if (!lock) { + bsp_fatal(MPC55XX_FATAL_FMPLL_LOCK); + } + } + #endif +#endif + +BSP_START_TEXT_SECTION void mpc55xx_start_clock(void) +{ + #ifdef MPC55XX_NEEDS_LOW_LEVEL_INIT + const mpc55xx_clock_config *cfg = mpc55xx_start_config_clock; + + #ifdef MPC55XX_HAS_FMPLL + volatile struct FMPLL_tag *fmpll = &FMPLL; + + fmpll->SYNCR.R = cfg->syncr_tmp.R; + fmpll->SYNCR.R; + fmpll_wait_for_lock(); + + fmpll->SYNCR.R = cfg->syncr_final.R; + fmpll->SYNCR.R; + fmpll_wait_for_lock(); + #endif + + #ifdef MPC55XX_HAS_FMPLL_ENHANCED + volatile struct FMPLL_tag *fmpll = &FMPLL; + + fmpll->ESYNCR2.R = cfg->esyncr2_tmp.R; + fmpll->ESYNCR2.R; + fmpll->ESYNCR1.R = cfg->esyncr1_final.R; + fmpll->ESYNCR1.R; + fmpll_wait_for_lock(); + + fmpll->ESYNCR2.R = cfg->esyncr2_final.R; + fmpll->ESYNCR2.R; + fmpll_wait_for_lock(); + + #if MPC55XX_CHIP_FAMILY == 551 || MPC55XX_CHIP_FAMILY == 566 + /* System clock supplied by PLL */ + SIU.SYSCLK.B.SYSCLKSEL = 2; + #endif + #endif + + #ifdef MPC55XX_HAS_MODE_CONTROL + volatile CGM_tag *cgm = &CGM; + size_t fmpll_count = sizeof(cfg->fmpll) / sizeof(cfg->fmpll [0]); + size_t auxclk_count = sizeof(cfg->auxclk) / sizeof(cfg->auxclk [0]); + size_t i = 0; + + for (i = 0; i < auxclk_count; ++i) { + cgm->AUXCLK [i].AC_SC.R = cfg->auxclk [i].AC_SC.R; + cgm->AUXCLK [i].AC_DC0_3.R = cfg->auxclk [i].AC_DC0_3.R; + } + + for (i = 0; i < fmpll_count; ++i) { + cgm->FMPLL [i].CR.R = cfg->fmpll [i].cr.R; + cgm->FMPLL [i].MR.R = cfg->fmpll [i].mr.R; + } + + cgm->OC_EN.R = cfg->oc_en.R; + cgm->OCDS_SC.R = cfg->ocds_sc.R; + #endif + #endif +} diff --git a/bsps/powerpc/mpc55xxevb/start/start-config-clock.c b/bsps/powerpc/mpc55xxevb/start/start-config-clock.c new file mode 100644 index 0000000000..d820af3755 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-config-clock.c @@ -0,0 +1,132 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief Clock and FMPLL configuration. + */ + +/* + * 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/mpc55xx-config.h> + +const mpc55xx_clock_config mpc55xx_start_config_clock [1] = { { + #ifdef MPC55XX_HAS_FMPLL + .syncr_tmp = { + .B = { + .PREDIV = MPC55XX_FMPLL_PREDIV - 1, + .MFD = MPC55XX_FMPLL_MFD, + .RFD = 2, + .LOCEN = 1 + } + }, + .syncr_final = { + .B = { + .PREDIV = MPC55XX_FMPLL_PREDIV - 1, + .MFD = MPC55XX_FMPLL_MFD, + .RFD = 0, + .LOCEN = 1, + .LOLIRQ = 1, + .LOCIRQ = 1 + } + } + #endif + #ifdef MPC55XX_HAS_FMPLL_ENHANCED + #define EPREDIV_VAL (MPC55XX_FMPLL_PREDIV-1) + #define EMFD_VAL (MPC55XX_FMPLL_MFD-16) + #define VCO_CLK_REF (MPC55XX_REFERENCE_CLOCK/(EPREDIV_VAL+1)) + #define VCO_CLK_OUT (VCO_CLK_REF*(EMFD_VAL+16)) + #define ERFD_VAL \ + (((VCO_CLK_OUT + MPC55XX_SYSTEM_CLOCK - 1) / MPC55XX_SYSTEM_CLOCK)-1) + + .esyncr2_tmp = { + .B = { + .LOCEN = 0, + .LOLRE = 0, + .LOCRE = 0, + .LOLIRQ = 0, + .LOCIRQ = 0, + .ERATE = 0, + .EDEPTH = 0, + .ERFD = ERFD_VAL + 2 /* reduce output clock during init */ + } + }, + .esyncr2_final = { + .B = { + .LOCEN = 0, + .LOLRE = 0, + .LOCRE = 0, + .LOLIRQ = 0, + .LOCIRQ = 0, + .ERATE = 0, + #if MPC55XX_CHIP_FAMILY == 567 + .CLKCFG_DIS = 1, + #endif + .EDEPTH = 0, + .ERFD = ERFD_VAL /* nominal output clock after init */ + } + }, + .esyncr1_final = { + .B = { + .CLKCFG = MPC55XX_FMPLL_ESYNCR1_CLKCFG, + .EPREDIV = EPREDIV_VAL, + .EMFD = EMFD_VAL + } + } + #endif + #ifdef MPC55XX_HAS_MODE_CONTROL + .fmpll = { + { + .cr = { + #if MPC55XX_REFERENCE_CLOCK == 8000000 + .B = { .IDF = 0, .ODF = 1, .NDIV = 60, .I_LOCK = 1, .PLL_ON = 1 } + #elif MPC55XX_REFERENCE_CLOCK == 40000000 + .B = { .IDF = 3, .ODF = 1, .NDIV = 48, .I_LOCK = 1, .PLL_ON = 1 } + #else + #error "unexpected reference clock" + #endif + } + }, + { + .cr = { + .B = { .IDF = 3, .ODF = 2, .NDIV = 32, .I_LOCK = 1, .PLL_ON = 1 } + } + } + }, + .ocds_sc = { + .B = { .SELDIV = 2, .SELCTL = 2 } + }, + .auxclk = { + [0] = { + .AC_SC = { .B = { .SELCTL = 4 } }, + .AC_DC0_3 = { .B = { .DE0 = 1, .DIV0 = 0 } } + }, + [1] = { + .AC_SC = { .B = { .SELCTL = 4 } }, + .AC_DC0_3 = { .B = { .DE0 = 1, .DIV0 = 11 } } + }, + [2] = { + .AC_SC = { .B = { .SELCTL = 4 } }, + .AC_DC0_3 = { .B = { .DE0 = 1, .DIV0 = 11 } } + }, + [3] = { + .AC_SC = { .B = { .SELCTL = 1 } } + }, + [4] = { + .AC_SC = { .B = { .SELCTL = 1 } } + } + } + #endif +} }; diff --git a/bsps/powerpc/mpc55xxevb/start/start-config-ebi-cs-cal.c b/bsps/powerpc/mpc55xxevb/start/start-config-ebi-cs-cal.c new file mode 100644 index 0000000000..69f9b61a7d --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-config-ebi-cs-cal.c @@ -0,0 +1,257 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief EBI calibration chip-select configuration. + */ + +/* + * 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/mpc55xx-config.h> + +#ifdef MPC55XX_HAS_EBI + +const struct EBI_CAL_CS_tag mpc55xx_start_config_ebi_cal_cs [] = { +#if defined(MPC55XX_BOARD_MPC5674FEVB) + /* External SRAM */ + { + .BR = { + .B = { + .BA = 0x20000000 >> 15, + .PS = 0, + .AD_MUX = 1, + .BL = 1, + .WEBS = 0, + .TBDIP = 1, + .SETA = 0, + .BI = 0, + .V = 1 + } + }, + .OR = { + .B = { + .AM = 0xfff80000 >> 15, + .SCY = 0, + .BSCY = 0 + } + } + }, + /* External Ethernet controller */ + { + .BR = { + .B = { + .BA = 0x3fff8000 >> 15, + .PS = 0, + .AD_MUX = 1, + .BL = 0, + .WEBS = 0, + .TBDIP = 0, + .SETA = 0, + .BI = 1, + .V = 1 + } + }, + .OR = { + .B = { + .AM = 0xfff80000 >> 15, + .SCY = 1, + .BSCY = 0 + } + } + } +#elif defined(MPC55XX_BOARD_MPC5674F_ECU508) \ + && defined(MPC55XX_NEEDS_LOW_LEVEL_INIT) + /* D_CS0 for external SRAM */ + { + .BR = { + .B = { + .BA = 0x20000000 >> 15, + .PS = 0, + .AD_MUX = 1, + .BL = 1, + .WEBS = 0, + .TBDIP = 1, + .SETA = 0, + .BI = 0, + .V = 1 + } + }, + .OR = { + .B = { + .AM = 0xffe00000 >> 15, + .SCY = 0, + .BSCY = 0 + } + } + }, + + /* D_CS1 for Ethernet Controller */ + { + .BR = { + .B = { + .BA = 0x3fff8000 >> 15, + .PS = 0, + .AD_MUX = 1, + .BL = 0, + .WEBS = 0, + .TBDIP = 0, + .SETA = 0, + .BI = 1, + .V = 1 + } + }, + .OR = { + .B = { + .AM = 0xffff8000 >> 15, + .SCY = 1, + .BSCY = 0 + } + } + }, + + /* D_CS2 unused */ + { + .BR = { + .B = { + .BA = 0x20000000 >> 15, + .PS = 0, + .AD_MUX = 1, + .BL = 0, + .WEBS = 0, + .TBDIP = 0, + .SETA = 0, + .BI = 1, + .V = 0 + } + }, + .OR = { + .B = { + .AM = 0xfff80000 >> 15, + .SCY = 0, + .BSCY = 0 + } + } + }, + + /* D_CS3 for MRAM, ARCNET */ + { + .BR = { + .B = { + .BA = 0x3ff80000 >> 15, + .PS = 1, + .AD_MUX = 1, + .BL = 0, + .WEBS = 1, + .TBDIP = 0, + .SETA = 0, + .BI = 1, + .V = 1 + } + }, + .OR = { + .B = { + .AM = 0xfff80000 >> 15, + .SCY = 1, + .BSCY = 0 + } + } + } +#elif defined(MPC55XX_BOARD_MPC5674F_RSM6) + /* D_CS0 for MRAM */ + { + .BR = { + .B = { + .BA = 0x20000000 >> 15, + .PS = 0, + .AD_MUX = 1, + .BL = 0, + .WEBS = 1, + .TBDIP = 0, + .SETA = 0, + .BI = 1, + .V = 1 + } + }, + .OR = { + .B = { + .AM = 0xffc00000 >> 15, + .SCY = 4, + .BSCY = 0 + } + } + }, + + /* D_CS1 for FPGA */ + { + .BR = { + .B = { + .BA = 0x21000000 >> 15, + .PS = 0, + .AD_MUX = 1, + .BL = 0, + .WEBS = 0, + .TBDIP = 0, + .SETA = 0, + .BI = 1, + .V = 1 + } + }, + .OR = { + .B = { + .AM = 0xff800000 >> 15, + .SCY = 0, + .BSCY = 0 + } + } + }, + + /* D_CS2 unused */ + { + .BR = { .R = 0x20000002 }, + .OR = { .R = 0xe0000000 } + }, + + /* D_CS3 for Ethernet Controller */ + { + .BR = { + .B = { + .BA = 0x23000000 >> 15, + .PS = 1, + .AD_MUX = 1, + .BL = 0, + .WEBS = 1, + .TBDIP = 0, + .SETA = 0, + .BI = 1, + .V = 1 + } + }, + .OR = { + .B = { + .AM = 0xfff80000 >> 15, + .SCY = 8, + .BSCY = 0 + } + } + } +#endif +}; + +const size_t mpc55xx_start_config_ebi_cal_cs_count [] = { + RTEMS_ARRAY_SIZE(mpc55xx_start_config_ebi_cal_cs) +}; + +#endif /* MPC55XX_HAS_EBI */ diff --git a/bsps/powerpc/mpc55xxevb/start/start-config-ebi-cs.c b/bsps/powerpc/mpc55xxevb/start/start-config-ebi-cs.c new file mode 100644 index 0000000000..d12d0fa059 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-config-ebi-cs.c @@ -0,0 +1,164 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief EBI chip-select configuration. + */ + +/* + * 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/mpc55xx-config.h> + +#ifdef MPC55XX_HAS_EBI + +const struct EBI_CS_tag mpc55xx_start_config_ebi_cs [] = { +#if defined(MPC55XX_BOARD_GWLCFM) + /* CS0: External SRAM (16 bit, 1 wait states, 512kB, no burst) */ + { + { + .B.BA = 0x20000000>>15, + .B.PS = 1, + .B.AD_MUX = 1, + .B.WEBS = 1, + .B.TBDIP = 0, + .B.BI = 1, + .B.V = 1 + }, + { + .B.AM = 0x1fff0, + .B.SCY = 1, + .B.BSCY = 0 + } + }, + /* CS1: External USB controller (16 bit, 3 wait states, 32kB, no burst) */ + { + { + .B.BA = 0x22000000>>15, + .B.PS = 1, + .B.AD_MUX = 1, + .B.WEBS = 0, + .B.TBDIP = 0, + .B.BI = 1, + .B.V = 1 + }, + { + .B.AM = 0x1ffff, + .B.SCY = 3, + .B.BSCY = 0 + } + }, + /* CS2: Ethernet (16 bit, 2 wait states, 32kB, no burst) */ + { + { + .B.BA = 0x22800000>>15, + .B.PS = 1, + .B.AD_MUX = 1, + .B.WEBS = 1, + .B.TBDIP = 0, + .B.BI = 1, + .B.V = 1 + }, + { + .B.AM = 0x1ffff, + .B.SCY = 1, + .B.BSCY = 0 + } + }, + { /* CS3: MOST Companion. */ + { + .B.BA = 0x23000000>>15, + .B.PS = 1, + .B.AD_MUX = 1, + .B.WEBS = 0, + .B.TBDIP = 0, + .B.BI = 1, + .B.V = 1 + }, + + { + .B.AM = 0x1fff0, + .B.SCY = 1, + .B.BSCY = 0 + } + } +#elif defined(MPC55XX_BOARD_PHYCORE_MPC5554) + /* CS0: External flash. */ + { + { .R = 0x20000003 }, /* Base 0x2000000, Burst Inhibit, Valid */ + { .R = 0xff000050 } + }, + /* CS1: External synchronous burst mode SRAM. */ + { + { .R = 0x21000051 }, /* Base 0x2100000, 4-word Burst Enabled, Valid */ + { .R = 0xff000000 } /* No wait states. */ + }, + /* CS2: External LAN91C111 */ + { + { .R = 0x22000003 }, /* Base 0x22000000, Burst inhibit, valid */ + { .R = 0xff000010 } + }, + + /* CS3: External FPGA */ + { + { .R = 0x23000003 }, /* Base 0x23000000, Burst inhibit, valid. */ + { .R = 0xff000020 } + } +#elif defined(MPC55XX_BOARD_MPC5566EVB) + /* CS0: External SRAM (2 wait states, 512kB, 4 word burst) */ + { + { + .B.BA = 0, + .B.PS = 1, + .B.BL = 1, + .B.WEBS = 0, + .B.TBDIP = 0, + .B.BI = 1, /* TODO: Enable burst */ + .B.V = 1 + }, + + { + .B.AM = 0x1fff0, + .B.SCY = 0, + .B.BSCY = 0 + } + }, + { { .R = 0 }, { .R = 0 } }, /* CS1: Unused. */ + { { .R = 0 }, { .R = 0 } }, /* CS2: Unused. */ + { /* CS3: ethernet? */ + { + .B.BA = 0x7fff, + .B.PS = 1, + .B.BL = 0, + .B.WEBS = 0, + .B.TBDIP = 0, + .B.BI = 1, + .B.V = 1 + }, + + { + .B.AM = 0x1ffff, + .B.SCY = 1, + .B.BSCY = 0 + } + } +#endif +}; + +const size_t mpc55xx_start_config_ebi_cs_count [] = { + RTEMS_ARRAY_SIZE(mpc55xx_start_config_ebi_cs) +}; + +#endif /* MPC55XX_HAS_EBI */ diff --git a/bsps/powerpc/mpc55xxevb/start/start-config-ebi.c b/bsps/powerpc/mpc55xxevb/start/start-config-ebi.c new file mode 100644 index 0000000000..1ce2b297d8 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-config-ebi.c @@ -0,0 +1,62 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief EBI configuration. + */ + +/* + * Copyright (c) 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/mpc55xx-config.h> + +#ifdef MPC55XX_HAS_EBI + +const mpc55xx_ebi_config mpc55xx_start_config_ebi [] = { + #if defined(MPC55XX_BOARD_GWLCFM) + { + .ebi_mcr = { + .B = { + .DBM = 1, + .AD_MUX = 1, /* use multiplexed bus */ + .D16_31 = 1 /* use lower AD bus */ + } + }, + .siu_eccr_ebdf = 4 - 1 /* use CLK/4 as bus clock */ + } + #elif (defined(MPC55XX_BOARD_MPC5674FEVB) \ + || defined(MPC55XX_BOARD_MPC5674F_ECU508) \ + || defined(MPC55XX_BOARD_MPC5674F_RSM6)) \ + && defined(MPC55XX_NEEDS_LOW_LEVEL_INIT) + { + .ebi_mcr = { + .B = { + .ACGE = 0, + .MDIS = 0, + .D16_31 = 1, + .AD_MUX = 0, + .DBM = 0 + } + }, + .siu_eccr_ebdf = 2 - 1 + } + #endif +}; + +const size_t mpc55xx_start_config_ebi_count [] = { + RTEMS_ARRAY_SIZE(mpc55xx_start_config_ebi) +}; + +#endif /* MPC55XX_HAS_EBI */ diff --git a/bsps/powerpc/mpc55xxevb/start/start-config-mmu-early.c b/bsps/powerpc/mpc55xxevb/start/start-config-mmu-early.c new file mode 100644 index 0000000000..84e638d55c --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-config-mmu-early.c @@ -0,0 +1,64 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief MMU early configuration. + */ + +/* + * Copyright (c) 2011-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. + */ + +#include <bsp/mpc55xx-config.h> + +const struct MMU_tag mpc55xx_start_config_mmu_early [] = { +#if (defined(MPC55XX_BOARD_MPC5674F_ECU508) \ + || defined(MPC55XX_BOARD_MPC5674F_RSM6)) \ + && !defined(MPC55XX_NEEDS_LOW_LEVEL_INIT) + /* Used as cache-inhibited area later (ADC, DSPI queues) */ + MPC55XX_MMU_TAG_INITIALIZER(14, 0x4003c000, MPC55XX_MMU_16K, 0, 1, 1, 0) +#elif MPC55XX_CHIP_FAMILY == 555 + /* Internal SRAM 96k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_256K, 1, 1, 1, 0), +#elif MPC55XX_CHIP_FAMILY == 556 + /* Internal SRAM 128k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_64K, 1, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(5, 0x40010000, MPC55XX_MMU_64K, 0, 1, 1, 0), +#elif MPC55XX_CHIP_FAMILY == 564 + /* Internal flash 1M */ + MPC55XX_MMU_TAG_INITIALIZER(0, 0x00000000, MPC55XX_MMU_1M, 1, 0, 1, 1), + /* IO */ + MPC55XX_MMU_TAG_INITIALIZER(1, 0xffe00000, MPC55XX_MMU_2M, 0, 1, 1, 1), + MPC55XX_MMU_TAG_INITIALIZER(2, 0xc3f00000, MPC55XX_MMU_1M, 0, 1, 1, 1), + /* Internal SRAM 64k + 64k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_64K, 1, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(4, 0x50000000, MPC55XX_MMU_64K, 0, 1, 1, 0) +#elif MPC55XX_CHIP_FAMILY == 566 + /* Internal flash 2M */ + MPC55XX_MMU_TAG_INITIALIZER(1, 0x00000000, MPC55XX_MMU_1M, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(4, 0x00100000, MPC55XX_MMU_1M, 1, 0, 1, 0), + /* IO */ + MPC55XX_MMU_TAG_INITIALIZER(2, 0xc3f00000, MPC55XX_MMU_1M, 0, 1, 1, 1), + /* Internal SRAM 512k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_256K, 1, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(5, 0x40040000, MPC55XX_MMU_256K, 1, 1, 1, 0) +#elif MPC55XX_CHIP_FAMILY == 567 + /* Internal SRAM 256k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_256K, 1, 1, 1, 0) +#endif +}; + +const size_t mpc55xx_start_config_mmu_early_count [] = { + RTEMS_ARRAY_SIZE(mpc55xx_start_config_mmu_early) +}; diff --git a/bsps/powerpc/mpc55xxevb/start/start-config-mmu.c b/bsps/powerpc/mpc55xxevb/start/start-config-mmu.c new file mode 100644 index 0000000000..7cf319edd3 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-config-mmu.c @@ -0,0 +1,151 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief MMU configuration. + */ + +/* + * 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/mpc55xx-config.h> + +const struct MMU_tag mpc55xx_start_config_mmu [] = { +#if defined(MPC55XX_BOARD_GWLCFM) + /* External Ethernet Controller 64k */ + MPC55XX_MMU_TAG_INITIALIZER(5, 0x3fff8000, MPC55XX_MMU_64K, 0, 1, 1, 1) +#elif defined(MPC55XX_BOARD_PHYCORE_MPC5554) + /* Arguments macro: idx, addr, size, x, w, r, io */ + MPC55XX_MMU_TAG_INITIALIZER(8, 0x20000000, MPC55XX_MMU_8M, 1, 0, 1, 0), /* External FLASH 8M */ + MPC55XX_MMU_TAG_INITIALIZER(2, 0x21000000, MPC55XX_MMU_4M, 0, 1, 1, 0), /* Lower half SRAM */ + MPC55XX_MMU_TAG_INITIALIZER(5, 0x21400000, MPC55XX_MMU_4M, 1, 1, 1, 0), /* Upper half SRAM ("debug") */ + MPC55XX_MMU_TAG_INITIALIZER(6, 0x22000000, MPC55XX_MMU_16M, 0, 1, 1, 1), /* LAN91C111 */ + MPC55XX_MMU_TAG_INITIALIZER(7, 0x23000000, MPC55XX_MMU_16M, 0, 1, 1, 1), /* FPGA */ +#elif defined(MPC55XX_BOARD_MPC5566EVB) + /* Internal flash 3M */ + MPC55XX_MMU_TAG_INITIALIZER(1, 0x00000000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(6, 0x00010000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(7, 0x00020000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(8, 0x00030000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(9, 0x00040000, MPC55XX_MMU_256K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(10, 0x00080000, MPC55XX_MMU_256K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(11, 0x000c0000, MPC55XX_MMU_256K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(12, 0x00100000, MPC55XX_MMU_1M, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(13, 0x00200000, MPC55XX_MMU_1M, 1, 0, 1, 0), + /* External SRAM 512k */ + MPC55XX_MMU_TAG_INITIALIZER(2, 0x20000000, MPC55XX_MMU_256K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(14, 0x20040000, MPC55XX_MMU_256K, 0, 1, 1, 0), + /* Internal SRAM 128k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_64K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(5, 0x40010000, MPC55XX_MMU_64K, 0, 1, 1, 0), + /* External Ethernet Controller 64k */ + MPC55XX_MMU_TAG_INITIALIZER(15, 0x3fff8000, MPC55XX_MMU_64K, 0, 1, 1, 1) +#elif defined(MPC55XX_BOARD_MPC5674FEVB) + /* Internal flash 4M */ + MPC55XX_MMU_TAG_INITIALIZER(1, 0x00000000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(5, 0x00010000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(6, 0x00020000, MPC55XX_MMU_128K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(7, 0x00040000, MPC55XX_MMU_256K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(8, 0x00080000, MPC55XX_MMU_512K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(9, 0x00100000, MPC55XX_MMU_1M, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(10, 0x00200000, MPC55XX_MMU_2M, 1, 0, 1, 0), + /* External SRAM 512k */ + MPC55XX_MMU_TAG_INITIALIZER(2, 0x20000000, MPC55XX_MMU_512K, 0, 1, 1, 0), + /* Internal SRAM 256k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_128K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(11, 0x40020000, MPC55XX_MMU_64K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(12, 0x40030000, MPC55XX_MMU_32K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(13, 0x40038000, MPC55XX_MMU_16K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(14, 0x4003c000, MPC55XX_MMU_16K, 0, 1, 1, 1), + /* External Ethernet controller */ + MPC55XX_MMU_TAG_INITIALIZER(15, 0x3fff8000, MPC55XX_MMU_64K, 0, 1, 1, 1) +#elif defined(MPC55XX_BOARD_MPC5674F_ECU508) + #if defined(MPC55XX_NEEDS_LOW_LEVEL_INIT) + /* Arguments macro: idx, addr, size, x, w, r, io */ + + /* Internal flash 4M */ + /* First 64k unused, to detect NULL pointer access */ + MPC55XX_MMU_TAG_INITIALIZER(1, 0x00000000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(5, 0x00010000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(6, 0x00020000, MPC55XX_MMU_128K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(7, 0x00040000, MPC55XX_MMU_256K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(8, 0x00080000, MPC55XX_MMU_512K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(9, 0x00100000, MPC55XX_MMU_1M, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(10, 0x00200000, MPC55XX_MMU_2M, 1, 0, 1, 0), + /* External SRAM 2M */ + #ifndef BSP_DATA_CACHE_USE_WRITE_THROUGH + MPC55XX_MMU_TAG_INITIALIZER(2, 0x20000000, MPC55XX_MMU_2M, 0, 1, 1, 0), + #else + MPC55XX_MMU_TAG_INITIALIZER(2, 0x20000000, MPC55XX_MMU_2M, 0, 1, 1, 2), + #endif + /* Internal SRAM 256k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_256K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(11, 0x40020000, MPC55XX_MMU_64K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(12, 0x40030000, MPC55XX_MMU_32K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(13, 0x40038000, MPC55XX_MMU_16K, 0, 1, 1, 0), + /* Used as cache-inhibited area (ADC, DSPI queues) */ + MPC55XX_MMU_TAG_INITIALIZER(14, 0x4003c000, MPC55XX_MMU_16K, 0, 1, 1, 1), + /* External Ethernet controller */ + MPC55XX_MMU_TAG_INITIALIZER(15, 0x3fff8000, MPC55XX_MMU_1K, 0, 1, 1, 1), + /* External MRAM 128k */ + MPC55XX_MMU_TAG_INITIALIZER(16, 0x3ffa0000, MPC55XX_MMU_128K, 0, 1, 1, 0), + /* External ARCNET controller */ + MPC55XX_MMU_TAG_INITIALIZER(17, 0x3ffc0000, MPC55XX_MMU_1K, 0, 1, 1, 1) + /* Peripheral Bridge A-Registers on MMU-table pos 4 */ + /* Peripheral Bridge B-Registers on MMU-table pos 0 */ + #else + /* Used as cache-inhibited area (ADC, DSPI queues) */ + MPC55XX_MMU_TAG_INITIALIZER(14, 0x4003c000, MPC55XX_MMU_16K, 0, 1, 1, 1) + #endif +#elif defined(MPC55XX_BOARD_MPC5674F_RSM6) + /* Arguments macro: idx, addr, size, x, w, r, io */ + + /* Internal flash 4M */ + /* First 64k unused, to detect NULL pointer access */ + MPC55XX_MMU_TAG_INITIALIZER(1, 0x00000000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(5, 0x00010000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(6, 0x00020000, MPC55XX_MMU_128K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(7, 0x00040000, MPC55XX_MMU_256K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(8, 0x00080000, MPC55XX_MMU_512K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(9, 0x00100000, MPC55XX_MMU_1M, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(10, 0x00200000, MPC55XX_MMU_2M, 1, 0, 1, 0), + /* External MRAM 4M */ + MPC55XX_MMU_TAG_INITIALIZER(2, 0x20000000, MPC55XX_MMU_4M, 0, 1, 1, 0), + /* Internal SRAM 256k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_256K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(11, 0x40020000, MPC55XX_MMU_64K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(12, 0x40030000, MPC55XX_MMU_32K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(13, 0x40038000, MPC55XX_MMU_16K, 0, 1, 1, 0), + /* Used as cache-inhibited area (ADC, DSPI queues) */ + MPC55XX_MMU_TAG_INITIALIZER(14, 0x4003c000, MPC55XX_MMU_16K, 0, 1, 1, 1), + /* External FPGA */ + MPC55XX_MMU_TAG_INITIALIZER(15, 0x21000000, MPC55XX_MMU_8M, 0, 1, 1, 1), + /* External Ethernet controller */ + MPC55XX_MMU_TAG_INITIALIZER(16, 0x23000000, MPC55XX_MMU_1K, 0, 1, 1, 1) +#elif MPC55XX_CHIP_FAMILY == 564 + /* Internal flash 1M */ + MPC55XX_MMU_TAG_INITIALIZER(0, 0x00000000, MPC55XX_MMU_1M, 1, 0, 1, 0), + /* IO */ + MPC55XX_MMU_TAG_INITIALIZER(1, 0xffe00000, MPC55XX_MMU_2M, 0, 1, 1, 1), + MPC55XX_MMU_TAG_INITIALIZER(2, 0xc3f00000, MPC55XX_MMU_1M, 0, 1, 1, 1), + /* Internal SRAM 64k + 64k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_64K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(4, 0x50000000, MPC55XX_MMU_64K, 0, 1, 1, 0) +#endif +}; + +const size_t mpc55xx_start_config_mmu_count [] = { + RTEMS_ARRAY_SIZE(mpc55xx_start_config_mmu) +}; diff --git a/bsps/powerpc/mpc55xxevb/start/start-config-siu-pcr.c b/bsps/powerpc/mpc55xxevb/start/start-config-siu-pcr.c new file mode 100644 index 0000000000..8355e647ca --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-config-siu-pcr.c @@ -0,0 +1,148 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief SIU PCR configuration. + */ + +/* + * 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/mpc55xx-config.h> + +const mpc55xx_siu_pcr_config mpc55xx_start_config_siu_pcr [] = { +#if defined(MPC55XX_BOARD_GWLCFM) + { 0,16, 0, {.B.PA = 1, .B.WPE = 0}}, /* PA[ 0..15] analog input */ + { 16, 4, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PB[ 0.. 4] LED/CAN_STBN out */ + { 20, 2, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, /* PB[ 5.. 6] CAN_ERR/USBFLGC in*/ + { 22, 1, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PB[ 7 ] FR_A_EN out */ + { 23, 4, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, /* PB[ 8..10] IRQ/FR_A_ERR/USB_RDYin */ + { 27, 1, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PB[11..11] FR_STBN out */ + + { 32, 2, 0, {.B.PA = 2,.B.OBE = 1,.B.WPE = 0}}, /* PC[ 0.. 1] FR_A_TX/TXEN out */ + { 34, 1, 0, {.B.PA = 2,.B.IBE = 1,.B.WPE = 0}}, /* PC[ 2.. 2] FR_A_RX in */ + { 35, 2, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, /* PC[ 3.. 4] INIT_ERR/ISB_IRQ in */ + { 37, 2, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PC[ 5.. 6] PWRO1/2_ON out */ + { 39, 1, 0, {.B.PA = 2,.B.IBE = 1,.B.WPE = 0}}, /* PC[ 7.. 7] FR_B_RX in */ + { 40, 2, 0, {.B.PA = 2,.B.OBE = 1,.B.WPE = 0}}, /* PC[ 8.. 9] FR_B_TX/TXEN out */ + { 42, 1, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PC[10 ] FR_B_EN out */ + { 43, 1, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, /* PC[11 ] FOR_STATUS in */ + { 44, 1, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, /* PC[12 ] FR_B_ERRN in */ + { 45, 1, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PC[13 ] HS_CAN_STBN out */ + { 46, 1, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, /* PC[14 ] HS_CAN_ERR in */ + { 47, 1, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PC[15 ] HS_CAN_EN out */ + + { 48, 1, 0, {.B.PA = 1,.B.OBE = 1,.B.WPE = 0}}, /* PD[ 0 ] HS_CAN_TX out */ + { 49, 1, 0, {.B.PA = 1,.B.IBE = 1,.B.WPE = 0}}, /* PD[ 1 ] HS_CAN_RX in */ + { 50, 2, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, /* PD[ 2.. 3] PWRO1/2_OC in */ + { 52, 1, 0, {.B.PA = 1,.B.OBE = 1,.B.WPE = 0}}, /* PD[ 4 ] LS_CAN_TX out */ + { 53, 1, 0, {.B.PA = 1,.B.IBE = 1,.B.WPE = 0}}, /* PD[ 5 ] LS_CAN_RX in */ + { 54, 1, 0, {.B.PA = 1,.B.OBE = 1,.B.WPE = 0}}, /* PD[ 6 ] HS_CAN_TX out */ + { 55, 1, 0, {.B.PA = 1,.B.IBE = 1,.B.WPE = 0}}, /* PD[ 7 ] HS_CAN_RX in */ + { 56, 1, 0, {.B.PA = 2,.B.IBE = 1,.B.OBE = 1,.B.WPE = 0}}, + /* PD[ 8 ] I2C_SCL in/out */ + { 57, 1, 0, {.B.PA = 2,.B.IBE = 1,.B.OBE = 1,.B.WPE = 0}}, + /* PD[ 9 ] I2C_SDA in/out */ + + { 58, 1, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PD[10] LS_CAN_EN out*/ + { 59, 3, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, + /* PD[11..13] PWO1_OC, MOCO_INT in */ + + { 62, 4, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, /* PD[14..15] USB_FLGA/B in */ + + { 64, 5, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PE[ 0.. 4] LED_EXT1-5. out*/ + { 70, 1, 0, {.B.PA = 1,.B.SRC = 3,.B.WPE = 0}}, /* PE[ 6.. 6] CLKOUT out*/ + + { 80, 1, 0, {.B.PA = 1,.B.SRC = 1,.B.WPE = 0}}, /* PF[ 0.. 0] RD_WR out*/ + { 81, 1, 0, {.B.PA = 0,.B.SRC = 0,.B.WPE = 0}}, /* PF[ 1.. 1] (nc) in */ + { 82, 8, 0, {.B.PA = 2,.B.SRC = 1,.B.WPE = 0}}, /* PF[ 2..11] ADDR[8..15] out*/ + { 90, 2, 0, {.B.PA = 1,.B.SRC = 1,.B.WPE = 0}}, /* PF[ 2..11] CS[0..1] out*/ + { 92, 1, 0, {.B.PA = 3,.B.SRC = 3,.B.WPE = 0}}, /* PF[ 12] ALE out*/ + { 93, 3, 0, {.B.PA = 1,.B.SRC = 1,.B.WPE = 0}}, /* PF[13..15] OE/WE out*/ + + { 96,16, 0, {.B.PA = 1,.B.SRC = 1,.B.WPE = 0}}, /* PG[ 0..15] AD16..31 in/out*/ + + {113, 1, 1, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PH[ 1.. 1] RES_MOSTComp out*/ + {114, 1, 0, {.B.PA = 3,.B.OBE = 1,.B.WPE = 0}}, /* PH[ 2.. 2] CS3_MOSTComp out*/ + {115, 1, 0, {.B.PA = 3,.B.OBE = 1,.B.WPE = 0}}, /* PH[ 3.. 3] CS2_ETH out*/ + {116, 2, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PH[ 4.. 5] FR/HC_TERM out*/ + {118, 1, 0, {.B.PA = 2,.B.OBE = 1,.B.WPE = 0}}, /* PH[ 6.. 6] LIN_Tx out*/ + {119, 1, 0, {.B.PA = 2,.B.IBE = 1,.B.WPE = 0}}, /* PH[ 7.. 7] LIN_Rx in */ + {120, 1, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PH[ 8..11] LIN_SLP,RST out*/ + {121, 2, 1, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PH[ 8..11] LIN_SLP,RST out*/ + {120, 1, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}} /* PH[ 8..11] LIN_SLP,RST out*/ +#elif defined(MPC55XX_BOARD_PHYCORE_MPC5554) + { 0, 4, 0, {.B.PA = 1, .B.DSC = 1,.B.WPE=1,.B.WPS=1}}, /* !CS [0:3] */ + { 4,24, 0, {.B.PA = 1, .B.DSC = 1 }}, /* ADDR [8 : 31] */ + { 28,32, 0, {.B.PA = 1, .B.DSC = 1 }}, /* DATA [0 : 31] */ + { 60, 4, 0, {.B.PA = 1, .B.DSC = 1, }}, /* TSIZ[0:1], RD_!WR, BDIP */ + { 64, 6, 0, {.B.PA = 1, .B.DSC = 1,.B.WPE=1,.B.WPS=1}}, /* RD_!WR, BDIP, !WE, !OE, !TS */ + { 89, 4, 0, {.B.PA = 1 }}, /* ESCI_A and ESCI_B */ + {229, 4, 0, { .B.OBE= 1,.B.DSC = 1 }} /* CLKOUT */ +#elif defined(MPC55XX_BOARD_MPC5566EVB) + { 0, 1, 0, {.B.PA = 1,.B.DSC = 1,.B.WPE=1,.B.WPS=1}}, /* !CS [0] */ + { 3, 1, 0, {.B.PA = 1,.B.DSC = 1,.B.WPE=1,.B.WPS=1}}, /* !CS [3] */ + { 4,24, 0, {.B.PA = 1,.B.DSC = 1 }}, /* ADDR [8 : 31] */ + { 28,16, 0, {.B.PA = 1,.B.DSC = 1 }}, /* DATA [0 : 15] */ + { 62, 8, 0, {.B.PA = 1,.B.DSC = 1,.B.WPE=1,.B.WPS=1}}, /* RD_!WR, BDIP, + !WE, !OE, !TS */ + { 89, 2, 0, {.B.PA = 1 }} /* ESCI_B */ +#elif defined(MPC55XX_BOARD_MPC5674FEVB) + { 89, 2, 0, { .B = { .PA = 1 } } }, /* ESCI_A */ + { 256, 1, 0, { .B = { .PA = 1, .DSC = 1 } } }, /* D_CS0 */ + { 257, 1, 0, { .B = { .PA = 2, .DSC = 1 } } }, /* D_ADD_DAT31 */ + { 259, 4, 0, { .B = { .PA = 1, .DSC = 1 } } }, /* D_ADD12 .. D_ADD15 */ + { 263, 15, 0, { .B = { .PA = 2, .DSC = 1 } } }, /* D_ADD_DAT16 .. D_ADD_DAT30 */ + { 278, 16, 0, { .B = { .PA = 1, .DSC = 1 } } }, /* D_ADD_DAT0 .. D_ADD_DAT15 */ + { 294, 6, 0, { .B = { .PA = 1, .DSC = 1 } } }, /* D_RD_WR, D_WE0, D_WE1, D_OE, D_TS, D_ALE */ + { 301, 1, 0, { .B = { .PA = 1, .DSC = 1 } } }, /* D_CS1 */ + { 302, 6, 0, { .B = { .PA = 1, .DSC = 1 } } } /* D_BDIP, D_WE2, D_WE3, D_ADD9 .. D_ADD11 */ +#elif defined(MPC55XX_BOARD_MPC5674F_ECU508) \ + && defined(MPC55XX_NEEDS_LOW_LEVEL_INIT) + { 196, 2, 0, { .B = { .PA = 0, .OBE = 1, .WPE = 0 } } }, /* EMIOS17 .. EMIOS18 (5VS_EN, 80V_EN) */ + { 200, 4, 0, { .B = { .PA = 0, .OBE = 1, .WPE = 0 } } }, /* EMIOS21 .. EMIOS24 (\KS_RST, \LS_RST, \IGNINJ_RST, \INJDI_RST) */ + { 204, 1, 1, { .B = { .PA = 0, .OBE = 1, .WPE = 0 } } }, /* EMIOS25 (HBR12_RST) */ + { 244, 2, 0, { .B = { .PA = 1 } } }, /* ESCI_C */ + { 256, 1, 0, { .B = { .PA = 1, .DSC = 0 } } }, /* D_CS0 */ + { 257, 1, 0, { .B = { .PA = 2, .DSC = 1 } } }, /* D_ADD_DAT31 */ + { 258, 1, 0, { .B = { .PA = 1, .DSC = 0 } } }, /* D_CS3 */ + { 259, 4, 0, { .B = { .PA = 1, .DSC = 0 } } }, /* D_ADD12 .. D_ADD15 */ + { 263, 15, 0, { .B = { .PA = 2, .DSC = 1 } } }, /* D_ADD_DAT16 .. D_ADD_DAT30 */ + { 278, 16, 0, { .B = { .PA = 1, .DSC = 0 } } }, /* D_ADD_DAT0 .. D_ADD_DAT15 */ + { 294, 6, 0, { .B = { .PA = 1, .DSC = 0 } } }, /* D_RD_WR, D_WE0, D_WE1, D_OE, D_TS, D_ALE */ + { 301, 1, 0, { .B = { .PA = 1, .DSC = 0 } } }, /* D_CS1 */ + { 302, 3, 0, { .B = { .PA = 1, .DSC = 0 } } }, /* D_BDIP, D_WE2, D_WE3 */ + { 305, 3, 0, { .B = { .PA = 1, .DSC = 0 } } }, /* D_ADD9 .. D_ADD11 */ + { 432, 1, 1, { .B = { .PA = 0, .OBE = 1, .WPE = 0 } } }, /* EMIOS26 (HBR34_RST) */ + { 433, 1, 0, { .B = { .PA = 0, .OBE = 1, .WPE = 0 } } } /* EMIOS27 (\ETH_RST) */ +#elif defined(MPC55XX_BOARD_MPC5674F_RSM6) + { 89, 1, 0, { .B = { .PA = 1, .OBE = 1, .IBE = 1, .WPE = 1, .WPS = 1 } } }, /* TXD_A (ESCI_A)*/ + { 90, 1, 0, { .B = { .PA = 1, .OBE = 0, .IBE = 1, .WPE = 1, .WPS = 1 } } }, /* RXD_A (ESCI_A)*/ + { 256, 1, 0, { .B = { .PA = 1, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_CS0 */ + { 257, 1, 0, { .B = { .PA = 2, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_ADD_DAT31 */ + { 258, 1, 0, { .B = { .PA = 1, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_CS3 */ + { 259, 4, 0, { .B = { .PA = 1, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_ADD12 .. D_ADD15 */ + { 263, 15, 0, { .B = { .PA = 2, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_ADD_DAT16 .. D_ADD_DAT30 */ + { 278, 16, 0, { .B = { .PA = 1, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_ADD_DAT0 .. D_ADD_DAT15 */ + { 294, 6, 0, { .B = { .PA = 1, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_RD_WR, D_WE0, D_WE1, D_OE, D_TS, D_ALE */ + { 301, 1, 0, { .B = { .PA = 1, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_CS1 */ + { 302, 3, 0, { .B = { .PA = 1, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_BDIP, D_WE2, D_WE3 */ + { 305, 3, 0, { .B = { .PA = 1, .DSC = 3, .WPE = 1, .WPS = 1 } } } /* D_ADD9 .. D_ADD11 */ +#endif +}; + +const size_t mpc55xx_start_config_siu_pcr_count [] = { + RTEMS_ARRAY_SIZE(mpc55xx_start_config_siu_pcr) +}; diff --git a/bsps/powerpc/mpc55xxevb/start/start-early.c b/bsps/powerpc/mpc55xxevb/start/start-early.c new file mode 100644 index 0000000000..e1a0b3da09 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-early.c @@ -0,0 +1,216 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief Early initialization 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/mpc55xx-config.h> +#include <bsp/linker-symbols.h> + +/* This function is defined in start.S */ +BSP_START_TEXT_SECTION void mpc55xx_start_load_section( + void *dst, + const void *src, + size_t n +); + +static BSP_START_TEXT_SECTION void mpc55xx_start_mmu(void) +{ + #ifdef MPC55XX_BOOTFLAGS + /* If the low bit of bootflag 0 is clear don't change the MMU. */ + bool do_mmu_config = (mpc55xx_bootflag_0 [0] & 1) != 0; + #else + bool do_mmu_config = true; + #endif + + if (do_mmu_config) { + mpc55xx_start_mmu_apply_config( + &mpc55xx_start_config_mmu [0], + mpc55xx_start_config_mmu_count [0] + ); + } +} + +static BSP_START_TEXT_SECTION void mpc55xx_start_internal_ram(void) +{ + #ifdef MPC55XX_NEEDS_LOW_LEVEL_INIT + /* Initialize internal SRAM to zero (ECC) */ + bsp_start_zero( + (char *) bsp_ram_start + MPC55XX_EARLY_STACK_SIZE, + (size_t) bsp_ram_size - MPC55XX_EARLY_STACK_SIZE + ); + #ifdef MPC55XX_HAS_SECOND_INTERNAL_RAM_AREA + bsp_start_zero(&bsp_ram_1_start [0], (size_t) bsp_ram_1_size); + #endif + #else + bsp_start_zero( + bsp_section_sbss_begin, + (size_t) bsp_section_sbss_size + ); + bsp_start_zero( + bsp_section_bss_begin, + (size_t) bsp_section_bss_size + ); + #endif +} + +static BSP_START_TEXT_SECTION void mpc55xx_start_load_nocache_section(void) +{ + mpc55xx_start_load_section( + bsp_section_nocache_begin, + bsp_section_nocache_load_begin, + (size_t) bsp_section_nocache_size + ); + rtems_cache_flush_multiple_data_lines( + bsp_section_nocache_begin, + (size_t) bsp_section_nocache_size + ); +} + +static BSP_START_TEXT_SECTION void mpc55xx_start_mode_change(void) +{ + #ifdef MPC55XX_NEEDS_LOW_LEVEL_INIT + #ifdef MPC55XX_HAS_MODE_CONTROL + uint32_t mctl_key1 = 0x5af0; + uint32_t mctl_key2 = 0xa50f; + int i = 0; + + /* Clear any pending RGM status */ + RGM.FES.R = 0xffff; + RGM.DES.R = 0xffff; + + /* Make sure XOSC and PLLs are on in RUN0 state */ + ME.DRUN_MC.R = 0x001f0074; + ME.RUN_MC [0].R = 0x001f0074; + + /* + * Make sure all peripherals are active in DRUN and RUN0 state. + * + * FIXME: This might be optimized to reduce power consumtion. + */ + for (i = 0; i < 8; ++i) { + ME_RUN_PC_32B_tag run_pc = { .R = ME.RUN_PC [i].R }; + + run_pc.B.DRUN = 1; + run_pc.B.RUN0 = 1; + + ME.RUN_PC [i].R = run_pc.R; + } + + /* Switch to RUN0 state */ + ME.MCTL.R = 0x40000000 | mctl_key1; + ME.MCTL.R = 0x40000000 | mctl_key2; + + while (ME.GS.B.S_MTRANS) { + /* Wait for mode switch to be completed */ + } + #endif + #endif +} + +static BSP_START_TEXT_SECTION void mpc55xx_start_siu(void) +{ + size_t i = 0; + + for (i = 0; i < mpc55xx_start_config_siu_pcr_count [0]; ++i) { + const mpc55xx_siu_pcr_config *e = &mpc55xx_start_config_siu_pcr [i]; + int j = e->index; + int n = j + e->count; + uint8_t gpdo = e->output; + uint16_t pcr = e->pcr.R; + + while (j < n) { + SIU.GPDO [j].R = gpdo; + SIU.PCR [j].R = pcr; + ++j; + } + } +} + +static BSP_START_TEXT_SECTION void mpc55xx_start_ebi_chip_select(void) +{ + #ifdef MPC55XX_HAS_EBI + size_t i = 0; + + for (i = 0; i < mpc55xx_start_config_ebi_cs_count [0]; ++i) { + EBI.CS [i] = mpc55xx_start_config_ebi_cs [i]; + } + + for (i = 0; i < mpc55xx_start_config_ebi_cal_cs_count [0]; ++i) { + EBI.CAL_CS [i] = mpc55xx_start_config_ebi_cal_cs [i]; + } + #endif +} + +static BSP_START_TEXT_SECTION void mpc55xx_start_ebi(void) +{ + #ifdef MPC55XX_HAS_EBI + size_t i = 0; + + for (i = 0; i < mpc55xx_start_config_ebi_count [0]; ++i) { + SIU.ECCR.B.EBDF = mpc55xx_start_config_ebi [i].siu_eccr_ebdf; + EBI.MCR.R = mpc55xx_start_config_ebi [i].ebi_mcr.R; + } + #endif +} + +#ifdef MPC55XX_NEEDS_LOW_LEVEL_INIT +static BSP_START_TEXT_SECTION bool +mpc55xx_start_is_in_internal_ram(const void *addr) +{ + return (size_t) addr - (size_t) bsp_ram_start < (size_t) bsp_ram_size; +} +#endif + +static BSP_START_TEXT_SECTION void mpc55xx_start_clear_bss(void) +{ + #ifdef MPC55XX_NEEDS_LOW_LEVEL_INIT + if (!mpc55xx_start_is_in_internal_ram(bsp_section_sbss_begin)) { + bsp_start_zero( + bsp_section_sbss_begin, + (size_t) bsp_section_sbss_size + ); + } + + if (!mpc55xx_start_is_in_internal_ram(bsp_section_bss_begin)) { + bsp_start_zero( + bsp_section_bss_begin, + (size_t) bsp_section_bss_size + ); + } + #endif +} + +BSP_START_TEXT_SECTION void mpc55xx_start_early(void) +{ + mpc55xx_start_watchdog(); + mpc55xx_start_clock(); + mpc55xx_start_flash(); + #if defined(BSP_DATA_CACHE_ENABLED) || defined(BSP_INSTRUCTION_CACHE_ENABLED) + mpc55xx_start_cache(); + #endif + mpc55xx_start_internal_ram(); + mpc55xx_start_load_nocache_section(); + mpc55xx_start_mmu(); + mpc55xx_start_mode_change(); + mpc55xx_start_siu(); + mpc55xx_start_ebi_chip_select(); + mpc55xx_start_ebi(); + mpc55xx_start_clear_bss(); +} diff --git a/bsps/powerpc/mpc55xxevb/start/start-flash.S b/bsps/powerpc/mpc55xxevb/start/start-flash.S new file mode 100644 index 0000000000..9c87d38a83 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-flash.S @@ -0,0 +1,139 @@ +/** + * @file + * + * @ingroup mpc55xx_asm + * + * @brief Flash configuration. + */ + +/* + * Copyright (c) 2008-2015 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 <libcpu/powerpc-utility.h> +#include <mpc55xx/reg-defs.h> + + .section ".bsp_start_text", "ax" + +#if MPC55XX_CHIP_FAMILY == 551 + +/* MPC5510 Microcontroller Family Data Sheet, Rev. 3, Table 16, Num 7 */ +.equ FLASH_CLOCK_0, 25000000 +.equ FLASH_CLOCK_1, 50000000 +.equ FLASH_CLOCK_2, 80000000 +.equ FLASH_CLOCK_3, FLASH_CLOCK_2 +.equ FLASH_SETTINGS_0, FLASH_BUICR_CPU_PREFTCH | FLASH_BUICR_APC_0 | FLASH_BUICR_RWSC_0 | FLASH_BUICR_WWSC_1 | FLASH_BUICR_DPFEN_1 | FLASH_BUICR_IPFEN_1 | FLASH_BUICR_PFLIM_2 | FLASH_BUICR_BFEN +.equ FLASH_SETTINGS_1, FLASH_BUICR_CPU_PREFTCH | FLASH_BUICR_APC_1 | FLASH_BUICR_RWSC_1 | FLASH_BUICR_WWSC_1 | FLASH_BUICR_DPFEN_1 | FLASH_BUICR_IPFEN_1 | FLASH_BUICR_PFLIM_2 | FLASH_BUICR_BFEN +.equ FLASH_SETTINGS_2, FLASH_BUICR_CPU_PREFTCH | FLASH_BUICR_APC_2 | FLASH_BUICR_RWSC_2 | FLASH_BUICR_WWSC_1 | FLASH_BUICR_DPFEN_1 | FLASH_BUICR_IPFEN_1 | FLASH_BUICR_PFLIM_2 | FLASH_BUICR_BFEN +.equ FLASH_SETTINGS_3, FLASH_SETTINGS_2 + +#else + +/* Optimized flash configurations (Table 13-15 [MPC5567 Microcontroller Reference Manual]) */ +.equ FLASH_CLOCK_0, 82000000 +.equ FLASH_CLOCK_1, 102000000 +.equ FLASH_CLOCK_2, 132000000 +.equ FLASH_CLOCK_3, 264000000 +.equ FLASH_SETTINGS_0, FLASH_BUICR_CPU_PREFTCH | FLASH_BUICR_APC_1 | FLASH_BUICR_RWSC_1 | FLASH_BUICR_WWSC_1 | FLASH_BUICR_DPFEN_3 | FLASH_BUICR_IPFEN_3 | FLASH_BUICR_PFLIM_6 | FLASH_BUICR_BFEN +.equ FLASH_SETTINGS_1, FLASH_BUICR_CPU_PREFTCH | FLASH_BUICR_APC_1 | FLASH_BUICR_RWSC_2 | FLASH_BUICR_WWSC_1 | FLASH_BUICR_DPFEN_3 | FLASH_BUICR_IPFEN_3 | FLASH_BUICR_PFLIM_6 | FLASH_BUICR_BFEN +.equ FLASH_SETTINGS_2, FLASH_BUICR_CPU_PREFTCH | FLASH_BUICR_APC_2 | FLASH_BUICR_RWSC_3 | FLASH_BUICR_WWSC_1 | FLASH_BUICR_DPFEN_3 | FLASH_BUICR_IPFEN_3 | FLASH_BUICR_PFLIM_6 | FLASH_BUICR_BFEN +.equ FLASH_SETTINGS_3, 0x01716B15 + +#endif + +/** + * @fn void mpc55xx_start_flash() + * @brief Optimized flash configuration. + * @warning Code will be copied and executed on the stack. + */ +GLOBAL_FUNCTION mpc55xx_start_flash +#if !defined(MPC55XX_NEEDS_LOW_LEVEL_INIT) \ + || MPC55XX_CHIP_FAMILY == 564 \ + || MPC55XX_CHIP_FAMILY == 566 + blr +#else + .equ stack_size, 20 + .equ lr_offset, 28 + + /* Reserve stack frame */ + stwu r1, -stack_size(r1) + mflr r0 + stw r0, lr_offset(r1) + + /* Flash settings dependent on system clock */ + bl mpc55xx_get_system_clock + LWI r4, FLASH_CLOCK_0 + cmpw r3, r4 + ble clock_0 + LWI r4, FLASH_CLOCK_1 + cmpw r3, r4 + ble clock_1 + LWI r4, FLASH_CLOCK_2 + cmpw r3, r4 + ble clock_2 + LWI r4, FLASH_CLOCK_3 + cmpw r3, r4 + ble clock_3 + + /* + * In case we don't have the right flash settings for the system clock + * value, then rely on the BAM settings. + */ + blr + +clock_0: + LWI r3, FLASH_SETTINGS_0 + b settings_done +clock_1: + LWI r3, FLASH_SETTINGS_1 + b settings_done +clock_2: + LWI r3, FLASH_SETTINGS_2 + b settings_done +clock_3: + LWI r3, FLASH_SETTINGS_3 + b settings_done +settings_done: + + /* Copy store code on the stack */ + LA r4, store_start + lwz r6, 0(r4) + lwz r7, 4(r4) + lwz r8, 8(r4) + stw r6, 8(r1) + stw r7, 12(r1) + stw r8, 16(r1) + + /* Execute store code */ + LA r4, FLASH_BIUCR + addi r5, r1, 8 + mtctr r5 + bctrl + + /* Return */ + lwz r0, lr_offset(r1) + addi r1, r1, stack_size + mtlr r0 + blr + +/* + * Store flash settings + */ + +store_start: + + stw r3, 0(r4) + isync + blr + +#endif diff --git a/bsps/powerpc/mpc55xxevb/start/start-prologue.c b/bsps/powerpc/mpc55xxevb/start/start-prologue.c new file mode 100644 index 0000000000..872a96edfd --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-prologue.c @@ -0,0 +1,28 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief Start prologue. + */ + +/* + * Copyright (c) 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 <bsp/mpc55xx-config.h> + +BSP_START_TEXT_SECTION void mpc55xx_start_prologue(void) +{ + /* Do nothing */ +} diff --git a/bsps/powerpc/mpc55xxevb/start/start-watchdog.c b/bsps/powerpc/mpc55xxevb/start/start-watchdog.c new file mode 100644 index 0000000000..7cf36ef02f --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-watchdog.c @@ -0,0 +1,39 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief Watchdog initialization code. + */ + +/* + * 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.h> +#include <bsp/start.h> +#include <bsp/mpc55xx-config.h> + +BSP_START_TEXT_SECTION void mpc55xx_start_watchdog(void) +{ + #ifdef MPC55XX_NEEDS_LOW_LEVEL_INIT + #ifdef MPC55XX_HAS_SWT + /* Write keys to clear soft lock bit */ + SWT.SR.R = 0x0000c520; + SWT.SR.R = 0x0000d928; + + /* Clear watchdog enable (WEN) */ + SWT.CR.R = 0x8000010A; + #endif + #endif +} diff --git a/bsps/powerpc/mpc8260ads/start/bsp_specs b/bsps/powerpc/mpc8260ads/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/mpc8260ads/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/mpc8260ads/start/bspstart.c b/bsps/powerpc/mpc8260ads/start/bspstart.c new file mode 100644 index 0000000000..44ec072775 --- /dev/null +++ b/bsps/powerpc/mpc8260ads/start/bspstart.c @@ -0,0 +1,191 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * The MPC860 specific stuff was written by Jay Monkman (jmonkman@frasca.com) + * + * Modified for the MPC8260ADS board by Andy Dachs <a.dachs@sstl.co.uk> + * Surrey Satellite Technology Limited, 2001 + * A 40MHz system clock is assumed. + * The PON. RST.CONF. Dip switches (DS1) are + * 1 - Off + * 2 - On + * 3 - Off + * 4 - On + * 5 - Off + * 6 - Off + * 7 - Off + * 8 - Off + * Dip switches on DS2 and DS3 are all set to ON + * The LEDs on the board are used to signal panic and fatal_error + * conditions. + * The mmu is unused at this time. + * + * COPYRIGHT (c) 1989-2007. + * 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> + +/* +#include <mmu.h> +*/ + +#include <mpc8260.h> +#include <rtems/score/thread.h> +#include <rtems/powerpc/powerpc.h> + +#include <rtems/bspIo.h> +#include <rtems/counter.h> +#include <bsp/irq.h> +#include <libcpu/cpuIdent.h> +#include <libcpu/spr.h> + +#include <string.h> + +#define UART1_E 0x02000002 /* bit 6 of BCSR1 */ +#define UART2_E 0x01000001 /* bit 7 of BCSR1 */ + +#define GP0_LED 0x02000002 /* bit 6 of BCSR0 */ +#define GP1_LED 0x01000001 /* bit 7 of BCSR0 */ + +SPR_RW(SPRG1) + +/* + * Driver configuration parameters + */ +uint32_t bsp_clock_speed; +uint32_t bsp_time_base_frequency; +uint32_t bsp_clicks_per_usec; +uint32_t bsp_serial_per_sec; /* Serial clocks per second */ +bool bsp_serial_external_clock; +bool bsp_serial_xon_xoff; +bool bsp_serial_cts_rts; +uint32_t bsp_serial_rate; + +extern char IntrStack_start []; +extern char intrStack []; + +static void _BSP_GPLED0_on(void) +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr0 &= ~GP0_LED; /* Turn on GP0 LED */ +} + +static void _BSP_GPLED0_off(void) +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr0 |= GP0_LED; /* Turn off GP0 LED */ +} + +static void _BSP_GPLED1_on(void) +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr0 &= ~GP1_LED; /* Turn on GP1 LED */ +} + +static void _BSP_GPLED1_off(void) +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr0 |= GP1_LED; /* Turn off GP1 LED */ +} + +static void _BSP_Uart1_enable(void) +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr1 &= ~UART1_E; /* Enable Uart1 */ +} + +static void _BSP_Uart2_enable(void) +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr1 &= ~UART2_E; /* Enable Uart2 */ +} + +void bsp_start(void) +{ + /* Set MPC8260ADS board LEDS and Uart enable lines */ + _BSP_GPLED0_off(); + _BSP_GPLED1_off(); + _BSP_Uart1_enable(); + _BSP_Uart2_enable(); + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function stores the result in global variables so that it can be used + * later... + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + cpu_init(); + +/* + mmu_init(); +*/ + + /* Initialize exception handler */ + /* FIXME: Interrupt stack begin and size */ + ppc_exc_initialize( + (uintptr_t) IntrStack_start, + (uintptr_t) intrStack - (uintptr_t) IntrStack_start + ); + + /* Initalize interrupt support */ + bsp_interrupt_initialize(); + +/* + mmu_init(); +*/ + + /* + * Enable instruction and data caches. Do not force writethrough mode. + */ +#if BSP_INSTRUCTION_CACHE_ENABLED + rtems_cache_enable_instruction(); +#endif +#if BSP_DATA_CACHE_ENABLED + rtems_cache_enable_data(); +#endif + + /* + * initialize the device driver parameters + */ + bsp_time_base_frequency = 10000000; + bsp_clicks_per_usec = 10; /* for 40MHz extclk */ + bsp_serial_per_sec = 40000000; + bsp_serial_external_clock = 0; + bsp_serial_xon_xoff = 0; + bsp_serial_cts_rts = 0; + bsp_serial_rate = 9600; + bsp_clock_speed = 40000000; + rtems_counter_initialize_converter(bsp_clock_speed); + +#ifdef REV_0_2 + /* set up some board specific registers */ + m8260.siumcr &= 0xF3FFFFFF; /* set TBEN ** BUG FIX ** */ + m8260.siumcr |= 0x08000000; +#endif + + /* use BRG1 to generate 32kHz timebase */ +/* + m8260.brgc1 = M8260_BRG_EN + (uint32_t)(((uint16_t)((40016384)/(32768)) - 1) << 1) + 0; +*/ + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Exit from bspstart\n"); +#endif + +} diff --git a/bsps/powerpc/mpc8260ads/start/cpuinit.c b/bsps/powerpc/mpc8260ads/start/cpuinit.c new file mode 100644 index 0000000000..c56ec69362 --- /dev/null +++ b/bsps/powerpc/mpc8260ads/start/cpuinit.c @@ -0,0 +1,49 @@ +/* + * cpuinit.c - this file contains functions for initializing the CPU + * + * Written by Jay Monkman (jmonkman@frasca.com) + */ + +#include <bsp.h> + +/* Macros for handling all the MMU SPRs */ +#define PUT_IC_CST(r) __asm__ volatile ("mtspr 0x230,%0\n" ::"r"(r)) +#define GET_IC_CST(r) __asm__ volatile ("mfspr %0,0x230\n" :"=r"(r)) +#define PUT_DC_CST(r) __asm__ volatile ("mtspr 0x238,%0\n" ::"r"(r)) +#define GET_DC_CST(r) __asm__ volatile ("mfspr %0,0x238\n" :"=r"(r)) + +void cpu_init(void) +{ + /* BRGCLK is VCO_OUT/4 */ +/* + m8260.sccr = 0; +*/ + +#if 0 + register unsigned long t1, t2; + + /* Let's clear MSR[IR] and MSR[DR] */ + t2 = PPC_MSR_IR | PPC_MSR_DR; + __asm__ volatile ( + "mfmsr %0\n" + "andc %0, %0, %1\n" + "mtmsr %0\n" :"=r"(t1), "=r"(t2): + "1"(t2)); + + t1 = M8xx_CACHE_CMD_UNLOCK; + /* PUT_DC_CST(t1); */ + PUT_IC_CST(t1); + + t1 = M8xx_CACHE_CMD_INVALIDATE; + /* PUT_DC_CST(t1); */ + PUT_IC_CST(t1); + + t1 = M8xx_CACHE_CMD_ENABLE; + PUT_IC_CST(t1); + + t1 = M8xx_CACHE_CMD_SFWT; + /* PUT_DC_CST(t1); */ + t1 = M8xx_CACHE_CMD_ENABLE; + /* PUT_DC_CST(t1);*/ +#endif +} diff --git a/bsps/powerpc/mpc8260ads/start/linkcmds b/bsps/powerpc/mpc8260ads/start/linkcmds new file mode 100644 index 0000000000..f3092b862d --- /dev/null +++ b/bsps/powerpc/mpc8260ads/start/linkcmds @@ -0,0 +1,352 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the MPC8260ADS Board + */ + +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc) + +ENTRY(start) +STARTUP(start.o) +EXTERN(__vectors) + +/* + * Declare some sizes. + * XXX: The assignment of ". += XyzSize;" fails in older gld's if the + * number used there is not constant. If this happens to you, edit + * the lines marked XXX below to use a constant value. + */ +StackSize = DEFINED(StackSize) ? StackSize : 0x8000; +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamDiskSize : 0x0800000; /* 8M program ram */ +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +RamDiskBase = DEFINED(RamDiskBase) ? RamDiskBase : 0x0800000; +RamDiskSize = DEFINED(RamDiskSize) ? RamDiskSize : 0x0800000; /* 8M ram disk */ + +MEMORY +{ + ram : org = 0x0, l = 8M + ramdisk : org = 0x0800000, l = 8M + dpram : org = 0x04700000, l = 128K + flash : org = 0xff800000, l = 8M +} + + +SECTIONS +{ + /* + * The stack will live in this area - between the vectors and + * the text section. + */ + + .text 0x10000: + { + _textbase = .; + + + text.start = .; + + /* Entry point is the .entry section */ + *(.entry) + *(.entry2) + + /* Actual Code */ + *(.text*) + + + *(.rodata*) + *(.rodata1) + + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* C++ constructors/destructors */ + *(.gnu.linkonce.t*) + + /* Initialization and finalization code. + * + * Various files can provide initialization and finalization functions. + * The bodies of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues from + * ecrti.o and function epilogues from ecrtn.o. ecrti.o must be linked + * first; ecrtn.o must be linked last. Because these are wildcards, it + * doesn't matter if the user does not actually link against ecrti.o and + * ecrtn.o; the linker won't look for a file to match a wildcard. The + * wildcard also means that it doesn't matter which directory ecrti.o + * and ecrtn.o are in. + */ + PROVIDE (_init = .); + *ecrti.o(.init) + *(.init) + *ecrtn.o(.init) + + PROVIDE (_fini = .); + *ecrti.o(.fini) + *(.fini) + *ecrtn.o(.init) + + /* + * C++ constructors and destructors for static objects. + * PowerPC EABI does not use crtstuff yet, so we build "old-style" + * constructor and destructor lists that begin with the list length + * end terminate with a NULL entry. + */ + + PROVIDE (__CTOR_LIST__ = .); + /* LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) */ + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + LONG(0) + PROVIDE (__CTOR_END__ = .); + + PROVIDE (__DTOR_LIST__ = .); + /* LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) */ + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + LONG(0) + PROVIDE (__DTOR_END__ = .); + + /* Exception frame info */ + *(.eh_frame) + + /* Miscellaneous read-only data */ + _rodata_start = . ; + *(.gnu.linkonce.r*) + *(.lit) + *(.shdata) + *(.rodata) + *(.rodata1) + KEEP (*(SORT(.rtemsroset.*))) + *(.descriptors) + *(rom_ver) + _erodata = .; + + + /* Various possible names for the end of the .text section */ + etext = ALIGN(0x10); + _etext = .; + _endtext = .; + text.end = .; + PROVIDE (etext = .); + PROVIDE (__etext = .); + + } > ram + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >ram + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >ram + + _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)); + + + .rel.dyn : + { + *(.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.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) + *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) + *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) + *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + } >ram + .rela.dyn : + { + *(.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.got1) + *(.rela.got2) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } >ram + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + + PROVIDE (__EXCEPT_START__ = .); + .gcc_except_table : { *(.gcc_except_table*) } >ram + PROVIDE (__EXCEPT_END__ = .); + __GOT_START__ = .; + .got : + { + s.got = .; + *(.got.plt) *(.got) + } > ram + __GOT_END__ = .; + + .got1 : { *(.got1) } >ram + PROVIDE (__GOT2_START__ = .); + PROVIDE (_GOT2_START_ = .); + .got2 : { *(.got2) } >ram + PROVIDE (__GOT2_END__ = .); + PROVIDE (_GOT2_END_ = .); + + PROVIDE (__FIXUP_START__ = .); + PROVIDE (_FIXUP_START_ = .); + .fixup : { *(.fixup) } >ram + PROVIDE (_FIXUP_END_ = .); + PROVIDE (__FIXUP_END__ = .); + + .sdata : { + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + } > ram + + .sbss : { + __bss_start = .; + + PROVIDE (__sbss_start = .); PROVIDE (___sbss_start = .); + *(.scommon) + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + PROVIDE (__sbss_end = .); PROVIDE (___sbss_end = .); + } > ram + + .sdata2 : { + PROVIDE (_SDA2_BASE_ = 32768); + + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + } > ram =0 + + .sbss2 : { + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + } > ram =0 + + .bss : + { + bss.start = .; + *(.bss .bss* .gnu.linkonce.b*) + . = ALIGN(4); + bss.end = .; + } > ram + + /* R/W Data */ + .data ( . ) : + { + . = ALIGN (4); + + data.start = .; + + *(.data) + *(.data1) + *(.data.* .gnu.linkonce.d.*) + KEEP (*(SORT(.rtemsrwset.*))) + PROVIDE (__SDATA_START__ = .); + *(.sdata .sdata.* .gnu.linkonce.s.*) + data.end = .; + } > ram + + data.size = data.end - data.start; + bss.size = bss.end - bss.start; + text.size = text.end - text.start; + + PROVIDE(_end = data.end); + + .gzipmalloc : { + . = ALIGN (16); + _startmalloc = .; + } >ram + + + /* + * Interrupt stack setup + */ + IntrStack_start = ALIGN(0x10); + . += 0x4000; + intrStack = .; + PROVIDE(intrStackPtr = intrStack); + + + clear_end = .; + + WorkAreaBase = .; + + /* Sections for compressed .text and .data */ + /* after the .datarom section is an int specifying */ + /* the length of the following compressed image */ + /* Executes once then could get overwritten */ + .textrom 0x100000 : + { + *(.textrom) + _endloader = .; + } > ram + + .datarom : + { + _dr_start = .; + *(.datarom) + _dr_end = .; + } > ram + dr_len = _dr_end - _dr_start; + + .dpram : + { + m8260 = .; + _m8260 = .; + . += (128 * 1024); + } > dpram + + + /* the reset vector is at 0xfff00000 which is */ + /* located at offset 0x400000 from the base */ + /* of flash */ + .bootrom 0xFFF00000 : + { + *(.bootrom) + _endboot = .; + } > flash + + + .line 0 : { *(.line) } + .debug 0 : { *(.debug) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_aregion 0 : { *(.debug_aregion) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } +} diff --git a/bsps/powerpc/mvme3100/start/bsp_specs b/bsps/powerpc/mvme3100/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/mvme3100/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/mvme3100/start/bspstart.c b/bsps/powerpc/mvme3100/start/bspstart.c new file mode 100644 index 0000000000..27b483332c --- /dev/null +++ b/bsps/powerpc/mvme3100/start/bspstart.c @@ -0,0 +1,440 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * COPYRIGHT (c) 1989-1998. + * 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. + * + * Modified to support the MCP750. + * Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr + * + * Modified for mvme3100 by T. Straumann + */ + +#include <string.h> +#include <stdlib.h> +#include <inttypes.h> + +#include <rtems.h> +#include <bsp.h> +#include <bsp/bootcard.h> +#include <rtems/bspIo.h> +#include <rtems/counter.h> +#include <rtems/sysinit.h> +#include <libcpu/spr.h> +#include <libcpu/io.h> +#include <libcpu/e500_mmu.h> +#include <bsp/uart.h> +#include <bsp/irq.h> +#include <bsp/pci.h> +#include <bsp/vpd.h> +#include <libcpu/cpuIdent.h> +#include <bsp/vectors.h> +#include <bsp/VME.h> +#include <rtems/powerpc/powerpc.h> + +#define SHOW_MORE_INIT_SETTINGS +#undef DEBUG + +#define NumberOf(arr) (sizeof(arr)/sizeof(arr[0])) + +#ifdef DEBUG +#define STATIC +#else +#define STATIC static +#endif + +extern unsigned long __rtems_end[]; +extern unsigned ppc_exc_lock_std, ppc_exc_gpr3_std; + +/* + * Copy Additional boot param passed by boot loader + */ +#define CMDLINE_BUF_SIZE 2048 + +static char cmdline_buf[CMDLINE_BUF_SIZE] = {0}; +char *BSP_commandline_string = cmdline_buf; + +/* + * Vital Board data Start using DATA RESIDUAL + */ +uint32_t bsp_clicks_per_usec = 0; +/* + * Total memory using RESIDUAL DATA + */ +unsigned int BSP_mem_size = 0; +/* + * PCI Bus Frequency + */ +unsigned int BSP_pci_bus_frequency = 0xdeadbeef; +/* + * PPC Bus Frequency + */ +unsigned int BSP_bus_frequency = 0; +/* + * processor clock frequency + */ +unsigned int BSP_processor_frequency = 0; +/* + * Time base divisior (how many tick for 1 second). + */ +unsigned int BSP_time_base_divisor = 8000; /* if external RTC clock unused (HID0) */ + +/* Board identification string */ +char BSP_productIdent[20] = {0}; +char BSP_serialNumber[20] = {0}; + +/* VPD appends an extra char -- what for ? */ +char BSP_enetAddr0[7] = {0}; +char BSP_enetAddr1[7] = {0}; +char BSP_enetAddr2[7] = {0}; + +static void +prether(char *b, int idx) +{ +int i; + printk("Ethernet %i %02X", idx, *b++); + for ( i=0; i<5; i++ ) + printk(":%02X",*b++); + printk("\n"); +} + +BSP_output_char_function_type BSP_output_char = BSP_output_char_via_serial; +BSP_polling_getchar_function_type BSP_poll_char = NULL; + +char *rtems_progname; + +/* + * Use the shared implementations of the following routines + */ +char *save_boot_params( + void *r3, + void *r4, + void *r5, + char *cmdline_start, + char *cmdline_end +) +{ + + strncpy(cmdline_buf, cmdline_start, CMDLINE_BUF_SIZE); + cmdline_buf[CMDLINE_BUF_SIZE - 1] ='\0'; + return cmdline_buf; +} + +#define CS_CONFIG_CS_EN (1<<31) +#define CS_BNDS_SA(x) ((((uint32_t)(x))>>(31-15)) & 0xff) +#define CS_BNDS_EA(x) ((((uint32_t)(x))>>(31-31)) & 0xff) + +static inline uint32_t +_ccsr_rd32(uint32_t off) +{ + return in_be32( (volatile uint32_t *)(BSP_8540_CCSR_BASE + off) ); +} + +static inline void +_ccsr_wr32(uint32_t off, uint32_t val) +{ + out_be32( (volatile uint32_t *)(BSP_8540_CCSR_BASE + off), val ); +} + + +STATIC uint32_t +BSP_get_mem_size( void ) +{ + int i; + uint32_t cs_bnds, cs_config; + uint32_t memsz=0; + uint32_t v; + + for ( cs_bnds = 0x2000, cs_config=0x2080, i=0; i<4; i++, cs_bnds+=8, cs_config+=4 ) { + if ( CS_CONFIG_CS_EN & _ccsr_rd32( cs_config ) ) { + v = _ccsr_rd32( cs_bnds ); + + memsz += CS_BNDS_EA(v) - CS_BNDS_SA(v) + 1; + } + } + return memsz << 24; +} + +STATIC void +BSP_calc_freqs( void ) +{ + uint32_t porpllsr = _ccsr_rd32( 0xe0000 ); + unsigned plat_ratio = (porpllsr >> (31-30)) & 0x1f; + unsigned e500_ratio = (porpllsr >> (31-15)) & 0x3f; + + switch ( plat_ratio ) { + case 2: case 3: case 4: case 5: case 6: + case 8: case 9: case 10: case 12: case 16: + /* supported ratios */ + BSP_bus_frequency = BSP_pci_bus_frequency * plat_ratio; + break; + + default: + rtems_panic("Unknown PLL sys-clock ratio; something's wrong here"); + } + + switch ( e500_ratio ) { + case 4: case 5: case 6: case 7: + BSP_processor_frequency = (BSP_pci_bus_frequency * e500_ratio) >> 1; + break; + + default: + rtems_panic("Unknown PLL e500-clock ratio; something's wrong here"); + } + + printk("Core Complex Bus (CCB) Clock Freq: %10u Hz\n", BSP_bus_frequency); + printk("CPU Clock Freq: %10u Hz\n", BSP_processor_frequency); +} + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ + +#include <libcpu/spr.h> + +SPR_RW(HID1) + +void bsp_start( void ) +{ + unsigned char *stack; + uintptr_t intrStackStart; + uintptr_t intrStackSize; + char *chpt; + int i; + ppc_cpu_id_t myCpu; + ppc_cpu_revision_t myCpuRevision; + E500_tlb_va_cache_t *tlb; + +VpdBufRec vpdData [] = { + { key: ProductIdent, instance: 0, buf: BSP_productIdent, buflen: sizeof(BSP_productIdent) - 1 }, + { key: SerialNumber, instance: 0, buf: BSP_serialNumber, buflen: sizeof(BSP_serialNumber) - 1 }, + { key: BusClockHz, instance: 0, buf: &BSP_pci_bus_frequency, buflen: sizeof(BSP_pci_bus_frequency) }, + { key: EthernetAddr, instance: 0, buf: BSP_enetAddr0, buflen: sizeof(BSP_enetAddr0) }, + { key: EthernetAddr, instance: 1, buf: BSP_enetAddr1, buflen: sizeof(BSP_enetAddr1) }, + { key: EthernetAddr, instance: 2, buf: BSP_enetAddr2, buflen: sizeof(BSP_enetAddr2) }, + VPD_END +}; + + /* Intersperse messages with actions to help locate problems */ + printk("-----------------------------------------\n"); + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function store the result in global variables so that it can be used + * later... + */ + myCpu = get_ppc_cpu_type(); + myCpuRevision = get_ppc_cpu_revision(); + + printk("Welcome to %s\n", _RTEMS_version); + printk("BSP: %s, CVS Release ($Name$)\n", "mvme3100"); + + /* + * the initial stack has aready been set to this value in start.S + * so there is no need to set it in r1 again... It is just for info + * so that It can be printed without accessing R1. + */ + asm volatile("mr %0, 1":"=r"(stack)); + + /* tag the bottom */ + *((uint32_t*)stack) = 0; + + /* + * Initialize the interrupt related settings. + */ + intrStackStart = (uintptr_t) __rtems_end; + intrStackSize = rtems_configuration_get_interrupt_stack_size(); + + /* + * Initialize default raw exception handlers. + */ + ppc_exc_initialize(intrStackStart, intrStackSize); + + printk("CPU 0x%x - rev 0x%x\n", myCpu, myCpuRevision); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Additionnal boot options are %s\n", BSP_commandline_string); + printk("Initial system stack at %" PRIxPTR "\n", (uintptr_t) stack); + printk("Software IRQ stack starts at %x with size %u\n", intrStackStart, intrStackSize); +#endif + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Going to start PCI buses scanning and initialization\n"); +#endif + + BSP_mem_size = BSP_get_mem_size(); + + { + /* memory-select errors were disabled in 'start.S'; + * motload has all TLBs mapping a possible larger area as + * memory (not-guarded, caching-enabled) than actual physical + * memory is available. + * In case of speculative loads this may cause 'memory-select' errors + * which seem to raise 'core_fault_in' (found no description in + * the manual but I experienced this problem). + * Such errors (if HID1[RFXE] is clear) may *stall* execution + * leading to mysterious 'hangs'. + * + * Here we remove all mappings, re-enable memory-select + * errors and make sure we enable HID1[RFXE] to avoid + * stalls (since we don't implement handling individual + * error-handling interrupts). + */ + + /* enable machine check for bad bus errors */ + _write_HID1( _read_HID1() | 0x20000 ); + + rtems_e500_initlb(); + + for ( i=0, tlb=rtems_e500_tlb_va_cache; i<NumberOf(rtems_e500_tlb_va_cache); i++, tlb++ ) { + /* disable TLBs for caching-enabled, non-guarded areas + * beyond physical memory + */ + if ( tlb->att.v + && 0xa != (tlb->att.wimge & 0xa) + && (tlb->va.va_epn<<12) >= BSP_mem_size ) { + rtems_e500_clrtlb( E500_SELTLB_1 | i ); + } + } + + /* clear all pending memory errors */ + _ccsr_wr32(0x2e40, 0xffffffff); + /* enable checking for memory-select errors */ + _ccsr_wr32(0x2e44, _ccsr_rd32(0x2e44) & ~1 ); + } + + BSP_vpdRetrieveFields( vpdData ); + + printk("Board Type: %s (S/N %s)\n", + BSP_productIdent[0] ? BSP_productIdent : "n/a", + BSP_serialNumber[0] ? BSP_serialNumber : "n/a"); + + printk("External (=PCI Bus) Clock Freq "); + if ( 0xdeadbeef == BSP_pci_bus_frequency ) { + BSP_pci_bus_frequency = 66666666; + printk(" NOT FOUND in VPD; using %10u Hz\n", + BSP_pci_bus_frequency); + } else { + printk(": %10u Hz\n", + BSP_pci_bus_frequency); + } + + /* Calculate CPU and CCB bus freqs */ + BSP_calc_freqs(); + + pci_initialize(); + + prether(BSP_enetAddr0, 0); + prether(BSP_enetAddr1, 1); + prether(BSP_enetAddr2, 2); + + /* need to tweak the motload setup */ + BSP_motload_pci_fixup(); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Number of PCI buses found is : %d\n", pci_bus_count()); + { + BSP_pciConfigDump_early(); + } +#endif + + if ( (chpt = strstr(BSP_commandline_string,"MEMSZ=")) ) { + char *endp; + uint32_t sz; + chpt+=6 /* strlen("MEMSZ=") */; + sz = strtoul(chpt, &endp, 0); + if ( endp != chpt ) + BSP_mem_size = sz; + } + + printk("Memory: %10u bytes\n", BSP_mem_size); + + BSP_bus_frequency = 333333333; + BSP_processor_frequency = 833333333; + BSP_time_base_divisor = 8000; /* if external RTC clock unused (HID0) */ + + /* clear hostbridge errors but leave MCP disabled - + * PCI config space scanning code will trip otherwise :-( + */ + _BSP_clear_hostbridge_errors(0 /* enableMCP */, 0/*quiet*/); + + bsp_clicks_per_usec = BSP_bus_frequency/(BSP_time_base_divisor * 1000); + rtems_counter_initialize_converter( + BSP_bus_frequency / (BSP_time_base_divisor / 1000) + ); + + /* + * Initalize RTEMS IRQ system + */ + BSP_rtems_irq_mng_init(0); + + if (1) { + int i; + unsigned msr,tcr; + asm volatile("mfmsr %0":"=r"(msr)); + asm volatile("mftcr %0":"=r"(tcr)); + printk("MSR is 0x%08x, TCR 0x%08x\n",msr,tcr); + asm volatile("mttcr %0"::"r"(0)); + if (0) { + asm volatile("mtmsr %0"::"r"(msr|0x8000)); + for (i=0; i<12; i++) + BSP_enable_irq_at_pic(i); + printk("IRQS enabled\n"); + } + } + + if (0) { + unsigned x; + asm volatile("mfivpr %0":"=r"(x)); + printk("IVPR: 0x%08x\n",x); + asm volatile("mfivor8 %0":"=r"(x)); + printk("IVOR8: 0x%08x\n",x); + printk("0x%08x\n",*(unsigned *)0xc00); + printk("0x%08x\n",*(unsigned *)0xc04); + printk("0x%08x\n",*(unsigned *)0xc08); + printk("0x%08x\n\n\n",*(unsigned *)0xc0c); + if (0) { + *(unsigned *)0xc08 = 0x4c000064; + asm volatile("dcbf 0, %0; icbi 0, %0; sync; isync"::"r"(0xc00)); + } + + printk("0x%08x\n", ppc_exc_lock_std); + printk("0x%08x\n", ppc_exc_gpr3_std); + + asm volatile("sc"); + + printk("0x%08x\n", ppc_exc_lock_std); + printk("0x%08x\n", ppc_exc_gpr3_std); + } + + printk("-----------------------------------------\n"); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Exit from bspstart\n"); +#endif +} + +static void mvme3100_i2c_initialize(void) +{ + BSP_i2c_initialize(); +} + +RTEMS_SYSINIT_ITEM( + mvme3100_i2c_initialize, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); + +RTEMS_SYSINIT_ITEM( + BSP_vme_config, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); diff --git a/bsps/powerpc/mvme3100/start/linkcmds b/bsps/powerpc/mvme3100/start/linkcmds new file mode 100644 index 0000000000..b30fb91277 --- /dev/null +++ b/bsps/powerpc/mvme3100/start/linkcmds @@ -0,0 +1,5 @@ +STARTUP(motld_start.o) +ENTRY(__rtems_entry_point) +EXTERN(__vectors) + +INCLUDE linkcmds.share diff --git a/bsps/powerpc/mvme3100/start/misc.c b/bsps/powerpc/mvme3100/start/misc.c new file mode 100644 index 0000000000..3a15397480 --- /dev/null +++ b/bsps/powerpc/mvme3100/start/misc.c @@ -0,0 +1,131 @@ +/* Miscellaneous small BSP routines; reboot, board CSR, ... */ + +/* + * Authorship + * ---------- + * This software ('mvme3100' RTEMS BSP) was created by + * + * Till Straumann <strauman@slac.stanford.edu>, 2005-2007, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * The 'mvme3100' BSP was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +void +bsp_reset(void) +{ +uint8_t v; + /* + * AFAIK, the hardest reset available; cleared + * some errors a VME-bus reset wouldn't (hung + * i2c bus)... + */ + v = in_8( BSP_MVME3100_SYS_CR ); + v &= ~BSP_MVME3100_SYS_CR_RESET_MSK; + v |= BSP_MVME3100_SYS_CR_RESET; + out_8( BSP_MVME3100_SYS_CR, v ); +} + +uint8_t +BSP_setSysReg(volatile uint8_t *r, uint8_t mask) +{ +uint8_t v; +rtems_interrupt_level l; + + if ( !mask ) + return in_8( r ); + + rtems_interrupt_disable(l); + v = in_8( r ); + if ( mask ) { + out_8( r, v | mask ); + } + rtems_interrupt_enable(l); + return v; +} + +uint8_t +BSP_clrSysReg(volatile uint8_t *r, uint8_t mask) +{ +uint8_t v; +rtems_interrupt_level l; + + if ( !mask ) + return in_8( r ); + + rtems_interrupt_disable(l); + v = in_8( r ); + if ( mask ) { + out_8( r, v & ~mask ); + } + rtems_interrupt_enable(l); + return v; +} + +uint8_t +BSP_setLEDs(uint8_t mask) +{ + return BSP_setSysReg( BSP_MVME3100_SYS_IND_REG, mask ); +} + +uint8_t +BSP_clrLEDs(uint8_t mask) +{ + return BSP_clrSysReg( BSP_MVME3100_SYS_IND_REG, mask ); +} + +uint8_t +BSP_eeprom_write_protect(void) +{ +uint8_t m = BSP_MVME3100_SYS_CR_EEPROM_WP; +volatile uint8_t *r = BSP_MVME3100_SYS_CR; + + return m & BSP_setSysReg( r, m ); +} + +uint8_t +BSP_eeprom_write_enable(void) +{ +uint8_t m = BSP_MVME3100_SYS_CR_EEPROM_WP; +volatile uint8_t *r = BSP_MVME3100_SYS_CR; + + return m & BSP_clrSysReg( r, m ); +} diff --git a/bsps/powerpc/mvme5500/start/bootpstuff.c b/bsps/powerpc/mvme5500/start/bootpstuff.c new file mode 100644 index 0000000000..518a43cdc8 --- /dev/null +++ b/bsps/powerpc/mvme5500/start/bootpstuff.c @@ -0,0 +1,70 @@ +#define FLAG_MAND 1 +#define FLAG_NOUSE 2 /* dont put into the commandline at all */ +#define FLAG_CLRBP 4 /* field needs to be cleared for bootp */ + +typedef struct ParmRec_ { + char *name; + char **pval; + int flags; +} ParmRec, *Parm; + + +static char *boot_filename=0; +static char *boot_srvname=0; +static char *boot_use_bootp=0; +static char *boot_my_ip=0; +static char *boot_my_netmask=0; + +#define boot_cmdline BSP_commandline_string + +static ParmRec parmList[]={ + { "BP_FILE=", &boot_filename, + FLAG_MAND, + }, + { "BP_PARM=", &boot_cmdline, + 0, + }, + { "BP_SRVR=", &boot_srvname, + FLAG_MAND, + }, + { "BP_GTWY=", &net_config.gateway, + FLAG_CLRBP, + }, + { "BP_MYIP=", &boot_my_ip, + FLAG_MAND | FLAG_CLRBP, + }, + { "BP_MYMK=", &boot_my_netmask, + FLAG_MAND | FLAG_CLRBP, + }, + { "BP_MYNM=", &net_config.hostname, + FLAG_CLRBP, + }, + { "BP_MYDN=", &net_config.domainname, + FLAG_CLRBP, + }, + { "BP_LOGH=", &net_config.log_host, + FLAG_CLRBP, + }, + { "BP_DNS1=", &net_config.name_server[0], + FLAG_CLRBP, + }, + { "BP_DNS2=", &net_config.name_server[1], + FLAG_CLRBP, + }, + { "BP_DNS3=", &net_config.name_server[2], + FLAG_CLRBP, + }, + { "BP_NTP1=", &net_config.ntp_server[0], + FLAG_CLRBP, + }, + { "BP_NTP2=", &net_config.ntp_server[1], + FLAG_CLRBP, + }, + { "BP_NTP3=", &net_config.ntp_server[2], + FLAG_CLRBP, + }, + { "BP_ENBL=", &boot_use_bootp, + 0, + }, + { 0, } +}; diff --git a/bsps/powerpc/mvme5500/start/bsp_specs b/bsps/powerpc/mvme5500/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/mvme5500/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/mvme5500/start/bspclean.c b/bsps/powerpc/mvme5500/start/bspclean.c new file mode 100644 index 0000000000..bd332cc89c --- /dev/null +++ b/bsps/powerpc/mvme5500/start/bspclean.c @@ -0,0 +1,26 @@ +/* Copyright 2003, Shuchen Kate Feng <feng1@bnl.gov>, + * NSLS,Brookhaven National Laboratory + */ +#include <bsp.h> +#include <bsp/bootcard.h> +#include <rtems/bspIo.h> +#include <libcpu/stackTrace.h> + +#define AUTO_BOOT 0 + +void bsp_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code error +) +{ +#if AUTO_BOOT + /* Till Straumann <strauman@slac.stanford.edu> for SVGM */ + bsp_reset(); +#else + /* Kate Feng <feng1@bnl.gov> for the MVME5500 */ + printk("\nPrinting a stack trace for your convenience :-)\n"); + CPU_print_stack(); + printk("RTEMS terminated; Boot manually or turn on AUTO_BOOT.\n"); +#endif +} diff --git a/bsps/powerpc/mvme5500/start/bspreset.c b/bsps/powerpc/mvme5500/start/bspreset.c new file mode 100644 index 0000000000..de15bc4972 --- /dev/null +++ b/bsps/powerpc/mvme5500/start/bspreset.c @@ -0,0 +1,22 @@ +/* Copyright 2003, Shuchen Kate Feng <feng1@bnl.gov>, + * NSLS,Brookhaven National Laboratory + * + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <rtems/bspIo.h> +#include <libcpu/io.h> +#include <libcpu/stackTrace.h> +#include <stdint.h> + +void bsp_reset() +{ + + printk("Printing a stack trace for your convenience :-)\n"); + CPU_print_stack(); + + printk("RTEMS terminated; Rebooting ...\n"); + /* Mvme5500 board reset : 2004 S. Kate Feng <feng1@bnl.gov> */ + out_8((volatile uint8_t*) (GT64x60_DEV1_BASE +2), 0x80); +} diff --git a/bsps/powerpc/mvme5500/start/bspstart.c b/bsps/powerpc/mvme5500/start/bspstart.c new file mode 100644 index 0000000000..279524eb8f --- /dev/null +++ b/bsps/powerpc/mvme5500/start/bspstart.c @@ -0,0 +1,351 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * COPYRIGHT (c) 1989-2007. + * 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. + * + * Modified to support the MCP750. + * Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr + * + * Modified to support the Synergy VGM & Motorola PowerPC boards + * (C) by Till Straumann, <strauman@slac.stanford.edu>, 2002, 2004, 2005 + * + * Modified to support the MVME5500 board. + * Also, the settings of L1, L2, and L3 caches is not necessary here. + * (C) by Brookhaven National Lab., S. Kate Feng <feng1@bnl.gov>, 2003-2009 + */ + +#include <string.h> +#include <stdlib.h> +#include <ctype.h> + +#include <rtems/sysinit.h> +#include <rtems/system.h> +#include <rtems/powerpc/powerpc.h> + +#include <libcpu/spr.h> /* registers.h is included here */ +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/uart.h> +#include <bsp/pci.h> +#include <libcpu/bat.h> +#include <libcpu/pte121.h> +#include <libcpu/cpuIdent.h> +#include <bsp/vectors.h> +#include <bsp/VME.h> +#include <bsp/bspException.h> + +#include <rtems/bspIo.h> +#include <rtems/counter.h> + +/* +#define SHOW_MORE_INIT_SETTINGS +#define SHOW_LCR1_REGISTER +#define SHOW_LCR2_REGISTER +#define SHOW_LCR3_REGISTER +#define CONF_VPD +*/ + +extern uint32_t probeMemoryEnd(void); /* from shared/startup/probeMemoryEnd.c */ + +BSP_output_char_function_type BSP_output_char = BSP_output_char_via_serial; +BSP_polling_getchar_function_type BSP_poll_char = NULL; + +extern void _return_to_ppcbug(void); +extern unsigned long __rtems_end[]; +extern unsigned get_L1CR(void), get_L2CR(void), get_L3CR(void); +extern Triv121PgTbl BSP_pgtbl_setup(unsigned int *); +extern void BSP_pgtbl_activate(Triv121PgTbl); +extern int I2Cread_eeprom(unsigned char I2cBusAddr, uint32_t devA2A1A0, uint32_t AddrBytes, unsigned char *pBuff, uint32_t numBytes); +extern void BSP_vme_config(void); + +extern unsigned char ReadConfVPD_buff(int offset); + +uint32_t bsp_clicks_per_usec; + +typedef struct CmdLineRec_ { + unsigned long size; + char buf[0]; +} CmdLineRec, *CmdLine; + + +#define mtspr(reg, val) \ + __asm __volatile("mtspr %0,%1" : : "K"(reg), "r"(val)) + + +#define mfspr(reg) \ + ( { unsigned val; \ + __asm __volatile("mfspr %0,%1" : "=r"(val) : "K"(reg)); \ + val; } ) + +/* + * Copy Additional boot param passed by boot loader + */ +#define MAX_LOADER_ADD_PARM 80 +char loaderParam[MAX_LOADER_ADD_PARM]; + +/* + * Total memory using RESIDUAL DATA + */ +unsigned int BSP_mem_size; +/* + * PCI Bus Frequency + */ +unsigned int BSP_bus_frequency; +/* + * processor clock frequency + */ +unsigned int BSP_processor_frequency; +/* + * Time base divisior (how many tick for 1 second). + */ +unsigned int BSP_time_base_divisor; +static unsigned char ConfVPD_buff[200]; + +#define CMDLINE_BUF_SIZE 2048 + +static char cmdline_buf[CMDLINE_BUF_SIZE]; +char *BSP_commandline_string = cmdline_buf; + +/* NOTE: we cannot simply malloc the commandline string; + * save_boot_params() is called during a very early stage when + * libc/malloc etc. are not yet initialized! + * + * Here's what we do: + * + * initial layout setup by the loader (preload.S): + * + * 0..RTEMS...__rtems_end | cmdline ....... TOP + * + * After the save_boot_params() routine returns, the stack area will be + * set up (start.S): + * + * 0..RTEMS..__rtems_end | INIT_STACK | IRQ_STACK | ..... TOP + * + * initialize_executive_early() [called from boot_card()] + * will initialize the workspace: + * + * 0..RTEMS..__rtems_end | INIT_STACK | IRQ_STACK | ...... | workspace | TOP + * + * and later calls our bsp_predriver_hook() which ends up initializing + * libc which in turn initializes the heap + * + * 0..RTEMS..__rtems_end | INIT_STACK | IRQ_STACK | heap | workspace | TOP + * + * The idea here is to first move the commandline to the future 'heap' area + * from where it will be picked up by our bsp_predriver_hook(). + * bsp_predriver_hook() then moves it either to INIT_STACK or the workspace + * area using proper allocation, initializes libc and finally moves + * the data to the environment / malloced areas... + */ + +/* this routine is called early at shared/start/start.S + * and must be safe with a not properly aligned stack + */ +char * +save_boot_params( + void *r3, + void *r4, + void* r5, + char *cmdline_start, + char *cmdline_end +) +{ + int i=cmdline_end-cmdline_start; + + if ( i >= CMDLINE_BUF_SIZE ) + i = CMDLINE_BUF_SIZE-1; + else if ( i < 0 ) + i = 0; + + memmove(cmdline_buf, cmdline_start, i); + cmdline_buf[i]=0; + return cmdline_buf; +} + +void bsp_start( void ) +{ +#ifdef CONF_VPD + int i; +#endif +#ifdef SHOW_LCR1_REGISTER + unsigned l1cr; +#endif +#ifdef SHOW_LCR2_REGISTER + unsigned l2cr; +#endif +#ifdef SHOW_LCR3_REGISTER + unsigned l3cr; +#endif + uintptr_t intrStackStart; + uintptr_t intrStackSize; + Triv121PgTbl pt=0; + + /* Till Straumann: 4/2005 + * Need to map the system registers early, so we can printk... + * (otherwise we silently die) + */ + /* + * Kate Feng : PCI 0 domain memory space, want to leave room for the VME window + */ + setdbat(2, PCI0_MEM_BASE, PCI0_MEM_BASE, 0x10000000, IO_PAGE); + + /* Till Straumann: 2004 + * map the PCI 0, 1 Domain I/O space, GT64260B registers + * and the reserved area so that the size is the power of 2. + * 2009 : map the entire 256 M space + * + */ + setdbat(3,PCI0_IO_BASE, PCI0_IO_BASE, 0x10000000, IO_PAGE); + + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function store the result in global variables so that it can be used later. + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + +#ifdef SHOW_LCR1_REGISTER + l1cr = get_L1CR(); + printk("Initial L1CR value = %x\n", l1cr); +#endif + + /* + * Initialize the interrupt related settings. + */ + intrStackStart = (uintptr_t) __rtems_end; + intrStackSize = rtems_configuration_get_interrupt_stack_size(); + + /* + * Initialize default raw exception handlers. + */ + ppc_exc_initialize(intrStackStart, intrStackSize); + + /* + * Init MMU block address translation to enable hardware + * access + * More PCI1 memory mapping to be done after BSP_pgtbl_activate. + */ + printk("-----------------------------------------\n"); + printk("Welcome to %s on MVME5500-0163\n", _RTEMS_version ); + printk("-----------------------------------------\n"); + + BSP_mem_size = probeMemoryEnd(); + + /* TODO: calculate the BSP_bus_frequency using the REF_CLK bit + * of System Status register + */ + /* rtems_bsp_delay_in_bus_cycles are defined in registers.h */ + BSP_bus_frequency = 133333333; + BSP_processor_frequency = 1000000000; + /* P94 : 7455 clocks the TB/DECR at 1/4 of the system bus clock frequency */ + BSP_time_base_divisor = 4000; + + /* Maybe not setup yet becuase of the warning message */ + /* Allocate and set up the page table mappings + * This is only available on >604 CPUs. + * + * NOTE: This setup routine may modify the available memory + * size. It is essential to call it before + * calculating the workspace etc. + */ + pt = BSP_pgtbl_setup(&BSP_mem_size); + if (!pt) + printk("WARNING: unable to setup page tables.\n"); + + printk("Now BSP_mem_size = 0x%x\n",BSP_mem_size); + + /* P94 : 7455 TB/DECR is clocked by the system bus clock frequency */ + + bsp_clicks_per_usec = BSP_bus_frequency/(BSP_time_base_divisor * 1000); + rtems_counter_initialize_converter( + BSP_bus_frequency / (BSP_time_base_divisor / 1000) + ); + + /* + * Initalize RTEMS IRQ system + */ + BSP_rtems_irq_mng_init(0); + +#ifdef SHOW_LCR2_REGISTER + l2cr = get_L2CR(); + printk("Initial L2CR value = %x\n", l2cr); +#endif + +#ifdef SHOW_LCR3_REGISTER + /* L3CR needs DEC int. handler installed for bsp_delay()*/ + l3cr = get_L3CR(); + printk("Initial L3CR value = %x\n", l3cr); +#endif + + + /* Activate the page table mappings only after + * initializing interrupts because the irq_mng_init() + * routine needs to modify the text + */ + if (pt) { +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Page table setup finished; will activate it NOW...\n"); +#endif + BSP_pgtbl_activate(pt); + } + /* Read Configuration Vital Product Data (VPD) */ + if ( I2Cread_eeprom(0xa8, 4,2, &ConfVPD_buff[0], 150)) + printk("I2Cread_eeprom() error \n"); + else { +#ifdef CONF_VPD + printk("\n"); + for (i=0; i<150; i++) { + printk("%2x ", ConfVPD_buff[i]); + if ((i % 20)==0 ) printk("\n"); + } + printk("\n"); +#endif + } + + /* + * PCI 1 domain memory space + */ + setdbat(1, PCI1_MEM_BASE, PCI1_MEM_BASE, 0x10000000, IO_PAGE); + + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Going to start PCI buses scanning and initialization\n"); +#endif + pci_initialize(); +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Number of PCI buses found is : %d\n", pci_bus_count()); +#endif + + /* Install our own exception handler (needs PCI) */ + globalExceptHdl = BSP_exceptionHandler; + + /* clear hostbridge errors. MCP signal is not used on the MVME5500 + * PCI config space scanning code will trip otherwise :-( + */ + _BSP_clear_hostbridge_errors(0, 1 /*quiet*/); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("MSR %x \n", _read_MSR()); + printk("Exit from bspstart\n"); +#endif + +} + +unsigned char ReadConfVPD_buff(int offset) +{ + return(ConfVPD_buff[offset]); +} + +RTEMS_SYSINIT_ITEM( + BSP_vme_config, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); diff --git a/bsps/powerpc/mvme5500/start/linkcmds b/bsps/powerpc/mvme5500/start/linkcmds new file mode 100644 index 0000000000..384b623474 --- /dev/null +++ b/bsps/powerpc/mvme5500/start/linkcmds @@ -0,0 +1,5 @@ +STARTUP(mvme5500start.o) +ENTRY(__rtems_entry_point) +EXTERN(__vectors) + +INCLUDE linkcmds.share diff --git a/bsps/powerpc/mvme5500/start/pgtbl_activate.c b/bsps/powerpc/mvme5500/start/pgtbl_activate.c new file mode 100644 index 0000000000..79725c6a06 --- /dev/null +++ b/bsps/powerpc/mvme5500/start/pgtbl_activate.c @@ -0,0 +1,37 @@ +/* + * Default activation of the page tables. This is a weak + * alias, so applications may easily override this + * default activation procedure. + */ + +/* Author: Till Straumann, <strauman@slac.stanford.edu>, 4/2002 + * Kate Feng <feng1@bnl.gov> ported it to MVME5500, 4/2004 + */ + +#include <rtems.h> +#include <libcpu/pte121.h> +#include <libcpu/bat.h> + +static void +__BSP_default_pgtbl_activate(Triv121PgTbl pt) +{ + if (!pt) + return; + + /* switch the text/ro sements to RO only after + * initializing the interrupts because the irq_mng + * installs some code... + * + * activate the page table; it is still masked by the + * DBAT0, however + */ + triv121PgTblActivate(pt); + + /* finally, switch off DBAT0 & DBAT1 */ + setdbat(0,0,0,0,0); + setdbat(1,0,0,0,0); /* <skf> */ + /* At this point, DBAT0 is available for other use... */ +} + +void BSP_pgtbl_activate(Triv121PgTbl) + __attribute__ (( weak, alias("__BSP_default_pgtbl_activate") )); diff --git a/bsps/powerpc/psim/start/bsp_specs b/bsps/powerpc/psim/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/psim/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/psim/start/bspstart.c b/bsps/powerpc/psim/start/bspstart.c new file mode 100644 index 0000000000..3a9809c022 --- /dev/null +++ b/bsps/powerpc/psim/start/bspstart.c @@ -0,0 +1,113 @@ +/* + * This set of routines starts the application. It includes application, + * board, and monitor specific initialization and configuration. + * The generic CPU dependent initialization has been performed + * before any of these are invoked. + * + * COPYRIGHT (c) 1989-2008. + * 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 <string.h> +#include <fcntl.h> +#include <bsp.h> +#include <bsp/irq.h> +#include <psim.h> +#include <bsp/bootcard.h> +#include <bsp/linker-symbols.h> +#include <rtems/bspIo.h> +#include <rtems/counter.h> +#include <rtems/powerpc/powerpc.h> + +#include <libcpu/cpuIdent.h> +#include <libcpu/bat.h> +#include <libcpu/spr.h> + +SPR_RW(SPRG1) + +/* On psim, each click of the decrementer register corresponds + * to 1 instruction. By setting this to 100, we are indicating + * that we are assuming it can execute 100 instructions per + * microsecond. This corresponds to sustaining 1 instruction + * per cycle at 100 Mhz. Whether this is a good guess or not + * is anyone's guess. + */ +extern int PSIM_INSTRUCTIONS_PER_MICROSECOND[]; + +/* + * PCI Bus Frequency + */ +unsigned int BSP_bus_frequency; + +/* + * Driver configuration parameters + */ +uint32_t bsp_clicks_per_usec; + +/* + * Memory on this board. + */ +uint32_t BSP_mem_size = (uint32_t)RamSize; + +/* + * Time base divisior (how many tick for 1 second). + */ +unsigned int BSP_time_base_divisor; + +extern unsigned long __rtems_end[]; + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ +void bsp_start( void ) +{ + /* + * Note we can not get CPU identification dynamically. + * PVR has to be set to PPC_PSIM (0xfffe) from the device + * file. + */ + + get_ppc_cpu_type(); + + /* + * initialize the device driver parameters + */ + BSP_bus_frequency = (unsigned int)PSIM_INSTRUCTIONS_PER_MICROSECOND; + bsp_clicks_per_usec = BSP_bus_frequency; + BSP_time_base_divisor = 1; + rtems_counter_initialize_converter(bsp_clicks_per_usec * 1000000); + + /* + * Initialize default raw exception handlers. + */ + ppc_exc_initialize_with_vector_base( + (uintptr_t) bsp_section_work_begin, + rtems_configuration_get_interrupt_stack_size(), + (void *) 0xfff00000 + ); + + /* + * Initalize RTEMS IRQ system + */ + BSP_rtems_irq_mng_init(0); + + /* + * Setup BATs and enable MMU + */ + /* Memory */ + setdbat(0, 0x0<<24, 0x0<<24, 2<<24, _PAGE_RW); + setibat(0, 0x0<<24, 0x0<<24, 2<<24, 0); + /* PCI */ + setdbat(1, 0x8<<24, 0x8<<24, 1<<24, IO_PAGE); + setdbat(2, 0xc<<24, 0xc<<24, 1<<24, IO_PAGE); + + _write_MSR(_read_MSR() | MSR_DR | MSR_IR); + __asm__ volatile("sync; isync"); + +} diff --git a/bsps/powerpc/psim/start/device-tree b/bsps/powerpc/psim/start/device-tree new file mode 100644 index 0000000000..bd2a2a56ef --- /dev/null +++ b/bsps/powerpc/psim/start/device-tree @@ -0,0 +1,4 @@ +#/openprom/init/register/pc 0 +#/openprom/options/smp 2 +#/openprom/options/oea-memory-size 4194304 +/openprom/options/oea-memory-size 8388608 diff --git a/bsps/powerpc/psim/start/linkcmds b/bsps/powerpc/psim/start/linkcmds new file mode 100644 index 0000000000..ba9319c91d --- /dev/null +++ b/bsps/powerpc/psim/start/linkcmds @@ -0,0 +1,40 @@ +/* + * COPYRIGHT (c) 1989-2008. + * 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. + */ + +EXTERN (__vectors) + +MEMORY { + RAM : ORIGIN = 0, LENGTH = 16M + EMPTY : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", 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_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", EMPTY); +REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +PROVIDE (PSIM_INSTRUCTIONS_PER_MICROSECOND = 10000); + +PSIM = 0x0c000000; + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/qemuppc/start/bsp_specs b/bsps/powerpc/qemuppc/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/qemuppc/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/qemuppc/start/bspstart.c b/bsps/powerpc/qemuppc/start/bspstart.c new file mode 100644 index 0000000000..94d7f4b84d --- /dev/null +++ b/bsps/powerpc/qemuppc/start/bspstart.c @@ -0,0 +1,121 @@ +/* + * This set of routines starts the application. It includes application, + * board, and monitor specific initialization and configuration. + * The generic CPU dependent initialization has been performed + * before any of these are invoked. + * + * COPYRIGHT (c) 1989-2008. + * 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 <string.h> +#include <fcntl.h> + +#include <rtems/counter.h> + +#include <libcpu/bat.h> +#include <libcpu/spr.h> +#include <libcpu/powerpc-utility.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/vectors.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> + +/* + * CPU Bus Frequency + */ +unsigned int BSP_bus_frequency; + +/* Configuration parameter for clock driver */ +uint32_t bsp_time_base_frequency; + +/* Legacy */ +uint32_t bsp_clicks_per_usec; + +/* + * Memory on this board. + */ +extern char RamSize[]; +extern char bsp_interrupt_stack_start[]; +extern char bsp_interrupt_stack_end[]; +uint32_t BSP_mem_size = (uint32_t)RamSize; + +/* Default decrementer exception handler */ +static int default_decrementer_exception_handler( BSP_Exception_frame *frame, unsigned number) +{ + ppc_set_decrementer_register(UINT32_MAX); + + return 0; +} + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ + +void bsp_start( void ) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + uintptr_t intrStackStart; + uintptr_t intrStackSize; + + /* + * Note we can not get CPU identification dynamically, so + * force current_ppc_cpu. + */ + current_ppc_cpu = PPC_PSIM; + + /* + * initialize the device driver parameters + * assume we are running with 20MHz bus + * this should speed up some tests :-) + */ + BSP_bus_frequency = 20; + bsp_time_base_frequency = 20000000; + bsp_clicks_per_usec = BSP_bus_frequency; + rtems_counter_initialize_converter(bsp_time_base_frequency); + + /* + * Initialize the interrupt related settings. + */ + intrStackStart = (uintptr_t) bsp_interrupt_stack_start; + intrStackSize = (uintptr_t) bsp_interrupt_stack_end - intrStackStart; + + BSP_mem_size = (uint32_t )RamSize; + + /* + * Initialize default raw exception handlers. + */ + ppc_exc_initialize(intrStackStart, intrStackSize); + + /* Install default handler for the decrementer exception */ + sc = ppc_exc_set_handler( ASM_DEC_VECTOR, default_decrementer_exception_handler); + if (sc != RTEMS_SUCCESSFUL) { + rtems_panic("cannot install decrementer exception handler"); + } + + /* Initalize interrupt support */ + bsp_interrupt_initialize(); + +#if 0 + /* + * Setup BATs and enable MMU + */ + /* Memory */ + setdbat(0, 0x0<<24, 0x0<<24, 2<<24, _PAGE_RW); + setibat(0, 0x0<<24, 0x0<<24, 2<<24, 0); + /* PCI */ + setdbat(1, 0x8<<24, 0x8<<24, 1<<24, IO_PAGE); + setdbat(2, 0xc<<24, 0xc<<24, 1<<24, IO_PAGE); + + _write_MSR(_read_MSR() | MSR_DR | MSR_IR); + __asm__ volatile("sync; isync"); +#endif +} diff --git a/bsps/powerpc/qemuppc/start/cmain.c b/bsps/powerpc/qemuppc/start/cmain.c new file mode 100644 index 0000000000..bf46d03177 --- /dev/null +++ b/bsps/powerpc/qemuppc/start/cmain.c @@ -0,0 +1,55 @@ +#include <bsp/bootcard.h> +#include <bsp/linker-symbols.h> + +static void +__outb(int port, unsigned char v) +{ + *((volatile unsigned char *)(0x80000000 + port)) = v; +} + +#if 0 +/* currently unused but keep just in case */ + +static unsigned char +__inb(int port) +{ + return *((volatile unsigned char *)(0x80000000 + port)); +} +#endif + +static void +__memcpy (unsigned char *d, unsigned char *s, int len) +{ + while (len--) + *d++ = *s++; +} + +static void +__bzero (unsigned char *d, int len) +{ + while (len--) + *d++ = 0; +} + + +/* + * Prototype this here because it is just the entry symbol and + * not referenced from any compileable code. + */ +void cmain (void); + +void cmain (void) +{ + /* + * init variable sections + */ + __memcpy (bsp_section_data_begin, bsp_section_data_load_begin, (int)bsp_section_data_size); + __bzero (bsp_section_bss_begin, (int)bsp_section_bss_size); + __bzero (bsp_section_sbss_begin, (int)bsp_section_sbss_size); + /* printk( "start of BSP\n"); */ + boot_card(0); + /* printk( "end of BSP\n"); */ + __outb (0x92, 0x01); + while (1) + ; +} diff --git a/bsps/powerpc/qemuppc/start/linkcmds b/bsps/powerpc/qemuppc/start/linkcmds new file mode 100644 index 0000000000..3169ad2741 --- /dev/null +++ b/bsps/powerpc/qemuppc/start/linkcmds @@ -0,0 +1,38 @@ +EXTERN(__vectors) + +MEMORY + { + EMPTY : ORIGIN = 0, LENGTH = 0 + RAM : ORIGIN = 0x2000, LENGTH = 4M - 0x2000 + ROM : ORIGIN = 0xFFC00000, LENGTH = 4M + VECTORS : ORIGIN = 0xFFF00000, LENGTH = 0x20000 + RESET : ORIGIN = 0xFFFFFFFC, LENGTH = 0x4 + } + +REGION_ALIAS ("REGION_START", ROM); +REGION_ALIAS ("REGION_FAST_TEXT", ROM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", EMPTY); +REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +SECTIONS { + .reset : + { + KEEP(*(.reset)) + } >RESET +} + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/qoriq/start/bsp_specs b/bsps/powerpc/qoriq/start/bsp_specs new file mode 100644 index 0000000000..001c45b3c4 --- /dev/null +++ b/bsps/powerpc/qoriq/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s rtems_crtn.o%s ecrtn.o%s} diff --git a/bsps/powerpc/qoriq/start/bspreset.c b/bsps/powerpc/qoriq/start/bspreset.c new file mode 100644 index 0000000000..545aa28ee3 --- /dev/null +++ b/bsps/powerpc/qoriq/start/bspreset.c @@ -0,0 +1,64 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief BSP reset. + */ + +/* + * Copyright (c) 2010, 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/bootcard.h> +#include <bsp/fdt.h> +#include <bsp/qoriq.h> + +#include <libfdt.h> + +static int find_rstcr_node(const void *fdt, int node) +{ + return fdt_node_offset_by_prop_value(fdt, node, "fsl,has-rstcr", NULL, 0); +} + +void bsp_reset(void) +{ + rtems_interrupt_level level; + const char *fdt; + + rtems_interrupt_local_disable(level); + (void) level; + + fdt = bsp_fdt_get(); + + /* If we do not find a RSTCR, then loop forever */ + while (true) { + int node; + + node = -1; + + while ((node = find_rstcr_node(fdt, node)) >= 0) { + const uint32_t *reg; + int len; + + reg = fdt_getprop(fdt, node, "reg", &len); + if (reg != NULL && len >= 4) { + volatile uint32_t *rstcr; + + rstcr = (volatile uint32_t *) + ((uintptr_t) &qoriq + fdt32_to_cpu(reg[0]) + 0xb0); + *rstcr = 0x2; + } + } + } +} diff --git a/bsps/powerpc/qoriq/start/bsprestart.c b/bsps/powerpc/qoriq/start/bsprestart.c new file mode 100644 index 0000000000..36e751e50d --- /dev/null +++ b/bsps/powerpc/qoriq/start/bsprestart.c @@ -0,0 +1,146 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief BSP restart. + */ + +/* + * Copyright (c) 2016, 2018 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/irq.h> +#include <bsp/fatal.h> +#include <bsp/fdt.h> +#include <bsp/linker-symbols.h> +#include <bsp/qoriq.h> + +#include <libcpu/powerpc-utility.h> + +#include <string.h> + +static char fdt_copy[BSP_FDT_BLOB_SIZE_MAX]; + +static RTEMS_NO_RETURN void do_restart(void *addr) +{ + void (*restart)(uintptr_t); + + qoriq_reset_qman_and_bman(); + + memcpy(fdt_copy, bsp_fdt_get(), sizeof(fdt_copy)); + rtems_cache_flush_multiple_data_lines(fdt_copy, sizeof(fdt_copy)); + + restart = addr; + (*restart)((uintptr_t) fdt_copy); + bsp_fatal(QORIQ_FATAL_RESTART_FAILED); +} + +#if defined(RTEMS_SMP) && !defined(QORIQ_IS_HYPERVISOR_GUEST) + +#include <rtems/score/smpimpl.h> +#include <rtems/score/smpbarrier.h> + +#define RESTART_IPI_INDEX 1 + +static SMP_barrier_Control restart_barrier = SMP_BARRIER_CONTROL_INITIALIZER; + +static void restart_interrupt(void *arg) +{ + uint32_t cpu_self_index; + uint32_t thread_index; + rtems_interrupt_level level; + SMP_barrier_State bs; + + rtems_interrupt_local_disable(level); + (void) level; + + _SMP_barrier_State_initialize(&bs); + _SMP_barrier_Wait(&restart_barrier, &bs, _SMP_Processor_count); + + cpu_self_index = rtems_get_current_processor(); + thread_index = cpu_self_index % QORIQ_THREAD_COUNT; + + if (cpu_self_index == 0) { + do_restart(arg); + } else if (thread_index == 0) { + uint32_t real_processor_index; + const qoriq_start_spin_table *spin_table; + + real_processor_index = cpu_self_index / QORIQ_THREAD_COUNT; + spin_table = qoriq_start_spin_table_addr[real_processor_index]; + + qoriq_restart_secondary_processor(spin_table); + } else { + uint32_t pir_reset_value; + + /* Restore reset PIR value */ + pir_reset_value = (cpu_self_index & ~0x1U) << 2; + PPC_SET_SPECIAL_PURPOSE_REGISTER(BOOKE_PIR, pir_reset_value); + + /* Thread Enable Clear (TENC) */ + PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_TENC, 1U << thread_index); + + RTEMS_UNREACHABLE(); + } +} + +static void raise_restart_interrupt(void) +{ + qoriq.pic.ipidr[RESTART_IPI_INDEX].reg = + _Processor_mask_To_uint32_t(_SMP_Get_online_processors(), 0); + ppc_synchronize_data(); + ppc_synchronize_instructions(); +} + +void bsp_restart(void *addr) +{ + rtems_status_code sc; + size_t i; + + for (i = 0; i < RTEMS_ARRAY_SIZE(qoriq_start_spin_table_addr); ++i) { + qoriq_start_spin_table *spin_table; + + spin_table = qoriq_start_spin_table_addr[i]; + memset(spin_table, 0, sizeof(*spin_table)); + rtems_cache_flush_multiple_data_lines(spin_table, sizeof(*spin_table)); + } + + sc = rtems_interrupt_handler_install( + QORIQ_IRQ_IPI_0 + RESTART_IPI_INDEX, + "Restart", + RTEMS_INTERRUPT_UNIQUE, + restart_interrupt, + addr + ); + if (sc != RTEMS_SUCCESSFUL) { + bsp_fatal(QORIQ_FATAL_RESTART_INSTALL_INTERRUPT); + } + + raise_restart_interrupt(); + bsp_fatal(QORIQ_FATAL_RESTART_INTERRUPT_FAILED); +} + +#else /* !RTEMS_SMP || QORIQ_IS_HYPERVISOR_GUEST */ + +void bsp_restart(void *addr) +{ + rtems_interrupt_level level; + + rtems_interrupt_local_disable(level); + (void) level; + do_restart(addr); +} + +#endif /* RTEMS_SMP && !QORIQ_IS_HYPERVISOR_GUEST */ diff --git a/bsps/powerpc/qoriq/start/bspsmp.c b/bsps/powerpc/qoriq/start/bspsmp.c new file mode 100644 index 0000000000..a2d9fbede5 --- /dev/null +++ b/bsps/powerpc/qoriq/start/bspsmp.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2013, 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/score/smpimpl.h> + +#include <libfdt.h> + +#include <libcpu/powerpc-utility.h> + +#include <bsp.h> +#include <bsp/fdt.h> +#include <bsp/mmu.h> +#include <bsp/fatal.h> +#include <bsp/qoriq.h> +#include <bsp/vectors.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> + +LINKER_SYMBOL(bsp_exc_vector_base); + +#if QORIQ_THREAD_COUNT > 1 +void _start_thread(void); +#endif + +void _start_secondary_processor(void); + +#define IPI_INDEX 0 + +#if QORIQ_THREAD_COUNT > 1 +static bool is_started_by_u_boot(uint32_t cpu_index) +{ + return cpu_index % QORIQ_THREAD_COUNT == 0; +} + +void qoriq_start_thread(void) +{ + const Per_CPU_Control *cpu_self = _Per_CPU_Get(); + + ppc_exc_initialize_interrupt_stack( + (uintptr_t) cpu_self->interrupt_stack_low, + rtems_configuration_get_interrupt_stack_size() + ); + + bsp_interrupt_facility_initialize(); + + _SMP_Start_multitasking_on_secondary_processor(); +} +#endif + +static void start_thread_if_necessary(uint32_t cpu_index_self) +{ +#if QORIQ_THREAD_COUNT > 1 + uint32_t i; + + for (i = 1; i < QORIQ_THREAD_COUNT; ++i) { + uint32_t cpu_index_next = cpu_index_self + i; + + if ( + is_started_by_u_boot(cpu_index_self) + && cpu_index_next < rtems_configuration_get_maximum_processors() + && _SMP_Should_start_processor(cpu_index_next) + ) { + /* Thread Initial Next Instruction Address (INIA) */ + PPC_SET_THREAD_MGMT_REGISTER(321, (uintptr_t) _start_thread); + + /* Thread Initial Machine State (IMSR) */ + PPC_SET_THREAD_MGMT_REGISTER(289, QORIQ_INITIAL_MSR); + + /* Thread Enable Set (TENS) */ + PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_TENS, 1U << i); + } + } +#endif +} + +void bsp_start_on_secondary_processor(void) +{ + uint32_t cpu_index_self = _SMP_Get_current_processor(); + const Per_CPU_Control *cpu_self = _Per_CPU_Get_by_index(cpu_index_self); + + qoriq_initialize_exceptions(cpu_self->interrupt_stack_low); + bsp_interrupt_facility_initialize(); + + start_thread_if_necessary(cpu_index_self); + + _SMP_Start_multitasking_on_secondary_processor(); +} + +#ifndef QORIQ_IS_HYPERVISOR_GUEST +static void bsp_inter_processor_interrupt(void *arg) +{ + _SMP_Inter_processor_interrupt_handler(); +} +#endif + +static void setup_boot_page(void) +{ +#ifdef QORIQ_IS_HYPERVISOR_GUEST + qoriq_mmu_context mmu_context; + + qoriq_mmu_context_init(&mmu_context); + qoriq_mmu_add( + &mmu_context, + 0xfffff000, + 0xffffffff, + 0, + 0, + FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, + 0 + ); + qoriq_mmu_partition(&mmu_context, 1); + qoriq_mmu_write_to_tlb1(&mmu_context, QORIQ_TLB1_ENTRY_COUNT - 1); +#endif +} + +static uint32_t discover_processors(void) +{ + const void *fdt = bsp_fdt_get(); + int cpus = fdt_path_offset(fdt, "/cpus"); + int node = fdt_first_subnode(fdt, cpus); + uint32_t cpu = 0; + + while (node >= 0 && cpu < RTEMS_ARRAY_SIZE(qoriq_start_spin_table_addr)) { + int len; + fdt64_t *addr_fdt = (fdt64_t *) + fdt_getprop(fdt, node, "cpu-release-addr", &len); + + if (addr_fdt != NULL) { + uintptr_t addr = (uintptr_t) fdt64_to_cpu(*addr_fdt); + + qoriq_start_spin_table_addr[cpu] = (qoriq_start_spin_table *) addr; + } + + ++cpu; + node = fdt_next_subnode(fdt, node); + } + + return cpu * QORIQ_THREAD_COUNT; +} + +uint32_t _CPU_SMP_Initialize(void) +{ + uint32_t cpu_count = 1; + + if (rtems_configuration_get_maximum_processors() > 0) { + setup_boot_page(); + cpu_count = discover_processors(); + } + + start_thread_if_necessary(0); + + return cpu_count; +} + +static bool release_processor( + qoriq_start_spin_table *spin_table, + uint32_t cpu_index +) +{ + bool spin_table_present = (spin_table != NULL); + + if (spin_table_present) { + const Per_CPU_Control *cpu = _Per_CPU_Get_by_index(cpu_index); + + spin_table->pir = cpu_index; + spin_table->r3 = (uintptr_t) cpu->interrupt_stack_high; + rtems_cache_flush_multiple_data_lines(spin_table, sizeof(*spin_table)); + ppc_synchronize_data(); + spin_table->addr = (uintptr_t) _start_secondary_processor; + rtems_cache_flush_multiple_data_lines(spin_table, sizeof(*spin_table)); + } + + return spin_table_present; +} + +static qoriq_start_spin_table *get_spin_table(uint32_t cpu_index) +{ + qoriq_start_spin_table *spin_table; + + spin_table = qoriq_start_spin_table_addr[cpu_index / QORIQ_THREAD_COUNT]; + + return spin_table; +} + +bool _CPU_SMP_Start_processor(uint32_t cpu_index) +{ +#if QORIQ_THREAD_COUNT > 1 + if (is_started_by_u_boot(cpu_index)) { + qoriq_start_spin_table *spin_table = get_spin_table(cpu_index); + + return release_processor(spin_table, cpu_index); + } else { + return _SMP_Should_start_processor(cpu_index - 1); + } +#else + qoriq_start_spin_table *spin_table = get_spin_table(cpu_index); + + return release_processor(spin_table, cpu_index); +#endif +} + +void _CPU_SMP_Finalize_initialization(uint32_t cpu_count) +{ +#ifdef QORIQ_IS_HYPERVISOR_GUEST + (void) cpu_count; +#else + if (cpu_count > 1) { + rtems_status_code sc; + + sc = rtems_interrupt_handler_install( + QORIQ_IRQ_IPI_0 + IPI_INDEX, + "IPI", + RTEMS_INTERRUPT_UNIQUE, + bsp_inter_processor_interrupt, + NULL + ); + if (sc != RTEMS_SUCCESSFUL) { + bsp_fatal(QORIQ_FATAL_SMP_IPI_HANDLER_INSTALL); + } + } +#endif +} + +void _CPU_SMP_Prepare_start_multitasking(void) +{ + /* Do nothing */ +} + +void _CPU_SMP_Send_interrupt(uint32_t target_processor_index) +{ +#ifdef QORIQ_IS_HYPERVISOR_GUEST + uint32_t msg; + + /* DBELL message type */ + msg = (0U << (63 - 36)) | target_processor_index; + __asm__ volatile ("msgsnd %0" : : "r" (msg)); +#else + qoriq.pic.ipidr [IPI_INDEX].reg = 1U << target_processor_index; +#endif +} diff --git a/bsps/powerpc/qoriq/start/bspstart.c b/bsps/powerpc/qoriq/start/bspstart.c new file mode 100644 index 0000000000..7d9fa0d3c7 --- /dev/null +++ b/bsps/powerpc/qoriq/start/bspstart.c @@ -0,0 +1,197 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief BSP startup. + */ + +/* + * Copyright (c) 2010, 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 <libfdt.h> + +#include <rtems.h> +#include <rtems/config.h> +#include <rtems/counter.h> +#include <rtems/sysinit.h> + +#include <libcpu/powerpc-utility.h> + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/console-termios.h> +#include <bsp/fatal.h> +#include <bsp/fdt.h> +#include <bsp/intercom.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> +#include <bsp/mmu.h> +#include <bsp/qoriq.h> +#include <bsp/vectors.h> + +LINKER_SYMBOL(bsp_exc_vector_base); + +qoriq_start_spin_table * +qoriq_start_spin_table_addr[QORIQ_CPU_COUNT / QORIQ_THREAD_COUNT]; + +/* Configuration parameters for console driver, ... */ +unsigned int BSP_bus_frequency; + +/* Configuration parameter for clock driver, ... */ +uint32_t bsp_time_base_frequency; + +uint32_t qoriq_clock_frequency; + +static void initialize_frequency_parameters(void) +{ + const void *fdt = bsp_fdt_get(); + int node; + int len; + fdt32_t *val_fdt; + + node = fdt_node_offset_by_prop_value(fdt, -1, "device_type", "cpu", 4); + + val_fdt = (fdt32_t *) fdt_getprop(fdt, node, "bus-frequency", &len); + if (val_fdt == NULL || len != 4) { + bsp_fatal(QORIQ_FATAL_FDT_NO_BUS_FREQUENCY); + } + BSP_bus_frequency = fdt32_to_cpu(*val_fdt) / QORIQ_BUS_CLOCK_DIVIDER; + + val_fdt = (fdt32_t *) fdt_getprop(fdt, node, "timebase-frequency", &len); + if (val_fdt == NULL || len != 4) { + bsp_fatal(QORIQ_FATAL_FDT_NO_BUS_FREQUENCY); + } + bsp_time_base_frequency = fdt32_to_cpu(*val_fdt); + + #ifdef __PPC_CPU_E6500__ + val_fdt = (fdt32_t *) fdt_getprop(fdt, node, "clock-frequency", &len); + if (val_fdt == NULL || len != 4) { + bsp_fatal(QORIQ_FATAL_FDT_NO_CLOCK_FREQUENCY); + } + qoriq_clock_frequency = fdt32_to_cpu(*val_fdt); + #endif + rtems_counter_initialize_converter(fdt32_to_cpu(*val_fdt)); +} + +#define MTIVPR(base) \ + __asm__ volatile ("mtivpr %0" : : "r" (base)) + +#ifdef __powerpc64__ +#define VECTOR_TABLE_ENTRY_SIZE 32 +#else +#define VECTOR_TABLE_ENTRY_SIZE 16 +#endif + +#define MTIVOR(vec, offset) \ + do { \ + __asm__ volatile ("mtspr " RTEMS_XSTRING(vec) ", %0" : : "r" (offset)); \ + offset += VECTOR_TABLE_ENTRY_SIZE; \ + } while (0) + +void qoriq_initialize_exceptions(void *interrupt_stack_begin) +{ + uintptr_t addr; + + ppc_exc_initialize_interrupt_stack( + (uintptr_t) interrupt_stack_begin, + rtems_configuration_get_interrupt_stack_size() + ); + + addr = (uintptr_t) bsp_exc_vector_base; + MTIVPR(addr); + MTIVOR(BOOKE_IVOR0, addr); + MTIVOR(BOOKE_IVOR1, addr); + MTIVOR(BOOKE_IVOR2, addr); + MTIVOR(BOOKE_IVOR3, addr); + MTIVOR(BOOKE_IVOR4, addr); + MTIVOR(BOOKE_IVOR5, addr); + MTIVOR(BOOKE_IVOR6, addr); +#ifdef __PPC_CPU_E6500__ + MTIVOR(BOOKE_IVOR7, addr); +#endif + MTIVOR(BOOKE_IVOR8, addr); +#ifdef __PPC_CPU_E6500__ + MTIVOR(BOOKE_IVOR9, addr); +#endif + MTIVOR(BOOKE_IVOR10, addr); + MTIVOR(BOOKE_IVOR11, addr); + MTIVOR(BOOKE_IVOR12, addr); + MTIVOR(BOOKE_IVOR13, addr); + MTIVOR(BOOKE_IVOR14, addr); + MTIVOR(BOOKE_IVOR15, addr); + MTIVOR(BOOKE_IVOR32, addr); + MTIVOR(BOOKE_IVOR33, addr); +#ifndef __PPC_CPU_E6500__ + MTIVOR(BOOKE_IVOR34, addr); +#endif + MTIVOR(BOOKE_IVOR35, addr); +#ifdef __PPC_CPU_E6500__ + MTIVOR(BOOKE_IVOR36, addr); + MTIVOR(BOOKE_IVOR37, addr); +#ifndef QORIQ_IS_HYPERVISOR_GUEST + MTIVOR(BOOKE_IVOR38, addr); + MTIVOR(BOOKE_IVOR39, addr); + MTIVOR(BOOKE_IVOR40, addr); + MTIVOR(BOOKE_IVOR41, addr); + MTIVOR(BOOKE_IVOR42, addr); +#endif +#endif +} + +void bsp_start(void) +{ + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() function + * store the result in global variables so that it can be used latter... + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + initialize_frequency_parameters(); + + qoriq_initialize_exceptions(bsp_section_work_begin); + bsp_interrupt_initialize(); + + rtems_cache_coherent_add_area( + bsp_section_nocacheheap_begin, + (uintptr_t) bsp_section_nocacheheap_size + ); + +#ifndef QORIQ_IS_HYPERVISOR_GUEST + /* Disable boot page translation */ +#if QORIQ_CHIP_IS_T_VARIANT(QORIQ_CHIP_VARIANT) + qoriq.lcc.bstar &= ~LCC_BSTAR_EN; +#else + qoriq.lcc.bptr &= ~BPTR_EN; +#endif +#endif +} + +uint32_t bsp_fdt_map_intr(const uint32_t *intr, size_t icells) +{ +#ifndef QORIQ_IS_HYPERVISOR_GUEST + return intr[0] - 16; +#else + return intr[0]; +#endif +} + +#ifdef RTEMS_MULTIPROCESSING +RTEMS_SYSINIT_ITEM( + qoriq_intercom_init, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); +#endif diff --git a/bsps/powerpc/qoriq/start/epapr_hcalls.S b/bsps/powerpc/qoriq/start/epapr_hcalls.S new file mode 100644 index 0000000000..b019e5d710 --- /dev/null +++ b/bsps/powerpc/qoriq/start/epapr_hcalls.S @@ -0,0 +1,26 @@ +/* + * 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 <libcpu/powerpc-utility.h> + + .text + + .global epapr_hypercall_start +epapr_hypercall_start: + + sc 1 + nop + nop + nop + blr diff --git a/bsps/powerpc/qoriq/start/l1cache.S b/bsps/powerpc/qoriq/start/l1cache.S new file mode 100644 index 0000000000..bee3d28123 --- /dev/null +++ b/bsps/powerpc/qoriq/start/l1cache.S @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015, 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 <libcpu/powerpc-utility.h> + + .global qoriq_l1cache_invalidate + + .section ".bsp_start_text", "ax" + +qoriq_l1cache_invalidate: + + /* Invalidate L1 data cache */ + mfspr r3, FSL_EIS_L1CSR0 + ori r3, r3, FSL_EIS_L1CSR0_CFI + mtspr FSL_EIS_L1CSR0, r3 +1: + mfspr r3, FSL_EIS_L1CSR0 + andi. r3, r3, FSL_EIS_L1CSR0_CFI + bne 1b + isync + + /* Invalidate L1 instruction cache */ + mfspr r3, FSL_EIS_L1CSR1 + ori r3, r3, FSL_EIS_L1CSR1_ICFI + mtspr FSL_EIS_L1CSR1, r3 +1: + mfspr r3, FSL_EIS_L1CSR1 + andi. r3, r3, FSL_EIS_L1CSR1_ICFI + bne 1b + isync + + blr diff --git a/bsps/powerpc/qoriq/start/l2cache.S b/bsps/powerpc/qoriq/start/l2cache.S new file mode 100644 index 0000000000..1c57659aa1 --- /dev/null +++ b/bsps/powerpc/qoriq/start/l2cache.S @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015, 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 <libcpu/powerpc-utility.h> + + .global qoriq_l2cache_flush_invalidate + + .section ".bsp_start_text", "ax" + +qoriq_l2cache_flush_invalidate: + + /* Flush L2 cache */ + lwz r4, 0(r3) + oris r4, r4, FSL_EIS_L2CSR0_L2FL >> 16 + stw r4, 0(r3) +1: + lwz r4, 0(r3) + andis. r4, r4, FSL_EIS_L2CSR0_L2FL >> 16 + bne 1b + isync + + /* Invalidate L2 cache */ + lwz r4, 0(r3) + oris r4, r4, FSL_EIS_L2CSR0_L2FI >> 16 + stw r4, 0(r3) +1: + lwz r4, 0(r3) + andis. r4, r4, FSL_EIS_L2CSR0_L2FI >> 16 + bne 1b + isync + + blr diff --git a/bsps/powerpc/qoriq/start/linkcmds.qoriq_core_0 b/bsps/powerpc/qoriq/start/linkcmds.qoriq_core_0 new file mode 100644 index 0000000000..80ae3937bf --- /dev/null +++ b/bsps/powerpc/qoriq/start/linkcmds.qoriq_core_0 @@ -0,0 +1,38 @@ +/** + * @file + * + * @brief Memory map for QorIQ Core 0. + */ + +EXTERN (__vectors) + +MEMORY { + LOW : ORIGIN = 0x4000, LENGTH = 16M - 16k + HIGH : ORIGIN = 0x1000000, LENGTH = 32M + EMPTY : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", LOW); +REGION_ALIAS ("REGION_FAST_TEXT", LOW); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", LOW); +REGION_ALIAS ("REGION_TEXT", LOW); +REGION_ALIAS ("REGION_TEXT_LOAD", LOW); +REGION_ALIAS ("REGION_RODATA", HIGH); +REGION_ALIAS ("REGION_RODATA_LOAD", LOW); +REGION_ALIAS ("REGION_FAST_DATA", HIGH); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", LOW); +REGION_ALIAS ("REGION_DATA", HIGH); +REGION_ALIAS ("REGION_DATA_LOAD", LOW); +REGION_ALIAS ("REGION_BSS", HIGH); +REGION_ALIAS ("REGION_RWEXTRA", HIGH); +REGION_ALIAS ("REGION_WORK", HIGH); +REGION_ALIAS ("REGION_STACK", HIGH); +REGION_ALIAS ("REGION_NOCACHE", EMPTY); +REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +bsp_section_robarrier_align = 0x1000000; +bsp_section_rwbarrier_align = 0x1000000; +qoriq = 0xffe00000; + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/qoriq/start/linkcmds.qoriq_core_1 b/bsps/powerpc/qoriq/start/linkcmds.qoriq_core_1 new file mode 100644 index 0000000000..ecb601b9ef --- /dev/null +++ b/bsps/powerpc/qoriq/start/linkcmds.qoriq_core_1 @@ -0,0 +1,37 @@ +/** + * @file + * + * @brief Memory map for QorIQ Core 1. + */ + +EXTERN (__vectors) + +MEMORY { + RAM : ORIGIN = 0x4000000, LENGTH = 64M + EMPTY : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", 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_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", EMPTY); +REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +bsp_section_robarrier_align = 0x1000000; +bsp_section_rwbarrier_align = 0x1000000; +qoriq = 0xffe00000; + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/qoriq/start/linkcmds.qoriq_e500 b/bsps/powerpc/qoriq/start/linkcmds.qoriq_e500 new file mode 100644 index 0000000000..b727aefaa8 --- /dev/null +++ b/bsps/powerpc/qoriq/start/linkcmds.qoriq_e500 @@ -0,0 +1,38 @@ +/** + * @file + * + * Memory map for P1020RDB. + */ + +EXTERN (__vectors) + +MEMORY { + LOW : ORIGIN = 0x4000, LENGTH = 16M - 16k + HIGH : ORIGIN = 0x1000000, LENGTH = 512M - 16M + EMPTY : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", LOW); +REGION_ALIAS ("REGION_FAST_TEXT", LOW); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", LOW); +REGION_ALIAS ("REGION_TEXT", LOW); +REGION_ALIAS ("REGION_TEXT_LOAD", LOW); +REGION_ALIAS ("REGION_RODATA", HIGH); +REGION_ALIAS ("REGION_RODATA_LOAD", LOW); +REGION_ALIAS ("REGION_FAST_DATA", HIGH); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", LOW); +REGION_ALIAS ("REGION_DATA", HIGH); +REGION_ALIAS ("REGION_DATA_LOAD", LOW); +REGION_ALIAS ("REGION_BSS", HIGH); +REGION_ALIAS ("REGION_RWEXTRA", HIGH); +REGION_ALIAS ("REGION_WORK", HIGH); +REGION_ALIAS ("REGION_STACK", HIGH); +REGION_ALIAS ("REGION_NOCACHE", EMPTY); +REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +bsp_section_robarrier_align = 0x1000000; +bsp_section_rwbarrier_align = 0x1000000; +qoriq = 0xffe00000; + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/qoriq/start/linkcmds.qoriq_e6500_32 b/bsps/powerpc/qoriq/start/linkcmds.qoriq_e6500_32 new file mode 100644 index 0000000000..900147c163 --- /dev/null +++ b/bsps/powerpc/qoriq/start/linkcmds.qoriq_e6500_32 @@ -0,0 +1,41 @@ +/** + * @file + * + * Memory map for e6500 core based QorIQ chips, e.g. T2080, T4240. + */ + +EXTERN (__vectors) + +MEMORY { + LOW : ORIGIN = 0x00004000, LENGTH = 16M - 16k + NOCACHE : ORIGIN = 0x01000000, LENGTH = 48M + HIGH : ORIGIN = 0x04000000, LENGTH = 512M - 64M + EMPTY : ORIGIN = 0x00000000, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", LOW); +REGION_ALIAS ("REGION_FAST_TEXT", LOW); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", LOW); +REGION_ALIAS ("REGION_TEXT", LOW); +REGION_ALIAS ("REGION_TEXT_LOAD", LOW); +REGION_ALIAS ("REGION_RODATA", HIGH); +REGION_ALIAS ("REGION_RODATA_LOAD", LOW); +REGION_ALIAS ("REGION_FAST_DATA", HIGH); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", LOW); +REGION_ALIAS ("REGION_DATA", HIGH); +REGION_ALIAS ("REGION_DATA_LOAD", LOW); +REGION_ALIAS ("REGION_BSS", HIGH); +REGION_ALIAS ("REGION_RWEXTRA", HIGH); +REGION_ALIAS ("REGION_WORK", HIGH); +REGION_ALIAS ("REGION_STACK", HIGH); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", LOW); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +bsp_section_robarrier_align = 0x1000000; +bsp_section_rwbarrier_align = 0x1000000; +qoriq = 0xffe000000; +qoriq_bman_portal = 0xff4000000; +qoriq_qman_portal = 0xff6000000; + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/qoriq/start/linkcmds.qoriq_e6500_64 b/bsps/powerpc/qoriq/start/linkcmds.qoriq_e6500_64 new file mode 100644 index 0000000000..a4969756ec --- /dev/null +++ b/bsps/powerpc/qoriq/start/linkcmds.qoriq_e6500_64 @@ -0,0 +1 @@ +INCLUDE linkcmds.qoriq_e6500_32 diff --git a/bsps/powerpc/qoriq/start/mmu-config.c b/bsps/powerpc/qoriq/start/mmu-config.c new file mode 100644 index 0000000000..b59d9c7114 --- /dev/null +++ b/bsps/powerpc/qoriq/start/mmu-config.c @@ -0,0 +1,352 @@ +/** + * @file + * + * @ingroup QorIQMMU + * + * @brief MMU implementation. + */ + +/* + * Copyright (c) 2011, 2018 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/fdt.h> +#include <bsp/linker-symbols.h> +#include <bsp/mmu.h> +#include <bsp/qoriq.h> + +#include <sys/param.h> + +#include <libfdt.h> + +#include <rtems/config.h> + +#define TEXT __attribute__((section(".bsp_start_text"))) +#define DATA __attribute__((section(".bsp_start_data"))) + +typedef struct { + uintptr_t begin; + uintptr_t size; + uint32_t mas2; + uint32_t mas3; + uint32_t mas7; +} entry; + +#define ENTRY_X(b, s) { \ + .begin = (uintptr_t) b, \ + .size = (uintptr_t) s, \ + .mas2 = 0, \ + .mas3 = FSL_EIS_MAS3_SX \ +} + +#define ENTRY_R(b, s) { \ + .begin = (uintptr_t) b, \ + .size = (uintptr_t) s, \ + .mas2 = 0, \ + .mas3 = FSL_EIS_MAS3_SR \ +} + +#ifdef RTEMS_SMP + #define ENTRY_RW_MAS2 FSL_EIS_MAS2_M +#else + #define ENTRY_RW_MAS2 0 +#endif + +#define ENTRY_RW(b, s) { \ + .begin = (uintptr_t) b, \ + .size = (uintptr_t) s, \ + .mas2 = ENTRY_RW_MAS2, \ + .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW \ +} + +#define ENTRY_IO(b, s) { \ + .begin = (uintptr_t) b, \ + .size = (uintptr_t) s, \ + .mas2 = FSL_EIS_MAS2_I | FSL_EIS_MAS2_G, \ + .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW \ +} + +#define ENTRY_DEV(b, s) { \ + .begin = (uintptr_t) b, \ + .size = (uintptr_t) s, \ + .mas2 = FSL_EIS_MAS2_I | FSL_EIS_MAS2_G, \ + .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, \ + .mas7 = QORIQ_MMU_DEVICE_MAS7 \ +} + +/* + * MMU entry for BMan and QMan software portals. + * + * The M bit must be set if stashing is used, see 3.3.8.6 DQRR Entry Stashing + * and 3.3.8 Software Portals in T4240DPAARM. + * + * The G bit must be set, otherwise ECC errors in the QMan software portals + * will occur. No documentation reference for this is available. + */ +#define ENTRY_DEV_CACHED(b, s) { \ + .begin = (uintptr_t) b, \ + .size = (uintptr_t) s, \ + .mas2 = FSL_EIS_MAS2_M | FSL_EIS_MAS2_G, \ + .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, \ + .mas7 = QORIQ_MMU_DEVICE_MAS7 \ +} + +#define WORKSPACE_ENTRY_INDEX 0 + +static entry DATA config[] = { + /* Must be first entry, see WORKSPACE_ENTRY_INDEX */ + ENTRY_RW(bsp_section_work_begin, bsp_section_work_size), + + #if defined(RTEMS_MULTIPROCESSING) && \ + defined(QORIQ_INTERCOM_AREA_BEGIN) && \ + defined(QORIQ_INTERCOM_AREA_SIZE) + { + .begin = QORIQ_INTERCOM_AREA_BEGIN, + .size = QORIQ_INTERCOM_AREA_SIZE, + .mas2 = FSL_EIS_MAS2_M, + .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW + }, + #endif + ENTRY_X(bsp_section_start_begin, bsp_section_start_size), + ENTRY_R(bsp_section_fast_text_load_begin, bsp_section_fast_text_size), + ENTRY_X(bsp_section_fast_text_begin, bsp_section_fast_text_size), + ENTRY_X(bsp_section_text_begin, bsp_section_text_size), + ENTRY_R(bsp_section_rodata_load_begin, bsp_section_rodata_size), + ENTRY_R(bsp_section_rodata_begin, bsp_section_rodata_size), + ENTRY_R(bsp_section_fast_data_load_begin, bsp_section_fast_data_size), + ENTRY_RW(bsp_section_fast_data_begin, bsp_section_fast_data_size), + ENTRY_R(bsp_section_data_load_begin, bsp_section_data_size), + ENTRY_RW(bsp_section_data_begin, bsp_section_data_size), + ENTRY_RW(bsp_section_sbss_begin, bsp_section_sbss_size), + ENTRY_RW(bsp_section_bss_begin, bsp_section_bss_size), + ENTRY_RW(bsp_section_rwextra_begin, bsp_section_rwextra_size), + ENTRY_RW(bsp_section_stack_begin, bsp_section_stack_size), + ENTRY_IO(bsp_section_nocache_begin, bsp_section_nocache_size), + ENTRY_IO(bsp_section_nocachenoload_begin, bsp_section_nocachenoload_size), +#ifndef QORIQ_IS_HYPERVISOR_GUEST +#if QORIQ_CHIP_IS_T_VARIANT(QORIQ_CHIP_VARIANT) + /* BMan Portals */ + ENTRY_DEV_CACHED(&qoriq_bman_portal[0][0], sizeof(qoriq_bman_portal[0])), + ENTRY_DEV(&qoriq_bman_portal[1][0], sizeof(qoriq_bman_portal[1])), + /* QMan Portals */ + ENTRY_DEV_CACHED(&qoriq_qman_portal[0][0], sizeof(qoriq_qman_portal[0])), + ENTRY_DEV(&qoriq_qman_portal[1][0], sizeof(qoriq_qman_portal[1])), +#endif + ENTRY_DEV(&qoriq, sizeof(qoriq)) +#endif +}; + +static DATA char memory_path[] = "/memory"; + +#ifdef QORIQ_IS_HYPERVISOR_GUEST +static void TEXT add_dpaa_bqman_portals( + qoriq_mmu_context *context, + const void *fdt, + const char *compatible +) +{ + int node; + + node = -1; + + while (true) { + const void *val; + int len; + uintptr_t paddr; + uintptr_t size; + + node = fdt_node_offset_by_compatible(fdt, node, compatible); + if (node < 0) { + break; + } + + val = fdt_getprop(fdt, node, "reg", &len); + if (len != 32) { + continue; + } + + paddr = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[0]); + size = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[1]); + + qoriq_mmu_add( + context, + paddr, + paddr + size - 1, + 0, + FSL_EIS_MAS2_M | FSL_EIS_MAS2_G, + FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, + QORIQ_MMU_DEVICE_MAS7 + ); + + paddr = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[2]); + size = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[3]); + + qoriq_mmu_add( + context, + paddr, + paddr + size - 1, + 0, + FSL_EIS_MAS2_I | FSL_EIS_MAS2_G, + FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, + QORIQ_MMU_DEVICE_MAS7 + ); + } +} + +static void TEXT add_dpaa_bpool(qoriq_mmu_context *context, const void *fdt) +{ + int node; + + node = -1; + + while (true) { + const void *val; + int len; + uintptr_t config_count; + uintptr_t size; + uintptr_t paddr; + + node = fdt_node_offset_by_compatible(fdt, node, "fsl,bpool"); + if (node < 0) { + break; + } + + val = fdt_getprop(fdt, node, "fsl,bpool-ethernet-cfg", &len); + if (len != 24) { + continue; + } + + config_count = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[0]); + size = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[1]); + paddr = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[2]); + + qoriq_mmu_add( + context, + paddr, + paddr + config_count * size - 1, + 0, + FSL_EIS_MAS2_M, + FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, + 0 + ); + } +} +#endif + +static void TEXT config_fdt_adjust(const void *fdt) +{ + int node; + + node = fdt_path_offset_namelen( + fdt, + memory_path, + (int) sizeof(memory_path) - 1 + ); + + if (node >= 0) { + int len; + const void *val; + uint64_t mem_begin; + uint64_t mem_size; + + val = fdt_getprop(fdt, node, "reg", &len); + if (len == 8) { + mem_begin = fdt32_to_cpu(((fdt32_t *) val)[0]); + mem_size = fdt32_to_cpu(((fdt32_t *) val)[1]); + } else if (len == 16) { + mem_begin = fdt64_to_cpu(((fdt64_t *) val)[0]); + mem_size = fdt64_to_cpu(((fdt64_t *) val)[1]); + } else { + mem_begin = 0; + mem_size = 0; + } + +#ifndef __powerpc64__ + mem_size = MIN(mem_size, 0x80000000U); +#endif + + if ( + mem_begin == 0 + && mem_size > (uintptr_t) bsp_section_work_end + && (uintptr_t) bsp_section_nocache_end + < (uintptr_t) bsp_section_work_end + ) { + /* Assign new value to allow a bsp_restart() */ + config[WORKSPACE_ENTRY_INDEX].size = (uintptr_t) mem_size + - (uintptr_t) bsp_section_work_begin; + } + } +} + +void TEXT qoriq_mmu_config(bool boot_processor, int first_tlb, int scratch_tlb) +{ + qoriq_mmu_context context; + const void *fdt; + int max_count; + int i; + + for (i = 0; i < QORIQ_TLB1_ENTRY_COUNT; ++i) { + if (i != scratch_tlb) { + qoriq_tlb1_invalidate(i); + } + } + + fdt = bsp_fdt_get(); + qoriq_mmu_context_init(&context); + +#ifdef QORIQ_IS_HYPERVISOR_GUEST + add_dpaa_bqman_portals(&context, fdt, "fsl,bman-portal"); + add_dpaa_bqman_portals(&context, fdt, "fsl,qman-portal"); + add_dpaa_bpool(&context, fdt); + max_count = QORIQ_TLB1_ENTRY_COUNT - 1; +#else + max_count = (3 * QORIQ_TLB1_ENTRY_COUNT) / 4; +#endif + + if (boot_processor) { + config_fdt_adjust(fdt); + } + + for (i = 0; i < (int) (sizeof(config) / sizeof(config [0])); ++i) { + const entry *cur = &config [i]; + if (cur->size > 0) { + qoriq_mmu_add( + &context, + cur->begin, + cur->begin + cur->size - 1, + 0, + cur->mas2, + cur->mas3, + cur->mas7 + ); + } + } + + qoriq_mmu_partition(&context, max_count); + qoriq_mmu_write_to_tlb1(&context, first_tlb); +} + +void TEXT bsp_work_area_initialize(void) +{ + const entry *we = &config[WORKSPACE_ENTRY_INDEX]; + uintptr_t begin = we->begin; + uintptr_t end = begin + we->size; + +#ifdef BSP_INTERRUPT_STACK_AT_WORK_AREA_BEGIN + begin += rtems_configuration_get_interrupt_stack_size(); +#endif + + bsp_work_area_initialize_default((void *) begin, end - begin); +} diff --git a/bsps/powerpc/qoriq/start/mmu-tlb1.S b/bsps/powerpc/qoriq/start/mmu-tlb1.S new file mode 100644 index 0000000000..2dd06e2ed8 --- /dev/null +++ b/bsps/powerpc/qoriq/start/mmu-tlb1.S @@ -0,0 +1,107 @@ +/** + * @file + * + * @ingroup QorIQMMU + * + * @brief qoriq_tlb1_write() and qoriq_tlb1_invalidate() implementation. + */ + +/* + * Copyright (c) 2011, 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 <bspopts.h> + +#include <libcpu/powerpc-utility.h> + + .global qoriq_tlb1_write + .global qoriq_tlb1_invalidate + .global qoriq_tlb1_invalidate_all_by_ts + + .section ".bsp_start_text", "ax" + +qoriq_tlb1_write: + rlwinm r3, r3, 16, 10, 15 +#ifdef __powerpc64__ + rldicr r8, r8, 0, 51 +#else + rlwinm r8, r8, 0, 0, 19 +#endif + oris r3, r3, 0x1000 + mtspr FSL_EIS_MAS0, r3 + oris r4, r4, 0xc000 + rlwinm r9, r9, 8, 20, 23 + or r9, r4, r9 + mtspr FSL_EIS_MAS1, r9 + or r5, r8, r5 + mtspr FSL_EIS_MAS2, r5 + or r6, r8, r6 + mtspr FSL_EIS_MAS3, r6 +#ifdef __powerpc64__ + srdi r8, r8, 32 + or r7, r7, r8 + mtspr FSL_EIS_MAS7, r7 +#endif + mtspr FSL_EIS_MAS7, r7 +#if defined(QORIQ_HAS_HYPERVISOR_MODE) && !defined(QORIQ_IS_HYPERVISOR_GUEST) + li r0, 0 + mtspr FSL_EIS_MAS8, r0 +#endif + isync + msync + tlbwe + isync + blr + +qoriq_tlb1_invalidate: + rlwinm r3, r3, 16, 10, 15 + oris r3, r3, 0x1000 + mtspr FSL_EIS_MAS0, r3 + li r0, 0 + mtspr FSL_EIS_MAS1, r0 + mtspr FSL_EIS_MAS2, r0 + mtspr FSL_EIS_MAS3, r0 + mtspr FSL_EIS_MAS7, r0 +#if defined(QORIQ_HAS_HYPERVISOR_MODE) && !defined(QORIQ_IS_HYPERVISOR_GUEST) + mtspr FSL_EIS_MAS8, r0 +#endif + isync + msync + tlbwe + isync + blr + +/* r3 = 0 for TS0, 1 for TS1 */ +qoriq_tlb1_invalidate_all_by_ts: + mflr r12 + li r11, QORIQ_TLB1_ENTRY_COUNT + mtctr r11 + li r11, 0 + mr r10, r3 + +2: + rlwinm r0, r11, 16, 10, 15 + oris r0, r0, (FSL_EIS_MAS0_TLBSEL >> 16) + mtspr FSL_EIS_MAS0, r0 + tlbre + mfspr r0, FSL_EIS_MAS1 + rlwinm r0, r0, 20, 31, 31 + cmpw r0, r10 + bne 1f + mr r3, r11 + bl qoriq_tlb1_invalidate +1: + addi r11, r11, 1 + bdnz 2b + mtlr r12 + blr diff --git a/bsps/powerpc/qoriq/start/mmu.c b/bsps/powerpc/qoriq/start/mmu.c new file mode 100644 index 0000000000..2629c9f999 --- /dev/null +++ b/bsps/powerpc/qoriq/start/mmu.c @@ -0,0 +1,368 @@ +/** + * @file + * + * @ingroup QorIQMMU + * + * @brief MMU implementation. + */ + +/* + * Copyright (c) 2011, 2018 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/mmu.h> +#include <libcpu/powerpc-utility.h> + +#define TEXT __attribute__((section(".bsp_start_text"))) + +static uintptr_t TEXT power_of_two(uintptr_t val) +{ + uintptr_t test_power = QORIQ_MMU_MIN_POWER; + uintptr_t power = test_power; + uintptr_t alignment = 1U << test_power; + + while (test_power <= QORIQ_MMU_MAX_POWER && (val & (alignment - 1)) == 0) { + power = test_power; + alignment <<= QORIQ_MMU_POWER_STEP; + test_power += QORIQ_MMU_POWER_STEP; + } + + return power; +} + +static uintptr_t TEXT max_power_of_two(uintptr_t val) +{ + uintptr_t test_power = QORIQ_MMU_MIN_POWER; + uintptr_t power = test_power; + uintptr_t max = 1U << test_power; + + do { + power = test_power; + max <<= QORIQ_MMU_POWER_STEP; + test_power += QORIQ_MMU_POWER_STEP; + } while (test_power <= QORIQ_MMU_MAX_POWER && max <= val); + + return power; +} + +void TEXT qoriq_mmu_context_init(qoriq_mmu_context *self) +{ + int *cur = (int *) self; + const int *end = cur + sizeof(*self) / sizeof(*cur); + + while (cur != end) { + *cur = 0; + ++cur; + } +} + +static void TEXT sort(qoriq_mmu_context *self) +{ + qoriq_mmu_entry *entries = self->entries; + int n = self->count; + int i = 0; + + for (i = 1; i < n; ++i) { + qoriq_mmu_entry key = entries [i]; + int j = 0; + + for (j = i - 1; j >= 0 && entries [j].begin > key.begin; --j) { + entries [j + 1] = entries [j]; + } + + entries [j + 1] = key; + } +} + +static bool TEXT mas_compatible(const qoriq_mmu_entry *a, const qoriq_mmu_entry *b) +{ + uint32_t m = FSL_EIS_MAS2_M; + + return (a->mas2 & ~m) == (b->mas2 & ~m); +} + +static bool TEXT can_merge(const qoriq_mmu_entry *prev, const qoriq_mmu_entry *cur) +{ + return mas_compatible(prev, cur) + && (prev->begin == cur->begin || prev->last >= cur->begin - 1); +} + +static void TEXT merge(qoriq_mmu_context *self) +{ + qoriq_mmu_entry *entries = self->entries; + int n = self->count; + int i = 0; + + for (i = 1; i < n; ++i) { + qoriq_mmu_entry *prev = &entries [i - 1]; + qoriq_mmu_entry *cur = &entries [i]; + + if (can_merge(prev, cur)) { + int j = 0; + + prev->mas1 |= cur->mas1; + prev->mas2 |= cur->mas2; + prev->mas3 |= cur->mas3; + + if (cur->last > prev->last) { + prev->last = cur->last; + } + + for (j = i + 1; j < n; ++j) { + entries [j - 1] = entries [j]; + } + + --i; + --n; + } + } + + self->count = n; +} + +static void TEXT compact(qoriq_mmu_context *self) +{ + sort(self); + merge(self); +} + +static bool TEXT can_expand_down( + const qoriq_mmu_context *self, + const qoriq_mmu_entry *cur, + int i, + uintptr_t new_begin +) +{ + int j; + + for (j = 0; j < i; ++j) { + const qoriq_mmu_entry *before = &self->entries[j]; + + if ( + before->begin <= new_begin + && new_begin <= before->last + && !mas_compatible(before, cur) + ) { + return false; + } + } + + return true; +} + +static bool TEXT can_expand_up( + const qoriq_mmu_context *self, + const qoriq_mmu_entry *cur, + int i, + int n, + uintptr_t new_last +) +{ + int j; + + for (j = i + 1; j < n; ++j) { + const qoriq_mmu_entry *after = &self->entries[j]; + + if ( + after->begin <= new_last + && new_last <= after->last + && !mas_compatible(after, cur) + ) { + return false; + } + } + + return true; +} + +static void TEXT align(qoriq_mmu_context *self, uintptr_t alignment) +{ + int n = self->count; + int i; + + for (i = 0; i < n; ++i) { + qoriq_mmu_entry *cur = &self->entries[i]; + uintptr_t new_begin = cur->begin & ~(alignment - 1); + uintptr_t new_last = alignment + (cur->last & ~(alignment - 1)) - 1; + + if ( + can_expand_down(self, cur, i, new_begin) + && can_expand_up(self, cur, i, n, new_last) + ) { + cur->begin = new_begin; + cur->last = new_last; + } + } +} + +static bool TEXT is_full(qoriq_mmu_context *self) +{ + return self->count >= QORIQ_TLB1_ENTRY_COUNT; +} + +static void TEXT append(qoriq_mmu_context *self, const qoriq_mmu_entry *new_entry) +{ + self->entries [self->count] = *new_entry; + ++self->count; +} + +bool TEXT qoriq_mmu_add( + qoriq_mmu_context *self, + uintptr_t begin, + uintptr_t last, + uint32_t mas1, + uint32_t mas2, + uint32_t mas3, + uint32_t mas7 +) +{ + bool ok = true; + + if (is_full(self)) { + compact(self); + } + + if (!is_full(self)) { + if (begin < last) { + qoriq_mmu_entry new_entry = { + .begin = begin, + .last = last, + .mas1 = mas1, + .mas2 = mas2, + .mas3 = mas3, + .mas7 = mas7 + }; + append(self, &new_entry); + } else { + ok = false; + } + } else { + ok = false; + } + + return ok; +} + +static uintptr_t TEXT min(uintptr_t a, uintptr_t b) +{ + return a < b ? a : b; +} + +static bool TEXT split(qoriq_mmu_context *self, qoriq_mmu_entry *cur) +{ + bool again = false; + uintptr_t begin = cur->begin; + uintptr_t end = cur->last + 1; + uintptr_t size = end - begin; + uintptr_t begin_power = power_of_two(begin); + uintptr_t size_power = max_power_of_two(size); + uintptr_t power = min(begin_power, size_power); + uintptr_t split_size = power < 32 ? (1U << power) : 0; + uintptr_t split_pos = begin + split_size; + + if (split_pos != end && !is_full(self)) { + qoriq_mmu_entry new_entry = *cur; + cur->begin = split_pos; + new_entry.last = split_pos - 1; + append(self, &new_entry); + again = true; + } + + return again; +} + +static void TEXT split_all(qoriq_mmu_context *self) +{ + qoriq_mmu_entry *entries = self->entries; + int n = self->count; + int i = 0; + + for (i = 0; i < n; ++i) { + qoriq_mmu_entry *cur = &entries [i]; + + while (split(self, cur)) { + /* Repeat */ + } + } +} + +static TEXT void partition(qoriq_mmu_context *self) +{ + compact(self); + split_all(self); + sort(self); +} + +void TEXT qoriq_mmu_partition(qoriq_mmu_context *self, int max_count) +{ + uintptr_t alignment = 4096; + + sort(self); + + do { + align(self, alignment); + partition(self); + alignment *= 4; + } while (self->count > max_count); +} + +void TEXT qoriq_mmu_write_to_tlb1(qoriq_mmu_context *self, int first_tlb) +{ + qoriq_mmu_entry *entries = self->entries; + int n = self->count; + int i = 0; + + for (i = 0; i < n; ++i) { + qoriq_mmu_entry *cur = &entries [i]; + uintptr_t ea = cur->begin; + uintptr_t size = cur->last - ea + 1; + uintptr_t tsize = (power_of_two(size) - 10) / 2; + int tlb = first_tlb + i; + + qoriq_tlb1_write( + tlb, + cur->mas1, + cur->mas2, + cur->mas3, + cur->mas7, + ea, + (int) tsize + ); + } +} + +void qoriq_mmu_change_perm(uint32_t test, uint32_t set, uint32_t clear) +{ + int i = 0; + + for (i = 0; i < 16; ++i) { + uint32_t mas0 = FSL_EIS_MAS0_TLBSEL | FSL_EIS_MAS0_ESEL(i); + uint32_t mas1 = 0; + + PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS0, mas0); + asm volatile ("tlbre"); + + mas1 = PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS1); + if ((mas1 & FSL_EIS_MAS1_V) != 0) { + uint32_t mask = 0x3ff; + uint32_t mas3 = PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS3); + + if ((mas3 & mask) == test) { + mas3 &= ~(clear & mask); + mas3 |= set & mask; + PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS3, mas3); + asm volatile ("isync; msync; tlbwe; isync" : : : "memory"); + } + } + } +} diff --git a/bsps/powerpc/qoriq/start/portal.c b/bsps/powerpc/qoriq/start/portal.c new file mode 100644 index 0000000000..f20eaf4d28 --- /dev/null +++ b/bsps/powerpc/qoriq/start/portal.c @@ -0,0 +1,43 @@ +/* + * 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/qoriq.h> + +#if QORIQ_CHIP_IS_T_VARIANT(QORIQ_CHIP_VARIANT) + +#include <libcpu/powerpc-utility.h> + +void qoriq_clear_ce_portal(void *base, size_t size) +{ + size_t offset; + + for (offset = 0; offset < size; offset += 64) { + ppc_data_cache_block_clear_to_zero_2(base, offset); + ppc_data_cache_block_flush_2(base, offset); + } +} + +void qoriq_clear_ci_portal(void *base, size_t size) +{ + uint32_t zero; + size_t offset; + + zero = 0; + + for (offset = 0; offset < size; offset += 4) { + ppc_write_word(zero, (char *) base + offset); + } +} + +#endif diff --git a/bsps/powerpc/qoriq/start/restart.S b/bsps/powerpc/qoriq/start/restart.S new file mode 100644 index 0000000000..7dd9eb198d --- /dev/null +++ b/bsps/powerpc/qoriq/start/restart.S @@ -0,0 +1,80 @@ +/* + * 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 <libcpu/powerpc-utility.h> + +#define FIRST_TLB 0 + +#define SCRATCH_TLB QORIQ_TLB1_ENTRY_COUNT - 1 + + .global qoriq_restart_secondary_processor + + .section ".bsp_start_text", "ax" + +qoriq_restart_secondary_processor: + + mr r14, r3 + + /* Invalidate all TS1 MMU entries */ + li r3, 1 + bl qoriq_tlb1_invalidate_all_by_ts + + /* Add TS1 entry for the first 4GiB of RAM */ + li r3, SCRATCH_TLB + li r4, FSL_EIS_MAS1_TS + li r5, FSL_EIS_MAS2_I + li r6, FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW | FSL_EIS_MAS3_SX + li r7, 0 + li r8, 0 + li r9, 11 + bl qoriq_tlb1_write + + bl qoriq_l1cache_invalidate + + /* Set MSR and use TS1 for address translation */ + LWI r0, QORIQ_INITIAL_MSR | MSR_IS | MSR_DS + mtmsr r0 + isync + + /* Invalidate all TS0 MMU entries */ + li r3, 0 + bl qoriq_tlb1_invalidate_all_by_ts + + /* Add TS0 entry for the first 4GiB of RAM */ + li r3, FIRST_TLB + li r4, 0 + li r5, FSL_EIS_MAS2_I + li r6, FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW | FSL_EIS_MAS3_SX + li r7, 0 + li r8, 0 + li r9, 11 + bl qoriq_tlb1_write + + /* Use TS0 for address translation */ + LWI r0, QORIQ_INITIAL_MSR + mtmsr r0 + isync + + bl qoriq_l1cache_invalidate + + /* Wait for restart request */ + li r0, 0 +.Lrestartagain: + lwz r4, 4(r14) + cmpw r0, r4 + beq .Lrestartagain + isync + mtctr r4 + lwz r3, 12(r14) + bctr diff --git a/bsps/powerpc/shared/start/bspgetworkarea.c b/bsps/powerpc/shared/start/bspgetworkarea.c new file mode 100644 index 0000000000..3c86905020 --- /dev/null +++ b/bsps/powerpc/shared/start/bspgetworkarea.c @@ -0,0 +1,40 @@ +/* + * 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 <libcpu/powerpc-utility.h> + +#include <rtems/sysinit.h> + +LINKER_SYMBOL(__rtems_end) + +void bsp_work_area_initialize(void) +{ + /* + * Cannot do work area initialization before bsp_start(), since BSP_mem_size + * and MMU is not set up. + */ +} + +static void bsp_work_area_initialize_later(void) +{ + uintptr_t work_size; + uintptr_t work_area; + + work_area = (uintptr_t)__rtems_end + + rtems_configuration_get_interrupt_stack_size(); + work_size = (uintptr_t)BSP_mem_size - work_area; + + bsp_work_area_initialize_default((void *) work_area, work_size); +} + +RTEMS_SYSINIT_ITEM( + bsp_work_area_initialize_later, + RTEMS_SYSINIT_BSP_START, + RTEMS_SYSINIT_ORDER_LAST +); diff --git a/bsps/powerpc/shared/start/bspidle.c b/bsps/powerpc/shared/start/bspidle.c new file mode 100644 index 0000000000..de37fa1ced --- /dev/null +++ b/bsps/powerpc/shared/start/bspidle.c @@ -0,0 +1,36 @@ +/* + * Moved to libbsp/powerpc/shared by Joel Sherrill (9 Sept 09). + */ + +/* + * The MPC860 specific stuff was written by Jay Monkman (jmonkman@frasca.com) + * + * Modified for the MPC8260ADS board by Andy Dachs <a.dachs@sstl.co.uk> + * Surrey Satellite Technology Limited, 2001 + * + * 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> + +/** + * @brief BSP Idle thread body. + * + * The MSR[POW] bit is set to put the CPU into the low power mode + * defined in HID0. HID0 is set during starup in start.S. + */ +void *bsp_idle_thread( uintptr_t ignored ) +{ + for( ; ; ) { + __asm__ volatile( + "mfmsr 3; oris 3,3,4; sync; mtmsr 3; isync; ori 3,3,0; ori 3,3,0" + ); + } + + return 0; /* to remove warning */ +} diff --git a/bsps/powerpc/shared/start/linkcmds.base b/bsps/powerpc/shared/start/linkcmds.base new file mode 100644 index 0000000000..e0dfdcc914 --- /dev/null +++ b/bsps/powerpc/shared/start/linkcmds.base @@ -0,0 +1,436 @@ +/** + * @file + * + * @ingroup bsp_linker + * + * @brief Linker command base file. + */ + +/* + * Copyright (c) 2011, 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. + */ + +ENTRY (_start) +STARTUP (start.o) + +/* + * Global symbols that may be defined externally + */ + +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; + +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_TEXT AT > REGION_TEXT + + .text : ALIGN_WITH_INPUT { + bsp_section_text_begin = .; + *(SORT(.bsp_text*)) + *(.text.unlikely .text.*_unlikely) + *(.text .stub .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + *(.sfpr .glink) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .init : ALIGN_WITH_INPUT { + KEEP (*(.init)) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .fini : ALIGN_WITH_INPUT { + PROVIDE (_fini = .); + 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; + + .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; + + .robarrier : ALIGN_WITH_INPUT { + . = ALIGN (bsp_section_robarrier_align); + } > REGION_RODATA AT > REGION_RODATA + + .rodata : ALIGN_WITH_INPUT { + bsp_section_rodata_begin = .; + *(SORT(.bsp_rodata*)) + *(.rodata .rodata.* .gnu.linkonce.r.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rodata1 : ALIGN_WITH_INPUT { + *(.rodata1) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .sdata2 : ALIGN_WITH_INPUT { + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .sbss2 : ALIGN_WITH_INPUT { + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .eh_frame_hdr : ALIGN_WITH_INPUT { + *(.eh_frame_hdr) + } > 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 (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .ctors : ALIGN_WITH_INPUT { + KEEP (*ecrti.o(.ctors)) + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o *ecrtn.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dtors : ALIGN_WITH_INPUT { + KEEP (*ecrti.o(.dtors)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o *ecrtn.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .jcr : ALIGN_WITH_INPUT { + KEEP (*(.jcr)) + } > 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 + .fixup : ALIGN_WITH_INPUT { + *(.fixup) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynamic : ALIGN_WITH_INPUT { + *(.dynamic) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .opd : ALIGN_WITH_INPUT { + KEEP (*(.opd)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .tm_clone_table : ALIGN_WITH_INPUT { + *(.tm_clone_table) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .toc1 : ALIGN_WITH_INPUT { + *(.toc1) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .branch_lt : ALIGN_WITH_INPUT { + *(.branch_lt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .got1 : ALIGN_WITH_INPUT { + *(.got1) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .got2 : ALIGN_WITH_INPUT { + *(.got2) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .got : ALIGN_WITH_INPUT { + *(.got) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .toc : ALIGN_WITH_INPUT { + *(.toc) + } > 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 + .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 + .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.got1) + *(.rela.got2) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.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 + .rela.plt : ALIGN_WITH_INPUT { + *(.rela.plt) + } > 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 + + .fast_data : ALIGN_WITH_INPUT { + bsp_section_fast_data_begin = .; + *(SORT(.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 = .; + *(SORT(.bsp_data*)) + *(.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.*))) + } > REGION_DATA AT > REGION_DATA_LOAD + .sdata : ALIGN_WITH_INPUT { + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + 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; + + .sbss : ALIGN_WITH_INPUT { + bsp_section_sbss_begin = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + bsp_section_sbss_end = .; + } > REGION_DATA AT > REGION_DATA + bsp_section_sbss_size = bsp_section_sbss_end - bsp_section_sbss_begin; + + .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; + + .rwextra : ALIGN_WITH_INPUT { + bsp_section_rwextra_begin = .; + *(.bsp_rwextra) + bsp_section_rwextra_end = .; + } > REGION_RWEXTRA AT > REGION_RWEXTRA + bsp_section_rwextra_size = bsp_section_rwextra_end - bsp_section_rwextra_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; + + .nvram (NOLOAD) : ALIGN_WITH_INPUT { + bsp_section_nvram_begin = .; + *(SORT_BY_ALIGNMENT (SORT_BY_NAME (.bsp_nvram*))) + bsp_section_nvram_end = .; + } > REGION_NVRAM AT > REGION_NVRAM + bsp_section_nvram_size = bsp_section_nvram_end - bsp_section_nvram_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_line.* .debug_line_end ) } + .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) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + .PPC.EMB.apuinfo 0 : { *(.PPC.EMB.apuinfo) } + /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/powerpc/shared/start/linkcmds.share b/bsps/powerpc/shared/start/linkcmds.share new file mode 100644 index 0000000000..59f538e3a2 --- /dev/null +++ b/bsps/powerpc/shared/start/linkcmds.share @@ -0,0 +1,296 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc) +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +PROVIDE (__stack = 0); +MEMORY { + VECTORS : ORIGIN = 0x0 , LENGTH = 0x3000 + CODE : ORIGIN = 0x3000 , LENGTH = 32M - 0x3000 +} +SECTIONS +{ + .entry_point_section : + { + KEEP(*(.entry_point_section)) + } > VECTORS + + /* + * This section is used only if NO_DYNAMIC_EXCEPTION_VECTOR_INSTALL + * is defined in vectors/vectors.S + */ + .vectors : + { + *(.vectors) + } > VECTORS + + /* Read-only sections, merged into text segment: */ + .interp : { *(.interp) } > CODE + .hash : { *(.hash) } > CODE + .dynsym : { *(.dynsym) } > CODE + .dynstr : { *(.dynstr) } > CODE + .gnu.version : { *(.gnu.version) } > CODE + .gnu.version_d : { *(.gnu.version_d) } > CODE + .gnu.version_r : { *(.gnu.version_r) } > CODE + .rela.text : + { *(.rela.text) *(.rela.gnu.linkonce.t*) } > CODE + .rela.data : + { *(.rela.data) *(.rela.gnu.linkonce.d*) } > CODE + .rela.rodata : + { *(.rela.rodata*) *(.rela.gnu.linkonce.r*) } > CODE + .rela.got : { *(.rela.got) } > CODE + .rela.got1 : { *(.rela.got1) } > CODE + .rela.got2 : { *(.rela.got2) } > CODE + .rela.ctors : { *(.rela.ctors) } > CODE + .rela.dtors : { *(.rela.dtors) } > CODE + .rela.init : { *(.rela.init) } > CODE + .rela.fini : { *(.rela.fini) } > CODE + .rela.bss : { *(.rela.bss) } > CODE + .rela.plt : { *(.rela.plt) } > CODE + .rela.sdata : { *(.rela.sdata) } > CODE + .rela.sbss : { *(.rela.sbss) } > CODE + .rela.sdata2 : { *(.rela.sdata2) } > CODE + .rela.sbss2 : { *(.rela.sbss2) } > CODE + .rela.dyn : { *(.rela.dyn) } > CODE + + .init : { KEEP(*(.init)) } > CODE + + .text : + { + *(.text*) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } > CODE + + .fini : { _fini = .; KEEP(*(.fini)) } > CODE + + .rodata : { *(.rodata*) KEEP (*(SORT(.rtemsroset.*))) *(.gnu.linkonce.r*) } > CODE + .rodata1 : { *(.rodata1) } > CODE + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >CODE + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >CODE + + _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)); + + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(0x10000) + (. & (0x10000 - 1)); + /* Ensure the __preinit_array_start label is properly aligned. We + could instead move the label definition inside the section, but + the linker would then create the section even if it turns out to + be empty, which isn't pretty. */ + . = ALIGN(32 / 8); + PROVIDE (__preinit_array_start = .); + .preinit_array : { *(.preinit_array) } >CODE + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + .init_array : { *(.init_array) } >CODE + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + .fini_array : { *(.fini_array) } >CODE + PROVIDE (__fini_array_end = .); + + .sdata2 : {PROVIDE (_SDA2_BASE_ = 32768); *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } >CODE + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + /* avoid empty sdata2/sbss2 area -- __eabi would not set up r2 + * which may be important if run-time loading is used + */ + . += 1; + PROVIDE (__SBSS2_END__ = .); + } >CODE + .eh_frame : { *(.eh_frame) } >CODE + + /* NOTE: if the BSP uses page tables, the correctness of + * '_etext' (and __DATA_START__) is CRUCIAL - otherwise, + * an invalid mapping may result!!! + */ + _etext = .; + PROVIDE (etext = .); + + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. It would + be more correct to do this: + . = ALIGN(0x40000) + (ALIGN(8) & (0x40000 - 1)); + The current expression does not correctly handle the case of a + text segment ending precisely at the end of a page; it causes the + data segment to skip a page. The above expression does not have + this problem, but it will currently (2/95) cause BFD to allocate + a single segment, combining both text and data, for this case. + This will prevent the text segment from being shared among + multiple executions of the program; I think that is more + important than losing a page of the virtual address space (note + that no actual memory is lost; the page which is skipped can not + be referenced). */ + . = ALIGN(0x1000); + .data ALIGN(0x1000) : + { + /* NOTE: if the BSP uses page tables, the correctness of + * '__DATA_START__' (and _etext) is CRUCIAL - otherwise, + * an invalid mapping may result!!! + */ + PROVIDE(__DATA_START__ = ABSOLUTE(.) ); + *(.data .data.* .gnu.linkonce.d*) + KEEP (*(SORT(.rtemsrwset.*))) + SORT(CONSTRUCTORS) + } > CODE + .data1 : { *(.data1) } > CODE + PROVIDE (__EXCEPT_START__ = .); + .gcc_except_table : { *(.gcc_except_table*) } > CODE + PROVIDE (__EXCEPT_END__ = .); + .got1 : { *(.got1) } > CODE + /* Put .ctors and .dtors next to the .got2 section, so that the pointers + get relocated with -mrelocatable. Also put in the .fixup pointers. + The current compiler no longer needs this, but keep it around for 2.7.2 */ + PROVIDE (_GOT2_START_ = .); + .got2 : { *(.got2) } > CODE + .dynamic : { *(.dynamic) } > CODE + + .ctors : + { + /* 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)) + /* We don't want to include the .ctor section from + 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 ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } > CODE + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } > CODE + + + PROVIDE (_FIXUP_START_ = .); + .fixup : { *(.fixup) } > CODE + PROVIDE (_FIXUP_END_ = .); + PROVIDE (_GOT2_END_ = .); + PROVIDE (_GOT_START_ = .); + + .got : { *(.got) } > CODE + .got.plt : { *(.got.plt) } > CODE + + PROVIDE (_GOT_END_ = .); + + .jcr : { KEEP (*(.jcr)) } > CODE + + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : { PROVIDE (_SDA_BASE_ = 32768); *(.sdata*) *(.gnu.linkonce.s.*) } >CODE + _edata = .; + PROVIDE (edata = .); + .sbss : + { + PROVIDE (__sbss_start = .); + *(.dynsbss) + *(.sbss* .gnu.linkonce.sb.*) + *(.scommon) + /* avoid empty sdata/sbss area -- __eabi would not set up r13 + * which may be important if run-time loading is used + */ + . += 1; + PROVIDE (__SBSS_END__ = .); + PROVIDE (__sbss_end = .); + } > CODE + .plt : { *(.plt) } > CODE + .bss : + { + PROVIDE (__bss_start = .); + *(.dynbss) + *(.bss .bss* .gnu.linkonce.b*) + *(COMMON) + . = ALIGN(16); + PROVIDE (__bss_end = .); + } > CODE + . = ALIGN(16); + . += 0x1000; + __stack = .; + _end = . ; + __rtems_end = . ; + PROVIDE (end = .); + /DISCARD/ : + { + *(.comment) + } + + + /* 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) } + .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) } + /* These must appear regardless of . */ +} diff --git a/bsps/powerpc/shared/start/pgtbl_activate.c b/bsps/powerpc/shared/start/pgtbl_activate.c new file mode 100644 index 0000000000..2455f1e06d --- /dev/null +++ b/bsps/powerpc/shared/start/pgtbl_activate.c @@ -0,0 +1,77 @@ +#include <rtems.h> +#include <libcpu/pte121.h> +#include <libcpu/bat.h> + +/* Default activation of the page tables. This is a weak + * alias, so applications may easily override this + * default activation procedure. + */ + +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 4/2002, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ + +void __BSP_default_pgtbl_activate(Triv121PgTbl pt); +void +BSP_pgtbl_activate(Triv121PgTbl) + __attribute__ (( weak, alias("__BSP_default_pgtbl_activate") )); + +void +__BSP_default_pgtbl_activate(Triv121PgTbl pt) +{ + if (!pt) return; + + /* switch the text/ro sements to RO only after + * initializing the interrupts because the irq_mng + * installs some code... + * + * activate the page table; it is still masked by the + * DBAT0, however + */ + triv121PgTblActivate(pt); + + /* finally, switch off DBAT0 */ + setdbat(0,0,0,0,0); + /* At this point, DBAT0 is available for other use... */ +} diff --git a/bsps/powerpc/shared/start/pgtbl_setup.c b/bsps/powerpc/shared/start/pgtbl_setup.c new file mode 100644 index 0000000000..8a8407bd49 --- /dev/null +++ b/bsps/powerpc/shared/start/pgtbl_setup.c @@ -0,0 +1,135 @@ +#include <rtems.h> +#include <libcpu/mmu.h> +#include <rtems/bspIo.h> +#include <libcpu/pte121.h> + +/* Default setup of the page tables. This is a weak + * alias, so applications may easily override this + * default setup. + * + * NOTE: while it is possible to change the individual + * mappings, the page table itself MUST be + * allocated at the top of the physical memory! + * bspstart.c RELIES on this. + * Also, the 'setup' routine must reduce + * *pmemsize by the size of the page table. + */ +/* to align the pointer to the (next) page boundary */ +#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) + + +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 4/2002, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ + +Triv121PgTbl __BSP_default_pgtbl_setup(unsigned int *pmemsize); +Triv121PgTbl BSP_pgtbl_setup(unsigned int *) + __attribute__ (( weak, alias("__BSP_default_pgtbl_setup") )); + +/* get those from the linker script. + * NOTE THAT THE CORRECTNESS OF THE LINKER SCRIPT IS CRUCIAL + */ +extern unsigned long __DATA_START__[], _etext[]; + +Triv121PgTbl +__BSP_default_pgtbl_setup(unsigned int *pmemsize) +{ +Triv121PgTbl pt; +unsigned ldPtSize,tmp; + + /* Allocate a page table large enough to map + * the entire physical memory. We put the page + * table at the top of the physical memory. + */ + + /* get minimal size (log base 2) of PT for + * this board's memory + */ + ldPtSize = triv121PgTblLdMinSize(*pmemsize); + ldPtSize++; /* double this amount -- then why? */ + + /* allocate the page table at the top of the physical + * memory - THIS IS NOT AN OPTION - bspstart.c RELIES + * ON THIS LAYOUT! (the size, however may be changed) + */ + if ( (pt = triv121PgTblInit(*pmemsize - (1<<ldPtSize), ldPtSize)) ) { + /* map text and RO data read-only */ + tmp = triv121PgTblMap( + pt, + TRIV121_121_VSID, + 0, + (PAGE_ALIGN((unsigned long)_etext) - 0) >> PG_SHIFT, + 0, /* WIMG */ + TRIV121_PP_RO_PAGE); + if (TRIV121_MAP_SUCCESS != tmp) { + printk("Unable to map page index %i; reverting to BAT0\n", + tmp); + pt = 0; + } else { + /* map the rest (without the page table itself) RW */ + tmp = triv121PgTblMap( + pt, + TRIV121_121_VSID, + (unsigned long)__DATA_START__, + (*pmemsize - (1<<ldPtSize) - (unsigned long)__DATA_START__ )>> PG_SHIFT, + 0, /* WIMG */ + TRIV121_PP_RW_PAGE); + if (TRIV121_MAP_SUCCESS != tmp) { + printk("Unable to map page index %i; reverting to BAT0\n", + tmp); + pt = 0; + } + } + } else { + printk("WARNING: unable to allocate page table, keeping DBAT0\n"); + } + if (pt) { +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Setting up page table mappings; protecting text/read-only data from write access\n"); +#endif + /* SUCCESS; reduce available memory by size of the page table */ + *pmemsize -= (1<<ldPtSize); + } + return pt; +} diff --git a/bsps/powerpc/shared/start/ppc_idle.c b/bsps/powerpc/shared/start/ppc_idle.c new file mode 100644 index 0000000000..44ae87311c --- /dev/null +++ b/bsps/powerpc/shared/start/ppc_idle.c @@ -0,0 +1,106 @@ +/* + * ppc_idle.c + * + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2010, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ +#include <bsp.h> +#include <stdint.h> + +#ifdef BSP_IDLE_TASK_BODY + +/* Provide an idle-task body which switches the + * CPU into power-save mode when idle. Any exception + * (including an interrupt/external-exception) + * wakes it up. + * + * IIRC - this cannot be used on real hardware due + * to errata on many chips which is a real + * pity. However, when used under qemu it + * saves host-CPU cycles. + * While qemu-0.12.4 needed to be patched + * (would otherwise hang because an exception + * didn't clear MSR_POW) qemu-0.14.1 seems + * to work fine. + */ + +#include <rtems/powerpc/registers.h> +#include <libcpu/cpuIdent.h> +#include <libcpu/spr.h> + +SPR_RW(HID0) + +void * +bsp_ppc_idle_task_body(uintptr_t ignored) +{ +uint32_t msr; + + switch ( current_ppc_cpu ) { + + case PPC_7400: + case PPC_7455: + case PPC_7457: + /* Must enable NAP mode in HID0 for MSR_POW to work */ + _write_HID0( _read_HID0() | HID0_NAP ); + break; + + default: + break; + } + + for ( ;; ) { + _CPU_MSR_GET(msr); + msr |= MSR_POW; + asm volatile( + "1: sync \n" + " mtmsr %0 \n" + " isync \n" + " b 1b \n" + ::"r"(msr) + ); + } + + return 0; +} + +#endif diff --git a/bsps/powerpc/shared/start/probeMemEnd.c b/bsps/powerpc/shared/start/probeMemEnd.c new file mode 100644 index 0000000000..73b85d4709 --- /dev/null +++ b/bsps/powerpc/shared/start/probeMemEnd.c @@ -0,0 +1,219 @@ +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2005, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ + +#include <bsp.h> +#include <libcpu/spr.h> +#include <libcpu/cpuIdent.h> +#include <rtems/bspIo.h> +#include <inttypes.h> + +/* Simple memory probing routine + * + * - call from MMU-disabled section to avoid having to + * set up mappings. + * NOTE: this implies WIMG = 0011 + * - call AFTER image is at its destination and PRIOR + * to setting up the heap or using any memory beyond + * __rtems_end, i.e., the probing algorithm may safely + * tamper with memory > __rtems_end. + * - MUST lock caches since we're gonna hit space with + * no memory attached. + * + * ASSUMPTIONS: + * o image occupies addresses between 0..__rtems_end + * o memory size is a multiple of 1<<LD_MEM_PROBE_STEP + * + * CAVEATS: + * o all caches must be disabled or locked (some + * boards really don't like it if you try to + * cache physical addresses with nothing attached) + * and this is highly CPU dependent :-(... + * + * - RETURNS size of memory detected in bytes or 0 on + * error. + */ + +/* declare as an array so the compiler doesn't generate + * a reloc to .sdata & friends + */ +extern uint32_t __rtems_end[]; + +#ifndef LD_MEM_PROBE_STEP +#define LD_MEM_PROBE_STEP (24) /* 16MB */ +#endif + +#define TAG 0xfeedcafe + +#define __DO_ALIGN(a, s) (((uint32_t)(a) + (s)-1) & ~((s)-1)) +#define __ALIGN(a) __DO_ALIGN(a, (1<<LD_MEM_PROBE_STEP)) + +#define SWITCH_MSR(msr) \ + do { \ + register uint32_t __rr; \ + asm volatile( \ + " mtsrr1 %0 \n" \ + " bl 1f \n" \ + "1: mflr %0 \n" \ + " addi %0, %0, 1f-1b \n"\ + " mtsrr0 %0 \n" \ + " sync \n" \ + " rfi \n" \ + "1: \n" \ + :"=b&"(__rr) \ + :"0"(msr) \ + :"lr","memory" \ + ); \ + } while (0) + +SPR_RW(L2CR) +SPR_RW(L3CR) +SPR_RO(PPC_PVR) +SPR_RW(HID0) + + +/* Shouldn't matter if the caches are enabled or not... */ + +/* FIXME: This should go into libcpu, really... */ +static int +CPU_lockUnlockCaches(register int doLock) +{ +register uint32_t v, x; + if ( _read_MSR() & MSR_VE ) { +#define DSSALL 0x7e00066c /* dssall opcode */ + __asm__ volatile(" .long %0"::"i"(DSSALL)); +#undef DSSALL + } + asm volatile("sync"); + switch ( _read_PPC_PVR()>>16 ) { + default: printk(__FILE__" CPU_lockUnlockCaches(): unknown CPU (PVR = 0x%08" PRIx32 ")\n",_read_PPC_PVR()); + return -1; + case PPC_750: printk("CPU_lockUnlockCaches(): Can't lock L2 on a mpc750, sorry :-(\n"); + return -2; /* cannot lock L2 :-( */ + case PPC_7455: + case PPC_7457: + v = _read_L3CR(); + x = 1<<(31-9); + v = doLock ? v | x : v & ~x; + _write_L3CR(v); + + v = _read_L2CR(); + x = 1<<(31-11); + v = doLock ? v | x : v & ~x; + _write_L2CR(v); + break; + + case PPC_7400: + v = _read_L2CR(); + x = 1<<(31-21); + v = doLock ? v | x : v & ~x; + _write_L2CR(v); + break; + case PPC_603: + case PPC_604: + case PPC_604e: + break; + } + + v = _read_HID0(); + x = 1<<(31-19); + v = doLock ? v | x : v & ~x; + _write_HID0(v); + asm volatile("sync":::"memory"); + return 0; +} + +uint32_t +probeMemoryEnd(void) +{ +register volatile uint32_t *probe; +register uint32_t scratch; +register uint32_t tag = TAG; +register uint32_t flags; + + probe = (volatile uint32_t *)__ALIGN(__rtems_end); + + /* Start with some checks. We avoid using any services + * such as 'printk' so we can run at a very early stage. + * Also, we *try* to avoid to really rely on the memory + * being unused by restoring the probed locations and + * keeping everything in registers. Hence we could + * even probe our own stack :-) + */ + + if ( CPU_lockUnlockCaches(1) ) + return 0; + + _CPU_MSR_GET(flags); + + SWITCH_MSR( flags & ~(MSR_EE|MSR_DR|MSR_IR) ); + + for ( ; (uint32_t)probe ; probe += (1<<LD_MEM_PROBE_STEP)/sizeof(*probe) ) { + + /* see if by chance our tag is already there */ + if ( tag == (scratch = *probe) ) { + /* try another tag */ + tag = ~tag; + } + *probe = tag; + + /* make sure it's written out */ + asm volatile ("sync":::"memory"); + + /* try to read back */ + if ( tag != *probe ) { + break; + } + /* restore */ + *probe = scratch; + /* make sure the icache is not contaminated */ + asm volatile ("sync; icbi 0, %0"::"r"(probe):"memory"); + } + + SWITCH_MSR(flags); + + CPU_lockUnlockCaches(0); + + return (uint32_t) probe; +} diff --git a/bsps/powerpc/shared/start/sbrk.c b/bsps/powerpc/shared/start/sbrk.c new file mode 100644 index 0000000000..f17a1511e4 --- /dev/null +++ b/bsps/powerpc/shared/start/sbrk.c @@ -0,0 +1,147 @@ +/* + * sbrk.c + * + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2002, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ + +/* + * Hack around the 32bit powerpc 32M problem: + * + * GCC by default uses relative branches which can not jump + * farther than 32M. Hence all program text is confined to + * a single 32M segment. + * This hack gives the RTEMS malloc region all memory below + * 32M at startup. Only when this region is exhausted will sbrk + * add more memory. Loading modules may fail at that point, hence + * the user is expected to load all modules at startup _prior_ + * to malloc()ing lots of memory... + * + * NOTE: it would probably be better to have a separate region + * for module code. + */ + +#include <errno.h> +#include <unistd.h> + +#include <bsp/bootcard.h> + +#define INVALID_REMAINING_START ((uintptr_t) -1) + +static uintptr_t remaining_start = INVALID_REMAINING_START; +static uintptr_t remaining_size = 0; + +/* App. may provide a value by defining the BSP_sbrk_policy + * variable. + * + * (-1) -> give all memory to the heap at initialization time + * > 0 -> value used as sbrk amount; initially give 32M + * 0 -> limit memory effectively to 32M. + * + */ +extern uintptr_t BSP_sbrk_policy[] __attribute__((weak)); + +#define LIMIT_32M 0x02000000 + +ptrdiff_t bsp_sbrk_init(Heap_Area *area, uintptr_t min_size) +{ + uintptr_t rval = 0; + uintptr_t policy; + uintptr_t remaining_end; + + remaining_start = (uintptr_t) area->begin; + remaining_size = area->size; + remaining_end = remaining_start + remaining_size; + + if (remaining_start < LIMIT_32M && + remaining_end > LIMIT_32M && + min_size <= LIMIT_32M - remaining_start) { + /* clip at LIMIT_32M */ + rval = remaining_end - LIMIT_32M; + area->size = LIMIT_32M - remaining_start; + remaining_start = LIMIT_32M; + remaining_size = rval; + } + + policy = (0 == BSP_sbrk_policy[0] ? (uintptr_t)(-1) : BSP_sbrk_policy[0]); + switch ( policy ) { + case (uintptr_t)(-1): + area->size += rval; + remaining_start = (uintptr_t) area->begin + area->size; + remaining_size = 0; + break; + + case 0: + remaining_size = 0; + break; + + default: + if ( rval > policy ) + rval = policy; + break; + } + + return (ptrdiff_t) (rval <= PTRDIFF_MAX ? rval : rval / 2); +} + +/* + * This is just so the sbrk test can force its magic. All normal applications + * should just use the default implementation in this file. + */ +void *sbrk(ptrdiff_t incr) __attribute__ (( weak, alias("bsp_sbrk") )); +static void *bsp_sbrk(ptrdiff_t incr) +{ + void *rval=(void*)-1; + + if ( remaining_start != INVALID_REMAINING_START && incr <= remaining_size) { + remaining_size-=incr; + rval = (void *) remaining_start; + remaining_start += incr; + } else { + errno = ENOMEM; + } + #ifdef DEBUG + printk("************* SBRK 0x%08x (ret 0x%08x) **********\n", incr, rval); + #endif + return rval; +} diff --git a/bsps/powerpc/shared/start/zerobss.c b/bsps/powerpc/shared/start/zerobss.c new file mode 100644 index 0000000000..b3ab1ad9d9 --- /dev/null +++ b/bsps/powerpc/shared/start/zerobss.c @@ -0,0 +1,42 @@ +/* + * zero the various bss areas. + */ + +/* + * COPYRIGHT (c) 1989-2014. + * 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. + * + * Modified to support the MCP750. + * Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr + */ + +#include <string.h> +#include <bsp.h> + +/* prevent these from being accessed in the short data areas */ +extern unsigned long __bss_start[], __SBSS_START__[], __SBSS_END__[]; +extern unsigned long __SBSS2_START__[], __SBSS2_END__[]; +extern unsigned long __bss_end[]; + +void zero_bss(void) +{ + memset( + __SBSS_START__, + 0, + ((unsigned) __SBSS_END__) - ((unsigned)__SBSS_START__) + ); + memset( + __SBSS2_START__, + 0, + ((unsigned) __SBSS2_END__) - ((unsigned)__SBSS2_START__) + ); + memset( + __bss_start, + 0, + ((unsigned) __bss_end) - ((unsigned)__bss_start) + ); +} diff --git a/bsps/powerpc/ss555/start/bsp_specs b/bsps/powerpc/ss555/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/ss555/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/ss555/start/bspstart.c b/bsps/powerpc/ss555/start/bspstart.c new file mode 100644 index 0000000000..f47ca7d5be --- /dev/null +++ b/bsps/powerpc/ss555/start/bspstart.c @@ -0,0 +1,97 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * COPYRIGHT (c) 1989-2007. + * 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. + * + * SS555 port sponsored by Defence Research and Development Canada - Suffield + * Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca) + * + * Derived from c/src/lib/libbsp/powerpc/mbx8xx/startup/bspstart.c: + * + * Modifications for MBX860: + * Copyright (c) 1999, National Research Council of Canada + */ + +#include <rtems/bspIo.h> +#include <rtems/counter.h> +#include <bsp/bootcard.h> +#include <rtems/powerpc/powerpc.h> + +#include <libcpu/cpuIdent.h> +#include <libcpu/spr.h> + +#include <bsp/irq.h> +#include <bsp.h> + +SPR_RW(SPRG1) + +extern unsigned long intrStackPtr; + +/* + * Driver configuration parameters + */ +uint32_t bsp_clicks_per_usec; +uint32_t bsp_clock_speed; /* Serial clocks per second */ + +/* + * bsp_start() + * + * Board-specific initialization code. Called from the generic boot_card() + * function defined in rtems/c/src/lib/libbsp/shared/main.c. That function + * does some of the board independent initialization. It is called from the + * SS555 entry point _start() defined in + * rtems/c/src/lib/libbsp/powerpc/ss555/start/start.S + * + * _start() has set up a stack, has zeroed the .bss section, has set up the + * .data section from contents stored in ROM, has turned off interrupts, + * and placed the processor in the supervisor mode. boot_card() has left + * the processor in that state when bsp_start() was called. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + */ +void bsp_start(void) +{ + register unsigned char* intrStack; + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function stores the result in global variables so that it can be used + * later. + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + /* + * Initialize some SPRG registers related to irq handling + */ + intrStack = (((unsigned char*)&intrStackPtr) - PPC_MINIMUM_STACK_FRAME_SIZE); + _write_SPRG1((unsigned int)intrStack); + + /* + * Install our own set of exception vectors + */ + initialize_exceptions(); + + /* + * initialize the device driver parameters + */ + bsp_clicks_per_usec = BSP_CRYSTAL_HZ / 4 / 1000000; + bsp_clock_speed = BSP_CLOCK_HZ; /* for SCI baud rate generator */ + rtems_counter_initialize_converter(BSP_CRYSTAL_HZ / 4); + + /* + * Initalize RTEMS IRQ system + */ + BSP_rtems_irq_mng_init(0); +} diff --git a/bsps/powerpc/ss555/start/iss555.c b/bsps/powerpc/ss555/start/iss555.c new file mode 100644 index 0000000000..034ae74b1d --- /dev/null +++ b/bsps/powerpc/ss555/start/iss555.c @@ -0,0 +1,148 @@ +/* + * Intec SS555 initialization routines. + */ + +/* + * SS555 port sponsored by Defence Research and Development Canada - Suffield + * Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca) + * + * Derived from c/src/lib/libbsp/powerpc/mbx8xx/startup/imbx8xx.c: + * + * Copyright (c) 1999, National Research Council of Canada + * + * 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> + +SPR_RW(ICTRL); +SPR_RW(PPC_DEC); +SPR_RW(TBWU); +SPR_RW(TBWL); +SPR_RO(IMMR); +SPR_RW(MI_GRA); +SPR_RW(L2U_GRA); +SPR_RW(BBCMCR); + +extern char int_ram_top[]; /* top of internal ram */ + +/* + * Initialize SS555 + */ +void _InitSS555 (void) +{ + register uint32_t plprcr, msr; + + /* + * Initialize the System Protection Control Register (SYPCR). + * The SYPCR can only be written once after Reset. + */ + usiu.sypcr = + USIU_SYPCR_SWTC(WATCHDOG_TIMEOUT) /* set watchdog timeout */ + | USIU_SYPCR_BMT(0xFF) /* set bus monitor timeout */ + | USIU_SYPCR_BME /* enable bus monitor */ + | USIU_SYPCR_SWF /* watchdog halted in freeze */ +#if WATCHDOG_TIMEOUT != 0xFFFF + | USIU_SYPCR_SWE /* enable watchdog */ +#endif + | USIU_SYPCR_SWRI /* watchdog forces reset */ + | USIU_SYPCR_SWP; /* prescale watchdog by 2048 */ + + TICKLE_WATCHDOG(); /* restart watchdog timer */ + + /* + * Re-tune the PLL to the desired system clock frequency. + */ + usiu.plprck = USIU_UNLOCK_KEY; /* unlock PLPRCR */ + usiu.plprcr = + USIU_PLPRCR_TEXPS /* assert TEXP always */ + | USIU_PLPRCR_MF(BSP_CLOCK_HZ / BSP_CRYSTAL_HZ); + /* PLL multiplication factor */ + usiu.plprck = 0; /* lock PLPRCR */ + + while (((plprcr = usiu.plprcr) & USIU_PLPRCR_SPLS) == 0) + ; /* wait for PLL to re-lock */ + + /* + * Enable the timebase and decrementer, then initialize decrementer + * register to a large value to guarantee that a decrementer interrupt + * will not be generated before the kernel is fully initialized. + * Initialize the timebase register to zero. + */ + usiu.tbscrk = USIU_UNLOCK_KEY; + usiu.tbscr |= USIU_TBSCR_TBE; /* enable time base and decrementer */ + usiu.tbscrk = 0; + + usiu.tbk = USIU_UNLOCK_KEY; + _write_PPC_DEC(0x7FFFFFFF); + _write_TBWU(0x00000000 ); + _write_TBWL(0x00000000 ); + usiu.tbk = 0; + + /* + * Run the Inter-Module Bus at full speed. + */ + imb.uimb.umcr &= ~UIMB_UMCR_HSPEED; + + /* + * Initialize Memory Controller for External RAM + * + * Initialize the Base and Option Registers (BR0-BR7 and OR0-OR7). Note + * that for all chip selects, ORx should be programmed before BRx. + * + * If booting from internal flash ROM, configure the external RAM to + * extend the internal RAM. If booting from external RAM, leave it at + * zero but set it up appropriately. + */ + usiu.memc[0]._or = + USIU_MEMC_OR_512K /* bank size */ + | USIU_MEMC_OR_SCY(0) /* wait states in first beat of burst */ + | USIU_MEMC_OR_BSCY(0); /* wait states in subsequent beats */ + + usiu.memc[0]._br = + USIU_MEMC_BR_BA(_read_IMMR() & IMMR_FLEN + ? (uint32_t)int_ram_top : 0) /* base address */ + | USIU_MEMC_BR_PS32 /* 32-bit data bus */ + | USIU_MEMC_BR_TBDIP /* toggle bdip */ + | USIU_MEMC_BR_V; /* base register valid */ + + /* + * Initialize Memory Controller for External CPLD + * + * The SS555 board includes a CPLD to control on-board features and + * off-board devices. (Configuration taken from Intec's hwhook.c) + */ + usiu.memc[3]._or = + USIU_MEMC_OR_16M /* bank size */ + | USIU_MEMC_OR_CSNT /* negate CS/WE early */ + | USIU_MEMC_OR_ACS_HALF /* assert CS half cycle after address */ + | USIU_MEMC_OR_SCY(15) /* wait states in first beat of burst */ + | USIU_MEMC_OR_TRLX; /* relaxed timing */ + + usiu.memc[3]._br = + USIU_MEMC_BR_BA(&cpld) /* base address */ + | USIU_MEMC_BR_PS16 /* 16-bit data bus */ + | USIU_MEMC_BR_BI /* inhibit bursting */ + | USIU_MEMC_BR_V; /* base register valid */ + + /* + * Disable show cycles and serialization so that burst accesses will work + * properly. A different value, such as 0x0, may be more appropriate for + * debugging, but can be set with the debugger, if needed. + */ + _write_ICTRL(0x00000007); + + /* + * Set up Burst Buffer Controller (BBC) + */ + _write_BBCMCR( + BBCMCR_ETRE /* enable exception relocation */ + | BBCMCR_BE); /* enable burst accesses */ + _isync; + + _CPU_MSR_GET(msr); + msr |= MSR_IP; /* set prefix for exception relocation */ + _CPU_MSR_SET(msr); +} diff --git a/bsps/powerpc/ss555/start/linkcmds b/bsps/powerpc/ss555/start/linkcmds new file mode 100644 index 0000000000..8282d6c605 --- /dev/null +++ b/bsps/powerpc/ss555/start/linkcmds @@ -0,0 +1,328 @@ +/* + * Linker command file for Intec SS555 board + * + * When debugging, we assume that the internal flash ROM will be replaced by + * the external RAM on the SS555 board. All sections are stacked starting + * at address zero. Nothing is placed in the internal RAM, since it's not + * contiguous with the external SRAM when the external RAM is placed at + * zero. + * + * For final production, we assume that the .text section will be burned + * into flash ROM starting at address zero. The .data, .bss, heap, and + * workspace will reside in RAM, starting at the beginning of the internal + * RAM. The system startup code will configure the external RAM to begin + * where the internal RAM ends, so as to make one large RAM block. + */ + +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") +OUTPUT_ARCH(powerpc) +ENTRY(start) +EXTERN(_vectors) + +int_ram_org = 0x003F9800; /* base of internal RAM */ +int_ram_top = 0x00400000; /* top of internal RAM */ +ext_ram_size = 0x00080000; /* size of external RAM */ + +RamBase = DEFINED(_RamBase) ? RamBase : 0x003F9800; +RamSize = DEFINED(_RamSize) ? RamSize : 0x00486800; +HeapSize = DEFINED(_HeapSize) ? HeapSize : 0x0; + +SECTIONS +{ + .vectors 0x0: + { + /* + * For the MPC555, we use the compressed vector table format which puts + * all of the exception vectors before 0x100. + */ + *(.vectors) + } + + .text 0x100: + { + /* Read-only sections, merged into text segment: */ + + text.start = .; + + /* Entry point is the .entry section */ + *(.entry) + *(.entry2) + + /* Actual code */ + *(.text*) + + /* C++ constructors/destructors */ + *(.gnu.linkonce.t*) + + /* Initialization and finalization code. + * + * Various files can provide initialization and finalization functions. + * The bodies of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues from + * ecrti.o and function epilogues from ecrtn.o. ecrti.o must be linked + * first; ecrtn.o must be linked last. Because these are wildcards, it + * doesn't matter if the user does not actually link against ecrti.o and + * ecrtn.o; the linker won't look for a file to match a wildcard. The + * wildcard also means that it doesn't matter which directory ecrti.o + * and ecrtn.o are in. + */ + PROVIDE (_init = .); + *ecrti.o(.init) + *(.init) + *ecrtn.o(.init) + + PROVIDE (_fini = .); + *ecrti.o(.fini) + *(.fini) + *ecrtn.o(.init) + + /* + * C++ constructors and destructors for static objects. + * PowerPC EABI does not use crtstuff yet, so we build "old-style" + * constructor and destructor lists that begin with the list length + * end terminate with a NULL entry. + */ + PROVIDE (__CTOR_LIST__ = .); + /* LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) */ + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + LONG(0) + PROVIDE (__CTOR_END__ = .); + + PROVIDE (__DTOR_LIST__ = .); + /* LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) */ + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + LONG(0) + PROVIDE (__DTOR_END__ = .); + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* Exception frame info */ + *(.eh_frame) + + /* Miscellaneous read-only data */ + _rodata_start = . ; + *(.gnu.linkonce.r*) + *(.lit) + *(.shdata) + *(.rodata*) + *(.rodata1) + KEEP (*(SORT(.rtemsroset.*))) + *(.descriptors) + *(rom_ver) + _erodata = .; + + /* Various possible names for the end of the .text section */ + etext = ALIGN(0x10); + _etext = .; + _endtext = .; + text.end = .; + PROVIDE (etext = .); + PROVIDE (__etext = .); + } + text.size = text.end - text.start; + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + + /* + * .data section contents, copied to RAM at system startup. + */ + . = ALIGN(0x20); + data.contents.start = .; + } + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } + _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)); + + /* + * If debugging, stack the read/write sections directly after the text + * section. Otherwise, stack the read/write sections starting at base of + * internal RAM. + */ + . = DEFINED(RTEMS_DEBUG) ? . : int_ram_org; + + .data : AT (data.contents.start) + { + data.start = .; + + *(.data) + *(.data.*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.data1) + + PROVIDE (__SDATA_START__ = .); + *(.sdata .sdata.* .gnu.linkonce.s.*) + PROVIDE (__SDATA_END__ = .); + + PROVIDE (__EXCEPT_START__ = .); + *(.gcc_except_table*) + PROVIDE (__EXCEPT_END__ = .); + + PROVIDE(__GOT_START__ = .); + *(.got.plt) + *(.got) + PROVIDE(__GOT_END__ = .); + + *(.got1) + + PROVIDE (__GOT2_START__ = .); + PROVIDE (_GOT2_START_ = .); + *(.got2) + PROVIDE (__GOT2_END__ = .); + PROVIDE (_GOT2_END_ = .); + + PROVIDE (__FIXUP_START__ = .); + PROVIDE (_FIXUP_START_ = .); + *(.fixup) + PROVIDE (_FIXUP_END_ = .); + PROVIDE (__FIXUP_END__ = .); + + /* We want the small data sections together, so single-instruction + * offsets can access them all. + */ + PROVIDE (__SDATA2_START__ = .); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + PROVIDE (__SDATA2_END__ = .); + + data.end = .; + } + data.size = data.end - data.start; + + bss.start = .; + .sbss : + { + PROVIDE (__sbss_start = .); PROVIDE (___sbss_start = .); + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + PROVIDE (__sbss_end = .); PROVIDE (___sbss_end = .); + } + .bss : + { + *(.dynbss) + *(.bss .bss* .gnu.linkonce.b*) + *(COMMON) + . = ALIGN(4); + } + bss.end = .; + bss.size = bss.end - bss.start; + + PROVIDE(_end = bss.end); + + /* + * Initialization stack + */ + InitStack_start = ALIGN(0x10); + . += 0x1000; + initStack = .; + PROVIDE(initStackPtr = initStack); + + /* + * Interrupt stack + */ + IntrStack_start = ALIGN(0x10); + . += 0x4000; + intrStack = .; + PROVIDE(intrStackPtr = intrStack); + + /* + * Work Area + * + * The Work Area is configured at run-time to use all available memory. It + * begins just after the end of the Workspace and continues to the end of + * the external RAM. + */ + . = DEFINED(RTEMS_DEBUG) ? 0 + ext_ram_size : int_ram_top + ext_ram_size; + WorkAreaBase = .; + + + /* + * Internal I/O devices + */ + .usiu 0x002FC000: /* unified system interface unit */ + { + usiu = .; + } + + .imb 0x00300000: /* inter-module bus and devices */ + { + imb = .; + } + + .sram 0x00380000: /* internal SRAM control registers */ + { + sram = .; + } + + /* + * SS555 external devices managed by on-board CPLD + */ + .cpld 0xFF000000: /* SS555 external CPLD devices */ + { + cpld = .; + } + + + /* 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) } + .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) } + /* These must appear regardless of . */ +} diff --git a/bsps/powerpc/ss555/start/tm27supp.c b/bsps/powerpc/ss555/start/tm27supp.c new file mode 100644 index 0000000000..4c1660ff70 --- /dev/null +++ b/bsps/powerpc/ss555/start/tm27supp.c @@ -0,0 +1,14 @@ +/* + * Support routines for TM27 + */ + +#include <bsp.h> + +rtems_irq_connect_data tm27IrqData = { + CPU_USIU_EXT_IRQ_7, + (rtems_irq_hdl)0, + NULL, + NULL, + NULL +}; + diff --git a/bsps/powerpc/t32mppc/start/bsp_specs b/bsps/powerpc/t32mppc/start/bsp_specs new file mode 100644 index 0000000000..f8bbffbdf6 --- /dev/null +++ b/bsps/powerpc/t32mppc/start/bsp_specs @@ -0,0 +1,11 @@ +%rename endfile old_endfile +%rename startfile old_startfile +%rename link old_link + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} + diff --git a/bsps/powerpc/t32mppc/start/bspreset.c b/bsps/powerpc/t32mppc/start/bspreset.c new file mode 100644 index 0000000000..9472192fab --- /dev/null +++ b/bsps/powerpc/t32mppc/start/bspreset.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 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 <stdbool.h> + +#include <bsp/bootcard.h> + +void bsp_reset(void) +{ + while (true) { + /* Do nothing */ + } +} diff --git a/bsps/powerpc/t32mppc/start/bspstart.c b/bsps/powerpc/t32mppc/start/bspstart.c new file mode 100644 index 0000000000..5fc36b4019 --- /dev/null +++ b/bsps/powerpc/t32mppc/start/bspstart.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2012, 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/config.h> +#include <rtems/counter.h> + +#include <bsp.h> +#include <bsp/vectors.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> + +LINKER_SYMBOL(bsp_exc_vector_base); + +/* + * Configuration parameter for clock driver. The Trace32 PowerPC simulator has + * an odd decrementer frequency. The time base frequency is one tick per + * instruction. The decrementer frequency is one tick per ten instructions. + * The clock driver assumes that the time base and decrementer frequencies are + * equal. For now we simulate processor that issues 10000000 instructions per + * second. + */ +uint32_t bsp_time_base_frequency = 10000000; + +#define MTIVPR(base) \ + __asm__ volatile ("mtivpr %0" : : "r" (base)) + +#define VECTOR_TABLE_ENTRY_SIZE 16 + +#define MTIVOR(vec, offset) \ + do { \ + __asm__ volatile ("mtspr " RTEMS_XSTRING(vec) ", %0" : : "r" (offset)); \ + offset += VECTOR_TABLE_ENTRY_SIZE; \ + } while (0) + +static void t32mppc_initialize_exceptions(void *interrupt_stack_begin) +{ + uintptr_t addr; + + ppc_exc_initialize_interrupt_stack( + (uintptr_t) interrupt_stack_begin, + rtems_configuration_get_interrupt_stack_size() + ); + + addr = (uintptr_t) bsp_exc_vector_base; + MTIVPR(addr); + MTIVOR(BOOKE_IVOR0, addr); + MTIVOR(BOOKE_IVOR1, addr); + MTIVOR(BOOKE_IVOR2, addr); + MTIVOR(BOOKE_IVOR3, addr); + MTIVOR(BOOKE_IVOR4, addr); + MTIVOR(BOOKE_IVOR5, addr); + MTIVOR(BOOKE_IVOR6, addr); + MTIVOR(BOOKE_IVOR7, addr); + MTIVOR(BOOKE_IVOR8, addr); + MTIVOR(BOOKE_IVOR9, addr); + MTIVOR(BOOKE_IVOR10, addr); + MTIVOR(BOOKE_IVOR11, addr); + MTIVOR(BOOKE_IVOR12, addr); + MTIVOR(BOOKE_IVOR13, addr); + MTIVOR(BOOKE_IVOR14, addr); + MTIVOR(BOOKE_IVOR15, addr); + MTIVOR(BOOKE_IVOR32, addr); + MTIVOR(BOOKE_IVOR33, addr); + MTIVOR(BOOKE_IVOR34, addr); + MTIVOR(BOOKE_IVOR35, addr); +} + +void bsp_start(void) +{ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + rtems_counter_initialize_converter(bsp_time_base_frequency); + + t32mppc_initialize_exceptions(bsp_section_work_begin); + bsp_interrupt_initialize(); +} diff --git a/bsps/powerpc/t32mppc/start/linkcmds.t32mppc b/bsps/powerpc/t32mppc/start/linkcmds.t32mppc new file mode 100644 index 0000000000..02367f57d0 --- /dev/null +++ b/bsps/powerpc/t32mppc/start/linkcmds.t32mppc @@ -0,0 +1,27 @@ +EXTERN (__vectors) + +MEMORY { + RAM : ORIGIN = 0x0, LENGTH = 128M + EMPTY : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", 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_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", RAM); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/tqm8xx/start/bsp_specs b/bsps/powerpc/tqm8xx/start/bsp_specs new file mode 100644 index 0000000000..b5cd6764ce --- /dev/null +++ b/bsps/powerpc/tqm8xx/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn%O%s} diff --git a/bsps/powerpc/tqm8xx/start/bspgetworkarea.c b/bsps/powerpc/tqm8xx/start/bspgetworkarea.c new file mode 100644 index 0000000000..4a0a4db534 --- /dev/null +++ b/bsps/powerpc/tqm8xx/start/bspgetworkarea.c @@ -0,0 +1,34 @@ +/** + * @file + * + * @ingroup tqm8xx + * + * @brief Source for BSP Get Work Area Memory + */ + +/* + * Copyright (c) 2008, 2018 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/linker-symbols.h> + +void bsp_work_area_initialize(void) +{ + char *ram_end = (char *) (TQM_BD_INFO.sdram_size - (uint32_t)TopRamReserved); + void *area_start = bsp_section_work_begin; + uintptr_t area_size = (uintptr_t) ram_end - (uintptr_t) area_start; + + bsp_work_area_initialize_default( area_start, area_size ); +} diff --git a/bsps/powerpc/tqm8xx/start/bspstart.c b/bsps/powerpc/tqm8xx/start/bspstart.c new file mode 100644 index 0000000000..df0581ce77 --- /dev/null +++ b/bsps/powerpc/tqm8xx/start/bspstart.c @@ -0,0 +1,156 @@ +/** + * @file + * + * @ingroup tqm8xx + * + * @brief Source for BSP startup code. + */ + +/* + * Copyright (c) 2008 + * 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 <stdlib.h> + +#include <rtems.h> +#include <rtems/counter.h> + +#include <libcpu/powerpc-utility.h> + +#include <bsp.h> +#include <bsp/vectors.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> + +#ifdef BSP_HAS_TQMMON +/* + * FIXME: TQ Monitor structure + */ +#endif /* BSP_HAS_TQMMON */ + +/* Configuration parameters for console driver, ... */ +uint32_t BSP_bus_frequency; + +/* Configuration parameter for clock driver */ +uint32_t bsp_time_base_frequency; + +/* Legacy */ +uint32_t bsp_clicks_per_usec; /* for PIT driver: OSCCLK */ + +static const char *bsp_tqm_get_cib_string( const char *cib_id) +{ + char srch_pattern[10] = ""; + char *fnd_str; + /* + * create search pattern + */ + strcat(srch_pattern,"-"); + strncat(srch_pattern, + cib_id, + sizeof(srch_pattern)-1-strlen(srch_pattern)); + strncat(srch_pattern, + " ", + sizeof(srch_pattern)-1-strlen(srch_pattern)); + /* + * search for pattern in info block (CIB) + */ + fnd_str = strstr((const char *)TQM_CONF_INFO_BLOCK_ADDR,srch_pattern); + + if (fnd_str == NULL) { + return NULL; + } + else { + /* + * found? then advance behind search pattern + */ + return fnd_str + strlen(srch_pattern); + } +} + +static rtems_status_code bsp_tqm_get_cib_uint32( const char *cib_id, + uint32_t *result) +{ + const char *item_ptr; + char *end_ptr; + item_ptr = bsp_tqm_get_cib_string(cib_id); + if (item_ptr == NULL) { + return RTEMS_INVALID_ID; + } + /* + * convert string to uint32 + */ + *result = strtoul(item_ptr,&end_ptr,10); + return RTEMS_SUCCESSFUL; +} + +void bsp_start( void) +{ + + uintptr_t interrupt_stack_start = (uintptr_t) bsp_interrupt_stack_start; + uintptr_t interrupt_stack_size = (uintptr_t) bsp_interrupt_stack_end + - interrupt_stack_start; + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function stores the result in global variables so that it can be used + * later... + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + /* Basic CPU initialization */ + cpu_init(); + + /* + * Enable instruction and data caches. Do not force writethrough mode. + */ + +#if BSP_INSTRUCTION_CACHE_ENABLED + rtems_cache_enable_instruction(); +#endif + +#if BSP_DATA_CACHE_ENABLED + rtems_cache_enable_data(); +#endif + + /* + * This is evaluated during runtime, so it should be ok to set it + * before we initialize the drivers. + */ + + /* Initialize some device driver parameters */ + /* + * get the (internal) bus frequency + * NOTE: the external bus may be clocked at a lower speed + * but this does not concern the internal units like PIT, + * DEC, baudrate generator etc) + */ + if (RTEMS_SUCCESSFUL != + bsp_tqm_get_cib_uint32("cu", + &BSP_bus_frequency)) { + rtems_panic("Cannot determine BUS frequency\n"); + } + + bsp_time_base_frequency = BSP_bus_frequency / 16; + bsp_clicks_per_usec = bsp_time_base_frequency / 1000000; + rtems_counter_initialize_converter(bsp_time_base_frequency); + + /* Initialize exception handler */ + ppc_exc_initialize(interrupt_stack_start, interrupt_stack_size); + + /* Initalize interrupt support */ + bsp_interrupt_initialize(); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Exit from bspstart\n"); +#endif +} diff --git a/bsps/powerpc/tqm8xx/start/cpuinit.c b/bsps/powerpc/tqm8xx/start/cpuinit.c new file mode 100644 index 0000000000..5d34e07cfb --- /dev/null +++ b/bsps/powerpc/tqm8xx/start/cpuinit.c @@ -0,0 +1,133 @@ +/* + * cpuinit.c + * + * TQM8xx initialization routines. + * derived from MBX8xx BSP + * adapted to TQM8xx by Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> + * + * Copyright (c) 1999, National Research Council of Canada + * + * 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/tqm.h> + + +/* + * Initialize TQM8xx + */ +void _InitTQM8xx (void) +{ + register uint32_t r1; + + /* + * Initialize the Instruction Support Control Register (ICTRL) to a + * an appropriate value for normal operation. A different value, + * such as 0x0, may be more appropriate for debugging. + */ + r1 = 0x00000007; + _mtspr( M8xx_ICTRL, r1 ); + + /* + * Disable and invalidate the instruction and data caches. + */ + r1 = M8xx_CACHE_CMD_DISABLE; + _mtspr( M8xx_IC_CST, r1 ); + _isync; + r1 = M8xx_CACHE_CMD_UNLOCKALL; + _mtspr( M8xx_IC_CST, r1 ); + _isync; + r1 = M8xx_CACHE_CMD_INVALIDATE; /* invalidate all */ + _mtspr( M8xx_IC_CST, r1 ); + _isync; + + r1 = M8xx_CACHE_CMD_DISABLE; + _mtspr( M8xx_DC_CST, r1 ); + _isync; + r1 = M8xx_CACHE_CMD_UNLOCKALL; + _mtspr( M8xx_DC_CST, r1 ); + _isync; + r1 = M8xx_CACHE_CMD_INVALIDATE; /* invalidate all */ + _mtspr( M8xx_DC_CST, r1 ); + _isync; + + /* + * Initialize the SIU Module Configuration Register (SIUMCR) + * m8xx.siumcr = 0x00602900, the default value. + */ + m8xx.siumcr = M8xx_SIUMCR_EARP0 | M8xx_SIUMCR_DBGC3 | M8xx_SIUMCR_DBPC0 | + M8xx_SIUMCR_DPC | M8xx_SIUMCR_MLRC2 | M8xx_SIUMCR_SEME; + + /* + * Initialize the System Protection Control Register (SYPCR). + * The SYPCR can only be written once after Reset. + * - Enable bus monitor + * - Disable software watchdog timer + * m8xx.sypcr = 0xFFFFFF88, the default MBX and firmware value. + */ + m8xx.sypcr = M8xx_SYPCR_SWTC(0xFFFF) | M8xx_SYPCR_BMT(0xFF) | + M8xx_SYPCR_BME | M8xx_SYPCR_SWF; + + /* Initialize the SIU Interrupt Edge Level Mask Register (SIEL) */ + m8xx.siel = 0xAAAA0000; /* Default MBX and firmware value. */ + + /* Initialize the Transfer Error Status Register (TESR) */ + m8xx.tesr = 0xFFFFFFFF; /* Default firmware value. */ + + /* Initialize the SDMA Configuration Register (SDCR) */ + m8xx.sdcr = 0x00000001; /* Default firmware value. */ + + /* + * Initialize the Timebase Status and Control Register (TBSCR) + * m8xx.tbscr = 0x00C3, default MBX and firmware value. + */ + m8xx.tbscrk = M8xx_UNLOCK_KEY; /* unlock TBSCR */ + m8xx.tbscr = M8xx_TBSCR_REFA | M8xx_TBSCR_REFB | + M8xx_TBSCR_TBF | M8xx_TBSCR_TBE; + + /* Initialize the Real-Time Clock Status and Control Register (RTCSC) */ + m8xx.rtcsk = M8xx_UNLOCK_KEY; /* unlock RTCSC */ + m8xx.rtcsc = 0x00C3; /* Default MBX and firmware value. */ + + /* Unlock other Real-Time Clock registers */ + m8xx.rtck = M8xx_UNLOCK_KEY; /* unlock RTC */ + m8xx.rtseck = M8xx_UNLOCK_KEY; /* unlock RTSEC */ + m8xx.rtcalk = M8xx_UNLOCK_KEY; /* unlock RTCAL */ + + /* Initialize the Periodic Interrupt Status and Control Register (PISCR) */ + m8xx.piscrk = M8xx_UNLOCK_KEY; /* unlock PISCR */ + m8xx.piscr = 0x0083; /* Default MBX and firmware value. */ + + /* Initialize the System Clock and Reset Control Register (SCCR) + * Set the clock sources and division factors: + * Timebase Source is GCLK2 / 16 + */ + m8xx.sccrk = M8xx_UNLOCK_KEY; /* unlock SCCR */ + m8xx.sccr |= 0x02000000; + + /* Unlock the timebase and decrementer registers. */ + m8xx.tbk = M8xx_UNLOCK_KEY; + /* + * Initialize decrementer register to a large value to + * guarantee that a decrementer interrupt will not be + * generated before the kernel is fully initialized. + */ + r1 = 0x7FFFFFFF; + _mtspr( M8xx_DEC, r1 ); + + /* Initialize the timebase register (TB is 64 bits) */ + r1 = 0x00000000; + _mtspr( M8xx_TBU_WR, r1 ); + _mtspr( M8xx_TBL_WR, r1 ); +} +/* + * further initialization (called from bsp_start) + */ +void cpu_init(void) +{ + /* mmu initialization */ + mmu_init(); +} diff --git a/bsps/powerpc/tqm8xx/start/linkcmds b/bsps/powerpc/tqm8xx/start/linkcmds new file mode 100644 index 0000000000..7171d0230a --- /dev/null +++ b/bsps/powerpc/tqm8xx/start/linkcmds @@ -0,0 +1,43 @@ +/** + * @file + * + * TQM8xx + */ + +TopRamReserved = DEFINED(TopRamReserved) ? TopRamReserved : 0; + +MEMORY { + EMPTY : ORIGIN = 0, LENGTH = 0 + RAM : ORIGIN = 0x10000, LENGTH = 128M - 64k + immr : org = 0xfa200000, l = 16K + ROM : ORIGIN = 0x40000000, LENGTH = 8M +} + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", 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_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", EMPTY); +REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +SECTIONS { + dpram : { + m8xx = .; + _m8xx = .; + /* . += (16 * 1024); this makes the mbx loader crash */ + } >immr +} + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/tqm8xx/start/mmutlbtab.c b/bsps/powerpc/tqm8xx/start/mmutlbtab.c new file mode 100644 index 0000000000..8b1ad90036 --- /dev/null +++ b/bsps/powerpc/tqm8xx/start/mmutlbtab.c @@ -0,0 +1,103 @@ +/*===============================================================*\ +| Project: RTEMS TQM8xx BSP | ++-----------------------------------------------------------------+ +| This file has been adapted to MPC8xx by | +| Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | +| Copyright (c) 2008 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | +| | +| See the other copyright notice below for the original parts. | ++-----------------------------------------------------------------+ +| 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. | +| | ++-----------------------------------------------------------------+ +| this file contains the console driver | +\*===============================================================*/ +/* derived from: */ +/* + * mmutlbtab.c + * + * Copyright (c) 1999, National Research Council of Canada + * + * 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 <mpc8xx/mmu.h> +/* + * This MMU_TLB_table is used to statically initialize the Table Lookaside + * Buffers in the MMU of the TQM8xx board. + * + * We initialize the entries in both the instruction and data TLBs + * with the same values - a few bits relevant to the data TLB are unused + * in the instruction TLB. + * + * An Effective Page Number (EPN), Tablewalk Control Register (TWC) and + * Real Page Number (RPN) value are supplied in the table for each TLB entry. + * + * The instruction and data TLBs each can hold 32 entries, so _TLB_Table must + * not have more than 32 lines in it! + * + * We set up the virtual memory map so that virtual address of a + * location is equal to its real address. + */ +MMU_TLB_table_t MMU_TLB_table[] = { + /* + * DRAM: Start address 0x00000000, 128M, + * ASID=0x0, APG=0x0, not guarded memory, copyback data cache policy, + * R/W,X for all, no ASID comparison, not cache-inhibited. + * EPN TWC RPN + */ + { 0x00000200, 0x0D, 0x000009FD }, /* DRAM - PS=8M */ + { 0x00800200, 0x0D, 0x008009FD }, /* DRAM - PS=8M */ + { 0x01000200, 0x0D, 0x010009FD }, /* DRAM - PS=8M */ + { 0x01800200, 0x0D, 0x018009FD }, /* DRAM - PS=8M */ + { 0x02000200, 0x0D, 0x020009FD }, /* DRAM - PS=8M */ + { 0x02800200, 0x0D, 0x028009FD }, /* DRAM - PS=8M */ + { 0x03000200, 0x0D, 0x030009FD }, /* DRAM - PS=8M */ + { 0x03800200, 0x0D, 0x038009FD }, /* DRAM - PS=8M */ + { 0x04000200, 0x0D, 0x040009FD }, /* DRAM - PS=8M */ + { 0x04800200, 0x0D, 0x048009FD }, /* DRAM - PS=8M */ + { 0x05000200, 0x0D, 0x050009FD }, /* DRAM - PS=8M */ + { 0x05800200, 0x0D, 0x058009FD }, /* DRAM - PS=8M */ + { 0x06000200, 0x0D, 0x060009FD }, /* DRAM - PS=8M */ + { 0x06800200, 0x0D, 0x068009FD }, /* DRAM - PS=8M */ + { 0x07000200, 0x0D, 0x070009FD }, /* DRAM - PS=8M */ + { 0x07800200, 0x0D, 0x078009FD }, /* DRAM - PS=8M */ + /* + * + * (IMMR-SPRs) Dual Port RAM: Start address 0xFA200000, 16K, + * ASID=0x0, APG=0x0, guarded memory, write-through data cache policy, + * R/W,X for all, no ASID comparison, cache-inhibited. + * + * Note: We use the value in MBXA/PG2, which is also the value that + * EPPC-Bug programmed into our boards. The alternative is the value + * in MBXA/PG1: 0xFFA00000. This value might well depend on the revision + * of the firmware. + * EPN TWC RPN + */ + { 0xFA200200, 0x13, 0xFA2009FF }, /* IMMR - PS=16K */ + /* + * + * Flash: Start address 0x40000000, 8M, + * ASID=0x0, APG=0x0, not guarded memory, + * R/O,X for all, no ASID comparison, not cache-inhibited. + * EPN TWC RPN + */ + { 0x40000200, 0x0D, 0x40000CFD } /* Flash - PS=8M */ +}; + +/* + * MMU_N_TLB_Table_Entries is defined here because the size of the + * MMU_TLB_table is only known in this file. + */ +int MMU_N_TLB_Table_Entries = ( sizeof(MMU_TLB_table) / sizeof(MMU_TLB_table[0]) ); diff --git a/bsps/powerpc/virtex/start/bsp_specs b/bsps/powerpc/virtex/start/bsp_specs new file mode 100644 index 0000000000..6cb546f392 --- /dev/null +++ b/bsps/powerpc/virtex/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/virtex/start/bspstart.c b/bsps/powerpc/virtex/start/bspstart.c new file mode 100644 index 0000000000..5b4a4a135f --- /dev/null +++ b/bsps/powerpc/virtex/start/bspstart.c @@ -0,0 +1,105 @@ +/* bsp_start() + * + * This routine starts the application. It includes application, + * board, and monitor specific initialization and configuration. + * The generic CPU dependent initialization has been performed + * before this routine is invoked. + * + * INPUT: NONE + * + * OUTPUT: NONE + * + * Author: Thomas Doerfler <td@imd.m.isar.de> + * IMD Ingenieurbuero fuer Microcomputertechnik + * + * COPYRIGHT (c) 1998 by IMD + * + * Changes from IMD are covered by the original distributions terms. + * This file has been derived from the papyrus BSP: + * + * Author: Andrew Bray <andy@i-cubed.co.uk> + * + * COPYRIGHT (c) 1995 by i-cubed ltd. + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of i-cubed limited not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * i-cubed limited makes no representations about the suitability + * of this software for any purpose. + * + * Modifications for spooling console driver and control of memory layout + * with linker command file by + * Thomas Doerfler <td@imd.m.isar.de> + * for these modifications: + * COPYRIGHT (c) 1997 by IMD, Puchheim, Germany. + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies. IMD makes no representations about the suitability + * of this software for any purpose. + * + * Derived from c/src/lib/libbsp/no_cpu/no_bsp/startup/bspstart.c: + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * + * Modifications for PPC405GP by Dennis Ehlin + */ + +#include <rtems/counter.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> +#include <bsp/bootcard.h> +#include <bsp/linker-symbols.h> + +#include <libcpu/powerpc-utility.h> + +#include RTEMS_XPARAMETERS_H + +/* Symbols defined in linker command file */ +LINKER_SYMBOL(virtex_exc_vector_base); + +/* + * Driver configuration parameters + */ +uint32_t bsp_time_base_frequency = XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ; + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ +void bsp_start( void ) +{ + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function store the result in global variables + * so that it can be used latter... + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + rtems_counter_initialize_converter(bsp_time_base_frequency); + + /* + * Initialize default raw exception handlers. + */ + ppc_exc_initialize_with_vector_base( + (uintptr_t) bsp_section_work_begin, + rtems_configuration_get_interrupt_stack_size(), + virtex_exc_vector_base + ); + __asm__ volatile ("mtevpr %0" : : "r" (virtex_exc_vector_base)); + + bsp_interrupt_initialize(); +} diff --git a/bsps/powerpc/virtex/start/linkcmds.in b/bsps/powerpc/virtex/start/linkcmds.in new file mode 100644 index 0000000000..13f9217e9d --- /dev/null +++ b/bsps/powerpc/virtex/start/linkcmds.in @@ -0,0 +1,35 @@ +EXTERN (__vectors) + +MEMORY { + RAM : ORIGIN = @VIRTEX_RAM_ORIGIN@, LENGTH = @VIRTEX_RAM_LENGTH@ + FAST_RAM : ORIGIN = @VIRTEX_FAST_RAM_ORIGIN@, LENGTH = @VIRTEX_FAST_RAM_LENGTH@ + RESET : ORIGIN = @VIRTEX_RESET_ORIGIN@, LENGTH = @VIRTEX_RESET_LENGTH@ + EMPTY : ORIGIN = 0x0, LENGTH = 0x0 +} + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", FAST_RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", 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_FAST_DATA", FAST_RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", EMPTY); +REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +SECTIONS { + .virtex_reset : { + KEEP (*(.virtex_reset)) + } > RESET AT > RESET +} + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/virtex4/start/bsp_specs b/bsps/powerpc/virtex4/start/bsp_specs new file mode 100644 index 0000000000..ccbea2690c --- /dev/null +++ b/bsps/powerpc/virtex4/start/bsp_specs @@ -0,0 +1,10 @@ +%rename startfile old_startfile +%rename endfile old_endfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} \ +%{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/virtex4/start/bspclean.c b/bsps/powerpc/virtex4/start/bspclean.c new file mode 100644 index 0000000000..bd5829e0b2 --- /dev/null +++ b/bsps/powerpc/virtex4/start/bspclean.c @@ -0,0 +1,54 @@ +/* + * This routine normally is part of start.s and usually returns + * control to a monitor. + * + * INPUT: NONE + * + * OUTPUT: NONE + * + * Author: Andrew Bray <andy@i-cubed.co.uk> + * + * COPYRIGHT (c) 1995 by i-cubed ltd. + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of i-cubed limited not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * i-cubed limited makes no representations about the suitability + * of this software for any purpose. + * + * Derived from c/src/lib/libbsp/no_cpu/no_bsp/startup/bspclean.c: + * + * COPYRIGHT (c) 1989-1999. + * 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> + +static void _noopfun(void) {} + +void app_bsp_cleanup(void) +__attribute__(( weak, alias("_noopfun") )); + +void bsp_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code error +) +{ + if ( source == RTEMS_FATAL_SOURCE_EXIT ) { + app_bsp_cleanup(); + } + + /* All done. Hang out. */ + BSP_ask_for_reset(); +} diff --git a/bsps/powerpc/virtex4/start/bspstart.c b/bsps/powerpc/virtex4/start/bspstart.c new file mode 100644 index 0000000000..d5c255be6d --- /dev/null +++ b/bsps/powerpc/virtex4/start/bspstart.c @@ -0,0 +1,219 @@ +/* + * This routine starts the application. It includes application, + * board, and monitor specific initialization and configuration. + * The generic CPU dependent initialization has been performed + * before this routine is invoked. + */ + +/* + * Author: Thomas Doerfler <td@imd.m.isar.de> + * IMD Ingenieurbuero fuer Microcomputertechnik + * + * COPYRIGHT (c) 1998 by IMD + * + * Changes from IMD are covered by the original distributions terms. + * This file has been derived from the papyrus BSP: + * + * Author: Andrew Bray <andy@i-cubed.co.uk> + * + * COPYRIGHT (c) 1995 by i-cubed ltd. + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of i-cubed limited not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * i-cubed limited makes no representations about the suitability + * of this software for any purpose. + * + * Modifications for spooling console driver and control of memory layout + * with linker command file by + * Thomas Doerfler <td@imd.m.isar.de> + * for these modifications: + * COPYRIGHT (c) 1997 by IMD, Puchheim, Germany. + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies. IMD makes no representations about the suitability + * of this software for any purpose. + * + * Derived from c/src/lib/libbsp/no_cpu/no_bsp/startup/bspstart.c: + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * + * Modifications for PPC405GP by Dennis Ehlin + * Modifications for Virtex4 by Richard Claus <claus@slac.stanford.edu> + */ +#include <rtems.h> +#include <rtems/config.h> +#include <rtems/bspIo.h> +#include <rtems/counter.h> +#include <rtems/libio.h> +#include <rtems/libcsupport.h> +#include <rtems/sysinit.h> + +#include <libcpu/cpuIdent.h> +#include <libcpu/spr.h> + +#include <bsp.h> +#include <bsp/vectors.h> +#include <bsp/bootcard.h> +#include <bsp/irq.h> + +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> + +#define DO_DOWN_ALIGN(x,a) ((x) & ~((a)-1)) + +#define DO_UP_ALIGN(x,a) DO_DOWN_ALIGN(((x) + (a) - 1 ),a) + +#define CPU_DOWN_ALIGN(x) DO_DOWN_ALIGN(x, CPU_ALIGNMENT) +#define CPU_UP_ALIGN(x) DO_UP_ALIGN(x, CPU_ALIGNMENT) + + +/* Defined in linkcmds linker script */ +LINKER_SYMBOL(RamBase); +LINKER_SYMBOL(RamSize); +LINKER_SYMBOL(__bsp_ram_start); +LINKER_SYMBOL(__bsp_ram_end); +LINKER_SYMBOL(__rtems_end); +LINKER_SYMBOL(_stack); +LINKER_SYMBOL(StackSize); +LINKER_SYMBOL(__stack_base); +LINKER_SYMBOL(WorkAreaBase); +LINKER_SYMBOL(MsgAreaBase); +LINKER_SYMBOL(MsgAreaSize); +LINKER_SYMBOL(__phy_ram_end); +LINKER_SYMBOL(bsp_exc_vector_base); + + +/* Expected by clock.c */ +uint32_t bsp_clicks_per_usec; + + +/* + * Provide weak aliases so that RTEMS distribution builds + */ +static void _noopfun(void) {} + + +void app_bsp_start(void) +__attribute__(( weak, alias("_noopfun") )); + +void app_bsp_predriver_hook(void) +__attribute__(( weak, alias("_noopfun") )); + + +static char* bspMsgBuffer = (char*)MsgAreaBase; + +static void __bsp_outchar_to_memory(char c) +{ + static char* msgBuffer = (char*)MsgAreaBase; + *msgBuffer++ = c; + if (msgBuffer >= &bspMsgBuffer[(int)MsgAreaSize]) msgBuffer = bspMsgBuffer; + *msgBuffer = 0x00; /* Overwrite next location to show EOM */ +} + + +void BSP_ask_for_reset(void) +{ + printk("\nSystem stopped, issue RESET"); + + for(;;); +} + + +/*===================================================================*/ + +/* + * BSP start routine. Called by boot_card(). + * + * This routine does the bulk of the system initialization. + */ +void bsp_start(void) +{ + uintptr_t intrStackStart; + uintptr_t intrStackSize; + + ppc_cpu_id_t myCpu; + ppc_cpu_revision_t myCpuRevision; + + /* Set the character output function; The application may override this */ + BSP_output_char = __bsp_outchar_to_memory; + + printk("RTEMS %s\n", rtems_get_version_string()); + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function stores the result in global variables so that it can be used later... + */ + myCpu = get_ppc_cpu_type(); + myCpuRevision = get_ppc_cpu_revision(); + printk("CPU: 0x%04x, Revision: 0x%04x = %d, Name: %s\n", + myCpu, myCpuRevision, myCpuRevision, get_ppc_cpu_type_name(myCpu)); + + /* + * Initialize the device driver parameters + */ + + /* Timebase register ticks/microsecond; The application may override these */ + bsp_clicks_per_usec = 350; + rtems_counter_initialize_converter(bsp_clicks_per_usec * 1000000); + + /* + * Initialize the interrupt related settings. + */ + intrStackStart = CPU_UP_ALIGN((uint32_t)__bsp_ram_start); + intrStackSize = rtems_configuration_get_interrupt_stack_size(); + + ppc_exc_initialize(intrStackStart, intrStackSize); + + /* Let the user know what parameters we were compiled with */ + printk(" Base/Start End Size\n" + "RAM: %p %p\n" + "RTEMS: %p\n" + "Interrupt Stack: 0x%08x 0x%x\n" + "Stack: %p %p %p\n" + "Workspace: %p %p\n" + "MsgArea: %p %p\n" + "Physical RAM %p\n", + RamBase, RamSize, + __rtems_end, + intrStackStart, intrStackSize, + __stack_base, _stack, StackSize, + WorkAreaBase, __bsp_ram_end, + MsgAreaBase, MsgAreaSize, + __phy_ram_end); + + /* + * Initialize RTEMS IRQ system + */ + BSP_rtems_irq_mngt_init(0); + + /* Continue with application-specific initialization */ + app_bsp_start(); +} + + +/* + * BSP predriver hook. Called by boot_card() just before drivers are + * initialized. Clear out any stale interrupts here. + */ +static void virtex4_pre_driver_hook(void) +{ + app_bsp_predriver_hook(); +} + +RTEMS_SYSINIT_ITEM( + virtex4_pre_driver_hook, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); diff --git a/bsps/powerpc/virtex4/start/dummy_console.c b/bsps/powerpc/virtex4/start/dummy_console.c new file mode 100644 index 0000000000..642fe45618 --- /dev/null +++ b/bsps/powerpc/virtex4/start/dummy_console.c @@ -0,0 +1,88 @@ +#include <rtems.h> +#include <rtems/libio.h> +#include <rtems/bspIo.h> +#include <rtems/console.h> + +#include <string.h> + +ssize_t app_memory_write(int minor, const char* buf, size_t len) +__attribute__(( weak, alias("__bsp_memory_write") )); + +ssize_t __bsp_memory_write(int minor, const char* buf, size_t len); +rtems_device_driver console_initialize(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg); + +ssize_t __bsp_memory_write(int minor, const char* buf, size_t len) +{ + const char* const last = buf+len; + while (buf < last) + { + rtems_putc(*buf++); + } + return len; +} + +static rtems_termios_callbacks gMemCallbacks = { + 0, /* firstOpen */ + 0, /* lastClose */ + 0, /* PollRead */ + app_memory_write, /* write */ + 0, /* SetAttr */ + 0, /* stopRemoteTx */ + 0, /* startRemoteTx */ + 0 /* outputUsesInterrupts */ +}; + +rtems_device_driver console_initialize(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + rtems_status_code status; + + rtems_termios_initialize(); + + status = rtems_io_register_name("/dev/console", major, 0); + + if (status != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (status); + return RTEMS_SUCCESSFUL; +} + +rtems_device_driver console_open(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + rtems_status_code sc; + + sc = rtems_termios_open (major, minor, arg, &gMemCallbacks); + + return sc; +} + +rtems_device_driver console_close(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + return rtems_termios_close(arg); +} + +rtems_device_driver console_read(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + return rtems_termios_read(arg); +} + +rtems_device_driver console_write(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + return rtems_termios_write(arg); +} + +rtems_device_driver console_control(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + return rtems_termios_ioctl(arg); +} diff --git a/bsps/powerpc/virtex4/start/linkcmds b/bsps/powerpc/virtex4/start/linkcmds new file mode 100644 index 0000000000..50d3a3f13c --- /dev/null +++ b/bsps/powerpc/virtex4/start/linkcmds @@ -0,0 +1,288 @@ +/* + * This file contains directives for the GNU linker which are specific to the + * Virtex 4 PPC 405. No assumptions are made on the firmware in the FPGA. + * This file is intended to be used together with start.S to generate + * downloadable code. + */ + +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") +OUTPUT_ARCH(powerpc) + +ENTRY(download_entry) +EXTERN(download_entry) +EXTERN(__vectors) + +MsgAreaSize = DEFINED(MsgAreaSize) ? MsgAreaSize : 1M; +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamSize : 128M - MsgAreaSize; +IntrStackSize = DEFINED(IntrStackSize) ? IntrStackSize : 16K; +StackSize = DEFINED(StackSize) ? StackSize : 64K; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0; /* 0=Use def */ + + +MEMORY +{ + VECTORS : ORIGIN = 0x00000000, LENGTH = 12K + RAM : ORIGIN = 0x00003000, LENGTH = 128M - 12K +} + + +SECTIONS +{ + bsp_exc_vector_base = 0x100; + __exeentry = download_entry; + __exestart = bsp_exc_vector_base; + .vectors bsp_exc_vector_base : { *(.vectors) } > VECTORS + + /* Read-only sections, merged into text segment: */ + .interp : { *(.interp) } > RAM + .hash : { *(.hash) } > RAM + .dynsym : { *(.dynsym) } > RAM + .dynstr : { *(.dynstr) } > RAM + .gnu.version : { *(.gnu.version) } > RAM + .gnu.version_d : { *(.gnu.version_d) } > RAM + .gnu.version_r : { *(.gnu.version_r) } > RAM + .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) } > RAM + .rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) } > RAM + .rela.rodata : { *(.rela.rodata*) *(.rela.gnu.linkonce.r*) } > RAM + .rela.got : { *(.rela.got) } > RAM + .rela.got1 : { *(.rela.got1) } > RAM + .rela.got2 : { *(.rela.got2) } > RAM + .rela.ctors : { *(.rela.ctors) } > RAM + .rela.dtors : { *(.rela.dtors) } > RAM + .rela.init : { *(.rela.init) } > RAM + .rela.fini : { *(.rela.fini) } > RAM + .rela.bss : { *(.rela.bss) } > RAM + .rela.plt : { *(.rela.plt) } > RAM + .rela.sdata : { *(.rela.sdata) } > RAM + .rela.sbss : { *(.rela.sbss) } > RAM + .rela.sdata2 : { *(.rela.sdata2) } > RAM + .rela.sbss2 : { *(.rela.sbss2) } > RAM + .rela.dyn : { *(.rela.dyn) } > RAM + + /* Initialization code */ + .init : { PROVIDE (_init = .); + *ecrti.o(.init) + KEEP(*(.init)) + *ecrtn.o(.init) + } > RAM + + .text : { *(.entry) + *(.text) + *(.text.*) + + /* Special FreeBSD sysctl sections */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* .gnu.warning sections are handled specially by elf32.em + */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } > RAM + + /* Finalization code */ + .fini : { PROVIDE (_fini = .); + *ecrti.o(.fini) + KEEP(*(.fini)) + *ecrtn.o(.fini) + } > RAM + + /* Miscellaneous read-only data */ + .rodata : { *(.rodata.* .gnu.linkonce.r*) KEEP (*(SORT(.rtemsroset.*))) } > RAM + .rodata1 : { *(.rodata1) } > RAM + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >RAM + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >RAM + + _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)); + + /* Initialised small data addressed as offsets from r2 */ + .sdata2 : { PROVIDE (_SDA2_BASE_ = 32768); *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } > RAM + + /* Zeroed small data addressed as offsets from r2 */ + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + + /* Avoid empty sdata2/sbss2 area: __eabi would not set up + * r2 which may be important if run-time loading is used + */ + . += 1; + + PROVIDE (__SBSS2_END__ = .); + } > RAM + + /* Exception frame info */ + .eh_frame : { *(.eh_frame .eh_frame.*) } > RAM + .eh_frame_hdr : { *(.eh_frame_hdr) } > RAM + + /* Declares where the .text section ends */ + _etext = .; + PROVIDE (etext = .); + + /* Initialized R/W Data section goes in RAM */ + .data : { PROVIDE(__DATA_START__ = ABSOLUTE(.) ); + *(.data) + *(.data.*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + } > RAM + + .data1 : { *(.data1) } > RAM + + PROVIDE (__EXCEPT_START__ = .); + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } > RAM + PROVIDE (__EXCEPT_END__ = .); + + .got1 : { *(.got1) } > RAM + + /* Put .ctors and .dtors next to the .got2 section, so that the pointers + * get relocated with -mrelocatable. Also put in the .fixup pointers. + * The current compiler no longer needs this, but keep it around for 2.7.2. + */ + PROVIDE (_GOT2_START_ = .); + .got2 : { *(.got2) } > RAM + + .dynamic : { *(.dynamic) } > RAM + + .ctors : { /* 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)) + /* 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 ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } > RAM + + .dtors : { KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } > RAM + + PROVIDE (_FIXUP_START_ = .); + .fixup : { *(.fixup) } > RAM + PROVIDE (_FIXUP_END_ = .); + + PROVIDE (_GOT2_END_ = .); + + PROVIDE (_GOT_START_ = .); + .got : { __got_start = .; + *(.got) + } > RAM + + .got.plt : { *(.got.plt) } > RAM + PROVIDE (_GOT_END_ = .); + + .jcr : { KEEP (*(.jcr)) } > RAM + + /* We want the small data sections together, so single-instruction offsets + * can access them all, and initialized data all before uninitialized, so + * we can shorten the on-disk segment size. + */ + /* Initialised small data addressed as offsets from r13 */ + .sdata : { PROVIDE (_SDA_BASE_ = 32768); *(.sdata* .gnu.linkonce.s.*) } > RAM + + _edata = .; + PROVIDE (edata = .); + + /* Zeroed small data addressed as offsets from r13 */ + .sbss : { PROVIDE (__sbss_start = .); + *(.dynsbss) + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.scommon) + + /* Avoid empty sdata/sbss area: __eabi would not set up + * r13, which may be important if run-time loading is used + */ + . += 1; + + PROVIDE (__SBSS_END__ = .); + PROVIDE (__sbss_end = .); + } > RAM + + .plt : { *(.plt) } > RAM + .iplt : { *(.iplt) } > RAM + + /* Zeroed large data */ + .bss : { PROVIDE (__bss_start = .); + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b*) + *(COMMON) + + PROVIDE (__bss_end = ALIGN(4)); + __bss_size = __bss_end - __bss_start; + } > RAM + + __exeend = ALIGN(4); + __rtems_end = .; + . = ALIGN(0x10); /* Align to a cache-line boundary */ + PROVIDE(__bsp_ram_start = .); + + /* Interrupt stack: aligned on a cache-line boundary */ + . += IntrStackSize; + __intrStack = .; + + /* Main stack lives here */ + _stack = ALIGN(0x10); /* Align to a cache-line boundary */ + . += StackSize; + __stack_base = .; /* Initial stack builds downwards */ + + /* RTEMS workspace: size specified by application */ + WorkAreaBase = ALIGN(0x10); /* Align to a cache-line boundary */ + + /* The heap comes after the work space */ + + . = RamBase + RamSize; + PROVIDE(__bsp_ram_end = .); + + /* Message area for capturing early printk output */ + /* Placed here to be easily findable with a debugger */ + MsgAreaBase = .; + . += MsgAreaSize; + + __phy_ram_end = .; /* True end of physical memory */ + + /DISCARD/ : + { + *(.comment) + } + + /* Some configuration constants: Not clear why they're placed here */ + __dccr = 0x80000000; + __iccr = 0x80000000; + __sgr = 0x7fffffff; + __vectors = 0; +} diff --git a/bsps/powerpc/virtex5/start/bsp_specs b/bsps/powerpc/virtex5/start/bsp_specs new file mode 100644 index 0000000000..ccbea2690c --- /dev/null +++ b/bsps/powerpc/virtex5/start/bsp_specs @@ -0,0 +1,10 @@ +%rename startfile old_startfile +%rename endfile old_endfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} \ +%{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/virtex5/start/bspclean.c b/bsps/powerpc/virtex5/start/bspclean.c new file mode 100644 index 0000000000..bd5829e0b2 --- /dev/null +++ b/bsps/powerpc/virtex5/start/bspclean.c @@ -0,0 +1,54 @@ +/* + * This routine normally is part of start.s and usually returns + * control to a monitor. + * + * INPUT: NONE + * + * OUTPUT: NONE + * + * Author: Andrew Bray <andy@i-cubed.co.uk> + * + * COPYRIGHT (c) 1995 by i-cubed ltd. + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of i-cubed limited not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * i-cubed limited makes no representations about the suitability + * of this software for any purpose. + * + * Derived from c/src/lib/libbsp/no_cpu/no_bsp/startup/bspclean.c: + * + * COPYRIGHT (c) 1989-1999. + * 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> + +static void _noopfun(void) {} + +void app_bsp_cleanup(void) +__attribute__(( weak, alias("_noopfun") )); + +void bsp_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code error +) +{ + if ( source == RTEMS_FATAL_SOURCE_EXIT ) { + app_bsp_cleanup(); + } + + /* All done. Hang out. */ + BSP_ask_for_reset(); +} diff --git a/bsps/powerpc/virtex5/start/bspstart.c b/bsps/powerpc/virtex5/start/bspstart.c new file mode 100644 index 0000000000..ff821574a9 --- /dev/null +++ b/bsps/powerpc/virtex5/start/bspstart.c @@ -0,0 +1,240 @@ +/* + * + * This routine starts the application. It includes application, + * board, and monitor specific initialization and configuration. + * The generic CPU dependent initialization has been performed + * before this routine is invoked. + */ + +/* + * Author: Thomas Doerfler <td@imd.m.isar.de> + * IMD Ingenieurbuero fuer Microcomputertechnik + * + * COPYRIGHT (c) 1998 by IMD + * + * Changes from IMD are covered by the original distributions terms. + * This file has been derived from the papyrus BSP: + * + * Author: Andrew Bray <andy@i-cubed.co.uk> + * + * COPYRIGHT (c) 1995 by i-cubed ltd. + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of i-cubed limited not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * i-cubed limited makes no representations about the suitability + * of this software for any purpose. + * + * Modifications for spooling console driver and control of memory layout + * with linker command file by + * Thomas Doerfler <td@imd.m.isar.de> + * for these modifications: + * COPYRIGHT (c) 1997 by IMD, Puchheim, Germany. + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies. IMD makes no representations about the suitability + * of this software for any purpose. + * + * Derived from c/src/lib/libbsp/no_cpu/no_bsp/startup/bspstart.c: + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * + * Modifications for PPC405GP by Dennis Ehlin + * Modifications for Virtex5 by Richard Claus <claus@slac.stanford.edu> + */ +#include <rtems.h> +#include <rtems/config.h> +#include <rtems/bspIo.h> +#include <rtems/counter.h> +#include <rtems/libio.h> +#include <rtems/libcsupport.h> +#include <rtems/sysinit.h> + +#include <libcpu/cpuIdent.h> +#include <libcpu/spr.h> + +#include <bsp.h> +#include <bsp/vectors.h> +#include <bsp/bootcard.h> +#include <bsp/irq.h> + +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> + +#define DO_DOWN_ALIGN(x,a) ((x) & ~((a)-1)) + +#define DO_UP_ALIGN(x,a) DO_DOWN_ALIGN(((x) + (a) - 1 ),a) + +#define CPU_DOWN_ALIGN(x) DO_DOWN_ALIGN(x, CPU_ALIGNMENT) +#define CPU_UP_ALIGN(x) DO_UP_ALIGN(x, CPU_ALIGNMENT) + + +/* Defined in linkcmds linker script */ +LINKER_SYMBOL(RamBase); +LINKER_SYMBOL(RamSize); +LINKER_SYMBOL(__bsp_ram_start); +LINKER_SYMBOL(__bsp_ram_end); +LINKER_SYMBOL(__rtems_end); +LINKER_SYMBOL(_stack); +LINKER_SYMBOL(StackSize); +LINKER_SYMBOL(__stack_base); +LINKER_SYMBOL(WorkAreaBase); +LINKER_SYMBOL(MsgAreaBase); +LINKER_SYMBOL(MsgAreaSize); +LINKER_SYMBOL(__phy_ram_end); +LINKER_SYMBOL(bsp_exc_vector_base); + + +/* Expected by clock.c */ +uint32_t bsp_clicks_per_usec; + +/* + * Bus Frequency + */ +unsigned int BSP_bus_frequency; +/* + * processor clock frequency + */ +unsigned int BSP_processor_frequency; + +/* + * Time base divisior (bus freq / TB clock) + */ +unsigned int BSP_time_base_divisor; + +/* + * Provide weak aliases so that RTEMS distribution builds + */ +static void _noopfun(void) {} + + +void app_bsp_start(void) +__attribute__(( weak, alias("_noopfun") )); + +void app_bsp_predriver_hook(void) +__attribute__(( weak, alias("_noopfun") )); + + +static char* bspMsgBuffer = (char*)MsgAreaBase; + +static void __bsp_outchar_to_memory(char c) +{ + static char* msgBuffer = (char*)MsgAreaBase; + *msgBuffer++ = c; + if (msgBuffer >= &bspMsgBuffer[(int)MsgAreaSize]) msgBuffer = bspMsgBuffer; + *msgBuffer = 0x00; /* Overwrite next location to show EOM */ +} + + +void BSP_ask_for_reset(void) +{ + printk("\nSystem stopped, issue RESET"); + + for(;;); +} + + +/*===================================================================*/ + +/* + * BSP start routine. Called by boot_card(). + * + * This routine does the bulk of the system initialization. + */ +void bsp_start(void) +{ + uintptr_t intrStackStart; + uintptr_t intrStackSize; + + ppc_cpu_id_t myCpu; + ppc_cpu_revision_t myCpuRevision; + + /* Set the character output function; The application may override this */ + BSP_output_char = __bsp_outchar_to_memory; + + printk("RTEMS %s\n", rtems_get_version_string()); + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function stores the result in global variables so that it can be used later... + */ + myCpu = get_ppc_cpu_type(); + myCpuRevision = get_ppc_cpu_revision(); + printk("CPU: 0x%04x, Revision: 0x%04x = %d, Name: %s\n", + myCpu, myCpuRevision, myCpuRevision, get_ppc_cpu_type_name(myCpu)); + + /* + * Initialize the device driver parameters + */ + + /* For mpc6xx clock driver: */ + BSP_bus_frequency = 465000000; + BSP_processor_frequency = 465000000; /* Measured with a DPM 440 2012/8/13 */ + BSP_time_base_divisor = 1000; + + /* Timebase register ticks/microsecond; The application may override these */ + bsp_clicks_per_usec = BSP_bus_frequency/(BSP_time_base_divisor * 1000); + rtems_counter_initialize_converter( + BSP_bus_frequency / (BSP_time_base_divisor / 1000) + ); + + /* + * Initialize the interrupt related settings. + */ + intrStackStart = CPU_UP_ALIGN((uint32_t)__bsp_ram_start); + intrStackSize = rtems_configuration_get_interrupt_stack_size(); + + ppc_exc_initialize(intrStackStart, intrStackSize); + + /* Let the user know what parameters we were compiled with */ + printk(" Base/Start End Size\n" + "RAM: %p %p\n" + "RTEMS: %p\n" + "Interrupt Stack: 0x%08x 0x%x\n" + "Stack: %p %p %p\n" + "Workspace: %p %p\n" + "MsgArea: %p %p\n" + "Physical RAM %p\n", + RamBase, RamSize, + __rtems_end, + intrStackStart, intrStackSize, + __stack_base, _stack, StackSize, + WorkAreaBase, __bsp_ram_end, + MsgAreaBase, MsgAreaSize, + __phy_ram_end); + + /* + * Initialize RTEMS IRQ system + */ + BSP_rtems_irq_mngt_init(0); + + /* Continue with application-specific initialization */ + app_bsp_start(); +} + + +/* + * BSP predriver hook. Called by boot_card() just before drivers are + * initialized. Clear out any stale interrupts here. + */ +static void virtex5_pre_driver_hook(void) +{ + app_bsp_predriver_hook(); +} + +RTEMS_SYSINIT_ITEM( + virtex5_pre_driver_hook, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); diff --git a/bsps/powerpc/virtex5/start/dummy_console.c b/bsps/powerpc/virtex5/start/dummy_console.c new file mode 100644 index 0000000000..2cdab33c8c --- /dev/null +++ b/bsps/powerpc/virtex5/start/dummy_console.c @@ -0,0 +1,85 @@ +#include <rtems.h> +#include <rtems/libio.h> +#include <rtems/bspIo.h> +#include <rtems/console.h> + +#include <string.h> + +ssize_t app_memory_write(int minor, const char* buf, size_t len) +__attribute__(( weak, alias("__bsp_memory_write") )); + +ssize_t __bsp_memory_write(int minor, const char* buf, size_t len); + +ssize_t __bsp_memory_write(int minor, const char* buf, size_t len) +{ + const char* const last = buf+len; + while (buf < last) + { + rtems_putc(*buf++); + } + return len; +} + +static rtems_termios_callbacks gMemCallbacks = { + 0, /* firstOpen */ + 0, /* lastClose */ + 0, /* PollRead */ + app_memory_write, /* write */ + 0, /* SetAttr */ + 0, /* stopRemoteTx */ + 0, /* startRemoteTx */ + 0 /* outputUsesInterrupts */ +}; + +rtems_device_driver console_initialize(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + rtems_status_code status; + + rtems_termios_initialize(); + + status = rtems_io_register_name("/dev/console", major, 0); + + if (status != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (status); + return RTEMS_SUCCESSFUL; +} + +rtems_device_driver console_open(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + rtems_status_code sc; + + sc = rtems_termios_open (major, minor, arg, &gMemCallbacks); + + return sc; +} + +rtems_device_driver console_close(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + return rtems_termios_close(arg); +} + +rtems_device_driver console_read(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + return rtems_termios_read(arg); +} + +rtems_device_driver console_write(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + return rtems_termios_write(arg); +} + +rtems_device_driver console_control(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + return rtems_termios_ioctl(arg); +} diff --git a/bsps/powerpc/virtex5/start/linkcmds b/bsps/powerpc/virtex5/start/linkcmds new file mode 100644 index 0000000000..9bd7c2e67f --- /dev/null +++ b/bsps/powerpc/virtex5/start/linkcmds @@ -0,0 +1,285 @@ +/* + * This file contains directives for the GNU linker which are specific to the + * Virtex 5 PPC 440. No assumptions are made on the firmware in the FPGA. + * This file is intended to be used together with start.S to generate + * downloadable code. + */ + +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") +OUTPUT_ARCH(powerpc) + +ENTRY(download_entry) +EXTERN(download_entry) +EXTERN(__vectors) + +MsgAreaSize = DEFINED(MsgAreaSize) ? MsgAreaSize : 1M; +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamSize : 2048M - MsgAreaSize; +IntrStackSize = DEFINED(IntrStackSize) ? IntrStackSize : 16K; +StackSize = DEFINED(StackSize) ? StackSize : 64K; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0; /* 0=Use def */ + + +MEMORY +{ + VECTORS : ORIGIN = 0x00000000, LENGTH = 512 + RAM : ORIGIN = 0x00000200, LENGTH = 2048M - 512 +} + + +SECTIONS +{ + bsp_exc_vector_base = 0; + __exeentry = download_entry; + __exestart = bsp_exc_vector_base; + .vectors bsp_exc_vector_base : { *(.vectors) } > VECTORS + + /* Read-only sections, merged into text segment: */ + .interp : { *(.interp) } > RAM + .hash : { *(.hash) } > RAM + .dynsym : { *(.dynsym) } > RAM + .dynstr : { *(.dynstr) } > RAM + .gnu.version : { *(.gnu.version) } > RAM + .gnu.version_d : { *(.gnu.version_d) } > RAM + .gnu.version_r : { *(.gnu.version_r) } > RAM + .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) } > RAM + .rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) } > RAM + .rela.rodata : { *(.rela.rodata*) *(.rela.gnu.linkonce.r*) } > RAM + .rela.got : { *(.rela.got) } > RAM + .rela.got1 : { *(.rela.got1) } > RAM + .rela.got2 : { *(.rela.got2) } > RAM + .rela.ctors : { *(.rela.ctors) } > RAM + .rela.dtors : { *(.rela.dtors) } > RAM + .rela.init : { *(.rela.init) } > RAM + .rela.fini : { *(.rela.fini) } > RAM + .rela.bss : { *(.rela.bss) } > RAM + .rela.plt : { *(.rela.plt) } > RAM + .rela.sdata : { *(.rela.sdata) } > RAM + .rela.sbss : { *(.rela.sbss) } > RAM + .rela.sdata2 : { *(.rela.sdata2) } > RAM + .rela.sbss2 : { *(.rela.sbss2) } > RAM + .rela.dyn : { *(.rela.dyn) } > RAM + + /* Initialization code */ + .init : { PROVIDE (_init = .); + *ecrti.o(.init) + KEEP(*(.init)) + *ecrtn.o(.init) + } > RAM + + .text : { *(.entry) + *(.text) + *(.text.*) + + /* Special FreeBSD sysctl sections */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* .gnu.warning sections are handled specially by elf32.em + */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } > RAM + + /* Finalization code */ + .fini : { PROVIDE (_fini = .); + *ecrti.o(.fini) + KEEP(*(.fini)) + *ecrtn.o(.fini) + } > RAM + + /* Miscellaneous read-only data */ + .rodata : { *(.rodata.* .gnu.linkonce.r*) KEEP (*(SORT(.rtemsroset.*))) } > RAM + .rodata1 : { *(.rodata1) } > RAM + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >RAM + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >RAM + + _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)); + + /* Initialised small data addressed as offsets from r2 */ + .sdata2 : { PROVIDE (_SDA2_BASE_ = 32768); *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } > RAM + + /* Zeroed small data addressed as offsets from r2 */ + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + + /* Avoid empty sdata2/sbss2 area: __eabi would not set up + * r2 which may be important if run-time loading is used + */ + . += 1; + + PROVIDE (__SBSS2_END__ = .); + } > RAM + + /* Exception frame info */ + .eh_frame : { *(.eh_frame .eh_frame.*) } > RAM + .eh_frame_hdr : { *(.eh_frame_hdr) } > RAM + + /* Declares where the .text section ends */ + _etext = .; + PROVIDE (etext = .); + + /* Initialized R/W Data section goes in RAM */ + .data : { PROVIDE(__DATA_START__ = ABSOLUTE(.) ); + *(.data) + *(.data.*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + } > RAM + + .data1 : { *(.data1) } > RAM + + PROVIDE (__EXCEPT_START__ = .); + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } > RAM + PROVIDE (__EXCEPT_END__ = .); + + .got1 : { *(.got1) } > RAM + + /* Put .ctors and .dtors next to the .got2 section, so that the pointers + * get relocated with -mrelocatable. Also put in the .fixup pointers. + * The current compiler no longer needs this, but keep it around for 2.7.2. + */ + PROVIDE (_GOT2_START_ = .); + .got2 : { *(.got2) } > RAM + + .dynamic : { *(.dynamic) } > RAM + + .ctors : { /* 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)) + /* 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 ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } > RAM + + .dtors : { KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } > RAM + + PROVIDE (_FIXUP_START_ = .); + .fixup : { *(.fixup) } > RAM + PROVIDE (_FIXUP_END_ = .); + + PROVIDE (_GOT2_END_ = .); + + PROVIDE (_GOT_START_ = .); + .got : { __got_start = .; + *(.got) + } > RAM + + .got.plt : { *(.got.plt) } > RAM + PROVIDE (_GOT_END_ = .); + + .jcr : { KEEP (*(.jcr)) } > RAM + + /* We want the small data sections together, so single-instruction offsets + * can access them all, and initialized data all before uninitialized, so + * we can shorten the on-disk segment size. + */ + /* Initialised small data addressed as offsets from r13 */ + .sdata : { PROVIDE (_SDA_BASE_ = 32768); *(.sdata* .gnu.linkonce.s.*) } > RAM + + _edata = .; + PROVIDE (edata = .); + + /* Zeroed small data addressed as offsets from r13 */ + .sbss : { PROVIDE (__sbss_start = .); + *(.dynsbss) + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.scommon) + + /* Avoid empty sdata/sbss area: __eabi would not set up + * r13, which may be important if run-time loading is used + */ + . += 1; + + PROVIDE (__SBSS_END__ = .); + PROVIDE (__sbss_end = .); + } > RAM + + .plt : { *(.plt) } > RAM + .iplt : { *(.iplt) } > RAM + + /* Zeroed large data */ + .bss : { PROVIDE (__bss_start = .); + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b*) + *(COMMON) + + PROVIDE (__bss_end = ALIGN(4)); + __bss_size = __bss_end - __bss_start; + } > RAM + + __exeend = ALIGN(4); + __rtems_end = .; + . = ALIGN(0x20); /* Align to a cache-line boundary */ + PROVIDE(__bsp_ram_start = .); + + /* Interrupt stack: aligned on a cache-line boundary */ + . += IntrStackSize; + __intrStack = .; + + /* Main stack lives here */ + _stack = ALIGN(0x20); /* Align to a cache-line boundary */ + . += StackSize; + __stack_base = .; /* Initial stack builds downwards */ + + /* RTEMS workspace: size specified by application */ + WorkAreaBase = ALIGN(0x20); /* Align to a cache-line boundary */ + + /* The heap comes after the work space */ + + . = RamBase + RamSize; + PROVIDE(__bsp_ram_end = .); + + /* Message area for capturing early printk output */ + /* Placed here to be easily findable with a debugger */ + MsgAreaBase = __bsp_ram_end; + . += MsgAreaSize; + + __phy_ram_end = .; /* True end of physical memory */ + + /DISCARD/ : + { + *(.comment) + } + + /* Some configuration constants */ + __vectors = 0; +} diff --git a/bsps/riscv/riscv_generic/start/bsp_fatal_halt.c b/bsps/riscv/riscv_generic/start/bsp_fatal_halt.c new file mode 100644 index 0000000000..64c307990b --- /dev/null +++ b/bsps/riscv/riscv_generic/start/bsp_fatal_halt.c @@ -0,0 +1,35 @@ +/* @ingroup riscv_generic + * @brief riscv_generic BSP Fatal_halt handler. + * + * Copyright (c) 2015 University of York. + * Hesham Almatary <hesham@alumni.york.ac.uk> + * + * 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. + */ + +#include <bsp.h> + +/* Send a power-off signal to the host */ +void _CPU_Fatal_halt(uint32_t source, uint32_t error) +{ + htif_poweroff(); +} diff --git a/bsps/riscv/riscv_generic/start/bsp_specs b/bsps/riscv/riscv_generic/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/riscv/riscv_generic/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/riscv/riscv_generic/start/linkcmds b/bsps/riscv/riscv_generic/start/linkcmds new file mode 100644 index 0000000000..fad1d1e1d2 --- /dev/null +++ b/bsps/riscv/riscv_generic/start/linkcmds @@ -0,0 +1,378 @@ +/** + * @file + * + * @ingroup bsp_linker + * + * @brief Memory map + */ + +/* + * + * Copyright (c) 2015 University of York. + * Hesham ALMatary <hmka501@york.ac.uk> + * + * 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. + */ + +OUTPUT_ARCH (riscv) + +ENTRY (_start) +STARTUP (start.o) + +MEMORY +{ + RAM : ORIGIN = 0x0000000010000000, LENGTH = 0x10000000 +} + +REGION_ALIAS ("REGION_VECTOR", RAM); +REGION_ALIAS ("REGION_START", 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_HTIF", RAM); +REGION_ALIAS ("REGION_HTIF_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); + +/* + * 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 : 16; + +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); + +_bsp_processor_count = DEFINED (_bsp_processor_count) ? _bsp_processor_count : 1; + +SECTIONS { + + .vector : + { + . = ALIGN(8); + bsp_section_vector_begin = .; + *(.vector) + . = ALIGN(bsp_vector_table_size); + 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 = bsp_section_vector_begin; + bsp_vector_table_end = bsp_vector_table_begin + bsp_vector_table_size; + + .start : + { + . = ALIGN(8); + 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 (bsp_section_xbarrier_align); + } > REGION_VECTOR AT > REGION_VECTOR + +.text : { + . = ALIGN(8); + 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 : { + KEEP (*(.init)) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .fini : { + KEEP (*(.fini)) + . = ALIGN(8); + 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 (bsp_section_robarrier_align); + } > REGION_RODATA AT > REGION_RODATA + +.rodata : { + . = ALIGN(8); + bsp_section_rodata_begin = .; + *(.rodata .rodata.* .gnu.linkonce.r.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD +.eh_frame : { + KEEP (*(.eh_frame)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gcc_except_table : { + *(.gcc_except_table .gcc_except_table.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > REGION_RODATA AT > REGION_RODATA_LOAD + .tbss : { + _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 : { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .init_array : { + 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 : { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .ctors : { + /* 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 : { + 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 : { + *(.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 : { + KEEP (*(.jcr)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .interp : { + *(.interp) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .note.gnu.build-id : { + *(.note.gnu.build-id) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .hash : { + *(.hash) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.hash : { + *(.gnu.hash) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynsym : { + *(.dynsym) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynstr : { + *(.dynstr) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version : { + *(.gnu.version) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version_d : { + *(.gnu.version_d) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version_r : { + *(.gnu.version_r) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rel.dyn : { + *(.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 : { + *(.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.*) + 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 : { + *(.rel.plt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rela.plt : { + *(.rela.plt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .plt : { + *(.plt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .iplt : { + *(.iplt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynamic : { + *(.dynamic) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .got : { + *(.got.plt) *(.igot.plt) *(.got) *(.igot) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rtemsroset : { + /* Special FreeBSD linker set sections */ + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = .; + *(set_domain_*); + *(set_pseudo_*); + + KEEP (*(SORT(.rtemsroset.*))) + . = ALIGN(8); + 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; + + /*--------------------------------------------------------------------*/ + /* HTIF, isolated onto separate page */ + /*--------------------------------------------------------------------*/ + .htif : + { + . = ALIGN(0x1000); + *(.htif) + . = ALIGN(0x1000); + } > REGION_HTIF AT > REGION_HTIF_LOAD + + +.rwbarrier : { + . = ALIGN(8); + . = ALIGN (bsp_section_rwbarrier_align); + } > REGION_DATA AT > REGION_DATA + +.data : { + . = ALIGN(8); + bsp_section_data_begin = .; + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } > REGION_DATA AT > REGION_DATA_LOAD + .data1 : { + *(.data1) + } > REGION_DATA AT > REGION_DATA_LOAD + .rtemsrwset : { + KEEP (*(SORT(.rtemsrwset.*))) + . = ALIGN(8); + 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(8); + bsp_section_bss_begin = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(8); + bsp_section_bss_end = .; + } > REGION_BSS AT > REGION_BSS + bsp_section_bss_size = bsp_section_bss_end - bsp_section_bss_begin; + +.work : { + /* + * The work section will occupy the remaining REGION_WORK region and + * contains the RTEMS work space and heap. + */ + . = ALIGN(8); + bsp_section_work_begin = .; + . += ORIGIN (REGION_WORK) + LENGTH (REGION_WORK) - ABSOLUTE (.); + . = ALIGN(8); + bsp_section_work_end = .; + } > REGION_WORK AT > REGION_WORK + bsp_section_work_size = bsp_section_work_end - bsp_section_work_begin; + + .stack : { + . = ALIGN(8); + bsp_section_stack_begin = .; + . += ORIGIN (REGION_STACK) + LENGTH (REGION_STACK) - ABSOLUTE (.); + . = ALIGN(8); + bsp_section_stack_end = .; + } > REGION_STACK AT > REGION_STACK + bsp_section_stack_size = bsp_section_stack_begin - bsp_section_stack_end; + + RamBase = ORIGIN (REGION_WORK); + RamSize = LENGTH (REGION_WORK); + WorkAreaBase = bsp_section_work_begin; + HeapSize = 0; +} diff --git a/bsps/sh/gensh1/start/bsp_specs b/bsps/sh/gensh1/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/sh/gensh1/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/sh/gensh1/start/cpu_asm.c b/bsps/sh/gensh1/start/cpu_asm.c new file mode 100644 index 0000000000..99d9cc9a6a --- /dev/null +++ b/bsps/sh/gensh1/start/cpu_asm.c @@ -0,0 +1,181 @@ +/* + * This file contains the basic algorithms for all assembly code used + * in an specific CPU port of RTEMS. These algorithms must be implemented + * in assembly language + * + * NOTE: This port uses a C file with inline assembler instructions + * + * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and + * Bernd Becker (becker@faw.uni-ulm.de) + * + * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * + * COPYRIGHT (c) 1998. + * 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. + * + */ + +/* + * This is supposed to be an assembly file. This means that system.h + * and cpu.h should not be included in a "real" cpu_asm file. An + * implementation in assembly should include "cpu_asm.h" + */ + +#include <rtems/system.h> +#include <rtems/score/percpu.h> +#include <rtems/score/isr.h> +#include <rtems/score/threaddispatch.h> +#include <rtems/score/sh.h> +#include <rtems/score/ispsh7032.h> + +#include <rtems/score/ispsh7032.h> +#include <rtems/score/iosh7032.h> +#include <rtems/score/sh_io.h> + +/* from cpu_isps.c */ +extern proc_ptr _Hardware_isr_Table[]; + +#if (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + unsigned long *_old_stack_ptr; +#endif + +register unsigned long *stack_ptr __asm__ ("r15"); + +/* + * sh_set_irq_priority + * + * this function sets the interrupt level of the specified interrupt + * + * parameters: + * - irq : interrupt number + * - prio: priority to set for this interrupt number + * + * returns: 0 if ok + * -1 on error + */ + +unsigned int sh_set_irq_priority( + unsigned int irq, + unsigned int prio ) +{ + uint32_t shiftcount; + uint32_t prioreg; + uint16_t temp16; + ISR_Level level; + + /* + * first check for valid interrupt + */ + if (( irq > 113) || (_Hardware_isr_Table[irq] == _dummy_isp)) + return -1; + /* + * check for valid irq priority + */ + if ( prio > 15 ) + return -1; + + /* + * look up appropriate interrupt priority register + */ + if ( irq > 71) + { + irq = irq - 72; + shiftcount = 12 - ((irq & ~0x03) % 16); + + switch( irq / 16) + { + case 0: { prioreg = INTC_IPRC; break;} + case 1: { prioreg = INTC_IPRD; break;} + case 2: { prioreg = INTC_IPRE; break;} + default: return -1; + } + } + else + { + shiftcount = 12 - 4 * ( irq % 4); + if ( irq > 67) + prioreg = INTC_IPRB; + else + prioreg = INTC_IPRA; + } + + /* + * Set the interrupt priority register + */ + _ISR_Local_disable( level ); + + temp16 = read16( prioreg); + temp16 &= ~( 15 << shiftcount); + temp16 |= prio << shiftcount; + write16( temp16, prioreg); + + _ISR_Local_enable( level ); + + return 0; +} + +/* + * This routine provides the RTEMS interrupt management. + */ + +void __ISR_Handler( uint32_t vector) +{ + ISR_Level level; + + _ISR_Local_disable( level ); + + _Thread_Dispatch_disable(); + +#if (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + if ( _ISR_Nest_level == 0 ) + { + /* Install irq stack */ + _old_stack_ptr = stack_ptr; + stack_ptr = _CPU_Interrupt_stack_high; + } + +#endif + + _ISR_Nest_level++; + + _ISR_Local_enable( level ); + + /* call isp */ + if ( _ISR_Vector_table[ vector]) + (*_ISR_Vector_table[ vector ])( vector ); + + _ISR_Local_disable( level ); + + _Thread_Dispatch_unnest( _Per_CPU_Get() ); + + _ISR_Nest_level--; + +#if(CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + + if ( _ISR_Nest_level == 0 ) + /* restore old stack pointer */ + stack_ptr = _old_stack_ptr; +#endif + + _ISR_Local_enable( level ); + + if ( _ISR_Nest_level ) + return; + + if ( !_Thread_Dispatch_is_enabled() ) { + return; + } + + if ( _Thread_Dispatch_necessary ) { + _Thread_Dispatch(); + } +} diff --git a/bsps/sh/gensh1/start/ispsh7032.c b/bsps/sh/gensh1/start/ispsh7032.c new file mode 100644 index 0000000000..05ba2f1e90 --- /dev/null +++ b/bsps/sh/gensh1/start/ispsh7032.c @@ -0,0 +1,248 @@ +/* + * This file contains the isp frames for the user interrupts. + * From these procedures __ISR_Handler is called with the vector number + * as argument. + * + * __ISR_Handler is kept in a separate file (cpu_asm.c), because a bug in + * some releases of gcc doesn't properly handle #pragma interrupt, if a + * file contains both isrs and normal functions. + * + * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and + * Bernd Becker (becker@faw.uni-ulm.de) + * + * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE + * + * + * COPYRIGHT (c) 1998. + * 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/system.h> +#include <rtems/score/ispsh7032.h> + +/* + * This is an exception vector table + * + * It has the same structure like the actual vector table (vectab) + */ +proc_ptr _Hardware_isr_Table[256]={ +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, +_nmi_isp, _usb_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, +/* trapa 0 -31 */ +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +/* irq 64 ... */ +_irq0_isp, _irq1_isp, _irq2_isp, _irq3_isp, +_irq4_isp, _irq5_isp, _irq6_isp, _irq7_isp, +_dma0_isp, _dummy_isp, _dma1_isp, _dummy_isp, +_dma2_isp, _dummy_isp, _dma3_isp, _dummy_isp, +_imia0_isp, _imib0_isp, _ovi0_isp, _dummy_isp, +_imia1_isp, _imib1_isp, _ovi1_isp, _dummy_isp, +_imia2_isp, _imib2_isp, _ovi2_isp, _dummy_isp, +_imia3_isp, _imib3_isp, _ovi3_isp, _dummy_isp, +_imia4_isp, _imib4_isp, _ovi4_isp, _dummy_isp, +_eri0_isp, _rxi0_isp, _txi0_isp, _tei0_isp, +_eri1_isp, _rxi1_isp, _txi1_isp, _tei1_isp, +_prt_isp, _adu_isp, _dummy_isp, _dummy_isp, +_wdt_isp, +/* 113 */ _dref_isp +}; + +#define Str(a)#a + +/* + * Some versions of gcc and all version of egcs at least until egcs-1.1b + * are not able to handle #pragma interrupt correctly if more than 1 isr is + * contained in a file and when optimizing. + * We try to work around this problem by using the macro below. + */ +#define isp( name, number, func)\ +__asm__ (".global _"Str(name)"\n\t" \ + "_"Str(name)": \n\t" \ + " mov.l r0,@-r15 \n\t" \ + " mov.l r1,@-r15 \n\t" \ + " mov.l r2,@-r15 \n\t" \ + " mov.l r3,@-r15 \n\t" \ + " mov.l r4,@-r15 \n\t" \ + " mov.l r5,@-r15 \n\t" \ + " mov.l r6,@-r15 \n\t" \ + " mov.l r7,@-r15 \n\t" \ + " mov.l r14,@-r15 \n\t" \ + " sts.l pr,@-r15 \n\t" \ + " sts.l mach,@-r15 \n\t" \ + " sts.l macl,@-r15 \n\t" \ + " mov r15,r14 \n\t" \ + " mov.l "Str(name)"_k, r1\n\t" \ + " jsr @r1 \n\t" \ + " mov #"Str(number)", r4\n\t" \ + " mov r14,r15 \n\t" \ + " lds.l @r15+,macl \n\t" \ + " lds.l @r15+,mach \n\t" \ + " lds.l @r15+,pr \n\t" \ + " mov.l @r15+,r14 \n\t" \ + " mov.l @r15+,r7 \n\t" \ + " mov.l @r15+,r6 \n\t" \ + " mov.l @r15+,r5 \n\t" \ + " mov.l @r15+,r4 \n\t" \ + " mov.l @r15+,r3 \n\t" \ + " mov.l @r15+,r2 \n\t" \ + " mov.l @r15+,r1 \n\t" \ + " mov.l @r15+,r0 \n\t" \ + " rte \n\t" \ + " nop \n\t" \ + " .align 2 \n\t" \ + #name"_k: \n\t" \ + ".long "Str(func)); + +/************************************************ + * Dummy interrupt service procedure for + * interrupts being not allowed --> Trap 34 + ************************************************/ +__asm__ (" .section .text\n\ +.global __dummy_isp\n\ +__dummy_isp:\n\ + mov.l r14,@-r15\n\ + mov r15, r14\n\ + trapa #34\n\ + mov.l @r15+,r14\n\ + rte\n\ + nop"); + +/***************************** + * Non maskable interrupt + *****************************/ +isp( _nmi_isp, NMI_ISP_V, ___ISR_Handler); + +/***************************** + * User break controller + *****************************/ +isp( _usb_isp, USB_ISP_V, ___ISR_Handler); + +/***************************** + * External interrupts 0-7 + *****************************/ +isp( _irq0_isp, IRQ0_ISP_V, ___ISR_Handler); +isp( _irq1_isp, IRQ1_ISP_V, ___ISR_Handler); +isp( _irq2_isp, IRQ2_ISP_V, ___ISR_Handler); +isp( _irq3_isp, IRQ3_ISP_V, ___ISR_Handler); +isp( _irq4_isp, IRQ4_ISP_V, ___ISR_Handler); +isp( _irq5_isp, IRQ5_ISP_V, ___ISR_Handler); +isp( _irq6_isp, IRQ6_ISP_V, ___ISR_Handler); +isp( _irq7_isp, IRQ7_ISP_V, ___ISR_Handler); + +/***************************** + * DMA - controller + *****************************/ +isp( _dma0_isp, DMA0_ISP_V, ___ISR_Handler); +isp( _dma1_isp, DMA1_ISP_V, ___ISR_Handler); +isp( _dma2_isp, DMA2_ISP_V, ___ISR_Handler); +isp( _dma3_isp, DMA3_ISP_V, ___ISR_Handler); + + +/***************************** + * Interrupt timer unit + *****************************/ + +/***************************** + * Timer 0 + *****************************/ +isp( _imia0_isp, IMIA0_ISP_V, ___ISR_Handler); +isp( _imib0_isp, IMIB0_ISP_V, ___ISR_Handler); +isp( _ovi0_isp, OVI0_ISP_V, ___ISR_Handler); + +/***************************** + * Timer 1 + *****************************/ +isp( _imia1_isp, IMIA1_ISP_V, ___ISR_Handler); +isp( _imib1_isp, IMIB1_ISP_V, ___ISR_Handler); +isp( _ovi1_isp, OVI1_ISP_V, ___ISR_Handler); + +/***************************** + * Timer 2 + *****************************/ +isp( _imia2_isp, IMIA2_ISP_V, ___ISR_Handler); +isp( _imib2_isp, IMIB2_ISP_V, ___ISR_Handler); +isp( _ovi2_isp, OVI2_ISP_V, ___ISR_Handler); + +/***************************** + * Timer 3 + *****************************/ +isp( _imia3_isp, IMIA3_ISP_V, ___ISR_Handler); +isp( _imib3_isp, IMIB3_ISP_V, ___ISR_Handler); +isp( _ovi3_isp, OVI3_ISP_V, ___ISR_Handler); + +/***************************** + * Timer 4 + *****************************/ +isp( _imia4_isp, IMIA4_ISP_V, ___ISR_Handler); +isp( _imib4_isp, IMIB4_ISP_V, ___ISR_Handler); +isp( _ovi4_isp, OVI4_ISP_V, ___ISR_Handler); + + +/***************************** + * Serial interfaces + *****************************/ + +/***************************** + * Serial interface 0 + *****************************/ +isp( _eri0_isp, ERI0_ISP_V, ___ISR_Handler); +isp( _rxi0_isp, RXI0_ISP_V, ___ISR_Handler); +isp( _txi0_isp, TXI0_ISP_V, ___ISR_Handler); +isp( _tei0_isp, TEI0_ISP_V, ___ISR_Handler); + +/***************************** + * Serial interface 1 + *****************************/ +isp( _eri1_isp, ERI1_ISP_V, ___ISR_Handler); +isp( _rxi1_isp, RXI1_ISP_V, ___ISR_Handler); +isp( _txi1_isp, TXI1_ISP_V, ___ISR_Handler); +isp( _tei1_isp, TEI1_ISP_V, ___ISR_Handler); + + +/***************************** + * Parity control unit of + * the bus state controller + *****************************/ +isp( _prt_isp, PRT_ISP_V, ___ISR_Handler); + + +/****************************** + * Analog digital converter + * ADC + ******************************/ +isp( _adu_isp, ADU_ISP_V, ___ISR_Handler); + + +/****************************** + * Watchdog timer + ******************************/ +isp( _wdt_isp, WDT_ISP_V, ___ISR_Handler); + + +/****************************** + * DRAM refresh control unit + * of bus state controller + ******************************/ +isp( _dref_isp, DREF_ISP_V, ___ISR_Handler); diff --git a/bsps/sh/gensh1/start/linkcmds b/bsps/sh/gensh1/start/linkcmds new file mode 100644 index 0000000000..d268d4cfc7 --- /dev/null +++ b/bsps/sh/gensh1/start/linkcmds @@ -0,0 +1,230 @@ +/* + * This is an adapted linker script from egcs-1.0.1 + * + * Memory layout for an SH 7032 with main memory in area 2 + * This memory layout it very similar to that used for Hitachi's + * EVB with CMON in rom + * + * NOTE: The ram start address may vary, all other start addresses are fixed + * Not suiteable for gdb's simulator + * + * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and + * Bernd Becker (becker@faw.uni-ulm.de) + * + * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * + * COPYRIGHT (c) 1998. + * 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. + */ + +OUTPUT_ARCH(sh) +ENTRY(_start) +STARTUP(start.o) + +_RamBase = DEFINED(_RamBase) ? _RamBase : 0x0a040000; +_RamSize = DEFINED(_RamSize) ? _RamSize : 512K; +_HeapSize = DEFINED(_HeapSize) ? _HeapSize : 0x0; + +MEMORY +{ + rom : o = 0x00000000, l = 128k + onchip_peri : o = 0x05000000, l = 512 + ram : o = 0x0A040000, l = 512k /* enough to link all tests */ + + onchip_ram : o = 0x0f000000, l = 8k +} + +SECTIONS +{ + /* boot vector table */ + .monvects 0x00000000 (NOLOAD): { + _monvects = . ; + } > rom + + /* monitor play area */ + .monram 0x0A040000 (NOLOAD) : + { + _ramstart = .; + } > ram + + /* monitor vector table */ + .vects 0x0A042000 (NOLOAD) : { + _vectab = . ; + *(.vects); + } + + /* Read-only sections, merged into text segment: */ + + . = 0x0a044000 ; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rela.dyn : + { + *(.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.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } >ram + .rel.text : + { *(.rel.text) *(.rel.gnu.linkonce.t*) } + .rel.data : + { *(.rel.data) *(.rel.gnu.linkonce.d*) } + .rel.rodata : + { *(.rel.rodata*) *(.rel.gnu.linkonce.r*) } + .rel.got : { *(.rel.got) } + .rel.ctors : { *(.rel.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rel.init : { *(.rel.init) } + .rel.fini : { *(.rel.fini) } + .rel.bss : { *(.rel.bss) } + .rel.plt : { *(.rel.plt) } + .plt : { *(.plt) } + .text . : + { + _start = .; + *(.text*) + *(.stub) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + ___start_set_sysctl_set = .; + *(set_sysc*); /* set_sysctl_* but name is truncated by SH-coff */ + __stop_set_sysctl_set = ABSOLUTE(.); + ___stop_set_sysctl_set = ABSOLUTE(.); + *(set_doma*); /* set_domain_* but name is truncated by SH-coff */ + *(set_pseu*); /* set_pseudo_* but name is truncated by SH-coff */ + + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } > ram + _etext = .; + PROVIDE (etext = .); + .init . : { KEEP(*(.init)) } > ram =0 + .fini . : { KEEP(*(.fini)) } > ram =0 + .ctors . : { KEEP(*(.ctors)) } > ram =0 + .dtors . : { KEEP(*(.dtors)) } > ram =0 + .rodata . : { *(.rodata*) KEEP (*(SORT(.rtemsroset.*))) *(.gnu.linkonce.r*) } > ram + .rodata1 . : { *(.rodata1) } > ram + .tdata : { + __TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + __TLS_Data_end = .; + } > ram + .tbss : { + __TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + __TLS_BSS_end = .; + } > ram + __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)); + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(128) + (. & (128 - 1)); + .data . : + { + *(.data*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gcc_exc*) + ___EH_FRAME_BEGIN__ = .; + *(.eh_fram*) + ___EH_FRAME_END__ = .; + LONG(0); + *(.gcc_except_table*) + *(.gnu.linkonce.d*) + CONSTRUCTORS + } > ram + .data1 . : { *(.data1) } + .got . : { *(.got.plt) *(.got) } + .dynamic . : { *(.dynamic) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata . : { *(.sdata) } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + .sbss . : { *(.sbss*) *(.scommon) } + .bss . : + { + *(.dynbss) + *(.bss .bss* .gnu.linkonce.b*) + *(COMMON) + } > ram + _end = . ; + PROVIDE (end = .); + + _WorkAreaBase = . ; + + _CPU_Interrupt_stack_low = 0x0f000000 ; + _CPU_Interrupt_stack_high = _CPU_Interrupt_stack_low + 4096 ; + + /* 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) } + .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) } + + stack : { _stack = .; *(.stack) } > onchip_ram + /* These must appear regardless of . */ +} diff --git a/bsps/sh/gensh2/start/bsp_specs b/bsps/sh/gensh2/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/sh/gensh2/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/sh/gensh2/start/cpu_asm.c b/bsps/sh/gensh2/start/cpu_asm.c new file mode 100644 index 0000000000..47bc859dbd --- /dev/null +++ b/bsps/sh/gensh2/start/cpu_asm.c @@ -0,0 +1,182 @@ +/* + * This file contains the basic algorithms for all assembly code used + * in an specific CPU port of RTEMS. These algorithms must be implemented + * in assembly language + * + * NOTE: This port uses a C file with inline assembler instructions + * + * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and + * Bernd Becker (becker@faw.uni-ulm.de) + * + * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * + * COPYRIGHT (c) 1998. + * 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. + */ + +/* + * This is supposed to be an assembly file. This means that system.h + * and cpu.h should not be included in a "real" cpu_asm file. An + * implementation in assembly should include "cpu_asm.h" + */ + +#include <rtems/system.h> +#include <rtems/score/cpu.h> +#include <rtems/score/isr.h> +#include <rtems/score/threaddispatch.h> +#include <rtems/score/sh.h> + +#include <rtems/score/ispsh7045.h> +#include <rtems/score/iosh7045.h> +#include <rtems/score/sh_io.h> + +/* from cpu_isps.c */ +extern proc_ptr _Hardware_isr_Table[]; + +#if (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + unsigned long *_old_stack_ptr; +#endif + +register unsigned long *stack_ptr __asm__ ("r15"); + +/* + * sh_set_irq_priority + * + * this function sets the interrupt level of the specified interrupt + * + * parameters: + * - irq : interrupt number + * - prio: priority to set for this interrupt number + * + * returns: 0 if ok + * -1 on error + */ + +unsigned int sh_set_irq_priority( + unsigned int irq, + unsigned int prio ) +{ + uint32_t shiftcount; + uint32_t prioreg; + uint16_t temp16; + ISR_Level level; + + /* + * first check for valid interrupt + */ + if (( irq > 156) || (irq < 64) || (_Hardware_isr_Table[irq] == _dummy_isp)) + return -1; + /* + * check for valid irq priority + */ + if ( prio > 15 ) + return -1; + + /* + * look up appropriate interrupt priority register + */ + if ( irq > 71) + { + irq = irq - 72; + shiftcount = 12 - ((irq & ~0x03) % 16); + + switch( irq / 16) + { + case 0: { prioreg = INTC_IPRC; break;} + case 1: { prioreg = INTC_IPRD; break;} + case 2: { prioreg = INTC_IPRE; break;} + case 3: { prioreg = INTC_IPRF; break;} + case 4: { prioreg = INTC_IPRG; break;} + case 5: { prioreg = INTC_IPRH; break;} + default: return -1; + } + } + else + { + shiftcount = 12 - 4 * ( irq % 4); + if ( irq > 67) + prioreg = INTC_IPRB; + else + prioreg = INTC_IPRA; + } + + /* + * Set the interrupt priority register + */ + _ISR_Local_disable( level ); + + temp16 = read16( prioreg); + temp16 &= ~( 15 << shiftcount); + temp16 |= prio << shiftcount; + write16( temp16, prioreg); + + _ISR_Local_enable( level ); + + return 0; +} + +/* + * This routine provides the RTEMS interrupt management. + */ + +void __ISR_Handler( uint32_t vector) +{ + ISR_Level level; + + _ISR_Local_disable( level ); + + _Thread_Dispatch_disable(); + +#if (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + if ( _ISR_Nest_level == 0 ) + { + /* Install irq stack */ + _old_stack_ptr = stack_ptr; + stack_ptr = _CPU_Interrupt_stack_high; + } + +#endif + + _ISR_Nest_level++; + + _ISR_Local_enable( level ); + + /* call isp */ + if ( _ISR_Vector_table[ vector]) + (*_ISR_Vector_table[ vector ])( vector ); + + _ISR_Local_disable( level ); + + _Thread_Dispatch_unnest( _Per_CPU_Get() ); + + _ISR_Nest_level--; + +#if (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + + if ( _ISR_Nest_level == 0 ) + /* restore old stack pointer */ + stack_ptr = _old_stack_ptr; +#endif + + _ISR_Local_enable( level ); + + if ( _ISR_Nest_level ) + return; + + if ( !_Thread_Dispatch_is_enabled() ) { + return; + } + + if ( _Thread_Dispatch_necessary ) { + _Thread_Dispatch(); + } +} diff --git a/bsps/sh/gensh2/start/hw_init.c b/bsps/sh/gensh2/start/hw_init.c new file mode 100644 index 0000000000..f3cbb54ecf --- /dev/null +++ b/bsps/sh/gensh2/start/hw_init.c @@ -0,0 +1,112 @@ +/* + * hw_init.c: set up sh7045F internal subunits + * Pin and memory assignments assume + * target is Hitachi SH7045F EVB ("lcevb") + * + * Provides two initialization routines: + * A. 'void early_hw_init(void)' for 'start.S' + * sets up hw needed for early RTEMS boot, and + * B. 'void bsp_hw_init(void)' for 'bspstart.c' + * sets up hardware used by this BSP. + * + * Author: John M. Mills (jmills@tga.com) + * COPYRIGHT(c) 2000, TGA Technologies, Inc + * Norcross, GA 30071 U.S.A + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * + * 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. + * + * Adapted from Hitachi EVB7045F tutorial files by: + * John M. Mills (jmills@tga.com) + * TGA Technologies, Inc. + * 100 Pinnacle Way, Suite 140 + * Norcross, GA 30071 U.S.A. + * + * + * This file may be copied and distributed in accordance + * the above-referenced license. It is provided for critique and + * developmental purposes without any warranty nor representation + * by the authors or by TGA Technologies. + */ + +#include <bsp.h> + +#include <stdlib.h> + +#include <rtems/libio.h> +#include <rtems/score/sh_io.h> +#include <rtems/score/iosh7045.h> + +/* exported entries */ +extern void bsp_hw_init (void); +extern void early_hw_init (void); + +/* called from 'start.S' on "#ifdef START_HW_INIT" */ +void early_hw_init (void) +{ +#ifdef STANDALONE_EVB + /* STANDALONE_EVB minimally sets up bus and DRAM here */ + /* no STANDALONE_EVB accepts defaults from debug monitor */ + + /* FIXME: replace 'magic numbers' with logical names */ + + write16(0x2020, BSC_BCR1); /* Bus width access - 32-bit on CS1 */ + write16(0xF3DD, BSC_BCR2); /* Idle cycles CS3-CS0 - 0 idle cycles*/ + write16(0xFF3F, BSC_WCR1); /* Waits for CS3-CS0 - 3 waits on CS1 */ + write16(0x000F, BSC_WCR2); /* Waits for DRAM/DMA access - default */ + write16(0x0000, BSC_DCR); /* DRAM control - default */ + write16(0x0000, BSC_RTCSR); /* DRAM refresh - default */ + write16(0x0000, BSC_RTCNT); /* DRAM refresh counter - default*/ + write16(0x0000, BSC_RTCOR); /* DRAM refresh compare match - default */ +#endif + + /* add early-init functions here */ + +}; + +/* to be called from 'bspstart.c' */ +void bsp_hw_init (void) +{ + uint16_t temp16; + +#ifdef STANDALONE_EVB + /* STANDALONE_EVB: sets up PFC */ + /* no STANDALONE_EVB: accepts defaults, adds RESET */ + + /* FIXME: replace 'magic numbers' */ + + write16(0x5000, PFC_PACRH); /* Pin function controller - WRHH, WRHL */ + write16(0x1550, PFC_PACRL1); /* Pin fun. controller - WRH,WRL,RD,CS1 */ + write16(0x0000, PFC_PBCR1); /* Pin function controller - default */ + write16(0x2005, PFC_PBCR2); /* Pin fcn. controller - A18,A17,A16 */ + write16(0xFFFF, PFC_PCCR); /* Pin function controller - A15-A0 */ + write16(0x5555, PFC_PDCRH1); /* Pin function controller - D31-D24 */ + write16(0x5555, PFC_PDCRH2); /* Pin function controller - D23-D16 */ + write16(0xFFFF, PFC_PDCRL); /* Pin function controller - D15-D0 */ + write16(0x0000, PFC_IFCR); /* Pin function controller - default */ + write16(0x0000, PFC_PACRL2); /* default disconnects all I/O pins;*/ + /* [re-connected by DEVICE_open()] */ +#endif + + /* default hardware setup for SH7045F EVB */ + + /* PFC: General I/O except pin 13 (reset): */ + temp16 = read16(PFC_PECR1); + temp16 |= 0x0800; + write16(temp16, PFC_PECR1); + + /* All I/O lines bits 7-0: */ + write16(0x00, PFC_PECR2); + + /* P5 (LED) out, all other pins in: */ + temp16 = read16(PFC_PEIOR); + temp16 |= 0x0020; + write16(temp16, PFC_PEIOR); + +} diff --git a/bsps/sh/gensh2/start/ispsh7045.c b/bsps/sh/gensh2/start/ispsh7045.c new file mode 100644 index 0000000000..4e6dabed3f --- /dev/null +++ b/bsps/sh/gensh2/start/ispsh7045.c @@ -0,0 +1,310 @@ +/* + * This file contains the isp frames for the user interrupts. + * From these procedures __ISR_Handler is called with the vector number + * as argument. + * + * __ISR_Handler is kept in a separate file (cpu_asm.c), because a bug in + * some releases of gcc doesn't properly handle #pragma interrupt, if a + * file contains both isrs and normal functions. + * + * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and + * Bernd Becker (becker@faw.uni-ulm.de) + * + * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE + * + * + * COPYRIGHT (c) 1998. + * 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. + * + * Modified to reflect isp entries for sh7045 processor: + * John M. Mills (jmills@tga.com) + * TGA Technologies, Inc. + * 100 Pinnacle Way, Suite 140 + * Norcross, GA 30071 U.S.A. + * August, 1999 + * + * This modified file may be copied and distributed in accordance + * the above-referenced license. It is provided for critique and + * developmental purposes without any warranty nor representation + * by the authors or by TGA Technologies. + */ + +#include <rtems/system.h> + +/* + * This is a exception vector table + * + * It has the same structure as the actual vector table (vectab) + */ + + +/* SH-2 ISR Table */ +#include <rtems/score/ispsh7045.h> + +proc_ptr _Hardware_isr_Table[256]={ +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, /* PWRon Reset, Maual Reset,...*/ +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, +_nmi_isp, _usb_isp, /* irq 11, 12*/ +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, +/* trapa 0 -31 */ +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_irq0_isp, _irq1_isp, _irq2_isp, _irq3_isp, /* external H/W: irq 64-71 */ +_irq4_isp, _irq5_isp, _irq6_isp, _irq7_isp, +_dma0_isp, _dummy_isp, _dummy_isp, _dummy_isp, /* DMAC: irq 72-87*/ +_dma1_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dma2_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dma3_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_mtua0_isp, _mtub0_isp, _mtuc0_isp, _mtud0_isp, /* MTUs: irq 88-127 */ +_mtuv0_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_mtua1_isp, _mtub1_isp, _dummy_isp, _dummy_isp, +_mtuv1_isp, _mtuu1_isp, _dummy_isp, _dummy_isp, +_mtua2_isp, _mtub2_isp, _dummy_isp, _dummy_isp, +_mtuv2_isp, _mtuu2_isp, _dummy_isp, _dummy_isp, +_mtua3_isp, _mtub3_isp, _mtuc3_isp, _mtud3_isp, +_mtuv3_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_mtua4_isp, _mtub4_isp, _mtuc4_isp, _mtud4_isp, +_mtuv4_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_eri0_isp, _rxi0_isp, _txi0_isp, _tei0_isp, /* SCI0-1: irq 128-135*/ +_eri1_isp, _rxi1_isp, _txi1_isp, _tei1_isp, +_adi0_isp, _adi1_isp, _dummy_isp, _dummy_isp, /* ADC0-1: irq 136-139*/ +_dtci_isp, _dummy_isp, _dummy_isp, _dummy_isp, /* DTU: irq 140-143 */ +_cmt0_isp, _dummy_isp, _dummy_isp, _dummy_isp, /* CMT0-1: irq 144-151 */ +_cmt1_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_wdt_isp, /* WDT: irq 152*/ +_bsc_isp, _dummy_isp, _dummy_isp, /* BSC: irq 153-155*/ +_oei_isp, /* I/O Port: irq 156*/ +}; + +#define Str(a)#a + +/* + * Some versions of gcc and all version of egcs at least until egcs-1.1b + * are not able to handle #pragma interrupt correctly if more than 1 isr is + * contained in a file and when optimizing. + * We try to work around this problem by using the macro below. + */ +#define isp( name, number, func)\ +__asm__ (".global _"Str(name)"\n\t"\ + "_"Str(name)": \n\t"\ + " mov.l r0,@-r15 \n\t"\ + " mov.l r1,@-r15 \n\t"\ + " mov.l r2,@-r15 \n\t"\ + " mov.l r3,@-r15 \n\t"\ + " mov.l r4,@-r15 \n\t"\ + " mov.l r5,@-r15 \n\t"\ + " mov.l r6,@-r15 \n\t"\ + " mov.l r7,@-r15 \n\t"\ + " mov.l r14,@-r15 \n\t"\ + " sts.l pr,@-r15 \n\t"\ + " sts.l mach,@-r15 \n\t"\ + " sts.l macl,@-r15 \n\t"\ + " mov r15,r14 \n\t"\ + " mov.l "Str(name)"_v, r2 \n\t"\ + " mov.l "Str(name)"_k, r1\n\t"\ + " jsr @r1 \n\t"\ + " mov r2,r4 \n\t"\ + " mov r14,r15 \n\t"\ + " lds.l @r15+,macl \n\t"\ + " lds.l @r15+,mach \n\t"\ + " lds.l @r15+,pr \n\t"\ + " mov.l @r15+,r14 \n\t"\ + " mov.l @r15+,r7 \n\t"\ + " mov.l @r15+,r6 \n\t"\ + " mov.l @r15+,r5 \n\t"\ + " mov.l @r15+,r4 \n\t"\ + " mov.l @r15+,r3 \n\t"\ + " mov.l @r15+,r2 \n\t"\ + " mov.l @r15+,r1 \n\t"\ + " mov.l @r15+,r0 \n\t"\ + " rte \n\t"\ + " nop \n\t"\ + " .align 2 \n\t"\ + #name"_k: \n\t"\ + ".long "Str(func)"\n\t"\ + #name"_v: \n\t"\ + ".long "Str(number)); + +/************************************************ + * Dummy interrupt service procedure for + * interrupts being not allowed --> Trap 34 + ************************************************/ +__asm__ (" .section .text\n\ +.global __dummy_isp\n\ +__dummy_isp:\n\ + mov.l r14,@-r15\n\ + mov r15, r14\n\ + trapa #34\n\ + mov.l @r15+,r14\n\ + rte\n\ + nop"); + +/******************************************************************* + * ISP Vector Table for sh7045 family of processors * + *******************************************************************/ + + +/***************************** + * Non maskable interrupt + *****************************/ +isp( _nmi_isp, NMI_ISP_V, ___ISR_Handler); + +/***************************** + * User break controller + *****************************/ +isp( _usb_isp, USB_ISP_V, ___ISR_Handler); + +/***************************** + * External interrupts 0-7 + *****************************/ +isp( _irq0_isp, IRQ0_ISP_V, ___ISR_Handler); +isp( _irq1_isp, IRQ1_ISP_V, ___ISR_Handler); +isp( _irq2_isp, IRQ2_ISP_V, ___ISR_Handler); +isp( _irq3_isp, IRQ3_ISP_V, ___ISR_Handler); +isp( _irq4_isp, IRQ4_ISP_V, ___ISR_Handler); +isp( _irq5_isp, IRQ5_ISP_V, ___ISR_Handler); +isp( _irq6_isp, IRQ6_ISP_V, ___ISR_Handler); +isp( _irq7_isp, IRQ7_ISP_V, ___ISR_Handler); + +/***************************** + * DMA - controller + *****************************/ +isp( _dma0_isp, DMA0_ISP_V, ___ISR_Handler); +isp( _dma1_isp, DMA1_ISP_V, ___ISR_Handler); +isp( _dma2_isp, DMA2_ISP_V, ___ISR_Handler); +isp( _dma3_isp, DMA3_ISP_V, ___ISR_Handler); + + +/***************************** + * Match timer unit + *****************************/ + +/***************************** + * Timer 0 + *****************************/ +isp( _mtua0_isp, MTUA0_ISP_V, ___ISR_Handler); +isp( _mtub0_isp, MTUB0_ISP_V, ___ISR_Handler); +isp( _mtuc0_isp, MTUC0_ISP_V, ___ISR_Handler); +isp( _mtud0_isp, MTUD0_ISP_V, ___ISR_Handler); +isp( _mtuv0_isp, MTUV0_ISP_V, ___ISR_Handler); + +/***************************** + * Timer 1 + *****************************/ +isp( _mtua1_isp, MTUA1_ISP_V, ___ISR_Handler); +isp( _mtub1_isp, MTUB1_ISP_V, ___ISR_Handler); +isp( _mtuv1_isp, MTUV1_ISP_V, ___ISR_Handler); +isp( _mtuu1_isp, MTUU1_ISP_V, ___ISR_Handler); + +/***************************** + * Timer 2 + *****************************/ +isp( _mtua2_isp, MTUA2_ISP_V, ___ISR_Handler); +isp( _mtub2_isp, MTUB2_ISP_V, ___ISR_Handler); +isp( _mtuv2_isp, MTUV2_ISP_V, ___ISR_Handler); +isp( _mtuu2_isp, MTUU2_ISP_V, ___ISR_Handler); + +/***************************** + * Timer 3 + *****************************/ +isp( _mtua3_isp, MTUA3_ISP_V, ___ISR_Handler); +isp( _mtub3_isp, MTUB3_ISP_V, ___ISR_Handler); +isp( _mtuc3_isp, MTUC3_ISP_V, ___ISR_Handler); +isp( _mtud3_isp, MTUD3_ISP_V, ___ISR_Handler); +isp( _mtuv3_isp, MTUV3_ISP_V, ___ISR_Handler); + +/***************************** + * Timer 4 + *****************************/ +isp( _mtua4_isp, MTUA4_ISP_V, ___ISR_Handler); +isp( _mtub4_isp, MTUB4_ISP_V, ___ISR_Handler); +isp( _mtuc4_isp, MTUC4_ISP_V, ___ISR_Handler); +isp( _mtud4_isp, MTUD4_ISP_V, ___ISR_Handler); +isp( _mtuv4_isp, MTUV4_ISP_V, ___ISR_Handler); + + +/***************************** + * Serial interfaces + *****************************/ + +/***************************** + * Serial interface 0 + *****************************/ +isp( _eri0_isp, ERI0_ISP_V, ___ISR_Handler); +isp( _rxi0_isp, RXI0_ISP_V, ___ISR_Handler); +isp( _txi0_isp, TXI0_ISP_V, ___ISR_Handler); +isp( _tei0_isp, TEI0_ISP_V, ___ISR_Handler); + +/***************************** + * Serial interface 1 + *****************************/ +isp( _eri1_isp, ERI1_ISP_V, ___ISR_Handler); +isp( _rxi1_isp, RXI1_ISP_V, ___ISR_Handler); +isp( _txi1_isp, TXI1_ISP_V, ___ISR_Handler); +isp( _tei1_isp, TEI1_ISP_V, ___ISR_Handler); + + +/****************************** + * A/D converters + * ADC0-1 + ******************************/ +isp( _adi0_isp, ADI0_ISP_V, ___ISR_Handler); +isp( _adi1_isp, ADI1_ISP_V, ___ISR_Handler); + + +/****************************** + * Data transfer controller + ******************************/ +isp( _dtci_isp, DTC_ISP_V, ___ISR_Handler); + + +/****************************** + * Counter match timer + ******************************/ +isp( _cmt0_isp, CMT0_ISP_V, ___ISR_Handler); +isp( _cmt1_isp, CMT1_ISP_V, ___ISR_Handler); + + +/****************************** + * Watchdog timer + ******************************/ +isp( _wdt_isp, WDT_ISP_V, ___ISR_Handler); + + +/****************************** + * DRAM refresh control unit + * of bus state controller + ******************************/ +isp( _bsc_isp, CMI_ISP_V, ___ISR_Handler); + +/****************************** + * I/O port + ******************************/ +isp( _oei_isp, OEI_ISP_V, ___ISR_Handler); + + +/***************************** + * Parity control unit of + * the bus state controller + * NOT PROVIDED IN SH-2 + *****************************/ +/* isp( _prt_isp, PRT_ISP_V, ___ISR_Handler); */ diff --git a/bsps/sh/gensh2/start/linkcmds b/bsps/sh/gensh2/start/linkcmds new file mode 100644 index 0000000000..2c4d44a941 --- /dev/null +++ b/bsps/sh/gensh2/start/linkcmds @@ -0,0 +1,241 @@ +/* + * This is an adapted linker script from egcs-1.0.1 + * + * Memory layout for an SH7045F with main memory in area 2 + * This memory layout it very similar to that used for Hitachi's + * EVB with CMON in FLASH + * + * NOTE: The ram start address may vary, all other start addresses are fixed + * Not suiteable for gdb's simulator + * + * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and + * Bernd Becker (becker@faw.uni-ulm.de) + * + * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * + * COPYRIGHT (c) 1998. + * 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. + * + * Modified to reflect SH7045F processor and EVB: + * John M. Mills (jmills@tga.com) + * TGA Technologies, Inc. + * 100 Pinnacle Way, Suite 140 + * Norcross, GA 30071 U.S.A. + * + * This modified file may be copied and distributed in accordance + * the above-referenced license. It is provided for critique and + * developmental purposes without any warranty nor representation + * by the authors or by TGA Technologies. + */ + +OUTPUT_ARCH(sh) +ENTRY(_start) +STARTUP(start.o) + +/* These assignments load code into SH7045F EVB SRAM for monitor debugging */ + +_RamBase = DEFINED(_RamBase) ? _RamBase : 0x00440000; +_RamSize = DEFINED(_RamSize) ? _RamSize : 512K; +_HeapSize = DEFINED(_HeapSize) ? _HeapSize : 0x0; + +MEMORY +{ + rom : o = 0x00400000, l = 0x00040000 + ram : o = 0x00440000, l = 0x00080000 + onchip_peri : o = 0xFFFF8000, l = 0x00000800 + onchip_ram : o = 0xFFFFF000, l = 0x00001000 +} + +/* Sections are defined for RAM loading and monitor debugging */ +SECTIONS +{ + /* boot vector table */ + .monvects 0x00400000 (NOLOAD): { + _monvects = . ; + } > rom + + /* monitor play area */ + .monram 0x00440000 (NOLOAD) : + { + _ramstart = .; + } > ram + + /* monitor vector table */ + .vects 0x00442000 (NOLOAD) : { + _vectab = . ; + *(.vects); + } + + /* Read-only sections, merged into text segment: */ + + . = 0x00444000 ; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rela.dyn : + { + *(.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.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } >ram + .rel.text : + { *(.rel.text) *(.rel.gnu.linkonce.t*) } + .rel.data : + { *(.rel.data) *(.rel.gnu.linkonce.d*) } + .rel.rodata : + { *(.rel.rodata*) *(.rel.gnu.linkonce.r*) } + .rel.got : { *(.rel.got) } + .rel.ctors : { *(.rel.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rel.init : { *(.rel.init) } + .rel.fini : { *(.rel.fini) } + .rel.bss : { *(.rel.bss) } + .rel.plt : { *(.rel.plt) } + .plt : { *(.plt) } + .text . : + { + _start = .; + *(.text*) + *(.stub) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + ___start_set_sysctl_set = .; + *(set_sysc*); /* set_sysctl_* but name is truncated by SH-coff */ + ___stop_set_sysctl_set = ABSOLUTE(.); + *(set_doma*); /* set_domain_* but name is truncated by SH-coff */ + *(set_pseu*); /* set_pseudo_* but name is truncated by SH-coff */ + + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } > ram + _etext = .; + PROVIDE (etext = .); + .init . : { KEEP(*(.init)) } > ram =0 + .fini . : { KEEP(*(.fini)) } > ram =0 + .ctors . : { KEEP(*(.ctors)) } > ram =0 + .dtors . : { KEEP(*(.dtors)) } > ram =0 + .rodata . : { *(.rodata*) KEEP (*(SORT(.rtemsroset.*))) *(.gnu.linkonce.r*) } > ram + .rodata1 . : { *(.rodata1) } > ram + .tdata : { + __TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + __TLS_Data_end = .; + } > ram + .tbss : { + __TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + __TLS_BSS_end = .; + } > ram + __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)); + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(128) + (. & (128 - 1)); + .data . : + { + *(.data*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gcc_exc*) + ___EH_FRAME_BEGIN__ = .; + *(.eh_fram*) + ___EH_FRAME_END__ = .; + LONG(0); + *(.gcc_except_table*) + *(.gnu.linkonce.d*) + CONSTRUCTORS + } > ram + .data1 . : { *(.data1) } + .got . : { *(.got.plt) *(.got) } + .dynamic . : { *(.dynamic) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata . : { *(.sdata) } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + .sbss . : { *(.sbss*) *(.scommon) } + .bss . : + { + *(.dynbss) + *(.bss .bss* .gnu.linkonce.b*) + *(COMMON) + } > ram + _end = . ; + PROVIDE (end = .); + + _WorkAreaBase = . ; + + _CPU_Interrupt_stack_low = 0xFFFFF000; + _CPU_Interrupt_stack_high = 0xFFFFFFFF; + + /* 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) } + .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) } + + .stack 0xFFFFFEC0 : { _stack = .; *(.stack) } > onchip_ram + /* These must appear regardless of . */ +} diff --git a/bsps/sh/gensh2/start/linkcmds.ram b/bsps/sh/gensh2/start/linkcmds.ram new file mode 100644 index 0000000000..c5349398ff --- /dev/null +++ b/bsps/sh/gensh2/start/linkcmds.ram @@ -0,0 +1,244 @@ +/* + * This is an adapted linker script from egcs-1.0.1 + * + * Memory layout for an SH7045F with main memory in area 2 + * This memory layout it very similar to that used for Hitachi's + * EVB with CMON in FLASH + * + * NOTE: The ram start address may vary, all other start addresses are fixed + * Not suiteable for gdb's simulator + * + * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and + * Bernd Becker (becker@faw.uni-ulm.de) + * + * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * + * COPYRIGHT (c) 1998. + * 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. + * + * Modified to reflect SH7045F processor and EVB: + * John M. Mills (jmills@tga.com) + * TGA Technologies, Inc. + * 100 Pinnacle Way, Suite 140 + * Norcross, GA 30071 U.S.A. + * + * This modified file may be copied and distributed in accordance + * the above-referenced license. It is provided for critique and + * developmental purposes without any warranty nor representation + * by the authors or by TGA Technologies. + */ + +OUTPUT_ARCH(sh) +ENTRY(_start) +STARTUP(start.o) + +/* These assignments load code into SH7045F EVB SRAM for monitor debugging */ +_RamBase = DEFINED(_RamBase) ? _RamBase : 0x00440000; +_RamSize = DEFINED(_RamSize) ? _RamSize : 512K; +_HeapSize = DEFINED(_HeapSize) ? _HeapSize : 0x0; + +MEMORY +{ + rom : o = 0x00400000, l = 0x00040000 + ram : o = 0x00440000, l = 0x00080000 + onchip_peri : o = 0xFFFF8000, l = 0x00000800 + onchip_ram : o = 0xFFFFF000, l = 0x00001000 +} + +/* Sections are defined for RAM loading and monitor debugging */ +SECTIONS +{ + /* boot vector table */ + .monvects 0x00400000 (NOLOAD): { + _monvects = . ; + } > rom + + /* monitor play area */ + .monram 0x00440000 (NOLOAD) : + { + _ramstart = .; + } > ram + + /* monitor vector table */ + .vects 0x00442000 (NOLOAD) : { + _vectab = . ; + *(.vects); + } + + /* Read-only sections, merged into text segment: */ + + . = 0x00444000 ; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rela.dyn : + { + *(.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.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } >ram + .rel.text : + { *(.rel.text) *(.rel.gnu.linkonce.t*) } + .rel.data : + { *(.rel.data) *(.rel.gnu.linkonce.d*) } + .rel.rodata : + { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } + .rel.got : { *(.rel.got) } + .rel.ctors : { *(.rel.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rel.init : { *(.rel.init) } + .rel.fini : { *(.rel.fini) } + .rel.bss : { *(.rel.bss) } + .rel.plt : { *(.rel.plt) } + .init : { *(.init) } =0 + .plt : { *(.plt) } + .text . : + { + *(.text*) + *(.stub) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + ___start_set_sysctl_set = .; + *(set_sysc*); /* set_sysctl_* but name is truncated by SH-coff */ + ___stop_set_sysctl_set = ABSOLUTE(.); + *(set_doma*); /* set_domain_* but name is truncated by SH-coff */ + *(set_pseudo_*); + + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } > ram + _etext = .; + PROVIDE (etext = .); + .fini . : { *(.fini) } > ram =0 + .rodata . : { *(.rodata) KEEP (*(SORT(.rtemsroset.*))) *(.gnu.linkonce.r*) } > ram + .rodata1 . : { *(.rodata1) } > ram + .tdata : { + __TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + __TLS_Data_end = .; + } > ram + .tbss : { + __TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + __TLS_BSS_end = .; + } > ram + __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)); + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(128) + (. & (128 - 1)); + .data . : + { + *(.data) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + CONSTRUCTORS + } > ram + .data1 . : { *(.data1) } + .ctors . : + { + ___ctors = .; + *(.ctors) + ___ctors_end = .; + } + .dtors . : + { + ___dtors = .; + *(.dtors) + ___dtors_end = .; + } + .got . : { *(.got.plt) *(.got) } + .dynamic . : { *(.dynamic) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata . : { *(.sdata) } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + .sbss . : { *(.sbss*) *(.scommon) } + .bss . : + { + *(.dynbss) + *(.bss .bss* .gnu.linkonce.b*) + *(COMMON) + } > ram + _end = . ; + PROVIDE (end = .); + + _WorkAreaBase = . ; + . = 0x00480000 ; + + _CPU_Interrupt_stack_low = 0xFFFFF000; + _CPU_Interrupt_stack_high = 0xFFFFFFFF; + + /* 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) } + .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) } + + .stack 0xFFFFFEC0 : { _stack = .; *(.stack) } > onchip_ram + /* These must appear regardless of . */ +} diff --git a/bsps/sh/gensh2/start/linkcmds.rom b/bsps/sh/gensh2/start/linkcmds.rom new file mode 100644 index 0000000000..4934c10269 --- /dev/null +++ b/bsps/sh/gensh2/start/linkcmds.rom @@ -0,0 +1,248 @@ +/* + * This is an adapted linker script from egcs-1.0.1 + * + * Memory layout for an SH7045F with main memory in area 2 + * This memory layout it very similar to that used for Hitachi's + * EVB with CMON in FLASH + * + * NOTE: The ram start address may vary, all other start addresses are fixed + * Not suiteable for gdb's simulator + * + * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and + * Bernd Becker (becker@faw.uni-ulm.de) + * + * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * + * COPYRIGHT (c) 1998. + * 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. + * + * Modified to reflect SH7045F processor and EVB: + * John M. Mills (jmills@tga.com) + * TGA Technologies, Inc. + * 100 Pinnacle Way, Suite 140 + * Norcross, GA 30071 U.S.A. + * + * This modified file may be copied and distributed in accordance + * the above-referenced license. It is provided for critique and + * developmental purposes without any warranty nor representation + * by the authors or by TGA Technologies. + */ + +OUTPUT_ARCH(sh) +ENTRY(_start) +STARTUP(start.o) + +/* These asignments represent actual SH7045F EVB architecture */ +_RamBase = DEFINED(_RamBase) ? _RamBase : 0x00400000; +_RamSize = DEFINED(_RamSize) ? _RamSize : 0x0008000; +_HeapSize = DEFINED(_HeapSize) ? _HeapSize : 0x0; + +MEMORY +{ + rom : o = 0x00000000, l = 0x00040000 + ram : o = 0x00400000, l = 0x00080000 + onchip_peri : o = 0xFFFF8000, l = 0x00000800 + onchip_ram : o = 0xFFFFF000, l = 0x00001000 +} + + +/* Sections are defined for RAM loading and monitor debugging */ +SECTIONS +{ + /* boot vector table */ + .monvects 0x00000000 (NOLOAD): { + _monvects = . ; + } > rom + + /* monitor play area */ + .monram 0x00400000 (NOLOAD) : + { + _ramstart = .; + } > ram + + /* monitor vector table */ + .vects 0x00402000 (NOLOAD) : { + _vectab = . ; + *(.vects); + } + + /* Read-only sections, merged into text segment: */ + + . = 0x00404000 ; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rela.dyn : + { + *(.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.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } >ram + .rel.text : + { *(.rel.text) *(.rel.gnu.linkonce.t*) } + .rel.data : + { *(.rel.data) *(.rel.gnu.linkonce.d*) } + .rel.rodata : + { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } + .rel.got : { *(.rel.got) } + .rel.ctors : { *(.rel.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rel.init : { *(.rel.init) } + .rel.fini : { *(.rel.fini) } + .rel.bss : { *(.rel.bss) } + .rel.plt : { *(.rel.plt) } + .init : { *(.init) } =0 + .plt : { *(.plt) } + .text . : + { + *(.text*) + *(.stub) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + ___start_set_sysctl_set = .; + *(set_sysc*); /* set_sysctl_* but name is truncated by SH-coff */ + ___stop_set_sysctl_set = ABSOLUTE(.); + *(set_doma*); /* set_domain_* but name is truncated by SH-coff */ + *(set_pseudo_*); + + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } > ram + _etext = .; + PROVIDE (etext = .); + .fini . : { *(.fini) } > ram =0 + .rodata . : { *(.rodata) KEEP (*(SORT(.rtemsroset.*))) *(.gnu.linkonce.r*) } > ram + .rodata1 . : { *(.rodata1) } > ram + .tdata : { + __TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + __TLS_Data_end = .; + } > ram + .tbss : { + __TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + __TLS_BSS_end = .; + } > ram + __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)); + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(128) + (. & (128 - 1)); + .data . : + { + *(.data) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + CONSTRUCTORS + } > ram + .data1 . : { *(.data1) } + .ctors . : + { + ___ctors = .; + *(.ctors) + ___ctors_end = .; + } + .dtors . : + { + ___dtors = .; + *(.dtors) + ___dtors_end = .; + } + .got . : { *(.got.plt) *(.got) } + .dynamic . : { *(.dynamic) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata . : { *(.sdata) } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + .sbss . : { *(.sbss*) *(.scommon) } + .bss . : + { + *(.dynbss) + *(.bss .bss* .gnu.linkonce.b*) + *(COMMON) + } > ram + _end = . ; + PROVIDE (end = .); + + _HeapStart = . ; + . = . + 1024 * 20 ; + PROVIDE( _HeapEnd = . ); + + _WorkAreaBase = . ; + + _CPU_Interrupt_stack_low = 0xFFFFF000; + _CPU_Interrupt_stack_high = 0xFFFFFFFF; + + /* 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) } + .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) } + + .stack 0xFFFFFEC0 : { _stack = .; *(.stack) } > onchip_ram + /* These must appear regardless of . */ +} diff --git a/bsps/sh/gensh4/start/bsp_specs b/bsps/sh/gensh4/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/sh/gensh4/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/sh/gensh4/start/cpu_asm.c b/bsps/sh/gensh4/start/cpu_asm.c new file mode 100644 index 0000000000..52a033bb75 --- /dev/null +++ b/bsps/sh/gensh4/start/cpu_asm.c @@ -0,0 +1,105 @@ +/* + * This file contains the basic algorithms for all assembly code used + * in an specific CPU port of RTEMS. These algorithms must be implemented + * in assembly language + * + * NOTE: This port uses a C file with inline assembler instructions + * + * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and + * Bernd Becker (becker@faw.uni-ulm.de) + * + * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * + * COPYRIGHT (c) 1998. + * 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. + */ + +/* + * This is supposed to be an assembly file. This means that system.h + * and cpu.h should not be included in a "real" cpu_asm file. An + * implementation in assembly should include "cpu_asm.h" + */ + +#include <rtems/system.h> +#include <rtems/score/cpu.h> +#include <rtems/score/isr.h> +#include <rtems/score/threaddispatch.h> +#include <rtems/score/sh.h> +#include <rtems/score/ispsh7750.h> +#include <rtems/score/iosh7750.h> +#include <rtems/score/sh4_regs.h> +#include <rtems/score/sh_io.h> + +/* from cpu_isps.c */ +extern proc_ptr _Hardware_isr_Table[]; + +#if (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + unsigned long *_old_stack_ptr; +#endif + +register unsigned long *stack_ptr __asm__ ("r15"); + +/* + * This routine provides the RTEMS interrupt management. + */ + +void __ISR_Handler( uint32_t vector) +{ + ISR_Level level; + + _ISR_Local_disable( level ); + + _Thread_Dispatch_disable(); + +#if (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + if ( _ISR_Nest_level == 0 ) + { + /* Install irq stack */ + _old_stack_ptr = stack_ptr; + stack_ptr = _CPU_Interrupt_stack_high; + } + +#endif + + _ISR_Nest_level++; + + _ISR_Local_enable( level ); + + /* call isp */ + if ( _ISR_Vector_table[ vector]) + (*_ISR_Vector_table[ vector ])( vector ); + + _ISR_Local_disable( level ); + + _Thread_Dispatch_enable( _Per_CPU_Get() ); + + _ISR_Nest_level--; + +#if (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + if ( _ISR_Nest_level == 0 ) + /* restore old stack pointer */ + stack_ptr = _old_stack_ptr; +#endif + + _ISR_Local_enable( level ); + + if ( _ISR_Nest_level ) + return; + + if ( !_Thread_Dispatch_is_enabled() ) { + return; + } + + if ( _Thread_Dispatch_necessary ) { + _Thread_Dispatch(); + } +} diff --git a/bsps/sh/gensh4/start/ispsh7750.c b/bsps/sh/gensh4/start/ispsh7750.c new file mode 100644 index 0000000000..5a1282f583 --- /dev/null +++ b/bsps/sh/gensh4/start/ispsh7750.c @@ -0,0 +1,317 @@ +/* + * SH7750 interrupt support. + * + * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia + * Author: Victor V. Vengerov <vvv@oktet.ru> + * + * Based on work: + * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and + * Bernd Becker (becker@faw.uni-ulm.de) + * + * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE + * + * + * COPYRIGHT (c) 1998. + * 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. + * + * Modified to reflect isp entries for sh7045 processor: + * John M. Mills (jmills@tga.com) + * TGA Technologies, Inc. + * 100 Pinnacle Way, Suite 140 + * Norcross, GA 30071 U.S.A. + * August, 1999 + * + * This modified file may be copied and distributed in accordance + * the above-referenced license. It is provided for critique and + * developmental purposes without any warranty nor representation + * by the authors or by TGA Technologies. + */ + +#include <rtems/system.h> +#include <rtems/score/isr.h> + +/* + * This is a exception vector table + * + * It has the same structure as the actual vector table (vectab) + */ + + +#include <rtems/score/ispsh7750.h> +#include <rtems/score/sh4_regs.h> +#include <rtems/score/sh7750_regs.h> + +/* VBR register contents saved on startup -- used to hook exception by debug + * agent */ +void *_VBR_Saved; + +#define __STRINGIFY1__(x) #x +#define __STRINGIFY__(x) __STRINGIFY1__(x) + +#define STOP_TIMER \ + " mov.l TSTR_k,r0 \n" \ + " mov.b @r0,r1 \n" \ + " and #" __STRINGIFY__(~SH7750_TSTR_STR0) ",r1\n" \ + " mov.b r1,@r0 \n" + +#define START_TIMER \ + " mov.l TSTR_k,r0 \n" \ + " mov.b @r0,r1 \n" \ + " or #" __STRINGIFY__(SH7750_TSTR_STR0) ",r1\n" \ + " mov.b r1,@r0 \n" + +__asm__ (" .text\n" + " .balign 256\n" + " .global __vbr_base\n" + "__vbr_base:\n" + " .org __vbr_base + 0x100\n" + "vbr_100:\n" + " mov.l r0,@-r15\n" + " mov.l r1,@-r15\n" + " mov.l __VBR_Saved100_k, r0\n" + " mov.l offset100_k,r1\n" + " mov.l @r0,r0\n" + " add r1,r0\n" + " mov.l @r15+,r1\n" + " jmp @r0\n" + " mov.l @r15+,r0\n" + " .align 2\n" + "__VBR_Saved100_k:\n" + " .long __VBR_Saved\n" + "offset100_k:\n" + " .long 0x100\n" + + " .org __vbr_base + 0x400\n" + "vbr_400:\n" + " mov.l r0,@-r15\n" + " mov.l r1,@-r15\n" + " mov.l __VBR_Saved400_k, r0\n" + " mov.l offset400_k,r1\n" + " mov.l @r0,r0\n" + " add r1,r0\n" + " mov.l @r15+,r1\n" + " jmp @r0\n" + " mov.l @r15+,r0\n" + " .align 2\n" + "__VBR_Saved400_k:\n" + " .long __VBR_Saved\n" + "offset400_k:\n" + " .long 0x400\n" + + " .org __vbr_base + 0x600\n" + "vbr_600:\n" + " mov.l r0,@-r15 \n" + " mov.l r1,@-r15 \n" + " stc sr,r0 \n" + " mov.l __vbr_600_sr_and_k,r1\n" + " and r1,r0 \n" + " mov.l __vbr_600_sr_or_k,r1\n" + " or r1,r0 \n" + " ldc r0,sr \n" + " ldc.l @r15+,r1_bank\n" + " ldc.l @r15+,r0_bank\n" + " mov.l r0,@-r15 \n" + " mov.l r1,@-r15 \n" + " mov.l r2,@-r15 \n" + " mov.l r3,@-r15 \n" + " mov.l r4,@-r15 \n" + " mov.l r5,@-r15 \n" + " mov.l r6,@-r15 \n" + " mov.l r7,@-r15 \n" +#if 0 + " mov.l r8,@-r15 \n" + " mov.l r9,@-r15 \n" + " mov.l r10,@-r15 \n" + " mov.l r11,@-r15 \n" + " mov.l r12,@-r15 \n" + " mov.l r13,@-r15 \n" +#endif + " mov.l r14,@-r15 \n" + " sts.l fpscr,@-r15\n" + " sts.l fpul,@-r15 \n" + " mov.l __ISR_temp_fpscr_k,r0 \n" + " lds r0,fpscr \n" + " fmov fr0,@-r15 \n" + " fmov fr1,@-r15 \n" + " fmov fr2,@-r15 \n" + " fmov fr3,@-r15 \n" + " fmov fr4,@-r15 \n" + " fmov fr5,@-r15 \n" + " fmov fr6,@-r15 \n" + " fmov fr7,@-r15 \n" + " fmov fr8,@-r15 \n" + " fmov fr9,@-r15 \n" + " fmov fr10,@-r15 \n" + " fmov fr11,@-r15 \n" + " fmov fr12,@-r15 \n" + " fmov fr13,@-r15 \n" + " fmov fr14,@-r15 \n" + " fmov fr15,@-r15 \n" + + " sts.l pr,@-r15 \n" + " sts.l mach,@-r15 \n" + " sts.l macl,@-r15 \n" + " stc.l spc,@-r15 \n" + " stc.l ssr,@-r15 \n" + " mov r15,r14 \n" +#if 0 + " stc ssr,r0 \n" + " ldc r0,sr \n" +#endif + " mov.l __ISR_Handler_k, r1\n" + " mov.l _INTEVT_k,r4\n" + " mov.l @r4,r4 \n" + " shlr2 r4 \n" + " shlr r4 \n" + + " mov.l _ISR_Table_k,r0\n" + " mov.l @r0,r0 \n" + " add r4,r0 \n" + " mov.l @r0,r0 \n" + " cmp/eq #0,r0 \n" + " bt _ipl_hook \n" + + + " jsr @r1 \n" + " shlr2 r4 \n" + " mov r14,r15 \n" + " ldc.l @r15+,ssr \n" + " ldc.l @r15+,spc \n" + " lds.l @r15+,macl \n" + " lds.l @r15+,mach \n" + " lds.l @r15+,pr \n" + " mov.l __ISR_temp_fpscr_k,r0 \n" + " lds r0,fpscr \n" + + " fmov @r15+,fr15 \n" + " fmov @r15+,fr14 \n" + " fmov @r15+,fr13 \n" + " fmov @r15+,fr12 \n" + " fmov @r15+,fr11 \n" + " fmov @r15+,fr10 \n" + " fmov @r15+,fr9 \n" + " fmov @r15+,fr8 \n" + " fmov @r15+,fr7 \n" + " fmov @r15+,fr6 \n" + " fmov @r15+,fr5 \n" + " fmov @r15+,fr4 \n" + " fmov @r15+,fr3 \n" + " fmov @r15+,fr2 \n" + " fmov @r15+,fr1 \n" + " fmov @r15+,fr0 \n" + " lds.l @r15+,fpul \n" + " lds.l @r15+,fpscr\n" + " mov.l @r15+,r14 \n" +#if 0 + " mov.l @r15+,r13 \n" + " mov.l @r15+,r12 \n" + " mov.l @r15+,r11 \n" + " mov.l @r15+,r10 \n" + " mov.l @r15+,r9 \n" + " mov.l @r15+,r8 \n" +#endif + + " mov.l @r15+,r7 \n" + " mov.l @r15+,r6 \n" + " mov.l @r15+,r5 \n" + " mov.l @r15+,r4 \n" + " mov.l @r15+,r3 \n" + " mov.l @r15+,r2 \n" + " mov.l @r15+,r1 \n" + " mov.l @r15+,r0 \n" + " rte \n" + " nop \n" + " .align 2 \n" + "__vbr_600_sr_and_k: \n" + " .long " __STRINGIFY__(~(SH4_SR_RB | SH4_SR_BL)) "\n" + "__vbr_600_sr_or_k: \n" + " .long " __STRINGIFY__(SH4_SR_IMASK) "\n" + "__ISR_Handler_k: \n" + " .long ___ISR_Handler\n" + "_INTEVT_k: \n" + " .long " __STRINGIFY__(SH7750_INTEVT) "\n" + "_ISR_Table_k: \n" + " .long __ISR_Vector_table\n" + + "_ipl_hook: \n" + " mov r14,r15 \n" + " ldc.l @r15+,ssr \n" + " ldc.l @r15+,spc \n" + " lds.l @r15+,macl \n" + " lds.l @r15+,mach \n" + " lds.l @r15+,pr \n" + " mov.l __ISR_temp_fpscr_k,r0 \n" + " lds r0,fpscr \n" + " fmov @r15+,fr15 \n" + " fmov @r15+,fr14 \n" + " fmov @r15+,fr13 \n" + " fmov @r15+,fr12 \n" + " fmov @r15+,fr11 \n" + " fmov @r15+,fr10 \n" + " fmov @r15+,fr9 \n" + " fmov @r15+,fr8 \n" + " fmov @r15+,fr7 \n" + " fmov @r15+,fr6 \n" + " fmov @r15+,fr5 \n" + " fmov @r15+,fr4 \n" + " fmov @r15+,fr3 \n" + " fmov @r15+,fr2 \n" + " fmov @r15+,fr1 \n" + " fmov @r15+,fr0 \n" + " lds.l @r15+,fpul \n" + " lds.l @r15+,fpscr\n" + " mov.l @r15+,r14 \n" + + " mov.l @r15+,r13 \n" + " mov.l @r15+,r12 \n" + " mov.l @r15+,r11 \n" + " mov.l @r15+,r10 \n" + " mov.l @r15+,r9 \n" + " mov.l @r15+,r8 \n" + + + " mov.l @r15+,r7 \n" + " mov.l @r15+,r6 \n" + " mov.l @r15+,r5 \n" + " mov.l @r15+,r4 \n" + " mov.l @r15+,r3 \n" + " mov.l @r15+,r2 \n" + " mov.l __VBR_Saved600_k, r0\n" + " mov.l offset600_k,r1\n" + " mov.l @r0,r0\n" + " add r1,r0\n" + " mov.l @r15+,r1\n" + " jmp @r0\n" + " mov.l @r15+,r0\n" + " .align 2\n" + "__ISR_temp_fpscr_k: \n" + " .long " __STRINGIFY__(SH4_FPSCR_PR) " \n" + "__VBR_Saved600_k:\n" + " .long __VBR_Saved\n" + "offset600_k:\n" + " .long 0x600\n" + + ); + + +/************************************************ + * Dummy interrupt service procedure for + * interrupts being not allowed --> Trap 2 + ************************************************/ +__asm__ (" .section .text\n\ +.global __dummy_isp\n\ +__dummy_isp:\n\ + mov.l r14,@-r15\n\ + mov r15, r14\n\ + trapa #2\n\ + mov.l @r15+,r14\n\ + rte\n\ + nop"); diff --git a/bsps/sh/gensh4/start/linkcmds b/bsps/sh/gensh4/start/linkcmds new file mode 100644 index 0000000000..de6bb05693 --- /dev/null +++ b/bsps/sh/gensh4/start/linkcmds @@ -0,0 +1,193 @@ +/* + * This file contains GNU linker directives for an general SH4 + * board. + * + * Variations in memory size and allocation can be made by + * overriding some values with linker command-line arguments. + * + * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russia + * Author: Victor V. Vengerov <vvv@oktet.ru> + * + * 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_ARCH(sh) +ENTRY(_start) +STARTUP(start.o) + +/* Do we need any of these for elf? + __DYNAMIC = 0; */ + +_RamBase = DEFINED(_RamBase) ? _RamBase : 0x80000000; +_RamSize = DEFINED(_RamSize) ? _RamSize : 4M; +_HeapSize = DEFINED(_HeapSize) ? _HeapSize : 0x0; + +/* + * Area assignments: + * Area 0: Flash memory, SRAM interface + * Area 1: GDC + * Area 2: SDRAM + * Area 3-6: unused + */ +MEMORY +{ + ram : o = 0x88100000, l = 7M + rom : o = 0x80000000, l = 4M +} + +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + .text : + { + _start = .; + *(.text*) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + ___start_set_sysctl_set = .; + *(set_sysc*); /* set_sysctl_* but name is truncated by SH-coff */ + ___stop_set_sysctl_set = ABSOLUTE(.); + *(set_doma*); /* set_domain_* but name is truncated by SH-coff */ + *(set_pseu*); /* set_pseudo_* but name is truncated by SH-coff */ + + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } > ram + .rela.dyn : + { + *(.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.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } >ram + _etext = .; + PROVIDE (etext = .); + .init . : { KEEP(*(.init)) } > ram =0 + .fini . : { KEEP(*(.fini)) } > ram =0 + .ctors . : { KEEP(*(.ctors)) } > ram =0 + .dtors . : { KEEP(*(.dtors)) } > ram =0 + .rodata : + { + *(.rodata) + *(.rodata.*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + } > ram + .tdata : { + __TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + __TLS_Data_end = .; + } > ram + .tbss : { + __TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + __TLS_BSS_end = .; + } > ram + __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)); + + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(128) + (. & (128 - 1)); + .data : + { + copy_start = .; + *(.data*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gcc_exc*) + ___EH_FRAME_BEGIN__ = .; + *(.eh_fram*) + ___EH_FRAME_END__ = .; + LONG(0); + *(.gcc_except_table*) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + copy_end = .; + } > ram + .eh_frame : { *(.eh_frame) } > ram + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss* .gnu.linkonce.b*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(32 / 8); + __bss_end = .; + } > ram + + .stack . : { + . = . + 4096; + } + + . = ALIGN(16); + _WorkAreaBase = . ; + + . = ALIGN(16); + _CPU_Interrupt_stack_low = . ; + _CPU_Interrupt_stack_high = _CPU_Interrupt_stack_low + 4096 ; + + /* 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) } + .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) } + .stack : { _stack = .; *(.stack) } + /* These must appear regardless of . */ +} diff --git a/bsps/sh/gensh4/start/linkcmds.rom b/bsps/sh/gensh4/start/linkcmds.rom new file mode 100644 index 0000000000..13c6096af1 --- /dev/null +++ b/bsps/sh/gensh4/start/linkcmds.rom @@ -0,0 +1,239 @@ +/* + * This file contains GNU linker directives for an general SH4 + * board. + * + * Variations in memory size and allocation can be made by + * overriding some values with linker command-line arguments. + * + * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russia + * Author: Victor V. Vengerov <vvv@oktet.ru> + * + * 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-shl", "elf32-shl", + "elf32-shl") +OUTPUT_ARCH(sh) +ENTRY(_start) +STARTUP(start.o) + +/* Do we need any of these for elf? + __DYNAMIC = 0; */ + +_RamBase = DEFINED(_RamBase) ? _RamBase : 0x88000000; +_RamSize = DEFINED(_RamSize) ? _RamSize : 8M; +_HeapSize = DEFINED(_HeapSize) ? _HeapSize : (2 * 1024 * 1024); + +/* + * Area assignments: + * Area 0: Flash memory, SRAM interface + * Area 1: GDC + * Area 2: SDRAM + * Area 3-6: unused + */ +MEMORY +{ +/* + * Real values + */ + ram : o = 0x88000000, l = 8M + rom : o = 0x80000000, l = 4M +/* + * Fake values to test from gdb + */ +/* + ram : o = 0x88100000, l = 4M + rom : o = 0x88500000, l = 3M +*/ +} + +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + .init : + { + KEEP (*(.init)) + } =0 + .text : + { + *(.text*) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + ___start_set_sysctl_set = .; + *(set_sysc*); /* set_sysctl_* but name is truncated by SH-coff */ + ___stop_set_sysctl_set = ABSOLUTE(.); + *(set_doma*); /* set_domain_* but name is truncated by SH-coff */ + *(set_pseudo_*); + + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } > rom + _etext = .; + PROVIDE (etext = .); + .rela.dyn : + { + *(.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.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } >ram + .fini : + { + KEEP (*(.fini)) + } =0 + .rodata : + { + *(.rodata) + *(.rodata.*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + . = ALIGN(32); + } > rom + .tdata : { + __TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + __TLS_Data_end = .; + } > rom + .tbss : { + __TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + __TLS_BSS_end = .; + } > rom + __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)); + .ctors : + { + ___ctors = .; + /* 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)) + /* We don't want to include the .ctor section from + 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 ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + ___ctors_end = .; + } > rom + .dtors : + { + ___dtors = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + ___dtors_end = .; + copy_start_in_rom = .; + } > rom + + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(128) + (. & (128 - 1)); + .data : AT(LOADADDR(.dtors) + SIZEOF(.dtors)) + { + copy_start = .; + *(.data) + *(.data.*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + copy_end = .; + } > ram + .eh_frame : { *(.eh_frame) } > ram + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss* .gnu.linkonce.b*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(32 / 8); + __bss_end = .; + } > ram + + . = ALIGN(16); + _WorkAreaBase = . ; + + . = ALIGN(16); + .stack . : { + stack_start = .; + . = . + 4096; + stack_end = .; + } + + . = ALIGN(16); + _CPU_Interrupt_stack_low = . ; + _CPU_Interrupt_stack_high = _CPU_Interrupt_stack_low + 4096 ; + + /* 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) } + .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) } + .stack : { _stack = .; *(.stack) } + /* These must appear regardless of . */ +} diff --git a/bsps/sh/gensh4/start/linkcmds.rom2ram b/bsps/sh/gensh4/start/linkcmds.rom2ram new file mode 100644 index 0000000000..cc14d4e98d --- /dev/null +++ b/bsps/sh/gensh4/start/linkcmds.rom2ram @@ -0,0 +1,243 @@ +/* + * This file contains GNU linker directives for an general SH4 + * board. + * + * Variations in memory size and allocation can be made by + * overriding some values with linker command-line arguments. + * + * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russia + * Author: Victor V. Vengerov <vvv@oktet.ru> + * + * 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-shl", "elf32-shl", + "elf32-shl") +OUTPUT_ARCH(sh) +ENTRY(_start) +STARTUP(start.o) + +/* Do we need any of these for elf? + __DYNAMIC = 0; */ + +_RamBase = DEFINED(_RamBase) ? _RamBase : 0x88000000; +_RamSize = DEFINED(_RamSize) ? _RamSize : 8M; +_HeapSize = DEFINED(_HeapSize) ? _HeapSize : (2 * 1024 * 1024); + +/* + * Area assignments: + * Area 0: Flash memory, SRAM interface + * Area 1: GDC + * Area 2: SDRAM + * Area 3-6: unused + */ +MEMORY +{ +/* + * Real values + */ + ram : o = 0x88000000, l = 8M + rom : o = 0x80000000, l = 4M +/* + * Fake values to test from gdb + */ +/* + ram : o = 0x88100000, l = 4M + rom : o = 0x88500000, l = 3M +*/ +} + +SECTIONS +{ + rom : { + copy_start_in_rom = .; + } >rom + + /* Read-only sections, merged into text segment: */ + .init : + { + KEEP (*(.init)) + } =0 + .text : AT(copy_start_in_rom) + { + copy_start = .; + *(.text*) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + ___start_set_sysctl_set = .; + *(set_sysc*); /* set_sysctl_* but name is truncated by SH-coff */ + ___stop_set_sysctl_set = ABSOLUTE(.); + *(set_doma*); /* set_domain_* but name is truncated by SH-coff */ + *(set_pseudo_*); + + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } > ram + _etext = .; + PROVIDE (etext = .); + .fini : + { + KEEP (*(.fini)) + } =0 + .rodata : AT(LOADADDR(.text) + SIZEOF(.text)) + { + *(.rodata) + *(.rodata.*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + . = ALIGN(32); + } > ram + .tdata : { + __TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + __TLS_Data_end = .; + } > ram + .tbss : { + __TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + __TLS_BSS_end = .; + } > ram + __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)); + .ctors : AT(LOADADDR(.rodata) + SIZEOF(.rodata)) + { + ___ctors = .; + /* 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)) + /* We don't want to include the .ctor section from + 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 ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + ___ctors_end = .; + } > ram + .dtors : AT(LOADADDR(.ctors) + SIZEOF(.ctors)) + { + ___dtors = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + ___dtors_end = .; + } > ram + + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(128) + (. & (128 - 1)); + .data : AT(LOADADDR(.dtors) + SIZEOF(.dtors)) + { + *(.data) + *(.data.*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + copy_end = .; + } > ram + .eh_frame : { *(.eh_frame) } > ram + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss* .gnu.linkonce.b*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(32 / 8); + __bss_end = .; + } > ram + + .rela.dyn : + { + *(.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.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } >ram + . = ALIGN(16); + + _WorkAreaBase = . ; + + . = ALIGN(16); + .stack . : { + stack_start = .; + . = . + 4096; + stack_end = .; + } + + . = ALIGN(16); + _CPU_Interrupt_stack_low = . ; + _CPU_Interrupt_stack_high = _CPU_Interrupt_stack_low + 4096 ; + + /* 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) } + .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) } + .stack : { _stack = .; *(.stack) } + /* These must appear regardless of . */ +} diff --git a/bsps/sh/shared/start/bspstart.c b/bsps/sh/shared/start/bspstart.c new file mode 100644 index 0000000000..57b2c9e1ef --- /dev/null +++ b/bsps/sh/shared/start/bspstart.c @@ -0,0 +1,63 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * COPYRIGHT (c) 2001. + * Ralf Corsepius (corsepiu@faw.uni-ulm.de). + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * COPYRIGHT (c) 2001. + * 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> +#include <rtems/score/percpu.h> + +uint32_t bsp_clicks_per_second; + +#ifndef START_HW_INIT + void bsp_hw_init(void); +#endif + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ +void bsp_start( void ) +{ + /* + * For real boards you need to setup the hardware + * and need to copy the vector table from rom to ram. + * + * Depending on the board this can either be done from inside the rom + * startup code, rtems startup code or here. + */ + + #ifndef START_HW_INIT + /* board hardware setup here, or from 'start.S' */ + bsp_hw_init(); + #endif + + /* + * initialize the interrupt stack for this BSP + */ + #if ( CPU_ALLOCATE_INTERRUPT_STACK == FALSE ) + _CPU_Interrupt_stack_low = &CPU_Interrupt_stack_low; + _CPU_Interrupt_stack_high = &CPU_Interrupt_stack_high; + #endif + + /* + * initialize the device driver parameters + */ + bsp_clicks_per_second = CPU_CLOCK_RATE_HZ; +} diff --git a/bsps/sh/shsim/start/bsp_specs b/bsps/sh/shsim/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/sh/shsim/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/sh/shsim/start/cpu_asm.c b/bsps/sh/shsim/start/cpu_asm.c new file mode 100644 index 0000000000..2ca8926a24 --- /dev/null +++ b/bsps/sh/shsim/start/cpu_asm.c @@ -0,0 +1,83 @@ +/* + * Support for SuperH Simulator in GDB + */ + +/* + * COPYRIGHT (c) 1989-2008. + * 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/system.h> +#include <rtems/score/cpu.h> +#include <rtems/score/isr.h> +#include <rtems/score/percpu.h> +#include <rtems/score/threaddispatch.h> +#include <rtems/score/sh.h> + +#if (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + unsigned long *_old_stack_ptr; +#endif + +register unsigned long *stack_ptr __asm__ ("r15"); + +void __ISR_Handler(uint32_t vector); + +/* + * This routine provides the RTEMS interrupt management. + */ +void __ISR_Handler( uint32_t vector) +{ + ISR_Level level; + + _ISR_Local_disable( level ); + + _Thread_Dispatch_disable(); + +#if (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + if ( _ISR_Nest_level == 0 ) + { + /* Install irq stack */ + _old_stack_ptr = stack_ptr; + stack_ptr = _CPU_Interrupt_stack_high; + } + +#endif + + _ISR_Nest_level++; + + _ISR_Local_enable( level ); + + /* call isp */ + if ( _ISR_Vector_table[ vector]) + (*_ISR_Vector_table[ vector ])( vector ); + + _ISR_Local_disable( level ); + + _Thread_Dispatch_unnest( _Per_CPU_Get() ); + + _ISR_Nest_level--; + +#if (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + + if ( _ISR_Nest_level == 0 ) + /* restore old stack pointer */ + stack_ptr = _old_stack_ptr; +#endif + + _ISR_Local_enable( level ); + + if ( _ISR_Nest_level ) + return; + + if ( !_Thread_Dispatch_is_enabled() ) { + return; + } + + if ( _Thread_Dispatch_necessary ) { + _Thread_Dispatch(); + } +} diff --git a/bsps/sh/shsim/start/ispshgdb.c b/bsps/sh/shsim/start/ispshgdb.c new file mode 100644 index 0000000000..09843172d9 --- /dev/null +++ b/bsps/sh/shsim/start/ispshgdb.c @@ -0,0 +1,146 @@ +/* + * This file contains the isp frames for the user interrupts. + * From these procedures __ISR_Handler is called with the vector number + * as argument. + * + * __ISR_Handler is kept in a separate file (cpu_asm.c), because a bug in + * some releases of gcc doesn't properly handle #pragma interrupt, if a + * file contains both isrs and normal functions. + * + * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and + * Bernd Becker (becker@faw.uni-ulm.de) + * + * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE + * + * + * COPYRIGHT (c) 1998. + * 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. + * + * Modified to reflect dummy isp entries for GDB SH simulator by Joel. + */ + +#include <rtems/system.h> + +/* + * This is a exception vector table + * + * It has the same structure as the actual vector table (vectab) + */ + +void _dummy_isp(uint32_t); + +proc_ptr _Hardware_isr_Table[256]={ +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, /* PWRon Reset, Maual Reset,...*/ +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +/* trapa 0 -31 */ +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, /* irq 152-155*/ +_dummy_isp +}; + +#define Str(a)#a + +/* + * Some versions of gcc and all version of egcs at least until egcs-1.1b + * are not able to handle #pragma interrupt correctly if more than 1 isr is + * contained in a file and when optimizing. + * We try to work around this problem by using the macro below. + */ +#define isp( name, number, func)\ +__asm__ (".global _"Str(name)"\n\t"\ + "_"Str(name)": \n\t"\ + " mov.l r0,@-r15 \n\t"\ + " mov.l r1,@-r15 \n\t"\ + " mov.l r2,@-r15 \n\t"\ + " mov.l r3,@-r15 \n\t"\ + " mov.l r4,@-r15 \n\t"\ + " mov.l r5,@-r15 \n\t"\ + " mov.l r6,@-r15 \n\t"\ + " mov.l r7,@-r15 \n\t"\ + " mov.l r14,@-r15 \n\t"\ + " sts.l pr,@-r15 \n\t"\ + " sts.l mach,@-r15 \n\t"\ + " sts.l macl,@-r15 \n\t"\ + " mov r15,r14 \n\t"\ + " mov.l "Str(name)"_v, r2 \n\t"\ + " mov.l "Str(name)"_k, r1\n\t"\ + " jsr @r1 \n\t"\ + " mov r2,r4 \n\t"\ + " mov r14,r15 \n\t"\ + " lds.l @r15+,macl \n\t"\ + " lds.l @r15+,mach \n\t"\ + " lds.l @r15+,pr \n\t"\ + " mov.l @r15+,r14 \n\t"\ + " mov.l @r15+,r7 \n\t"\ + " mov.l @r15+,r6 \n\t"\ + " mov.l @r15+,r5 \n\t"\ + " mov.l @r15+,r4 \n\t"\ + " mov.l @r15+,r3 \n\t"\ + " mov.l @r15+,r2 \n\t"\ + " mov.l @r15+,r1 \n\t"\ + " mov.l @r15+,r0 \n\t"\ + " rte \n\t"\ + " nop \n\t"\ + " .align 2 \n\t"\ + #name"_k: \n\t"\ + ".long "Str(func)"\n\t"\ + #name"_v: \n\t"\ + ".long "Str(number)); + +/************************************************ + * Dummy interrupt service procedure for + * interrupts being not allowed --> Trap 34 + ************************************************/ +__asm__ (" .section .text\n\ +.global __dummy_isp\n\ +__dummy_isp:\n\ + mov.l r14,@-r15\n\ + mov r15, r14\n\ + trapa #34\n\ + mov.l @r15+,r14\n\ + rte\n\ + nop"); + diff --git a/bsps/sh/shsim/start/linkcmds b/bsps/sh/shsim/start/linkcmds new file mode 100644 index 0000000000..41c7245da0 --- /dev/null +++ b/bsps/sh/shsim/start/linkcmds @@ -0,0 +1,255 @@ +/* + * Memory layout for an SH 7032 with main memory in area 0 + * + * NOTES: + * + All RAM/ROM areas are mapped onto area 0, because gdb's simulator + * is not able to simulate memory areas but area 0. Area 5 (on-chip + * peripherials) can not be mapped onto area 0 and will cause SIGILL + * exceptions. + * + Assumed to be compatible with other SH-cpu family members (eg. SH7045) + * + * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) + * + * COPYRIGHT (c) 2001, Ralf Corsepius, Ulm, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +OUTPUT_ARCH(sh) +ENTRY(_start) +STARTUP(start.o) + +_RamBase = DEFINED(_RamBase) ? _RamBase : 0x00000000; +_RamSize = DEFINED(_RamSize) ? _RamSize : 16M; +_HeapSize = DEFINED(_HeapSize) ? _HeapSize : 0x0; + +MEMORY +{ +/* Real memory layout submitted + rom : o = 0x00000000, l = 128k + ram : o = 0x00040000, l = 256k +*/ + +/* Memory layout which links all tests */ + rom : o = 0x01000000, l = 512k + ram : o = 0x00040000, l = 512k + + onchip_peri : o = 0x05000000, l = 512 +} + +SECTIONS +{ + /* boot vector table */ + .monvects (NOLOAD) : + { + _monvects = . ; + } > rom + + /* monitor play area */ + .monram 0x00040000 (NOLOAD) : + { + _ramstart = .; + } > ram + + /* monitor vector table */ + .vects 0x00042000 (NOLOAD) : { + _vectab = . ; + *(.vects); + } + + /* Read-only sections, merged into text segment: */ + + . = 0x00044000 ; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rela.dyn : + { + *(.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.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } >ram + .rel.text : + { *(.rel.text) *(.rel.gnu.linkonce.t*) } + .rel.data : + { *(.rel.data) *(.rel.gnu.linkonce.d*) } + .rel.rodata : + { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } + .rel.got : { *(.rel.got) } + .rel.ctors : { *(.rel.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rel.init : { *(.rel.init) } + .rel.fini : { *(.rel.fini) } + .rel.bss : { *(.rel.bss) } + .rel.plt : { *(.rel.plt) } + .plt : { *(.plt) } + .text . : + { + _start = .; + *(.text*) + *(.stub) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + ___start_set_sysctl_set = .; + *(set_sysc*); /* set_sysctl_* but name is truncated by SH-coff */ + ___stop_set_sysctl_set = ABSOLUTE(.); + *(set_doma*); /* set_domain_* but name is truncated by SH-coff */ + *(set_pseu*); /* set_pseudo_* but name is truncated by SH-coff */ + + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } > ram + .init : + { + KEEP (*(.init)) + } >ram + .fini : + { + KEEP (*(.fini)) + } >ram + _etext = .; + PROVIDE (etext = .); + .rodata . : { *(.rodata*) .rodata.* *(.gnu.linkonce.r*) } > ram + .rodata1 . : { *(.rodata1) } > ram + .tdata : { + __TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + __TLS_Data_end = .; + } > ram + .tbss : { + __TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + __TLS_BSS_end = .; + } > ram + .init . : { KEEP(*(.init)) } > ram =0 + .fini . : { KEEP(*(.fini)) } > ram =0 + .ctors . : { KEEP(*(.ctors)) } > ram =0 + .dtors . : { KEEP(*(.dtors)) } > ram =0 + __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)); + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(128) + (. & (128 - 1)); + .data . : + { + *(.data*) + *(.gcc_exc*) + ___EH_FRAME_BEGIN__ = .; + *(.eh_fram*) + ___EH_FRAME_END__ = .; + LONG(0); + *(.gcc_except_table*) + *(.gnu.linkonce.d*) + CONSTRUCTORS + } > ram + .data1 . : { *(.data1) } + .rtemsroset : { + /* for pre rtems-libbsd FreeBSD code */ + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = .; + *(set_domain_*); + *(set_pseudo_*); + + KEEP (*(SORT(.rtemsroset.*))) + } >ram + .rtemsrwset : { + KEEP (*(SORT(.rtemsrwset.*))) + } >ram + + .got . : { *(.got.plt) *(.got) } + .dynamic . : { *(.dynamic) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata . : { *(.sdata) } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + .sbss . : { *(.sbss*) *(.scommon) } + .bss . : + { + *(.dynbss) + *(.bss .bss* .gnu.linkonce.b*) + *(COMMON) + } > ram + _end = . ; + PROVIDE (end = .); + + .stack : { + . += 0x1000; + *(.stack) + _stack = .; + } > ram + _stack = .; + + _WorkAreaBase = . ; + + _CPU_Interrupt_stack_low = 0x00080000 ; + _CPU_Interrupt_stack_high = _CPU_Interrupt_stack_low + 4096 ; + + /* 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) } + .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) } + +/* + .stack 0x00081ff0 : { _stack = .; *(.stack) } > onchip_ram +*/ + /* These must appear regardless of . */ +} diff --git a/bsps/sh/shsim/start/sysexit.c b/bsps/sh/shsim/start/sysexit.c new file mode 100644 index 0000000000..dde20f35e8 --- /dev/null +++ b/bsps/sh/shsim/start/sysexit.c @@ -0,0 +1,22 @@ +/* + * This file contains the simulator specific exit trap. + */ + +/* + * COPYRIGHT (c) 1989-2014. + * 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/syscall.h> + +int errno; /* assumed to exist by exit_k() */ + +int _sys_exit (int n) +{ + return __trap34 (SYS_exit, n, 0, 0); +} diff --git a/bsps/sparc/erc32/start/boardinit.S b/bsps/sparc/erc32/start/boardinit.S new file mode 100644 index 0000000000..9ced1c3639 --- /dev/null +++ b/bsps/sparc/erc32/start/boardinit.S @@ -0,0 +1,92 @@ +/** + * @file + * + * @ingroup sparc_erc32 + * + * @brief Initialise various ERC32 registers + */ + +/* + * COPYRIGHT (c) 2000. + * European Space Agency. + * + * 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 <erc32.h> + + .global __bsp_board_init +__bsp_board_init: + +/* Check if MEC is initialised. If not, this means that we are + running on the simulator. Initiate some of the parameters + that are done by the boot-prom otherwise. +*/ + + set SYM(ERC32_MEC), %g3 ! g3 = base address of peripherals + ld [%g3], %g2 + set 0xfe080000, %g1 + andcc %g1, %g2, %g0 + bne 2f + + /* Stop the watchdog */ + + st %g0, [%g3 + SYM(ERC32_MEC_WATCHDOG_TRAP_DOOR_SET_OFFSET)] + + /* Set zero waitstates */ + + st %g0, [%g3 + SYM(ERC32_MEC_WAIT_STATE_CONFIGURATION_OFFSET)] + + /* Set the correct memory size in MEC memory config register */ + + set SYM(PROM_SIZE), %l0 + set 0, %l1 + srl %l0, 18, %l0 +1: + tst %l0 + srl %l0, 1, %l0 + bne,a 1b + inc %l1 + sll %l1, 8, %l1 + + set SYM(RAM_SIZE), %l0 + srl %l0, 19, %l0 +1: + tst %l0 + srl %l0, 1, %l0 + bne,a 1b + inc %l1 + sll %l1, 10, %l1 + + ! set the Memory Configuration + st %l1, [ %g3 + ERC32_MEC_MEMORY_CONFIGURATION_OFFSET ] + + set SYM(RAM_START), %l1 ! Cannot use RAM_END due to bug in linker + set SYM(RAM_SIZE), %l2 + add %l1, %l2, %sp + + set SYM(CLOCK_SPEED), %g6 ! Use 14 MHz in simulator + set 14, %g1 + st %g1, [%g6] + +2: + + /* Initialise timer */ + + set SYM(_ERC32_MEC_Timer_Control_Mirror), %l2 + st %g0, [%l2] + st %g0, [%g3 + SYM(ERC32_MEC_TIMER_CONTROL_OFFSET)] + + /* Enable power-down */ + + ld [%g3 + SYM(ERC32_MEC_CONTROL_OFFSET)], %l2 + or %l2, ERC32_CONFIGURATION_POWER_DOWN_ALLOWED, %l2 + st %l2, [%g3 + SYM(ERC32_MEC_CONTROL_OFFSET)] + + retl + nop + +/* end of file */ diff --git a/bsps/sparc/erc32/start/bsp_specs b/bsps/sparc/erc32/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/sparc/erc32/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/sparc/erc32/start/bspdelay.c b/bsps/sparc/erc32/start/bspdelay.c new file mode 100644 index 0000000000..afd42cbd6f --- /dev/null +++ b/bsps/sparc/erc32/start/bspdelay.c @@ -0,0 +1,25 @@ +/* + * ERC32 BSP Delay Method + */ + +/* + * COPYRIGHT (c) 1989-2014. + * 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> + +void rtems_bsp_delay(int usecs) +{ + uint32_t then; + + then = ERC32_MEC.Real_Time_Clock_Counter; + then += usecs; + + while (ERC32_MEC.Real_Time_Clock_Counter >= then) + ; +} diff --git a/bsps/sparc/erc32/start/bspidle.c b/bsps/sparc/erc32/start/bspidle.c new file mode 100644 index 0000000000..4b41625e84 --- /dev/null +++ b/bsps/sparc/erc32/start/bspidle.c @@ -0,0 +1,27 @@ +/* + * ERC32 Idle Thread with power-down function + * + * 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. + * + * Ported to ERC32 implementation of the SPARC by On-Line Applications + * Research Corporation (OAR) under contract to the European Space + * Agency (ESA). + * + * ERC32 modifications of respective RTEMS file: COPYRIGHT (c) 1995. + * European Space Agency. + */ + +#include <bsp.h> + +void *bsp_idle_thread( uintptr_t ignored ) +{ + while (1) { + ERC32_MEC.Power_Down = 0; /* value is irrelevant */ + } + return NULL; +} diff --git a/bsps/sparc/erc32/start/erc32mec.c b/bsps/sparc/erc32/start/erc32mec.c new file mode 100644 index 0000000000..7b0ccbd309 --- /dev/null +++ b/bsps/sparc/erc32/start/erc32mec.c @@ -0,0 +1,15 @@ +/* + * Put this variable in a separate file so it is only linked in when needed. + * + * COPYRIGHT (c) 1989-2002. + * 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.h> + +ERC32_Register_Map ERC32_MEC; diff --git a/bsps/sparc/erc32/start/linkcmds b/bsps/sparc/erc32/start/linkcmds new file mode 100644 index 0000000000..9df3a0d94f --- /dev/null +++ b/bsps/sparc/erc32/start/linkcmds @@ -0,0 +1,29 @@ +/* linkcmds + */ + +/* Default values, can be overridden */ + +_PROM_SIZE = DEFINED (_PROM_SIZE) ? _PROM_SIZE : 2M; +_PROM_START = DEFINED (_PROM_START) ? _PROM_START : 0x00000000; + +_RAM_SIZE = DEFINED (_RAM_SIZE) ? _RAM_SIZE : 4M; +_RAM_START = DEFINED (_RAM_START) ? _RAM_START : 0x02000000; + +/* + * Base address of the on-CPU peripherals + */ + +_ERC32_MEC = 0x01f80000; +ERC32_MEC = _ERC32_MEC; + +/* these are the maximum values */ + +MEMORY +{ + rom : ORIGIN = 0x00000000, LENGTH = 16 + ram : ORIGIN = 0x02000000, LENGTH = 32M +} + +ENTRY(start) + +INCLUDE linkcmds.base diff --git a/bsps/sparc/erc32/start/setvec.c b/bsps/sparc/erc32/start/setvec.c new file mode 100644 index 0000000000..d3aa8ed72f --- /dev/null +++ b/bsps/sparc/erc32/start/setvec.c @@ -0,0 +1,59 @@ +/* set_vector + * + * This routine installs an interrupt vector on the SPARC simulator. + * + * INPUT PARAMETERS: + * handler - interrupt handler entry point + * vector - vector number + * type - 0 indicates raw hardware connect + * 1 indicates RTEMS interrupt connect + * + * OUTPUT PARAMETERS: NONE + * + * RETURNS: + * address of previous interrupt handler + * + * COPYRIGHT (c) 1989-1999. + * 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. + * + * Ported to ERC32 implementation of the SPARC by On-Line Applications + * Research Corporation (OAR) under contract to the European Space + * Agency (ESA). + * + * ERC32 modifications of respective RTEMS file: COPYRIGHT (c) 1995. + * European Space Agency. + */ + +#include <bsp.h> + +rtems_isr_entry set_vector( /* returns old vector */ + rtems_isr_entry handler, /* isr routine */ + rtems_vector_number vector, /* vector number */ + int type /* RTEMS or RAW intr */ +) +{ + rtems_isr_entry previous_isr; + uint32_t real_trap; + uint32_t source; + + if ( type ) + rtems_interrupt_catch( handler, vector, &previous_isr ); + else + _CPU_ISR_install_raw_handler( vector, handler, (void *)&previous_isr ); + + real_trap = SPARC_REAL_TRAP_NUMBER( vector ); + + if ( ERC32_Is_MEC_Trap( real_trap ) ) { + + source = ERC32_TRAP_SOURCE( real_trap ); + + ERC32_Clear_interrupt( source ); + ERC32_Unmask_interrupt( source ); + } + + return previous_isr; +} diff --git a/bsps/sparc/erc32/start/spurious.c b/bsps/sparc/erc32/start/spurious.c new file mode 100644 index 0000000000..b022f96f5c --- /dev/null +++ b/bsps/sparc/erc32/start/spurious.c @@ -0,0 +1,194 @@ +/* + * ERC32 Spurious Trap Handler + * + * This is just enough of a trap handler to let us know what + * the likely source of the trap was. + * + * Developed as part of the port of RTEMS to the ERC32 implementation + * of the SPARC by On-Line Applications Research Corporation (OAR) + * under contract to the European Space Agency (ESA). + * + * COPYRIGHT (c) 1995. European Space Agency. + * + * This terms of the RTEMS license apply to this file. + */ + +#include <bsp.h> +#include <rtems/bspIo.h> +#include <inttypes.h> + +void _CPU_Exception_frame_print( const CPU_Exception_frame *frame ) +{ + uint32_t trap; + uint32_t real_trap; + const CPU_Interrupt_frame *isf; + + trap = frame->trap; + real_trap = SPARC_REAL_TRAP_NUMBER(trap); + isf = frame->isf; + + printk( + "Unexpected trap (%2" PRId32 ") at address 0x%08" PRIx32 "\n", + real_trap, + isf->tpc + ); + + switch (real_trap) { + + /* + * First the ones defined by the basic architecture + */ + + case 0x00: + printk( "reset\n" ); + break; + case 0x01: + printk( "instruction access exception\n" ); + break; + case 0x02: + printk( "illegal instruction\n" ); + break; + case 0x03: + printk( "privileged instruction\n" ); + break; + case 0x04: + printk( "fp disabled\n" ); + break; + case 0x07: + printk( "memory address not aligned\n" ); + break; + case 0x08: + printk( "fp exception\n" ); + break; + case 0x09: + printk("data access exception at 0x%08" PRIx32 "\n", + ERC32_MEC.First_Failing_Address ); + break; + case 0x0A: + printk( "tag overflow\n" ); + break; + + /* + * Then the ones defined by the ERC32 in particular + */ + + case ERC32_TRAP_TYPE( ERC32_INTERRUPT_MASKED_ERRORS ): + printk( "ERC32_INTERRUPT_MASKED_ERRORS\n" ); + break; + case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_1 ): + printk( "ERC32_INTERRUPT_EXTERNAL_1\n" ); + break; + case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_2 ): + printk( "ERC32_INTERRUPT_EXTERNAL_2\n" ); + break; + case ERC32_TRAP_TYPE( ERC32_INTERRUPT_UART_A_RX_TX ): + printk( "ERC32_INTERRUPT_UART_A_RX_TX\n" ); + break; + case ERC32_TRAP_TYPE( ERC32_INTERRUPT_UART_B_RX_TX ): + printk( "ERC32_INTERRUPT_UART_A_RX_TX\n" ); + break; + case ERC32_TRAP_TYPE( ERC32_INTERRUPT_CORRECTABLE_MEMORY_ERROR ): + printk( "ERC32_INTERRUPT_CORRECTABLE_MEMORY_ERROR\n" ); + break; + case ERC32_TRAP_TYPE( ERC32_INTERRUPT_UART_ERROR ): + printk( "ERC32_INTERRUPT_UART_ERROR\n" ); + break; + case ERC32_TRAP_TYPE( ERC32_INTERRUPT_DMA_ACCESS_ERROR ): + printk( "ERC32_INTERRUPT_DMA_ACCESS_ERROR\n" ); + break; + case ERC32_TRAP_TYPE( ERC32_INTERRUPT_DMA_TIMEOUT ): + printk( "ERC32_INTERRUPT_DMA_TIMEOUT\n" ); + break; + case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_3 ): + printk( "ERC32_INTERRUPT_EXTERNAL_3\n" ); + break; + case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_4 ): + printk( "ERC32_INTERRUPT_EXTERNAL_4\n" ); + break; + case ERC32_TRAP_TYPE( ERC32_INTERRUPT_GENERAL_PURPOSE_TIMER ): + printk( "ERC32_INTERRUPT_GENERAL_PURPOSE_TIMER\n" ); + break; + case ERC32_TRAP_TYPE( ERC32_INTERRUPT_REAL_TIME_CLOCK ): + printk( "ERC32_INTERRUPT_REAL_TIME_CLOCK\n" ); + break; + case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_5 ): + printk( "ERC32_INTERRUPT_EXTERNAL_5\n" ); + break; + case ERC32_TRAP_TYPE( ERC32_INTERRUPT_WATCHDOG_TIMEOUT ): + printk( "ERC32_INTERRUPT_WATCHDOG_TIMEOUT\n" ); + break; + + default: + break; + } +} + +static rtems_isr bsp_spurious_handler( + rtems_vector_number trap, + CPU_Interrupt_frame *isf +) +{ + CPU_Exception_frame frame = { + .trap = trap, + .isf = isf + }; + +#if !defined(SPARC_USE_LAZY_FP_SWITCH) + if ( SPARC_REAL_TRAP_NUMBER( trap ) == 4 ) { + _Internal_error( INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT ); + } +#endif + + rtems_fatal( + RTEMS_FATAL_SOURCE_EXCEPTION, + (rtems_fatal_code) &frame + ); +} + +/* + * bsp_spurious_initialize + * + * Install the spurious handler for most traps. Note that set_vector() + * will unmask the corresponding asynchronous interrupt, so the initial + * interrupt mask is restored after the handlers are installed. + */ + +void bsp_spurious_initialize() +{ + uint32_t trap; + uint32_t level = 15; + uint32_t mask; + + level = sparc_disable_interrupts(); + mask = ERC32_MEC.Interrupt_Mask; + + for ( trap=0 ; trap<256 ; trap++ ) { + + /* + * Skip window overflow, underflow, and flush as well as software + * trap 0,9,10 which we will use as a shutdown, IRQ disable, IRQ enable. + * Also avoid trap 0x70 - 0x7f which cannot happen and where some of the + * space is used to pass parameters to the program. + */ + + if (( trap == 5 || trap == 6 ) || +#if defined(SPARC_USE_LAZY_FP_SWITCH) + ( trap == 4 ) || +#endif + (( trap >= 0x11 ) && ( trap <= 0x1f )) || + (( trap >= 0x70 ) && ( trap <= 0x83 )) || + ( trap == 0x80 + SPARC_SWTRAP_IRQDIS ) || +#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH) + ( trap == 0x80 + SPARC_SWTRAP_IRQDIS_FP ) || +#endif + ( trap == 0x80 + SPARC_SWTRAP_IRQEN )) + continue; + + set_vector( (rtems_isr_entry) bsp_spurious_handler, + SPARC_SYNCHRONOUS_TRAP( trap ), 1 ); + } + + ERC32_MEC.Interrupt_Mask = mask; + sparc_enable_interrupts(level); + +} diff --git a/bsps/sparc/leon2/start/bsp_specs b/bsps/sparc/leon2/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/sparc/leon2/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/sparc/leon2/start/bspdelay.c b/bsps/sparc/leon2/start/bspdelay.c new file mode 100644 index 0000000000..5ee8123157 --- /dev/null +++ b/bsps/sparc/leon2/start/bspdelay.c @@ -0,0 +1,27 @@ +/** + * @file + * @ingroup sparc_leon2 + * @brief LEON2 BSP Delay Method + */ + +/* + * COPYRIGHT (c) 1989-2011. + * 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> + +void rtems_bsp_delay(int usecs) +{ + uint32_t then; + + then = LEON_REG.Timer_Counter_1; + then += usecs; + + while (LEON_REG.Timer_Counter_1 >= then) + ; +} diff --git a/bsps/sparc/leon2/start/bspidle.c b/bsps/sparc/leon2/start/bspidle.c new file mode 100644 index 0000000000..8f11f66fb1 --- /dev/null +++ b/bsps/sparc/leon2/start/bspidle.c @@ -0,0 +1,35 @@ +/** + * @file + * @ingroup sparc_leon2 + * @brief LEON2 Idle Thread + */ + +/* + * LEON2 Idle Thread with power-down function + * + * 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. + * + * Ported to LEON implementation of the SPARC by On-Line Applications + * Research Corporation (OAR) under contract to the European Space + * Agency (ESA). + * + * LEON modifications of respective RTEMS file: COPYRIGHT (c) 1995. + * European Space Agency. + */ + +#include <bsp.h> + +void *bsp_idle_thread( uintptr_t ignored ) +{ + while (1) { + /* make sure on load follows store to power-down reg */ + LEON_REG.Power_Down = LEON_REG.Power_Down; + } + return NULL; +} + diff --git a/bsps/sparc/leon2/start/bspstart.c b/bsps/sparc/leon2/start/bspstart.c new file mode 100644 index 0000000000..f2ed8ae16c --- /dev/null +++ b/bsps/sparc/leon2/start/bspstart.c @@ -0,0 +1,127 @@ +/** + * @file + * @ingroup sparc_leon2 + * @brief LEON2 Cache Snooping Support + */ + +/* + * LEON2 Cache Snooping Support + * + * COPYRIGHT (c) 2011 + * Aeroflex Gaisler + * + * 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. + * + * Ported to ERC32 implementation of the SPARC by On-Line Applications + * Research Corporation (OAR) under contract to the European Space + * Agency (ESA). + * + * ERC32 modifications of respective RTEMS file: COPYRIGHT (c) 1995. + * European Space Agency. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <rtems/sysinit.h> + +/* + * Tells us if data cache snooping is available + */ +int CPU_SPARC_HAS_SNOOPING; + +/* + * set_snooping + * + * Read the data cache configuration register to determine if + * bus snooping is available. This is needed for some drivers so + * that they can select the most efficient copy routines. + */ +static inline int set_snooping(void) +{ + unsigned int tmp = *(unsigned int *)0x80000014; /* Cache control register */ + return ((tmp>>23) & 1); /* Data cache snooping enabled */ +} + +void bsp_start( void ) +{ + CPU_SPARC_HAS_SNOOPING = set_snooping(); +} + +/* If RTEMS_DRVMGR_STARTUP is defined extra code is added that + * registers the LEON2 AMBA bus driver as root driver into the + * driver manager. + * + * The structues here are declared weak so that the user can override + * the configuration and add custom cores in the RTEMS project. + */ +#ifdef RTEMS_DRVMGR_STARTUP +#include <drvmgr/drvmgr.h> +#include <drvmgr/leon2_amba_bus.h> + +/* All drivers included by BSP, this is overridden by the user by including + * the devmgr_confdefs.h. No specifc drivers needed by BSP since IRQ/TIMER/UART + * is not drvmgr drivers. + */ +drvmgr_drv_reg_func drvmgr_drivers[] __attribute__((weak)) = +{ + NULL /* End array with NULL */ +}; + +/* Defines what cores are avilable on the bus in addition to the standard + * LEON2 peripherals. + */ +struct leon2_core leon2_amba_custom_cores[] __attribute__((weak)) = +{ + EMPTY_LEON2_CORE +}; + +/* Configure LEON2 Root bus driver */ +struct leon2_bus leon2_bus_config __attribute__((weak)) = +{ + &leon2_std_cores[0], /* The standard cores, defined by driver */ + &leon2_amba_custom_cores[0], /* custom cores, defined by us */ + DRVMGR_TRANSLATE_ONE2ONE, + DRVMGR_TRANSLATE_ONE2ONE, +}; + +/* Driver resources on LEON2 AMBA bus. Used to set options for particular + * LEON2 cores, it is up to the driver to look at the configuration paramters + * once started. + */ +struct drvmgr_bus_res leon2_amba_res __attribute__((weak)) = +{ + .next = NULL, + .resource = { + DRVMGR_RES_EMPTY + }, +}; +#endif /* RTEMS_DRVMGR_STARTUP */ + +/* + * Called just before drivers are initialized. Is used to initialize shared + * interrupt handling. + */ +static void leon2_pre_driver_hook( void ) +{ + bsp_spurious_initialize(); + + /* Initialize shared interrupt handling, must be done after IRQ + * controller has been found and initialized. + */ + BSP_shared_interrupt_init(); + +#ifdef RTEMS_DRVMGR_STARTUP + leon2_root_register(&leon2_bus_config, &leon2_amba_res); +#endif +} + +RTEMS_SYSINIT_ITEM( + leon2_pre_driver_hook, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); diff --git a/bsps/sparc/leon2/start/linkcmds b/bsps/sparc/leon2/start/linkcmds new file mode 100644 index 0000000000..f1c7b9ce3e --- /dev/null +++ b/bsps/sparc/leon2/start/linkcmds @@ -0,0 +1,29 @@ +/* linkcmds + */ + +/* Default values, can be overridden */ + +_PROM_SIZE = DEFINED (_PROM_SIZE) ? _PROM_SIZE : 2M; +_PROM_START = DEFINED (_PROM_START) ? _PROM_START : 0x00000000; + +_RAM_SIZE = DEFINED (_RAM_SIZE) ? _RAM_SIZE : 4M; +_RAM_START = DEFINED (_RAM_START) ? _RAM_START : 0x40000000; + +/* + * Base address of the on-CPU peripherals + */ + +_LEON_REG = 0x80000000; +LEON_REG = _LEON_REG; + +/* these are the maximum values */ + +MEMORY +{ + rom : ORIGIN = 0x00000000, LENGTH = 256M + ram : ORIGIN = 0x40000000, LENGTH = 1024M +} + +ENTRY(start) + +INCLUDE linkcmds.base diff --git a/bsps/sparc/leon2/start/linkcmds.at697f b/bsps/sparc/leon2/start/linkcmds.at697f new file mode 100644 index 0000000000..36e6ec49cb --- /dev/null +++ b/bsps/sparc/leon2/start/linkcmds.at697f @@ -0,0 +1 @@ +INCLUDE linkcmds.leon2 diff --git a/bsps/sparc/leon2/start/linkcmds.leon2 b/bsps/sparc/leon2/start/linkcmds.leon2 new file mode 100644 index 0000000000..f1c7b9ce3e --- /dev/null +++ b/bsps/sparc/leon2/start/linkcmds.leon2 @@ -0,0 +1,29 @@ +/* linkcmds + */ + +/* Default values, can be overridden */ + +_PROM_SIZE = DEFINED (_PROM_SIZE) ? _PROM_SIZE : 2M; +_PROM_START = DEFINED (_PROM_START) ? _PROM_START : 0x00000000; + +_RAM_SIZE = DEFINED (_RAM_SIZE) ? _RAM_SIZE : 4M; +_RAM_START = DEFINED (_RAM_START) ? _RAM_START : 0x40000000; + +/* + * Base address of the on-CPU peripherals + */ + +_LEON_REG = 0x80000000; +LEON_REG = _LEON_REG; + +/* these are the maximum values */ + +MEMORY +{ + rom : ORIGIN = 0x00000000, LENGTH = 256M + ram : ORIGIN = 0x40000000, LENGTH = 1024M +} + +ENTRY(start) + +INCLUDE linkcmds.base diff --git a/bsps/sparc/leon2/start/setvec.c b/bsps/sparc/leon2/start/setvec.c new file mode 100644 index 0000000000..e2d839c2e4 --- /dev/null +++ b/bsps/sparc/leon2/start/setvec.c @@ -0,0 +1,65 @@ +/** + * @file + * @ingroup sparc_leon2 + * @brief Installs an interrupt vector on the SPARC simulator + */ + +/* set_vector + * + * This routine installs an interrupt vector on the SPARC simulator. + * + * INPUT PARAMETERS: + * handler - interrupt handler entry point + * vector - vector number + * type - 0 indicates raw hardware connect + * 1 indicates RTEMS interrupt connect + * + * OUTPUT PARAMETERS: NONE + * + * RETURNS: + * address of previous interrupt handler + * + * COPYRIGHT (c) 1989-1998. + * 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. + * + * Ported to LEON implementation of the SPARC by On-Line Applications + * Research Corporation (OAR) under contract to the European Space + * Agency (ESA). + * + * LEON modifications of respective RTEMS file: COPYRIGHT (c) 1995. + * European Space Agency. + */ + +#include <bsp.h> + +rtems_isr_entry set_vector( /* returns old vector */ + rtems_isr_entry handler, /* isr routine */ + rtems_vector_number vector, /* vector number */ + int type /* RTEMS or RAW intr */ +) +{ + rtems_isr_entry previous_isr; + uint32_t real_trap; + uint32_t source; + + if ( type ) + rtems_interrupt_catch( handler, vector, &previous_isr ); + else + _CPU_ISR_install_raw_handler( vector, handler, (void *)&previous_isr ); + + real_trap = SPARC_REAL_TRAP_NUMBER( vector ); + + if ( LEON_INT_TRAP( real_trap ) ) { + + source = LEON_TRAP_SOURCE( real_trap ); + + LEON_Clear_interrupt( source ); + LEON_Unmask_interrupt( source ); + } + + return previous_isr; +} diff --git a/bsps/sparc/leon2/start/spurious.c b/bsps/sparc/leon2/start/spurious.c new file mode 100644 index 0000000000..971c3cd44b --- /dev/null +++ b/bsps/sparc/leon2/start/spurious.c @@ -0,0 +1,184 @@ +/** + * @file + * @ingroup sparc_leon2 + * @brief LEON Spurious Trap Handler + */ + +/* + * LEON Spurious Trap Handler + * + * This is just enough of a trap handler to let us know what + * the likely source of the trap was. + * + * Developed as part of the port of RTEMS to the LEON implementation + * of the SPARC by On-Line Applications Research Corporation (OAR) + * under contract to the European Space Agency (ESA). + * + * COPYRIGHT (c) 1995. European Space Agency. + * + * This terms of the RTEMS license apply to this file. + */ + +#include <bsp.h> +#include <rtems/bspIo.h> +#include <inttypes.h> + +void _CPU_Exception_frame_print( const CPU_Exception_frame *frame ) +{ + uint32_t trap; + uint32_t real_trap; + const CPU_Interrupt_frame *isf; + + trap = frame->trap; + real_trap = SPARC_REAL_TRAP_NUMBER(trap); + isf = frame->isf; + + printk( + "Unexpected trap (%2" PRId32 ") at address 0x%08" PRIx32 "\n", + real_trap, + isf->tpc + ); + + switch (real_trap) { + + /* + * First the ones defined by the basic architecture + */ + + case 0x00: + printk( "reset\n" ); + break; + case 0x01: + printk( "instruction access exception\n" ); + break; + case 0x02: + printk( "illegal instruction\n" ); + break; + case 0x03: + printk( "privileged instruction\n" ); + break; + case 0x04: + printk( "fp disabled\n" ); + break; + case 0x07: + printk( "memory address not aligned\n" ); + break; + case 0x08: + printk( "fp exception\n" ); + break; + case 0x09: + printk("data access exception at 0x%08x\n", LEON_REG.Failed_Address ); + break; + case 0x0A: + printk( "tag overflow\n" ); + break; + + /* + * Then the ones defined by the LEON in particular + */ + + case LEON_TRAP_TYPE( LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR ): + printk( "LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR\n" ); + break; + case LEON_TRAP_TYPE( LEON_INTERRUPT_UART_2_RX_TX ): + printk( "LEON_INTERRUPT_UART_2_RX_TX\n" ); + break; + case LEON_TRAP_TYPE( LEON_INTERRUPT_UART_1_RX_TX ): + printk( "LEON_INTERRUPT_UART_1_RX_TX\n" ); + break; + case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_0 ): + printk( "LEON_INTERRUPT_EXTERNAL_0\n" ); + break; + case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_1 ): + printk( "LEON_INTERRUPT_EXTERNAL_1\n" ); + break; + case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_2 ): + printk( "LEON_INTERRUPT_EXTERNAL_2\n" ); + break; + case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_3 ): + printk( "LEON_INTERRUPT_EXTERNAL_3\n" ); + break; + case LEON_TRAP_TYPE( LEON_INTERRUPT_TIMER1 ): + printk( "LEON_INTERRUPT_TIMER1\n" ); + break; + case LEON_TRAP_TYPE( LEON_INTERRUPT_TIMER2 ): + printk( "LEON_INTERRUPT_TIMER2\n" ); + break; + + default: + break; + } +} + +static rtems_isr bsp_spurious_handler( + rtems_vector_number trap, + CPU_Interrupt_frame *isf +) +{ + CPU_Exception_frame frame = { + .trap = trap, + .isf = isf + }; + +#if !defined(SPARC_USE_LAZY_FP_SWITCH) + if ( SPARC_REAL_TRAP_NUMBER( trap ) == 4 ) { + _Internal_error( INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT ); + } +#endif + + rtems_fatal( + RTEMS_FATAL_SOURCE_EXCEPTION, + (rtems_fatal_code) &frame + ); +} + +/* + * bsp_spurious_initialize + * + * Install the spurious handler for most traps. Note that set_vector() + * will unmask the corresponding asynchronous interrupt, so the initial + * interrupt mask is restored after the handlers are installed. + */ + +void bsp_spurious_initialize() +{ + uint32_t trap; + uint32_t level; + uint32_t mask; + + level = sparc_disable_interrupts(); + mask = LEON_REG.Interrupt_Mask; + + for ( trap=0 ; trap<256 ; trap++ ) { + + /* + * Skip window overflow, underflow, and flush as well as software + * trap 0,9,10 which we will use as a shutdown, IRQ disable, IRQ enable. + * Also avoid trap 0x70 - 0x7f which cannot happen and where some of the + * space is used to pass parameters to the program. + */ + + if (( trap == 5 || trap == 6 ) || +#if defined(SPARC_USE_LAZY_FP_SWITCH) + ( trap == 4 ) || +#endif + (( trap >= 0x11 ) && ( trap <= 0x1f )) || + (( trap >= 0x70 ) && ( trap <= 0x83 )) || + ( trap == 0x80 + SPARC_SWTRAP_IRQDIS ) || +#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH) + ( trap == 0x80 + SPARC_SWTRAP_IRQDIS_FP ) || +#endif + ( trap == 0x80 + SPARC_SWTRAP_IRQEN )) + continue; + + set_vector( + (rtems_isr_entry) bsp_spurious_handler, + SPARC_SYNCHRONOUS_TRAP( trap ), + 1 + ); + } + + LEON_REG.Interrupt_Mask = mask; + sparc_enable_interrupts(level); + +} diff --git a/bsps/sparc/leon3/start/bsp_fatal_halt.c b/bsps/sparc/leon3/start/bsp_fatal_halt.c new file mode 100644 index 0000000000..fa907a3363 --- /dev/null +++ b/bsps/sparc/leon3/start/bsp_fatal_halt.c @@ -0,0 +1,36 @@ +/** + * @file + * @ingroup sparc_leon3 + * @brief LEON3 BSP Fatal_halt handler. + * + * COPYRIGHT (c) 2014. + * Aeroflex Gaisler AB. + * + * 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 <leon.h> + +#ifdef BSP_POWER_DOWN_AT_FATAL_HALT + +/* Power down LEON CPU on fatal error exit */ +void _CPU_Fatal_halt(uint32_t source, uint32_t error) +{ + sparc_disable_interrupts(); + leon3_power_down_loop(); +} + +#else + +/* return to debugger, simulator, hypervisor or similar by exiting + * with an error code. g1=1, g2=FATAL_SOURCE, G3=error-code. + */ +void _CPU_Fatal_halt(uint32_t source, uint32_t error) +{ + sparc_syscall_exit(source, error); +} + +#endif diff --git a/bsps/sparc/leon3/start/bsp_specs b/bsps/sparc/leon3/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/sparc/leon3/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_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/sparc/leon3/start/bspclean.c b/bsps/sparc/leon3/start/bspclean.c new file mode 100644 index 0000000000..eff9c8635b --- /dev/null +++ b/bsps/sparc/leon3/start/bspclean.c @@ -0,0 +1,83 @@ +/** + * @file + * @ingroup sparc_leon3 + * @brief LEON3 BSP fatal extension + * + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * COPYRIGHT (c) 2014 + * Aeroflex Gaisler + * + * 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 source, + bool always_set_to_false, + rtems_fatal_code code +) +{ + /* On SMP we must wait for all other CPUs not requesting a fatal halt, they + * are responding to another CPU's fatal request. These CPUs goes into + * power-down. The CPU requesting fatal halt waits for the others and then + * handles the system shutdown via the normal procedure. + */ + #ifdef RTEMS_SMP + if ((source == RTEMS_FATAL_SOURCE_SMP) && + (code == SMP_FATAL_SHUTDOWN_RESPONSE)) { + leon3_power_down_loop(); /* CPU didn't start shutdown sequence .. */ + } else { + volatile struct irqmp_regs *irqmp = LEON3_IrqCtrl_Regs; + + if (irqmp != NULL) { + /* + * Value was choosen to get something in the magnitude of 1ms on a 200MHz + * processor. + */ + uint32_t max_wait = 1234567; + uint32_t self_cpu = rtems_get_current_processor(); + uint32_t cpu_count = rtems_get_processor_count(); + uint32_t halt_mask = 0; + uint32_t i; + + for (i = 0; i < cpu_count; ++i) { + if ( (i != self_cpu) && _SMP_Should_start_processor( i ) ) { + halt_mask |= UINT32_C(1) << i; + } + } + + /* Wait some time for secondary processors to halt */ + i = 0; + while ((irqmp->mpstat & halt_mask) != halt_mask && i < max_wait) { + ++i; + } + } + } + #endif + + #if (BSP_PRINT_EXCEPTION_CONTEXT) + if ( source == RTEMS_FATAL_SOURCE_EXCEPTION ) { + rtems_exception_frame_print( (const rtems_exception_frame *) code ); + } + #endif + + /* + * If user wants to implement custom reset/reboot it can be done here + */ + #if (BSP_RESET_BOARD_AT_EXIT) + bsp_reset(); + #endif +} diff --git a/bsps/sparc/leon3/start/bspdelay.c b/bsps/sparc/leon3/start/bspdelay.c new file mode 100644 index 0000000000..938a8bdccb --- /dev/null +++ b/bsps/sparc/leon3/start/bspdelay.c @@ -0,0 +1,27 @@ +/** + * @file + * + * LEON3 BSP Delay Method + */ + +/* + * COPYRIGHT (c) 1989-2011. + * 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> + +void rtems_bsp_delay(int usecs) +{ + uint32_t then; + + then =LEON3_Timer_Regs->timer[0].value; + then += usecs; + + while (LEON3_Timer_Regs->timer[0].value >= then) + ; +} diff --git a/bsps/sparc/leon3/start/bspidle.S b/bsps/sparc/leon3/start/bspidle.S new file mode 100644 index 0000000000..8557ff42a1 --- /dev/null +++ b/bsps/sparc/leon3/start/bspidle.S @@ -0,0 +1,28 @@ +/* + * Idle Thread Body + * + * This routine puts LEON3 in power-down mode. + * + * COPYRIGHT (c) 2004. + * Gaisler Research. + * + * 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> + +/* LEON specific power-down function */ + + .align 4 + PUBLIC(bsp_idle_thread) + PUBLIC(leon3_power_down_loop) +SYM(bsp_idle_thread): +SYM(leon3_power_down_loop): +pwdloop: mov %g0, %asr19 + lda [%sp] 1, %g0 ! Needed for UT699 and GR712 + ba,a pwdloop + nop diff --git a/bsps/sparc/leon3/start/bspsmp.c b/bsps/sparc/leon3/start/bspsmp.c new file mode 100644 index 0000000000..280788fa1c --- /dev/null +++ b/bsps/sparc/leon3/start/bspsmp.c @@ -0,0 +1,97 @@ +/** + * @file + * @ingroup sparc_leon3 + * @brief LEON3 SMP BSP Support + */ + +/* + * COPYRIGHT (c) 1989-2011. + * 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> +#include <bsp/fatal.h> +#include <leon.h> +#include <rtems/bspIo.h> +#include <rtems/score/smpimpl.h> +#include <stdlib.h> + +#if !defined(__leon__) || defined(RTEMS_PARAVIRT) +uint32_t _CPU_SMP_Get_current_processor( void ) +{ + return _LEON3_Get_current_processor(); +} +#endif + +static rtems_isr bsp_inter_processor_interrupt( + rtems_vector_number vector +) +{ + _SMP_Inter_processor_interrupt_handler(); +} + +void bsp_start_on_secondary_processor() +{ + uint32_t cpu_index_self = _CPU_SMP_Get_current_processor(); + + /* + * If data cache snooping is not enabled we terminate using BSP_fatal_exit() + * instead of bsp_fatal(). This is done since the latter function tries to + * acquire a ticket lock, an operation which requires data cache snooping to + * be enabled. + */ + if ( !leon3_data_cache_snooping_enabled() ) + BSP_fatal_exit( LEON3_FATAL_INVALID_CACHE_CONFIG_SECONDARY_PROCESSOR ); + + /* Unmask IPI interrupts at Interrupt controller for this CPU */ + LEON3_IrqCtrl_Regs->mask[cpu_index_self] |= 1U << LEON3_mp_irq; + + _SMP_Start_multitasking_on_secondary_processor(); +} + +uint32_t _CPU_SMP_Initialize( void ) +{ + if ( !leon3_data_cache_snooping_enabled() ) + bsp_fatal( LEON3_FATAL_INVALID_CACHE_CONFIG_MAIN_PROCESSOR ); + + if ( rtems_configuration_get_maximum_processors() > 1 ) { + LEON_Unmask_interrupt(LEON3_mp_irq); + set_vector(bsp_inter_processor_interrupt, LEON_TRAP_TYPE(LEON3_mp_irq), 1); + } + + return leon3_get_cpu_count(LEON3_IrqCtrl_Regs); +} + +bool _CPU_SMP_Start_processor( uint32_t cpu_index ) +{ + #if defined(RTEMS_DEBUG) + printk( "Waking CPU %d\n", cpu_index ); + #endif + + LEON3_IrqCtrl_Regs->mpstat = 1U << cpu_index; + + return true; +} + +void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ) +{ + (void) cpu_count; + + /* Nothing to do */ +} + +void _CPU_SMP_Prepare_start_multitasking( void ) +{ + rtems_cache_invalidate_entire_instruction(); +} + +void _CPU_SMP_Send_interrupt(uint32_t target_processor_index) +{ + /* send interrupt to destination CPU */ + LEON3_IrqCtrl_Regs->force[target_processor_index] = 1 << LEON3_mp_irq; +} diff --git a/bsps/sparc/leon3/start/bspstart.c b/bsps/sparc/leon3/start/bspstart.c new file mode 100644 index 0000000000..58fc7d0907 --- /dev/null +++ b/bsps/sparc/leon3/start/bspstart.c @@ -0,0 +1,125 @@ +/* + * This set of routines starts the application. It includes application, + * board, and monitor specific initialization and configuration. + * The generic CPU dependent initialization has been performed + * before any of these are invoked. + * + * COPYRIGHT (c) 2011 + * Aeroflex Gaisler + * + * COPYRIGHT (c) 1989-2013. + * On-Line Applications Research Corporation (OAR). + * + * Modified for LEON3 BSP. + * COPYRIGHT (c) 2004. + * Gaisler Research. + * + * 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 <leon.h> +#include <bsp/bootcard.h> +#include <drvmgr/drvmgr.h> +#include <rtems/sysinit.h> + +#if defined(RTEMS_SMP) || defined(RTEMS_MULTIPROCESSING) +/* Irq used by shared memory driver and for inter-processor interrupts. + * Can be overridden by being defined in the application. + */ +const unsigned char LEON3_mp_irq __attribute__((weak)) = 14; +#endif + +/* + * Tells us if data cache snooping is available + */ +int CPU_SPARC_HAS_SNOOPING; + +/* Index of CPU, in an AMP system CPU-index may be non-zero */ +uint32_t LEON3_Cpu_Index = 0; + +#if defined(RTEMS_SMP) +/* Index of the boot CPU. Set by the first CPU at boot to its CPU ID. */ +int LEON3_Boot_Cpu = -1; +#endif + +/* + * set_snooping + * + * Read the cache control register to determine if + * bus snooping is available and enabled. This is needed for some + * drivers so that they can select the most efficient copy routines. + * + */ + +static inline int set_snooping(void) +{ + return (leon3_get_cache_control_register() >> 23) & 1; +} + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ +void bsp_start( void ) +{ + CPU_SPARC_HAS_SNOOPING = set_snooping(); +} + +static void leon3_cpu_index_init(void) +{ + /* Get the LEON3 CPU index, normally 0, but for MP systems we do + * _not_ assume that this is CPU0. One may run another OS on CPU0 + * and RTEMS on this CPU, and AMP system with mixed operating + * systems + */ + LEON3_Cpu_Index = _LEON3_Get_current_processor(); +} + +RTEMS_SYSINIT_ITEM( + leon3_cpu_index_init, + RTEMS_SYSINIT_BSP_START, + RTEMS_SYSINIT_ORDER_FIRST +); + +static void leon3_interrupt_common_init( void ) +{ + /* Initialize shared interrupt handling, must be done after IRQ + * controller has been found and initialized. + */ + BSP_shared_interrupt_init(); +} + +/* + * Called just before drivers are initialized. Is used to initialize shared + * interrupt handling. + */ +static void leon3_pre_driver_hook( void ) +{ + bsp_spurious_initialize(); + +#ifndef RTEMS_DRVMGR_STARTUP + leon3_interrupt_common_init(); +#endif +} + +RTEMS_SYSINIT_ITEM( + leon3_pre_driver_hook, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); + +#ifdef RTEMS_DRVMGR_STARTUP +/* + * Initialize shared interrupt handling, must be done after IRQ controller has + * been found and initialized. + */ +RTEMS_SYSINIT_ITEM( + leon3_interrupt_common_init, + RTEMS_SYSINIT_DRVMGR_LEVEL_1, + RTEMS_SYSINIT_ORDER_LAST +); +#endif diff --git a/bsps/sparc/leon3/start/cpucounter.c b/bsps/sparc/leon3/start/cpucounter.c new file mode 100644 index 0000000000..87554ce550 --- /dev/null +++ b/bsps/sparc/leon3/start/cpucounter.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014, 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 <leon.h> + +#include <rtems/counter.h> +#include <rtems/sysinit.h> +#include <rtems/score/sparcimpl.h> + +static void leon3_counter_initialize(void) +{ + volatile struct irqmp_timestamp_regs *irqmp_ts; + volatile struct gptimer_regs *gpt; + unsigned int freq; + + irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0]; + gpt = LEON3_Timer_Regs; + + leon3_up_counter_enable(); + + if (leon3_up_counter_is_available()) { + /* Use the LEON4 up-counter if available */ + + _SPARC_Counter_initialize( + _SPARC_Counter_read_asr23, + _SPARC_Counter_difference_normal, + NULL + ); + + freq = leon3_up_counter_frequency(); + rtems_counter_initialize_converter(freq); + } else if (leon3_irqmp_has_timestamp(irqmp_ts)) { + /* Use the interrupt controller timestamp counter if available */ + + /* Enable interrupt timestamping for an arbitrary interrupt line */ + irqmp_ts->control = 0x1; + + _SPARC_Counter_initialize( + _SPARC_Counter_read_address, + _SPARC_Counter_difference_normal, + (volatile const uint32_t *) &irqmp_ts->counter + ); + + freq = ambapp_freq_get(&ambapp_plb, LEON3_IrqCtrl_Adev); + rtems_counter_initialize_converter(freq); + } else if (gpt != NULL) { + /* Fall back to the first GPTIMER if available */ + + /* Enable timer just in case no clock driver is configured */ + gpt->timer[LEON3_CLOCK_INDEX].ctrl |= GPTIMER_TIMER_CTRL_EN; + + _SPARC_Counter_initialize( + _SPARC_Counter_read_address, + _SPARC_Counter_difference_clock_period, + (volatile const uint32_t *) &gpt->timer[LEON3_CLOCK_INDEX].value + ); + + freq = ambapp_freq_get(&ambapp_plb, LEON3_Timer_Adev); + rtems_counter_initialize_converter(freq / (gpt->scaler_reload - 1)); + } +} + +RTEMS_SYSINIT_ITEM( + leon3_counter_initialize, + RTEMS_SYSINIT_BSP_START, + RTEMS_SYSINIT_ORDER_THIRD +); + +SPARC_COUNTER_DEFINITION; diff --git a/bsps/sparc/leon3/start/eirq.c b/bsps/sparc/leon3/start/eirq.c new file mode 100644 index 0000000000..1f7be1ba74 --- /dev/null +++ b/bsps/sparc/leon3/start/eirq.c @@ -0,0 +1,66 @@ +/* + * GRLIB/LEON3 extended interrupt controller + * + * COPYRIGHT (c) 2011 + * Aeroflex Gaisler + * + * 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 <leon.h> +#include <bsp/irq.h> + +/* GRLIB extended IRQ controller IRQ number */ +int LEON3_IrqCtrl_EIrq = -1; + +/* Initialize Extended Interrupt controller */ +void leon3_ext_irq_init(void) +{ + if ( (LEON3_IrqCtrl_Regs->mpstat >> 16) & 0xf ) { + /* Extended IRQ controller available */ + LEON3_IrqCtrl_EIrq = (LEON3_IrqCtrl_Regs->mpstat >> 16) & 0xf; + } +} + +void bsp_interrupt_set_affinity( + rtems_vector_number vector, + const Processor_mask *affinity +) +{ + uint32_t unmasked = 0; + uint32_t cpu_count = rtems_get_processor_count(); + uint32_t cpu_index; + + for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) { + if (_Processor_mask_Is_set(affinity, cpu_index)) { + BSP_Cpu_Unmask_interrupt(vector, cpu_index); + ++unmasked; + } + } + + if (unmasked > 1) { + LEON_Enable_interrupt_broadcast(vector); + } else { + LEON_Disable_interrupt_broadcast(vector); + } +} + +void bsp_interrupt_get_affinity( + rtems_vector_number vector, + Processor_mask *affinity +) +{ + uint32_t cpu_count = rtems_get_processor_count(); + uint32_t cpu_index; + + _Processor_mask_Zero(affinity); + + for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) { + if (!BSP_Cpu_Is_interrupt_masked(vector, cpu_index)) { + _Processor_mask_Set(affinity, cpu_index); + } + } +} diff --git a/bsps/sparc/leon3/start/linkcmds.gr712rc b/bsps/sparc/leon3/start/linkcmds.gr712rc new file mode 100644 index 0000000000..6954e88f45 --- /dev/null +++ b/bsps/sparc/leon3/start/linkcmds.gr712rc @@ -0,0 +1,22 @@ +/* linkcmds + */ + +/* Default values, can be overridden */ + +_PROM_SIZE = DEFINED (_PROM_SIZE) ? _PROM_SIZE : 2M; +_PROM_START = DEFINED (_PROM_START) ? _PROM_START : 0x00000000; + +_RAM_SIZE = DEFINED (_RAM_SIZE) ? _RAM_SIZE : 4M; +_RAM_START = DEFINED (_RAM_START) ? _RAM_START : 0x40000000; + +/* these are the maximum values */ + +MEMORY +{ + rom : ORIGIN = 0x00000000, LENGTH = 256M + ram : ORIGIN = 0x40000000, LENGTH = 1024M +} + +ENTRY(start) + +INCLUDE linkcmds.base diff --git a/bsps/sparc/leon3/start/linkcmds.gr740 b/bsps/sparc/leon3/start/linkcmds.gr740 new file mode 100644 index 0000000000..c16fd7fd7f --- /dev/null +++ b/bsps/sparc/leon3/start/linkcmds.gr740 @@ -0,0 +1,21 @@ +/* Default values, can be overridden */ + +_PROM_SIZE = DEFINED (_PROM_SIZE) ? _PROM_SIZE : 0; + +_RAM_SIZE = DEFINED (_RAM_SIZE) ? _RAM_SIZE : 64M; + +/* these are the maximum values */ + +MEMORY +{ + rom : ORIGIN = 0xC0000000, LENGTH = 256M + ram : ORIGIN = 0x00000000, LENGTH = 2048M + sram : ORIGIN = 0xD0000000, LENGTH = 256M +} + +_PROM_START = ORIGIN (rom); +_RAM_START = ORIGIN (ram); + +ENTRY(start) + +INCLUDE linkcmds.base diff --git a/bsps/sparc/leon3/start/linkcmds.leon3 b/bsps/sparc/leon3/start/linkcmds.leon3 new file mode 100644 index 0000000000..6954e88f45 --- /dev/null +++ b/bsps/sparc/leon3/start/linkcmds.leon3 @@ -0,0 +1,22 @@ +/* linkcmds + */ + +/* Default values, can be overridden */ + +_PROM_SIZE = DEFINED (_PROM_SIZE) ? _PROM_SIZE : 2M; +_PROM_START = DEFINED (_PROM_START) ? _PROM_START : 0x00000000; + +_RAM_SIZE = DEFINED (_RAM_SIZE) ? _RAM_SIZE : 4M; +_RAM_START = DEFINED (_RAM_START) ? _RAM_START : 0x40000000; + +/* these are the maximum values */ + +MEMORY +{ + rom : ORIGIN = 0x00000000, LENGTH = 256M + ram : ORIGIN = 0x40000000, LENGTH = 1024M +} + +ENTRY(start) + +INCLUDE linkcmds.base diff --git a/bsps/sparc/leon3/start/linkcmds.ut699 b/bsps/sparc/leon3/start/linkcmds.ut699 new file mode 100644 index 0000000000..6954e88f45 --- /dev/null +++ b/bsps/sparc/leon3/start/linkcmds.ut699 @@ -0,0 +1,22 @@ +/* linkcmds + */ + +/* Default values, can be overridden */ + +_PROM_SIZE = DEFINED (_PROM_SIZE) ? _PROM_SIZE : 2M; +_PROM_START = DEFINED (_PROM_START) ? _PROM_START : 0x00000000; + +_RAM_SIZE = DEFINED (_RAM_SIZE) ? _RAM_SIZE : 4M; +_RAM_START = DEFINED (_RAM_START) ? _RAM_START : 0x40000000; + +/* these are the maximum values */ + +MEMORY +{ + rom : ORIGIN = 0x00000000, LENGTH = 256M + ram : ORIGIN = 0x40000000, LENGTH = 1024M +} + +ENTRY(start) + +INCLUDE linkcmds.base diff --git a/bsps/sparc/leon3/start/linkcmds.ut700 b/bsps/sparc/leon3/start/linkcmds.ut700 new file mode 100644 index 0000000000..6954e88f45 --- /dev/null +++ b/bsps/sparc/leon3/start/linkcmds.ut700 @@ -0,0 +1,22 @@ +/* linkcmds + */ + +/* Default values, can be overridden */ + +_PROM_SIZE = DEFINED (_PROM_SIZE) ? _PROM_SIZE : 2M; +_PROM_START = DEFINED (_PROM_START) ? _PROM_START : 0x00000000; + +_RAM_SIZE = DEFINED (_RAM_SIZE) ? _RAM_SIZE : 4M; +_RAM_START = DEFINED (_RAM_START) ? _RAM_START : 0x40000000; + +/* these are the maximum values */ + +MEMORY +{ + rom : ORIGIN = 0x00000000, LENGTH = 256M + ram : ORIGIN = 0x40000000, LENGTH = 1024M +} + +ENTRY(start) + +INCLUDE linkcmds.base diff --git a/bsps/sparc/leon3/start/setvec.c b/bsps/sparc/leon3/start/setvec.c new file mode 100644 index 0000000000..5b5888d51a --- /dev/null +++ b/bsps/sparc/leon3/start/setvec.c @@ -0,0 +1,64 @@ +/** + * @file + * @ingroup sparc_leon3 + * @brief Install an interrupt vector on SPARC + */ + +/* This routine installs an interrupt vector on the SPARC simulator. + * + * INPUT PARAMETERS: + * handler - interrupt handler entry point + * vector - vector number + * type - 0 indicates raw hardware connect + * 1 indicates RTEMS interrupt connect + * + * OUTPUT PARAMETERS: NONE + * + * RETURNS: + * address of previous interrupt handler + */ + +/* COPYRIGHT (c) 1989-1998. + * 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. + * + * Ported to LEON implementation of the SPARC by On-Line Applications + * Research Corporation (OAR) under contract to the European Space + * Agency (ESA). + * + * LEON modifications of respective RTEMS file: COPYRIGHT (c) 1995. + * European Space Agency. + */ + +#include <bsp.h> + +rtems_isr_entry set_vector( /* returns old vector */ + rtems_isr_entry handler, /* isr routine */ + rtems_vector_number vector, /* vector number */ + int type /* RTEMS or RAW intr */ +) +{ + rtems_isr_entry previous_isr; + uint32_t real_trap; + uint32_t source; + + if ( type ) + rtems_interrupt_catch( handler, vector, &previous_isr ); + else + _CPU_ISR_install_raw_handler( vector, handler, (void *)&previous_isr ); + + real_trap = SPARC_REAL_TRAP_NUMBER( vector ); + + if ( LEON_INT_TRAP( real_trap ) ) { + + source = LEON_TRAP_SOURCE( real_trap ); + + LEON_Clear_interrupt( source ); + LEON_Unmask_interrupt( source ); + } + + return previous_isr; +} diff --git a/bsps/sparc/leon3/start/spurious.c b/bsps/sparc/leon3/start/spurious.c new file mode 100644 index 0000000000..23ac4bf4cf --- /dev/null +++ b/bsps/sparc/leon3/start/spurious.c @@ -0,0 +1,183 @@ +/* + * LEON Spurious Trap Handler + * + * This is just enough of a trap handler to let us know what + * the likely source of the trap was. + * + * Developed as part of the port of RTEMS to the LEON implementation + * of the SPARC by On-Line Applications Research Corporation (OAR) + * under contract to the European Space Agency (ESA). + * + * COPYRIGHT (c) 1995. European Space Agency. + * + * Modified for LEON3 BSP. + * COPYRIGHT (c) 2004. + * Gaisler Research. + * + * This terms of the RTEMS license apply to this file. + */ + +#include <bsp.h> +#include <rtems/score/cpu.h> +#include <rtems/bspIo.h> +#include <inttypes.h> + +void _CPU_Exception_frame_print( const CPU_Exception_frame *frame ) +{ + uint32_t trap; + uint32_t real_trap; + const CPU_Interrupt_frame *isf; + + trap = frame->trap; + real_trap = SPARC_REAL_TRAP_NUMBER(trap); + isf = frame->isf; + + printk( + "Unexpected trap (%2" PRId32 ") at address 0x%08" PRIx32 "\n", + real_trap, + isf->tpc + ); + + switch (real_trap) { + + /* + * First the ones defined by the basic architecture + */ + + case 0x00: + printk( "reset\n" ); + break; + case 0x01: + printk( "instruction access exception\n" ); + break; + case 0x02: + printk( "illegal instruction\n" ); + break; + case 0x03: + printk( "privileged instruction\n" ); + break; + case 0x04: + printk( "fp disabled\n" ); + break; + case 0x07: + printk( "memory address not aligned\n" ); + break; + case 0x08: + printk( "fp exception\n" ); + break; + case 0x0A: + printk( "tag overflow\n" ); + break; + + /* + * Then the ones defined by the LEON in particular + */ + /* FIXME */ + + /* + case LEON_TRAP_TYPE( LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR ): + printk( "LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR\n" ); + break; + case LEON_TRAP_TYPE( LEON_INTERRUPT_UART_2_RX_TX ): + printk( "LEON_INTERRUPT_UART_2_RX_TX\n" ); + break; + case LEON_TRAP_TYPE( LEON_INTERRUPT_UART_1_RX_TX ): + printk( "LEON_INTERRUPT_UART_1_RX_TX\n" ); + break; + case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_0 ): + printk( "LEON_INTERRUPT_EXTERNAL_0\n" ); + break; + case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_1 ): + printk( "LEON_INTERRUPT_EXTERNAL_1\n" ); + break; + case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_2 ): + printk( "LEON_INTERRUPT_EXTERNAL_2\n" ); + break; + case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_3 ): + printk( "LEON_INTERRUPT_EXTERNAL_3\n" ); + break; + case LEON_TRAP_TYPE( LEON_INTERRUPT_TIMER1 ): + printk( "LEON_INTERRUPT_TIMER1\n" ); + break; + case LEON_TRAP_TYPE( LEON_INTERRUPT_TIMER2 ): + printk( "LEON_INTERRUPT_TIMER2\n" ); + break; + */ + + default: + break; + } +} + +static rtems_isr bsp_spurious_handler( + rtems_vector_number trap, + CPU_Interrupt_frame *isf +) +{ + CPU_Exception_frame frame = { + .trap = trap, + .isf = isf + }; + +#if !defined(SPARC_USE_LAZY_FP_SWITCH) + if ( SPARC_REAL_TRAP_NUMBER( trap ) == 4 ) { + _Internal_error( INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT ); + } +#endif + + rtems_fatal( + RTEMS_FATAL_SOURCE_EXCEPTION, + (rtems_fatal_code) &frame + ); +} + +/* + * bsp_spurious_initialize + * + * Install the spurious handler for most traps. Note that set_vector() + * will unmask the corresponding asynchronous interrupt, so the initial + * interrupt mask is restored after the handlers are installed. + */ + +void bsp_spurious_initialize() +{ + uint32_t trap; + uint32_t level; + /* uint32_t mask; */ + + level = sparc_disable_interrupts(); + /* mask = LEON3_IrqCtrl_Regs->mask_p0; */ + + for ( trap=0 ; trap<256 ; trap++ ) { + + /* + * Skip window overflow, underflow, and flush as well as software + * trap 0,9,10 which we will use as a shutdown, IRQ disable, IRQ enable. + * Also avoid trap 0x70 - 0x7f which cannot happen and where some of the + * space is used to pass parameters to the program. + */ + + if (( trap == 5 ) || ( trap == 6 ) || +#if defined(SPARC_USE_LAZY_FP_SWITCH) + ( trap == 4 ) || +#endif + (( trap >= 0x11 ) && ( trap <= 0x1f )) || + (( trap >= 0x70 ) && ( trap <= 0x83 )) || + ( trap == 0x80 + SPARC_SWTRAP_IRQDIS ) || +#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH) + ( trap == 0x80 + SPARC_SWTRAP_IRQDIS_FP ) || +#endif + ( trap == 0x80 + SPARC_SWTRAP_IRQEN )) + continue; + + set_vector( + (rtems_isr_entry) bsp_spurious_handler, + SPARC_SYNCHRONOUS_TRAP( trap ), + 1 + ); + } + + /* LEON3_IrqCtrl_Regs->mask_p0 = mask; */ + sparc_enable_interrupts(level); + +} diff --git a/bsps/sparc/shared/start/bsp_fatal_exit.c b/bsps/sparc/shared/start/bsp_fatal_exit.c new file mode 100644 index 0000000000..8b64125c93 --- /dev/null +++ b/bsps/sparc/shared/start/bsp_fatal_exit.c @@ -0,0 +1,22 @@ +/** + * @file + * @ingroup sparc_bsp + * @brief ERC32/LEON2/LEON3 BSP specific exit handler. + */ + +/* + * COPYRIGHT (c) 2014. + * Aeroflex Gaisler AB. + * + * 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/score/cpu.h> + +void BSP_fatal_exit(uint32_t error) +{ + sparc_syscall_exit(RTEMS_FATAL_SOURCE_BSP, error); +} diff --git a/bsps/sparc/shared/start/bsp_fatal_halt.c b/bsps/sparc/shared/start/bsp_fatal_halt.c new file mode 100644 index 0000000000..f32ddaafc0 --- /dev/null +++ b/bsps/sparc/shared/start/bsp_fatal_halt.c @@ -0,0 +1,38 @@ +/** + * @file + * @ingroup sparc_bsp + * @brief ERC32/LEON2 BSP Fatal_halt handler. + * + * COPYRIGHT (c) 2014. + * Aeroflex Gaisler AB. + * + * 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> + +#ifdef BSP_POWER_DOWN_AT_FATAL_HALT + +/* Spin CPU on fatal error exit */ +void _CPU_Fatal_halt(uint32_t source, uint32_t error) +{ + uint32_t level = sparc_disable_interrupts(); + + __asm__ volatile ( "mov %0, %%g1 " : "=r" (level) : "0" (level) ); + + while (1) ; /* loop forever */ +} + +#else + +/* return to debugger, simulator, hypervisor or similar by exiting + * with an error code. g1=1, g2=FATAL_SOURCE, G3=error-code. + */ +void _CPU_Fatal_halt(uint32_t source, uint32_t error) +{ + sparc_syscall_exit(source, error); +} + +#endif diff --git a/bsps/sparc/shared/start/bspgetworkarea.c b/bsps/sparc/shared/start/bspgetworkarea.c new file mode 100644 index 0000000000..b05113d9eb --- /dev/null +++ b/bsps/sparc/shared/start/bspgetworkarea.c @@ -0,0 +1,63 @@ +/* + * This set of routines are the BSP specific initialization + * support routines. + * + * COPYRIGHT (c) 1989-2008. + * 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. + */ + +/* #define BSP_GET_WORK_AREA_DEBUG */ +#include <bsp.h> +#include <bsp/bootcard.h> +#ifdef BSP_GET_WORK_AREA_DEBUG + #include <rtems/bspIo.h> +#endif + +/* Tells us where to put the workspace in case remote debugger is present. */ +extern uint32_t rdb_start; + +/* + * This method returns the base address and size of the area which + * is to be allocated between the RTEMS Workspace and the C Program + * Heap. + */ +void bsp_work_area_initialize(void) +{ + /* must be identical to STACK_SIZE in start.S */ + #define STACK_SIZE (16 * 1024) + + /* Early dynamic memory allocator is placed just above _end */ + void *work_area_start = (void *)&end; + uintptr_t work_area_size = + (uintptr_t)rdb_start - (uintptr_t)&end - STACK_SIZE; + + /* + * The following may be helpful in debugging what goes wrong when + * you are allocating the Work Area in a new BSP. + */ + #ifdef BSP_GET_WORK_AREA_DEBUG + { + void *sp = __builtin_frame_address(0); + void *end = *work_area_start + *work_area_size; + printk( + "work_area_start = 0x%p\n" + "work_area_size = %d 0x%08x\n" + "end = 0x%p\n" + "current stack pointer = 0x%p%s\n", + work_area_start, + work_area_size, /* decimal */ + work_area_size, /* hexadecimal */ + end, + sp, + ((sp >= *work_area_start && sp <= end) ? " OVERLAPS!" : "") + ); + printk( "rdb_start = 0x%08x\n", rdb_start ); + } + #endif + + bsp_work_area_initialize_default(work_area_start, work_area_size); +} diff --git a/bsps/sparc/shared/start/linkcmds.base b/bsps/sparc/shared/start/linkcmds.base new file mode 100644 index 0000000000..4c7750dfe0 --- /dev/null +++ b/bsps/sparc/shared/start/linkcmds.base @@ -0,0 +1,207 @@ +/* linkcmds + */ + +OUTPUT_ARCH(sparc) +__DYNAMIC = 0; + +/* + * The memory map looks like this: + * +--------------------+ <- low memory + * | .text | + * | etext | + * | ctor list | the ctor and dtor lists are for + * | dtor list | C++ support + * | _endtext | + * +--------------------+ + * | .data | initialized data goes here + * | _sdata | + * | _edata | + * +--------------------+ + * | .bss | + * | __bss_start | start of bss, cleared by crt0 + * | _end | start of heap, used by sbrk() + * +--------------------+ + * | heap space | + * | _ENDHEAP | + * | stack space | + * | __stack | top of stack + * +--------------------+ <- high memory + */ + +_RAM_END = _RAM_START + _RAM_SIZE; + +_PROM_END = _PROM_START + _PROM_SIZE; + +/* + * Alternate names without leading _. + */ + +PROM_START = _PROM_START; +PROM_SIZE = _PROM_SIZE; +PROM_END = _PROM_END; + +RAM_START = _RAM_START; +RAM_SIZE = _RAM_SIZE; +RAM_END = _RAM_END; + +/* + * SPARC monitor assumes this is present to provide proper RTEMS awareness. + */ +EXTERN(rtems_get_version_string); + +STARTUP(start.o) + +/* + * stick everything in ram (of course) + */ +SECTIONS +{ + .text : + { + CREATE_OBJECT_SYMBOLS + text_start = .; + _text_start = .; + *(.text*) + . = ALIGN (16); + + KEEP(*(.eh_frame*)) + . = ALIGN (16); + + *(.gnu.linkonce.t*) + + /* + * C++ constructors + */ + /* 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)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + + _rodata_start = . ; + *(.rodata*) + *(.gnu.linkonce.r*) + _erodata = ALIGN( 0x10 ) ; + + etext = ALIGN(0x10); + _etext = .; + KEEP(*(.init*)) + KEEP(*(.fini*)) + *(.lit) + *(.shdata) + . = ALIGN (16); + } > ram + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > ram + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } > ram + _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)); + .rtemsroset : { + /* for pre rtems-libbsd FreeBSD code */ + __start_set_sysctl_set = .; + KEEP(*(set_sysctl_*)); + __stop_set_sysctl_set = .; + KEEP(*(set_domain_*)); + KEEP(*(set_pseudo_*)); + + KEEP (*(SORT(.rtemsroset.*))) + + . = ALIGN (16); + _endtext = .; + } >ram + .rela.dyn : + { + *(.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*) + } >ram + .data : + { + data_start = .; + _data_start = .; + _sdata = . ; + *(.data*) + *(.gnu.linkonce.d*) + . = ALIGN(0x10); + *(.gcc_except_table*) + . = ALIGN(0x10); + edata = .; + _edata = .; + } > ram + _data_load_start = LOADADDR (.data); + .rtemsrwset : { + KEEP (*(SORT(.rtemsrwset.*))) + } >ram + .dynamic : { *(.dynamic) } >ram + .jcr : { *(.jcr) } >ram + .got : { *(.got) } >ram + .plt : { *(.plt) } >ram + .hash : { *(.hash) } >ram + .dynrel : { *(.dynrel) } >ram + .dynsym : { *(.dynsym) } >ram + .dynstr : { *(.dynstr) } >ram + .hash : { *(.hash) } >ram + .shbss : + { + *(.shbss) + } > ram + .bss : + { + __bss_start = ALIGN(0x8); + _bss_start = .; + bss_start = .; + *(.bss .bss* .gnu.linkonce.b*) + *(COMMON) + . = ALIGN (16); + end = .; + _end = ALIGN(0x8); + __end = ALIGN(0x8); + } > ram + .stab . (NOLOAD) : + { + [ .stab ] + } + .stabstr . (NOLOAD) : + { + [ .stabstr ] + } +} diff --git a/bsps/sparc64/niagara/start/bsp_specs b/bsps/sparc64/niagara/start/bsp_specs new file mode 100644 index 0000000000..0b4b0db932 --- /dev/null +++ b/bsps/sparc64/niagara/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_endfile)} %{!nostdlib: %{qrtems: crtend.o%s crtn.o%s}} diff --git a/bsps/sparc64/niagara/start/bspclean.c b/bsps/sparc64/niagara/start/bspclean.c new file mode 100644 index 0000000000..eacc264e5b --- /dev/null +++ b/bsps/sparc64/niagara/start/bspclean.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2014 Gedare Bloom. + * + * 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 "m5op.h" + +void bsp_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code code +) +{ + m5_exit(0); +} diff --git a/bsps/sparc64/niagara/start/m5op.h b/bsps/sparc64/niagara/start/m5op.h new file mode 100644 index 0000000000..d349e4d6bc --- /dev/null +++ b/bsps/sparc64/niagara/start/m5op.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2003-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * 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; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT + * OWNER 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. + * + * Authors: Nathan Binkert + * Ali Saidi + */ + +#ifndef __M5OP_H__ +#define __M5OP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +void arm(uint64_t address); +void quiesce(void); +void quiesceNs(uint64_t ns); +void quiesceCycle(uint64_t cycles); +uint64_t quiesceTime(void); +uint64_t rpns(void); +void wakeCPU(uint64_t cpuid); + +void m5_exit(uint64_t ns_delay); +void m5_fail(uint64_t ns_delay, uint64_t code); +uint64_t m5_initparam(void); +void m5_checkpoint(uint64_t ns_delay, uint64_t ns_period); +void m5_reset_stats(uint64_t ns_delay, uint64_t ns_period); +void m5_dump_stats(uint64_t ns_delay, uint64_t ns_period); +void m5_dumpreset_stats(uint64_t ns_delay, uint64_t ns_period); +uint64_t m5_readfile(void *buffer, uint64_t len, uint64_t offset); +uint64_t m5_writefile(void *buffer, uint64_t len, uint64_t offset, const char *filename); +void m5_debugbreak(void); +void m5_switchcpu(void); +void m5_addsymbol(uint64_t addr, char *symbol); +void m5_panic(void); +void m5_work_begin(uint64_t workid, uint64_t threadid); +void m5_work_end(uint64_t workid, uint64_t threadid); + +// These operations are for critical path annotation +void m5a_bsm(char *sm, const void *id, int flags); +void m5a_esm(char *sm); +void m5a_begin(int flags, char *st); +void m5a_end(void); +void m5a_q(const void *id, char *q, int count); +void m5a_dq(const void *id, char *q, int count); +void m5a_wf(const void *id, char *q, char *sm, int count); +void m5a_we(const void *id, char *q, char *sm, int count); +void m5a_ws(const void *id, char *q, char *sm); +void m5a_sq(const void *id, char *q, int count, int flags); +void m5a_aq(const void *id, char *q, int count); +void m5a_pq(const void *id, char *q, int count); +void m5a_l(char *lsm, const void *id, char *sm); +void m5a_identify(uint64_t id); +uint64_t m5a_getid(void); + +#define M5_AN_FL_NONE 0x0 +#define M5_AN_FL_BAD 0x2 +#define M5_AN_FL_LINK 0x10 +#define M5_AN_FL_RESET 0x20 + +#ifdef __cplusplus +} +#endif +#endif // __M5OP_H__ diff --git a/bsps/sparc64/niagara/start/m5op_sparc.S b/bsps/sparc64/niagara/start/m5op_sparc.S new file mode 100644 index 0000000000..40248ff8bf --- /dev/null +++ b/bsps/sparc64/niagara/start/m5op_sparc.S @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2003-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * 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; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT + * OWNER 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. + * + * Authors: Nathan Binkert + * Ali Saidi + */ + +#define m5_op 0x2 +#define m5_op3 0x37 + +#include "m5ops.h" + +#define INST(func, rs1, rs2, rd) \ + .long (m5_op) << 30 | (rd) << 25 | (m5_op3) << 19 | (func) << 7 | \ + (rs1) << 14 | (rs2) << 0; + + +#define LEAF(func) \ + .section ".text"; \ + .align 4; \ + .global func; \ + .type func, #function; \ +func: + +#define END(func) \ + .size func, (.-func) + +#define DEBUGBREAK INST(debugbreak_func, 0, 0, 0) +#define M5EXIT INST(exit_func, 0, 0, 0) +#define PANIC INST(panic_func, 0, 0, 0) +#define READFILE INST(readfile_func, 0, 0, 0) + +LEAF(m5_exit) + retl + M5EXIT +END(m5_exit) + +LEAF(m5_panic) + retl + PANIC +END(m5_panic) + +LEAF(m5_readfile) + retl + READFILE +END(m5_readfile) + +LEAF(m5_debugbreak) + retl + DEBUGBREAK +END(m5_debugbreak) + +/* !!!!!! All code below here just panics !!!!!! */ +LEAF(arm) + retl + PANIC +END(arm) + +LEAF(quiesce) + retl + PANIC +END(quiesce) + +LEAF(quiesceNs) + retl + PANIC +END(quiesceNs) + +LEAF(quiesceCycle) + retl + PANIC +END(quiesceCycle) + +LEAF(quiesceTime) + retl + PANIC +END(quiesceTime) + +LEAF(m5_initparam) + retl + PANIC +END(m5_initparam) + +LEAF(m5_loadsymbol) + retl + PANIC +END(m5_loadsymbol) + +LEAF(m5_reset_stats) + retl + PANIC +END(m5_reset_stats) + +LEAF(m5_dump_stats) + retl + PANIC +END(m5_dump_stats) + +LEAF(m5_dumpreset_stats) + retl + PANIC +END(m5_dumpreset_stats) + +LEAF(m5_checkpoint) + retl + PANIC +END(m5_checkpoint) + +LEAF(m5_switchcpu) + retl + PANIC +END(m5_switchcpu) + +LEAF(m5_addsymbol) + retl + PANIC +END(m5_addsymbol) + +LEAF(m5_anbegin) + retl + PANIC +END(m5_anbegin) + +LEAF(m5_anwait) + retl + PANIC +END(m5_anwait) + + diff --git a/bsps/sparc64/niagara/start/m5ops.h b/bsps/sparc64/niagara/start/m5ops.h new file mode 100644 index 0000000000..8ff1ac42f1 --- /dev/null +++ b/bsps/sparc64/niagara/start/m5ops.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2003-2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * 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; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT + * OWNER 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. + * + * Authors: Nathan Binkert + * Ali Saidi + */ + +#define arm_func 0x00 +#define quiesce_func 0x01 +#define quiescens_func 0x02 +#define quiescecycle_func 0x03 +#define quiescetime_func 0x04 +#define rpns_func 0x07 +#define wakecpu_func 0x09 +#define deprecated1_func 0x10 // obsolete ivlb +#define deprecated2_func 0x11 // obsolete ivle +#define deprecated3_func 0x20 // deprecated exit function +#define exit_func 0x21 +#define fail_func 0x22 +#define initparam_func 0x30 +#define loadsymbol_func 0x31 +#define resetstats_func 0x40 +#define dumpstats_func 0x41 +#define dumprststats_func 0x42 +#define ckpt_func 0x43 +#define writefile_func 0x4F +#define readfile_func 0x50 +#define debugbreak_func 0x51 +#define switchcpu_func 0x52 +#define addsymbol_func 0x53 +#define panic_func 0x54 + +#define reserved2_func 0x56 // Reserved for user +#define reserved3_func 0x57 // Reserved for user +#define reserved4_func 0x58 // Reserved for user +#define reserved5_func 0x59 // Reserved for user + +#define work_begin_func 0x5a +#define work_end_func 0x5b + +// These operations are for critical path annotation +#define annotate_func 0x55 +#define an_bsm 0x1 +#define an_esm 0x2 +#define an_begin 0x3 +#define an_end 0x4 +#define an_q 0x6 +#define an_dq 0x7 +#define an_wf 0x8 +#define an_we 0x9 +#define an_rq 0xA +#define an_ws 0xB +#define an_sq 0xC +#define an_aq 0xD +#define an_pq 0xE +#define an_l 0xF +#define an_identify 0x10 +#define an_getid 0x11 + diff --git a/bsps/sparc64/shared/start/linkcmds b/bsps/sparc64/shared/start/linkcmds new file mode 100644 index 0000000000..2f9db3a087 --- /dev/null +++ b/bsps/sparc64/shared/start/linkcmds @@ -0,0 +1,218 @@ +/* linkcmds + */ + +/* + * For alignment, SPARC v9 specifies that instructions are 4-byte aligned, + * and the worst-case alignment requirements for data are for quad-word + * accesses, which must be 16-byte aligned. + */ + +/* + * Declare some sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamSize : 4M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 1M; + +RAM_END = RamBase + RamSize; + +/* Default linker script, for normal executables */ +OUTPUT_FORMAT("elf64-sparc") +ENTRY(_start) +STARTUP(start.o) + +MEMORY +{ + ram : ORIGIN = 0x0, LENGTH = 12M +} + +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.text : + { + *(.rel.text) + *(.rel.text.*) + *(.rel.gnu.linkonce.t*) + } + .rela.text : + { + *(.rela.text) + *(.rela.text.*) + *(.rela.gnu.linkonce.t*) + } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.rodata : + { + *(.rel.rodata) + *(.rel.rodata.*) + *(.rel.gnu.linkonce.r*) + } + .rela.rodata : + { + *(.rela.rodata) + *(.rela.rodata.*) + *(.rela.gnu.linkonce.r*) + } + .rel.data : + { + *(.rel.data) + *(.rel.data.*) + *(.rel.gnu.linkonce.d*) + } + .rela.data : + { + *(.rela.data) + *(.rela.data.*) + *(.rela.gnu.linkonce.d*) + } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + /* Internal text space or external memory */ + .text 0x4000 : AT (0x4000) + { + *(BOOTSTRAP); + *(.text*) + + KEEP (*(.init)) + KEEP (*(.fini)) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + *(.eh_frame) + . = ALIGN (16); + + *(.gnu.linkonce.t*) + *(.gcc_except_table*) + + /* + * C++ constructors + */ + /* 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)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + + _rodata_start = . ; + *(.rodata*) + KEEP (*(SORT(.rtemsroset.*))) + *(.gnu.linkonce.r*) + _erodata = ALIGN( 0x10 ) ; + + *(.lit) + *(.shdata) + + . = ALIGN (16); + _endtext = . ; + _etext = . ; + } > ram + + .tdata : AT (ADDR (.text) + SIZEOF (.text)) { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > ram + .tbss : AT (ADDR (.tdata) + SIZEOF (.tdata)) { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } > ram + _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)); + + .data : AT (ADDR (.tbss) + SIZEOF (.tbss)) + { + PROVIDE (__data_start = .) ; + data_start = . ; + _data_start = . ; + *(.data) + *(.data*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.rodata) /* We need to include .rodata here if gcc is used */ + *(.rodata*) /* with -fdata-sections. */ + *(.gnu.linkonce.d*) + . = ALIGN(2); + edata = . ; + _edata = . ; + PROVIDE (__data_end = .) ; + } > ram + + /* XXX + __data_load_start = LOADADDR(.data); + __data_load_end = __data_load_start + SIZEOF(.data); + */ + . = ALIGN (16); + .dynamic : { *(.dynamic) } >ram + .jcr : { *(.jcr) } > ram + .shbss : { *(.shbss) } > ram + .bss : + { + FILL(0x00000000); + . = ALIGN(16); + __bss_start = ALIGN(0x8); + bss_start = .; + bss_start = .; + *(.bss .bss* .gnu.linkonce.b*) + *(COMMON) + . = ALIGN (16); + end = .; + _end = .; + __end = .; + + . = ALIGN (16); /* arbitrary alignment */ + PROVIDE (WorkAreaBase = .); + . += HeapSize; + PROVIDE (HeapBase = .); + . += HeapSize; + } > ram +} + + diff --git a/bsps/sparc64/shared/start/setvec.c b/bsps/sparc64/shared/start/setvec.c new file mode 100644 index 0000000000..12c7713285 --- /dev/null +++ b/bsps/sparc64/shared/start/setvec.c @@ -0,0 +1,57 @@ +/* set_vector + * + * This routine installs an interrupt vector on the sun4v niagara + * + * INPUT PARAMETERS: + * handler - interrupt handler entry point + * vector - vector number + * type - 0 indicates raw hardware connect + * 1 indicates RTEMS interrupt connect + * + * OUTPUT PARAMETERS: NONE + * + * RETURNS: + * address of previous interrupt handler + * + * COPYRIGHT (c) 1989-1998. On-Line Applications Research Corporation (OAR). + * COPYRIGHT (c) 2010. Gedare Bloom. + * + * 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> + +rtems_isr_entry set_vector( /* returns old vector */ + rtems_isr_entry handler, /* isr routine */ + rtems_vector_number vector, /* vector number */ + int type /* RTEMS or RAW intr */ +) +{ + rtems_isr_entry previous_isr; + uint32_t real_trap; + uint32_t source; + int bit_mask; + + if ( type ) + rtems_interrupt_catch( handler, vector, &previous_isr ); + else + _CPU_ISR_install_raw_handler( vector, handler, (void *)&previous_isr ); + + real_trap = SPARC_REAL_TRAP_NUMBER( vector ); + + /* check if this is an interrupt, if so, clear and unmask interrupts for + * this level + */ + /* Interrupts have real_trap numbers between 0x41 and 0x4F (levels 1 - 15) */ + if (real_trap >= 0x41 && real_trap <= 0x4F) { + source = real_trap - 0x40; + bit_mask = 1<<source; + + sparc64_clear_interrupt_bits(bit_mask); + } + + + return previous_isr; +} diff --git a/bsps/sparc64/usiii/start/bsp_specs b/bsps/sparc64/usiii/start/bsp_specs new file mode 100644 index 0000000000..0b4b0db932 --- /dev/null +++ b/bsps/sparc64/usiii/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_endfile)} %{!nostdlib: %{qrtems: crtend.o%s crtn.o%s}} diff --git a/bsps/v850/gdbv850sim/start/bsp_specs b/bsps/v850/gdbv850sim/start/bsp_specs new file mode 100644 index 0000000000..13be8e3f41 --- /dev/null +++ b/bsps/v850/gdbv850sim/start/bsp_specs @@ -0,0 +1,5 @@ +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: }} diff --git a/bsps/v850/gdbv850sim/start/bspreset.c b/bsps/v850/gdbv850sim/start/bspreset.c new file mode 100644 index 0000000000..b2986f4a24 --- /dev/null +++ b/bsps/v850/gdbv850sim/start/bspreset.c @@ -0,0 +1,23 @@ +/** + * @file + * + * This routine exits the simulator. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * 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/syscall.h> + +void bsp_reset( void ) +{ + TRAP0 (SYS_exit, 0, 0, 0); +} diff --git a/bsps/v850/gdbv850sim/start/linkcmds b/bsps/v850/gdbv850sim/start/linkcmds new file mode 100644 index 0000000000..42dccab5ae --- /dev/null +++ b/bsps/v850/gdbv850sim/start/linkcmds @@ -0,0 +1,242 @@ +/* + * Declare some sizes. + */ +_RamBase = DEFINED(_RamBase) ? _RamBase : 0x100000; /* RAM starts at 1MB */ +_RamSize = DEFINED(_RamSize) ? _RamSize : 0x100000; /* default is 1MB */ +_HeapSize = DEFINED(_HeapSize) ? _HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x1000; + +/* Default linker script, for normal executables */ +OUTPUT_FORMAT("elf32-v850-rh850", "elf32-v850-rh850", + "elf32-v850-rh850") +STARTUP(start.o) +OUTPUT_ARCH(v850-rh850) +ENTRY(_start) +/* GROUP(-lc -lsim -lgcc) */ +SEARCH_DIR(.); +EXTERN(__ctbp __ep __gp); +SECTIONS +{ + /* This saves a little space in the ELF file, since the zda starts + at a higher location that the ELF headers take up. */ + .zdata 0x160 : + { + *(.zdata) + *(.zbss) + *(reszdata) + *(.zcommon) + } + /* This is the read only part of the zero data area. + Having it as a seperate section prevents its + attributes from being inherited by the zdata + section. Specifically it prevents the zdata + section from being marked READONLY. */ + .rozdata ALIGN (4) : + { + *(.rozdata) + *(romzdata) + *(romzbss) + } + /* Read-only sections, merged into text segment. */ + . = 0x100000; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.gcc_except_table : { *(.rel.gcc_except_table) } + .rela.gcc_except_table : { *(.rela.gcc_except_table) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { KEEP (*(.init)) } =0 + .plt : { *(.plt) } + .text : + { + *(.text) + *(.text.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } =0 + _etext = .; + PROVIDE (etext = .); + /* This is special code area at the end of the normal text section. + It contains a small lookup table at the start followed by the + code pointed to by entries in the lookup table. */ + .call_table_data ALIGN (4) : + { + PROVIDE(__ctbp = .); + *(.call_table_data) + } = 0xff /* Fill gaps with 0xff. */ + .call_table_text : + { + *(.call_table_text) + } + .fini : { KEEP (*(.fini)) } =0 + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .rtemsroset : { + /* for pre rtems-libbsd FreeBSD code */ + ___start_set_sysctl_set = .; + *(set_sysctl_*); + ___stop_set_sysctl_set = .; + *(set_domain_*); + *(set_pseudo_*); + + KEEP (*(SORT(.rtemsroset.*))) + } =0xff + .tdata : { + __TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + __TLS_Data_end = .; + } + .tbss : { + __TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + __TLS_BSS_end = .; + } + __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)); + .data : + { + *(.data) + *(.data.*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + CONSTRUCTORS + } + .data1 : { *(.data1) } + .ctors : + { + ___ctors = .; + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend(.ctors)) + ___ctors_end = .; + } + .dtors : + { + ___dtors = .; + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + ___dtors_end = .; + } + .jcr : + { + KEEP (*(.jcr)) + } + .gcc_except_table : { *(.gcc_except_table) } + .got : { *(.got.plt) *(.got) } + .dynamic : { *(.dynamic) } + .tdata ALIGN (4) : + { + PROVIDE (__ep = .); + *(.tbyte) + *(.tcommon_byte) + *(.tdata) + *(.tbss) + *(.tcommon) + } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata ALIGN (4) : + { + PROVIDE (__gp = . + 0x8000); + *(.sdata) + } + /* See comment about .rozdata. */ + .rosdata ALIGN (4) : + { + *(.rosdata) + } + /* We place the .sbss data section AFTER the .rosdata section, so that + it can directly preceed the .bss section. This allows runtime startup + code to initialise all the zero-data sections by simply taking the + value of '_edata' and zeroing until it reaches '_end'. */ + .sbss : + { + __sbss_start = .; + *(.sbss) + *(.scommon) + } + _edata = DEFINED (__sbss_start) ? __sbss_start : . ; + PROVIDE (edata = _edata); + .bss : + { + __bss_start = DEFINED (__sbss_start) ? __sbss_start : . ; + __real_bss_start = . ; + *(.dynbss) + *(.bss) + *(COMMON) + } + . += _StackSize; + _stack = .; + _WorkAreaBase = .; + _end = . ; + PROVIDE (end = .); + /* 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) } + /* libgloss - User stack. */ +/* + .stack 0x200000 : + { + __stack = .; + *(.stack) + } +*/ +} + diff --git a/bsps/v850/gdbv850sim/start/trap.S b/bsps/v850/gdbv850sim/start/trap.S new file mode 100644 index 0000000000..b6003b216d --- /dev/null +++ b/bsps/v850/gdbv850sim/start/trap.S @@ -0,0 +1,14 @@ +/* from libgloss/v850 */ + .text + .global ___trap0 +___trap0: + trap 31 + tst r10,r10 + bz .L0 +/* + * Libgloss cares about the errno from this. We don't + movhi hi(_errno),r0,r6 + st.w r10,lo(_errno)[r6] +*/ +.L0: + jmp [r31] |