1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #20101 from maribu/tests/periph/selftest_shield

tests/periph/selftest_shield: Improve error output
This commit is contained in:
Marian Buschsieweke 2023-11-22 13:03:08 +00:00 committed by GitHub
commit 8d8bd82437
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 99 additions and 61 deletions

View File

@ -245,10 +245,10 @@ extern "C"
{
#endif
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include "kernel_defines.h"
#include "periph/gpio.h"
#include "periph/i2c.h"
@ -326,14 +326,18 @@ typedef uint8_t pcf857x_data_t; /**< type that can mask all expander pins */
#endif /* MODULE_PCF8575 || DOXYGEN */
/** @} */
/** Definition of PCF857X driver error codes */
/**
* @brief Definition of PCF857X driver error codes
*
* @deprecated These are aliases for errno error codes now, use them directly
*/
typedef enum {
PCF857X_OK, /**< success */
PCF857X_ERROR_I2C, /**< I2C communication error */
PCF857X_ERROR_INV_EXP, /**< invalid expander variant */
PCF857X_ERROR_INV_MODE, /**< invalid pin mode */
PCF857X_ERROR_INV_FLANK, /**< invalid interrupt flank */
PCF857X_ERROR_INT_PIN, /**< interrupt pin initialization failed */
PCF857X_OK = 0, /**< success */
PCF857X_ERROR_I2C = ENXIO, /**< I2C communication error */
PCF857X_ERROR_INV_EXP = ENOTSUP, /**< invalid expander variant */
PCF857X_ERROR_INV_MODE = EINVAL, /**< invalid pin mode */
PCF857X_ERROR_INV_FLANK = EINVAL, /**< invalid interrupt flank */
PCF857X_ERROR_INT_PIN = ENOSYS, /**< interrupt pin initialization failed */
} pcf857x_error_codes_t;
/**
@ -453,9 +457,8 @@ typedef struct {
* has to be defined by the default configuration parameter
* #PCF857X_PARAM_INT_PIN (pcf857x_params_t::int_pin).
*
* @retval PCF857X_OK on success
* @retval PCF857X_ERROR_* a negative error code on error,
* see #pcf857x_error_codes_t
* @retval 0 on success
* @retval <0 a negative errno error code on error
*/
int pcf857x_init(pcf857x_t *dev, const pcf857x_params_t *params);
@ -472,13 +475,12 @@ int pcf857x_init(pcf857x_t *dev, const pcf857x_params_t *params);
* the driver physically supports only the modes #GPIO_IN_PU and
* #GPIO_OD_PU. The other logically identical modes #GPIO_IN, #GPIO_OUT
* and #GPIO_OD are emulated. For the #GPIO_IN_PU mode the function returns
* with #PCF857X_ERROR_INV_MODE.
* with `-EINVAL`.
* - After initialization in #GPIO_OUT mode the pin is actively driven LOW,
* after initialization in all other modes the pin is pulled-up to HIGH.
*
* @retval PCF857X_OK on success
* @retval PCF857X_ERROR_* a negative error code on error,
* see #pcf857x_error_codes_t
* @retval 0 on success
* @retval <0 a negative errno error code on error
*/
int pcf857x_gpio_init(pcf857x_t *dev, gpio_t pin, gpio_mode_t mode);
@ -504,7 +506,7 @@ int pcf857x_gpio_init(pcf857x_t *dev, gpio_t pin, gpio_mode_t mode);
* the driver physically supports only the modes #GPIO_IN_PU and
* #GPIO_OD_PU. The other logically identical modes #GPIO_IN, #GPIO_OUT
* and #GPIO_OD are emulated. For the #GPIO_IN_PU mode the function returns
* with #PCF857X_ERROR_INV_MODE.
* with `-EINVAL`.
* - After initialization in #GPIO_OUT mode the pin is actively driven LOW,
* after initialization in all other modes the pin is pulled-up to HIGH.
*
@ -515,9 +517,8 @@ int pcf857x_gpio_init(pcf857x_t *dev, gpio_t pin, gpio_mode_t mode);
* @param[in] isr ISR that is called back from interrupt context
* @param[in] arg optional argument passed to the callback
*
* @retval PCF857X_OK on success
* @retval PCF857X_ERROR_* a negative error code on error,
* see #pcf857x_error_codes_t
* @retval 0 on success
* @retval <0 a negative errno error code on error
*/
int pcf857x_gpio_init_int(pcf857x_t *dev, gpio_t pin,
gpio_mode_t mode,

View File

@ -14,8 +14,9 @@
* @{
*/
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "pcf857x.h"
@ -104,7 +105,7 @@ int pcf857x_init(pcf857x_t *dev, const pcf857x_params_t *params)
dev->params.addr += PCF8575_BASE_ADDR;
break;
#endif
default: return -PCF857X_ERROR_INV_EXP;
default: return -ENOTSUP;
}
#if IS_USED(MODULE_PCF857X_IRQ)
@ -121,7 +122,7 @@ int pcf857x_init(pcf857x_t *dev, const pcf857x_params_t *params)
/* initialize the interrupt pin */
if (gpio_init_int(dev->params.int_pin,
GPIO_IN_PU, GPIO_FALLING, _irq_isr, (void*)dev)) {
return -PCF857X_ERROR_INT_PIN;
return -ENOSYS;
}
#endif /* MODULE_PCF857X_IRQ */
@ -131,13 +132,15 @@ int pcf857x_init(pcf857x_t *dev, const pcf857x_params_t *params)
/* write 1 to all pins to switch them to INPUTS pulled up to HIGH */
dev->out = ~0;
res |= _write(dev, dev->out);
res = _write(dev, dev->out);
/* initial read all pins */
res |= _read(dev, &dev->in);
if (!res) {
/* initial read all pins */
res = _read(dev, &dev->in);
/* set all pin modes to INPUT and set internal output data to 1 (HIGH) */
dev->modes = ~0;
/* set all pin modes to INPUT and set internal output data to 1 (HIGH) */
dev->modes = ~0;
}
_release(dev);
@ -161,7 +164,7 @@ int pcf857x_gpio_init(pcf857x_t *dev, gpio_t pin, gpio_mode_t mode)
*/
switch (mode) {
case GPIO_IN_PD: DEBUG_DEV("gpio mode GPIO_IN_PD not supported", dev);
return -PCF857X_ERROR_INV_MODE;
return -EINVAL;
case GPIO_OUT: dev->modes &= ~(1 << pin); /* set mode bit to 0 */
dev->out &= ~(1 << pin); /* set output bit to 0 */
break;
@ -228,7 +231,7 @@ int pcf857x_gpio_init_int(pcf857x_t *dev, gpio_t pin,
dev->enabled[pin] = true;
break;
default: DEBUG_DEV("invalid flank %d for pin %d", dev, flank, pin);
return -PCF857X_ERROR_INV_FLANK;
return -EINVAL;
}
return PCF857X_OK;
@ -428,7 +431,7 @@ static int _read(const pcf857x_t *dev, pcf857x_data_t *data)
if (res != 0) {
DEBUG_DEV("could not read data, reason %d (%s)",
dev, res, strerror(res * -1));
return -PCF857X_ERROR_I2C;
return res;
}
if (dev->pin_num == 8) {
@ -469,7 +472,7 @@ static int _write(const pcf857x_t *dev, pcf857x_data_t data)
if (res != 0) {
DEBUG_DEV("could not write data, reason %d (%s)",
dev, res, strerror(res * -1));
return -PCF857X_ERROR_I2C;
return res;
}
return PCF857X_OK;

View File

@ -20,6 +20,8 @@ FEATURES_OPTIONAL += periph_spi
FEATURES_OPTIONAL += periph_timer
FEATURES_OPTIONAL += periph_uart
USEMODULE += tiny_strerror
STOP_ON_FAILURE ?= 0
DETAILED_OUTPUT ?= 0

View File

@ -40,6 +40,7 @@
#include "periph/timer.h"
#include "periph/uart.h"
#include "stdio_uart.h" /* for STDIO_UART_DEV */
#include "tiny_strerror.h"
/* BEGIN: controls of the behavior of the testing app: */
#ifndef STOP_ON_FAILURE
@ -232,7 +233,7 @@ static bool do_test(bool failed, uint16_t line)
return failed;
}
static void do_assert(bool failed, uint16_t line)
static void MAYBE_UNUSED do_assert(bool failed, uint16_t line)
{
if (failed) {
printf("CRITICAL ");
@ -244,6 +245,18 @@ static void do_assert(bool failed, uint16_t line)
}
}
static void do_assert_no_error(int retval, uint16_t line)
{
if (retval != 0) {
printf("ERROR in " __FILE__ ":%" PRIu16 " with code %s\n",
line, tiny_strerror(retval));
ARCHITECTURE_BREAKPOINT(1);
while (1) {
/* stop */
}
}
}
static void print_result(bool failed)
{
if (failed) {
@ -277,9 +290,28 @@ static void _print_start(const char *name, const char *detail, uint16_t line)
# define print_start(name, detail) _print_start(name, NULL, __LINE__)
#endif
/**
* @brief Expression @p x must evaluate, otherwise fail but continue other
* tests
*
* @pre The test is safe to continue even if the test fails
*/
#define TEST(x) do_test(!(x), __LINE__)
/**
* @brief Expression @p x must evaluate, otherwise fail and abort
*
* @pre The test is ***NOT*** safe to continue if the test fails
*/
#define ASSERT(x) do_assert(!(x), __LINE__)
/**
* @brief The expression @p must return 0, otherwise abort
*
* @pre The return value will be a positive or negative errno code, if it
* is not zero
*
* This prints the errno code and aborts if @p x is not evaluating to zero
*/
#define ASSERT_NO_ERROR(x) do_assert_no_error(x, __LINE__)
static void stupid_delay(unsigned count)
{
@ -312,8 +344,8 @@ static bool periph_gpio_test_push_pull(void)
{
bool failed = false;
print_start("GPIO", "push-pull");
ASSERT(gpio_init(ARDUINO_PIN_3, GPIO_IN) == 0);
ASSERT(gpio_init(ARDUINO_PIN_4, GPIO_OUT) == 0);
ASSERT_NO_ERROR(gpio_init(ARDUINO_PIN_3, GPIO_IN));
ASSERT_NO_ERROR(gpio_init(ARDUINO_PIN_4, GPIO_OUT));
gpio_clear(ARDUINO_PIN_4);
for (unsigned i = 0; i < flaky_test_repetitions; i++) {
@ -334,7 +366,7 @@ static bool periph_gpio_test_input_pull_up(void)
{
bool failed = false;
print_start("GPIO", "input pull-up");
ASSERT(gpio_init(ARDUINO_PIN_4, GPIO_IN) == 0);
ASSERT_NO_ERROR(gpio_init(ARDUINO_PIN_4, GPIO_IN));
if (gpio_init(ARDUINO_PIN_3, GPIO_IN_PU) == 0) {
/* give pull resistor a little time to pull */
brief_delay();
@ -346,7 +378,7 @@ static bool periph_gpio_test_input_pull_up(void)
}
/* push/pull on D4 should still be able to force down D3 */
ASSERT(gpio_init(ARDUINO_PIN_4, GPIO_OUT) == 0);
ASSERT_NO_ERROR(gpio_init(ARDUINO_PIN_4, GPIO_OUT));
gpio_clear(ARDUINO_PIN_4);
for (unsigned i = 0; i < flaky_test_repetitions; i++) {
failed |= TEST(gpio_read(ARDUINO_PIN_3) == 0);
@ -364,7 +396,7 @@ static bool periph_gpio_test_input_pull_down(void)
{
bool failed = false;
print_start("GPIO", "input pull-down");
ASSERT(gpio_init(ARDUINO_PIN_4, GPIO_IN) == 0);
ASSERT_NO_ERROR(gpio_init(ARDUINO_PIN_4, GPIO_IN));
if (gpio_init(ARDUINO_PIN_3, GPIO_IN_PD) == 0) {
/* give pull resistor a little time to pull */
brief_delay();
@ -376,7 +408,7 @@ static bool periph_gpio_test_input_pull_down(void)
}
/* push/pull on D4 should still be able to force up D3 */
ASSERT(gpio_init(ARDUINO_PIN_4, GPIO_OUT) == 0);
ASSERT_NO_ERROR(gpio_init(ARDUINO_PIN_4, GPIO_OUT));
gpio_set(ARDUINO_PIN_4);
for (unsigned i = 0; i < flaky_test_repetitions; i++) {
failed |= TEST(gpio_read(ARDUINO_PIN_3) != 0);
@ -395,7 +427,7 @@ static bool periph_gpio_test_open_drain_pull_up(void)
bool failed = false;
print_start("GPIO", "open-drain pull-up");
ASSERT(gpio_init(ARDUINO_PIN_4, GPIO_IN) == 0);
ASSERT_NO_ERROR(gpio_init(ARDUINO_PIN_4, GPIO_IN));
if (gpio_init(ARDUINO_PIN_3, GPIO_OD_PU) == 0) {
gpio_set(ARDUINO_PIN_3);
/* give pull resistor a little time to pull */
@ -468,9 +500,9 @@ static bool periph_gpio_irq_test_falling(void)
bool failed = false;
print_start("GPIO-IRQ", "falling-edge");
atomic_uint cnt = 0;
ASSERT(gpio_init(ARDUINO_PIN_4, GPIO_OUT) == 0);
ASSERT_NO_ERROR(gpio_init(ARDUINO_PIN_4, GPIO_OUT));
gpio_clear(ARDUINO_PIN_4);
ASSERT(gpio_init_int(ARDUINO_PIN_3, GPIO_IN, GPIO_FALLING, gpio_cb, &cnt) == 0);
ASSERT_NO_ERROR(gpio_init_int(ARDUINO_PIN_3, GPIO_IN, GPIO_FALLING, gpio_cb, &cnt));
/* no stray IRQ */
brief_delay();
@ -531,9 +563,9 @@ static bool periph_gpio_irq_test_rising(void)
bool failed = false;
print_start("GPIO-IRQ", "rising-edge");
atomic_uint cnt = 0;
ASSERT(gpio_init(ARDUINO_PIN_4, GPIO_OUT) == 0);
ASSERT_NO_ERROR(gpio_init(ARDUINO_PIN_4, GPIO_OUT));
gpio_set(ARDUINO_PIN_4);
ASSERT(gpio_init_int(ARDUINO_PIN_3, GPIO_IN, GPIO_RISING, gpio_cb, &cnt) == 0);
ASSERT_NO_ERROR(gpio_init_int(ARDUINO_PIN_3, GPIO_IN, GPIO_RISING, gpio_cb, &cnt));
/* no stray IRQ */
brief_delay();
@ -594,9 +626,9 @@ static bool periph_gpio_irq_test_both(void)
bool failed = false;
print_start("GPIO-IRQ", "both-edges");
atomic_uint cnt = 0;
ASSERT(gpio_init(ARDUINO_PIN_4, GPIO_OUT) == 0);
ASSERT_NO_ERROR(gpio_init(ARDUINO_PIN_4, GPIO_OUT));
gpio_set(ARDUINO_PIN_4);
ASSERT(gpio_init_int(ARDUINO_PIN_3, GPIO_IN, GPIO_BOTH, gpio_cb, &cnt) == 0);
ASSERT_NO_ERROR(gpio_init_int(ARDUINO_PIN_3, GPIO_IN, GPIO_BOTH, gpio_cb, &cnt));
/* no stray IRQ */
brief_delay();
@ -667,10 +699,10 @@ static bool periph_i2c_test(void)
{
bool failed = false;
print_start("I2C", "GPIO extender");
ASSERT(gpio_init(ARDUINO_PIN_8, GPIO_IN) == 0);
ASSERT(gpio_init(ARDUINO_PIN_9, GPIO_OUT) == 0);
ASSERT(pcf857x_gpio_init(&egpios, PCF857X_GPIO_PIN(0, 0), GPIO_OUT) == 0);
ASSERT(pcf857x_gpio_init(&egpios, PCF857X_GPIO_PIN(0, 1), GPIO_IN) == 0);
ASSERT_NO_ERROR(gpio_init(ARDUINO_PIN_8, GPIO_IN));
ASSERT_NO_ERROR(gpio_init(ARDUINO_PIN_9, GPIO_OUT));
ASSERT_NO_ERROR(pcf857x_gpio_init(&egpios, PCF857X_GPIO_PIN(0, 0), GPIO_OUT));
ASSERT_NO_ERROR(pcf857x_gpio_init(&egpios, PCF857X_GPIO_PIN(0, 1), GPIO_IN));
for (unsigned i = 0; i < flaky_test_repetitions; i++) {
gpio_set(ARDUINO_PIN_9);
@ -707,7 +739,7 @@ static bool periph_uart_rxtx_test(uint32_t symbolrate)
uint16_t start;
memset(&serial_buf, 0, sizeof(serial_buf));
ASSERT(uart_init(UART_TEST_DEV, symbolrate, uart_rx_cb, NULL) == 0);
ASSERT_NO_ERROR(uart_init(UART_TEST_DEV, symbolrate, uart_rx_cb, NULL));
if (IS_USED(MODULE_PERIPH_TIMER)) {
bit_ticks = TIMER_FREQ_UART_TEST / symbolrate;
@ -778,7 +810,7 @@ static bool periph_uart_test(void)
bool failed = false;
if (IS_USED(MODULE_PERIPH_TIMER)) {
ASSERT(timer_init(TIMER, TIMER_FREQ_UART_TEST, NULL, NULL) == 0);
ASSERT_NO_ERROR(timer_init(TIMER, TIMER_FREQ_UART_TEST, NULL, NULL));
timer_start(TIMER);
}
@ -836,8 +868,8 @@ static bool periph_spi_rxtx_test(spi_t bus, spi_mode_t mode, spi_clk_t clk,
* theoretical time. Given the overhead of, this already has some
* room for error */
transfer_too_fast |= (byte_time < byte_transfer_ticks);
/* C̅S̅ should be still LOW while chip is selected */
}
/* C̅S̅ should be still LOW while chip is selected */
failed |= TEST(gpio_read(cs_check) == 0);
}
@ -886,7 +918,7 @@ static bool periph_spi_rxtx_test(spi_t bus, spi_mode_t mode, spi_clk_t clk,
static bool periph_spi_test(void)
{
if (IS_USED(MODULE_PERIPH_TIMER)) {
ASSERT(timer_init(TIMER, TIMER_FREQ_SPI_TEST, NULL, NULL) == 0);
ASSERT_NO_ERROR(timer_init(TIMER, TIMER_FREQ_SPI_TEST, NULL, NULL));
timer_start(TIMER);
}
@ -896,7 +928,7 @@ static bool periph_spi_test(void)
if (IS_USED(MODULE_PCF857X)) {
for (int i = 0; i < (int)ARRAY_SIZE(spi_clk_check_pins); i++) {
ASSERT(pcf857x_gpio_init(&egpios, spi_clk_check_pins[i], GPIO_IN) == 0);
ASSERT_NO_ERROR(pcf857x_gpio_init(&egpios, spi_clk_check_pins[i], GPIO_IN));
}
}
@ -931,7 +963,7 @@ static bool periph_pwm_test_chan(pwm_t pwm_dev, uint8_t pwm_chan, pwm_mode_t pwm
return failed;
}
ASSERT(adc_init(adc_line) == 0);
ASSERT_NO_ERROR(adc_init(adc_line));
for (uint16_t i = 0; i <= UINT8_MAX; i++) {
pwm_set(pwm_dev, pwm_chan, i);
@ -975,10 +1007,10 @@ static bool periph_pwm_test(void)
static void r_2r_dac_init(void)
{
ASSERT(pcf857x_gpio_init(&egpios, PCF857X_GPIO_PIN(0, 4), GPIO_OUT) == 0);
ASSERT(pcf857x_gpio_init(&egpios, PCF857X_GPIO_PIN(0, 5), GPIO_OUT) == 0);
ASSERT(pcf857x_gpio_init(&egpios, PCF857X_GPIO_PIN(0, 6), GPIO_OUT) == 0);
ASSERT(pcf857x_gpio_init(&egpios, PCF857X_GPIO_PIN(0, 7), GPIO_OUT) == 0);
ASSERT_NO_ERROR(pcf857x_gpio_init(&egpios, PCF857X_GPIO_PIN(0, 4), GPIO_OUT));
ASSERT_NO_ERROR(pcf857x_gpio_init(&egpios, PCF857X_GPIO_PIN(0, 5), GPIO_OUT));
ASSERT_NO_ERROR(pcf857x_gpio_init(&egpios, PCF857X_GPIO_PIN(0, 6), GPIO_OUT));
ASSERT_NO_ERROR(pcf857x_gpio_init(&egpios, PCF857X_GPIO_PIN(0, 7), GPIO_OUT));
}
static void r_2r_dac_write(uint8_t val)
@ -1029,7 +1061,7 @@ int main(void)
/* the GPIO extender is used by the I2C test and the ADC test, so only
* initialize it once here */
if (IS_USED(MODULE_PCF857X)) {
ASSERT(pcf857x_init(&egpios, &params) == PCF857X_OK);
ASSERT_NO_ERROR(pcf857x_init(&egpios, &params));
}
if (IS_USED(MODULE_PERIPH_GPIO)) {