Merge pull request #11612 from ben-postman/pr_cc26x0_uart_mode

cpu/cc26x0: implement uart_mode()
This commit is contained in:
Kevin "Bear Puncher" Weiss 2019-06-06 15:43:07 +02:00 committed by GitHub
commit 002e033f5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 309 additions and 3 deletions

View File

@ -1,3 +1,5 @@
FEATURES_PROVIDED += periph_cpuid
FEATURES_PROVIDED += periph_uart
FEATURES_PROVIDED += periph_uart_modecfg
-include $(RIOTCPU)/cortexm_common/Makefile.features

View File

@ -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

View File

@ -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
*

View File

@ -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;

View 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

View 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.

View 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;
}