Merge pull request #11612 from ben-postman/pr_cc26x0_uart_mode
cpu/cc26x0: implement uart_mode()
This commit is contained in:
commit
002e033f5e
@ -1,3 +1,5 @@
|
||||
FEATURES_PROVIDED += periph_cpuid
|
||||
FEATURES_PROVIDED += periph_uart
|
||||
FEATURES_PROVIDED += periph_uart_modecfg
|
||||
|
||||
-include $(RIOTCPU)/cortexm_common/Makefile.features
|
||||
|
||||
@ -72,9 +72,8 @@ typedef struct {
|
||||
#define UART_FR_RXFF 0x40
|
||||
#define UART_FR_TXFE 0x80
|
||||
|
||||
#define UART_LCRH_PEN 0x1
|
||||
#define UART_LCRH_EPS 0x2
|
||||
#define UART_LCRH_RXFE 0x4
|
||||
#define UART_LCRH_PEN 0x2
|
||||
#define UART_LCRH_EPS 0x4
|
||||
#define UART_LCRH_STP2 0x8
|
||||
#define UART_LCRH_FEN 0x10
|
||||
#define UART_LCRH_WLEN_mask 0x60
|
||||
|
||||
@ -65,6 +65,53 @@ typedef enum {
|
||||
GPIO_BOTH = IOCFG_EDGEDET_BOTH
|
||||
} gpio_flank_t;
|
||||
|
||||
/*
|
||||
* @brief Invalid UART mode mask
|
||||
*
|
||||
* This mask is also used to force data_bits_t to be uint32_t type
|
||||
* since it may be assigned a uint32_t variable in uart_mode
|
||||
*/
|
||||
#define UART_INVALID_MODE (0x8000000)
|
||||
|
||||
/**
|
||||
* @brief Override parity values
|
||||
* @{
|
||||
*/
|
||||
#define HAVE_UART_PARITY_T
|
||||
typedef enum {
|
||||
UART_PARITY_NONE = 0,
|
||||
UART_PARITY_EVEN = (UART_LCRH_PEN | UART_LCRH_EPS),
|
||||
UART_PARITY_ODD = UART_LCRH_PEN,
|
||||
UART_PARITY_MARK = UART_INVALID_MODE | 4,
|
||||
UART_PARITY_SPACE = UART_INVALID_MODE | 5
|
||||
} uart_parity_t;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Override data bits length values
|
||||
* @{
|
||||
*/
|
||||
#define HAVE_UART_DATA_BITS_T
|
||||
typedef enum {
|
||||
UART_DATA_BITS_5 = UART_LCRH_WLEN_5,
|
||||
UART_DATA_BITS_6 = UART_LCRH_WLEN_6,
|
||||
UART_DATA_BITS_7 = UART_LCRH_WLEN_7,
|
||||
UART_DATA_BITS_8 = UART_LCRH_WLEN_8
|
||||
} uart_data_bits_t;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Override stop bits length values
|
||||
* @{
|
||||
*/
|
||||
#define HAVE_UART_STOP_BITS_T
|
||||
typedef enum {
|
||||
UART_STOP_BITS_1 = 0,
|
||||
UART_STOP_BITS_2 = UART_LCRH_STP2,
|
||||
} uart_stop_bits_t;
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @brief Configuration of low-level general purpose timers
|
||||
*
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
|
||||
#include "cpu.h"
|
||||
#include "periph/uart.h"
|
||||
#include "periph_conf.h"
|
||||
|
||||
/**
|
||||
* @brief Bit mask for the fractional part of the baudrate
|
||||
@ -91,6 +92,47 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
return UART_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifdef MODULE_PERIPH_UART_MODECFG
|
||||
int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity,
|
||||
uart_stop_bits_t stop_bits)
|
||||
{
|
||||
assert(data_bits == UART_DATA_BITS_5 ||
|
||||
data_bits == UART_DATA_BITS_6 ||
|
||||
data_bits == UART_DATA_BITS_7 ||
|
||||
data_bits == UART_DATA_BITS_8);
|
||||
|
||||
assert(parity == UART_PARITY_NONE ||
|
||||
parity == UART_PARITY_EVEN ||
|
||||
parity == UART_PARITY_ODD ||
|
||||
parity == UART_PARITY_MARK ||
|
||||
parity == UART_PARITY_SPACE);
|
||||
|
||||
assert(stop_bits == UART_STOP_BITS_1 ||
|
||||
stop_bits == UART_STOP_BITS_2);
|
||||
|
||||
/* make sure the uart device is valid */
|
||||
if (uart != 0) {
|
||||
return UART_NODEV;
|
||||
}
|
||||
|
||||
/* cc26x0 does not support mark or space parity */
|
||||
if (parity == UART_PARITY_MARK || parity == UART_PARITY_SPACE) {
|
||||
return UART_NOMODE;
|
||||
}
|
||||
|
||||
/* Disable UART and clear old settings */
|
||||
UART->CTL = 0;
|
||||
UART->LCRH = 0;
|
||||
|
||||
/* Apply setting and enable UART */
|
||||
UART->LCRH = data_bits | parity | stop_bits;
|
||||
UART->CTL = ENABLE_MASK;
|
||||
|
||||
return UART_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
void uart_write(uart_t uart, const uint8_t *data, size_t len)
|
||||
{
|
||||
(void) uart;
|
||||
|
||||
14
tests/periph_uart_mode/Makefile
Normal file
14
tests/periph_uart_mode/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
BOARD_INSUFFICIENT_MEMORY := arduino-duemilanove arduino-leonardo arduino-nano\
|
||||
arduino-uno nucleo-f031k6
|
||||
|
||||
FEATURES_REQUIRED += periph_uart
|
||||
FEATURES_REQUIRED += periph_uart_modecfg
|
||||
|
||||
USEMODULE += xtimer
|
||||
|
||||
# Set this to prevent welcome message from printing and confusing output
|
||||
CFLAGS+=-DLOG_LEVEL=LOG_NONE
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
22
tests/periph_uart_mode/README.md
Normal file
22
tests/periph_uart_mode/README.md
Normal file
@ -0,0 +1,22 @@
|
||||
Expected result
|
||||
===============
|
||||
|
||||
Use a probe to examine the output from the UART. It tests all
|
||||
permutations of data-bits, parity, and stop-bits. For each mode, the mode
|
||||
configuration will be printed to STDOUT as:
|
||||
<data-bits><parity-bits><stop-bits>
|
||||
For example: 7 data-bits, even parity, and 2 stop-bits would be: 7E2
|
||||
Only supported mode strings will be printed out. At the end of the
|
||||
test, the default mode will be restored, and a list indicating which
|
||||
modes were supported and unsupported by the device. The scope still
|
||||
needs to be used to validate that the settings were applied properly.
|
||||
If a different BAUD rate than 115200 is desired, compile with:
|
||||
`CFLAGS+=-DSTDIO_UART_BAUDRATE=<BAUD>`
|
||||
|
||||
Background
|
||||
==========
|
||||
|
||||
This test was created because the existing periph_uart test relies on the
|
||||
presence of multiple UARTs, so that one can be used for the shell, and another
|
||||
for testing. This test requires no shell hookup, and automatically runs through
|
||||
the test procedure, relying on a probe to examine the results.
|
||||
180
tests/periph_uart_mode/main.c
Normal file
180
tests/periph_uart_mode/main.c
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Sparkmeter
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Manual test application for UART mode on CPUs with only one UART
|
||||
*
|
||||
* @author Ben Postman <ben.l.postman@gmail.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "periph/uart.h"
|
||||
#include "stdio_uart.h"
|
||||
#include "xtimer.h"
|
||||
|
||||
/* Number of different options for each mode parameter */
|
||||
#define DATA_BIT_OPTIONS (4)
|
||||
#define PARITY_OPTIONS (5)
|
||||
#define STOP_BIT_OPTIONS (2)
|
||||
#define TOTAL_OPTIONS (DATA_BIT_OPTIONS * PARITY_OPTIONS * STOP_BIT_OPTIONS)
|
||||
|
||||
/* Character positions in the mode string */
|
||||
#define DATA_BIT_POS (0)
|
||||
#define PARITY_POS (1)
|
||||
#define STOP_BIT_POS (2)
|
||||
|
||||
/* Length of the printable mode string, includes null terminator */
|
||||
#define MODE_STR_LEN (4)
|
||||
|
||||
/* UART_DEV is always 0 since this test is for device with 1 UART */
|
||||
#define _UART_DEV (UART_DEV(0))
|
||||
|
||||
/* Delay between each mode, makes parsing results easier */
|
||||
#ifndef DELAY_US
|
||||
#define DELAY_US 50000
|
||||
#endif
|
||||
|
||||
|
||||
/* Stores each mode string for printing at the end of the test */
|
||||
static char mode_strings[TOTAL_OPTIONS][MODE_STR_LEN];
|
||||
|
||||
|
||||
static void _get_mode(const uart_data_bits_t data_bits,
|
||||
const uart_parity_t parity, const uart_stop_bits_t stop_bits, char* mode_str) {
|
||||
switch (data_bits) {
|
||||
case UART_DATA_BITS_5:
|
||||
mode_str[DATA_BIT_POS] = '5';
|
||||
break;
|
||||
case UART_DATA_BITS_6:
|
||||
mode_str[DATA_BIT_POS] = '6';
|
||||
break;
|
||||
case UART_DATA_BITS_7:
|
||||
mode_str[DATA_BIT_POS] = '7';
|
||||
break;
|
||||
case UART_DATA_BITS_8:
|
||||
mode_str[DATA_BIT_POS] = '8';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (parity) {
|
||||
case UART_PARITY_NONE:
|
||||
mode_str[PARITY_POS] = 'N';
|
||||
break;
|
||||
case UART_PARITY_EVEN:
|
||||
mode_str[PARITY_POS] = 'E';
|
||||
break;
|
||||
case UART_PARITY_ODD:
|
||||
mode_str[PARITY_POS] = 'O';
|
||||
break;
|
||||
case UART_PARITY_MARK:
|
||||
mode_str[PARITY_POS] = 'M';
|
||||
break;
|
||||
case UART_PARITY_SPACE:
|
||||
mode_str[PARITY_POS] = 'S';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (stop_bits) {
|
||||
case UART_STOP_BITS_1:
|
||||
mode_str[STOP_BIT_POS] = '1';
|
||||
break;
|
||||
case UART_STOP_BITS_2:
|
||||
mode_str[STOP_BIT_POS] = '2';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mode_str[MODE_STR_LEN - 1] = '\0';
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int8_t status;
|
||||
|
||||
/* Stores the result for each mode */
|
||||
bool results[TOTAL_OPTIONS];
|
||||
|
||||
/* Results index that is used to associate mode_strings and results */
|
||||
uint8_t ridx = 0;
|
||||
|
||||
/* Use arrays so that each option can be easily iterated over */
|
||||
const uart_data_bits_t data_bits[DATA_BIT_OPTIONS] = {
|
||||
UART_DATA_BITS_5,
|
||||
UART_DATA_BITS_6,
|
||||
UART_DATA_BITS_7,
|
||||
UART_DATA_BITS_8
|
||||
};
|
||||
|
||||
const uart_parity_t parity[PARITY_OPTIONS] = {
|
||||
UART_PARITY_NONE,
|
||||
UART_PARITY_EVEN,
|
||||
UART_PARITY_ODD,
|
||||
UART_PARITY_MARK,
|
||||
UART_PARITY_SPACE
|
||||
};
|
||||
|
||||
const uart_stop_bits_t stop_bits[STOP_BIT_OPTIONS] = {
|
||||
UART_STOP_BITS_1,
|
||||
UART_STOP_BITS_2
|
||||
};
|
||||
|
||||
/* Test each permutation */
|
||||
for (int didx = 0; didx < 4; ++didx) {
|
||||
for (int pidx = 0; pidx < 5; ++pidx) {
|
||||
for (int sidx = 0; sidx < 2; ++sidx) {
|
||||
/* Initialize stdio to get printf */
|
||||
stdio_init();
|
||||
|
||||
status = uart_mode(_UART_DEV, data_bits[didx],
|
||||
parity[pidx], stop_bits[sidx]);
|
||||
_get_mode(data_bits[didx], parity[pidx],
|
||||
stop_bits[sidx], mode_strings[ridx]);
|
||||
|
||||
if (status == UART_OK) {
|
||||
results[ridx] = true;
|
||||
printf("%s\n", mode_strings[ridx]);
|
||||
xtimer_usleep(DELAY_US);
|
||||
}
|
||||
else {
|
||||
results[ridx] = false;
|
||||
}
|
||||
|
||||
ridx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset mode and print results */
|
||||
stdio_init();
|
||||
uart_mode(_UART_DEV, UART_DATA_BITS_8, UART_PARITY_NONE, UART_STOP_BITS_1);
|
||||
for (int i = 0; i < TOTAL_OPTIONS; ++i) {
|
||||
if (results[i] == true) {
|
||||
printf("%s: Supported\n", mode_strings[i]);
|
||||
}
|
||||
else {
|
||||
printf("%s: Unsupported\n", mode_strings[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user