diff options
22 files changed, 2544 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/arm/acinclude.m4 b/c/src/lib/libbsp/arm/acinclude.m4 index b800a60833..b4a597d340 100644 --- a/c/src/lib/libbsp/arm/acinclude.m4 +++ b/c/src/lib/libbsp/arm/acinclude.m4 @@ -2,6 +2,8 @@ AC_DEFUN([RTEMS_CHECK_BSPDIR], [ case "$1" in + altera-cyclone-v ) + AC_CONFIG_SUBDIRS([altera-cyclone-v]);; csb336 ) AC_CONFIG_SUBDIRS([csb336]);; csb337 ) diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am b/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am new file mode 100644 index 0000000000..64703a2996 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am @@ -0,0 +1,197 @@ +## +# +# @file +# +# @brief Makefile of LibBSP for the Altera Cyclone-V platform. +# + +ACLOCAL_AMFLAGS = -I ../../../../aclocal + +include $(top_srcdir)/../../../../automake/compile.am + +include_bspdir = $(includedir)/bsp +include_libcpudir = $(includedir)/libcpu + +dist_project_lib_DATA = bsp_specs + +############################################################################### +# Header # +############################################################################### + +include_HEADERS = include/bsp.h +include_HEADERS += include/tm27.h + +nodist_include_HEADERS = ../../shared/include/coverhd.h \ + include/bspopts.h + +nodist_include_bsp_HEADERS = ../../shared/include/bootcard.h + +include_bsp_HEADERS = +include_bsp_HEADERS += ../../shared/include/utility.h +include_bsp_HEADERS += ../../shared/include/irq-generic.h +include_bsp_HEADERS += ../../shared/include/irq-info.h +include_bsp_HEADERS += ../../shared/include/stackalloc.h +include_bsp_HEADERS += ../../shared/tod.h +include_bsp_HEADERS += ../shared/include/start.h +include_bsp_HEADERS += ../shared/include/arm-a9mpcore-clock.h +include_bsp_HEADERS += ../shared/include/arm-a9mpcore-irq.h +include_bsp_HEADERS += ../shared/include/arm-a9mpcore-regs.h +include_bsp_HEADERS += ../shared/include/arm-a9mpcore-start.h +include_bsp_HEADERS += ../shared/include/arm-cp15-start.h +include_bsp_HEADERS += ../shared/include/arm-errata.h +include_bsp_HEADERS += ../shared/include/arm-gic.h +include_bsp_HEADERS += ../shared/include/arm-gic-irq.h +include_bsp_HEADERS += ../shared/include/arm-gic-regs.h +include_bsp_HEADERS += ../shared/include/arm-gic-tm27.h +include_bsp_HEADERS += ../shared/include/arm-release-id.h +include_bsp_HEADERS += include/irq.h +include_bsp_HEADERS += include/nocache-heap.h + +# Altera hwlib +include_bsp_HEADERS += hwlib/include/alt_address_space.h +include_bsp_HEADERS += hwlib/include/alt_clock_group.h +include_bsp_HEADERS += hwlib/include/alt_clock_manager.h +include_bsp_HEADERS += hwlib/include/alt_generalpurpose_io.h +include_bsp_HEADERS += hwlib/include/alt_hwlibs_ver.h +include_bsp_HEADERS += hwlib/include/alt_interrupt_common.h +include_bsp_HEADERS += hwlib/include/alt_mpu_registers.h +include_bsp_HEADERS += hwlib/include/alt_reset_manager.h +include_bsp_HEADERS += hwlib/include/hwlib.h +#The following Altera hwlib header files have been left out because so far +#they are not required: +#include_bsp_HEADERS += hwlib/include/alt_16550_uart.h +#include_bsp_HEADERS += hwlib/include/alt_bridge_manager.h +#include_bsp_HEADERS += hwlib/include/alt_dma_common.h +#include_bsp_HEADERS += hwlib/include/alt_dma_program.h +#include_bsp_HEADERS += hwlib/include/alt_dma.h +#include_bsp_HEADERS += hwlib/include/alt_fpga_manager.h +#include_bsp_HEADERS += hwlib/include/alt_globaltmr.h +#include_bsp_HEADERS += hwlib/include/alt_system_manager.h +#include_bsp_HEADERS += hwlib/include/alt_timers.h +#include_bsp_HEADERS += hwlib/include/alt_watchdog.h +#The following Altera hwlib headers would be problematic with RTEMS: +#include_bsp_HEADERS += hwlib/include/alt_interrupt.h +#All header files from hwlib/include/socal are regarded as BSP +#internal and thus not installed + +include_libcpu_HEADERS = ../../../libcpu/arm/shared/include/arm-cp15.h + + + +############################################################################### +# Data # +############################################################################### + +noinst_LIBRARIES = libbspstart.a + +libbspstart_a_SOURCES = ../shared/start/start.S + +project_lib_DATA = start.$(OBJEXT) + +project_lib_DATA += startup/linkcmds +project_lib_DATA += startup/linkcmds.altcycv +project_lib_DATA += startup/linkcmds.altcycv_devkit +project_lib_DATA += startup/linkcmds.altcycv_devkit_smp + +############################################################################### +# LibBSP # +############################################################################### + +noinst_LIBRARIES += libbsp.a + +libbsp_a_SOURCES = +libbsp_a_CPPFLAGS = +libbsp_a_LIBADD = + +# for the Altera hwlib +libbsp_a_CPPFLAGS += -I ${srcdir}/hwlib/include +libbsp_a_CPPFLAGS += -std=gnu99 + +# hwlib from Altera +libbsp_a_SOURCES += hwlib/src/hwmgr/alt_address_space.c +libbsp_a_SOURCES += hwlib/src/hwmgr/alt_clock_manager.c +libbsp_a_SOURCES += hwlib/src/hwmgr/alt_generalpurpose_io.c +libbsp_a_SOURCES += hwlib/src/hwmgr/alt_reset_manager.c +#The following Altera hwlib source files have been left out because so far +#they are not required: +#libbsp_a_SOURCES += hwlib/src/hwmgr/alt_16550_uart.c +#libbsp_a_SOURCES += hwlib/src/hwmgr/alt_bridge_manager.c +#libbsp_a_SOURCES += hwlib/src/hwmgr/alt_dma_program.c +#libbsp_a_SOURCES += hwlib/src/hwmgr/alt_dma.c +#libbsp_a_SOURCES += hwlib/src/hwmgr/alt_fpga_manager.c +#libbsp_a_SOURCES += hwlib/src/hwmgr/alt_globaltmr.c +#libbsp_a_SOURCES += hwlib/src/hwmgr/alt_system_manager.c +#libbsp_a_SOURCES += hwlib/src/hwmgr/alt_timers.c +#libbsp_a_SOURCES += hwlib/src/hwmgr/alt_watchdog.c +# The following Altera hwlib source files would be problematic with RTEMS: +#libbsp_a_SOURCES += hwlib/src/hwmgr/alt_interrupt.c + + +# Shared +libbsp_a_SOURCES += ../../shared/bootcard.c +libbsp_a_SOURCES += ../../shared/bspclean.c +libbsp_a_SOURCES += ../../shared/bspgetworkarea.c +libbsp_a_SOURCES += ../../shared/bsplibc.c +libbsp_a_SOURCES += ../../shared/bsppost.c +libbsp_a_SOURCES += ../../shared/bsppredriverhook.c +libbsp_a_SOURCES += ../../shared/bsppretaskinghook.c +libbsp_a_SOURCES += ../../shared/cpucounterdiff.c +libbsp_a_SOURCES += ../../shared/gnatinstallhandler.c +libbsp_a_SOURCES += ../../shared/sbrk.c +libbsp_a_SOURCES += ../../shared/timerstub.c +libbsp_a_SOURCES += ../../shared/src/stackalloc.c +libbsp_a_SOURCES += ../shared/abort/simple_abort.c +libbsp_a_SOURCES += ../shared/startup/bsp-start-memcpy.S +libbsp_a_SOURCES += ../shared/arm-cp15-set-exception-handler.c +libbsp_a_SOURCES += ../shared/arm-cp15-set-ttb-entries.c + +# Startup +libbsp_a_SOURCES += startup/bspreset.c +libbsp_a_SOURCES += startup/bspstart.c +libbsp_a_SOURCES += startup/nocache-heap.c + +# IRQ +libbsp_a_SOURCES += ../../shared/src/irq-default-handler.c +libbsp_a_SOURCES += ../../shared/src/irq-generic.c +libbsp_a_SOURCES += ../../shared/src/irq-info.c +libbsp_a_SOURCES += ../../shared/src/irq-legacy.c +libbsp_a_SOURCES += ../../shared/src/irq-server.c +libbsp_a_SOURCES += ../../shared/src/irq-shell.c +libbsp_a_SOURCES += ../shared/arm-gic-irq.c + +# Network +libbsp_a_SOURCES += network/network.c + +# Console +libbsp_a_SOURCES += ../../shared/console.c +libbsp_a_SOURCES += ../../shared/console_control.c +libbsp_a_SOURCES += ../../shared/console_read.c +libbsp_a_SOURCES += ../../shared/console_select_simple.c +libbsp_a_SOURCES += ../../shared/console_write.c +libbsp_a_SOURCES += console/console-config.c + +# Clock +libbsp_a_SOURCES += ../../shared/clockdrv_shell.h +libbsp_a_SOURCES += ../shared/arm-a9mpcore-clock-config.c + +# Cache +libbsp_a_SOURCES += ../../../libcpu/shared/src/cache_manager.c +libbsp_a_SOURCES += ../shared/include/arm-cache-l1.h +libbsp_a_SOURCES += ../shared/arm-l2c-310/cache_.h +libbsp_a_CPPFLAGS += -I$(srcdir)/../shared/arm-l2c-310 + +# Start hooks +libbsp_a_SOURCES += startup/bspstarthooks.c + +if HAS_SMP +libbsp_a_SOURCES += ../shared/arm-a9mpcore-smp.c +endif + +############################################################################### +# Special Rules # +############################################################################### + +DISTCLEANFILES = include/bspopts.h + +include $(srcdir)/preinstall.am +include $(top_srcdir)/../../../../automake/local.am diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/README b/c/src/lib/libbsp/arm/altera-cyclone-v/README new file mode 100644 index 0000000000..575b72e4f5 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/README @@ -0,0 +1,3 @@ +Evaluation board for this BSP: +- Cyclone V SoC FPGA Development Kit +- DK-DEV-5CSXC6N/ES-0L
\ No newline at end of file diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/bsp_specs b/c/src/lib/libbsp/arm/altera-cyclone-v/bsp_specs new file mode 100644 index 0000000000..082653ad22 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/bsp_specs @@ -0,0 +1,13 @@ +%rename endfile old_endfile +%rename startfile old_startfile +%rename link old_link + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: start.o%s crti.o%s crtbegin.o%s -e _start}} + +*link: +%{!qrtems: %(old_link)} %{qrtems: -dc -dp -N} + +*endfile: +%{!qrtems: *(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s } diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/configure.ac b/c/src/lib/libbsp/arm/altera-cyclone-v/configure.ac new file mode 100644 index 0000000000..561a1929e5 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/configure.ac @@ -0,0 +1,56 @@ +## +# +# @file +# +# @brief Configure script of LibBSP for the Altera Cyclone-V platform. +# + +AC_PREREQ([2.69]) +AC_INIT([rtems-c-src-lib-libbsp-arm-xilinx-zynq-a9],[_RTEMS_VERSION],[http://www.rtems.org/bugzilla]) +AC_CONFIG_SRCDIR([bsp_specs]) +RTEMS_TOP(../../../../../..) + +RTEMS_CANONICAL_TARGET_CPU +AM_INIT_AUTOMAKE([no-define nostdinc foreign 1.12.2]) +RTEMS_BSP_CONFIGURE + +RTEMS_PROG_CC_FOR_TARGET +RTEMS_CANONICALIZE_TOOLS +RTEMS_PROG_CCAS + +RTEMS_CHECK_NETWORKING +AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes") + +RTEMS_BSPOPTS_SET([BSP_START_RESET_VECTOR],[*],[]) +RTEMS_BSPOPTS_HELP([BSP_START_RESET_VECTOR],[reset vector address for BSP start]) + +RTEMS_BSPOPTS_SET([BSP_ARM_A9MPCORE_PERIPHCLK],[altcycv_devkit*],[200000000U]) +RTEMS_BSPOPTS_SET([BSP_ARM_A9MPCORE_PERIPHCLK],[*],[100000000U]) +RTEMS_BSPOPTS_HELP([BSP_ARM_A9MPCORE_PERIPHCLK],[ARM Cortex-A9 MPCore PERIPHCLK clock frequency in Hz]) + +RTEMS_BSPOPTS_SET([CLOCK_DRIVER_USE_FAST_IDLE],[*qemu],[1]) +RTEMS_BSPOPTS_HELP([CLOCK_DRIVER_USE_FAST_IDLE], +[This sets a mode where the time runs as fast as possible when a clock ISR +occurs while the IDLE thread is executing. This can significantly reduce +simulation times.]) + +RTEMS_BSPOPTS_SET([BSP_CONSOLE_MINOR],[*],[0]) +RTEMS_BSPOPTS_HELP([BSP_CONSOLE_MINOR],[minor number of console device]) + +RTEMS_BSPOPTS_SET([CYCLONE_V_CONFIG_CONSOLE],[*],[0]) +RTEMS_BSPOPTS_HELP([CYCLONE_V_CONFIG_CONSOLE],[configuration for console (UART 0)]) + +RTEMS_BSPOPTS_SET([CYCLONE_V_CONFIG_UART_1],[*],[0]) +RTEMS_BSPOPTS_HELP([CYCLONE_V_CONFIG_UART_1],[configuration for UART 1]) + +RTEMS_BSPOPTS_SET([CYCLONE_V_UART_BAUD],[*],[115200U]) +RTEMS_BSPOPTS_HELP([CYCLONE_V_UART_BAUD],[baud for UARTs]) + +RTEMS_CHECK_SMP +AM_CONDITIONAL(HAS_SMP,[test "$rtems_cv_HAS_SMP" = "yes"]) + +RTEMS_BSP_CLEANUP_OPTIONS(0, 1) +RTEMS_BSP_LINKCMDS + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c b/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c new file mode 100644 index 0000000000..4241a5a1b7 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c @@ -0,0 +1,195 @@ +/* + * 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.com/license/LICENSE. + */ + +#include <assert.h> +#include <stdint.h> +#include <stdbool.h> +#include <libchip/serial.h> +#include <libchip/ns16550.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/alt_clock_manager.h> +#include "socal/alt_rstmgr.h" +#include "socal/socal.h" +#include "socal/alt_uart.h" +#include "socal/hps.h" + +bool altera_cyclone_v_uart_probe( int minor ); + +static uint8_t altera_cyclone_v_uart_get_register(uintptr_t addr, uint8_t i) +{ + volatile uint32_t *reg = (volatile uint32_t *) addr; + + return (uint8_t) reg [i]; +} + +static void altera_cyclone_v_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val) +{ + volatile uint32_t *reg = (volatile uint32_t *) addr; + + reg [i] = val; +} + +console_tbl Console_Configuration_Ports[] = { +#ifdef CYCLONE_V_CONFIG_CONSOLE + { + .sDeviceName = "/dev/ttyS0", + .deviceType = SERIAL_NS16550, + .pDeviceFns = &ns16550_fns, + .deviceProbe = altera_cyclone_v_uart_probe, + .pDeviceFlow = NULL, + .ulMargin = 16, + .ulHysteresis = 8, + .pDeviceParams = (void *)CYCLONE_V_UART_BAUD, + .ulCtrlPort1 = (uint32_t)ALT_UART0_ADDR, + .ulCtrlPort2 = 0, + .ulDataPort = (uint32_t)ALT_UART0_ADDR, + .getRegister = altera_cyclone_v_uart_get_register, + .setRegister = altera_cyclone_v_uart_set_register, + .getData = NULL, + .setData = NULL, + .ulClock = 0, + .ulIntVector = ALT_INT_INTERRUPT_UART0 + }, +#endif +#ifdef CYCLONE_V_CONFIG_UART_1 + { + .sDeviceName = "/dev/ttyS1", + .deviceType = SERIAL_NS16550, + .pDeviceFns = &ns16550_fns, + .deviceProbe = altera_cyclone_v_uart_probe, + .pDeviceFlow = NULL, + .ulMargin = 16, + .ulHysteresis = 8, + .pDeviceParams = (void *)CYCLONE_V_UART_BAUD, + .ulCtrlPort1 = (uint32_t)ALT_UART1_ADDR, + .ulCtrlPort2 = 0, + .ulDataPort = (uint32_t)ALT_UART1_ADDR, + .getRegister = altera_cyclone_v_uart_get_register, + .setRegister = altera_cyclone_v_uart_set_register, + .getData = NULL, + .setData = NULL, + .ulClock = 0, + .ulIntVector = ALT_INT_INTERRUPT_UART1 + } +#endif +}; + + +unsigned long Console_Configuration_Count = + RTEMS_ARRAY_SIZE(Console_Configuration_Ports); + +bool altera_cyclone_v_uart_probe(int minor) +{ + bool ret = true; + uint32_t uart_set_mask; + uint32_t ucr; + ALT_STATUS_CODE sc; + void* location; + + /* The ALT_CLK_L4_SP is required for all SoCFPGA UARTs. + * Check that it's enabled. */ + assert( alt_clk_is_enabled(ALT_CLK_L4_SP) == ALT_E_TRUE ); + if ( alt_clk_is_enabled(ALT_CLK_L4_SP) != ALT_E_TRUE ) { + ret = false; + } + + if ( ret ) { + switch(minor) + { + case(0): + /* UART 0 */ + uart_set_mask = ALT_RSTMGR_PERMODRST_UART0_SET_MSK; + location = ALT_UART0_ADDR; + break; + case(1): + /* UART 1 */ + uart_set_mask = ALT_RSTMGR_PERMODRST_UART1_SET_MSK; + location = ALT_UART1_ADDR; + break; + default: + /* Unknown case */ + assert( minor == 0 || minor == 1 ); + ret = false; + break; + } + } + if ( ret ) { + sc = alt_clk_freq_get(ALT_CLK_L4_SP, &Console_Configuration_Ports[minor].ulClock); + assert( sc == ALT_E_SUCCESS ); + if ( sc != ALT_E_SUCCESS ) { + ret = false; + } + } + + if ( ret ) { + // Bring UART out of reset. + alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, uart_set_mask); + + // Verify the UCR (UART Component Version) + ucr = alt_read_word( ALT_UART_UCV_ADDR( location ) ); + + assert( ucr == ALT_UART_UCV_UART_COMPONENT_VER_RESET ); + if ( ucr != ALT_UART_UCV_UART_COMPONENT_VER_RESET ) { + ret = false; + } + } + + if ( ret ) { + // Write SRR::UR (Shadow Reset Register :: UART Reset) + alt_write_word( ALT_UART_SRR_ADDR( location ), ALT_UART_SRR_UR_SET_MSK ); + + // Read the MSR to work around case:119085. + (void)alt_read_word( ALT_UART_MSR_ADDR( location ) ); + } + + return ret; +} + +static void output_char(char c) +{ + int minor = (int) Console_Port_Minor; + const console_tbl *ct = Console_Port_Tbl != NULL ? + Console_Port_Tbl[minor] : &Console_Configuration_Ports[minor]; + const console_fns *cf = ct->pDeviceFns; + + if (c == '\n') { + (*cf->deviceWritePolled)(minor, '\r'); + } + + (*cf->deviceWritePolled)(minor, c); +} + +static void output_char_init(char c) +{ + if (Console_Port_Tbl == NULL) { + int minor; + const console_fns *cf; + + bsp_console_select(); + + minor = (int) Console_Port_Minor; + cf = Console_Configuration_Ports[minor].pDeviceFns; + + (*cf->deviceInitialize)(minor); + } + + BSP_output_char = output_char; + output_char(c); +} + +BSP_output_char_function_type BSP_output_char = output_char_init; + +BSP_polling_getchar_function_type BSP_poll_char = NULL; diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/include/bsp.h b/c/src/lib/libbsp/arm/altera-cyclone-v/include/bsp.h new file mode 100644 index 0000000000..694fd14e43 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/include/bsp.h @@ -0,0 +1,65 @@ +/* + * 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.com/license/LICENSE. + */ + +#ifndef LIBBSP_ARM_ALTERY_CYCLONE_V_BSP_H +#define LIBBSP_ARM_ALTERY_CYCLONE_V_BSP_H + +#include <bspopts.h> + +#define BSP_FEATURE_IRQ_EXTENSION + +#ifndef ASM + +#include <rtems.h> +#include <rtems/console.h> +#include <rtems/clockdrv.h> + +#include <bsp/default-initial-extension.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define BSP_ARM_A9MPCORE_SCU_BASE 0xFFFEC000 + +#define BSP_ARM_GIC_CPUIF_BASE ( BSP_ARM_A9MPCORE_SCU_BASE + 0x00000100 ) + +#define BSP_ARM_A9MPCORE_GT_BASE ( BSP_ARM_A9MPCORE_SCU_BASE + 0x00000200 ) + +#define BSP_ARM_GIC_DIST_BASE ( BSP_ARM_A9MPCORE_SCU_BASE + 0x00001000 ) + +#define BSP_ARM_L2CC_BASE 0xFFFEF000U + +/* Forward declaration */ +struct rtems_bsdnet_ifconfig; + +/** @brief Network interface attach detach + * + * Attaches a network interface tp the network stack. + * NOTE: Detaching is not supported! + */ +int altera_cyclone_v_network_if_attach_detach( + struct rtems_bsdnet_ifconfig *config, + int attaching ); + +#define RTEMS_BSP_NETWORK_DRIVER_ATTACH altera_cyclone_v_network_if_attach_detach +#define RTEMS_BSP_NETWORK_DRIVER_NAME "eth0" + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* ASM */ + +#endif /* LIBBSP_ARM_ALTERY_CYCLONE_V_BSP_H */ diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/include/irq.h b/c/src/lib/libbsp/arm/altera-cyclone-v/include/irq.h new file mode 100644 index 0000000000..5a088ab097 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/include/irq.h @@ -0,0 +1,41 @@ +/* + * 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.com/license/LICENSE. + */ + +#ifndef LIBBSP_ARM_ALTERA_CYCLONE_V_IRQ_H +#define LIBBSP_ARM_ALTERA_CYCLONE_V_IRQ_H + +#ifndef ASM + +#include <rtems/irq.h> +#include <rtems/irq-extension.h> + +#include <bsp/arm-a9mpcore-irq.h> +#include <bsp/arm-gic-irq.h> +#include <bsp/alt_interrupt_common.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Use interrupt IDs as defined in alt_interrupt_common.h */ +#define BSP_INTERRUPT_VECTOR_MIN ALT_INT_INTERRUPT_SGI0 +#define BSP_INTERRUPT_VECTOR_MAX ALT_INT_INTERRUPT_RAM_ECC_UNCORRECTED_IRQ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* ASM */ + +#endif /* LIBBSP_ARM_ALTERA_CYCLONE_V_IRQ_H */
\ No newline at end of file diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/include/nocache-heap.h b/c/src/lib/libbsp/arm/altera-cyclone-v/include/nocache-heap.h new file mode 100644 index 0000000000..73f56f3e65 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/include/nocache-heap.h @@ -0,0 +1,55 @@ +/** + * @file + * + * @brief Heap handling for uncached RAM + */ + +/* + * Copyright (c) 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. + */ + +#ifndef NOCACHE_HEAP_H_ +#define NOCACHE_HEAP_H_ + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Initialize nocache heap. + * + * Initializes a heap for uncached RAM + */ +void altera_cyclone_v_nocache_init_heap( void ); + +/** @brief Nocache alloc. + * + * Allocate memory from uncached heap. + * @param size Number of bytes to be allocated. + * @returns Pointer to the allocated memory. + */ +void *altera_cyclone_v_nocache_malloc( const size_t size ); + +/** @brief Nocache free. + * + * Release memory from uncached heap. + * @param ptr Address of the memory to be released. + */ +void altera_cyclone_v_nocache_free( void *ptr ); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* NOCACHE_HEAP_H_ */ diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/include/tm27.h b/c/src/lib/libbsp/arm/altera-cyclone-v/include/tm27.h new file mode 100644 index 0000000000..96ab469033 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/include/tm27.h @@ -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.com/license/LICENSE. + */ + +#ifndef _RTEMS_TMTEST27 +#error "This is an RTEMS internal file you must not include directly." +#endif + +#ifndef __tm27_h +#define __tm27_h + +#include <bsp/arm-gic-tm27.h> + +#endif /* __tm27_h */ diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/make/custom/altcycv.inc b/c/src/lib/libbsp/arm/altera-cyclone-v/make/custom/altcycv.inc new file mode 100644 index 0000000000..bbe3f54ee3 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/make/custom/altcycv.inc @@ -0,0 +1,8 @@ +include $(RTEMS_ROOT)/make/custom/default.cfg + +RTEMS_CPU = arm + +CPU_CFLAGS = -march=armv7-a -mthumb -mfpu=neon -mfloat-abi=hard -mtune=cortex-a9 + +#CFLAGS_OPTIMIZE_V ?= -O0 -g +CFLAGS_OPTIMIZE_V ?= -O2 -g diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/make/custom/altcycv_devkit.cfg b/c/src/lib/libbsp/arm/altera-cyclone-v/make/custom/altcycv_devkit.cfg new file mode 100644 index 0000000000..ed54edfedd --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/make/custom/altcycv_devkit.cfg @@ -0,0 +1 @@ +include $(RTEMS_ROOT)/make/custom/altcycv.inc diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/make/custom/altcycv_devkit_smp.cfg b/c/src/lib/libbsp/arm/altera-cyclone-v/make/custom/altcycv_devkit_smp.cfg new file mode 100644 index 0000000000..ed54edfedd --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/make/custom/altcycv_devkit_smp.cfg @@ -0,0 +1 @@ +include $(RTEMS_ROOT)/make/custom/altcycv.inc diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/network/network.c b/c/src/lib/libbsp/arm/altera-cyclone-v/network/network.c new file mode 100644 index 0000000000..d2f669a658 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/network/network.c @@ -0,0 +1,1237 @@ +/** + * @file + * + * @brief Network Driver + * + * This driver is a wrapper for the DWMAC 1000 driver from libchip. + * The DWMAC 1000 driver is an on-chip Synopsys IP Ethernet controllers + */ + +/* + * Copyright (c) 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 <rtems.h> + +#if defined(RTEMS_NETWORKING) + +#include <assert.h> +#include <stdint.h> +#include <stdlib.h> +#include <errno.h> +#include <rtems.h> +#include <rtems/config.h> +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/linker-symbols.h> +#include <bsp/hwlib.h> +#include <bsp/alt_clock_manager.h> +#include <bsp/alt_generalpurpose_io.h> +#include <bsp/nocache-heap.h> +#include "socal/alt_rstmgr.h" +#include "socal/hps.h" +#include "socal/socal.h" +#include <libchip/dwmac.h> + +/** @brief Pin mask for the interrupt from the ethernet PHY */ +#define NETWORK_PIN_MASK_PHY_INTERRUPT 0x00000040U + +/** @brief Ethernet PHY status */ +typedef enum { + /** @brief The ethernet PHY is off */ + NETWORK_IF_PHY_STATUS_OFF, + + /** @brief The ethernet PHY is on an initialized, but stopped */ + NETWORK_IF_PHY_STATUS_STOPPED, + + /** @brief The ethernet PHY is started and will generate requested events */ + NETWORK_IF_PHY_STATUS_STARTED, + + /** @brief Number of ethernet PHY statuses */ + NETWORK_IF_PHY_STATUS_COUNT +} network_if_phy_status; + +/** @brief Phy context + * + * ethernet PHY device context + */ +typedef struct { + /** @brief PHY device status */ + network_if_phy_status status; + + /** @brief Interrupt mask which corresponds to currently requested events */ + uint16_t irq_mask; +} network_if_phy_context; + +/** @brief Phy context initializer + * + * @retval Initialized network PHY context + */ +#define NETWORK_IF_PHY_CONTEXT_INITIALIZER( \ + ) \ + { \ + NETWORK_IF_PHY_STATUS_OFF, \ + 0 \ + } + +/** @brief Network interface controller ID + * + * Identifies the network interface controller handled by the driver + */ +typedef enum { + /** @brief ID for EMAC0 */ + NETWORK_IF_NIC_ID_EMAC0, + + /** @brief ID for EMAC1 */ + NETWORK_IF_NIC_ID_EMAC1, + + /** @brief Number of network interface controller IDs */ + NETWORK_IF_NIC_ID_COUNT +} network_if_nic_id; + +/** @brief Network interface context + * + * Context for the micro controller specific part of the DWMAC 1000 n + * etwork driver + */ +typedef struct { + /** @brief Network interface controller ID */ + network_if_nic_id nic_id; + + /** @brief Driver context + * + * Address of the context of the low level DWMAC 1000 driver from libchip */ + void *driver_context; + + /** @brief Ethernet PHY context */ + network_if_phy_context phy; + + /* TODO: Create network context on micro controller level */ +} network_if_context; + +/** @brief Network interface context initializer + * + * Initializer for the context of a network interface + * @param nic_id ID of the network interface controller + * @param driver_context Address of the context of the low level DWMAC 1000 + * driver from libchip + * @retval Initialized network interface context + */ +#define NETWORK_IF_CONTEXT_INITIALIZER( \ + nic_id, \ + driver_context \ + ) \ + { \ + nic_id, \ + driver_context, \ + NETWORK_IF_PHY_CONTEXT_INITIALIZER() \ + } + +/****************************************************************************** +* Helper Methods +******************************************************************************/ + +/** @brief Altera status code to errno + * + * Convert Altera status code to errno error number + * @param status Altera status code as returned by methods from Alteras HWLib + * @retval Converted errno error number from errno.h + */ +static int network_if_altera_status_code_to_errno( ALT_STATUS_CODE status ) +{ + int eno = 0; + + switch ( status ) { + /*! + * Indicates a FALSE condition. + */ + case ALT_E_FALSE: + + /*! + * Indicates a TRUE condition. + */ + case ALT_E_TRUE: + + /*! The operation was successful. */ + /* case ALT_E_SUCCESS: */ + eno = 0; + break; + + /*! The operation failed. */ + case ALT_E_ERROR: + + /*! An invalid option was selected. */ + case ALT_E_INV_OPTION: + eno = EIO; /* I/O error */ + break; + + /*! FPGA configuration error detected.*/ + case ALT_E_FPGA_CFG: + eno = ECANCELED; /* Operation canceled */ + break; + + /*! FPGA CRC error detected. */ + case ALT_E_FPGA_CRC: + + /*! An error occurred on the FPGA configuration bitstream input source. */ + case ALT_E_FPGA_CFG_STM: + eno = EPROTO; /* Protocol error */ + break; + + /*! The FPGA is powered off. */ + case ALT_E_FPGA_PWR_OFF: + eno = ENODEV; /* No such device */ + break; + + /*! The SoC does not currently control the FPGA. */ + case ALT_E_FPGA_NO_SOC_CTRL: + + /*! The FPGA is not in USER mode. */ + case ALT_E_FPGA_NOT_USER_MODE: + eno = EPERM; /* Not super-user */ + break; + + /*! An argument violates a range constraint. */ + case ALT_E_ARG_RANGE: + + /*! A bad argument value was passed. */ + case ALT_E_BAD_ARG: + + /*! The argument value is reserved or unavailable. */ + case ALT_E_RESERVED: + eno = EINVAL; /* Invalid argument */ + break; + + /*! The operation is invalid or illegal. */ + case ALT_E_BAD_OPERATION: + + /*! The version ID is invalid. */ + case ALT_E_BAD_VERSION: + eno = EFAULT; /* Bad address */ + break; + + /*! An operation or response timeout period expired. */ + case ALT_E_TMO: + + /*! A clock is not enabled or violates an operational constraint. */ + case ALT_E_BAD_CLK: + eno = ETIME; /* Timer expired */ + break; + + /*! The buffer does not contain enough free space for the operation. */ + case ALT_E_BUF_OVF: + eno = ENOMEM; /* Not enough core */ + break; + default: + + /* Unknown case. Implement it! */ + assert( 0 == 1 ); + eno = EIO; + break; + } + + return eno; +} + +/** @brief PHY check chip ID + * + * Check the chip-ID of the KSZ8842 ethernet PHY. + * @param context Address of the network context + * @retval 0 if chip could be identified, error code from errno.h otherwise. + */ +static int network_if_phy_check_chip_id( network_if_context *context ) +{ + int eno; + uint16_t reg; + + eno = dwmac_if_read_from_phy( + context->driver_context, + 2, + ® + ); + + if ( eno == 0 ) { + if ( reg != 0x0022 ) { /* PHY ID part 1 */ + eno = ENXIO; + } else { + eno = dwmac_if_read_from_phy( + context->driver_context, + 3, + ® + ); + + if ( eno == 0 ) { + /* PHY ID part 2 and + * Manufacturers model number */ + if ( ( ( reg & 0xFC00 ) >> 10 ) != 0x0005 ) { + eno = ENXIO; + } else if ( ( ( reg & 0x03F0 ) >> 4 ) != 0x0021 ) { + eno = ENXIO; + } + } + } + } + + return eno; +} + +/****************************************************************************** +* Callback Methods +******************************************************************************/ + +/** @brief NIC enable + * + * Enables (powers up) the network interface card. + * @param[in] arg The void pointer argument passed to + * dwmac_network_if_attach_detach. + * @retval 0 on success, error code from errno.h on failure. + */ +static int network_if_nic_enable( void *arg ) +{ + int eno = 0; + network_if_context *context = (network_if_context *) arg; + ALT_CLK_t module_clk = ALT_CLK_EMAC0; + uint32_t permodrst_clr_msk = ALT_RSTMGR_PERMODRST_EMAC0_CLR_MSK; + + switch ( context->nic_id ) { + case NETWORK_IF_NIC_ID_EMAC0: + { + module_clk = ALT_CLK_EMAC0; + permodrst_clr_msk = ALT_RSTMGR_PERMODRST_EMAC0_CLR_MSK; + } + break; + case NETWORK_IF_NIC_ID_EMAC1: + { + module_clk = ALT_CLK_EMAC1; + permodrst_clr_msk = ALT_RSTMGR_PERMODRST_EMAC1_CLR_MSK; + } + break; + + case NETWORK_IF_NIC_ID_COUNT: + + /* Invalid case */ + eno = ENODEV; + break; + default: + + /* Unknown case */ + eno = ENOTSUP; + break; + } + + /* Pin mux configuration is handled by the Preloader. Thus no + * pin mux configuration here. */ + + /* Enable the clock for the EMAC module */ + if ( eno == 0 ) { + if ( ALT_E_FALSE == alt_clk_is_enabled( module_clk ) ) { + ALT_STATUS_CODE status = alt_clk_clock_enable( module_clk ); + eno = network_if_altera_status_code_to_errno( status ); + } + } + + /* Finish reset for the EMAC module */ + if ( eno == 0 ) { + uint32_t reg = alt_read_word( ALT_RSTMGR_PERMODRST_ADDR ); + alt_write_word( ALT_RSTMGR_PERMODRST_ADDR, reg & permodrst_clr_msk ); + } + + return eno; +} + +/** @brief NIC disable. + * + * Disables (powers down) the network interface card. + * @param[in] arg The void pointer argument passed to + * dwmac_network_if_attach_detach. + * @retval 0 on success, error code from errno.h on failure. + */ +static int network_if_nic_disable( void *arg ) +{ + int eno = 0; + network_if_context *context = (network_if_context *) arg; + ALT_CLK_t module_clk = ALT_CLK_EMAC0; + uint32_t permodrst_set_msk = ALT_RSTMGR_PERMODRST_EMAC0_SET_MSK; + + switch ( context->nic_id ) { + case NETWORK_IF_NIC_ID_EMAC0: + module_clk = ALT_CLK_EMAC0; + permodrst_set_msk = ALT_RSTMGR_PERMODRST_EMAC0_SET_MSK; + break; + case NETWORK_IF_NIC_ID_EMAC1: + module_clk = ALT_CLK_EMAC1; + permodrst_set_msk = ALT_RSTMGR_PERMODRST_EMAC1_SET_MSK; + break; + + case NETWORK_IF_NIC_ID_COUNT: + + /* Invalid case */ + eno = ENODEV; + break; + default: + + /* Unknown case */ + eno = ENOTSUP; + break; + } + + /* Enter rest status for the EMAC module */ + if ( eno == 0 ) { + uint32_t reg = alt_read_word( ALT_RSTMGR_PERMODRST_ADDR ); + alt_write_word( ALT_RSTMGR_PERMODRST_ADDR, reg | permodrst_set_msk ); + } + + /* Disable the clock for the EMAC module */ + if ( eno == 0 ) { + if ( ALT_E_TRUE == alt_clk_is_enabled( module_clk ) ) { + ALT_STATUS_CODE status = alt_clk_clock_disable( module_clk ); + eno = network_if_altera_status_code_to_errno( status ); + } + } + + return eno; +} + +/** @brief PHY disable. + * + * Disables (powers down) the network PHY. + * @param[in] arg The void pointer argument passed to + * dwmac_network_if_attach_detach. + * @retval 0 on success, error code from errno.h on failure. + */ +static int network_if_phy_disable( void *arg ) +{ + int eno = 0; + network_if_context *self = (network_if_context *) arg; + uint32_t mask; + ALT_STATUS_CODE status_code; + + /* The power pin of the PHY is hard wire to board power control and + * the PHY supports interrupts, This means we can not power it down + * and we don't need to stop a timer for polling PHY events. */ + + status_code = alt_gpio_port_int_mask_set( + ALT_GPIO_PORTB, + NETWORK_PIN_MASK_PHY_INTERRUPT, + NETWORK_PIN_MASK_PHY_INTERRUPT + ); + eno = network_if_altera_status_code_to_errno( status_code ); + + if ( eno == 0 ) { + mask = alt_gpio_port_int_enable_get( ALT_GPIO_PORTB ); + status_code = alt_gpio_port_int_enable( + ALT_GPIO_PORTB, + mask & ~NETWORK_PIN_MASK_PHY_INTERRUPT + ); + eno = network_if_altera_status_code_to_errno( status_code ); + } + + if ( eno == 0 ) { + status_code = alt_gpio_port_int_status_clear( + ALT_GPIO_PORTB, + NETWORK_PIN_MASK_PHY_INTERRUPT + ); + eno = network_if_altera_status_code_to_errno( status_code ); + } + + if ( eno == 0 ) { + self->phy.status = NETWORK_IF_PHY_STATUS_OFF; + } + + return eno; +} + +/** @brief PHY enable. + * + * Enables (powers up) the network PHY. + * @param[in] arg The void pointer argument passed to + * dwmac_network_if_attach_detach. + * @retval 0 on success, error code from errno.h on failure. + */ +static int network_if_phy_enable( void *arg ) +{ + int eno = 0; + network_if_context *self = (network_if_context *) arg; + ALT_STATUS_CODE status_code; + + /* The power pin of the PHY is hard wire to board power control and + * the PHY supports interrupts, This means we can not power it up + * and we don't need to start a timer for polling PHY events. */ + + eno = network_if_phy_check_chip_id( self ); + + if ( eno == 0 ) { + /* The phy is already enabled and we will reset it */ + eno = network_if_phy_disable( self ); + + if ( eno == 0 ) { + rtems_task_wake_after( rtems_clock_get_ticks_per_second() / 100 ); + } + } else { + eno = 0; + } + + status_code = alt_gpio_port_datadir_set( + ALT_GPIO_PORTB, + NETWORK_PIN_MASK_PHY_INTERRUPT, + 0 + ); + eno = network_if_altera_status_code_to_errno( status_code ); + + if ( eno == 0 ) { + status_code = alt_gpio_port_int_type_set( + ALT_GPIO_PORTB, + NETWORK_PIN_MASK_PHY_INTERRUPT, + 0 + ); + eno = network_if_altera_status_code_to_errno( status_code ); + } + + if ( eno == 0 ) { + status_code = alt_gpio_port_int_pol_set( + ALT_GPIO_PORTB, + NETWORK_PIN_MASK_PHY_INTERRUPT, + 1 + ); + eno = network_if_altera_status_code_to_errno( status_code ); + } + + if ( eno == 0 ) { + status_code = alt_gpio_port_debounce_set( + ALT_GPIO_PORTB, + NETWORK_PIN_MASK_PHY_INTERRUPT, + 0 + ); + eno = network_if_altera_status_code_to_errno( status_code ); + } + + if ( eno == 0 ) { + status_code = alt_gpio_port_int_enable( + ALT_GPIO_PORTB, + NETWORK_PIN_MASK_PHY_INTERRUPT + ); + eno = network_if_altera_status_code_to_errno( status_code ); + } + + if ( eno == 0 ) { + status_code = alt_gpio_port_int_mask_set( + ALT_GPIO_PORTB, + NETWORK_PIN_MASK_PHY_INTERRUPT, + 0 + ); + eno = network_if_altera_status_code_to_errno( status_code ); + } + + if ( eno == 0 ) { + status_code = alt_gpio_port_int_status_clear( + ALT_GPIO_PORTB, + NETWORK_PIN_MASK_PHY_INTERRUPT + ); + eno = network_if_altera_status_code_to_errno( status_code ); + } + + if ( eno == 0 ) { + self->phy.status = NETWORK_IF_PHY_STATUS_STOPPED; + } + + return eno; +} + +/** @brief Clear phy event status. + * + * Clears all PHY event statuses. + * @param[in] arg The void pointer argument passed to + * dwmac_network_if_attach_detach. + * @retval 0 on success, error code from errno.h on failure. + */ +static int network_if_phy_event_status_clear( void *arg ) +{ + int eno; + ALT_STATUS_CODE status_code; + + (void) arg; + + /* Clear the interrupt status */ + status_code = alt_gpio_port_int_status_clear( + ALT_GPIO_PORTB, + NETWORK_PIN_MASK_PHY_INTERRUPT + ); + eno = network_if_altera_status_code_to_errno( status_code ); + + if ( eno == 0 ) { + /* Unmask the interrupt (was masked within interrupt handler) */ + status_code = alt_gpio_port_int_mask_set( + ALT_GPIO_PORTB, + NETWORK_PIN_MASK_PHY_INTERRUPT, + 0 + ); + eno = network_if_altera_status_code_to_errno( status_code ); + } + + return eno; +} + +/** + * @brief Get the PHY event status. + * + * Reports status on PHY events (e.g. PHY interrupts). + * @param[in] arg The void pointer argument passed to + * dwmac_network_if_attach_detach. + * @param[out] event_set Pointer to a buffer for a set of events for which a + * PHY status change was detected. + * For events see @see dwmac_phy_event. + * @retval 0 on success, error code from errno.h on failure. + */ +static int network_if_phy_events_status_get( + void *arg, + dwmac_phy_event *event_set ) +{ + int eno = 0; + uint16_t reg = 0; + network_if_context *self = (network_if_context *) arg; + + eno = dwmac_if_read_from_phy( + self->driver_context, + 0x1B, + ® + ); + + if ( eno == 0 ) { + if ( ( reg & 0x80 ) != 0 ) { + *event_set |= PHY_EVENT_JABBER; + } + + if ( ( reg & 0x40 ) != 0 ) { + *event_set |= PHY_EVENT_RECEIVE_ERROR; + } + + if ( ( reg & 0x20 ) != 0 ) { + *event_set |= PHY_EVENT_PAGE_RECEIVE; + } + + if ( ( reg & 0x10 ) != 0 ) { + *event_set |= PHY_EVENT_PARALLEL_DETECT_FAULT; + } + + if ( ( reg & 0x08 ) != 0 ) { + *event_set |= PHY_EVENT_LINK_PARTNER_ACK; + } + + if ( ( reg & 0x04 ) != 0 ) { + *event_set |= PHY_EVENT_LINK_DOWN; + } + + if ( ( reg & 0x02 ) != 0 ) { + *event_set |= PHY_EVENT_REMOTE_FAULT; + } + + if ( ( reg & 0x01 ) != 0 ) { + *event_set |= PHY_EVENT_LINK_UP; + } + } + + return eno; +} + +/** @brief Network PHY interrupt handler + * + * Handling method for interrupts from the PHY. + * @param arg Address of the network interface context + */ +static void network_if_phy_interrupt_handler( void *arg ) +{ + int eno = 0; + network_if_context *self = (network_if_context *) arg; + uint32_t reg; + + reg = alt_gpio_port_int_status_get( ALT_GPIO_PORTB ); + + if ( reg & NETWORK_PIN_MASK_PHY_INTERRUPT ) { + /* We have a level interrupt and we expect the driver to do + * the actual interrupt handling from within a task context. + * Thus we have to mask the interrupt. A call to + * network_if_phy_event_status_clear() will unmask it */ + ALT_STATUS_CODE status_code = alt_gpio_port_int_mask_set( + ALT_GPIO_PORTB, + NETWORK_PIN_MASK_PHY_INTERRUPT, + NETWORK_PIN_MASK_PHY_INTERRUPT + ); + eno = network_if_altera_status_code_to_errno( status_code ); + + if ( eno == 0 ) { + eno = dwmac_if_handle_phy_event( + self->driver_context + ); + } + } + + assert( eno == 0 ); +} + +/** @brief PHY event enable. + * + * Enables generation of events for an event set. + * @param[in] arg The void pointer argument passed to + * dwmac_network_if_attach_detach. + * @param[in] event_set Set of events. For these events shall get generated + * upon PHY status change. + * @retval 0 on success, error code from errno.h on failure. + */ +static int network_if_phy_event_enable( + void *arg, + const dwmac_phy_event event_set ) +{ + int eno = 0; + uint16_t reg = 0; + network_if_context *self = (network_if_context *) arg; + network_if_phy_status old_status = self->phy.status; + + if ( arg != NULL ) { + switch ( self->phy.status ) { + case NETWORK_IF_PHY_STATUS_OFF: + break; + case NETWORK_IF_PHY_STATUS_STOPPED: + break; + case NETWORK_IF_PHY_STATUS_STARTED: + { + eno = dwmac_if_read_from_phy( + self->driver_context, + 0x1B, + ® + ); + + if ( eno == 0 ) { + /* Disable all interrupts, but leave interrupt status + * bits untouched */ + reg &= 0x00FF; + eno = dwmac_if_write_to_phy( + self->driver_context, + 0x1B, + reg + ); + } + + if ( eno == 0 ) { + self->phy.irq_mask = 0; + self->phy.status = NETWORK_IF_PHY_STATUS_STOPPED; + } + } + break; + case NETWORK_IF_PHY_STATUS_COUNT: + { + /* Invalid case */ + assert( self->phy.status != NETWORK_IF_PHY_STATUS_COUNT ); + eno = ENOTSUP; + } + break; + default: + { + /* Unknown case */ + assert( + self->phy.status == NETWORK_IF_PHY_STATUS_OFF + || self->phy.status == NETWORK_IF_PHY_STATUS_STOPPED + || self->phy.status == NETWORK_IF_PHY_STATUS_STARTED + ); + eno = ENOTSUP; + } + break; + } + + if ( eno == 0 ) { + /* Select interrupts to enable */ + if ( ( event_set & PHY_EVENT_JABBER ) != 0 ) { + reg |= 0x8000; + } + + if ( ( event_set & PHY_EVENT_RECEIVE_ERROR ) != 0 ) { + reg |= 0x4000; + } + + if ( ( event_set & PHY_EVENT_PAGE_RECEIVE ) != 0 ) { + reg |= 0x2000; + } + + if ( ( event_set & PHY_EVENT_PARALLEL_DETECT_FAULT ) != 0 ) { + reg |= 0x1000; + } + + if ( ( event_set & PHY_EVENT_LINK_PARTNER_ACK ) != 0 ) { + reg |= 0x0800; + } + + if ( ( event_set & PHY_EVENT_LINK_DOWN ) != 0 ) { + reg |= 0x0400; + } + + if ( ( event_set & PHY_EVENT_REMOTE_FAULT ) != 0 ) { + reg |= 0x0200; + } + + if ( ( event_set & PHY_EVENT_LINK_UP ) != 0 ) { + reg |= 0x100; + } + + switch ( old_status ) { + case NETWORK_IF_PHY_STATUS_OFF: + break; + case NETWORK_IF_PHY_STATUS_STOPPED: + break; + case NETWORK_IF_PHY_STATUS_STARTED: + { + if ( eno == 0 ) { + /* Modify interrupt enable bits, but leave + * interrupt status bits untouched */ + eno = dwmac_if_write_to_phy( + self->driver_context, + 0x1B, + reg & 0xFF00 + ); + } + } + break; + case NETWORK_IF_PHY_STATUS_COUNT: + { + /* Invalid case */ + assert( self->phy.status != NETWORK_IF_PHY_STATUS_COUNT ); + eno = ENOTSUP; + } + break; + default: + { + /* Unknown case */ + assert( + self->phy.status == NETWORK_IF_PHY_STATUS_OFF + || self->phy.status == NETWORK_IF_PHY_STATUS_STOPPED + || self->phy.status == NETWORK_IF_PHY_STATUS_STARTED + ); + eno = ENOTSUP; + } + break; + } + + if ( eno == 0 ) { + self->phy.irq_mask = reg & 0xFF00; + } + } + } + + return eno; +} + +/** + * @brief Stop the network PHY. + * + * Do anything necessary to stop the network PHY (stop generating events, ...). + * @param[in] arg The void pointer argument passed to + * dwmac_network_if_attach_detach. + * @retval 0 on success, error code from errno.h on failure. + */ +static int network_if_phy_stop( void *arg ) +{ + int eno = 0; + rtems_status_code sc = RTEMS_SUCCESSFUL; + network_if_context *self = (network_if_context *) arg; + + switch ( self->phy.status ) { + case NETWORK_IF_PHY_STATUS_OFF: + break; + case NETWORK_IF_PHY_STATUS_STOPPED: + break; + case NETWORK_IF_PHY_STATUS_STARTED: + { + /* Remove any selected interrupts */ + eno = dwmac_if_write_to_phy( + self->driver_context, + 0x1B, + 0 + ); + + if ( eno == 0 ) { + uint16_t reg; + + /* Clear interrupt status bits by reading them */ + eno = dwmac_if_read_from_phy( + self->driver_context, + 0x1B, + ® + ); + } + + if ( eno == 0 ) { + self->phy.irq_mask = 0; + + /* Remove interrupt handler */ + sc = rtems_interrupt_handler_remove( + ALT_INT_INTERRUPT_GPIO1, + network_if_phy_interrupt_handler, + self + ); + eno = rtems_status_code_to_errno( sc ); + + if ( eno == 0 ) { + self->phy.status = NETWORK_IF_PHY_STATUS_STOPPED; + } + } + } + break; + case NETWORK_IF_PHY_STATUS_COUNT: + { + /* Invalid case */ + assert( self->phy.status != NETWORK_IF_PHY_STATUS_COUNT ); + eno = ENOTSUP; + } + break; + default: + { + /* Unknown case */ + assert( + self->phy.status == NETWORK_IF_PHY_STATUS_OFF + || self->phy.status == NETWORK_IF_PHY_STATUS_STOPPED + || self->phy.status == NETWORK_IF_PHY_STATUS_STARTED + ); + eno = ENOTSUP; + } + break; + } + + return eno; +} + +/** + * @brief Start the network PHY. + * + * Do anything necessary to start the network PHY (start generating + * events, ...). + * @param[in] arg The void pointer argument passed to + * dwmac_network_if_attach_detach. + * @retval 0 on success, error code from errno.h on failure. + */ +static int network_if_phy_start( void *arg ) +{ + int eno = 0; + rtems_status_code sc = RTEMS_SUCCESSFUL; + network_if_context *self = (network_if_context *) arg; + + switch ( self->phy.status ) { + case NETWORK_IF_PHY_STATUS_OFF: + { + assert( self->phy.status != NETWORK_IF_PHY_STATUS_OFF ); + eno = EHOSTDOWN; + } + break; + case NETWORK_IF_PHY_STATUS_STOPPED: + + /* Disable all interrupts */ + eno = dwmac_if_write_to_phy( + self->driver_context, + 0x1B, + 0 + ); + + if ( eno == 0 ) { + } + + if ( eno == 0 ) { + /* Install interrupt handler */ + sc = rtems_interrupt_handler_install( + ALT_INT_INTERRUPT_GPIO1, + NULL, + RTEMS_INTERRUPT_SHARED, + network_if_phy_interrupt_handler, + self + ); + eno = rtems_status_code_to_errno( sc ); + } + + if ( eno == 0 ) { + /* Enable interrupts */ + eno = dwmac_if_write_to_phy( + self->driver_context, + 0x1B, + self->phy.irq_mask + ); + } + + break; + case NETWORK_IF_PHY_STATUS_STARTED: + { + uint16_t irq_mask = self->phy.irq_mask; + + /* Re-start the phy */ + eno = network_if_phy_stop( self ); + + if ( eno == 0 ) { + self->phy.irq_mask = irq_mask; + + eno = network_if_phy_start( + self + ); + } + } + break; + + case NETWORK_IF_PHY_STATUS_COUNT: + { + /* Invalid case */ + assert( self->phy.status != NETWORK_IF_PHY_STATUS_COUNT ); + eno = ENOTSUP; + } + break; + default: + { + /* Unknown case */ + assert( + self->phy.status == NETWORK_IF_PHY_STATUS_OFF + || self->phy.status == NETWORK_IF_PHY_STATUS_STOPPED + || self->phy.status == NETWORK_IF_PHY_STATUS_STARTED + ); + eno = ENOTSUP; + } + break; + } + + if ( eno == 0 ) { + self->phy.status = NETWORK_IF_PHY_STATUS_STARTED; + } + + return eno; +} + +/** + * @brief Allocate nocache RAM. + * + * Allocate uncached RAM. + * @param[in] arg The void pointer argument passed to + * dwmac_network_if_attach_detach. + * @param[out] memory Pointer of a buffer to write the address of the + * allocated memory to. + * @param[in] size Number of bytes to be allocated + * @retval 0 on success, error code from errno.h on failure. + */ +static int network_if_mem_alloc_nocache( + void *arg, + void **memory, + const size_t size ) +{ + int eno = EINVAL; + + (void) arg; + + assert( memory != NULL ); + + if ( memory != NULL ) { + *memory = altera_cyclone_v_nocache_malloc( size ); + + if ( *memory != NULL ) { + eno = 0; + } else { + eno = ENOMEM; + } + } + + return eno; +} + +/** + * @brief Free nocache RAM. + * + * Release uncached RAM. + * @param[in] arg The void pointer argument passed to + * dwmac_network_if_attach_detach. + * @param[in] memory Pointer to the memory to be freed. + * @retval 0 on success, error code from errno.h on failure. + */ +static int network_if_mem_free_nocache( + void *arg, + void *memory ) +{ + int eno = EINVAL; + + (void) arg; + + assert( memory != NULL ); + + if ( memory != NULL ) { + altera_cyclone_v_nocache_free( memory ); + eno = 0; + } + + return eno; +} + +/** + * @brief Bus setup. + * + * Callback method for setting up the system bus for the network driver. + * @param[in] arg The void pointer argument passed to + * dwmac_network_if_attach_detach. + * @retval 0 on success, error code from errno.h on failure. + */ +static int network_if_bus_setup( void *arg ) +{ + (void) arg; + + /* Nothing to be done */ + return 0; +} + +/***************************************************************************** +* Context Data +******************************************************************************/ + +/** @brief Network interface context */ +static network_if_context context = NETWORK_IF_CONTEXT_INITIALIZER( + + /** @brief Use EMAC1 */ + NETWORK_IF_NIC_ID_EMAC1, + + /** @brief Address of driver context + * + * To be assigned with return value of dwmac_network_if_attach_detach */ + NULL + ); + +/** @brief Network driver DMA configuration data */ +static const dwmac_dma_cfg NETWORK_DMA_CFG = DWMAC_DMA_CFG_INITIALIZER( + + /** @brief Bus mode burst length */ + DWMAC_DMA_CFG_BUS_MODE_BURST_LENGTH_64, + + /** @brief Bus mode fixed burst? */ + DWMAC_DMA_CFG_BUS_MODE_BURST_MODE_SINGLE_OR_INCR, + + /** @brief Bus mode mixed burst? */ + DWMAC_DMA_CFG_BUS_MODE_BURST_NOT_MIXED, + + /** @brief Permit AXI burst length of 4 */ + DWMAC_DMA_CFG_AXI_BURST_LENGTH_4_NOT_SUPPORTED, + + /** @brief Permit AXI burst length of 8 */ + DWMAC_DMA_CFG_AXI_BURST_LENGTH_8_NOT_SUPPORTED, + + /** @brief Permit AXI burst length of 16 */ + DWMAC_DMA_CFG_AXI_BURST_LENGTH_16_NOT_SUPPORTED, + + /** @brief Select boundary crossing mode */ + DWMAC_DMA_CFG_AXI_BURST_BOUNDARY_4_KB + ); + +/** @brief Network driver configuration data */ +static const dwmac_cfg NETWORK_DRIVER_CFG = DWMAC_CFG_INITIALIZER( + + /** @brief GMII clock rate */ + 75000000, + + /** @brief Address of the GMAC registers for emac1 */ + ALT_EMAC1_GMACGRP_ADDR, + + /** @brief Address of the DMA registers for emac1 */ + ALT_EMAC1_DMAGRP_ADDR, + + /** @brief Address of the PHY on the mdio bus */ + 4, + + /** @brief Bytes per L1 cache line */ + 32, + + /** @brief Interrupt number for the EMAC */ + ALT_INT_INTERRUPT_EMAC1_IRQ, + + /** @brief DMA configuration */ + &NETWORK_DMA_CFG, + + /** @brief Callback method for enabling the network controller */ + network_if_nic_enable, + + /** @brief Callback method for disabling the network controller */ + network_if_nic_disable, + + /** @brief Callback method for enabling the PHY */ + network_if_phy_enable, + + /** @brief Callback method for disabling the PHY */ + network_if_phy_disable, + + /** @brief Callback which enables PHY events for forwarding to driver */ + network_if_phy_event_enable, + + /** @brief Callback method for clearing PHY interrupt status */ + network_if_phy_event_status_clear, + + /** @brief Callback method for getting a set of events from the PHY */ + network_if_phy_events_status_get, + + /** @brief Callback method for making the PHY start forwarding events */ + network_if_phy_start, + + /** @brief Callback method for making the PHY stop forwarding events */ + network_if_phy_stop, + + /** @brief Callback method for allocating uncached memory */ + network_if_mem_alloc_nocache, + + /** @brief Callback method for freeing uncached memory */ + network_if_mem_free_nocache, + + /** @brief Callback method for setting up bus upon driver startup */ + network_if_bus_setup, + + /** @brief Operations for the ethernet mac 1000 */ + &DWMAC_1000_ETHERNET_MAC_OPS, + + /** @brief Operations for the enhanced DMA descriptors */ + &DWMAC_DESCRIPTOR_OPS_ENHANCED + ); + +/****************************************************************************** +* API +******************************************************************************/ + +/** @brief Network interface attach/detach + * + * The standard attach/detach method for network interfaces. + * This methods will call the DWMAC 1000 attach/detach method and pass + * configuration data and callback methods into it. Via these the general + * DWMAC 1000 driver is able the handle micro controller specific things. + * NOTE: Detaching is NOT supported! + * @param config Configuration parameters from and for the BSD network + * stack. + * @param attaching True if attaching the driver to the network stack, false if + * detaching. + * @retval 0 if successful, error code from errno.h if not. + */ +int altera_cyclone_v_network_if_attach_detach( + struct rtems_bsdnet_ifconfig *config, + int attaching ) +{ + int eno = 0; + + assert( config != NULL ); + + /* Network controller initialization */ + context.driver_context = dwmac_network_if_attach_detach( + config, + &NETWORK_DRIVER_CFG, + &context, + attaching + ); + + if ( context.driver_context == NULL ) { + eno = EFAULT; + } + + return eno; +} + +#endif /* defined(RTEMS_NETWORKING) */ diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/preinstall.am b/c/src/lib/libbsp/arm/altera-cyclone-v/preinstall.am new file mode 100644 index 0000000000..3f83665577 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/preinstall.am @@ -0,0 +1,200 @@ +## Automatically generated by ampolish3 - Do not edit + +if AMPOLISH3 +$(srcdir)/preinstall.am: Makefile.am + $(AMPOLISH3) $(srcdir)/Makefile.am > $(srcdir)/preinstall.am +endif + +PREINSTALL_DIRS = +DISTCLEANFILES += $(PREINSTALL_DIRS) + +all-local: $(TMPINSTALL_FILES) + +TMPINSTALL_FILES = +CLEANFILES = $(TMPINSTALL_FILES) + +all-am: $(PREINSTALL_FILES) + +PREINSTALL_FILES = +CLEANFILES += $(PREINSTALL_FILES) + +$(PROJECT_LIB)/$(dirstamp): + @$(MKDIR_P) $(PROJECT_LIB) + @: > $(PROJECT_LIB)/$(dirstamp) +PREINSTALL_DIRS += $(PROJECT_LIB)/$(dirstamp) + +$(PROJECT_INCLUDE)/$(dirstamp): + @$(MKDIR_P) $(PROJECT_INCLUDE) + @: > $(PROJECT_INCLUDE)/$(dirstamp) +PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp) + +$(PROJECT_INCLUDE)/bsp/$(dirstamp): + @$(MKDIR_P) $(PROJECT_INCLUDE)/bsp + @: > $(PROJECT_INCLUDE)/bsp/$(dirstamp) +PREINSTALL_DIRS += $(PROJECT_INCLUDE)/bsp/$(dirstamp) + +$(PROJECT_INCLUDE)/libcpu/$(dirstamp): + @$(MKDIR_P) $(PROJECT_INCLUDE)/libcpu + @: > $(PROJECT_INCLUDE)/libcpu/$(dirstamp) +PREINSTALL_DIRS += $(PROJECT_INCLUDE)/libcpu/$(dirstamp) + +$(PROJECT_LIB)/bsp_specs: bsp_specs $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/bsp_specs +PREINSTALL_FILES += $(PROJECT_LIB)/bsp_specs + +$(PROJECT_INCLUDE)/bsp.h: include/bsp.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp.h + +$(PROJECT_INCLUDE)/tm27.h: include/tm27.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tm27.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/tm27.h + +$(PROJECT_INCLUDE)/coverhd.h: ../../shared/include/coverhd.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/coverhd.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/coverhd.h + +$(PROJECT_INCLUDE)/bspopts.h: include/bspopts.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bspopts.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bspopts.h + +$(PROJECT_INCLUDE)/bsp/bootcard.h: ../../shared/include/bootcard.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/bootcard.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/bootcard.h + +$(PROJECT_INCLUDE)/bsp/utility.h: ../../shared/include/utility.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/utility.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/utility.h + +$(PROJECT_INCLUDE)/bsp/irq-generic.h: ../../shared/include/irq-generic.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-generic.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-generic.h + +$(PROJECT_INCLUDE)/bsp/irq-info.h: ../../shared/include/irq-info.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-info.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-info.h + +$(PROJECT_INCLUDE)/bsp/stackalloc.h: ../../shared/include/stackalloc.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/stackalloc.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/stackalloc.h + +$(PROJECT_INCLUDE)/bsp/tod.h: ../../shared/tod.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/tod.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/tod.h + +$(PROJECT_INCLUDE)/bsp/start.h: ../shared/include/start.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/start.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/start.h + +$(PROJECT_INCLUDE)/bsp/arm-a9mpcore-clock.h: ../shared/include/arm-a9mpcore-clock.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-a9mpcore-clock.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-a9mpcore-clock.h + +$(PROJECT_INCLUDE)/bsp/arm-a9mpcore-irq.h: ../shared/include/arm-a9mpcore-irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-a9mpcore-irq.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-a9mpcore-irq.h + +$(PROJECT_INCLUDE)/bsp/arm-a9mpcore-regs.h: ../shared/include/arm-a9mpcore-regs.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-a9mpcore-regs.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-a9mpcore-regs.h + +$(PROJECT_INCLUDE)/bsp/arm-a9mpcore-start.h: ../shared/include/arm-a9mpcore-start.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-a9mpcore-start.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-a9mpcore-start.h + +$(PROJECT_INCLUDE)/bsp/arm-cp15-start.h: ../shared/include/arm-cp15-start.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-cp15-start.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-cp15-start.h + +$(PROJECT_INCLUDE)/bsp/arm-errata.h: ../shared/include/arm-errata.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-errata.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-errata.h + +$(PROJECT_INCLUDE)/bsp/arm-gic.h: ../shared/include/arm-gic.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-gic.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-gic.h + +$(PROJECT_INCLUDE)/bsp/arm-gic-irq.h: ../shared/include/arm-gic-irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-gic-irq.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-gic-irq.h + +$(PROJECT_INCLUDE)/bsp/arm-gic-regs.h: ../shared/include/arm-gic-regs.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-gic-regs.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-gic-regs.h + +$(PROJECT_INCLUDE)/bsp/arm-gic-tm27.h: ../shared/include/arm-gic-tm27.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-gic-tm27.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-gic-tm27.h + +$(PROJECT_INCLUDE)/bsp/arm-release-id.h: ../shared/include/arm-release-id.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-release-id.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-release-id.h + +$(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/nocache-heap.h: include/nocache-heap.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/nocache-heap.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/nocache-heap.h + +$(PROJECT_INCLUDE)/bsp/alt_address_space.h: hwlib/include/alt_address_space.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_address_space.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_address_space.h + +$(PROJECT_INCLUDE)/bsp/alt_clock_group.h: hwlib/include/alt_clock_group.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_clock_group.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_clock_group.h + +$(PROJECT_INCLUDE)/bsp/alt_clock_manager.h: hwlib/include/alt_clock_manager.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_clock_manager.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_clock_manager.h + +$(PROJECT_INCLUDE)/bsp/alt_generalpurpose_io.h: hwlib/include/alt_generalpurpose_io.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_generalpurpose_io.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_generalpurpose_io.h + +$(PROJECT_INCLUDE)/bsp/alt_hwlibs_ver.h: hwlib/include/alt_hwlibs_ver.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_hwlibs_ver.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_hwlibs_ver.h + +$(PROJECT_INCLUDE)/bsp/alt_interrupt_common.h: hwlib/include/alt_interrupt_common.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_interrupt_common.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_interrupt_common.h + +$(PROJECT_INCLUDE)/bsp/alt_mpu_registers.h: hwlib/include/alt_mpu_registers.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_mpu_registers.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_mpu_registers.h + +$(PROJECT_INCLUDE)/bsp/alt_reset_manager.h: hwlib/include/alt_reset_manager.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_reset_manager.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_reset_manager.h + +$(PROJECT_INCLUDE)/bsp/hwlib.h: hwlib/include/hwlib.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/hwlib.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/hwlib.h + +$(PROJECT_INCLUDE)/libcpu/arm-cp15.h: ../../../libcpu/arm/shared/include/arm-cp15.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/arm-cp15.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/arm-cp15.h + +$(PROJECT_LIB)/start.$(OBJEXT): start.$(OBJEXT) $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/start.$(OBJEXT) +TMPINSTALL_FILES += $(PROJECT_LIB)/start.$(OBJEXT) + +$(PROJECT_LIB)/linkcmds: startup/linkcmds $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds +TMPINSTALL_FILES += $(PROJECT_LIB)/linkcmds + +$(PROJECT_LIB)/linkcmds.altcycv: startup/linkcmds.altcycv $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds.altcycv +TMPINSTALL_FILES += $(PROJECT_LIB)/linkcmds.altcycv + +$(PROJECT_LIB)/linkcmds.altcycv_devkit: startup/linkcmds.altcycv_devkit $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds.altcycv_devkit +TMPINSTALL_FILES += $(PROJECT_LIB)/linkcmds.altcycv_devkit + +$(PROJECT_LIB)/linkcmds.altcycv_devkit_smp: startup/linkcmds.altcycv_devkit_smp $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds.altcycv_devkit_smp +TMPINSTALL_FILES += $(PROJECT_LIB)/linkcmds.altcycv_devkit_smp + diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspreset.c b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspreset.c new file mode 100644 index 0000000000..65e8624847 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspreset.c @@ -0,0 +1,37 @@ +/* + * 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.com/license/LICENSE. + */ + +#include <bsp/bootcard.h> +#include <bsp/alt_reset_manager.h> +#include "socal/alt_rstmgr.h" +#include "socal/hps.h" + +void bsp_reset(void) +{ + uint32_t self_cpu = rtems_smp_get_current_processor(); + volatile uint32_t *mpumodrst = ALT_RSTMGR_MPUMODRST_ADDR; + + if( self_cpu == 0 ) { + /* Reset CPU1 */ + (*mpumodrst) |= ALT_RSTMGR_MPUMODRST_CPU1_SET_MSK; + + /* Simply call the reset method from alteras HWLIB */ + (void) alt_reset_cold_reset(); + } else { + /* Keep CPU1 waiting until it gets reset by CPU0 */ + while ( true ) { + __asm__ volatile ("wfi"); + } + } +} diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspstart.c b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspstart.c new file mode 100644 index 0000000000..abdcbfd816 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspstart.c @@ -0,0 +1,69 @@ +/* + * 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.com/license/LICENSE. + */ + +#include <assert.h> +#include <stdint.h> +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> +#include <bsp/start.h> +#include <bsp/nocache-heap.h> +#include <rtems/config.h> +#include "socal/alt_rstmgr.h" +#include "socal/alt_sysmgr.h" +#include "socal/hps.h" + +#ifndef MIN +#define MIN( a, b ) ( ( a ) < ( b ) ? ( a ) : ( b ) ) +#endif + +#define BSPSTART_MAX_CORES_PER_CONTROLLER 2 + +static void bsp_start_secondary_cores( void ) +{ +#ifdef RTEMS_SMP + volatile uint32_t *mpumodrst = ALT_RSTMGR_MPUMODRST_ADDR; + uint32_t *cpu1_start_addr = ( + ALT_SYSMGR_ROMCODE_ADDR + ALT_SYSMGR_ROMCODE_CPU1STARTADDR_OFST ); + const uint32_t CORES = MIN( + (uintptr_t) bsp_processor_count, + rtems_configuration_get_maximum_processors() ); + unsigned int index; + + + /* Memory would get overwritten if a too small processor count + * would be specified */ + assert( + (uintptr_t) bsp_processor_count >= BSPSTART_MAX_CORES_PER_CONTROLLER ); + + if ( (uintptr_t) bsp_processor_count >= BSPSTART_MAX_CORES_PER_CONTROLLER ) { + for ( index = 1; index < CORES; ++index ) { + /* set the start address from where the core will execute */ + (*cpu1_start_addr) = ALT_SYSMGR_ROMCODE_CPU1STARTADDR_VALUE_SET( + (uintptr_t) _start ); + + /* Make the core finish it's reset */ + (*mpumodrst) &= ~ALT_RSTMGR_MPUMODRST_CPU1_SET_MSK; + } + } +#endif /* #ifdef RTEMS_SMP */ +} + +void bsp_start( void ) +{ + bsp_interrupt_initialize(); + altera_cyclone_v_nocache_init_heap(); + bsp_start_secondary_cores(); +} diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspstarthooks.c b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspstarthooks.c new file mode 100644 index 0000000000..c8266a50fc --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspstarthooks.c @@ -0,0 +1,204 @@ +/* + * 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.com/license/LICENSE. + */ + +#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 <alt_address_space.h> +#include "socal/socal.h" +#include "socal/alt_sdr.h" +#include "socal/hps.h" +#include "../include/arm-cache-l1.h" + +/*#define DEBUG_ECC_ERROR*/ /* TODO: Delete DEBUG_ECC_ERROR after the implementation phase */ + +#ifdef RTEMS_SMP + #define MMU_DATA_READ_WRITE ARMV7_MMU_DATA_READ_WRITE_SHAREABLE +#else + #define MMU_DATA_READ_WRITE ARMV7_MMU_DATA_READ_WRITE_CACHED +#endif + +/* 1 MB reset default value for address filtering start */ +#define BSPSTART_L2_CACHE_ADDR_FILTERING_START_RESET 0x100000 + +#ifndef BSPSTARTHOOKS_MIN +#define BSPSTARTHOOKS_MIN( a, b ) ( ( a ) < ( b ) ? ( a ) : ( b ) ) +#endif + +LINKER_SYMBOL( bsp_section_nocache_size ); +LINKER_SYMBOL( bsp_section_nocache_end ); +LINKER_SYMBOL( bsp_section_nocache_begin ); + +BSP_START_DATA_SECTION static const arm_cp15_start_section_config + altcycv_mmu_config_table[] = { + ARMV7_CP15_START_DEFAULT_SECTIONS, + { + .begin = (uint32_t) bsp_section_nocache_begin, + .end = (uint32_t) bsp_section_nocache_end, + + .flags = ARMV7_MMU_DATA_READ_WRITE | ARM_MMU_SECT_TEX_0 + }, { /* Periphery area */ + .begin = 0xFC000000U, + .end = 0x00000000U, + .flags = ARMV7_MMU_DEVICE + } +}; + +BSP_START_TEXT_SECTION static void setup_mmu_and_cache( const uint32_t CPU_ID ) +{ + uint32_t ctrl = arm_cp15_get_control(); + const uint32_t CORES = BSPSTARTHOOKS_MIN( + (uintptr_t) bsp_processor_count, + rtems_configuration_get_maximum_processors() ); + + /* We expect the L1 caches and program flow prediction to be off */ + assert( ( ctrl & ARM_CP15_CTRL_I ) == 0 ); + assert( ( ctrl & ARM_CP15_CTRL_C ) == 0 ); + assert( ( ctrl & ARM_CP15_CTRL_Z ) == 0 ); + + ctrl = arm_cp15_start_setup_mmu_and_cache( + ARM_CP15_CTRL_A | ARM_CP15_CTRL_M, + ARM_CP15_CTRL_AFE + ); + + if( CPU_ID == 0 ) { + arm_cp15_start_setup_translation_table( + (uint32_t *) bsp_translation_table_base, + ARM_MMU_DEFAULT_CLIENT_DOMAIN, + &altcycv_mmu_config_table[0], + RTEMS_ARRAY_SIZE( altcycv_mmu_config_table ) + ); + } else { + /* FIXME: Sharing the translation table between processors is brittle */ + arm_cp15_set_translation_table_base((uint32_t *) bsp_translation_table_base); + } + + /* Enable MMU */ + ctrl |= ARM_CP15_CTRL_M; + + arm_cp15_set_control( ctrl ); + + if( CPU_ID == (CORES - 1) ) { + /* Enable all cache levels for the last core */ + rtems_cache_enable_instruction(); + rtems_cache_enable_data(); + } else { + /* Enable only L1 cache */ + arm_cache_l1_enable_data(); + arm_cache_l1_enable_instruction(); + } + + /* Enable flow control prediction aka. branch prediction */ + +/* TODO: With the current network stack 06-Feb2014 in_checksum() + * becomes a severe performance bottle neck with branch prediction enabled + ctrl |= ARM_CP15_CTRL_Z; + arm_cp15_set_control(ctrl);*/ +} + +BSP_START_TEXT_SECTION void bsp_start_hook_0( void ) +{ + uint32_t ctrl; + volatile a9mpcore_scu *scu = (volatile a9mpcore_scu *) BSP_ARM_A9MPCORE_SCU_BASE; + uint32_t cpu_id = arm_cortex_a9_get_multiprocessor_cpu_id(); + const uint32_t CORES = BSPSTARTHOOKS_MIN( + (uintptr_t) bsp_processor_count, + rtems_configuration_get_maximum_processors() ); + + assert( cpu_id < CORES ); + + if( cpu_id < CORES ) { + if( cpu_id == 0 ) { + ctrl = arm_cp15_mmu_disable( 32 ); + + ctrl &= ~( ARM_CP15_CTRL_I | ARM_CP15_CTRL_C | ARM_CP15_CTRL_Z ); + arm_cp15_set_control( ctrl ); + + /* Enable Snoop Control Unit (SCU) */ + arm_a9mpcore_start_scu_enable( scu ); + } + +#ifdef RTEMS_SMP + /* Enable cache coherency support for this processor */ + uint32_t actlr = arm_cp15_get_auxiliary_control(); + actlr |= ARM_CORTEX_A9_ACTL_SMP; + arm_cp15_set_auxiliary_control(actlr); +#endif + + if (cpu_id == 0) { + arm_a9mpcore_start_scu_invalidate(scu, cpu_id, 0xF); + } + + setup_mmu_and_cache( cpu_id ); + +#ifdef RTEMS_SMP + if (cpu_id != 0) { + arm_a9mpcore_start_set_vector_base(); + + arm_gic_irq_initialize_secondary_cpu(); + + arm_cp15_set_domain_access_control( + ARM_CP15_DAC_DOMAIN(ARM_MMU_DEFAULT_CLIENT_DOMAIN, ARM_CP15_DAC_CLIENT) + ); + _SMP_Start_multitasking_on_secondary_processor(); + } +#endif + } else { + /* FIXME: Shutdown processor */ + while (1) { + __asm__ volatile ("wfi"); + } + } +} + +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(); + + bsp_start_clear_bss(); +}
\ No newline at end of file diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/startup/linkcmds.altcycv b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/linkcmds.altcycv new file mode 100644 index 0000000000..da4275ff63 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/linkcmds.altcycv @@ -0,0 +1,26 @@ +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); + +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); + +INCLUDE linkcmds.armv4 diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/startup/linkcmds.altcycv_devkit b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/linkcmds.altcycv_devkit new file mode 100644 index 0000000000..60f99a04f9 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/linkcmds.altcycv_devkit @@ -0,0 +1,18 @@ +MEMORY { + RAM_MMU : ORIGIN = 0x00100000, LENGTH = 16k + NOCACHE : ORIGIN = 0x00200000, LENGTH = 1M + RAM : ORIGIN = 0x00300000, LENGTH = 1024M - 1M - 1M - 1M +} + +SECTIONS { + .nocache : { + bsp_section_nocache_begin = .; + *(SORT(.bsp_nocache*)) + bsp_section_nocache_end = .; + } > NOCACHE AT > NOCACHE + 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; +} + +INCLUDE linkcmds.altcycv diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/startup/linkcmds.altcycv_devkit_smp b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/linkcmds.altcycv_devkit_smp new file mode 100644 index 0000000000..2da086579f --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/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/c/src/lib/libbsp/arm/altera-cyclone-v/startup/nocache-heap.c b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/nocache-heap.c new file mode 100644 index 0000000000..0f01989b8d --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/nocache-heap.c @@ -0,0 +1,89 @@ +/** + * @file + * + * @brief Heap handling for uncached RAM + */ + +/* + * Copyright (c) 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 <assert.h> +#include <bsp/linker-symbols.h> +#include <bsp/nocache-heap.h> +#include <rtems/score/heapimpl.h> +#include <rtems/score/apimutex.h> + +/** @brief Uncached RAM pool + * + * Allocate the whole bsp_nocache for the nocache heap */ +static char nocache_pool[1024 + * 1024] __attribute__( ( section( ".bsp_nocache" ) ) ); + +/** @brief Nocache heap + * + * Heap control for the uncached RAM heap */ +static Heap_Control nocache_heap; + +/** @brief Init nocache heap + * + * Constructor for the uncached RAM heap + * @returns 0 on succuss, error code from errno.h on failure + */ +void altera_cyclone_v_nocache_init_heap( void ) +{ + uintptr_t heap_status = 0; + + heap_status = _Heap_Initialize( + &nocache_heap, + &nocache_pool[0], + sizeof( nocache_pool ), + 0 + ); + assert( heap_status != 0 ); +} + +/** @brief Allocate uncached RAM + * + * Allocates RAM from the uncached heap + * @param size Number of bytes to be allocated + * @returns Pointer to the allocated RAM + */ +void *altera_cyclone_v_nocache_malloc( const size_t size ) +{ + void* ret = NULL; + + _RTEMS_Lock_allocator(); + ret = _Heap_Allocate( &nocache_heap, size ); + _RTEMS_Unlock_allocator(); + + return ret; +} + +/** @brief Free uncached RAM + * + * Releases RAM from the uncached heap + * @param ptr Address of the RAM to be released + */ +void altera_cyclone_v_nocache_free( void *ptr ) +{ + if ( ptr != NULL ) { + bool ok; + + _RTEMS_Lock_allocator(); + ok = _Heap_Free( &nocache_heap, ptr ); + _RTEMS_Unlock_allocator(); + + assert( ok ); + } +} |