/** * @file * * @ingroup mpc55xx * * @brief 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.com/license/LICENSE. */ #include #include #include #include #include #include #include #include #include #include #include #define RTEMS_STATUS_CHECKS_USE_PRINTK #include #define DEBUG_DONE() DEBUG_PRINT( "Done\n") #define MPC55XX_INTERRUPT_STACK_SIZE 0x1000 /* Symbols defined in linker command file */ LINKER_SYMBOL( bsp_ram_start); LINKER_SYMBOL( bsp_ram_end); LINKER_SYMBOL( bsp_external_ram_start); LINKER_SYMBOL( bsp_external_ram_size); LINKER_SYMBOL( bsp_section_bss_end); unsigned int bsp_clock_speed = 0; uint32_t bsp_clicks_per_usec = 0; void BSP_panic( char *s) { rtems_interrupt_level level; rtems_interrupt_disable( level); printk( "%s PANIC %s\n", _RTEMS_version, s); while (1) { /* Do nothing */ } } void _BSP_Fatal_error( unsigned n) { rtems_interrupt_level level; rtems_interrupt_disable( level); printk( "%s PANIC ERROR %u\n", _RTEMS_version, n); while (1) { /* Do nothing */ } } void bsp_pretasking_hook() { uint32_t heap_start = bsp_external_ram_start; uint32_t heap_size = bsp_external_ram_size; bsp_libc_init( heap_start, heap_size, 0); #ifdef STACK_CHECKER_ON Stack_check_Initialize(); #endif #ifdef RTEMS_DEBUG rtems_debug_enable( RTEMS_DEBUG_ALL_MASK ); #endif } void bsp_predriver_hook() { rtems_status_code sc = RTEMS_SUCCESSFUL; DEBUG_PRINT( "Initialize eDMA ...\n"); sc = mpc55xx_edma_init(); if (sc != RTEMS_SUCCESSFUL) { BSP_panic( "Cannot initialize eDMA"); } else { DEBUG_DONE(); } } static void mpc55xx_ebi_init() { struct EBI_CS_tag cs = { BR : MPC55XX_ZERO_FLAGS, OR : MPC55XX_ZERO_FLAGS }; union SIU_PCR_tag pcr = MPC55XX_ZERO_FLAGS; int i = 0; /* External SRAM (0 wait states, 512kB, 4 word burst) */ cs.BR.B.BA = 0; cs.BR.B.PS = 1; cs.BR.B.BL = 1; cs.BR.B.WEBS = 0; cs.BR.B.TBDIP = 0; cs.BR.B.BI = 1; /* TODO: Enable burst */ cs.BR.B.V = 1; cs.OR.B.AM = 0x1fff0; cs.OR.B.SCY = 0; cs.OR.B.BSCY = 0; EBI.CS [0] = cs; /* !CS [0] */ SIU.PCR [0].R = 0x443; /* ADDR [8 : 31] */ for (i = 4; i < 4 + 24; ++i) { SIU.PCR [i].R = 0x440; } /* DATA [0 : 15] */ for (i = 28; i < 28 + 16; ++i) { SIU.PCR [i].R = 0x440; } /* RD_!WR */ SIU.PCR [62].R = 0x443; /* !BDIP */ SIU.PCR [63].R = 0x443; /* !WE [0 : 3] */ for (i = 64; i < 64 + 4; ++i) { SIU.PCR [i].R = 0x443; } /* !OE */ SIU.PCR [68].R = 0x443; /* !TS */ SIU.PCR [69].R = 0x443; } /** * @brief Start BSP. */ void bsp_start(void) { ppc_cpu_id_t myCpu; ppc_cpu_revision_t myCpuRevision; uint32_t ram_start = bsp_ram_start; uint32_t ram_end = bsp_ram_end; uint32_t interrupt_stack_start = ram_end - 2 * MPC55XX_INTERRUPT_STACK_SIZE; uint32_t interrupt_stack_size = MPC55XX_INTERRUPT_STACK_SIZE; uint32_t work_space_start = bsp_section_bss_end; uint32_t work_space_end = work_space_start + rtems_configuration_get_work_space_size(); /* ESCI pad configuration */ SIU.PCR [89].R = 0x400; SIU.PCR [90].R = 0x400; DEBUG_PRINT( "BSP start ...\n"); /* Memory layout */ Configuration.work_space_start = work_space_start; DEBUG_PRINT( "System clock : %i\n", mpc55xx_get_system_clock()); DEBUG_PRINT( "Memory start : 0x%08x\n", ram_start); DEBUG_PRINT( "Memory end : 0x%08x\n", ram_end); DEBUG_PRINT( "Memory size : 0x%08x\n", ram_end - ram_start); DEBUG_PRINT( "Work space start : 0x%08x\n", work_space_start); DEBUG_PRINT( "Work space end : 0x%08x\n", work_space_end); DEBUG_PRINT( "Work space size : 0x%08x\n", work_space_end - work_space_start); DEBUG_PRINT( "Interrupt stack start : 0x%08x\n", interrupt_stack_start); DEBUG_PRINT( "Interrupt stack end : 0x%08x\n", interrupt_stack_start + interrupt_stack_size); DEBUG_PRINT( "Interrupt stack size : 0x%08x\n", interrupt_stack_size); if (work_space_end > interrupt_stack_start) { BSP_panic( "Not enough memory for the work space"); } /* * 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... */ myCpu = get_ppc_cpu_type(); myCpuRevision = get_ppc_cpu_revision(); /* Time reference value */ bsp_clicks_per_usec = bsp_clock_speed / 1000000; /* Initialize External Bus Interface */ mpc55xx_ebi_init(); /* Initialize exceptions */ DEBUG_PRINT( "Initialize exceptions ...\n"); ppc_exc_initialize( PPC_INTERRUPT_DISABLE_MASK_DEFAULT, interrupt_stack_start, interrupt_stack_size); DEBUG_DONE(); /* Initialize interrupts */ DEBUG_PRINT( "Initialize interrupts ...\n"); if (bsp_interrupt_initialize() != RTEMS_SUCCESSFUL) { BSP_panic( "Cannot initialize interrupts"); } else { DEBUG_DONE(); } DEBUG_PRINT( "BSP start done\n"); return; /* TODO */ /* * Enable instruction and data caches. Do not force writethrough mode. */ #if INSTRUCTION_CACHE_ENABLE rtems_cache_enable_instruction(); #endif #if DATA_CACHE_ENABLE rtems_cache_enable_data(); #endif } /** * @brief Idle thread body. */ Thread _Thread_Idle_body( uint32_t ignored) { while (1) { asm volatile( "mfmsr 3;" "oris 3,3,4;" "sync;" "mtmsr 3;" "isync;" "ori 3,3,0;" "ori 3,3,0" ); } return 0; }