[PATCH v2] BSP for TMS570LS31x Hercules Development Kit from TI (TMS570LS3137)
Gedare Bloom
gedare at rtems.org
Mon Aug 18 13:36:18 UTC 2014
On Fri, Aug 15, 2014 at 12:32 PM, Premysl Houdek <kom541000 at gmail.com> wrote:
> Included variants:
> tms570ls3137_hdk_intram - place code and data into internal SRAM
> tms570ls3137_hdk_sdram - place code into external SDRAM and data to SRAM
> tms570ls3137_hdk - variant prepared for stand-alone RTEMS aplication
> stored and running directly from flash. Not working yet.
>
> Chip initialization code not included in BSP.
> External startup generated by TI's HalCoGen was used for
> testing and debugging.
>
> More information about TMS570 BSP can be found at
> http://www.rtems.org/wiki/index.php/Tms570
>
> Patch version 2
> - most of the formatting suggestion applied.
> - BSP converted to use clock shell
> - console driver "set attributes" tested. Baudrate change working
> Todo:
> refractor header files (name register fields)
> ---
> c/src/lib/libbsp/arm/tms570/Makefile.am | 144 +++++
> c/src/lib/libbsp/arm/tms570/README | 67 +++
> c/src/lib/libbsp/arm/tms570/bsp_specs | 13 +
> c/src/lib/libbsp/arm/tms570/clock/clock.c | 157 ++++++
> c/src/lib/libbsp/arm/tms570/configure.ac | 52 ++
> .../lib/libbsp/arm/tms570/console/printk-support.c | 85 +++
> c/src/lib/libbsp/arm/tms570/console/tms570-sci.c | 560 ++++++++++++++++++++
> c/src/lib/libbsp/arm/tms570/include/bsp.h | 102 ++++
> c/src/lib/libbsp/arm/tms570/include/irq.h | 134 +++++
> c/src/lib/libbsp/arm/tms570/include/tms570-pom.h | 101 ++++
> c/src/lib/libbsp/arm/tms570/include/tms570-rti.h | 95 ++++
> .../libbsp/arm/tms570/include/tms570-sci-driver.h | 40 ++
> c/src/lib/libbsp/arm/tms570/include/tms570-sci.h | 76 +++
> c/src/lib/libbsp/arm/tms570/include/tms570-vim.h | 75 +++
> c/src/lib/libbsp/arm/tms570/include/tms570.h | 28 +
> c/src/lib/libbsp/arm/tms570/irq/irq.c | 192 +++++++
> .../make/custom/tms570ls3137_hdk-testsuite.tcfg | 19 +
> .../arm/tms570/make/custom/tms570ls3137_hdk.cfg | 20 +
> .../tms570/make/custom/tms570ls3137_hdk_intram.cfg | 21 +
> .../tms570/make/custom/tms570ls3137_hdk_sdram.cfg | 20 +
> c/src/lib/libbsp/arm/tms570/pom/tms570-pom.c | 100 ++++
> c/src/lib/libbsp/arm/tms570/preinstall.am | 123 +++++
> c/src/lib/libbsp/arm/tms570/startup/bspreset.c | 37 ++
> c/src/lib/libbsp/arm/tms570/startup/bspstart.c | 42 ++
> .../lib/libbsp/arm/tms570/startup/bspstarthooks.c | 41 ++
> .../arm/tms570/startup/linkcmds.tms570ls3137_hdk | 27 +
> .../startup/linkcmds.tms570ls3137_hdk_intram | 28 +
> .../tms570/startup/linkcmds.tms570ls3137_hdk_sdram | 27 +
> 28 files changed, 2426 insertions(+)
> create mode 100644 c/src/lib/libbsp/arm/tms570/Makefile.am
> create mode 100644 c/src/lib/libbsp/arm/tms570/README
> create mode 100644 c/src/lib/libbsp/arm/tms570/bsp_specs
> create mode 100644 c/src/lib/libbsp/arm/tms570/clock/clock.c
> create mode 100644 c/src/lib/libbsp/arm/tms570/configure.ac
> create mode 100644 c/src/lib/libbsp/arm/tms570/console/printk-support.c
> create mode 100644 c/src/lib/libbsp/arm/tms570/console/tms570-sci.c
> create mode 100644 c/src/lib/libbsp/arm/tms570/include/bsp.h
> create mode 100644 c/src/lib/libbsp/arm/tms570/include/irq.h
> create mode 100644 c/src/lib/libbsp/arm/tms570/include/tms570-pom.h
> create mode 100644 c/src/lib/libbsp/arm/tms570/include/tms570-rti.h
> create mode 100644 c/src/lib/libbsp/arm/tms570/include/tms570-sci-driver.h
> create mode 100644 c/src/lib/libbsp/arm/tms570/include/tms570-sci.h
> create mode 100644 c/src/lib/libbsp/arm/tms570/include/tms570-vim.h
> create mode 100644 c/src/lib/libbsp/arm/tms570/include/tms570.h
> create mode 100644 c/src/lib/libbsp/arm/tms570/irq/irq.c
> create mode 100644 c/src/lib/libbsp/arm/tms570/make/custom/tms570ls3137_hdk-testsuite.tcfg
> create mode 100644 c/src/lib/libbsp/arm/tms570/make/custom/tms570ls3137_hdk.cfg
> create mode 100644 c/src/lib/libbsp/arm/tms570/make/custom/tms570ls3137_hdk_intram.cfg
> create mode 100644 c/src/lib/libbsp/arm/tms570/make/custom/tms570ls3137_hdk_sdram.cfg
> create mode 100644 c/src/lib/libbsp/arm/tms570/network/tms570-ethernet.c
> create mode 100644 c/src/lib/libbsp/arm/tms570/network/tms570-ethernet.h
> create mode 100644 c/src/lib/libbsp/arm/tms570/pom/tms570-pom.c
> create mode 100644 c/src/lib/libbsp/arm/tms570/preinstall.am
> create mode 100644 c/src/lib/libbsp/arm/tms570/startup/bspreset.c
> create mode 100644 c/src/lib/libbsp/arm/tms570/startup/bspstart.c
> create mode 100644 c/src/lib/libbsp/arm/tms570/startup/bspstarthooks.c
> create mode 100644 c/src/lib/libbsp/arm/tms570/startup/linkcmds.tms570ls3137_hdk
> create mode 100644 c/src/lib/libbsp/arm/tms570/startup/linkcmds.tms570ls3137_hdk_intram
> create mode 100644 c/src/lib/libbsp/arm/tms570/startup/linkcmds.tms570ls3137_hdk_sdram
[...]
> diff --git a/c/src/lib/libbsp/arm/tms570/clock/clock.c b/c/src/lib/libbsp/arm/tms570/clock/clock.c
> new file mode 100644
> index 0000000..3e14cb3
> --- /dev/null
> +++ b/c/src/lib/libbsp/arm/tms570/clock/clock.c
> @@ -0,0 +1,157 @@
> +/**
> + * @file clock.c
> + *
> + * @ingroup tms570
> + *
> + * @brief clock functions definitions.
> + */
> +
> +/*
> + * Copyright (c) 2014 Premysl Houdek <kom541000 at gmail.com>
> + *
> + * Google Summer of Code 2014 at
> + * Czech Technical University in Prague
> + * Zikova 1903/4
> + * 166 36 Praha 6
> + * Czech Republic
> + *
> + * Based on LPC24xx and LPC1768 BSP
> + * by embedded brains GmbH and others
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems.org/license/LICENSE.
> + */
> +
> +#include <stdlib.h>
> +
> +#include <rtems.h>
> +#include <bsp.h>
> +#include <bsp/irq.h>
> +#include <bsp/tms570-rti.h>
> +
> +/**
> + *
> + */
> +uint32_t tms570_rti_last_tick_fcr0;
> +
Make this variable static if it is only used in this file.
> +/**
> + * @brief Initialize the HW peripheral for clock driver
> + *
> + * Clock driver is implemented by RTI module
> + *
> + * @retval Void
> + */
> +static void tms570_clock_driver_support_initialize_hardware( void )
> +{
> +
> + uint32_t microsec_per_tick = rtems_configuration_get_microseconds_per_tick();
> +
> + /* Hardware specific initialize */
> + TMS570_RTI.RTIGCTRL = 0;
> + TMS570_RTI.RTICPUC0 = BSP_PLL_OUT_CLOCK /1000000 / 2; /* prescaler */
> + TMS570_RTI.RTITBCTRL = 2;
> + TMS570_RTI.RTICAPCTRL = 0;
> + TMS570_RTI.RTICOMPCTRL = 0;
> + /* set counter to zero */
> + TMS570_RTI.RTIUC0 = 0;
> + TMS570_RTI.RTIFRC0 = 0;
> + /* clear interrupts*/
> + TMS570_RTI.RTICLEARINTENA = 0x00070f0f;
> + TMS570_RTI.RTIINTFLAG = 0x0007000f;
> + /* set timer */
> + TMS570_RTI.RTICOMP0 = TMS570_RTI.RTIFRC0 + microsec_per_tick;
> + TMS570_RTI.RTICOMP0CLR = TMS570_RTI.RTICOMP0 + microsec_per_tick / 2;
> + TMS570_RTI.RTIUDCP0 = microsec_per_tick;
> + /* enable interupt */
> + TMS570_RTI.RTISETINTENA = 0x1;
> + /* enable timer */
> + TMS570_RTI.RTIGCTRL = 1;
> +}
> +
> +/**
> + * @brief Clears interrupt source
> + *
> + * @retval Void
> + */
> +static void tms570_clock_driver_support_at_tick( void )
> +{
> + TMS570_RTI.RTIINTFLAG = 0x00000001;
> + tms570_rti_last_tick_fcr0 = TMS570_RTI.RTICOMP0 - TMS570_RTI.RTIUDCP0;
> + /* TMS570_RTI.RTICOMP0 += 1000; */
Remove commented-out code that is not going to be uncommented in the
future. Otherwise add a note about the purpose of the commented-out
code.
> +}
> +
> +/**
> + * @brief registers RTI interrupt handler
> + *
> + * @param[in] Clock_isr new ISR handler
> + * @param[in] Old_ticker old ISR handler (unused and type broken)
> + *
> + * @retval Void
> + */
> +static void tms570_clock_driver_support_install_isr(
> + rtems_isr_entry Clock_isr
> +)
> +{
> + rtems_status_code sc = RTEMS_SUCCESSFUL;
> +
> + sc = rtems_interrupt_handler_install(
> + TMS570_IRQ_TIMER_0,
> + "Clock",
> + RTEMS_INTERRUPT_UNIQUE,
> + (rtems_interrupt_handler) Clock_isr,
> + NULL
> + );
> + if (sc != RTEMS_SUCCESSFUL) {
> + rtems_fatal_error_occurred(0xdeadbeef);
> + }
> +}
> +
> +/**
> + * @brief disables RTI interrupt
> + *
> + * Called when closing clock driver
> + *
> + * @retval Void
> + */
> +static void tms570_clock_driver_support_shutdown_hardware( void )
> +{
> + /* turn off the timer interrupts */
> + TMS570_RTI.RTICLEARINTENA = 0x20000;
> +}
> +
> +/**
> + * @brief returns the nanoseconds since last tick
> + *
> + * Return the nanoseconds since last tick
> + *
> + * @retval x nanoseconds
> + *
> + */
> +static uint32_t tms570_clock_driver_nanoseconds_since_last_tick( void )
> +{
> + uint32_t actual_fcr0 = TMS570_RTI.RTIFRC0;
> + uint32_t nsec_since_tick;
I guess this is actually usec (microseconds) since tick, since you
multiply by 1000 for the return value?
> +
> + nsec_since_tick = actual_fcr0 - tms570_rti_last_tick_fcr0;
> +
> + return nsec_since_tick * 1000;
> +}
> +
> +#define Clock_driver_support_initialize_hardware \
> + tms570_clock_driver_support_initialize_hardware
> +#define Clock_driver_support_at_tick \
> + tms570_clock_driver_support_at_tick
> +#define Clock_driver_support_initialize_hardware \
> + tms570_clock_driver_support_initialize_hardware
> +#define Clock_driver_support_shutdown_hardware \
> + tms570_clock_driver_support_shutdown_hardware
> +#define Clock_driver_nanoseconds_since_last_tick \
> + tms570_clock_driver_nanoseconds_since_last_tick
> +
> +#define Clock_driver_support_install_isr(Clock_isr, Old_ticker ) \
> + tms570_clock_driver_support_install_isr( Clock_isr )
> +
> +void Clock_isr(void *arg); /* to supress warning */
> +
> +#include "../../../shared/clockdrv_shell.h"
[...]
> diff --git a/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c b/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c
> new file mode 100644
> index 0000000..89e3100
> --- /dev/null
> +++ b/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c
> @@ -0,0 +1,560 @@
> +/**
> + * @file tms570-sci.c
> + *
> + * @ingroup tms570
> + *
> + * @brief Serial communication interface (SCI) functions definitions.
> + */
> +
> +/*
> + * Copyright (c) 2014 Premysl Houdek <kom541000 at gmail.com>
> + *
> + * Google Summer of Code 2014 at
> + * Czech Technical University in Prague
> + * Zikova 1903/4
> + * 166 36 Praha 6
> + * Czech Republic
> + *
> + * Based on LPC24xx and LPC1768 BSP
> + * by embedded brains GmbH and others
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems.org/license/LICENSE.
> + */
> +
> +#include <bspopts.h>
> +#include <termios.h>
> +#include <rtems/termiostypes.h>
> +#include <libchip/sersupp.h>
> +#include <bsp/tms570-sci.h>
> +#include <bsp/tms570-sci-driver.h>
> +#include <rtems/console.h>
> +#include <bsp.h>
> +#include <bsp/fatal.h>
> +#include <bsp/irq.h>
> +
> +#define TMS570_SCI_BUFFER_SIZE 1
> +
> +/**
> + * @brief Table including all serial drivers
> + *
> + * Definitions of all serial drivers
> + */
> +const tms570_sci_context driver_context_table[] = {
> + {
> + .device_name = "/dev/console",
> + .regs = &TMS570_SCI,
> + .irq = TMS570_IRQ_SCI_LEVEL_0,
> + },
> + {
> + .device_name = "/dev/ttyS1",
> + .regs = &TMS570_SCI2,
> + .irq = TMS570_IRQ_SCI2_LEVEL_0,
> + }
> +};
> +
> +/**
> + * @brief Serial drivers init function
> + *
> + * Initialize all serial drivers specified in driver_context_table
> + *
> + * @param[in] major
> + * @param[in] minor
> + * @param[in] arg
> + * @retval RTEMS_SUCCESSFUL Initialization completed
> + */
> +rtems_device_driver console_initialize(
> + rtems_device_major_number major,
> + rtems_device_minor_number minor,
> + void *arg
> +)
> +{
> + rtems_status_code sc;
> +#if CONSOLE_USE_INTERRUPTS
> + const rtems_termios_device_handler *handler = &tms570_sci_handler_interrupt;
> +#else
> + const rtems_termios_device_handler *handler = &tms570_sci_handler_polled;
> +#endif
> +
> + /*
> + * Initialize the Termios infrastructure. If Termios has already
> + * been initialized by another device driver, then this call will
> + * have no effect.
> + */
> + rtems_termios_initialize();
> +
> + /* Initialize each device */
> + for (
> + minor = 0;
> + minor < RTEMS_ARRAY_SIZE(driver_context_table);
> + ++minor
> + ) {
> + tms570_sci_context *ctx = (tms570_sci_context *) &driver_context_table[minor];
> +
> + /*
> + * Install this device in the file system and Termios. In order
> + * to use the console (i.e. being able to do printf, scanf etc.
> + * on stdin, stdout and stderr), one device must be registered as
> + * "/dev/console" (CONSOLE_DEVICE_NAME).
> + */
> + sc = rtems_termios_device_install(
> + ctx->device_name,
> + major,
> + minor,
> + handler,
> + ctx
> + );
> + if (sc != RTEMS_SUCCESSFUL) {
> + bsp_fatal(BSP_FATAL_CONSOLE_NO_DEV);
> + }
> + }
> + return RTEMS_SUCCESSFUL;
> +}
> +
> +/**
> + * @brief Reads chars from HW
> + *
> + * Reads chars from HW peripheral specified in driver context.
> + * TMS570 does not have HW buffer for serial line so this function can
> + * return only 0 or 1 char
> + *
> + * @param[in] ctx context of the driver
> + * @param[out] buf read data buffer
> + * @param[in] N size of buffer
> + * @retval x Number of read chars from peripherals
> + */
> +static int tms570_sci_read_received_chars(
> + tms570_sci_context * ctx,
> + char * buf,
> + int N)
> +{
> + if (N<1){
Fix white space, there should be a space before and after each
parenthesis and operator here, that is:
if ( N < 1 ) {
> + return 0;
> + }
> + if (ctx->regs->SCIRD != 0){
ditto.
> + buf[0] = ctx->regs->SCIRD;
> + return 1;
> + }
> + return 0;
> +}
> +
> +/**
> + * @brief Enables RX interrupt
> + *
> + * Enables RX interrupt source of SCI peripheral
> + * specified in the driver context.
> + *
> + * @param[in] ctx context of the driver
> + * @retval Void
> + */
> +static void tms570_sci_enable_interrupts(tms570_sci_context * ctx){
> + ctx->regs->SCISETINT = (1<<9);
> +}
> +
> +/**
> + * @brief Disables RX interrupt
> + *
> + * Disables RX interrupt source of SCI peripheral specified in the driver context.
> + *
> + * @param[in] ctx context of the driver
> + * @retval Void
> + */
> +static void tms570_sci_disable_interrupts(tms570_sci_context * ctx){
> + ctx->regs->SCICLEARINT = (1<<9);
> +}
> +
> +/**
> + * @brief Check whether driver has put char in HW
> + *
> + * Check whether driver has put char in HW.
> + * This information is read from the driver context not from a peripheral.
> + * TMS570 does not have write data buffer asociated with SCI
> + * so the return can be only 0 or 1.
> + *
> + * @param[in] ctx context of the driver
> + * @retval x
> + */
> +static int tms570_sci_transmitted_chars(tms570_sci_context * ctx)
> +{
> + int ret;
> +
> + ret = ctx->tx_chars_in_hw;
> + if ( ret == 1 ){
> + ctx->tx_chars_in_hw = 0;
> + return 1;
> + }
> + return ret;
> +}
> +
> +/**
> + * @brief Set attributes of the HW peripheral
> + *
> + * Sets attributes of the HW peripheral (parity, baud rate, etc.)
> + * TODO: untested function
> + *
> + * @param[in] tty rtems_termios_tty
> + * @param[in] t termios driver
> + * @retval true peripheral setting is changed
> + */
> +static bool tms570_sci_set_attributes(
> + rtems_termios_tty *tty,
> + const struct termios *t
> +)
> +{
> +
> + tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
> + rtems_interrupt_lock_context lock_context;
> + int32_t bauddiv;
> + int32_t baudrate;
> +
> + rtems_termios_interrupt_lock_acquire(tty, &lock_context);
> +
> + ctx->regs->SCIGCR1 &= ~( (1<<7) | (1<<25) | (1<<24) );
> +
> + ctx->regs->SCIGCR1 &= ~(1<<4); /*one stop bit*/
> + ctx->regs->SCIFORMAT = 0x7;
> +
> + switch (t->c_cflag & (PARENB|PARODD)) {
> + case (PARENB|PARODD):
> + /* Odd parity */
> + ctx->regs->SCIGCR1 &= ~(1<<3);
> + ctx->regs->SCIGCR1 |= (1<<2);
> + break;
> +
> + case PARENB:
> + /* Even parity */
> + ctx->regs->SCIGCR1 |= (1<<3);
> + ctx->regs->SCIGCR1 |= (1<<2);
> + break;
> +
> + default:
> + case 0:
> + case PARODD:
> + /* No Parity */
> + ctx->regs->SCIGCR1 &= ~(1<<2);
> + }
> +
> + /* Baud rate */
> + baudrate = rtems_termios_baud_to_number(cfgetospeed(t));
> + baudrate *= 2 * 16;
> + bauddiv = (BSP_PLL_OUT_CLOCK + baudrate / 2) / baudrate;
> + ctx->regs->BRS = bauddiv;
> +
> + ctx->regs->SCIGCR1 |= (1<<7) | (1<<25) | (1<<24);
> +
> + rtems_termios_interrupt_lock_release(tty, &lock_context);
> +
> + return true;
> +}
> +
> +/**
> + * @brief sci interrupt handler
> + *
> + * Handler checks which interrupt occured and provides nessesary maintenance
> + * dequeue characters in termios driver whether character is send succesfully
> + * enqueue characters in termios driver whether character is recieved
> + *
> + * @param[in] arg rtems_termios_tty
> + * @retval Void
> + */
> +static void tms570_sci_interrupt_handler(void * arg){
> + rtems_termios_tty *tty = arg;
> + tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
> + char buf[TMS570_SCI_BUFFER_SIZE];
> + size_t n;
> +
> + /*
> + * Check if we have received something.
> + */
> + if ( (ctx->regs->SCIFLR & (1<<9) ) == (1<<9) ){
> + n = tms570_sci_read_received_chars(ctx, buf, TMS570_SCI_BUFFER_SIZE);
> + if (n > 0) {
> + /* Hand the data over to the Termios infrastructure */
> + rtems_termios_enqueue_raw_characters(tty, buf, n);
> + }
> + }
> + /*
> + * Check if we have something transmitted.
> + */
> + if ( (ctx->regs->SCIFLR & (1<<8) ) == (1<<8) ){
> + n = tms570_sci_transmitted_chars(ctx);
> + if (n > 0) {
> + /*
> + * Notify Termios that we have transmitted some characters. It
> + * will call now the interrupt write function if more characters
> + * are ready for transmission.
> + */
> + rtems_termios_dequeue_characters(tty, n);
> + }
> + }
> +}
> +
> +/**
> + * @brief sci write function called from interrupt
> + *
> + * Nonblocking write function. Writes characters to HW peripheral
> + * TMS570 does not have write data buffer asociated with SCI
> + * so only one character can be written.
> + *
> + * @param[in] tty rtems_termios_tty
> + * @param[in] buf buffer of characters pending to send
> + * @param[in] len size of the buffer
> + * @retval Void
> + */
> +static void tms570_sci_interrupt_write(
> + rtems_termios_tty *tty,
> + const char *buf,
> + size_t len
> +)
> +{
> + tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
> +
> + if (len > 0) {
> + /* start UART TX, this will result in an interrupt when done */
> + ctx->regs->SCITD = *buf;
> + /* character written - raise count*/
> + ctx->tx_chars_in_hw = 1;
> + /* Enable TX interrupt (interrupt is edge-triggered) */
> + ctx->regs->SCISETINT = (1<<8);
> +
> + } else {
> + /* No more to send, disable TX interrupts */
> + ctx->regs->SCICLEARINT = (1<<8);
> + /* Tell close that we sent everything */
> + }
> +}
> +
> +/**
> + * @brief sci write function
> + *
> + * Blocking write function. Waits until HW peripheral is ready and then writes
> + * character to HW peripheral. Writes all characters in the buffer.
> + *
> + * @param[in] tty rtems_termios_tty
> + * @param[in] buf buffer of characters pending to send
> + * @param[in] len size of the buffer
> + * @retval Void
> + */
> +static void tms570_sci_poll_write(
> + rtems_termios_tty *tty,
> + const char *buf,
> + size_t n
> +)
> +{
> + tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
> + size_t i;
> +
> + /* Write */
> +
> + for (i = 0; i < n; ++i) {
> + while ( (ctx->regs->SCIFLR & (1<<11) ) == 0) {
> + ;
> + }
> + ctx->regs->SCITD = buf[i];
> + }
> +}
> +
> +/**
> + * @brief See if there is recieved charakter to read
> + *
> + * read the RX flag from peripheral specified in context
> + *
> + * @param[in] ctx context of the driver
> + * @retval 0 No character to read
> + * @retval x Character ready to read
> + */
> +static int TMS570_sci_can_read_char(
> + tms570_sci_context * ctx
> +)
> +{
> + return ctx->regs->SCIFLR & (1<<9);
> +}
> +
> +/**
> + * @brief reads character from peripheral
> + *
> + * reads the recieved character from peripheral specified in context
> + *
> + * @param[in] ctx context of the driver
> + * @retval x Character
> + */
> +static char TMS570_sci_read_char(
> + tms570_sci_context * ctx
> +)
> +{
> + return ctx->regs->SCIRD;
> +}
> +
> +/**
> + * @brief sci read function
> + *
> + * check if there is recieved character to be read and reads it.
> + *
> + * @param[in] tty rtems_termios_tty (context of the driver)
> + * @retval -1 No character to be read
> + * @retval x Read character
> + */
> +static int tms570_sci_poll_read(rtems_termios_tty *tty)
> +{
> + tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
> +
> + /* Check if a character is available */
> + if (TMS570_sci_can_read_char(ctx)) {
> + return TMS570_sci_read_char(ctx);
> + } else {
> + return -1;
> + }
> +}
> +
> +/**
> + * @brief initialization of the driver
> + *
> + * initialization of the HW peripheral specified in contex of the driver.
> + * This function is called only once when opening the driver.
> + *
> + * @param[in] tty context of the driver
> + * @param[in] args
> + * @retval false Error occured during initialization
> + * @retval true Driver is open and ready
> + */
> +static bool tms570_sci_poll_first_open(
> + rtems_termios_tty *tty,
> + rtems_libio_open_close_args_t *args
> +)
> +{
> + bool ok;
> + tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
> + /* TODO: test peripheral startup code below
> + ctx->regs->SCISETINTLVL = 0;
> + */
> + rtems_termios_set_best_baud(tty, TMS570_SCI_BAUD_RATE);
> + ok = tms570_sci_set_attributes(tty, rtems_termios_get_termios(tty));
> + if ( !ok ) {
> + return false;
> + }
> + return true;
> +}
> +
> +/**
> + * @brief initialization of the interrupt driven driver
> + *
> + * calls tms570_sci_poll_first_open function.
> + * install and enables interrupts.
> + *
> + * @param[in] tty context of the driver
> + * @param[in] args
> + * @retval false Error occured during initialization
> + * @retval true Driver is open and ready
> + */
> +static bool tms570_sci_interrupt_first_open(
> + rtems_termios_tty *tty,
> + rtems_libio_open_close_args_t *args
> +)
> +{
> + tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
> + rtems_status_code sc;
> + bool ret;
> +
> + ret = tms570_sci_poll_first_open(tty,args);
> + if ( ret == false ){
> + return false;
> + }
> + /* Register Interrupt handler */
> + sc = rtems_interrupt_handler_install(ctx->irq,
> + ctx->device_name,
> + RTEMS_INTERRUPT_SHARED,
> + tms570_sci_interrupt_handler,
> + tty);
Continuation lines get just an extra double-indent (4 spaces). Also,
put the closing ); on its own line without extra indentation.
> + if ( sc != RTEMS_SUCCESSFUL )
> + return false;
> + tms570_sci_enable_interrupts(rtems_termios_get_device_context(tty));
> + return true;
> +}
> +
> +/**
> + * @brief closes sci peripheral
> + *
> + * @param[in] tty context of the driver
> + * @param[in] args
> + * @retval false Error occured during initialization
> + * @retval true Driver is open and ready
> + */
> +static void tms570_sci_poll_last_close(
> + rtems_termios_tty *tty,
> + rtems_libio_open_close_args_t *args
> +)
> +{
> + /*tms570_sci_context *ctx = rtems_termios_get_device_context(tty);*/
> +
> + /* TODO: Here shall be peripheral HW reset, someday */
> +
> +}
> +
> +/**
> + * @brief closes sci peripheral of interrupt driven driver
> + *
> + * calls tms570_sci_poll_last_close and disables interrupts
> + *
> + * @param[in] tty context of the driver
> + * @param[in] args
> + * @retval false Error occured during initialization
> + * @retval true Driver is open and ready
> + */
> +static void tms570_sci_interrupt_last_close(
> + rtems_termios_tty *tty,
> + rtems_libio_open_close_args_t *args
> +)
> +{
> + tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
> + rtems_interrupt_lock_context lock_context;
> +
> + /* Turn off RX interrupts */
> + rtems_termios_interrupt_lock_acquire(tty, &lock_context);
> + tms570_sci_disable_interrupts(ctx);
> + rtems_termios_interrupt_lock_release(tty, &lock_context);
> +
> + /* Flush device */
> + while ((ctx->regs->SCIFLR & (1<<11)) > 0) {
> + ;/* Wait until all data has been sent */
> + }
> +
> + /* uninstall ISR */
> + rtems_interrupt_handler_remove(ctx->irq, tms570_sci_interrupt_handler, tty);
> +
> + tms570_sci_poll_last_close(tty,args);
> +}
> +
> +/**
> + * @brief Struct containing definitions of polled driver functions.
> + *
> + * Encapsulates polled driver functions.
> + * Use of this table is determited by not defining TMS570_USE_INTERRUPTS
> + */
> +const rtems_termios_device_handler tms570_sci_handler_polled = {
> + .first_open = tms570_sci_poll_first_open,
> + .last_close = tms570_sci_poll_last_close,
> + .poll_read = tms570_sci_poll_read,
> + .write = tms570_sci_poll_write,
> + .set_attributes = tms570_sci_set_attributes,
> + .stop_remote_tx = NULL,
> + .start_remote_tx = NULL,
> + .mode = TERMIOS_POLLED
> +};
> +
> +/**
> + * @brief Struct containing definitions of interrupt driven driver functions.
> + *
> + * Encapsulates interrupt driven driver functions.
> + * Use of this table is determited by defining TMS570_USE_INTERRUPTS
> + */
> +const rtems_termios_device_handler tms570_sci_handler_interrupt = {
> + .first_open = tms570_sci_interrupt_first_open,
> + .last_close = tms570_sci_interrupt_last_close,
> + .poll_read = NULL,
> + .write = tms570_sci_interrupt_write,
> + .set_attributes = tms570_sci_set_attributes,
> + .stop_remote_tx = NULL,
> + .start_remote_tx = NULL,
> + .mode = TERMIOS_IRQ_DRIVEN
> +};
> diff --git a/c/src/lib/libbsp/arm/tms570/include/bsp.h b/c/src/lib/libbsp/arm/tms570/include/bsp.h
> new file mode 100644
> index 0000000..fccfca5
> --- /dev/null
> +++ b/c/src/lib/libbsp/arm/tms570/include/bsp.h
> @@ -0,0 +1,102 @@
> +/**
> + * @file bsp.h
> + *
> + * @ingroup tms570
> + *
> + * @brief Global BSP definitions.
> + */
> +
> +/*
> + * Copyright (c) 2014 Premysl Houdek <kom541000 at gmail.com>
> + *
> + * Google Summer of Code 2014 at
> + * Czech Technical University in Prague
> + * Zikova 1903/4
> + * 166 36 Praha 6
> + * Czech Republic
> + *
> + * Based on LPC24xx and LPC1768 BSP
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems.org/license/LICENSE.
> + */
> +
> +#ifndef LIBBSP_ARM_TMS570_BSP_H
> +#define LIBBSP_ARM_TMS570_BSP_H
> +
> +#include <bspopts.h>
> +
> +#define TMS570_PCLK ( TMS570_CCLK / TMS570_PCLKDIV )
> +#define TMS570_MPU_REGION_COUNT 8u
> +
> +#define BSP_FEATURE_IRQ_EXTENSION
> +
> +#ifndef ASM
> +
> +#include <rtems.h>
> +#include <rtems/console.h>
> +#include <rtems/clockdrv.h>
> +#include <bsp/default-initial-extension.h>
> +
> +#define BSP_OSCILATOR_CLOCK 8000000
> +#define BSP_PLL_OUT_CLOCK 160000000
> +
> +/** Define operation count for Tests */
> +#define OPERATION_COUNT 4
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif /* __cplusplus */
> +
> +struct rtems_bsdnet_ifconfig;
> +
> +/**
> + * @defgroup tms570 TMS570 Support
> + *
> + * @ingroup bsp_arm
> + *
> + * @brief TMS570 support package.
> + *
> + * @{
> + */
> +
> +/**
> + * @brief Optimized idle task.
> + *
> + * This idle task sets the power mode to idle. This causes the processor
> + * clock to be stopped, while on-chip peripherals remain active.
> + * Any enabled interrupt from a peripheral or an external interrupt source
> + * will cause the processor to resume execution.
> + *
> + * To enable the idle task use the following in the system configuration:
> + *
> + * @code
> + * #include <bsp.h>
> + *
> + * #define CONFIGURE_INIT
> + *
> + * #define CONFIGURE_IDLE_TASK_BODY bsp_idle_thread
> + *
> + * #include <confdefs.h>
> + * @endcode
> + */
Do we need all this documentation copied here?
> +void* bsp_idle_thread( uintptr_t ignored );
> +
> +
> +
Remove extra blank lines.
> +/**
> + * @brief Restarts the bsp with "addr" address
> + * @param addr Address used to restart the bsp
> + */
> +void bsp_restart( const void *addr );
> +
> +/** @} */
> +
> +#ifdef __cplusplus
> +}
> +#endif /* __cplusplus */
> +
> +#endif /* ASM */
> +
> +#endif /* LIBBSP_ARM_TMS570_BSP_H */
> diff --git a/c/src/lib/libbsp/arm/tms570/include/tms570-pom.h b/c/src/lib/libbsp/arm/tms570/include/tms570-pom.h
> new file mode 100644
> index 0000000..e1bbbcb
> --- /dev/null
> +++ b/c/src/lib/libbsp/arm/tms570/include/tms570-pom.h
> @@ -0,0 +1,101 @@
> +/**
> + * @file tms570-pom.h
> + * @ingroup tms570
> + * @brief Parameter Overlay Module (POM) header file
> + */
> +
> +/*
> + * Copyright (c) 2014 Pavel Pisa <pisa at cmp.felk.cvut.cz>
> + *
> + * Czech Technical University in Prague
> + * Zikova 1903/4
> + * 166 36 Praha 6
> + * Czech Republic
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems.org/license/LICENSE.
> + */
> +
> +
> +#ifndef LIBBSP_ARM_TMS570_POM_H
> +#define LIBBSP_ARM_TMS570_POM_H
> +
> +#include <stdint.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif /* __cplusplus */
> +
> +#define TMS570_POM_REGIONS 32
> +#define TMS570_POM_GLBCTRL_ENABLE 0x000000a0a
> +
> +#define TMS570_POM_REGSIZE_DISABLED 0
> +#define TMS570_POM_REGSIZE_64B 1
> +#define TMS570_POM_REGSIZE_128B 2
> +#define TMS570_POM_REGSIZE_256B 3
> +#define TMS570_POM_REGSIZE_5120B 4
> +#define TMS570_POM_REGSIZE_1KB 5
> +#define TMS570_POM_REGSIZE_2KB 6
> +#define TMS570_POM_REGSIZE_4KB 7
> +#define TMS570_POM_REGSIZE_8KB 8
> +#define TMS570_POM_REGSIZE_16KB 9
> +#define TMS570_POM_REGSIZE_32KB 0xa
> +#define TMS570_POM_REGSIZE_64KB 0xb
> +#define TMS570_POM_REGSIZE_128KB 0xc
> +#define TMS570_POM_REGSIZE_256KB 0xd
> +
These defines would look nicer if you used either decimal or hex.
> diff --git a/c/src/lib/libbsp/arm/tms570/irq/irq.c b/c/src/lib/libbsp/arm/tms570/irq/irq.c
> new file mode 100644
> index 0000000..87771b8
> --- /dev/null
> +++ b/c/src/lib/libbsp/arm/tms570/irq/irq.c
> @@ -0,0 +1,192 @@
> +/**
> + * @file irq.c
> + *
> + * @ingroup tms570
> + *
> + * @brief TMS570 interrupt support functions definitions.
> + */
> +
> +/*
> + * Copyright (c) 2014 Premysl Houdek <kom541000 at gmail.com>
> + *
> + * Google Summer of Code 2014 at
> + * Czech Technical University in Prague
> + * Zikova 1903/4
> + * 166 36 Praha 6
> + * Czech Republic
> + *
> + * Based on LPC24xx and LPC1768 BSP
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems.org/license/LICENSE.
> + */
> +
> +#include <rtems/score/armv4.h>
> +
> +#include <bsp.h>
> +#include <bsp/irq-generic.h>
> +#include <bsp/tms570-vim.h>
> +#include <bsp/irq.h>
> +#include <rtems/score/armv4.h>
> +
> +/**
> + * @brief Check if isr vector is valid
> + *
> + * Check if isr vector is valid by using BSP_INTERRUPT_VECTOR_MAX and
> + * BSP_INTERRUPT_VECTOR_MIN defined in irq.h
> + *
> + * @param[in] vector interrupt vector to be checked.
> + * @retval TRUE vector is valid.
> + * @retval FALSE vector is invalid
> + */
> +static inline bool tms570_irq_is_valid(
> + rtems_vector_number vector
> +)
> +{
> + return (vector <= BSP_INTERRUPT_VECTOR_MAX) &&
> + (vector > BSP_INTERRUPT_VECTOR_MIN);
> +}
> +
> +unsigned int priorityTable[BSP_INTERRUPT_VECTOR_MAX+1];
> +
> +/**
> + * @brief Set priority of the interrupt vector.
> + *
> + * This function is here because of compability. It should set
> + * priority of the interrupt vector.
> + * @warning It does not set any priority at HW layer. It is nearly imposible to
> + * @warning set priority of the interrupt on TMS570 in a nice way.
> + * @param[in] vector vector of isr
> + * @param[in] priority new priority assigned to the vector
> + * @return Void
> + */
> +void tms570_irq_set_priority(
> + rtems_vector_number vector,
> + unsigned priority
> +)
> +{
> + if (tms570_irq_is_valid(vector)) {
> + priorityTable[vector] = priority;
> + }
> +}
> +
> +/**
> + * @brief Gets priority of the interrupt vector.
> + *
> + * This function is here because of compability. It returns priority
> + * of the isr vector last set by tms570_irq_set_priority function.
> + *
> + * @warning It does not return any real priority of the HW layer.
> + * @param[in] vector vector of isr
> + * @retval 0 vector is invalid.
> + * @retval priority priority of the interrupt
> + */
> +unsigned tms570_irq_get_priority(
> + rtems_vector_number vector
> +)
> +{
> + if (tms570_irq_is_valid(vector)) {
> + return priorityTable[vector];
> + }
> + return 0;
> +}
> +
> +/**
> + * @brief Interrupt dispatch
> + *
> + * Called by OS to determine which interrupt occured.
> + * Function passes control to interrupt handler.
> + *
> + * @return Void
> + */
> +void bsp_interrupt_dispatch(void)
> +{
> + rtems_vector_number vector = TMS570_VIM.IRQINDEX-1;
> +
> + bsp_interrupt_handler_dispatch(vector);
> +}
> +
> +/**
> + * @brief enables interrupt vector in the HW
> + *
> + * Enables HW interrupt for specified vector
> + *
> + * @param[in] vector vector of the isr which needs to be enabled.
> + * @retval RTEMS_INVALID_ID vector is invalid.
> + * @retval RTEMS_SUCCESSFUL interrupt source enabled.
> + */
> +rtems_status_code bsp_interrupt_vector_enable(
> + rtems_vector_number vector
> +)
> +{
> + if(!tms570_irq_is_valid(vector))
> + return RTEMS_INVALID_ID;
> +
> + TMS570_VIM.REQENASET[vector >> 5] = 1 << (vector & 0x1f);
> +
> + return RTEMS_SUCCESSFUL;
> +}
> +
> +/**
> + * @brief disables interrupt vector in the HW
> + *
> + * Disables HW interrupt for specified vector
> + *
> + * @param[in] vector vector of the isr which needs to be disabled.
> + * @retval RTEMS_INVALID_ID vector is invalid.
> + * @retval RTEMS_SUCCESSFUL interrupt source disabled.
> + */
> +rtems_status_code bsp_interrupt_vector_disable(
> + rtems_vector_number vector
> +)
> +{
> + if(!tms570_irq_is_valid(vector))
> + return RTEMS_INVALID_ID;
> +
> + TMS570_VIM.REQENACLR[vector >> 5] = 1 << (vector & 0x1f);
> +
> + return RTEMS_SUCCESSFUL;
> +}
> +
> +/**
> + * @brief Init function of interrupt module
> + *
> + * Resets vectored interrupt interface to default state.
> + * Disables all interrupts.
> + * Set all sources as IRQ (not FIR).
> + *
> + * @retval RTEMS_SUCCESSFUL All is set
> + */
> +rtems_status_code bsp_interrupt_facility_initialize(void)
> +{
> + void (**vim_vec)(void) = (void (**)(void)) 0xFFF82000;
> + unsigned int value = 0x00010203;
> + unsigned int i = 0;
> + uint32_t sctlr;
> +
> + /* Disable interrupts */
> + for(i = 0; i < 3; i++)
> + TMS570_VIM.REQENACLR[i] = 0xffffffff;
> + /* Map default events on interrupt vectors */
> + for(i=0;i<24;i+=1,value += 0x04040404)
Add more white space around the parens and operators. Also, I believe
RTEMS prefers to always use { } even if there is only one line
following the conditional/loop statement. Perhaps this is not
explicitly stated though.
> + TMS570_VIM.CHANCTRL[i] = value;
> + /* Set all vectors as IRQ (not FIR) */
> + TMS570_VIM.FIRQPR[0] = 3;
> + TMS570_VIM.FIRQPR[1] = 0;
> + TMS570_VIM.FIRQPR[2] = 0;
> +
> + /*_CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL);*/
> + for(i = 0; i <= 94; i++)
> + vim_vec[i] = _ARMV4_Exception_interrupt;
> +
> + /* Clear bit VE in SCTLR register to not use VIM IRQ exception bypass*/
> + asm volatile ("mrc p15, 0, %0, c1, c0, 0\n": "=r" (sctlr));
> + sctlr &= ~(1 << 24);
> + asm volatile ("mcr p15, 0, %0, c1, c0, 0\n": : "r" (sctlr));
> +
> + return RTEMS_SUCCESSFUL;
> +}
> +
> +
> +
Remove extra blank lines.
> diff --git a/c/src/lib/libbsp/arm/tms570/network/tms570-ethernet.c b/c/src/lib/libbsp/arm/tms570/network/tms570-ethernet.c
> new file mode 100644
> index 0000000..e69de29
> diff --git a/c/src/lib/libbsp/arm/tms570/network/tms570-ethernet.h b/c/src/lib/libbsp/arm/tms570/network/tms570-ethernet.h
> new file mode 100644
> index 0000000..e69de29
Empty files?
> diff --git a/c/src/lib/libbsp/arm/tms570/pom/tms570-pom.c b/c/src/lib/libbsp/arm/tms570/pom/tms570-pom.c
> new file mode 100644
> index 0000000..be2d904
> --- /dev/null
> +++ b/c/src/lib/libbsp/arm/tms570/pom/tms570-pom.c
> @@ -0,0 +1,100 @@
> +/**
> + * @file tms570-pom.c
> + *
> + * @ingroup tms570
> + *
> + * @brief TMS570 Parameter Overlay Module functions definitions.
> + */
> +
> + /*
> + * Copyright (c) 2014 Pavel Pisa <pisa at cmp.felk.cvut.cz>
> + *
> + * Czech Technical University in Prague
> + * Zikova 1903/4
> + * 166 36 Praha 6
> + * Czech Republic
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems.org/license/LICENSE.
> + */
> +
> +#include <stdint.h>
> +#include <bsp/tms570-pom.h>
> +#include <bsp/linker-symbols.h>
> +#include <bsp.h>
> +
> +/**
> + * @brief Prints part of the memory
> + *
> + * debug function
> + *
> + * @retval 0
> + */
> +int mem_dump(void *buf, unsigned long start, unsigned long len, int blen)
> +{
> + unsigned long addr=start;
> + volatile unsigned char *p=buf;
> + int i;
> +
> + while ( len ){
> + printk("%08lX:",addr);
> + i=len>16?16:len;
> + addr+=i;
> + len-=i;
> + while(i>0){
Add whitespace.
> + i -= blen;
> + switch(blen){
> + case 4:
> + printk("%08lX%c",(unsigned long)*(volatile uint32_t*)p,i>0?' ':'\n');
> + break;
> + case 2:
> + printk("%04X%c",*(volatile uint16_t*)p,i>0?' ':'\n');
> + break;
> + default:
> + printk("%02X%c",*(volatile uint8_t*)(p),i>0?' ':'\n');
> + break;
> + }
> + p += blen;
> + }
> + }
> + return 0;
> +}
> +
> +/**
> + * @brief remaps vector table
> + *
> + * transfer the rtems start vector table to address 0x0
> + *
> + * @retval Void
> + */
> +void tms570_pom_remap(void)
> +{
> +
Delete blank line here. Shouldn't be one at start of function.
> + int i;
> + uint32_t vec_overlay_start = 0x08000000;
> +
> + memcpy((void*)vec_overlay_start, bsp_start_vector_table_begin, 64);
> +
> + TMS570_POM.GLBCTRL = 0;
> +
> + for (i = 0; i < TMS570_POM_REGIONS; i++)
> + TMS570_POM.REG[i].REGSIZE = TMS570_POM_REGSIZE_DISABLED;
> +
> + TMS570_POM.REG[0].PROGSTART = 0x0 & TMS570_POM_REGADDRMASK;
> + TMS570_POM.REG[0].OVLSTART = vec_overlay_start & TMS570_POM_REGADDRMASK;
> + TMS570_POM.REG[0].REGSIZE = TMS570_POM_REGSIZE_64B;
> +
> + TMS570_POM.GLBCTRL = TMS570_POM_GLBCTRL_ENABLE |
> + (vec_overlay_start & ~TMS570_POM_REGADDRMASK);
> +
> +#ifdef POM_REMAP_TEST
> + p32[1] = 0xe12fff1e;
> +
> + mem_dump((uint8_t *)0x00000000, 0x00000000, 256, 1);
> +
> + printk("Probing call to address 0x00000004\n");
> + ((void(*)(void))4)();
> + printk("POM call really returned\n");
> +#endif /*POM_REMAP_TEST*/
> +}
-Gedare
More information about the devel
mailing list