diff options
Diffstat (limited to 'c')
-rw-r--r-- | c/src/lib/libbsp/powerpc/virtex4/Makefile.am | 15 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/virtex4/README | 86 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/virtex4/clock/clock.c | 265 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/virtex4/include/mmu.h | 269 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c | 18 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/virtex4/mmu/mmu.c | 567 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/virtex4/preinstall.am | 4 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/virtex4/startup/bspstart.c | 84 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/virtex4/startup/linkcmds | 13 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/virtex4/startup/start.S | 22 |
10 files changed, 1010 insertions, 333 deletions
diff --git a/c/src/lib/libbsp/powerpc/virtex4/Makefile.am b/c/src/lib/libbsp/powerpc/virtex4/Makefile.am index adce2972f5..58fcea5beb 100644 --- a/c/src/lib/libbsp/powerpc/virtex4/Makefile.am +++ b/c/src/lib/libbsp/powerpc/virtex4/Makefile.am @@ -36,15 +36,12 @@ libbsp_a_SOURCES = startup/bspclean.c \ startup/bspstart.c \ ../../shared/bootcard.c \ ../../shared/sbrk.c \ - ../../shared/gnatinstallhandler.c + ../../shared/gnatinstallhandler.c \ + ../shared/src/memcpy.c # start libbsp_a_SOURCES += startup/start.S -# clock & timer -libbsp_a_SOURCES += ../../../libcpu/@RTEMS_CPU@/ppc403/clock/clock.c -libbsp_a_SOURCES += ../../../libcpu/@RTEMS_CPU@/ppc403/timer/timer.c - # console libbsp_a_SOURCES += startup/dummy_console.c \ ../../shared/dummy_printk_support.c @@ -53,6 +50,10 @@ libbsp_a_SOURCES += startup/dummy_console.c \ include_bsp_HEADERS += include/irq.h libbsp_a_SOURCES += irq/irq_init.c +# mmu +include_bsp_HEADERS += include/mmu.h +libbsp_a_SOURCES += mmu/mmu.c + #vectors include_bsp_HEADERS += ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/vectors.h include_bsp_HEADERS += ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/irq_supp.h @@ -60,7 +61,9 @@ include_bsp_HEADERS += ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/irq_s libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/@exceptions@/rtems-cpu.rel \ ../../../libcpu/@RTEMS_CPU@/@exceptions@/exc_bspsupport.rel \ ../../../libcpu/@RTEMS_CPU@/shared/cache.rel \ - ../../../libcpu/@RTEMS_CPU@/shared/cpuIdent.rel + ../../../libcpu/@RTEMS_CPU@/shared/cpuIdent.rel \ + ../../../libcpu/@RTEMS_CPU@/ppc403/clock.rel \ + ../../../libcpu/@RTEMS_CPU@/ppc403/timer.rel EXTRA_DIST = times diff --git a/c/src/lib/libbsp/powerpc/virtex4/README b/c/src/lib/libbsp/powerpc/virtex4/README new file mode 100644 index 0000000000..68a0c24e2e --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/README @@ -0,0 +1,86 @@ +# Adapted from virtex BSP + +BSP NAME: virtex4 +BOARD: N/A +BUS: N/A +CPU FAMILY: ppc +CPU: PowerPC 405D5 +COPROCESSORS: N/A +MODE: 32 bit mode + +DEBUG MONITOR: + +PERIPHERALS +=========== +TIMERS: 405 internal +SERIAL PORTS: none +REAL-TIME CLOCK: none +DMA: Xilinx virtex internal +VIDEO: none +SCSI: none +NETWORKING: none + +DRIVER INFORMATION +================== +CLOCK DRIVER: PPC Decrementer +IOSUPP DRIVER: N/A +SHMSUPP: N/A +TIMER DRIVER: N/A +TTY DRIVER: N/A + +STDIO +===== +PORT: N/A +ELECTRICAL: N/A +BAUD: N/A +BITS PER CHARACTER: N/A +PARITY: N/A +STOP BITS: N/A + +Notes +===== + +Board description +----------------- +clock rate: 350 MHz +ROM: N/A +RAM: 128MByte DRAM + +Virtex only supports single processor operations. + +Porting +------- +This board support package is written for a naked Virtex 4/PPC FPGA +system. The rough features of such a board are described above. +The BSP itself makes no assumptions on what is loaded in the FPGA, +other than that the CPU has access to some memory, either on-board +or external, from which code can be run. + +This BSP has been constructed so that an application of both firmware +and software can be layered on top of it by supplying implementations +for the various 'weak' symbols. These symbols are prefaced with the +term 'app_'. Applications can thus be built outside of the RTEMS +directory tree by linking with the appropriate libraries. + +The linkcmds file describes the memory layout. Included in this +definition is a section of memory named MsgArea. Output sent to +stdout is recorded in this area and can be dumped using the JTAG +interface, for example. + +For adapting this BSP to other boards, the following files should be +modified: + +- c/src/lib/libbsp/powerpc/virtex4/startup/linkcmds + for the memory layout required + +- c/src/lib/libbsp/powerpc/virtex4/startup/bspstart.c + Here you can select the clock source for the timers and the + serial interface (system clock or external clock pin), the + clock rates, etc. + +- c/src/lib/libbsp/powerpc/virtex4/include/bsp.h + some BSP-related constants + +- c/src/lib/libbsp/powerpc/virtex4/* + well, they should be generic, so there _should_ be no reason + to mess around there (but who knows...) diff --git a/c/src/lib/libbsp/powerpc/virtex4/clock/clock.c b/c/src/lib/libbsp/powerpc/virtex4/clock/clock.c deleted file mode 100644 index 7617720d45..0000000000 --- a/c/src/lib/libbsp/powerpc/virtex4/clock/clock.c +++ /dev/null @@ -1,265 +0,0 @@ -/* clock.c - * - * This routine initializes the interval timer on the - * PowerPC 403 CPU. The tick frequency is specified by the 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. - * - * Derived from c/src/lib/libcpu/hppa1.1/clock/clock.c: - * - * Modifications for deriving timer clock from cpu system clock by - * Thomas Doerfler <td@imd.m.isar.de> - * for these modifications: - * COPYRIGHT (c) 1997 by IMD, Puchheim, Germany. - * - * 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.com/license/LICENSE. - * - * Modifications for PPC405GP by Dennis Ehlin - */ - -#include <rtems.h> -#include <rtems/clockdrv.h> -#include <rtems/libio.h> -#include <stdlib.h> /* for atexit() */ -#include <rtems/bspIo.h> -#include <rtems/powerpc/powerpc.h> - -/* - * check, which exception handling code is present - */ - -#include <bsp.h> - -#include <bsp/vectors.h> -#include <bsp/irq_supp.h> - -volatile uint32_t Clock_driver_ticks; -static uint32_t pit_value, tick_time; -static bool auto_restart; - -void Clock_exit( void ); - -/* - * These are set by clock driver during its init - */ - -rtems_device_major_number rtems_clock_major = ~0; -rtems_device_minor_number rtems_clock_minor; - -static inline uint32_t get_itimer(void) -{ - register uint32_t rc; - - asm volatile ("mfspr %0, 0x10c" : "=r" ((rc))); /* 405GP TBL */ - - return rc; -} - -/* - * ISR Handler - */ - -int Clock_isr(BSP_Exception_frame *f, unsigned int vector) -{ - uint32_t clicks_til_next_interrupt; -#if defined(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL) - uint32_t l_orig = _ISR_Get_level(); -#endif - if (!auto_restart) - { - uint32_t itimer_value; - /* - * setup for next interrupt; making sure the new value is reasonably - * in the future.... in case we lost out on an interrupt somehow - */ - - itimer_value = get_itimer(); - tick_time += pit_value; - - /* - * how far away is next interrupt *really* - * It may be a long time; this subtraction works even if - * Clock_clicks_interrupt < Clock_clicks_low_order via - * the miracle of unsigned math. - */ - clicks_til_next_interrupt = tick_time - itimer_value; - - /* - * If it is too soon then bump it up. - * This should only happen if CPU_HPPA_CLICKS_PER_TICK is too small. - * But setting it low is useful for debug, so... - */ - - if (clicks_til_next_interrupt < 400) - { - tick_time = itimer_value + 1000; - clicks_til_next_interrupt = 1000; - /* XXX: count these! this should be rare */ - } - - /* - * If it is too late, that means we missed the interrupt somehow. - * Rather than wait 35-50s for a wrap, we just fudge it here. - */ - - if (clicks_til_next_interrupt > pit_value) - { - tick_time = itimer_value + 1000; - clicks_til_next_interrupt = 1000; - /* XXX: count these! this should never happen :-) */ - } - - asm volatile ("mtspr 0x3db, %0" :: "r" - (clicks_til_next_interrupt)); /* PIT */ - } - - /* Clear the Programmable Interrupt Status */ - asm volatile ( "mtspr 0x3d8, %0" :: "r" (0x08000000)); /* TSR */ - - Clock_driver_ticks++; - - rtems_clock_tick(); - - return 0; -} - -void ClockOff(void) -{ - register uint32_t tcr; - - asm volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */ - - tcr &= ~ 0x04400000; - - asm volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */ -} - -void ClockOn(void) -{ - uint32_t iocr; - register uint32_t tcr; - - Clock_driver_ticks = 0; - - asm volatile ("mfdcr %0, 0x0b2" : "=r" (iocr)); /*405GP CPC0_CR1 */ - if (bsp_timer_internal_clock) { - iocr &=~0x800000; /* timer clocked from system clock CETE*/ - } - else { - iocr |= 0x800000; /* select external timer clock CETE*/ - } - asm volatile ("mtdcr 0x0b2, %0" : "=r" (iocr) : "0" (iocr)); /* 405GP CPC0_CR1 */ - - /* - * Enable auto restart - */ - - auto_restart = true; - - pit_value = rtems_configuration_get_microseconds_per_tick() * - bsp_clicks_per_usec; - - /* - * Set PIT value - */ - - asm volatile ("mtspr 0x3db, %0" : : "r" (pit_value)); /* PIT */ - - /* - * Set timer to autoreload, bit TCR->ARE = 1 0x0400000 - * Enable PIT interrupt, bit TCR->PIE = 1 0x4000000 - */ - tick_time = get_itimer() + pit_value; - - asm volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */ - tcr = (tcr & ~0x04400000) | (auto_restart ? 0x04400000 : 0x04000000); - asm volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */ -} - - - -void Install_clock(ppc_exc_handler_t clock_isr) -{ -#ifdef ppc403 - uint32_t pvr; -#endif /* ppc403 */ - - Clock_driver_ticks = 0; - - /* - * initialize the interval here - * First tick is set to right amount of time in the future - * Future ticks will be incremented over last value set - * in order to provide consistent clicks in the face of - * interrupt overhead - */ - - ppc_exc_set_handler( BSP_PPC403_CLOCK_HOOK_EXCEPTION, clock_isr ); - ClockOn(); - - atexit(Clock_exit); -} - -void -ReInstall_clock(ppc_exc_handler_t clock_isr) -{ - uint32_t isrlevel = 0; - - rtems_interrupt_disable(isrlevel); - - ppc_exc_set_handler( BSP_PPC403_CLOCK_HOOK_EXCEPTION, clock_isr ); - ClockOn(); - - rtems_interrupt_enable(isrlevel); -} - - -/* - * Called via atexit() - * Remove the clock interrupt handler by setting handler to NULL - * - * This will not work on the 405GP because - * when bit's are set in TCR they can only be unset by a reset - */ - -void Clock_exit(void) -{ - ClockOff(); - ppc_exc_set_handler( BSP_PPC403_CLOCK_HOOK_EXCEPTION, 0 ); -} - -rtems_device_driver Clock_initialize( - rtems_device_major_number major, - rtems_device_minor_number minor, - void *pargp -) -{ - Install_clock( Clock_isr ); - - /* - * make major/minor avail to others such as shared memory driver - */ - - rtems_clock_major = major; - rtems_clock_minor = minor; - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/powerpc/virtex4/include/mmu.h b/c/src/lib/libbsp/powerpc/virtex4/include/mmu.h new file mode 100644 index 0000000000..3e2710b95c --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/include/mmu.h @@ -0,0 +1,269 @@ +#ifndef RTEMS_VIRTEX4_MMU_H +#define RTEMS_VIRTEX4_MMU_H +/** + * @file + * + * @ingroup Virtex4MMU + * + * @brief Routines to manipulate the PPC 405 MMU. + */ +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2005-2007, + * Stanford Linear Accelerator Center, Stanford University. + * and was transcribed for the PPC 405 by + * R. Claus <claus@slac.stanford.edu>, 2012, + * 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 <rtems.h> +#include <inttypes.h> +#include <stdio.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup Virtex4MMU Virtex 4 - MMU Support + * + * @ingroup Virtex4 + * + * @brief MMU support. + * + * @{ + */ + +/* Some routines require or return a index 'key'. + */ +typedef int bsp_tlb_idx_t; + +/* Cache the relevant TLB entries so that we can make sure the user cannot + * create conflicting (overlapping) entries. Keep them public for informational + * purposes. + */ +typedef struct { + struct { + uint32_t pad:24; + uint32_t tid:8; /** Translation ID */ + } id; + struct { + uint32_t epn:22; /** Effective page number */ + uint32_t size:3; /** Page size */ + uint32_t v:1; /** Valid */ + uint32_t att:2; /** Little-endian, User-defined */ + uint32_t pad:4; + } hi; /** High word*/ + struct { + uint32_t rpn:22; /** Real page number */ + uint32_t perm:6; /** Execute enable, Write-enable, Zone select */ + uint32_t wimg:4; /** Write-through, Caching inhibited, Mem coherent, Guarded */ + } lo; /** Low word */ +} bsp_tlb_entry_t; + +#define NTLBS 64 + +extern bsp_tlb_entry_t* bsp_mmu_cache; + + +// These constants will have to be shifted right by 20 bits before +// being inserted the high word of the TLB. + +#define MMU_M_SIZE_1K (0x00000000U) +#define MMU_M_SIZE_4K (0x08000000U) +#define MMU_M_SIZE_16K (0x10000000U) +#define MMU_M_SIZE_64K (0x18000000U) +#define MMU_M_SIZE_256K (0x20000000U) +#define MMU_M_SIZE_1M (0x28000000U) +#define MMU_M_SIZE_4M (0x30000000U) +#define MMU_M_SIZE_16M (0x38000000U) +#define MMU_M_SIZE_MIN (MMU_M_SIZE_1K) +#define MMU_M_SIZE_MAX (MMU_M_SIZE_16M) +#define MMU_M_SIZE (0x38000000U) +#define MMU_V_SIZE (27) + +#define MMU_M_ATTR_LITTLE_ENDIAN (0x02000000U) +#define MMU_M_ATTR_USER0 (0x01000000U) +#define MMU_M_ATTR (0x03000000U) +#define MMU_V_ATTR (24) + +// These constants have the same bit positions they'll occupy +// in low word of the TLB. + +#define MMU_M_PERM_EXEC (0x00000200U) +#define MMU_M_PERM_DATA_WRITE (0x00000100U) +#define MMU_M_PERM_ZONE_SELECT (0x000000f0U) +#define MMU_M_PERM (0x000003f0U) +#define MMU_V_PERM (4) + +#define MMU_M_PROP_WRITE_THROUGH (0x00000008U) +#define MMU_M_PROP_UNCACHED (0x00000004U) +#define MMU_M_PROP_MEM_COHERENT (0x00000002U) +#define MMU_M_PROP_GUARDED (0x00000001U) +#define MMU_M_PROP (0x0000000fU) +#define MMU_V_PROP (0) + + +/* + * Dump (cleartext) content info from cached TLB entries + * to a file (stdout if f==NULL). + */ +void +bsp_mmu_dump_cache(FILE *f); + +/* Read a TLB entry from the hardware and store the settings in the + * bsp_mmu_cache[] structure. + * + * The routine can perform this operation quietly or + * print information to a file. + * + * 'key': TLB entry index. + * 'quiet': perform operation silently (no info printed) if nonzero. + * 'f': open FILE where to print information. May be NULL, in + * which case 'stdout' is used. + * + * RETURNS: + * 0: success; TLB entry is VALID + * +1: success but TLB entry is INVALID + * < 0: error (-1: invalid argument) + * (-2: driver not initialized) + */ +int +bsp_mmu_update(bsp_tlb_idx_t key, bool quiet, FILE *f); + +/* Initialize cache. Should be done only once although this is not enforced. + * + * RETURNS: zero on success, nonzero on error; in this case the driver will + * refuse to change TLB entries (other than disabling them). + */ +int +bsp_mmu_initialize(void); + +/* Find first free TLB entry by examining all entries' valid bit. The first + * entry without the valid bit set is returned. + * + * RETURNS: A free TLB entry number. -1 if no entry can be found. + */ +bsp_tlb_idx_t +bsp_mmu_find_first_free(void); + +/* Write a TLB entry (can also be used to disable an entry). + * + * The routine checks against the cached data in bsp_mmu_cache[] + * to prevent the user from generating overlapping entries. + * + * 'idx': TLB entry # to manipulate + * 'ea': Effective address (must be page aligned) + * 'pa': Physical address (must be page aligned) + * 'sz': Page size selector; page size is 1024 * 2^(2*sz) bytes. + * 'sz' may also be one of the following: + * - page size in bytes ( >= 1024 ); the selector + * value is then computed by this routine. + * However, 'sz' must be a valid page size + * or -1 will be returned. + * - a value < 0 to invalidate/disable the + * TLB entry. + * 'flgs': Page's little-endian & user-defined flags, permissions and attributes + * 'tid': Translation ID + * + * RETURNS: 0 on success, nonzero on error: + * + * >0: requested mapping would overlap with + * existing mapping in another entry. Return + * value gives conflicting entry + 1; i.e., + * if a value of 4 is returned then the request + * conflicts with existing mapping in entry 3. + * -1: invalid argument + * -3: driver not initialized (or initialization failed). + * <0: other error + */ +bsp_tlb_idx_t +bsp_mmu_write(bsp_tlb_idx_t idx, uint32_t ea, uint32_t pa, uint sz, + uint32_t flgs, uint32_t tid); + +/* Check if a ea/tid/sz mapping overlaps with an existing entry. + * + * 'ea': The Effective Address to match against + * 'sz': The 'logarithmic' size selector; the page size + * is 1024*2^(2*sz). + * 'tid': The TID to match against + * + * RETURNS: + * >= 0: index of TLB entry that already provides a mapping + * which overlaps within the ea range. + * -1: SUCCESS (no conflicting entry found) + * <=-2: ERROR (invalid input) + */ +bsp_tlb_idx_t +bsp_mmu_match(uint32_t ea, int sz, uint32_t tid); + +/* Find TLB index that maps 'ea/tid' combination + * + * 'ea': Effective address to match against + * 'tid': The TID to match against + * + * RETURNS: index 'key'; i.e., the index number. + * + * On error (no mapping) -1 is returned. + */ +bsp_tlb_idx_t +bsp_mmu_find(uint32_t ea, uint32_t tid); + +/* Mark TLB entry as invalid ('disabled'). + * + * 'key': TLB entry index. + * + * RETURNS: zero on success, nonzero on error (TLB unchanged). + * + * NOTE: If a TLB entry is disabled the associated + * entry in bsp_mmu_cache[] is also marked as disabled. + */ +int +bsp_mmu_invalidate(bsp_tlb_idx_t key); + +/** @} */ + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c b/c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c index 74aaebb275..ba22c0275a 100644 --- a/c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c +++ b/c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c @@ -26,8 +26,6 @@ #include <rtems/powerpc/powerpc.h> #include <bsp/vectors.h> -uint32_t* IRQ_Counter = (uint32_t*)0x1500; - static rtems_irq_connect_data rtemsIrqTbl[BSP_IRQ_NUMBER]; rtems_irq_connect_data *BSP_rtems_irq_tbl; rtems_irq_global_settings* BSP_rtems_irq_config; @@ -37,21 +35,21 @@ rtems_irq_global_settings* BSP_rtems_irq_config; * these functions just do nothing fulfill the semantic * requirements to enable/disable a certain interrupt or exception */ -void BSP_irq_nop_func(const rtems_irq_connect_data *unused) +static void BSP_irq_nop_func(const rtems_irq_connect_data *unused) { /* * nothing to do */ } -void BSP_irq_nop_hdl(void *hdl) +static void BSP_irq_nop_hdl(void *hdl) { /* * nothing to do */ } -int BSP_irq_isOn_func(const rtems_irq_connect_data *unused) +static int BSP_irq_isOn_func(const rtems_irq_connect_data *unused) { /* * nothing to do @@ -66,7 +64,7 @@ int BSP_irq_isOn_func(const rtems_irq_connect_data *unused) /*********************************************************** * functions to enable/disable/query external/critical interrupts */ -void BSP_irqexc_on_fnc(rtems_irq_connect_data *conn_data) +void BSP_irqexc_on_fnc(const rtems_irq_connect_data *conn_data) { uint32_t msr_value; /* @@ -78,7 +76,7 @@ void BSP_irqexc_on_fnc(rtems_irq_connect_data *conn_data) _CPU_MSR_SET(msr_value); } -void BSP_irqexc_off_fnc(rtems_irq_connect_data *unused) +void BSP_irqexc_off_fnc(const rtems_irq_connect_data *unused) { uint32_t msr_value; /* @@ -277,7 +275,7 @@ int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config) * dummy for an empty IRQ handler entry */ static rtems_irq_connect_data emptyIrq = { - 0, /* Irq Name */ + 0, /* IRQ Name */ BSP_irq_nop_hdl, /* handler function */ NULL, /* handle passed to handler */ BSP_irq_nop_func, /* on function */ @@ -286,8 +284,8 @@ static rtems_irq_connect_data emptyIrq = { }; static rtems_irq_global_settings initialConfig = { - BSP_IRQ_NUMBER, /* irqNb */ - { 0, /* Irq Name */ + BSP_IRQ_NUMBER, /* IRQ Number */ + { 0, /* IRQ Name */ BSP_irq_nop_hdl, /* handler function */ NULL, /* handle passed to handler */ BSP_irq_nop_func, /* on function */ diff --git a/c/src/lib/libbsp/powerpc/virtex4/mmu/mmu.c b/c/src/lib/libbsp/powerpc/virtex4/mmu/mmu.c new file mode 100644 index 0000000000..92b4dbde38 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/mmu/mmu.c @@ -0,0 +1,567 @@ +/** + * @file + * + * @ingroup Virtex4MMU + * + * @brief Implementation of routines to manipulate the PPC 405 mmu. + * + * Since this is a real-time OS we want to stay away from + * software TLB replacement. + */ +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2005-2007, + * Stanford Linear Accelerator Center, Stanford University. + * and was transcribed for the PPC 405 by + * R. Claus <claus@slac.stanford.edu>, 2012, + * 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 + */ + +/* 405 MSR definitions; note that there are *substantial* differences + * compared to classic powerpc; in particular, IS/DS are *different* + * from IR/DR. + * + * Also: To disable/enable all external interrupts, CE and EE must both be + * controlled. + */ +#include <rtems.h> +#include <rtems/bspIo.h> +#include <rtems/powerpc/powerpc.h> +#include <inttypes.h> +#include <stdio.h> + +#include <bsp/mmu.h> + + +#ifdef DEBUG +#define STATIC +#else +#define STATIC static +#endif + + +bsp_tlb_entry_t* bsp_mmu_cache = 0; + + +/* Since it is likely that these routines are used during + * early initialization when stdio is not available yet + * we provide a helper that resorts to 'printk()' + */ +static void +myprintf(FILE *f, char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + if (!f || !_impure_ptr->__sdidinit) { + /* Might be called at an early stage when stdio is not yet initialized. */ + vprintk(fmt,ap); + } else { + vfprintf(f,fmt,ap); + } + va_end(ap); +} + + +void +bsp_mmu_dump_cache(FILE *f) +{ + bsp_tlb_idx_t idx; + if ( !bsp_mmu_cache ) { + myprintf(stderr,"MMU TLB cache not initialized\n"); + return; + } + for ( idx=0; idx<NTLBS; idx++ ) { + bsp_tlb_entry_t *tlb = bsp_mmu_cache + idx; + if ( !tlb->hi.v ) + continue; + myprintf(f, "#%2i: EA 0x%08x .. 0x%08x, TID 0x%03x, EU0 0x%01x\n", + idx, + tlb->hi.epn << 10, + (tlb->hi.epn << 10) + (1024<<(2*tlb->hi.size))-1, + tlb->id.tid, + tlb->hi.att); + myprintf(f, " PA 0x%08"PRIx32" .. 0x%08"PRIx32", PERM 0x%03x, WIMG 0x%02x\n", + tlb->lo.rpn << 10, + (tlb->lo.rpn << 10) + (1024<<(2*tlb->hi.size))-1, + tlb->lo.perm, + tlb->lo.wimg); + } +} + +static void +fetch(bsp_tlb_idx_t key, bsp_tlb_entry_t* tlb) +{ + register uint32_t tmp; + __asm__ volatile ("mfpid %[tmp] \n\t" + "stw %[tmp],0(%[tlb]) \n\t" + "tlbrehi %[tmp],%[key] \n\t" + "stw %[tmp],4(%[tlb]) \n\t" + "tlbrelo %[tmp],%[key] \n\t" + "stw %[tmp],8(%[tlb]) \n\t" + "sync \n\t" + : [tmp]"=&r"(tmp) + : [key]"r"(key), + [tlb]"b"(tlb) + ); +} + + +static void +store(bsp_tlb_idx_t key, bsp_tlb_entry_t* tlb) +{ + register uint32_t tmp; + __asm__ volatile ("lwz %[tmp],0(%[tlb]) \n\t" + "mtpid %[tmp] \n\t" + "lwz %[tmp],4(%[tlb]) \n\t" + "tlbwehi %[tmp],%[key] \n\t" + "lwz %[tmp],8(%[tlb]) \n\t" + "tlbwelo %[tmp],%[key] \n\t" + : [tmp]"=&r"(tmp) + : [tlb]"b"(tlb), + [key]"r"(key) + ); +} + + +static void +commit(void) +{ + __asm__ volatile("isync \n\t"); +} + + +/* + * Read a TLB entry from the hardware and store the current settings in the + * bsp_mmu_cache[] structure. + * + * The routine can perform this operation quietly or + * print information to a file. + * + * 'idx': which TLB entry to access. + * 'quiet': perform operation silently (no info printed) + * if nonzero. + * 'f': open FILE where to print information. May be + * NULL in which case 'stdout' is used. + * + * RETURNS: + * 0: success; TLB entry is VALID + * +1: success but TLB entry is INVALID + * < 0: error (-1: invalid argument) + * (-2: driver not initialized) + */ +int +bsp_mmu_update(bsp_tlb_idx_t key, bool quiet, FILE *f) +{ + rtems_interrupt_level lvl; + bsp_tlb_entry_t* tlb; + bsp_tlb_idx_t idx; + + idx = key; + + if ( idx < 0 || idx > NTLBS-1 ) + return -1; + + if (!bsp_mmu_cache) + return -2; + + tlb = bsp_mmu_cache + idx; + + rtems_interrupt_disable(lvl); + + fetch(idx, tlb); + + rtems_interrupt_enable(lvl); + + if ( tlb->hi.v ) { + if ( !quiet ) { +/* + "TLB Entry # 0 spans EA range 0x00000000 - 0x00000000 + "Mapping: VA [TID 0x00 / EPN 0x00000] -> RPN 0x00000" + "Size: TSIZE 0x0 (4^sz KB = 000000 KB = 0x00000000 B) + "Attributes: PERM 0x00 (ex/wr/zsel) WIMG 0x00 EU0 0x0" +*/ + myprintf(f, + "TLB Entry # %2d spans EA range 0x%08x - 0x%08x\n", + idx, + (tlb->hi.epn << 10), + (tlb->hi.epn << 10) + (1024<<(2*tlb->hi.size)) - 1 + ); + + myprintf(f, + "Mapping: VA [TID 0x%02x / EPN 0x%05x] -> RPN 0x%05"PRIx32"\n", + tlb->id.tid, tlb->hi.epn, tlb->lo.rpn + ); + myprintf(f, + "Size: TSIZE 0x%x (4^sz KB = %6d KB = 0x%08x B)\n", + tlb->hi.size, (1<<(2*tlb->hi.size)), (1024<<(2*tlb->hi.size)) + ); + myprintf(f, + "Attributes: PERM 0x%02x (ex/wr/zsel) WIMG 0x%02x EU0 0x%01x\n", + tlb->lo.perm, tlb->lo.wimg, tlb->hi.att + ); + } + } else { + if ( !quiet ) { + myprintf(f, + "TLB Entry # %2d <OFF> (size 0x%x = 0x%xb)\n", + idx, tlb->hi.size, (1024<<(2*tlb->hi.size)) + ); + } + return 1; + } + return 0; +} + +/* Initialize cache. Should be done only once although this is not enforced. + * + * RETURNS: zero on success, nonzero on error; in this case the driver will + * refuse to change TLB entries (other than disabling them). + */ +int +bsp_mmu_initialize() +{ + static bsp_tlb_entry_t mmu_cache[NTLBS]; + bsp_tlb_entry_t* tlb = mmu_cache; /* Should malloc if it's not too early */ + rtems_interrupt_level lvl; + + bsp_tlb_idx_t idx; + rtems_interrupt_disable(lvl); + for (idx=0; idx<NTLBS; tlb++, idx++) + { + fetch(idx, tlb); + } + rtems_interrupt_enable(lvl); + + bsp_mmu_cache = mmu_cache; + return 0; +} + +/* Find first free TLB entry by examining all entries' valid bit. The first + * entry without the valid bit set is returned. + * + * RETURNS: A free TLB entry number. -1 if no entry can be found. + */ +bsp_tlb_idx_t +bsp_mmu_find_first_free() +{ + bsp_tlb_idx_t idx; + bsp_tlb_entry_t entry; + + for (idx=0; idx<NTLBS; idx++) { + register uint32_t tmp; + __asm__ volatile ("tlbrehi %[tmp],%[idx] \n\t" + "stw %[tmp],4(%[tlb]) \n\t" /* entry.hi */ + "sync \n\t" + : [tmp]"=&r"(tmp) + : [idx]"r"(idx), + [tlb]"b"(&entry) + : "memory" + ); + if (!(entry.hi.v)) + break; + } + return (idx < NTLBS) ? idx : -1; +} + +/* + * Write TLB entry (can also be used to disable an entry). + * + * The routine checks against the cached data in + * bsp_mmu_cache[] to prevent the user from generating + * overlapping entries. + * + * 'idx': TLB entry # to manipulate + * 'ea': Effective address (must be page aligned) + * 'pa': Physical address (must be page aligned) + * 'sz': Page size selector; page size is + * 1024 * 2^(2*sz) bytes. + * 'sz' may also be one of the following: + * - page size in bytes ( >= 1024 ); the selector + * value is then computed by this routine. + * However, 'sz' must be a valid page size + * or -1 will be returned. + * - a value < 0 to invalidate/disable the + * TLB entry. + * 'flgs': Page's little-endian & user-defined flags, permissions and attributes + * 'tid': Translation ID + * + * RETURNS: 0 on success, nonzero on error: + * + * >0: requested mapping would overlap with + * existing mapping in other entry. Return + * value gives conflicting entry + 1; i.e., + * if a value of 4 is returned then the request + * conflicts with existing mapping in entry 3. + * -1: invalid argument + * -3: driver not initialized (or initialization failed). + * <0: other error + */ +bsp_tlb_idx_t +bsp_mmu_write(bsp_tlb_idx_t idx, uint32_t ea, uint32_t pa, uint sz, + uint32_t flgs, uint32_t tid) +{ + bsp_tlb_entry_t tlb; + uint32_t msk; + bsp_tlb_idx_t lkup; + rtems_interrupt_level lvl; + + if ( sz >= 1024 ) { + /* Assume they literally specify a size */ + msk = sz; + sz = 0; + while ( msk != (1024u<<(2*sz)) ) { + if ( ++sz > 7 ) { + return -1; + } + } + /* OK, acceptable */ + } + + msk = sz > 0 ? (1024u<<(2*sz)) - 1 : 0; + + if ( !bsp_mmu_cache && sz > 0 ) { + myprintf(stderr,"MMU driver not initialized; refusing to enable any entry\n"); + return -3; + } + + if ( (ea & msk) || (pa & msk) ) { + myprintf(stderr,"Misaligned EA (%08x) or PA (%08x) (mask is %08x)\n", ea, pa, msk); + return -1; + } + + if ( idx < 0 || idx > NTLBS-1 ) + return -1; + + if ( sz > 7 ) { + myprintf(stderr,"Invalid size %u = %08x = %u KB\n", sz, 1024u<<(2*sz), (1024u<<(2*sz))/1024); + return -1; + } + + if ( sz >=0 ) { + lkup = bsp_mmu_match(ea, sz, tid); + + if ( lkup < -1 ) { + /* some error */ + return lkup; + } + if ( (lkup >= 0) && (lkup != idx) && (bsp_mmu_cache[lkup].hi.v != 0) ) { + myprintf(stderr,"TLB #%i overlaps with requested mapping\n", lkup); + bsp_mmu_update( lkup, false, stderr); + return lkup+1; + } + } + + /* OK to proceed */ + tlb.id.tid = tid; + tlb.hi.v = sz >= 0; + tlb.hi.size = sz; + tlb.hi.epn = (ea & (0xfffffc00 << (sz + sz))) >> 10; + tlb.lo.rpn = (pa & (0xfffffc00 << (sz + sz))) >> 10; + tlb.hi.att = (flgs & MMU_M_ATTR) >> MMU_V_ATTR; + tlb.lo.perm = (flgs & MMU_M_PERM) >> MMU_V_PERM; + tlb.lo.wimg = (flgs & MMU_M_PROP) >> MMU_V_PROP; + + rtems_interrupt_disable(lvl); + + store(idx, &tlb); + + commit(); + + rtems_interrupt_enable(lvl); + + /* update cache */ + bsp_mmu_update(idx, true, 0); + + return 0; +} + +/* + * Check if a ea/sz/tid mapping overlaps with an existing entry. + * + * 'ea': The Effective Address to match against + * 'sz': The 'logarithmic' size selector; the page size + * is 1024*2^(2*sz). + * 'tid': The TID to match against + * + * RETURNS: + * >= 0: index of the TLB entry that already provides a mapping + * which overlaps within the ea range. + * -1: SUCCESS (no conflicting entry found) + * <=-2: ERROR (invalid input) + */ +bsp_tlb_idx_t +bsp_mmu_match(uint32_t ea, int sz, uint32_t tid) +{ + bsp_tlb_idx_t idx; + uint32_t m,a; + bsp_tlb_entry_t* tlb; + + if ( sz < 0 || sz > 7 ) + return -4; + + sz = (1024<<(2*sz)); + + if ( !bsp_mmu_cache ) { + /* cache not initialized */ + return -3; + } + + if ( ea & (sz-1) ) { + /* misaligned ea */ + return -2; + } + + for ( idx=0, tlb=bsp_mmu_cache; idx<NTLBS; idx++, tlb++ ) { + if ( ! tlb->hi.v ) + continue; + if ( tlb->id.tid && tlb->id.tid != tid ) + continue; + /* TID matches a valid entry */ + m = (1024<<(2*tlb->hi.size)) - 1; + /* calculate starting address of this entry */ + a = tlb->hi.epn << 10; + if ( ea <= a + m && ea + sz -1 >= a ) { + /* overlap */ + return idx; + } + } + return -1; +} + +/* Find TLB index that maps 'ea/tid' combination + * + * 'ea': Effective address to match against + * 'tid': The TID to match against + * + * RETURNS: index 'key' which indicates whether + * the mapping was found. + * + * On error (no mapping) -1 is returned. + */ +bsp_tlb_idx_t +bsp_mmu_find(uint32_t ea, uint32_t tid) +{ + rtems_interrupt_level lvl; + register uint32_t pid; + register bsp_tlb_idx_t idx; + register int failure; + + rtems_interrupt_disable(lvl); + + __asm__ volatile ("mfpid %[pid] \n\t" /* Save PID */ + "mtpid %[tid] \n\t" + "tlbsx. %[idx],0,%[ea] \n\t" /* Failure changes the index reg randomly. */ + "mfcr %[failure] \n\t" + "mtpid %[pid] \n\t" /* Restore PID */ + : [pid]"=r"(pid), + [idx]"=&r"(idx), + [failure]"=&r"(failure) + : [tid]"r"(tid), + [ea]"r"(ea) + : "cc" + ); + + rtems_interrupt_enable(lvl); + + return (failure & 0x20000000) ? idx : -1; +} + +/* Mark TLB entry as invalid ('disabled'). + * + * 'key': TLB entry (index). + * + * RETURNS: zero on success, nonzero on error (TLB unchanged). + * + * NOTE: If a TLB entry is disabled the associated + * entry in bsp_mmu_cache[] is also + * marked as disabled. + */ +int +bsp_mmu_invalidate(bsp_tlb_idx_t key) +{ + bsp_tlb_idx_t k0; + rtems_interrupt_level lvl; + bsp_tlb_entry_t tlb; + uint32_t msr; + + /* Minimal guard against bad key */ + if ( key < 0 || key > NTLBS-1 ) + return -1; + + _CPU_MSR_GET(msr); + + /* While address translation is enabled... */ + if (msr & (PPC_MSR_IR | PPC_MSR_DR)) + { + /* Must not invalidate page 0 which holds vectors, text etc... */ + k0 = bsp_mmu_find(0, 0); + if ( -1 == k0 ) { + myprintf(stderr,"No mapping for address 0 found\n"); + return -2; + } + + /* NOTE: we assume PID is ignored */ + if ( k0 == key ) { + myprintf(stderr,"Cannot invalidate page holding address 0 (always needed)\n"); + return -3; + } + } + + rtems_interrupt_disable(lvl); + + fetch(key, &tlb); + + /* Invalidate old entries */ + tlb.hi.v = 0; + + store(key, &tlb); + + commit(); + + /* update cache */ + bsp_mmu_cache[ key ].hi.v = tlb.hi.v; + + rtems_interrupt_enable(lvl); + + return 0; +} diff --git a/c/src/lib/libbsp/powerpc/virtex4/preinstall.am b/c/src/lib/libbsp/powerpc/virtex4/preinstall.am index 34b03f177c..e441f38b08 100644 --- a/c/src/lib/libbsp/powerpc/virtex4/preinstall.am +++ b/c/src/lib/libbsp/powerpc/virtex4/preinstall.am @@ -69,6 +69,10 @@ $(PROJECT_INCLUDE)/bsp/irq.h: include/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h +$(PROJECT_INCLUDE)/bsp/mmu.h: include/mmu.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/mmu.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/mmu.h + $(PROJECT_INCLUDE)/bsp/vectors.h: ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/vectors.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vectors.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/vectors.h diff --git a/c/src/lib/libbsp/powerpc/virtex4/startup/bspstart.c b/c/src/lib/libbsp/powerpc/virtex4/startup/bspstart.c index 2aab2c2505..73c2f847ed 100644 --- a/c/src/lib/libbsp/powerpc/virtex4/startup/bspstart.c +++ b/c/src/lib/libbsp/powerpc/virtex4/startup/bspstart.c @@ -54,20 +54,23 @@ * Modifications for PPC405GP by Dennis Ehlin * Modifications for Virtex4 by Richard Claus <claus@slac.stanford.edu> */ - -#include <string.h> -#include <fcntl.h> - -#include <bsp.h> -#include <bsp/irq.h> -#include <bsp/vectors.h> +#include <rtems.h> +#include <rtems/config.h> #include <rtems/bspIo.h> #include <rtems/libio.h> #include <rtems/libcsupport.h> -#include <rtems/sptables.h> /* for RTEMS_VERSION */ + #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> + #define DO_DOWN_ALIGN(x,a) ((x) & ~((a)-1)) #define DO_UP_ALIGN(x,a) DO_DOWN_ALIGN(((x) + (a) - 1 ),a) @@ -76,13 +79,6 @@ #define CPU_UP_ALIGN(x) DO_UP_ALIGN(x, CPU_ALIGNMENT) -/* Expected by clock.c */ -uint32_t bsp_clicks_per_usec; -bool bsp_timer_internal_clock; /* true, when timer runs with CPU clk */ -uint32_t bsp_timer_least_valid; -uint32_t bsp_timer_average_overhead; - - /* Defined in linkcmds linker script */ LINKER_SYMBOL(RamBase); LINKER_SYMBOL(RamSize); @@ -96,35 +92,24 @@ 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; +bool bsp_timer_internal_clock; /* true, when timer runs with CPU clk */ +uint32_t bsp_timer_least_valid; +uint32_t bsp_timer_average_overhead; /* * Provide weak aliases so that RTEMS distribution builds */ static void _noopfun(void) {} -static void _bsp_start(void) -{ - uintptr_t intrStackStart = CPU_UP_ALIGN((uint32_t)__bsp_ram_start); - uintptr_t intrStackSize = rtems_configuration_get_interrupt_stack_size(); - - /* - * Initialize default raw exception handlers. - * - * This BSP does not assume anything about firmware possibly loaded in the - * FPGA, so the external interrupt should not be enabled in order to avoid - * spurious interrupts. - */ - ppc_exc_initialize(PPC_INTERRUPT_DISABLE_MASK_DEFAULT & ~MSR_EE, - intrStackStart, - intrStackSize); - - /* Install our own set of exception vectors */ - BSP_rtems_irq_mngt_init(0); -} void app_bsp_start(void) -__attribute__(( weak, alias("_bsp_start") )); +__attribute__(( weak, alias("_noopfun") )); void app_bsp_pretasking_hook(void) __attribute__(( weak, alias("_noopfun") )); @@ -147,20 +132,31 @@ static void __bsp_outchar_to_memory(char c) void BSP_ask_for_reset(void) { printk("\nSystem stopped, issue RESET"); + for(;;); } void BSP_panic(char *s) { - printk("\n%s PANIC %s\n", _RTEMS_version, s); + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + + printk("\n%s PANIC %s\n", rtems_get_version_string(), s); + BSP_ask_for_reset(); } void _BSP_Fatal_error(unsigned int v) { - printk("\n%s FATAL ERROR %x\n", _RTEMS_version, v); + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + + printk("\n%s FATAL ERROR %x\n", rtems_get_version_string(), v); + BSP_ask_for_reset(); } @@ -176,13 +172,14 @@ 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("\nWelcome to RTEMS %s\n", _RTEMS_version ); + printk("RTEMS %s\n", rtems_get_version_string()); /* * Get CPU identification dynamically. Note that the get_ppc_cpu_type() @@ -208,6 +205,12 @@ void bsp_start(void) */ intrStackStart = CPU_UP_ALIGN((uint32_t)__bsp_ram_start); intrStackSize = rtems_configuration_get_interrupt_stack_size(); + + ppc_exc_initialize(PPC_INTERRUPT_DISABLE_MASK_DEFAULT, + intrStackStart, + intrStackSize); + + /* Let the user know what parameters we were compiled with */ printk(" Base/Start End Size\n" "RAM: 0x%08x 0x%x\n" "RTEMS: 0x%08x\n" @@ -224,6 +227,11 @@ void bsp_start(void) (uint32_t)MsgAreaBase, (uint32_t)MsgAreaSize, (uint32_t)__phy_ram_end); + /* + * Initialize RTEMS IRQ system + */ + BSP_rtems_irq_mngt_init(0); + /* Continue with application-specific initialization */ app_bsp_start(); } diff --git a/c/src/lib/libbsp/powerpc/virtex4/startup/linkcmds b/c/src/lib/libbsp/powerpc/virtex4/startup/linkcmds index cff5767aef..74a10aa079 100644 --- a/c/src/lib/libbsp/powerpc/virtex4/startup/linkcmds +++ b/c/src/lib/libbsp/powerpc/virtex4/startup/linkcmds @@ -20,16 +20,17 @@ HeapSize = DEFINED(HeapSize) ? HeapSize : 0; /* 0=Use def */ MEMORY { - VECTORS : ORIGIN = 0x00000000, LENGTH = 8K - RAM : ORIGIN = 0x00002000, LENGTH = 128M - 8K + VECTORS : ORIGIN = 0x00000000, LENGTH = 12K + RAM : ORIGIN = 0x00003000, LENGTH = 128M - 12K } SECTIONS { - __exeentry = download_entry; - __exestart = 0x100; - .vectors __exestart : { *(.vectors) } > VECTORS + 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 @@ -249,7 +250,7 @@ _SDA_BASE_ = __SDATA_START__ + 0x8000; /* Message area for capturing early printk output */ /* Placed here to be easily findable with a debugger */ - MsgAreaBase = __bsp_ram_end; + MsgAreaBase = .; . += MsgAreaSize; __phy_ram_end = .; /* True end of physical memory */ diff --git a/c/src/lib/libbsp/powerpc/virtex4/startup/start.S b/c/src/lib/libbsp/powerpc/virtex4/startup/start.S index c3053fb0b5..55d53183a4 100644 --- a/c/src/lib/libbsp/powerpc/virtex4/startup/start.S +++ b/c/src/lib/libbsp/powerpc/virtex4/startup/start.S @@ -166,15 +166,15 @@ startupDow: * Tell the processor where the exception vector table will be. *------------------------------------------------------------------*/ .extern SYM(__vectors) - lis r0, __vectors@h /* set EVPR exc. vector prefix */ - mtspr evpr,r0 + lis r2, __vectors@h /* set EVPR exc. vector prefix */ + mtevpr r2 /*------------------------------------------------------------------- * Set up the debug register to freeze timers on debug events. *------------------------------------------------------------------*/ - mfdbcr0 r0 - ori r0,r0,0x0001 - mtdbcr0 r0 + mfdbcr0 r2 + ori r2,r2,0x0001 + mtdbcr0 r2 isync /* Select whether APU, Wait Enable, interrupts/exceptions and address @@ -182,14 +182,20 @@ startupDow: lis r0,0x00000000@h /* SRR1 value */ mtsrr1 r0 /* Potentially: 0x80000000 >> 6 is APU */ + /* Configure timer facilities */ + mttbl r0 /* Clear Timebase to prevent Fixed Interval.. */ + mttbu r0 /* ..timer and Watchdog Timer exceptions */ + mtpit r0 /* Programmable interval timer */ + li r2,-1 /* -1 to clear TSR */ + mttsr r2 /* Timer status register */ + /* Clear out stale values in certain registers to avoid confusion */ + mtcrf 0xff,r0 /* Need for simulation */ + mtctr r0 /* Counter register */ mtxer r0 /* Fixed-point exception register */ mtesr r0 /* Exception syndrome register */ mtdear r0 /* Data exception address register */ mtmcsr r0 /* Machine check syndrome register */ - mtpit r0 /* Programmable interval timer */ - li r0,-1 /* -1 to clear TSR */ - mttsr r0 /* Timer status register */ /* Invalidate the data cache */ li r2,0 /* Start address */ |