diff --git a/cpu/sam0_common/include/periph_cpu_common.h b/cpu/sam0_common/include/periph_cpu_common.h index 0bad87b26500..ee425d144c2e 100644 --- a/cpu/sam0_common/include/periph_cpu_common.h +++ b/cpu/sam0_common/include/periph_cpu_common.h @@ -826,9 +826,20 @@ typedef enum { ADC_RES_10BIT = ADC_CTRLC_RESSEL_10BIT_Val, /**< ADC resolution: 10 bit */ ADC_RES_12BIT = ADC_CTRLC_RESSEL_12BIT_Val, /**< ADC resolution: 12 bit */ #endif - ADC_RES_14BIT = 0xfe, /**< not supported */ - ADC_RES_16BIT = 0xfd /**< not supported */ + ADC_RES_16BIT_2SAMPL = ( 0x1 << 2) | 0x1, /**< sum of 2 12 bit samples */ + ADC_RES_16BIT_4SAMPL = ( 0x2 << 2) | 0x1, /**< sum of 4 12 bit samples */ + ADC_RES_16BIT_8SAMPL = ( 0x3 << 2) | 0x1, /**< sum of 8 12 bit samples */ + ADC_RES_16BIT_16SAMPL = ( 0x4 << 2) | 0x1, /**< sum of 16 12 bit samples */ + ADC_RES_16BIT_32SAMPL = ( 0x5 << 2) | 0x1, /**< sum of 32 12 bit samples */ + ADC_RES_16BIT_64SAMPL = ( 0x6 << 2) | 0x1, /**< sum of 64 12 bit samples */ + ADC_RES_16BIT_128SAMPL = ( 0x7 << 2) | 0x1, /**< sum of 128 12 bit samples */ + ADC_RES_16BIT_256SAMPL = ( 0x8 << 2) | 0x1, /**< sum of 256 12 bit samples */ + ADC_RES_16BIT_512SAMPL = ( 0x9 << 2) | 0x1, /**< sum of 512 12 bit samples */ + ADC_RES_16BIT_1024SAMPL = ( 0xA << 2) | 0x1, /**< sum of 1024 12 bit samples */ + ADC_RES_14BIT = 0xfe, /**< not supported */ } adc_res_t; + +#define ADC_RES_16BIT ADC_RES_16BIT_16SAMPL /**< default to 16x oversampling */ #endif /* DOXYGEN */ /** diff --git a/cpu/sam0_common/periph/adc.c b/cpu/sam0_common/periph/adc.c index 3c906842b03c..59c236a7e811 100644 --- a/cpu/sam0_common/periph/adc.c +++ b/cpu/sam0_common/periph/adc.c @@ -23,6 +23,7 @@ #include "periph/gpio.h" #include "periph/adc.h" #include "periph_conf.h" +#include "macros/utils.h" #include "mutex.h" #define ENABLE_DEBUG 0 @@ -181,11 +182,7 @@ static void _setup_calibration(Adc *dev) static int _adc_configure(Adc *dev, adc_res_t res) { - /* Individual comparison necessary because ADC Resolution Bits are not - * numerically in order and 16Bit (averaging - not currently supported) - * falls between 12bit and 10bit. See datasheet for details */ - if (!((res == ADC_RES_8BIT) || (res == ADC_RES_10BIT) || - (res == ADC_RES_12BIT))){ + if ((res == ADC_RES_6BIT) || (res == ADC_RES_14BIT)) { return -1; } @@ -203,10 +200,10 @@ static int _adc_configure(Adc *dev, adc_res_t res) /* Set ADC resolution */ #ifdef ADC_CTRLC_RESSEL /* Reset resolution bits in CTRLC */ - dev->CTRLC.bit.RESSEL = res; + dev->CTRLC.bit.RESSEL = res & 0x3; #else /* Reset resolution bits in CTRLB */ - dev->CTRLB.bit.RESSEL = res; + dev->CTRLB.bit.RESSEL = res & 0x3; #endif /* Set Voltage Reference */ @@ -241,6 +238,12 @@ static int _adc_configure(Adc *dev, adc_res_t res) } #endif + if ((res & 0x3) == 1) { + dev->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM(res >> 2); + } else { + dev->AVGCTRL.reg = 0; + } + /* Enable ADC Module */ dev->CTRLA.reg |= ADC_CTRLA_ENABLE; _wait_syncbusy(dev); @@ -325,14 +328,23 @@ int32_t adc_sample(adc_t line, adc_res_t res) /* Wait for the result */ while (!(dev->INTFLAG.reg & ADC_INTFLAG_RESRDY)) {} - int16_t result = dev->RESULT.reg; + uint16_t sample = dev->RESULT.reg; + int result; _adc_poweroff(dev); _done(); /* in differential mode we lose one bit for the sign */ if (diffmode) { - result *= 2; + result = 2 * (int16_t)sample; + } else { + result = sample; + } + + /* 16 bit mode is implemented as oversampling */ + if ((res & 0x3) == 1) { + /* ADC does automatic right shifts beyond 16 samples */ + result <<= (4 - MIN(4, res >> 2)); } return result; diff --git a/dist/tools/insufficient_memory/add_insufficient_memory_board.sh b/dist/tools/insufficient_memory/add_insufficient_memory_board.sh index f08cdce47294..1219e6efcc42 100755 --- a/dist/tools/insufficient_memory/add_insufficient_memory_board.sh +++ b/dist/tools/insufficient_memory/add_insufficient_memory_board.sh @@ -61,7 +61,12 @@ for app in ${APPLICATIONS}; do if grep -e overflowed -e "not within region" "$TMPFILE" > /dev/null; then printf "${CBIG}%s${CRESET}\n" "too big" make -f "$(dirname "$0")"/Makefile.for_sh DIR="${RIOTBASE}/${application}" BOARD="${BOARD}" Makefile.ci > /dev/null - elif grep -e "not whitelisted" -e "unsatisfied feature requirements" "$TMPFILE" > /dev/null; then + elif grep -e "not whitelisted" \ + -e "unsatisfied feature requirements" \ + -e "Some feature requirements are blacklisted:" \ + -e "not supported. Stop." \ + -e "let the build continue on expected errors by setting CONTINUE_ON_EXPECTED_ERRORS=1" \ + "$TMPFILE" > /dev/null; then printf "${CWARN}%s${CRESET}\n" "not supported" else printf "${CERROR}%s${CRESET}\n" "build failed" diff --git a/dist/tools/insufficient_memory/create_makefile.ci.sh b/dist/tools/insufficient_memory/create_makefile.ci.sh index 6b01cccb592c..e20331ba7003 100755 --- a/dist/tools/insufficient_memory/create_makefile.ci.sh +++ b/dist/tools/insufficient_memory/create_makefile.ci.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh # # Copyright (C) 2021 Benjamin Valentin # @@ -7,10 +7,12 @@ # directory for more details. # -MAKE_ARGS="-j4" +if nproc > /dev/null 2>&1; then + MAKE_ARGS="-j$(nproc)" +fi APP_DIR=$(pwd) -if tput colors &> /dev/null && [ "$(tput colors)" -ge 8 ]; then +if tput colors > /dev/null 2>&1 && [ "$(tput colors)" -ge 8 ]; then COK="\e[1;32m" CBIG="\e[1;34m" CNORMAL="\e[1m" @@ -28,12 +30,12 @@ else CRESET= fi -if [ "$1" == "--no-docker" ]; then - LOCAL_MAKE_ARGS=${MAKE_ARGS} +if [ "$1" = "--no-docker" ]; then + LOCAL_MAKE_ARGS="${MAKE_ARGS}" shift 1 else # Use a standardized build within Docker and with minimal output - export DOCKER_MAKE_ARGS=${MAKE_ARGS} + export DOCKER_MAKE_ARGS="${MAKE_ARGS}" export BUILD_IN_DOCKER=1 fi @@ -43,21 +45,30 @@ BOARDS= rm "${APP_DIR}/Makefile.ci" 2>/dev/null touch "${APP_DIR}/Makefile.ci" +TMPFILE="$(mktemp)" -for BOARD in $(make --no-print-directory info-boards-supported -C "${APP_DIR}"); do +for BOARD in $(EXTERNAL_BOARD_DIRS="" make --no-print-directory info-boards-supported -C "${APP_DIR}"); do printf "${CNORMAL}%-40s${CRESET}" "${BOARD}" - output=$(make BOARD="${BOARD}" ${LOCAL_MAKE_ARGS} clean all -C "${APP_DIR}" 2>&1) - if [ "$?" != 0 ]; then - if echo "${output}" | grep -e overflowed -e "not within region" > /dev/null; then + # disabling warning about globbing and word splitting for LOCAL_MAKE_ARGS, + # as this is exactly what we want here + # shellcheck disable=SC2086 + if ! make BOARD="${BOARD}" ${LOCAL_MAKE_ARGS} clean all -C "${APP_DIR}" > "$TMPFILE" 2>&1; then + if grep -e overflowed -e "not within region" "$TMPFILE" > /dev/null; then printf "${CBIG}%s${CRESET}\n" "too big" BOARDS="${BOARDS} ${BOARD}" - elif echo "${output}" | grep -e "not whitelisted" -e "unsatisfied feature requirements" > /dev/null; then + elif grep -e "not whitelisted" \ + -e "unsatisfied feature requirements" \ + -e "Some feature requirements are blacklisted:" \ + -e "not supported. Stop." \ + -e "let the build continue on expected errors by setting CONTINUE_ON_EXPECTED_ERRORS=1" \ + "$TMPFILE" > /dev/null; then printf "${CWARN}%s${CRESET}\n" "not supported" else printf "${CERROR}%s${CRESET}\n" "build failed" + cat "$TMPFILE" fi else - if echo "${output}" | grep -e "skipping link step" > /dev/null; then + if grep -e "skipping link step" "$TMPFILE" > /dev/null; then printf "${CSKIP}%s${CRESET}\n" "skipped" else printf "${COK}%s${CRESET}\n" "OK"