Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subsystem for different uart implementations (e.g. peripheral UART and one over USB) #4163

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions boards/frdm-k64f/include/periph_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,12 @@ extern "C"
* @name UART configuration
* @{
*/
#if MODULE_USBDEV
#define UART_NUMOF (2U)
#define UART_ACM_0_EN 1
#else
#define UART_NUMOF (1U)
#endif
#define UART_0_EN 1
#define UART_IRQ_PRIO 1
#define UART_CLK CLOCK_CORECLOCK
Expand Down
5 changes: 5 additions & 0 deletions boards/pba-d-01-kw2x/include/periph_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,12 @@ extern "C"
* @name UART configuration
* @{
*/
#if MODULE_USBDEV
#define UART_NUMOF (2U)
#define UART_ACM_0_EN 1
#else
#define UART_NUMOF (1U)
#endif
#define UART_0_EN 1
#define UART_1_EN 0
#define UART_IRQ_PRIO 1
Expand Down
52 changes: 52 additions & 0 deletions core/include/init.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2015 PHYTEC Messtechnik GmbH
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @addtogroup core_util
* @{
*
* @file
* @brief Macros for initialisation of subsystem and drivers
*
* @author Johann Fischer <j.fischer@phytec.de>
*/

#ifndef INIT_H_
#define INIT_H_

#ifdef __cplusplus
extern "C" {
#endif

#define INIT_ORDER_CORE 0
#define INIT_ORDER_DRIVER 1
#define INIT_ORDER_SUBMOD 2
#define INIT_ORDER_MODULE 3

typedef int (*initcall_t)(void);

#define __system_initcall(name, fp, order) static initcall_t __initcall_##fp##order \
__attribute__((__used__)) \
__attribute__((section(".preinit_array." #order "." name))) \
__attribute__((aligned(sizeof(void*)))) = fp

#define core_init(fp) __system_initcall("core", fp, 0)

#define driver_init(fp) __system_initcall("driver", fp, 1)

#define submod_init(fp) __system_initcall("submod", fp, 2)

#define module_init(fp) __system_initcall("module", fp, 3)


#ifdef __cplusplus
}
#endif

#endif /* INIT_H_ */
/** @} */
26 changes: 15 additions & 11 deletions cpu/cortexm_common/ldscripts/cortexm_base.ld
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,18 @@ SECTIONS
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(SORT(.preinit_array.*)))
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);

. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);

. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
Expand All @@ -69,10 +72,11 @@ SECTIONS
KEEP(*(.fini))

. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
/* fini data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);

KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
Expand Down
1 change: 1 addition & 0 deletions cpu/kinetis_common/Makefile.include
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export INCLUDES += -I$(RIOTCPU)/kinetis_common/include
export LINKFLAGS += -L$(RIOTCPU)/kinetis_common/ldscripts

# add the CPU specific code for the linker
export UNDEF += $(BINDIR)kinetis_common/uart.o
export UNDEF += $(BINDIR)kinetis_common/fcfield.o

# include kinetis common periph drivers
Expand Down
44 changes: 39 additions & 5 deletions cpu/kinetis_common/periph/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "cpu.h"
#include "thread.h"
#include "sched.h"
#include "init.h"
#include "periph_conf.h"
#include "periph/uart.h"

Expand Down Expand Up @@ -53,12 +54,12 @@ static inline void kinetis_set_brfa(KINETIS_UART *dev, uint32_t baudrate, uint32
#endif
}

static int init_base(uart_t uart, uint32_t baudrate);
static int hw_init_base(uart_t uart, uint32_t baudrate);

int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
int hw_uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
{
/* do basic initialization */
int res = init_base(uart, baudrate);
int res = hw_init_base(uart, baudrate);

if (res < 0) {
return res;
Expand Down Expand Up @@ -95,7 +96,7 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
return 0;
}

static int init_base(uart_t uart, uint32_t baudrate)
static int hw_init_base(uart_t uart, uint32_t baudrate)
{
KINETIS_UART *dev;
PORT_Type *port;
Expand Down Expand Up @@ -182,7 +183,7 @@ static int init_base(uart_t uart, uint32_t baudrate)
return 0;
}

void uart_write(uart_t uart, const uint8_t *data, size_t len)
void hw_uart_write(uart_t uart, const uint8_t *data, size_t len)
{
KINETIS_UART *dev;

Expand Down Expand Up @@ -253,3 +254,36 @@ void UART_1_ISR(void)
irq_handler(UART_1, UART_1_DEV);
}
#endif

#if UART_0_EN
uartdev_ops_t kinetis_uart0_ops = {
.dev = UART_0,
.uart_init = hw_uart_init,
.uart_write = hw_uart_write,
.uart_poweron = NULL,
.uart_poweroff = NULL,
};
#endif

#if UART_1_EN
uartdev_ops_t kinetis_uart1_ops = {
.dev = UART_1,
.uart_init = hw_uart_init,
.uart_write = hw_uart_write,
.uart_poweron = NULL,
.uart_poweroff = NULL,
};
#endif

int kinetis_uart_init (void)
{
#if UART_0_EN
uartdev_register_driver(&kinetis_uart0_ops);
#endif
#if UART_1_EN
uartdev_register_driver(&kinetis_uart1_ops);
#endif
return 0;
}

driver_init(kinetis_uart_init);
6 changes: 6 additions & 0 deletions drivers/include/periph/dev_enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,12 @@ enum {
#endif
#if UART_6_EN
UART_6, /**< UART 6 */
#endif
#if UART_ACM_0_EN
UART_ACM_0, /**< UART 0 over USB */
#endif
#if UART_ACM_1_EN
UART_ACM_1, /**< UART 1 over USB */
#endif
UART_UNDEFINED /**< Deprecated symbol, use UART_UNDEF instead */
};
Expand Down
19 changes: 19 additions & 0 deletions drivers/include/periph/uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,25 @@ void uart_poweron(uart_t uart);
*/
void uart_poweroff(uart_t uart);

/**
* @brief uart device extended API definition.
*
* @details This is a set of functions that must be implemented by any driver.
*/
typedef struct {
uart_t dev;

int (*uart_init)(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg);

void (*uart_write)(uart_t uart, const uint8_t *data, size_t len);

void (*uart_poweron)(uart_t uart);

void (*uart_poweroff)(uart_t uart);
} uartdev_ops_t;

int uartdev_register_driver(uartdev_ops_t *uart_ops);

#ifdef __cplusplus
}
#endif
Expand Down
4 changes: 4 additions & 0 deletions sys/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ ifneq (,$(filter sema,$(USEMODULE)))
DIRS += sema
endif

ifneq (,$(filter uart,$(USEMODULE)))
DIRS += uart
endif

DIRS += $(dir $(wildcard $(addsuffix /Makefile, ${USEMODULE})))

include $(RIOTBASE)/Makefile.base
1 change: 1 addition & 0 deletions sys/uart/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base
74 changes: 74 additions & 0 deletions sys/uart/uart.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright (C) 2015 PHYTEC Messtechnik GmbH
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/

/**
* @defgroup driver_periph_extended_uart UART
* @ingroup driver_periph
* @brief Low-level extended UART peripheral driver
*
* @{
*
* @file
* @brief Low-level UART driver implementation
*
* @author Johann Fischer <j.fischer@phytec.de>
*
* @}
*/

#include <stdint.h>
#include <stdio.h>

#include "periph/uart.h"


static uartdev_ops_t *uartdev_lt[UART_NUMOF];

int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
{
if (uartdev_lt[uart]) {
return uartdev_lt[uart]->uart_init(uart, baudrate, rx_cb, arg);
}
return -1;
}

void uart_write(uart_t uart, const uint8_t *data, size_t len)
{
if (uartdev_lt[uart]) {
uartdev_lt[uart]->uart_write(uart, data, len);
}
}

void uart_poweron(uart_t uart)
{
if (uartdev_lt[uart]) {
uartdev_lt[uart]->uart_poweron(uart);
}
}


void uart_poweroff(uart_t uart)
{
if (uartdev_lt[uart]) {
uartdev_lt[uart]->uart_poweroff(uart);
}
}


int uartdev_register_driver(uartdev_ops_t *uart_ops)
{
if (uart_ops->dev > UART_NUMOF) {
return -1;
}

if (uartdev_lt[uart_ops->dev] == NULL) {
uartdev_lt[uart_ops->dev] = uart_ops;
return 0;
}
return -1;
}
12 changes: 12 additions & 0 deletions tests/init/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
APPLICATION = init_test
include ../Makefile.tests_common

USEMODULE += shell
USEMODULE += shell_commands
USEMODULE += ps
USEMODULE += xtimer

# chronos is missing a getchar implementation
BOARD_BLACKLIST += chronos

include $(RIOTBASE)/Makefile.include
Loading