From ed0612c56b30e8b9e4c2026293d3bb8fece1aed6 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 21 Nov 2016 17:45:28 +1100 Subject: [PATCH 01/25] Build system: Fix a bug with embedding binaries in object files Sometimes paths were generated absolute, need to keep those as-is --- make/component_wrapper.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/component_wrapper.mk b/make/component_wrapper.mk index 3018c18b55..2f492bd183 100644 --- a/make/component_wrapper.mk +++ b/make/component_wrapper.mk @@ -204,7 +204,7 @@ embed_txt/$$(notdir $(1)): $(call resolvepath,$(1),$(COMPONENT_PATH)) | embed_tx # full path passed to OBJCOPY makes it into the name of the symbols in the .o file $(1).$(2).o: embed_$(2)/$$(notdir $(1)) | $$(dir $(1)) $(summary) EMBED $$@ - cd embed_$(2); $(OBJCOPY) $(OBJCOPY_EMBED_ARGS) $$(notdir $$<) ../$$@ + cd embed_$(2); $(OBJCOPY) $(OBJCOPY_EMBED_ARGS) $$(notdir $$<) $$(call resolvepath,$$@,../) CLEAN_FILES += embed_$(2)/$$(notdir $(1)) endef From 1cc1d9d721663662e989cb43ac60bcf1d0a53a6b Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Mon, 21 Nov 2016 18:17:07 +0800 Subject: [PATCH 02/25] driver: Add PCNT code 1. add PCNT module in periph_ctrl.c/.h 2. add description of PCNT status in pcnt_struct.h 3. add PCNT driver code 4. add PCNT example code. --- components/driver/include/driver/pcnt.h | 343 ++++++++++++++++++ .../driver/include/driver/periph_ctrl.h | 1 + components/driver/pcnt.c | 277 ++++++++++++++ components/driver/periph_ctrl.c | 4 + components/esp32/include/soc/pcnt_struct.h | 13 +- examples/12_pcnt/Makefile | 9 + examples/12_pcnt/main/component.mk | 3 + examples/12_pcnt/main/pcnt_test.c | 185 ++++++++++ 8 files changed, 834 insertions(+), 1 deletion(-) create mode 100644 components/driver/include/driver/pcnt.h create mode 100644 components/driver/pcnt.c create mode 100644 examples/12_pcnt/Makefile create mode 100644 examples/12_pcnt/main/component.mk create mode 100644 examples/12_pcnt/main/pcnt_test.c diff --git a/components/driver/include/driver/pcnt.h b/components/driver/include/driver/pcnt.h new file mode 100644 index 0000000000..c49dc387ce --- /dev/null +++ b/components/driver/include/driver/pcnt.h @@ -0,0 +1,343 @@ +#ifndef __PCNT_H__ +#define __PCNT_H__ + +#include +#include "esp_intr.h" +#include "esp_err.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/xtensa_api.h" +#include "soc/soc.h" +#include "soc/pcnt_reg.h" +#include "soc/pcnt_struct.h" +#include "soc/gpio_sig_map.h" +#include "driver/gpio.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#define PCNT_PIN_NOT_USED (-1) + +typedef enum { + PCNT_MODE_KEEP = 0, /*!< Control mode: won't change counter mode*/ + PCNT_MODE_REVERSE = 1, /*!< Control mode: invert counter mode(increase -> decrease, decrease -> increase);*/ + PCNT_MODE_DISABLE = 2, /*!< Control mode: Inhibit counter(counter value will not change in this condition)*/ + PCNT_MODE_MAX +} pcnt_ctrl_mode_t; + +typedef enum { + PCNT_COUNT_DIS = 0, /*!< Counter mode: Decrease counter value*/ + PCNT_COUNT_INC = 1, /*!< Counter mode: Increase counter value*/ + PCNT_COUNT_DEC = 2, /*!< Counter mode: Inhibit counter(counter value will not change in this condition)*/ + PCNT_COUNT_MAX +} pcnt_count_mode_t; + +typedef enum { + PCNT_UNIT0 = 0, /*!< PCNT unit0 */ + PCNT_UNIT1 = 1, /*!< PCNT unit1 */ + PCNT_UNIT2 = 2, /*!< PCNT unit2 */ + PCNT_UNIT3 = 3, /*!< PCNT unit3 */ + PCNT_UNIT4 = 4, /*!< PCNT unit4 */ + PCNT_UNIT5 = 5, /*!< PCNT unit5 */ + PCNT_UNIT6 = 6, /*!< PCNT unit6 */ + PCNT_UNIT7 = 7, /*!< PCNT unit7 */ + PCNT_UNIT_MAX, +} pcnt_unit_t; + +typedef enum{ + PCNT_CHANNEL_0 = 0x00, /*!< PCNT channel0 */ + PCNT_CHANNEL_1 = 0x01, /*!< PCNT channel1 */ + PCNT_CHANNEL_MAX, +} pcnt_channel_t; + +typedef enum { + PCNT_EVT_L_LIM = 0, /*!< PCNT watch point event: Minimum counter value */ + PCNT_EVT_H_LIM = 1, /*!< PCNT watch point event: Maximum counter value*/ + PCNT_EVT_THRES0 = 2, /*!< PCNT watch point event: threshold0 value event*/ + PCNT_EVT_THRES1 = 3, /*!< PCNT watch point event: threshold1 value event*/ + PCNT_EVT_ZERO = 4, /*!< PCNT watch point event: counter value zero event*/ + PCNT_EVT_MAX +} pcnt_evt_type_t; + +/** + * @brief PCNT configure struct + */ +typedef struct { + int pulse_gpio_num; /*!< Pulse input gpio_num, if you want to use gpio16, pulse_gpio_num = 16, a negative value will be ignored */ + int ctrl_gpio_num; /*!< Contol signal input gpio_num, a negative value will be ignored*/ + pcnt_ctrl_mode_t lctrl_mode; /*!< PCNT low control mode*/ + pcnt_ctrl_mode_t hctrl_mode; /*!< PCNT high control mode*/ + pcnt_count_mode_t pos_mode; /*!< PCNT positive edge count mode*/ + pcnt_count_mode_t neg_mode; /*!< PCNT negative edge count mode*/ + int16_t counter_h_lim; /*!< Maximum counter value */ + int16_t counter_l_lim; /*!< Minimum counter value */ + pcnt_unit_t unit; /*!< PCNT unit number */ + pcnt_channel_t channel; /*!< the PCNT channel */ +} pcnt_config_t; + +/** + * @brief Configure PCNT unit + * + * @param pcnt_config Pointer of PCNT unit configure parameter + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_unit_config(pcnt_config_t *pcnt_config); + +/** + * @brief Get pulse counter value + * + * @param pcnt_unit PCNT unit number + * @param count Pointer to accept counter value + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_get_counter_value(pcnt_unit_t pcnt_unit, int16_t* count); + +/** + * @brief Pause PCNT counter of PCNT unit + * + * @param pcnt_unit PCNT unit number + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_counter_pause(pcnt_unit_t pcnt_unit); + +/** + * @brief Resume counting for PCNT counter + * + * @param pcnt_unit PCNT unit number, select from pcnt_unit_t + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_counter_resume(pcnt_unit_t pcnt_unit); + +/** + * @brief Clear and reset PCNT counter value to zero + * + * @param pcnt_unit PCNT unit number, select from pcnt_unit_t + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_counter_clear(pcnt_unit_t pcnt_unit); + +/** + * @brief Enable PCNT interrupt for PCNT unit + * @note + * Five watch point events share the same interrupt source for each unit. + * + * @param pcnt_unit PCNT unit number + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_intr_enable(pcnt_unit_t pcnt_unit); + +/** + * @brief Disable PCNT interrupt for PCNT uint + * + * @param pcnt_unit PCNT unit number + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_intr_disable(pcnt_unit_t pcnt_unit); + +/** + * @brief Enable PCNT event of PCNT unit + * + * @param unit PCNT unit number + * @param evt_type PCNT watch point event type, five events share a same interrupt source + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_event_enable(pcnt_unit_t unit, pcnt_evt_type_t evt_type); + +/** + * @brief Disable PCNT event of PCNT unit + * + * @param unit PCNT unit number + * @param evt_type PCNT watch point event type, five events share a same interrupt source + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_event_disable(pcnt_unit_t unit, pcnt_evt_type_t evt_type); + +/** + * @brief Set PCNT event value of PCNT unit + * + * @param unit PCNT unit number + * @param evt_type PCNT watch point event type, five events share a same interrupt source + * @param value Counter value for PCNT event + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_set_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value); + +/** + * @brief Get PCNT event value of PCNT unit + * + * @param unit PCNT unit number + * @param evt_type PCNT watch point event type, five events share a same interrupt source + * @param value Pointer to accept counter value for PCNT event + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_get_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value); + +/** + * @brief Register PCNT interrupt handler, the handler is an ISR. + * The handler will be attached to the same CPU core that this function is running on. + * @note + * Users should know that which CPU is running and then pick a INUM that is not used by system. + * We can find the information of INUM and interrupt level in soc.h. + * + * @param pcnt_intr_num PCNT interrupt number, check the info in soc.h, and please see the core-isa.h for more details + * @param fn Interrupt handler function. + * @note + * Note that the handler function MUST be defined with attribution of "IRAM_ATTR". + * @param arg Parameter for handler function + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Function pointer error. + */ +esp_err_t pcnt_isr_register(uint32_t pcnt_intr_num, void (*fn)(void*), void * arg); + +/** + * @brief Configure PCNT pulse signal input pin and control input pin + * + * @param unit PCNT unit number + * @param channel PCNT channel number + * @param pulse_io Pulse signal input GPIO + * @param ctrl_io Control signal input GPIO + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_set_pin(pcnt_unit_t unit, pcnt_channel_t channel, int pulse_io, int ctrl_io); + +/** + * @brief Enable PCNT input filter + * + * @param unit PCNT unit number + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_filter_enable(pcnt_unit_t unit); + +/** + * @brief Disable PCNT input filter + * + * @param unit PCNT unit number + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_filter_disable(pcnt_unit_t unit); + +/** + * @brief Set PCNT filter value + * + * @param unit PCNT unit number + * @param filter_val PCNT signal filter value, counter in APB_CLK cycles. + * Any pulses lasting shorter than this will be ignored when the filter is enabled. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_set_filter_value(pcnt_unit_t unit, uint16_t filter_val); + +/** + * @brief Get PCNT filter value + * + * @param unit PCNT unit number + * @param filter_val Pointer to accept PCNT filter value. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_get_filter_value(pcnt_unit_t unit, uint16_t *filter_val); + +/** + * @brief Set PCNT counter mode + * + * @param unit PCNT unit number + * @param channel PCNT channel number + * @param pos_mode Counter mode when detecting positive edge + * @param neg_mode Counter mode when detecting negative edge + * @param hctrl_mode Counter mode when control signal is high level + * @param lctrl_mode Counter mode when control signal is low level + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t pcnt_set_mode(pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode); + + +/***************************EXAMPLE********************************** + * + * + * ----------------EXAMPLE OF LEDC SETTING --------------------- + * @code{c} + * //1. Config PCNT unit + * pcnt_config_t pcnt_config = { + * .pulse_gpio_num = 4, //set gpio4 as pulse input gpio + * .ctrl_gpio_num = 5, //set gpio5 as control gpio + * .channel = PCNT_CHANNEL_0, //use unit 0 channel 0 + * .lctrl_mode = PCNT_MODE_REVERSE, //when control signal is low ,reverse the primary counter mode(inc->dec/dec->inc) + * .hctrl_mode = PCNT_MODE_KEEP, //when control signal is high,keep the primary counter mode + * .pos_mode = PCNT_COUNT_INC, //increment the counter + * .neg_mode = PCNT_COUNT_DIS, //keep the counter value + * .counter_h_lim = 10, + * .counter_l_lim = -10, + * }; + * pcnt_unit_config(&pcnt_config); //init unit + * @endcode + * + * @code{c} + * //2. Configure PCNT watchpoint event. + * pcnt_set_event_value(PCNT_UNIT0, PCNT_EVT_THRES1, 5); //set thres1 value + * pcnt_event_enable(PCNT_UNIT0, PCNT_EVT_THRES1); //enable thres1 event + * @endcode + * + * For more examples please refer to PCNT example code in IDF_PATH/examples + * + *--------------------------END OF EXAMPLE -------------------------- + */ + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/components/driver/include/driver/periph_ctrl.h b/components/driver/include/driver/periph_ctrl.h index 3faa347b54..c110b12eae 100644 --- a/components/driver/include/driver/periph_ctrl.h +++ b/components/driver/include/driver/periph_ctrl.h @@ -39,6 +39,7 @@ typedef enum { PERIPH_PWM3_MODULE, PERIPH_UHCI0_MODULE, PERIPH_UHCI1_MODULE, + PERIPH_PCNT_MODULE, } periph_module_t; /** diff --git a/components/driver/pcnt.c b/components/driver/pcnt.c new file mode 100644 index 0000000000..bfcdb7da1e --- /dev/null +++ b/components/driver/pcnt.c @@ -0,0 +1,277 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "esp_log.h" +#include "driver/pcnt.h" +#include "driver/periph_ctrl.h" + +#define PCNT_CHANNEL_ERR_STR "PCNT CHANNEL ERROR" +#define PCNT_UNIT_ERR_STR "PCNT UNIT ERROR" +#define PCNT_GPIO_ERR_STR "PCNT GPIO NUM ERROR" +#define PCNT_ADDRESS_ERR_STR "PCNT ADDRESS ERROR" +#define PCNT_PARAM_ERR_STR "PCNT PARAM ERROR" +#define PCNT_COUNT_MODE_ERR_STR "PCNT COUNTER MODE ERROR" +#define PCNT_CTRL_MODE_ERR_STR "PCNT CTRL MODE ERROR" +#define PCNT_CHECK(a,str,ret_val) if(!(a)) { \ + ESP_LOGE(PCNT_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \ + return (ret_val); \ + } + +static const char* PCNT_TAG = "PCNT"; +static portMUX_TYPE pcnt_spinlock = portMUX_INITIALIZER_UNLOCKED; + +#define PCNT_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux) +#define PCNT_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux) +#define PCNT_ENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux) +#define PCNT_EXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux) + +esp_err_t pcnt_unit_config(pcnt_config_t *pcnt_config) +{ + uint8_t unit = pcnt_config->channel; + uint8_t channel = pcnt_config->unit; + int input_io = pcnt_config->pulse_gpio_num; + int ctrl_io = pcnt_config->ctrl_gpio_num; + + PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(input_io < 0 || (GPIO_IS_VALID_GPIO(input_io) && (input_io != ctrl_io)), "PCNT pluse input io error", ESP_ERR_INVALID_ARG); + PCNT_CHECK(ctrl_io < 0 || GPIO_IS_VALID_GPIO(ctrl_io), "PCNT ctrl io error", ESP_ERR_INVALID_ARG); + PCNT_CHECK((pcnt_config->pos_mode < PCNT_COUNT_MAX) && (pcnt_config->neg_mode < PCNT_COUNT_MAX), PCNT_COUNT_MODE_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK((pcnt_config->hctrl_mode < PCNT_MODE_MAX) && (pcnt_config->lctrl_mode < PCNT_MODE_MAX), PCNT_CTRL_MODE_ERR_STR, ESP_ERR_INVALID_ARG); + /*Enalbe hardware module*/ + periph_module_enable(PERIPH_PCNT_MODULE); + /*Set counter range*/ + pcnt_set_event_value(unit, PCNT_EVT_H_LIM, pcnt_config->counter_h_lim); + pcnt_set_event_value(unit, PCNT_EVT_L_LIM, pcnt_config->counter_l_lim); + /*Default value after reboot is positive, we disable these events like others*/ + pcnt_event_disable(unit, PCNT_EVT_H_LIM); + pcnt_event_disable(unit, PCNT_EVT_L_LIM); + pcnt_event_disable(unit, PCNT_EVT_ZERO); + pcnt_filter_disable(unit); + /*set pulse input and control mode*/ + pcnt_set_mode(unit, channel, pcnt_config->pos_mode, pcnt_config->neg_mode, pcnt_config->hctrl_mode, pcnt_config->lctrl_mode); + /*Set pulse input and control pins*/ + pcnt_set_pin(unit, channel, input_io, ctrl_io); + return ESP_OK; +} + +esp_err_t pcnt_set_mode(pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode) +{ + PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK((pos_mode < PCNT_COUNT_MAX) && (neg_mode < PCNT_COUNT_MAX), PCNT_COUNT_MODE_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK((hctrl_mode < PCNT_MODE_MAX) && (lctrl_mode < PCNT_MODE_MAX), PCNT_CTRL_MODE_ERR_STR, ESP_ERR_INVALID_ARG); + + if(channel == 0) { + PCNT.conf_unit[unit].conf0.ch0_pos_mode = pos_mode; + PCNT.conf_unit[unit].conf0.ch0_neg_mode = neg_mode; + PCNT.conf_unit[unit].conf0.ch0_hctrl_mode = hctrl_mode; + PCNT.conf_unit[unit].conf0.ch0_lctrl_mode = lctrl_mode; + } else { + PCNT.conf_unit[unit].conf0.ch1_pos_mode = pos_mode; + PCNT.conf_unit[unit].conf0.ch1_neg_mode = neg_mode; + PCNT.conf_unit[unit].conf0.ch1_hctrl_mode = hctrl_mode; + PCNT.conf_unit[unit].conf0.ch1_lctrl_mode = lctrl_mode; + } + return ESP_OK; +} + +esp_err_t pcnt_set_pin(pcnt_unit_t unit, pcnt_channel_t channel, int pulse_io, int ctrl_io) +{ + PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(GPIO_IS_VALID_GPIO(pulse_io) || pulse_io < 0, PCNT_GPIO_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(GPIO_IS_VALID_GPIO(ctrl_io) || ctrl_io < 0, PCNT_GPIO_ERR_STR, ESP_ERR_INVALID_ARG); + int input_sig_index = (channel == 0 ? PCNT_SIG_CH0_IN0_IDX + 4 * unit : PCNT_SIG_CH1_IN0_IDX + 4 * unit); + int ctrl_sig_index = (channel == 0 ? PCNT_CTRL_CH0_IN0_IDX + 4 * unit : PCNT_CTRL_CH1_IN0_IDX + 4 * unit); + if(pulse_io >= 0) { + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pulse_io], PIN_FUNC_GPIO); + gpio_set_direction(pulse_io, GPIO_MODE_INPUT); + gpio_set_pull_mode(pulse_io, GPIO_PULLUP_ONLY); + gpio_matrix_in(pulse_io, input_sig_index, 0); + } + if(ctrl_io >= 0) { + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[ctrl_io], PIN_FUNC_GPIO); + gpio_set_direction(ctrl_io, GPIO_MODE_INPUT); + gpio_set_pull_mode(ctrl_io, GPIO_PULLUP_ONLY); + gpio_matrix_in(ctrl_io, ctrl_sig_index, 0); + } + return ESP_OK; +} + +esp_err_t pcnt_get_counter_value(pcnt_unit_t pcnt_unit, int16_t* count) +{ + PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(count != NULL, "PCNT ADDRESS ERROR", ESP_ERR_INVALID_ARG); + *count = (int16_t) PCNT.cnt_unit[pcnt_unit].cnt_val; + return ESP_OK; +} + +esp_err_t pcnt_counter_pause(pcnt_unit_t pcnt_unit) +{ + PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_ENTER_CRITICAL(&pcnt_spinlock); + PCNT.ctrl.val |= BIT(PCNT_CNT_PAUSE_U0_S + (pcnt_unit * 2)); + PCNT_EXIT_CRITICAL(&pcnt_spinlock); + return ESP_OK; +} + +esp_err_t pcnt_counter_resume(pcnt_unit_t pcnt_unit) +{ + PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_ENTER_CRITICAL(&pcnt_spinlock); + PCNT.ctrl.val &= (~(BIT(PCNT_CNT_PAUSE_U0_S + (pcnt_unit * 2)))); + PCNT_EXIT_CRITICAL(&pcnt_spinlock); + return ESP_OK; +} + +esp_err_t pcnt_counter_clear(pcnt_unit_t pcnt_unit) +{ + PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_ENTER_CRITICAL(&pcnt_spinlock); + PCNT.ctrl.val &= (~(BIT(PCNT_PLUS_CNT_RST_U0_S + (pcnt_unit * 2)))); + PCNT_EXIT_CRITICAL(&pcnt_spinlock); + return ESP_OK; +} + +esp_err_t pcnt_intr_enable(pcnt_unit_t pcnt_unit) +{ + PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_ENTER_CRITICAL(&pcnt_spinlock); + PCNT.int_ena.val |= BIT(PCNT_CNT_THR_EVENT_U0_INT_ENA_S + pcnt_unit); + PCNT_EXIT_CRITICAL(&pcnt_spinlock); + return ESP_OK; +} + +esp_err_t pcnt_intr_disable(pcnt_unit_t pcnt_unit) +{ + PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_ENTER_CRITICAL(&pcnt_spinlock); + PCNT.int_ena.val &= (~(BIT(PCNT_CNT_THR_EVENT_U0_INT_ENA_S + pcnt_unit))); + PCNT_EXIT_CRITICAL(&pcnt_spinlock); + return ESP_OK; +} + +esp_err_t pcnt_event_enable(pcnt_unit_t unit, pcnt_evt_type_t evt_type) +{ + PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(evt_type < PCNT_EVT_MAX, "PCNT value type error", ESP_ERR_INVALID_ARG); + if(evt_type == PCNT_EVT_L_LIM) { + PCNT.conf_unit[unit].conf0.thr_l_lim_en = 1; + } else if(evt_type == PCNT_EVT_H_LIM) { + PCNT.conf_unit[unit].conf0.thr_h_lim_en = 1; + } else if(evt_type == PCNT_EVT_THRES0) { + PCNT.conf_unit[unit].conf0.thr_thres0_en = 1; + } else if(evt_type == PCNT_EVT_THRES1) { + PCNT.conf_unit[unit].conf0.thr_thres1_en = 1; + } else if(evt_type == PCNT_EVT_ZERO) { + PCNT.conf_unit[unit].conf0.thr_zero_en = 1; + } + return ESP_OK; +} + +esp_err_t pcnt_event_disable(pcnt_unit_t unit, pcnt_evt_type_t evt_type) +{ + PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(evt_type < PCNT_EVT_MAX, "PCNT value type error", ESP_ERR_INVALID_ARG); + if(evt_type == PCNT_EVT_L_LIM) { + PCNT.conf_unit[unit].conf0.thr_l_lim_en = 0; + } else if(evt_type == PCNT_EVT_H_LIM) { + PCNT.conf_unit[unit].conf0.thr_h_lim_en = 0; + } else if(evt_type == PCNT_EVT_THRES0) { + PCNT.conf_unit[unit].conf0.thr_thres0_en = 0; + } else if(evt_type == PCNT_EVT_THRES1) { + PCNT.conf_unit[unit].conf0.thr_thres1_en = 0; + } else if(evt_type == PCNT_EVT_ZERO) { + PCNT.conf_unit[unit].conf0.thr_zero_en = 0; + } + return ESP_OK; +} + +esp_err_t pcnt_set_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value) +{ + PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(evt_type < PCNT_EVT_MAX, "PCNT value type error", ESP_ERR_INVALID_ARG); + if(evt_type == PCNT_EVT_L_LIM) { + PCNT.conf_unit[unit].conf2.cnt_l_lim = value; + } else if(evt_type == PCNT_EVT_H_LIM) { + PCNT.conf_unit[unit].conf2.cnt_h_lim = value; + } else if(evt_type == PCNT_EVT_THRES0) { + PCNT.conf_unit[unit].conf1.cnt_thres0 = value; + } else if(evt_type == PCNT_EVT_THRES1) { + PCNT.conf_unit[unit].conf1.cnt_thres1 = value; + } + return ESP_OK; +} + +esp_err_t pcnt_get_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value) +{ + PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(evt_type < PCNT_EVT_MAX, "PCNT value type error", ESP_ERR_INVALID_ARG); + PCNT_CHECK(value != NULL, "PCNT ADDRESS ERROR", ESP_ERR_INVALID_ARG); + + if(evt_type == PCNT_EVT_L_LIM) { + *value = (int16_t) PCNT.conf_unit[unit].conf2.cnt_l_lim; + } else if(evt_type == PCNT_EVT_H_LIM) { + *value = (int16_t) PCNT.conf_unit[unit].conf2.cnt_h_lim; + } else if(evt_type == PCNT_EVT_THRES0) { + *value = (int16_t) PCNT.conf_unit[unit].conf1.cnt_thres0; + } else if(evt_type == PCNT_EVT_THRES1) { + *value = (int16_t) PCNT.conf_unit[unit].conf1.cnt_thres1; + } else { + *value = 0; + } + return ESP_OK; +} + +esp_err_t pcnt_set_filter_value(pcnt_unit_t unit, uint16_t filter_val) +{ + PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(filter_val < 1024, PCNT_PARAM_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT.conf_unit[unit].conf0.filter_thres = filter_val; + return ESP_OK; +} + +esp_err_t pcnt_get_filter_value(pcnt_unit_t unit, uint16_t *filter_val) +{ + PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(filter_val != NULL, "PCNT ADDRESS ERROR", ESP_ERR_INVALID_ARG); + + *filter_val = PCNT.conf_unit[unit].conf0.filter_thres; + return ESP_OK; +} + +esp_err_t pcnt_filter_enable(pcnt_unit_t unit) +{ + PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT.conf_unit[unit].conf0.filter_en = 1; + return ESP_OK; +} + +esp_err_t pcnt_filter_disable(pcnt_unit_t unit) +{ + PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT.conf_unit[unit].conf0.filter_en = 0; + return ESP_OK; +} + +esp_err_t pcnt_isr_register(uint32_t pcnt_intr_num, void (*fun)(void*), void * arg) +{ + PCNT_CHECK(fun != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG); + ESP_INTR_DISABLE(pcnt_intr_num); + intr_matrix_set(xPortGetCoreID(), ETS_PCNT_INTR_SOURCE, pcnt_intr_num); + xt_set_interrupt_handler(pcnt_intr_num, fun, arg); + ESP_INTR_ENABLE(pcnt_intr_num); + return ESP_OK; +} + diff --git a/components/driver/periph_ctrl.c b/components/driver/periph_ctrl.c index 3a671abad4..bfdf0f51a6 100644 --- a/components/driver/periph_ctrl.c +++ b/components/driver/periph_ctrl.c @@ -89,6 +89,10 @@ void periph_module_enable(periph_module_t periph) SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UHCI1_CLK_EN); CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UHCI1_RST); break; + case PERIPH_PCNT_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PCNT_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PCNT_RST); + break; default: break; } diff --git a/components/esp32/include/soc/pcnt_struct.h b/components/esp32/include/soc/pcnt_struct.h index eef64a336f..506141ba10 100644 --- a/components/esp32/include/soc/pcnt_struct.h +++ b/components/esp32/include/soc/pcnt_struct.h @@ -113,7 +113,18 @@ typedef volatile struct { }; uint32_t val; } int_clr; - uint32_t status_unit[8]; + union { + struct { + uint32_t cnt_mode:2; /*0: positive value to zero; 1: negative value to zero; 2: counter value negative ; 3: counter value positive*/ + uint32_t thres1_lat:1; /* counter value equals to thresh1*/ + uint32_t thres0_lat:1; /* counter value equals to thresh0*/ + uint32_t l_lim_lat:1; /* counter value reaches h_lim*/ + uint32_t h_lim_lat:1; /* counter value reaches l_lim*/ + uint32_t zero_lat:1; /* counter value equals zero*/ + uint32_t reserved7:25; + }; + uint32_t val; + } status_unit[8]; union { struct { uint32_t cnt_rst_u0: 1; /*Set this bit to clear unit0's counter.*/ diff --git a/examples/12_pcnt/Makefile b/examples/12_pcnt/Makefile new file mode 100644 index 0000000000..5ae4b0b53f --- /dev/null +++ b/examples/12_pcnt/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := pcnt + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/12_pcnt/main/component.mk b/examples/12_pcnt/main/component.mk new file mode 100644 index 0000000000..44bd2b5273 --- /dev/null +++ b/examples/12_pcnt/main/component.mk @@ -0,0 +1,3 @@ +# +# Main Makefile. This is basically the same as a component makefile. +# diff --git a/examples/12_pcnt/main/pcnt_test.c b/examples/12_pcnt/main/pcnt_test.c new file mode 100644 index 0000000000..9e51c89ca1 --- /dev/null +++ b/examples/12_pcnt/main/pcnt_test.c @@ -0,0 +1,185 @@ +/* Pulse counter module - Example + + For other examples please check: + https://github.com/espressif/esp-idf/tree/master/examples + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/periph_ctrl.h" +#include "driver/ledc.h" +#include "driver/gpio.h" +#include "driver/pcnt.h" +#include "esp_attr.h" +#include "esp_log.h" +#include "soc/gpio_sig_map.h" + +/** + * TEST CODE BRIEF + * Use PCNT module to count rising edges generated by LEDC module. + * GPIO18 is used as ouput pin, GPIO4 is used as pulse input pin and GPIO5 is used as control input pin + * + * Open serial port to view the message printed on you screen + * + * To do this test, you should connect GPIO18 with GPIO4 + * GPIO5 is the control signal, you can leave it floating with internal pulled up, or connect it to ground. + * If you connect gpio5 to GND ,you will found the count value decreasing. + * + * When counter value reaches thresh1 or thresh0 value, it will trigger interrupt. + * When counter value reaches l_lim value or h_lim value, counter value will be reset to zero and trigger interrupt. + */ +static const char* TAG = "PCNT_TEST"; +#define PCNT_TEST_UNIT PCNT_UNIT0 +#define PCNT_H_LIM_VAL (10) +#define PCNT_L_LIM_VAL (-10) +#define PCNT_THRESH1_VAL (5) +#define PCNT_THRESH0_VAL (-5) +#define PCNT_INTR_NUM (18) +#define PCNT_INPUT_SIG_IO (4) +#define PCNT_INPUT_CTRL_IO (5) +#define LEDC_OUPUT_IO (18) + +void IRAM_ATTR pcnt_intr_handler(void* arg) +{ + uint32_t intr_status = PCNT.int_st.val; + int i; + for(i = 0; i < PCNT_UNIT_MAX; i++) { + if(intr_status & (BIT(i))) { + ESP_EARLY_LOGI(TAG, "EVENT[%d] intr\n", i); + PCNT.int_clr.val |= BIT(i); + if(PCNT.status_unit[i].h_lim_lat) { + ESP_EARLY_LOGI(TAG, "H LIM EVT\n"); + } + if(PCNT.status_unit[i].l_lim_lat) { + ESP_EARLY_LOGI(TAG, "L LIM EVT\n"); + } + if(PCNT.status_unit[i].thres0_lat) { + ESP_EARLY_LOGI(TAG, "THRES0 EVT\n"); + } + if(PCNT.status_unit[i].thres1_lat) { + ESP_EARLY_LOGI(TAG, "THRES1 EVT\n"); + } + if(PCNT.status_unit[i].zero_lat) { + ESP_EARLY_LOGI(TAG, "ZERO EVT\n"); + } + } + } +} + +static void ledc_init(void) +{ + periph_module_enable(PERIPH_LEDC_MODULE); + ledc_channel_config_t ledc_channel; + /*use GPIO18 as output pin*/ + ledc_channel.gpio_num = LEDC_OUPUT_IO; + /*LEDC high speed mode */ + ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE; + /*use LEDC channel 1*/ + ledc_channel.channel = LEDC_CHANNEL_1; + /*Disable LEDC interrupt*/ + ledc_channel.intr_type = LEDC_INTR_DISABLE; + /*Select LEDC timer 1 */ + ledc_channel.timer_sel = LEDC_TIMER_1; + /*Set duty 100 */ + ledc_channel.duty = 100; + ledc_channel_config(&ledc_channel); //ledc config + + ledc_timer_config_t ledc_timer; + /*LEDC timer high speed mode*/ + ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE; + /*10 bit PWM*/ + ledc_timer.bit_num = LEDC_TIMER_10_BIT; + /*Select timer 1*/ + ledc_timer.timer_num = LEDC_TIMER_1; + /*Set frequency 1 Hz */ + ledc_timer.freq_hz = 1; + ledc_timer_config(&ledc_timer); +} + +static void pcnt_init(void) +{ + pcnt_config_t pcnt_config = { + /*Set GPIO4 as pulse input gpio */ + .pulse_gpio_num = PCNT_INPUT_SIG_IO, + /*set gpio5 as control gpio */ + .ctrl_gpio_num = PCNT_INPUT_CTRL_IO, + /*Choose channel 0 */ + .channel = PCNT_CHANNEL_0, + /*Choose unit 0 */ + .unit = PCNT_TEST_UNIT, + /*Set counter and control mode*/ + /*Counter increase for positive edge on pulse input GPIO*/ + .pos_mode = PCNT_COUNT_INC, + /*Counter decrease for negative edge on pulse input GPIO*/ + .neg_mode = PCNT_COUNT_DIS, //keep the counter value + /*Counter mode reverse when control input is low level*/ + .lctrl_mode = PCNT_MODE_REVERSE, + /*Counter mode does not change when control input is high level*/ + .hctrl_mode = PCNT_MODE_KEEP, //when control signal is high,keep the primary counter mode + /*Set maximum value for increasing counter*/ + .counter_h_lim = PCNT_H_LIM_VAL, + /*Set minimum value for decreasing counter*/ + .counter_l_lim = PCNT_L_LIM_VAL, + }; + /*Initialize PCNT unit */ + pcnt_unit_config(&pcnt_config); + + /*Configure input filter value*/ + pcnt_set_filter_value(PCNT_TEST_UNIT, 100); + /*Enable input filter*/ + pcnt_filter_enable(PCNT_TEST_UNIT); + + /*Set value for watch point thresh1*/ + pcnt_set_event_value(PCNT_TEST_UNIT, PCNT_EVT_THRES1, PCNT_THRESH1_VAL); + /*Enable watch point event of thresh1*/ + pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_THRES1); + /*Set value for watch point thresh0*/ + pcnt_set_event_value(PCNT_TEST_UNIT, PCNT_EVT_THRES0, PCNT_THRESH0_VAL); + /*Enable watch point event of thresh0*/ + pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_THRES0); + /*Enable watch point event of h_lim*/ + pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_H_LIM); + /*Enable watch point event of l_lim*/ + pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_L_LIM); + /*Enable watch point event of zero*/ + pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_ZERO); + + /*Pause counter*/ + pcnt_counter_pause(PCNT_TEST_UNIT); + /*Reset counter value*/ + pcnt_counter_clear(PCNT_TEST_UNIT); + /*Register ISR handler*/ + pcnt_isr_register(PCNT_INTR_NUM, pcnt_intr_handler, NULL); + /*Enable interrupt for PCNT unit*/ + pcnt_intr_enable(PCNT_TEST_UNIT); + /*Resume counting*/ + pcnt_counter_resume(PCNT_TEST_UNIT); +} + +void pcnt_task(void *pvParameter) +{ + int16_t count = 0; + while(1) + { + pcnt_get_counter_value(PCNT_TEST_UNIT, &count); + printf("Current counter value :%d\n", count); + vTaskDelay(1000 / portTICK_RATE_MS); + } +} + +void app_main() +{ + /*Init LEDC for pulse input signal */ + ledc_init(); + /*Init PCNT functions*/ + pcnt_init(); + /*Create task to display PCNT counter value every one second*/ + xTaskCreate(&pcnt_task, "pcnt_task", 1024, NULL, 5, NULL); +} + From d3904493719d70cd205e01dedd1e0eeef77bfe16 Mon Sep 17 00:00:00 2001 From: antti Date: Thu, 17 Nov 2016 16:36:10 +0800 Subject: [PATCH 03/25] add unit tests to esp-idf rename nvs host test folder, modify .gitlab-ci.yml remove unit-test-app build re-format unit test files remove extra newlines in project.mk some refactoring for unit test part in project.mk add build files of unit-test-app in gitignore add README.md for unit test app correct headings in README.md remove files and make minor tweaks in unit test app update .gitlab-ci.yml to use unit test app delete unused lines in component_wrapper.mk delete periph_i2s.h and lcd test add text floating point in components/esp32/test/Kconfig correct idf test build paths in .gitlab-ci.yml --- .gitignore | 5 + .gitlab-ci.yml | 13 +- components/bootloader/Makefile.projbuild | 2 +- components/esp32/test/Kconfig | 9 + components/esp32/test/component.mk | 17 + components/esp32/test/logo.jpg | Bin 0 -> 7561 bytes components/esp32/test/test_ahb_arb.c | 293 ++++ components/esp32/test/test_ahb_arb_asm.S | 51 + components/esp32/test/test_fastbus.c | 132 ++ components/esp32/test/test_fastbus_asm.S | 32 + components/esp32/test/test_fp.c | 195 +++ components/esp32/test/test_miniz.c | 77 + components/esp32/test/test_tjpgd.c | 91 ++ components/esp32/test/test_unal_dma.c | 205 +++ components/freertos/test/component.mk | 5 + components/freertos/test/test_freertos.c | 229 +++ .../freertos/test/test_freertos_eventgroups.c | 105 ++ .../freertos/test/test_freertos_task_delete.c | 22 + components/freertos/test/test_newlib_reent.c | 60 + components/freertos/test/test_panic.c | 26 + components/freertos/test/test_ringbuf.c | 197 +++ components/freertos/test/test_tls_deletecb.c | 58 + components/mbedtls/test/component.mk | 5 + components/mbedtls/test/test_mbedtls.c | 134 ++ components/newlib/test/component.mk | 5 + components/newlib/test/test_newlib.c | 102 ++ components/nvs_flash/test/component.mk | 5 + components/nvs_flash/test/test_nvs.c | 54 + .../{test => test_nvs_host}/Makefile | 0 .../{test => test_nvs_host}/catch.hpp | 0 .../nvs_flash/{test => test_nvs_host}/crc.cpp | 0 .../nvs_flash/{test => test_nvs_host}/crc.h | 0 .../{test => test_nvs_host}/main.cpp | 0 .../{test => test_nvs_host}/sdkconfig.h | 0 .../spi_flash_emulation.cpp | 0 .../spi_flash_emulation.h | 0 .../test_compressed_enum_table.cpp | 0 .../test_intrusive_list.cpp | 0 .../{test => test_nvs_host}/test_nvs.cpp | 0 .../test_spi_flash_emulation.cpp | 0 components/partition_table/test/component.mk | 5 + .../partition_table/test/test_partition.c | 95 ++ components/spi_flash/test/component.mk | 5 + components/spi_flash/test/test_mmap.c | 83 ++ components/spi_flash/test/test_spi_flash.c | 92 ++ make/component_wrapper.mk | 3 - make/project.mk | 15 +- tools/unit-test-app/Makefile | 9 + tools/unit-test-app/README.md | 12 + .../components/unity/component.mk | 3 + .../components/unity/include/unity.h | 292 ++++ .../components/unity/include/unity_config.h | 75 + .../unity/include/unity_internals.h | 772 ++++++++++ .../components/unity/license.txt | 21 + tools/unit-test-app/components/unity/unity.c | 1306 +++++++++++++++++ .../components/unity/unity_platform.c | 165 +++ tools/unit-test-app/main/app_main.c | 18 + tools/unit-test-app/main/component.mk | 5 + tools/unit-test-app/sdkconfig | 125 ++ 59 files changed, 5215 insertions(+), 15 deletions(-) create mode 100644 components/esp32/test/Kconfig create mode 100644 components/esp32/test/component.mk create mode 100644 components/esp32/test/logo.jpg create mode 100644 components/esp32/test/test_ahb_arb.c create mode 100644 components/esp32/test/test_ahb_arb_asm.S create mode 100644 components/esp32/test/test_fastbus.c create mode 100644 components/esp32/test/test_fastbus_asm.S create mode 100644 components/esp32/test/test_fp.c create mode 100644 components/esp32/test/test_miniz.c create mode 100644 components/esp32/test/test_tjpgd.c create mode 100644 components/esp32/test/test_unal_dma.c create mode 100644 components/freertos/test/component.mk create mode 100644 components/freertos/test/test_freertos.c create mode 100644 components/freertos/test/test_freertos_eventgroups.c create mode 100644 components/freertos/test/test_freertos_task_delete.c create mode 100644 components/freertos/test/test_newlib_reent.c create mode 100644 components/freertos/test/test_panic.c create mode 100644 components/freertos/test/test_ringbuf.c create mode 100644 components/freertos/test/test_tls_deletecb.c create mode 100644 components/mbedtls/test/component.mk create mode 100644 components/mbedtls/test/test_mbedtls.c create mode 100644 components/newlib/test/component.mk create mode 100644 components/newlib/test/test_newlib.c create mode 100644 components/nvs_flash/test/component.mk create mode 100644 components/nvs_flash/test/test_nvs.c rename components/nvs_flash/{test => test_nvs_host}/Makefile (100%) rename components/nvs_flash/{test => test_nvs_host}/catch.hpp (100%) rename components/nvs_flash/{test => test_nvs_host}/crc.cpp (100%) rename components/nvs_flash/{test => test_nvs_host}/crc.h (100%) rename components/nvs_flash/{test => test_nvs_host}/main.cpp (100%) rename components/nvs_flash/{test => test_nvs_host}/sdkconfig.h (100%) rename components/nvs_flash/{test => test_nvs_host}/spi_flash_emulation.cpp (100%) rename components/nvs_flash/{test => test_nvs_host}/spi_flash_emulation.h (100%) rename components/nvs_flash/{test => test_nvs_host}/test_compressed_enum_table.cpp (100%) rename components/nvs_flash/{test => test_nvs_host}/test_intrusive_list.cpp (100%) rename components/nvs_flash/{test => test_nvs_host}/test_nvs.cpp (100%) rename components/nvs_flash/{test => test_nvs_host}/test_spi_flash_emulation.cpp (100%) create mode 100644 components/partition_table/test/component.mk create mode 100644 components/partition_table/test/test_partition.c create mode 100644 components/spi_flash/test/component.mk create mode 100644 components/spi_flash/test/test_mmap.c create mode 100644 components/spi_flash/test/test_spi_flash.c create mode 100644 tools/unit-test-app/Makefile create mode 100644 tools/unit-test-app/README.md create mode 100644 tools/unit-test-app/components/unity/component.mk create mode 100644 tools/unit-test-app/components/unity/include/unity.h create mode 100644 tools/unit-test-app/components/unity/include/unity_config.h create mode 100644 tools/unit-test-app/components/unity/include/unity_internals.h create mode 100644 tools/unit-test-app/components/unity/license.txt create mode 100644 tools/unit-test-app/components/unity/unity.c create mode 100644 tools/unit-test-app/components/unity/unity_platform.c create mode 100644 tools/unit-test-app/main/app_main.c create mode 100644 tools/unit-test-app/main/component.mk create mode 100644 tools/unit-test-app/sdkconfig diff --git a/.gitignore b/.gitignore index 2870b4a805..25a5a30910 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,8 @@ examples/*/build docs/_build/ docs/doxygen-warning-log.txt docs/xml/ + +# Unit test app files +tools/unit-test-app/sdkconfig +tools/unit-test-app/sdkconfig.old +tools/unit-test-app/build diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 814279ce15..1d68d2f601 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -78,15 +78,14 @@ build_esp_idf_tests: <<: *build_template artifacts: paths: - - ./esp-idf-tests/build/*.bin - - ./esp-idf-tests/build/*.elf - - ./esp-idf-tests/build/*.map - - ./esp-idf-tests/build/bootloader/*.bin + - ./tools/unit-test-app/build/*.bin + - ./tools/unit-test-app/build/*.elf + - ./tools/unit-test-app/build/*.map + - ./tools/unit-test-app/build/bootloader/*.bin expire_in: 6 mos script: - - git clone $GITLAB_SSH_SERVER/idf/esp-idf-tests.git - - cd esp-idf-tests + - cd tools/unit-test-app - git checkout ${CI_BUILD_REF_NAME} || echo "Using default branch..." - make defconfig - make @@ -131,7 +130,7 @@ test_nvs_on_host: tags: - nvs_host_test script: - - cd components/nvs_flash/test + - cd components/nvs_flash/test_nvs_host - make test test_build_system: diff --git a/components/bootloader/Makefile.projbuild b/components/bootloader/Makefile.projbuild index 3faff53d62..a49f3d8686 100644 --- a/components/bootloader/Makefile.projbuild +++ b/components/bootloader/Makefile.projbuild @@ -20,7 +20,7 @@ export SECURE_BOOT_SIGNING_KEY # used by bootloader_support component # Custom recursive make for bootloader sub-project BOOTLOADER_MAKE=+$(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/src \ - V=$(V) BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) + V=$(V) BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) TEST_COMPONENTS= .PHONY: bootloader-clean bootloader-flash bootloader $(BOOTLOADER_BIN) diff --git a/components/esp32/test/Kconfig b/components/esp32/test/Kconfig new file mode 100644 index 0000000000..af5e5b45e7 --- /dev/null +++ b/components/esp32/test/Kconfig @@ -0,0 +1,9 @@ +menu "TESTS" + +config FP_TEST_ENABLE + bool "Enable test fp" + default "y" + help + For FPGA single core CPU which has no floating point support, floating point test should be disabled. + +endmenu diff --git a/components/esp32/test/component.mk b/components/esp32/test/component.mk new file mode 100644 index 0000000000..5e7d11ddf8 --- /dev/null +++ b/components/esp32/test/component.mk @@ -0,0 +1,17 @@ +# +#Component Makefile +# + +COMPONENT_EXTRA_CLEAN := test_tjpgd_logo.h + +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive + +COMPONENT_SRCDIRS := . test_vectors + +include $(IDF_PATH)/make/component_common.mk + +test_tjpgd.o: test_tjpgd_logo.h + +test_tjpgd_logo.h: $(COMPONENT_PATH)/logo.jpg + $(summary) XXD logo.jpg + $(Q) cd $(COMPONENT_PATH); xxd -i logo.jpg $(COMPONENT_BUILD_DIR)/test_tjpgd_logo.h diff --git a/components/esp32/test/logo.jpg b/components/esp32/test/logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2bd9e775eac4d4195d9d7465239fa007715ff428 GIT binary patch literal 7561 zcmbW42UHYExTt$F8HO2 z-#8He2Qg0o(75Is>hIy^9*E&{;m3%{$;o1{_z-V=V4$#xvx}FrKMtdD&Bxc75DEZ) zzw>z%Kzm+W46(@4Vsg^b!r~&t^8X|Mt??hP{~pfg_HU1Grhm;Dh<@Z>-M_K_>aLXo zfb0RWHtGNBuI2$i$87*$nEzMDRSE#qF#ym$_S^f=pRX79z(8O5OP4}ILPR|9E+Xdz z{YU<<4*z)m*YMkTBIo1%Q#*_%-qktCI}meTRF`Ys*Mj^p0lv;Ic#QD>xrqPAfxo5o zTOLAYcvrkXo zGlm8r+amxJMGio&6ca6=f9B1A)CxG?dDd)ef3JHY6YYPs|EU3|5g)+;9&VU(wT77m z#wEx<_?(G*;=F+YWB@gQ1{i^h04Kl)2m|7P44?q00$P9`U<_CQHh=@*0=NS{fIkod zgac7PERY1G19yRZpaiG{YJo=J0nhK|`Pk z&>PSP&<5x$=qDHgrU0YCtY9ASC9o`54Xh8g0NaDzz<%H`a11yVoC_`oH-Ov0&%rOj zGvFogCinmXK*%BV5O#<#L>8g}F^1SeTp|9D2uLC%8&VEwgmgm&AXAVf$QI-W6b?l} zF;HQs0u&3igt|cepb^kyXg;(C+79i9PC-9FccG^+N*D`F5GD`Pgz&+vD;mPnKcoVz_J^^2bA0QA2MuZ?j31N(IMg$^a z5qXFP#52SsViob7gq(zpM4UvM#Fm6W5>1j#Qb+QXWRhf!Vq7tFfrNU9& zq$;3lr<$bNp(dr~rdFeNpbn$XrhZ60M!iKtO2b2=LE}slK~q4}MKecpfJ7n1kj6+K zWHPc2IfPuNMbPrlYSH3oV`wXA`)HR@5ELg$1LcCcg{nloK&_(TXkN4~+7q3GzKN!L-GUW>#Q!VNPUzz&y_aW)Wa9 zW4X>!!7{>fzmvO{)r+1Nvo1cpxWR^EQ)csE%VK-R_8CKmQNws+ zaxwjwU3M0BEPD`p8T%;vF$XV)B}X(z6USRlGEP}eSI#WXUd~-EHZDW1aISi;d2Ui} zS#Edk9PR<`BOYEJYo0is4xV*h23}p>Fy4CJMLtSC6+S<{a=vMPIKM2v7k?4|xByr{ zO2A#9KwwM|EGRALAy_0hAp{eW6Cwze3(W~r2&)MP3)c&O5TO?_5Q!G)5ZSrJb;`4kr;w6hEUrV8+ z45i|vdZkXJWu*P38>Kg7xMZAU3T5VG(XuA8$+ClTFgbO(n{toke#lG92g*N?|DqtQ z;H6Nfu&&6fh*zvsTvp;xa#ku+T2jU+J1LhcFR8GrIIEPad{pIB#i>@QuBq{>d8#$2 z?Wl{Y`>VI9A8E*I+|cOJglOt$CTfmq(P~+0@c_>K17h3zmGAL6*H%)K*ulYORi}HLWwP zmo8treB<&<8zvhMn@(GVt(9$+?SY+^-CeuYD^gctugu!>+W%oc+NsXzm$R{Rx%0tQ-K&LHcU?4Ga$GiXs<sVCUi;(Pgs-4)tnZSa zyx(2FU4MQ5ssK=ceL!a*ns}HR3E~U79rPhsIk+JBdx%xY!#|LJ5dIhm6$niTT?^9= zyLTOW-Q{|3ID2?h_=g*6H_9SF5mzI6Z*ty@xw#st6Il~Q7UdQ7Dq1u;GkX7)^{wt0 z)|kkc<=Z;9>tm^6{bT3i6yi$aq46H^qX`lTc?qY9xWwTk(WLC8U&$`X!zp4ZxhZF< zuBoGG(rLx%@N`1@Y=%lkO(rrkEOYse;hpv@Ojcsn{$0nrL)ntqB{^g{K{-pg2DzPi zTzTnvzw+JlXA0B{nhIG86AF)ta7B~Fs>O{ZtR+b$KTADIUzh2WwU_ghXIH>0f-62% zT2&6*lf744#Z;A4by7{JUaB#x>93Wkt*v9JORERh2i0#hTxl4;uX(?-QMj?JiM}bR z8E6h_{@mi!GW$UPLGMG^hmEb=t%YrM=pY1-cZu)K>Z^dpSw+napc3Quv zei_-lyt}&RzjyXE`5WW6>V3)m-UE|^cZWWQ$480Z8Nb*3ko__6)B5MyamX*kuiO*< zlkQXf)5SBNv$L}WK;!&B<97l7^>E&T|F=LOP{_G}!RG)y7cc|{gF=Zn6nfst|LTAk z1%^V1UjN^6)&n3(01-e00zv{{BnW~8o%I7O#4`;P^82xd6ow!n1A*ZXqE(Cr0N`NI zUzs7!&oTgrI5Z57AVC78v?w$?hnN~2r#L;Ml)9O7V8%mY$VCtU{?9!kNMIl+oD>Wp z1BiAx;^5~U65j%bfc?`Y5>CqwAjC*e9O7!GXijH3^{Y`Wq!$>tBqaUJ{4>fX&gKCM zVxC|m1PQ1BEQGg>`J)CQUP#F-xzzGh0~os=2ZsxT&KAHDAAhPGHoYM61%p~^axm#* zE{Cb=LLw1&4k2fNYT!fjMu%&&HMXo&Eq>kawg_64FrF5Q9fvugGW}2fmHoF5RLRsJ zxohC`+caXyCN#(=rR{G;?k1@bZm;B}f@_2Zeo&NjEw7XAQkxzXG!{<kf!6(wC;626t}Mv#N1 zi)*u5F5Zx^siNY4!o<|uGh-`)g#^|ieR?83I7 zV)Lx3s(|wyKTgGrPK*-*!}Bp5RGj@pVsm+Fd;Zr?I~xuA>K(FUMiI##4iy%?-G`5r zL&eogL%FEJP~wJb&fNFvziqjB%?kXA&X6WsjY`T@fI?d1ZZj+4y08z(vLaSYN)>(C z2T4e7*VS&iyLsA9yRSM5^u!{z)K-v7X_%FZY8&H~*>C;IW7m8#Yd7yG{wLQ2m9W%Y5u});LuHGd_yzt$GsmQ(65v3dlF(fjLOv0Cj(YTTq*p| zNtB&eAp0tQ(@oPX0jWhVKiw!C6V-jwwrM2b^VPCFe|=Rq_DYBDQwcIU{(yq?!!MO6 zi8v=Nlc#Uvk?Le#Y~^g%yr)sdc6HZGkFzWUSpE#99bWSmlY!n2Sxuc~rd8F62A_PH zkuN7>ruMiVVCFPEpYK)~?Uy-iVKT6DrGAkz>ECt~~^DtVfsY=^(pt0(f+J0qJd1a3Pga zSNG;m`OVbEuFI9RVUsbs8O(K!J9K)P!#!2fMV(sDIT^4|%+{L>ZOezMu5;cy&eL+K zn0jf-_JPI1iYs$)(BLjgEtme@Wj(yBP{=Ec$t?lBw>P^!mAaC~w0-euNm;WYWKW#P ziaBh2Tq)%bo`EiA?T$W(Y=wr(7tAQ)2pblg1LF}Zn`(JjWQ-2r|0*(9afSL;S8 zKAvU&Esm9LL|#K!s`<%%Tp=gvC)68#bsv=AkaJ<{c(lM{+v4(Sxeu-eMp|r|THJ<9 z>bvU4_${w}pE<1F+|FXx;kRyEY3_=w8wR0V^~*hoEp((($587)jSux_aAHaO#U^KX zgiGbLZ~46-R3X%Myv(XGi><_Wu|mjy?OmcG0Z!I)^1coEZp91Dlzv?|vE05Tw?XA9 z&C$^qJM95aOWX4rL`DgRBYUd7dP00{K>`)!A|L!k(4U3PM*&#nniie*RY2}agsTO< z%vafUK!0K^f%@{ zWWp&voNa~q4B$LiUkP5WobZwDFkBCDugSTay!=-CrR&qo%cXy8inTnIuzzcY{HlG@ zHm;bN&_H34ueRzyBoQoy<`KCie z?U(u3v4)`8@@9h#YtM=O^eOKjtY3uw{0o#!n31H{7a=P#B5{H~Iq!*4;+)PT4$8;KD)_R8CH(D!{@~N-7^~ z`@&tSh2=QLpe1V{ncvE7Z1>jT@|bPT)*RuHN>gnk%@Lb@Rmpt~hAJC(x4J~%=N%7U zk;CGg$wZfn7NUBKb14E^ZG9H=ik?|MEatddzZzd9Aou8V@tE1ODt{q=j~fEI>bZT# zs|Kn@IxR_bfr&5^H4JU8v+&Ox-6I&+R8GD*EA~h2XO#D?@994VS)%XZOk>%@xIK%< zkESLY_U)Ipx3>j^9*EL72umEdHrQpLm%?v9mXs(<7&RBs0A4t66ei8DIk${fuadW( z>P+|~lqi{-i{GDBoeUmib3Jk|T-siY&0T+`UOS1&pTyxy(MEbn|(LW|;;saHRZ zSt&I(o&mJQ#e|cTXAy*|DN+4^mXXEb{fwnKJO5Dpn|8gxA%*Cg1vDtEwrbeiS!{O2 z2M>RsdFTH0!>mVO-EEHF$NtLTd&lXJZe`@>3Obxc~k8a_SvQyawGPyT$d5!NW-p z^{8YRElovQGZ55Gn06#Em9*r`n7&PrvXq{`kY2dbSxqt$FltBG313rjD7m60s1Px3 zA75_9?Wlo&CGq<6=}(uVnGPx@`+VynNnwXK-1K#-9HzH@V{moVY)ht?Gz%g3>jGEx zhUscwnaMR&Bs#sjNuMGtPW?_H4uL3t6n%a2%P$_f0jYN*={65 zoAT(z_xGJvrDh$xm#d}|Mqf{shJUN=s^ah1xNtdSPqltPDh~vp7!i8XAuJowy@7WE zhGMF~4AtD8-Q*FECdEE)%dUE{Ye*^9rz}HFlpL^fa2S`^F&T1yaQ~qmuA;Il0`Aj;RC?MRe+Ecl=U>!T>FQ;)V(WAw z!>}X4xhacVX}BSoJcgRMj#ujXJbFe3UApxQkCZ|){jV<7lK?y_^_mG-_MX!vwDPZ@ ziSS}2`!@;o1aAGdOP&3@6wN6Erx3kd$d=!z-^^i5>+B)oSe0M0y(nQNHS^GeRucMf zVg~C>W`XPYVe{b4;8Jlduc?WpZ+^KJip~XQ&eI&r z*S5lM4sMRqZ3JtZV?OLO@STyq*(4w~H>vl*F2bF6$4q$+C8t9@-ISXZnS zoq^rv*)->4s1iu7v}4&|9<17*79d9}W?nMyb}_Tuuv-c7G+_X1RQNyO1UIHu$6A@G zA--h9_EBhb-gwd+Vy$kuZipRYLB+U#ivQ?o8y_DQ*2zF)b(sqkOY-jCvI==|!!xh< z->+?#h}ljk1wU{V3Sf;Z{;&X*4{$eLY|}z)<+ujR=w;#+E81T%32e>}w+d_(RgK5m z_ujM_owxF;xwqYr)qOFlt~Oa1`Mpm`*4HAz1@j07YafbEMjt1WU_J-G+NkRcYmWZ% znbZ7*cehet(1c3+g!wyLIeIm2n1`StI&-*&rz&eeQJDR5`L!6qsRc)=&4{+cxcD5O z;=S#?aOXttHzM`b(+&P@ORE>8&Z8 zb>5>VuY(ZD6l=0;wO>r0l6dMVY>4f~y*mf=HLJf~Cxto&9{d^>#_BTUN((af zOeFKVCdWV5=|#@~vk^UoDU^N0t_3j6Y|>e9>FC4LSiYMfumWaMk( z$T6j)k=r=}@r4u^+^aD&tE8g&KHCm*Ee$R4?|5!w*};8#i=(|QZ~rv5srG#0Dqh5;u|w3RBs;H%|yB7UEues z4?8u=6w~;jlow-@(<%CugQHx<4|yE_Rqb@Y@h+!Ky$_wm{g*GfKsc8pVbUa(#;uaM zQcZ_K$(a<|oc5oOOkcZ?JA1hAqzH3RxB6OfYxgKpHZ7;NiTuLAle* z_f^9D8PFs|GaQk)f}R$z@^Df1PyZet$w-^7f5eydUdi-P_4P;yuB@Uw9Y>0Zyk1~D zA~UojJCpf(4Ol?aXlH0Jon%T9f4i1>U($wd z&ORag#YMeAu2Jx&B;7Qi%0Y4RR}|vp8EfE_>gkuhG{n!;&c)5z7ozVUF~>zxkDpdF HoxS-F9Fyzg literal 0 HcmV?d00001 diff --git a/components/esp32/test/test_ahb_arb.c b/components/esp32/test/test_ahb_arb.c new file mode 100644 index 0000000000..65f4906fd5 --- /dev/null +++ b/components/esp32/test/test_ahb_arb.c @@ -0,0 +1,293 @@ + +#include +#include +#include +#include "rom/ets_sys.h" +#include "rom/lldesc.h" +#include "rom/gpio.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/xtensa_api.h" + +#include "unity.h" + +#include "soc/uart_reg.h" +#include "soc/dport_reg.h" +#include "soc/io_mux_reg.h" +#include "soc/gpio_sig_map.h" +#include "soc/gpio_reg.h" +#include "soc/i2s_reg.h" + + +#define DPORT_I2S0_CLK_EN (BIT(4)) +#define DPORT_I2S0_RST (BIT(4)) + + +/* +This test tests the s32c1i instruction when the AHB bus is also used. To create some AHB traffic, we use the I2S interface +to copy bytes over from one memory location to another. DO NOT USE the i2s routines inhere, they've been trial-and-error'ed until +the point where they happened to do what I want. +*/ + +static void lcdIfaceInit() +{ + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); + + //Init pins to i2s functions + SET_PERI_REG_MASK(GPIO_ENABLE_W1TS_REG, (1 << 11) | (1 << 3) | (1 << 0) | (1 << 2) | (1 << 5) | (1 << 16) | (1 << 17) | (1 << 18) | (1 << 19) | (1 << 20)); //ENABLE GPIO oe_enable + + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO16_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO18_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO20_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 2); //11 + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO26_U, 0); //RS + + WRITE_PERI_REG(GPIO_FUNC0_OUT_SEL_CFG_REG, (148 << GPIO_FUNC0_OUT_SEL_S)); + WRITE_PERI_REG(GPIO_FUNC2_OUT_SEL_CFG_REG, (149 << GPIO_FUNC0_OUT_SEL_S)); + WRITE_PERI_REG(GPIO_FUNC5_OUT_SEL_CFG_REG, (150 << GPIO_FUNC0_OUT_SEL_S)); + WRITE_PERI_REG(GPIO_FUNC16_OUT_SEL_CFG_REG, (151 << GPIO_FUNC0_OUT_SEL_S)); + WRITE_PERI_REG(GPIO_FUNC17_OUT_SEL_CFG_REG, (152 << GPIO_FUNC0_OUT_SEL_S)); + WRITE_PERI_REG(GPIO_FUNC18_OUT_SEL_CFG_REG, (153 << GPIO_FUNC0_OUT_SEL_S)); + WRITE_PERI_REG(GPIO_FUNC19_OUT_SEL_CFG_REG, (154 << GPIO_FUNC0_OUT_SEL_S)); + WRITE_PERI_REG(GPIO_FUNC20_OUT_SEL_CFG_REG, (155 << GPIO_FUNC0_OUT_SEL_S)); + WRITE_PERI_REG(GPIO_FUNC26_OUT_SEL_CFG_REG, (156 << GPIO_FUNC0_OUT_SEL_S)); //RS + WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG, (I2S0O_WS_OUT_IDX << GPIO_FUNC0_OUT_SEL_S)); +// WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG, (I2S0O_BCK_OUT_IDX< +#include +#include "rom/ets_sys.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/xtensa_api.h" +#include "unity.h" +#include "soc/uart_reg.h" +#include "soc/dport_reg.h" +#include "soc/io_mux_reg.h" + + +/* +This test tests the 'fast' peripherial bus at 0x3ff40000. This bus is connected directly to the core, and as such +can receive 'speculative' reads, that is, reads that may or may not actually be executed in the code flow. This +may mess with any FIFOs mapped in the region: if a byte gets dropped due to a missed speculative read, the fifo +may advance to the next byte anyway. + +This code tests reading/writing from the UART1 FIFO, using both cores. For this to work, it's required that the +UARTs RX and TX lines are connected. +*/ + + +void test_fastbus_cp(int fifo_addr, unsigned char *buf, int len, int *dummy); + +static volatile int state = 0; +static volatile int xor = 0; +static unsigned char res[128]; + +static void tskOne(void *pvParameters) +{ + int run = 0, err = 0; + int x; + int ct[256]; + volatile int w; + int dummy; + while (1) { + state = 1; + for (x = 0; x < 64; x++) { + WRITE_PERI_REG(UART_FIFO_REG(1), x ^ xor); + } + for (w = 0; w < (1 << 14); w++); //delay + state = 2; + test_fastbus_cp(UART_FIFO_REG(1), &res[0], 64, &dummy); + for (w = 0; w < (1 << 10); w++); //delay + for (x = 0; x < 255; x++) { + ct[x] = 0; //zero ctrs + } + for (x = 0; x < 128; x++) { + ct[(int)res[x]^xor]++; //count values + } + for (x = 0; x < 255; x++) { //check counts + if (ct[x] != (x < 128 ? 1 : 0)) { + //Disregard first few loops; there may be crap in the fifo. + if (run > 2) { + err++; + printf("Error! Received value %d %d times!\n", x, ct[x]); + } + } + } + run++; + if ((run & 255) == 0) { + printf("Loop %d errct %d\n", run, err); + } + xor = (xor + 1) & 0xff; + } +} + +#define FB2ADDR 0x40098000 + +static void tskTwo(void *pvParameters) +{ + int x; + int dummy; + int *p = (int *)FB2ADDR; + int *s = (int *)test_fastbus_cp; + for (x = 0; x < 100; x++) { + *p++ = *s++; + } + void (*test_fastbus_cp2)(int fifo_addr, unsigned char * buf, int len, int * dummy) = (void *)FB2ADDR; + + + while (1) { + while (state != 1) ; + for (x = 64; x < 128; x++) { + WRITE_PERI_REG(UART_FIFO_REG(1), x ^ xor); + } + while (state != 2); + test_fastbus_cp2(UART_FIFO_REG(1), &res[64], 64, &dummy); + } +} + + +// TODO: split this thing into separate orthogonal tests +TEST_CASE("Fast I/O bus test", "[hw]") +{ + int i; + if ((REG_UART_BASE(0) >> 16) != 0x3ff4) { + printf("Error! Uart base isn't on fast bus.\n"); + TEST_ASSERT(0); + } + + PIN_PULLUP_DIS(PERIPHS_IO_MUX_SD_DATA3_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, FUNC_SD_DATA2_U1RXD); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, FUNC_SD_DATA3_U1TXD); + + int reg_val = (1 << UART_RXFIFO_FULL_THRHD_S); + WRITE_PERI_REG(UART_CONF1_REG(1), reg_val); + WRITE_PERI_REG(UART_CLKDIV_REG(1), 0x30); //semi-random +// CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(1), UART_TXFIFO_EMPTY_INT_ENA|UART_RXFIFO_TOUT_INT_ENA); + + TaskHandle_t th[2]; + printf("Creating tasks\n"); + xTaskCreatePinnedToCore(tskOne , "tskone" , 2048, NULL, 3, &th[0], 0); + xTaskCreatePinnedToCore(tskTwo , "tsktwo" , 2048, NULL, 3, &th[1], 1); + + // Let stuff run for 20s + while (1) { + vTaskDelay(20000 / portTICK_PERIOD_MS); + } + + //Shut down all the tasks + for (i = 0; i < 2; i++) { + vTaskDelete(th[i]); + } + xt_ints_off(1 << ETS_UART0_INUM); +} + diff --git a/components/esp32/test/test_fastbus_asm.S b/components/esp32/test/test_fastbus_asm.S new file mode 100644 index 0000000000..1ced09fcf7 --- /dev/null +++ b/components/esp32/test/test_fastbus_asm.S @@ -0,0 +1,32 @@ +/* +This little bit of code is executed in-place by one CPU, but copied to a different memory region +by the other CPU. Make sure it stays position-independent. +*/ + .text + .align 4 + .global test_fastbus_cp + .type test_fastbus_cp,@function +//Args: +//a2 - fifo addr +//a3 - buf addr +//a4 - len +//a5 - ptr to int to use +test_fastbus_cp: + entry a1,64 +back: + beqi a4, 0, out //check if loop done + s32i a4, a5, 0 //store value, for shits and/or giggles + memw //make sure write happens + l32i a4, a5, 0 //load value again, to thwart any prediction in the pipeline + bbsi a4, 0, pred //Random jump to check predictive reads. Both branches should do the same. + l32i a6, a2, 0 //read from fifo 1 + j predout +pred: + l32i a6, a2, 0 //read from fifo 2 +predout: + s8i a6, a3, 0 //store result + addi a3, a3, 1 //inc ptr + addi a4, a4, -1 //next + j back //loop again +out: + retw //and we are done diff --git a/components/esp32/test/test_fp.c b/components/esp32/test/test_fp.c new file mode 100644 index 0000000000..5c2573b227 --- /dev/null +++ b/components/esp32/test/test_fp.c @@ -0,0 +1,195 @@ +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "unity.h" + +#if CONFIG_FP_TEST_ENABLE +static float addsf(float a, float b) +{ + float result; + asm volatile ( + "wfr f0, %1\n" + "wfr f1, %2\n" + "add.s f2, f0, f1\n" + "rfr %0, f2\n" + :"=r"(result):"r"(a), "r"(b) + ); + return result; +} + +static float mulsf(float a, float b) +{ + float result; + asm volatile ( + "wfr f0, %1\n" + "wfr f1, %2\n" + "mul.s f2, f0, f1\n" + "rfr %0, f2\n" + :"=r"(result):"r"(a), "r"(b) + ); + return result; +} + +static float divsf(float a, float b) +{ + float result; + asm volatile ( + "wfr f0, %1\n" + "wfr f1, %2\n" + "div0.s f3, f1 \n" + "nexp01.s f4, f1 \n" + "const.s f5, 1 \n" + "maddn.s f5, f4, f3 \n" + "mov.s f6, f3 \n" + "mov.s f7, f1 \n" + "nexp01.s f8, f0 \n" + "maddn.s f6, f5, f3 \n" + "const.s f5, 1 \n" + "const.s f2, 0 \n" + "neg.s f9, f8 \n" + "maddn.s f5,f4,f6 \n" + "maddn.s f2, f0, f3 \n" + "mkdadj.s f7, f0 \n" + "maddn.s f6,f5,f6 \n" + "maddn.s f9,f4,f2 \n" + "const.s f5, 1 \n" + "maddn.s f5,f4,f6 \n" + "maddn.s f2,f9,f6 \n" + "neg.s f9, f8 \n" + "maddn.s f6,f5,f6 \n" + "maddn.s f9,f4,f2 \n" + "addexpm.s f2, f7 \n" + "addexp.s f6, f7 \n" + "divn.s f2,f9,f6\n" + "rfr %0, f2\n" + :"=r"(result):"r"(a), "r"(b) + ); + return result; +} + +static float sqrtsf(float a) +{ + float result; + asm volatile ( + "wfr f0, %1\n" + "sqrt0.s f2, f0\n" + "const.s f5, 0\n" + "maddn.s f5, f2, f2\n" + "nexp01.s f3, f0\n" + "const.s f4, 3\n" + "addexp.s f3, f4\n" + "maddn.s f4, f5, f3\n" + "nexp01.s f5, f0\n" + "neg.s f6, f5\n" + "maddn.s f2, f4, f2\n" + "const.s f1, 0\n" + "const.s f4, 0\n" + "const.s f7, 0\n" + "maddn.s f1, f6, f2\n" + "maddn.s f4, f2, f3\n" + "const.s f6, 3\n" + "maddn.s f7, f6, f2\n" + "maddn.s f5, f1, f1\n" + "maddn.s f6, f4, f2\n" + "neg.s f3, f7\n" + "maddn.s f1, f5, f3\n" + "maddn.s f7, f6, f7\n" + "mksadj.s f2, f0\n" + "nexp01.s f5, f0\n" + "maddn.s f5, f1, f1\n" + "neg.s f3, f7\n" + "addexpm.s f1, f2\n" + "addexp.s f3, f2\n" + "divn.s f1, f5, f3\n" + "rfr %0, f1\n" + :"=r"(result):"r"(a) + ); + return result; +} + +TEST_CASE("test FP add", "[fp]") +{ + float a = 100.0f; + float b = 0.5f; + float c = addsf(a, b); + float eps = c - 100.5f; + printf("a=%g b=%g c=%g eps=%g\r\n", a, b, c, eps); + TEST_ASSERT_TRUE(fabs(eps) < 0.000001); +} + +TEST_CASE("test FP mul", "[fp]") +{ + float a = 100.0f; + float b = 0.05f; + float c = mulsf(a, b); + float eps = c - 5.0f; + printf("a=%g b=%g c=%g eps=%g\r\n", a, b, c, eps); + TEST_ASSERT_TRUE(fabs(eps) < 0.000001); +} + +TEST_CASE("test FP div", "[fp]") +{ + float a = 100.0f; + float b = 5.0f; + float c = divsf(a, b); + float eps = c - 20.0f; + printf("a=%g b=%g c=%g eps=%g\r\n", a, b, c, eps); + TEST_ASSERT_TRUE(fabs(eps) < 0.000001); +} + +TEST_CASE("test FP sqrt", "[fp]") +{ + float a = 100.0f; + float c = sqrtsf(a); + float eps = c - 10.0f; + printf("a=%g c=%g eps=%g\r\n", a, c, eps); + TEST_ASSERT_TRUE(fabs(eps) < 0.000001); +} + + +struct TestFPState { + int fail; + int done; +}; + +static const int testFpIter = 100000; + +static void tskTestFP(void *pvParameters) +{ + struct TestFPState *state = (struct TestFPState *) pvParameters; + for (int i = 0; i < testFpIter; ++i) { + // calculate zero in a slightly obscure way + float y = sqrtsf(addsf(1.0f, divsf(mulsf(sqrtsf(2), sqrtsf(2)), 2.0f))); + y = mulsf(y, y); + y = addsf(y, -2.0f); + // check that result is not far from zero + float eps = fabs(y); + if (eps > 1e-6f) { + state->fail++; + printf("%s: i=%d y=%f eps=%f\r\n", __func__, i, y, eps); + } + } + state->done++; + vTaskDelete(NULL); +} + +TEST_CASE("context switch saves FP registers", "[fp]") +{ + struct TestFPState state; + state.done = 0; + state.fail = 0; + xTaskCreatePinnedToCore(tskTestFP, "tsk1", 2048, &state, 3, NULL, 0); + xTaskCreatePinnedToCore(tskTestFP, "tsk2", 2048, &state, 3, NULL, 0); + xTaskCreatePinnedToCore(tskTestFP, "tsk3", 2048, &state, 3, NULL, 1); + xTaskCreatePinnedToCore(tskTestFP, "tsk4", 2048, &state, 3, NULL, 0); + while (state.done != 4) { + vTaskDelay(100 / portTICK_PERIOD_MS); + } + if (state.fail) { + const int total = testFpIter * 4; + printf("Failed: %d, total: %d\r\n", state.fail, total); + } + TEST_ASSERT(state.fail == 0); +} +#endif diff --git a/components/esp32/test/test_miniz.c b/components/esp32/test/test_miniz.c new file mode 100644 index 0000000000..3453c859a9 --- /dev/null +++ b/components/esp32/test/test_miniz.c @@ -0,0 +1,77 @@ + + +#include +#include "rom/miniz.h" +#include "unity.h" + + +#define DATASIZE (1024*64) + +TEST_CASE("Test miniz compression/decompression", "[miniz]") +{ + int x; + char b; + char *inbuf, *outbuf; + tdefl_compressor *comp; + tinfl_decompressor *decomp; + tdefl_status status; + size_t inbytes = 0, outbytes = 0, inpos = 0, outpos = 0, compsz; + printf("Allocating data buffer and filling it with semi-random data\n"); + inbuf = malloc(DATASIZE); + TEST_ASSERT(inbuf != NULL); + srand(0); + for (x = 0; x < DATASIZE; x++) { + inbuf[x] = (x & 1) ? rand() & 0xff : 0; + } + printf("Allocating compressor & outbuf (%d bytes)\n", sizeof(tdefl_compressor)); + comp = malloc(sizeof(tdefl_compressor)); + TEST_ASSERT(comp != NULL); + outbuf = malloc(DATASIZE); + TEST_ASSERT(outbuf != NULL); + printf("Compressing...\n"); + status = tdefl_init(comp, NULL, NULL, TDEFL_WRITE_ZLIB_HEADER | 1500); + TEST_ASSERT(status == TDEFL_STATUS_OKAY); + while (inbytes != DATASIZE) { + outbytes = DATASIZE - outpos; + inbytes = DATASIZE - inpos; + tdefl_compress(comp, &inbuf[inpos], &inbytes, &outbuf[outpos], &outbytes, TDEFL_FINISH); + printf("...Compressed %d into %d bytes\n", inbytes, outbytes); + inpos += inbytes; outpos += outbytes; + } + compsz = outpos; + free(comp); + //Kill inbuffer + for (x = 0; x < DATASIZE; x++) { + inbuf[x] = 0; + } + free(inbuf); + + inbuf = outbuf; + outbuf = malloc(DATASIZE); + TEST_ASSERT(outbuf != NULL); + printf("Reinflating...\n"); + decomp = malloc(sizeof(tinfl_decompressor)); + TEST_ASSERT(decomp != NULL); + tinfl_init(decomp); + inpos = 0; outpos = 0; + while (inbytes != compsz) { + outbytes = DATASIZE - outpos; + inbytes = compsz - inpos; + tinfl_decompress(decomp, (const mz_uint8 *)&inbuf[inpos], &inbytes, (uint8_t *)outbuf, (mz_uint8 *)&outbuf[outpos], &outbytes, TINFL_FLAG_PARSE_ZLIB_HEADER); + printf("...Decompressed %d into %d bytes\n", inbytes, outbytes); + inpos += inbytes; outpos += outbytes; + } + printf("Checking if same...\n"); + srand(0); + for (x = 0; x < DATASIZE; x++) { + b = (x & 1) ? rand() & 0xff : 0; + if (outbuf[x] != b) { + printf("Pos %x: %hhx!=%hhx\n", x, outbuf[x], b); + TEST_ASSERT(0); + } + } + printf("Great Success!\n"); + free(inbuf); + free(outbuf); + free(decomp); +} diff --git a/components/esp32/test/test_tjpgd.c b/components/esp32/test/test_tjpgd.c new file mode 100644 index 0000000000..60c687f079 --- /dev/null +++ b/components/esp32/test/test_tjpgd.c @@ -0,0 +1,91 @@ + + +#include +#include "rom/tjpgd.h" +#include +#include +#include +#include "unity.h" + +#include "test_tjpgd_logo.h" + +typedef struct { + const unsigned char *inData; + int inPos; + unsigned char *outData; + int outW; + int outH; +} JpegDev; + + +static UINT infunc(JDEC *decoder, BYTE *buf, UINT len) +{ + JpegDev *jd = (JpegDev *)decoder->device; + printf("Reading %d bytes from pos %d\n", len, jd->inPos); + if (buf != NULL) { + memcpy(buf, jd->inData + jd->inPos, len); + } + jd->inPos += len; + return len; +} + + +static UINT outfunc(JDEC *decoder, void *bitmap, JRECT *rect) +{ + unsigned char *in = (unsigned char *)bitmap; + unsigned char *out; + int y; + printf("Rect %d,%d - %d,%d\n", rect->top, rect->left, rect->bottom, rect->right); + JpegDev *jd = (JpegDev *)decoder->device; + for (y = rect->top; y <= rect->bottom; y++) { + out = jd->outData + ((jd->outW * y) + rect->left) * 3; + memcpy(out, in, ((rect->right - rect->left) + 1) * 3); + in += ((rect->right - rect->left) + 1) * 3; + } + return 1; +} + +#define TESTW 48 +#define TESTH 48 +#define WORKSZ 3100 + +TEST_CASE("Test JPEG decompression library", "[tjpgd]") +{ + char aapix[] = " .:;+=xX$$"; + unsigned char *decoded, *p; + char *work; + int r; + int x, y, v; + JDEC decoder; + JpegDev jd; + decoded = malloc(48 * 48 * 3); + for (x = 0; x < 48 * 48 * 3; x += 2) { + decoded[x] = 0; decoded[x + 1] = 0xff; + } + work = malloc(WORKSZ); + memset(work, 0, WORKSZ); + + jd.inData = logo_jpg; + jd.inPos = 0; + jd.outData = decoded; + jd.outW = TESTW; + jd.outH = TESTH; + + r = jd_prepare(&decoder, infunc, work, WORKSZ, (void *)&jd); + TEST_ASSERT_EQUAL(r, JDR_OK); + r = jd_decomp(&decoder, outfunc, 0); + TEST_ASSERT_EQUAL(r, JDR_OK); + + p = decoded + 2; + for (y = 0; y < TESTH; y++) { + for (x = 0; x < TESTH; x++) { + v = ((*p) * (sizeof(aapix) - 2) * 2) / 256; + printf("%c%c", aapix[v / 2], aapix[(v + 1) / 2]); + p += 3; + } + printf("%c%c", ' ', '\n'); + } + + free(work); + free(decoded); +} diff --git a/components/esp32/test/test_unal_dma.c b/components/esp32/test/test_unal_dma.c new file mode 100644 index 0000000000..3726632a41 --- /dev/null +++ b/components/esp32/test/test_unal_dma.c @@ -0,0 +1,205 @@ + +#include +#include +#include +#include +#include "rom/ets_sys.h" +#include "rom/lldesc.h" +#include "rom/gpio.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/xtensa_api.h" +#include "unity.h" + +#include "soc/uart_reg.h" +#include "soc/dport_reg.h" +#include "soc/io_mux_reg.h" +#include "soc/gpio_sig_map.h" +#include "soc/gpio_reg.h" +#include "soc/i2s_reg.h" + + +#define DPORT_I2S0_CLK_EN (BIT(4)) +#define DPORT_I2S0_RST (BIT(4)) + +static volatile lldesc_t dmaDesc[2]; + + +//hacked up routine to essentially do a memcpy() using dma. Supports max 4K-1 bytes. +static void dmaMemcpy(void *in, void *out, int len) +{ + volatile int i; + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); + + //Init pins to i2s functions + SET_PERI_REG_MASK(GPIO_ENABLE_W1TS_REG, (1 << 11) | (1 << 3) | (1 << 0) | (1 << 2) | (1 << 5) | (1 << 16) | (1 << 17) | (1 << 18) | (1 << 19) | (1 << 20)); //ENABLE GPIO oe_enable + + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO16_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO18_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO20_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 2); //11 + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO26_U, 0); //RS + + WRITE_PERI_REG(GPIO_FUNC0_OUT_SEL_CFG_REG, (148 << GPIO_FUNC0_OUT_SEL_S)); + WRITE_PERI_REG(GPIO_FUNC2_OUT_SEL_CFG_REG, (149 << GPIO_FUNC0_OUT_SEL_S)); + WRITE_PERI_REG(GPIO_FUNC5_OUT_SEL_CFG_REG, (150 << GPIO_FUNC0_OUT_SEL_S)); + WRITE_PERI_REG(GPIO_FUNC16_OUT_SEL_CFG_REG, (151 << GPIO_FUNC0_OUT_SEL_S)); + WRITE_PERI_REG(GPIO_FUNC17_OUT_SEL_CFG_REG, (152 << GPIO_FUNC0_OUT_SEL_S)); + WRITE_PERI_REG(GPIO_FUNC18_OUT_SEL_CFG_REG, (153 << GPIO_FUNC0_OUT_SEL_S)); + WRITE_PERI_REG(GPIO_FUNC19_OUT_SEL_CFG_REG, (154 << GPIO_FUNC0_OUT_SEL_S)); + WRITE_PERI_REG(GPIO_FUNC20_OUT_SEL_CFG_REG, (155 << GPIO_FUNC0_OUT_SEL_S)); + WRITE_PERI_REG(GPIO_FUNC26_OUT_SEL_CFG_REG, (156 << GPIO_FUNC0_OUT_SEL_S)); //RS + WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG, (I2S0O_WS_OUT_IDX << GPIO_FUNC0_OUT_SEL_S)); +// WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG, (I2S0O_BCK_OUT_IDX< +#include +#include "rom/ets_sys.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/xtensa_api.h" +#include "unity.h" +#include "soc/uart_reg.h" +#include "soc/dport_reg.h" +#include "soc/io_mux_reg.h" + + +void ets_isr_unmask(uint32_t unmask); + +static xQueueHandle myQueue; +static xQueueHandle uartRxQueue; + +int ctr; + +#if 1 +//Idle-loop for delay. Tests involuntary yielding +static void cvTaskDelay(int dummy) +{ + volatile int i; + for (i = 0; i < (1 << 17); i++); +} +#else +//Delay task execution using FreeRTOS methods. Tests voluntary yielding. +#define cvTaskDelay(x) vTaskDelay(x) +#endif + +#if 0 +static void dosegfault3(int i) +{ + volatile char *p = (volatile char *)0; + *p = i; +} + +static void dosegfault2(int i) +{ + if (i > 3) { + dosegfault3(i); + } +} + +static void dosegfault(int i) +{ + if (i < 5) { + dosegfault(i + 1); + } + dosegfault2(i); +} +#endif + +static void queueSender(void *pvParameters) +{ + int myCtr = xPortGetCoreID() * 100000; + while (1) { + printf("Core %d: Send to queue: %d\n", xPortGetCoreID(), myCtr); + xQueueSend(myQueue, (void *)(&myCtr), portMAX_DELAY); + printf("Send to queue done.\n"); + cvTaskDelay(100); + myCtr++; + } +} + +static void queueReceiver(void *pvParameters) +{ + int theCtr; + while (1) { + xQueueReceive(myQueue, &theCtr, portMAX_DELAY); + printf("Core %d: Receive from queue: %d\n", xPortGetCoreID(), theCtr); + } +} + + +static void tskone(void *pvParameters) +{ +// char *p=(char *)0; + while (1) { + ctr++; +// if (ctr>60) dosegfault(3); + printf("Task1, core %d, ctr=%d\n", xPortGetCoreID(), ctr); + cvTaskDelay(500); + } +} + +static void tsktwo(void *pvParameters) +{ + while (1) { + ctr++; + printf("Task2, core %d, ctr=%d\n", xPortGetCoreID(), ctr); + cvTaskDelay(500); + } +} + +static void tskthree(void *pvParameters) +{ + while (1) { + ctr++; + printf("Task3, core %d, ctr=%d\n", xPortGetCoreID(), ctr); + cvTaskDelay(500); + } +} + +static void tskfour(void *pvParameters) +{ + while (1) { + ctr++; + printf("Task4, core %d, ctr=%d\n", xPortGetCoreID(), ctr); + cvTaskDelay(500); + } +} + +static void tskfive(void *pvParameters) +{ + while (1) { + ctr++; + printf("Task5, core %d, ctr=%d\n", xPortGetCoreID(), ctr); + cvTaskDelay(500); + } +} + +static void tskyield(void *pvParameters) +{ + while (1) { + portYIELD(); + } +} + +static void tskUartRecv(void *pvParameters) +{ + char c; + while (1) { + xQueueReceive(uartRxQueue, &c, portMAX_DELAY); + printf("Uart received %c!\n", c); + } +} + + +static void uartIsrHdl(void *arg) +{ + char c; + BaseType_t xHigherPriorityTaskWoken; + SET_PERI_REG_MASK(UART_INT_CLR_REG(0), UART_RXFIFO_FULL_INT_CLR); + while (READ_PERI_REG(UART_STATUS_REG(0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) { + c = READ_PERI_REG(UART_FIFO_REG(0)); + xQueueSendFromISR(uartRxQueue, &c, &xHigherPriorityTaskWoken); + printf("ISR: %c\n", c); + } + if (xHigherPriorityTaskWoken) { + portYIELD_FROM_ISR(); + } +} + +static void uartRxInit(xQueueHandle q) +{ + uint32_t reg_val; + + PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_U0TXD); + + + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD); + +// reg_val = READ_PERI_REG(UART_CONF1(0)); + reg_val = (1 << UART_RXFIFO_FULL_THRHD_S); + WRITE_PERI_REG(UART_CONF1_REG(0), reg_val); + CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(0), UART_TXFIFO_EMPTY_INT_ENA | UART_RXFIFO_TOUT_INT_ENA); + SET_PERI_REG_MASK(UART_INT_ENA_REG(0), UART_RXFIFO_FULL_INT_ENA); + + printf("Enabling int %d\n", ETS_UART0_INUM); + REG_SET_FIELD(DPORT_PRO_UART_INTR_MAP_REG, DPORT_PRO_UART_INTR_MAP, ETS_UART0_INUM); + REG_SET_FIELD(DPORT_PRO_UART1_INTR_MAP_REG, DPORT_PRO_UART1_INTR_MAP, ETS_UART0_INUM); + + xt_set_interrupt_handler(ETS_UART0_INUM, uartIsrHdl, NULL); + xt_ints_on(1 << ETS_UART0_INUM); + +} + +// TODO: split this thing into separate orthogonal tests +TEST_CASE("Bunch of FreeRTOS tests", "[freertos]") +{ + char *tst; + TaskHandle_t th[12]; + int i; + printf("%s\n", __FUNCTION__); + tst = pvPortMalloc(16); + printf("Test malloc returns addr %p\n", tst); + printf("Free heap: %u\n", xPortGetFreeHeapSize()); + myQueue = xQueueCreate(10, sizeof(int)); + uartRxQueue = xQueueCreate(256, sizeof(char)); + printf("Free heap: %u\n", xPortGetFreeHeapSize()); + + printf("Creating tasks\n"); + xTaskCreatePinnedToCore(tskyield , "tskyield1" , 2048, NULL, 3, &th[0], 0); + xTaskCreatePinnedToCore(tskyield , "tskyield2" , 2048, NULL, 3, &th[1], 1); + + xTaskCreatePinnedToCore(tskone , "tskone" , 2048, NULL, 3, &th[2], 0); + xTaskCreatePinnedToCore(tsktwo , "tsktwo" , 2048, NULL, 3, &th[3], 1); + xTaskCreatePinnedToCore(tskthree, "tskthree", 2048, NULL, 3, &th[4], 0); + xTaskCreatePinnedToCore(tskfour , "tskfour" , 2048, NULL, 3, &th[5], tskNO_AFFINITY); + xTaskCreatePinnedToCore(tskfive , "tskfive" , 2048, NULL, 3, &th[6], tskNO_AFFINITY); + xTaskCreatePinnedToCore(queueSender , "qsend1" , 2048, NULL, 3, &th[7], 0); + xTaskCreatePinnedToCore(queueSender , "qsend2" , 2048, NULL, 3, &th[8], 1); + xTaskCreatePinnedToCore(queueReceiver , "qrecv1" , 2048, NULL, 3, &th[9], 1); + xTaskCreatePinnedToCore(queueReceiver , "qrecv2" , 2048, NULL, 3, &th[10], 0); + xTaskCreatePinnedToCore(tskUartRecv , "tskuart" , 2048, NULL, 4, &th[11], 1); + printf("Free heap: %u\n", xPortGetFreeHeapSize()); + uartRxInit(uartRxQueue); + + // Let stuff run for 20s + vTaskDelay(20000 / portTICK_PERIOD_MS); + + //Shut down all the tasks + for (i = 0; i < 12; i++) { + vTaskDelete(th[i]); + } + xt_ints_off(1 << ETS_UART0_INUM); +} + diff --git a/components/freertos/test/test_freertos_eventgroups.c b/components/freertos/test/test_freertos_eventgroups.c new file mode 100644 index 0000000000..35a5cc4ed2 --- /dev/null +++ b/components/freertos/test/test_freertos_eventgroups.c @@ -0,0 +1,105 @@ +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/event_groups.h" +#include "unity.h" + +#define BIT_CALL (1 << 0) +#define BIT_RESPONSE(TASK) (1 << (TASK+1)) +#define ALL_RESPONSE_BITS (((1 << NUM_TASKS) - 1) << 1) + +static const int NUM_TASKS = 4; +static const int COUNT = 4000; +static EventGroupHandle_t eg; + +static void task_event_group_call_response(void *param) +{ + int task_num = (int)param; + + printf("Started %d\n", task_num); + + for (int i = 0; i < COUNT; i++) { + /* Wait until the common "call" bit is set, starts off all tasks + (clear on return) */ + while (!xEventGroupWaitBits(eg, BIT_CALL, true, false, portMAX_DELAY)) { + } + + /* Set our individual "response" bit */ + xEventGroupSetBits(eg, BIT_RESPONSE(task_num)); + } + + printf("Task %d done\n", task_num); + + /* Delay is due to not-yet-fixed bug with deleting tasks at same time */ + vTaskDelay(100 / portTICK_RATE_MS); + vTaskDelete(NULL); +} + +TEST_CASE("FreeRTOS Event Groups", "[freertos]") +{ + eg = xEventGroupCreate(); + + /* Note: task_event_group_call_response all have higher priority than us, so will block together. + + This is important because we need to know they'll all have blocked on BIT_CALL each time we + signal it, or they get out of sync. + */ + for (int c = 0; c < NUM_TASKS; c++) { + xTaskCreatePinnedToCore(task_event_group_call_response, "tsk_call_resp", 4096, (void *)c, configMAX_PRIORITIES - 1, NULL, c % portNUM_PROCESSORS); + } + /* Scheduler weirdness, if we don't sleep a few ticks here then the tasks on the other CPU aren't running yet... */ + vTaskDelay(10); + + for (int i = 0; i < COUNT; i++) { + if (i % 100 == 0) { + //printf("Call %d\n", i); + } + /* signal all tasks with "CALL" bit... */ + xEventGroupSetBits(eg, BIT_CALL); + + while (xEventGroupWaitBits(eg, ALL_RESPONSE_BITS, true, true, portMAX_DELAY) != ALL_RESPONSE_BITS) { + } + } +} + + +#define BIT_DONE(X) (1<<(NUM_TASKS+1+X)) + +static void task_test_sync(void *param) +{ + int task_num = (int)param; + + printf("Started %d\n", task_num); + + for (int i = 0; i < COUNT; i++) { + /* set our bit, and wait on all tasks to set their bits */ + xEventGroupSync(eg, BIT_RESPONSE(task_num), ALL_RESPONSE_BITS, portMAX_DELAY); + /* clear our bit */ + xEventGroupClearBits(eg, BIT_RESPONSE(task_num)); + } + int after_done = xEventGroupSetBits(eg, BIT_DONE(task_num)); + + printf("Done %d = %x\n", task_num, after_done); + + /* Delay is due to not-yet-fixed bug with deleting tasks at same time */ + vTaskDelay(100 / portTICK_RATE_MS); + vTaskDelete(NULL); +} + +TEST_CASE("FreeRTOS Event Group Sync", "[freertos]") +{ + eg = xEventGroupCreate(); + + for (int c = 0; c < NUM_TASKS; c++) { + xTaskCreatePinnedToCore(task_test_sync, "task_test_sync", 4096, (void *)c, configMAX_PRIORITIES - 1, NULL, c % portNUM_PROCESSORS); + } + + for (int c = 0; c < NUM_TASKS; c++) { + printf("Waiting on %d (%x)\n", c, BIT_DONE(c)); + xEventGroupWaitBits(eg, BIT_DONE(c), false, false, portMAX_DELAY); + } +} + diff --git a/components/freertos/test/test_freertos_task_delete.c b/components/freertos/test/test_freertos_task_delete.c new file mode 100644 index 0000000000..3101db2564 --- /dev/null +++ b/components/freertos/test/test_freertos_task_delete.c @@ -0,0 +1,22 @@ +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/event_groups.h" +#include "unity.h" + +static void task_delete_self(void *param) +{ + printf("Task %p running on core %d. Deleting shortly...\n", xTaskGetCurrentTaskHandle(), xPortGetCoreID()); + vTaskDelete(NULL); +} + +TEST_CASE("FreeRTOS Delete Tasks", "[freertos]") +{ + xTaskCreatePinnedToCore(task_delete_self, "tsk_self_a", 4096, NULL, configMAX_PRIORITIES - 1, NULL, 0); + xTaskCreatePinnedToCore(task_delete_self, "tsk_self_a", 4096, NULL, configMAX_PRIORITIES - 1, NULL, 0); + vTaskDelay(200 / portTICK_PERIOD_MS); + printf("Done?\n"); +} diff --git a/components/freertos/test/test_newlib_reent.c b/components/freertos/test/test_newlib_reent.c new file mode 100644 index 0000000000..e0ec4aa458 --- /dev/null +++ b/components/freertos/test/test_newlib_reent.c @@ -0,0 +1,60 @@ +/* + Test for multicore FreeRTOS. This test spins up threads, fiddles with queues etc. +*/ + +#include +#include +#include +#include "rom/ets_sys.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/xtensa_api.h" +#include "unity.h" +#include "soc/uart_reg.h" +#include "soc/dport_reg.h" +#include "soc/io_mux_reg.h" + + +volatile static int done; +volatile static int error; + +static void tskTestRand(void *pvParameters) +{ + int l; + srand(0x1234); + vTaskDelay((int)pvParameters / portTICK_PERIOD_MS); + l = rand(); + printf("Rand1: %d\n", l); + if (l != 869320854) { + error++; + } + vTaskDelay((int)pvParameters / portTICK_PERIOD_MS); + l = rand(); + printf("Rand2: %d\n", l); + if (l != 1148737841) { + error++; + } + done++; + vTaskDelete(NULL); +} + + + +// TODO: split this thing into separate orthogonal tests +TEST_CASE("Test for per-task non-reentrant tasks", "[freertos]") +{ + done = 0; + error = 0; + xTaskCreatePinnedToCore(tskTestRand, "tsk1", 2048, (void *)100, 3, NULL, 0); + xTaskCreatePinnedToCore(tskTestRand, "tsk2", 2048, (void *)200, 3, NULL, 0); + xTaskCreatePinnedToCore(tskTestRand, "tsk3", 2048, (void *)300, 3, NULL, 1); + xTaskCreatePinnedToCore(tskTestRand, "tsk4", 2048, (void *)400, 3, NULL, 0); + while (done != 4) { + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + TEST_ASSERT(error == 0); +} + diff --git a/components/freertos/test/test_panic.c b/components/freertos/test/test_panic.c new file mode 100644 index 0000000000..782b7a5642 --- /dev/null +++ b/components/freertos/test/test_panic.c @@ -0,0 +1,26 @@ +/* + Test for multicore FreeRTOS. This test spins up threads, fiddles with queues etc. +*/ + +#include +#include +#include "rom/ets_sys.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/xtensa_api.h" +#include "unity.h" +#include "soc/uart_reg.h" +#include "soc/dport_reg.h" +#include "soc/io_mux_reg.h" + + +TEST_CASE("Panic handler", "[freertos]") +{ + volatile int *i; + i = (volatile int *)0x0; + *i = 1; +} + diff --git a/components/freertos/test/test_ringbuf.c b/components/freertos/test/test_ringbuf.c new file mode 100644 index 0000000000..7d3c8788c9 --- /dev/null +++ b/components/freertos/test/test_ringbuf.c @@ -0,0 +1,197 @@ +/* + Test for multicore FreeRTOS ringbuffer. +*/ + +#include +#include +#include "rom/ets_sys.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/ringbuf.h" +#include "freertos/xtensa_api.h" +#include "unity.h" +#include "soc/uart_reg.h" +#include "soc/dport_reg.h" +#include "soc/io_mux_reg.h" + +#include +#include + +void ets_isr_unmask(uint32_t unmask); + +static RingbufHandle_t rb; +typedef enum { + TST_MOSTLYFILLED, + TST_MOSTLYEMPTY, + TST_INTTOTASK, + TST_TASKTOINT, +} testtype_t; + +static volatile testtype_t testtype; + +static void task1(void *arg) +{ + testtype_t oldtest; + char buf[100]; + int i = 0; + int x, r; + while (1) { + oldtest = testtype; + if (testtype == TST_MOSTLYFILLED || testtype == TST_MOSTLYEMPTY) { + for (x = 0; x < 10; x++) { + sprintf(buf, "This is test %d item %d.", (int)testtype, i++); + ets_printf("TSK w"); + xRingbufferPrintInfo(rb); + r = xRingbufferSend(rb, buf, strlen(buf) + 1, 2000 / portTICK_PERIOD_MS); + if (!r) { + printf("Test %d: Timeout on send!\n", (int)testtype); + } + if (testtype == TST_MOSTLYEMPTY) { + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + } + //Send NULL event to stop other side. + r = xRingbufferSend(rb, NULL, 0, 10000 / portTICK_PERIOD_MS); + } + while (oldtest == testtype) { + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + } +} + +static void task2(void *arg) +{ + testtype_t oldtest; + char *buf; + size_t len; + while (1) { + oldtest = testtype; + if (testtype == TST_MOSTLYFILLED || testtype == TST_MOSTLYEMPTY) { + while (1) { + ets_printf("TSK r"); + xRingbufferPrintInfo(rb); + buf = xRingbufferReceive(rb, &len, 2000 / portTICK_PERIOD_MS); + if (buf == NULL) { + printf("Test %d: Timeout on recv!\n", (int)testtype); + } else if (len == 0) { + printf("End packet received.\n"); + vRingbufferReturnItem(rb, buf); + break; + } else { + printf("Received: %s (%d bytes, %p)\n", buf, len, buf); + vRingbufferReturnItem(rb, buf); + } + if (testtype == TST_MOSTLYFILLED) { + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + } + } + while (oldtest == testtype) { + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + } +} + + + +static void uartIsrHdl(void *arg) +{ + char c; + char buf[50]; + char *item; + int r; + size_t len; + BaseType_t xHigherPriorityTaskWoken; + SET_PERI_REG_MASK(UART_INT_CLR_REG(0), UART_RXFIFO_FULL_INT_CLR); + while (READ_PERI_REG(UART_STATUS_REG(0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) { + c = READ_PERI_REG(UART_FIFO_REG(0)); + if (c == 'r') { + ets_printf("ISR r"); + xRingbufferPrintInfo(rb); + item = xRingbufferReceiveFromISR(rb, &len); + if (item == NULL) { + ets_printf("ISR recv fail!\n"); + } else if (len == 0) { + ets_printf("ISR recv NULL!\n"); + vRingbufferReturnItemFromISR(rb, item, &xHigherPriorityTaskWoken); + } else { + ets_printf("ISR recv '%s' (%d bytes, %p)\n", buf, len, buf); + vRingbufferReturnItemFromISR(rb, item, &xHigherPriorityTaskWoken); + } + } else { + sprintf(buf, "UART: %c", c); + ets_printf("ISR w"); + xRingbufferPrintInfo(rb); + r = xRingbufferSendFromISR(rb, buf, strlen(buf) + 1, &xHigherPriorityTaskWoken); + if (!r) { + ets_printf("ISR send fail\n"); + } + } + } + if (xHigherPriorityTaskWoken) { + portYIELD_FROM_ISR(); + } +} + +static void uartRxInit() +{ + uint32_t reg_val; + PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_U0TXD); + +// reg_val = READ_PERI_REG(UART_CONF1(0)); + reg_val = (1 << UART_RXFIFO_FULL_THRHD_S); + WRITE_PERI_REG(UART_CONF1_REG(0), reg_val); + CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(0), UART_TXFIFO_EMPTY_INT_ENA | UART_RXFIFO_TOUT_INT_ENA); + SET_PERI_REG_MASK(UART_INT_ENA_REG(0), UART_RXFIFO_FULL_INT_ENA); + + printf("Enabling int %d\n", ETS_UART0_INUM); + REG_SET_FIELD(DPORT_PRO_UART_INTR_MAP_REG, DPORT_PRO_UART_INTR_MAP, ETS_UART0_INUM); + REG_SET_FIELD(DPORT_PRO_UART1_INTR_MAP_REG, DPORT_PRO_UART1_INTR_MAP, ETS_UART0_INUM); + + xt_set_interrupt_handler(ETS_UART0_INUM, uartIsrHdl, NULL); + xt_ints_on(1 << ETS_UART0_INUM); + +} + +static void testRingbuffer(int type) +{ + TaskHandle_t th[2]; + int i; + rb = xRingbufferCreate(32 * 3, type); + + testtype = TST_MOSTLYFILLED; + + xTaskCreatePinnedToCore(task1 , "tskone" , 2048, NULL, 3, &th[0], 0); + xTaskCreatePinnedToCore(task2 , "tsktwo" , 2048, NULL, 3, &th[1], 0); + uartRxInit(); + + printf("Press 'r' to read an event in isr, any other key to write one.\n"); + printf("Test: mostlyfilled; putting 10 items in ringbuff ASAP, reading 1 a second\n"); + vTaskDelay(15000 / portTICK_PERIOD_MS); + printf("Test: mostlyempty; putting 10 items in ringbuff @ 1/sec, reading as fast as possible\n"); + testtype = TST_MOSTLYEMPTY; + vTaskDelay(15000 / portTICK_PERIOD_MS); + + //Shut down all the tasks + for (i = 0; i < 2; i++) { + vTaskDelete(th[i]); + } + xt_ints_off(1 << ETS_UART0_INUM); +} + +// TODO: split this thing into separate orthogonal tests +TEST_CASE("FreeRTOS ringbuffer test, no splitting items", "[freertos]") +{ + testRingbuffer(0); +} + +TEST_CASE("FreeRTOS ringbuffer test, w/ splitting items", "[freertos]") +{ + testRingbuffer(1); +} + diff --git a/components/freertos/test/test_tls_deletecb.c b/components/freertos/test/test_tls_deletecb.c new file mode 100644 index 0000000000..5277b761ab --- /dev/null +++ b/components/freertos/test/test_tls_deletecb.c @@ -0,0 +1,58 @@ +#include +#include +#include "rom/ets_sys.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/xtensa_api.h" +#include "unity.h" +#include "soc/uart_reg.h" +#include "soc/dport_reg.h" +#include "soc/io_mux_reg.h" + + + +static void tskdelcb(int no, void *arg) +{ + printf("Delete callback: %d = %p!\n", no, arg); +} + + +static void tska(void *pvParameters) +{ + vTaskSetThreadLocalStoragePointerAndDelCallback(xTaskGetCurrentTaskHandle(), 0, (void *)0xAAAAAAAA, tskdelcb); + while (1) { + vTaskDelay(10000000 / portTICK_PERIOD_MS); + } +} + +static void tskb(void *pvParameters) +{ + vTaskSetThreadLocalStoragePointerAndDelCallback(xTaskGetCurrentTaskHandle(), 0, (void *)0xBBBBBBBB, tskdelcb); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TaskHandle_t a = (TaskHandle_t)pvParameters; + printf("Killing task A\n"); + vTaskDelete(a); + while (1) { + vTaskDelay(10000000 / portTICK_PERIOD_MS); + } +} + + +// TODO: split this thing into separate orthogonal tests +TEST_CASE("Freertos TLS delete cb", "[freertos]") +{ + TaskHandle_t a, b; + + xTaskCreatePinnedToCore(tska , "tska" , 2048, NULL, 3, &a, 0); + xTaskCreatePinnedToCore(tskb , "tska" , 2048, a, 3, &b, 0); + + // Let stuff run for 20s + vTaskDelay(5000 / portTICK_PERIOD_MS); + printf("Killing task B\n"); + //Shut down b + vTaskDelete(b); +} + diff --git a/components/mbedtls/test/component.mk b/components/mbedtls/test/component.mk new file mode 100644 index 0000000000..5dd172bdb7 --- /dev/null +++ b/components/mbedtls/test/component.mk @@ -0,0 +1,5 @@ +# +#Component Makefile +# + +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/mbedtls/test/test_mbedtls.c b/components/mbedtls/test/test_mbedtls.c new file mode 100644 index 0000000000..797c107efb --- /dev/null +++ b/components/mbedtls/test/test_mbedtls.c @@ -0,0 +1,134 @@ +/* mbedTLS internal tests wrapped into Unity + + Focus on testing functionality where we use ESP32 hardware + accelerated crypto features. + + See also test_hwcrypto.c +*/ +#include +#include +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" +#include "mbedtls/aes.h" +#include "mbedtls/bignum.h" +#include "unity.h" + +static int mbedtls_alt_sha256_self_test( int verbose ); + +TEST_CASE("mbedtls SHA self-tests", "[mbedtls]") +{ + TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha1_self_test(1), "SHA1 self-tests should pass."); + TEST_ASSERT_FALSE_MESSAGE(mbedtls_alt_sha256_self_test(1), "SHA256 self-tests should pass."); + TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha512_self_test(1), "SHA512 self-tests should pass."); +} + +TEST_CASE("mbedtls AES self-tests", "[aes]") +{ + TEST_ASSERT_FALSE_MESSAGE(mbedtls_aes_self_test(1), "AES self-tests should pass."); +} + +TEST_CASE("mbedtls MPI self-tests", "[bignum]") +{ + TEST_ASSERT_FALSE_MESSAGE(mbedtls_mpi_self_test(1), "MPI self-tests should pass."); +} + + +/* Following code is a copy of the mbedtls_sha256 test vectors, + with the SHA-224 support removed as we don't currently support this hash. +*/ + +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha256_test_buf[3][57] = { + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const int sha256_test_buflen[3] = { + 3, 56, 1000 +}; + +static const unsigned char sha256_test_sum[6][32] = { + /* + * SHA-256 test vectors + */ + { + 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD + }, + { + 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, + 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, + 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, + 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 + }, + { + 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, + 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, + 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, + 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 + } +}; + +/* + * Checkup routine + */ +static int mbedtls_alt_sha256_self_test( int verbose ) +{ + int j, n, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha256sum[32]; + mbedtls_sha256_context ctx; + + for ( j = 0; j < 3; j++ ) { + mbedtls_sha256_init( &ctx ); + + if ( verbose != 0 ) { + printf( " SHA-%d test #%d: ", 256, j + 1 ); + } + + mbedtls_sha256_starts( &ctx, 0 ); + + if ( j == 2 ) { + memset( buf, 'a', buflen = 1000 ); + + for ( n = 0; n < 1000; n++ ) { + mbedtls_sha256_update( &ctx, buf, buflen ); + } + } else + mbedtls_sha256_update( &ctx, sha256_test_buf[j], + sha256_test_buflen[j] ); + + mbedtls_sha256_finish( &ctx, sha256sum ); + + if ( memcmp( sha256sum, sha256_test_sum[j], 32 ) != 0 ) { + if ( verbose != 0 ) { + printf( "failed\n" ); + } + + mbedtls_sha256_free( &ctx ); + + ret = 1; + goto exit; + } + + if ( verbose != 0 ) { + printf( "passed\n" ); + } + + mbedtls_sha256_free( &ctx ); + } + + if ( verbose != 0 ) { + printf( "\n" ); + } + +exit: + + return ( ret ); +} diff --git a/components/newlib/test/component.mk b/components/newlib/test/component.mk new file mode 100644 index 0000000000..5dd172bdb7 --- /dev/null +++ b/components/newlib/test/component.mk @@ -0,0 +1,5 @@ +# +#Component Makefile +# + +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/newlib/test/test_newlib.c b/components/newlib/test/test_newlib.c new file mode 100644 index 0000000000..b498b4bd43 --- /dev/null +++ b/components/newlib/test/test_newlib.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include "unity.h" + + +TEST_CASE("test ctype functions", "[newlib]") +{ + TEST_ASSERT_TRUE( isalnum('a') && isalnum('A') && isalnum('z') && isalnum('Z') && isalnum('0') && isalnum('9') ); + TEST_ASSERT_FALSE( isalnum('(') || isalnum('-') || isalnum(' ') || isalnum('\x81') || isalnum('.') || isalnum('\\') ); + TEST_ASSERT_TRUE( isalpha('a') && isalpha('A') && isalpha('z') && isalpha('Z') ); + TEST_ASSERT_FALSE( isalpha('0') || isalpha('9') || isalpha(')') || isalpha('\t') || isalpha(' ') || isalpha('\x81') ); + TEST_ASSERT_TRUE( isspace(' ') && isspace('\t') && isspace('\n') && isspace('\r') ); + TEST_ASSERT_FALSE( isspace('0') || isspace('9') || isspace(')') || isspace('A') || isspace('*') || isspace('\x81') || isspace('a')); +} + +TEST_CASE("test atoX functions", "[newlib]") +{ + TEST_ASSERT_EQUAL_INT(-2147483648, atoi("-2147483648")); + TEST_ASSERT_EQUAL_INT(2147483647, atoi("2147483647")); + TEST_ASSERT_EQUAL_INT(42, atoi("000000042")); + TEST_ASSERT_EQUAL_INT(0, strtol("foo", NULL, 10)); +} + +TEST_CASE("test sprintf function", "[newlib]") +{ + char *res = NULL; + asprintf(&res, "%d %011i %lu %p %x %c %.4f\n", 42, 2147483647, 2147483648UL, (void *) 0x40010000, 0x40020000, 'Q', 1.0f / 137.0f); + TEST_ASSERT_NOT_NULL(res); + TEST_ASSERT_EQUAL_STRING(res, "42 02147483647 2147483648 0x40010000 40020000 Q 0.0073\n"); + free(res); +} + +TEST_CASE("test sscanf function", "[newlib]") +{ + const char *src = "42 02147483647 2147483648 0x40010000 40020000 Q 0.0073\n"; + int fourty_two; + int int_max; + unsigned long int_max_plus_one; + void *iram_ptr; + int irom_ptr; + char department; + float inv_fine_structure_constant; + int res = sscanf(src, "%d %d %lu %p %x %c %f", &fourty_two, &int_max, &int_max_plus_one, &iram_ptr, &irom_ptr, &department, &inv_fine_structure_constant); + TEST_ASSERT_EQUAL(7, res); + TEST_ASSERT_EQUAL(42, fourty_two); + TEST_ASSERT_EQUAL(2147483647, int_max); + TEST_ASSERT_EQUAL_UINT32(2147483648UL, int_max_plus_one); + TEST_ASSERT_EQUAL(0x40010000, iram_ptr); + TEST_ASSERT_EQUAL(0x40020000, irom_ptr); + TEST_ASSERT_EQUAL('Q', department); + TEST_ASSERT_TRUE(1.0f / inv_fine_structure_constant > 136 && 1.0f / inv_fine_structure_constant < 138); +} + +TEST_CASE("test time functions", "[newlib]") +{ + time_t now = 1464248488; + setenv("TZ", "UTC-8", 1); + struct tm *tm_utc = gmtime(&now); + TEST_ASSERT_EQUAL( 28, tm_utc->tm_sec); + TEST_ASSERT_EQUAL( 41, tm_utc->tm_min); + TEST_ASSERT_EQUAL( 7, tm_utc->tm_hour); + TEST_ASSERT_EQUAL( 26, tm_utc->tm_mday); + TEST_ASSERT_EQUAL( 4, tm_utc->tm_mon); + TEST_ASSERT_EQUAL(116, tm_utc->tm_year); + TEST_ASSERT_EQUAL( 4, tm_utc->tm_wday); + TEST_ASSERT_EQUAL(146, tm_utc->tm_yday); + + struct tm *tm_local = localtime(&now); + TEST_ASSERT_EQUAL( 28, tm_local->tm_sec); + TEST_ASSERT_EQUAL( 41, tm_local->tm_min); + TEST_ASSERT_EQUAL( 15, tm_local->tm_hour); + TEST_ASSERT_EQUAL( 26, tm_local->tm_mday); + TEST_ASSERT_EQUAL( 4, tm_local->tm_mon); + TEST_ASSERT_EQUAL(116, tm_local->tm_year); + TEST_ASSERT_EQUAL( 4, tm_local->tm_wday); + TEST_ASSERT_EQUAL(146, tm_local->tm_yday); + +} + + +static int checkFnRom(void *fn, char *name) +{ + int fnaddr = (int)fn; + printf("%s: 0X%x\n", name, fnaddr); + if ((fnaddr >= 0x40000000) && (fnaddr < 0x40070000)) { + return 1; + } else { + return 0; + } +} + + +TEST_CASE("check if ROM is used for functions", "[newlib]") +{ + TEST_ASSERT(checkFnRom(printf, "printf")); + TEST_ASSERT(checkFnRom(sscanf, "sscanf")); + TEST_ASSERT(checkFnRom(atoi, "atoi")); + TEST_ASSERT(checkFnRom(strtol, "strtol")); +} \ No newline at end of file diff --git a/components/nvs_flash/test/component.mk b/components/nvs_flash/test/component.mk new file mode 100644 index 0000000000..5dd172bdb7 --- /dev/null +++ b/components/nvs_flash/test/component.mk @@ -0,0 +1,5 @@ +# +#Component Makefile +# + +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/nvs_flash/test/test_nvs.c b/components/nvs_flash/test/test_nvs.c new file mode 100644 index 0000000000..c523026432 --- /dev/null +++ b/components/nvs_flash/test/test_nvs.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include "unity.h" +#include "nvs.h" +#include "nvs_flash.h" +#include "esp_spi_flash.h" +#include + +#define NVS_FLASH_SECTOR 6 +#define NVS_FLASH_SECTOR_COUNT_MIN 3 +#define NVS_FLASH_SECTOR_COUNT_MAX 10 + +TEST_CASE("various nvs tests", "[nvs]") +{ + nvs_handle handle_1; + TEST_ESP_ERR(nvs_open("namespace1", NVS_READWRITE, &handle_1), ESP_ERR_NVS_NOT_INITIALIZED); + for (uint16_t i = NVS_FLASH_SECTOR; i < NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN; ++i) { + spi_flash_erase_sector(i); + } + TEST_ESP_OK(nvs_flash_init_custom(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)); + + TEST_ESP_ERR(nvs_open("namespace1", NVS_READONLY, &handle_1), ESP_ERR_NVS_NOT_FOUND); + + // TEST_ESP_ERR(nvs_set_i32(handle_1, "foo", 0x12345678), ESP_ERR_NVS_READ_ONLY); + // nvs_close(handle_1); + + TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle_1)); + TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x12345678)); + TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x23456789)); + + nvs_handle handle_2; + TEST_ESP_OK(nvs_open("namespace2", NVS_READWRITE, &handle_2)); + TEST_ESP_OK(nvs_set_i32(handle_2, "foo", 0x3456789a)); + const char *str = "value 0123456789abcdef0123456789abcdef"; + TEST_ESP_OK(nvs_set_str(handle_2, "key", str)); + + int32_t v1; + TEST_ESP_OK(nvs_get_i32(handle_1, "foo", &v1)); + TEST_ASSERT_EQUAL_INT32(0x23456789, v1); + + int32_t v2; + TEST_ESP_OK(nvs_get_i32(handle_2, "foo", &v2)); + TEST_ASSERT_EQUAL_INT32(0x3456789a, v2); + + char buf[strlen(str) + 1]; + size_t buf_len = sizeof(buf); + + TEST_ESP_OK(nvs_get_str(handle_2, "key", buf, &buf_len)); + + TEST_ASSERT_EQUAL_INT32(0, strcmp(buf, str)); +} diff --git a/components/nvs_flash/test/Makefile b/components/nvs_flash/test_nvs_host/Makefile similarity index 100% rename from components/nvs_flash/test/Makefile rename to components/nvs_flash/test_nvs_host/Makefile diff --git a/components/nvs_flash/test/catch.hpp b/components/nvs_flash/test_nvs_host/catch.hpp similarity index 100% rename from components/nvs_flash/test/catch.hpp rename to components/nvs_flash/test_nvs_host/catch.hpp diff --git a/components/nvs_flash/test/crc.cpp b/components/nvs_flash/test_nvs_host/crc.cpp similarity index 100% rename from components/nvs_flash/test/crc.cpp rename to components/nvs_flash/test_nvs_host/crc.cpp diff --git a/components/nvs_flash/test/crc.h b/components/nvs_flash/test_nvs_host/crc.h similarity index 100% rename from components/nvs_flash/test/crc.h rename to components/nvs_flash/test_nvs_host/crc.h diff --git a/components/nvs_flash/test/main.cpp b/components/nvs_flash/test_nvs_host/main.cpp similarity index 100% rename from components/nvs_flash/test/main.cpp rename to components/nvs_flash/test_nvs_host/main.cpp diff --git a/components/nvs_flash/test/sdkconfig.h b/components/nvs_flash/test_nvs_host/sdkconfig.h similarity index 100% rename from components/nvs_flash/test/sdkconfig.h rename to components/nvs_flash/test_nvs_host/sdkconfig.h diff --git a/components/nvs_flash/test/spi_flash_emulation.cpp b/components/nvs_flash/test_nvs_host/spi_flash_emulation.cpp similarity index 100% rename from components/nvs_flash/test/spi_flash_emulation.cpp rename to components/nvs_flash/test_nvs_host/spi_flash_emulation.cpp diff --git a/components/nvs_flash/test/spi_flash_emulation.h b/components/nvs_flash/test_nvs_host/spi_flash_emulation.h similarity index 100% rename from components/nvs_flash/test/spi_flash_emulation.h rename to components/nvs_flash/test_nvs_host/spi_flash_emulation.h diff --git a/components/nvs_flash/test/test_compressed_enum_table.cpp b/components/nvs_flash/test_nvs_host/test_compressed_enum_table.cpp similarity index 100% rename from components/nvs_flash/test/test_compressed_enum_table.cpp rename to components/nvs_flash/test_nvs_host/test_compressed_enum_table.cpp diff --git a/components/nvs_flash/test/test_intrusive_list.cpp b/components/nvs_flash/test_nvs_host/test_intrusive_list.cpp similarity index 100% rename from components/nvs_flash/test/test_intrusive_list.cpp rename to components/nvs_flash/test_nvs_host/test_intrusive_list.cpp diff --git a/components/nvs_flash/test/test_nvs.cpp b/components/nvs_flash/test_nvs_host/test_nvs.cpp similarity index 100% rename from components/nvs_flash/test/test_nvs.cpp rename to components/nvs_flash/test_nvs_host/test_nvs.cpp diff --git a/components/nvs_flash/test/test_spi_flash_emulation.cpp b/components/nvs_flash/test_nvs_host/test_spi_flash_emulation.cpp similarity index 100% rename from components/nvs_flash/test/test_spi_flash_emulation.cpp rename to components/nvs_flash/test_nvs_host/test_spi_flash_emulation.cpp diff --git a/components/partition_table/test/component.mk b/components/partition_table/test/component.mk new file mode 100644 index 0000000000..5dd172bdb7 --- /dev/null +++ b/components/partition_table/test/component.mk @@ -0,0 +1,5 @@ +# +#Component Makefile +# + +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/partition_table/test/test_partition.c b/components/partition_table/test/test_partition.c new file mode 100644 index 0000000000..a4288d8e1d --- /dev/null +++ b/components/partition_table/test/test_partition.c @@ -0,0 +1,95 @@ +#include +#include +#include "unity.h" +#include "esp_partition.h" + + +TEST_CASE("Can read partition table", "[partition]") +{ + + const esp_partition_t *p = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL); + TEST_ASSERT_NOT_NULL(p); + TEST_ASSERT_EQUAL(p->address, 0x10000); + TEST_ASSERT_EQUAL(p->subtype, ESP_PARTITION_SUBTYPE_APP_FACTORY); + + esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, NULL); + TEST_ASSERT_NOT_NULL(it); + int count = 0; + for (; it != NULL; it = esp_partition_next(it)) { + const esp_partition_t *p = esp_partition_get(it); + TEST_ASSERT_NOT_NULL(p); + ++count; + } + esp_partition_iterator_release(it); + TEST_ASSERT_EQUAL(count, 2); + + printf("%d\n", __builtin_clz(count)); +} + +TEST_CASE("Can write, read, mmap partition", "[partition]") +{ + const esp_partition_t *p = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, NULL); + TEST_ASSERT_NOT_NULL(p); + const size_t max_size = 2 * SPI_FLASH_SEC_SIZE; + uint8_t *data = (uint8_t *) malloc(max_size); + TEST_ASSERT_NOT_NULL(data); + + TEST_ASSERT_EQUAL(ESP_OK, esp_partition_erase_range(p, 0, p->size)); + + srand(0); + size_t block_size; + for (size_t offset = 0; offset < p->size; offset += block_size) { + block_size = ((rand() + 4) % max_size) & (~0x3); + size_t left = p->size - offset; + if (block_size > left) { + block_size = left; + } + for (size_t i = 0; i < block_size / 4; ++i) { + ((uint32_t *) (data))[i] = rand(); + if (i == 0 && offset == 0) { + printf("write: %08x\n", ((uint32_t *) (data))[i]); + } + } + TEST_ASSERT_EQUAL(ESP_OK, esp_partition_write(p, offset, data, block_size)); + } + + srand(0); + for (size_t offset = 0; offset < p->size; offset += block_size) { + block_size = ((rand() + 4) % max_size) & (~0x3); + size_t left = p->size - offset; + if (block_size > left) { + block_size = left; + } + TEST_ASSERT_EQUAL(ESP_OK, esp_partition_read(p, offset, data, block_size)); + for (size_t i = 0; i < block_size / 4; ++i) { + TEST_ASSERT_EQUAL(rand(), ((uint32_t *) data)[i]); + } + } + + free(data); + + const uint32_t *mmap_data; + spi_flash_mmap_handle_t mmap_handle; + size_t begin = 3000; + size_t size = 12000; + TEST_ASSERT_EQUAL(ESP_OK, esp_partition_mmap(p, begin, size, SPI_FLASH_MMAP_DATA, + (const void **)&mmap_data, &mmap_handle)); + srand(0); + for (size_t offset = 0; offset < p->size; offset += block_size) { + block_size = ((rand() + 4) % max_size) & (~0x3); + size_t left = p->size - offset; + if (block_size > left) { + block_size = left; + } + for (size_t i = 0; i < block_size / 4; ++i) { + size_t pos = offset + i * 4; + uint32_t expected = rand(); + if (pos < begin || pos >= (begin + size)) { + continue; + } + TEST_ASSERT_EQUAL(expected, mmap_data[(pos - begin) / 4]); + } + } + + spi_flash_munmap(mmap_handle); +} diff --git a/components/spi_flash/test/component.mk b/components/spi_flash/test/component.mk new file mode 100644 index 0000000000..5dd172bdb7 --- /dev/null +++ b/components/spi_flash/test/component.mk @@ -0,0 +1,5 @@ +# +#Component Makefile +# + +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/spi_flash/test/test_mmap.c b/components/spi_flash/test/test_mmap.c new file mode 100644 index 0000000000..28d9ae6dda --- /dev/null +++ b/components/spi_flash/test/test_mmap.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +uint32_t buffer[1024]; + +static const uint32_t start = 0x200000; +static const uint32_t end = 0x300000; + + + +TEST_CASE("Prepare data for mmap tests", "[mmap]") +{ + srand(0); + for (int block = start / 0x10000; block < end / 0x10000; ++block) { + printf("Writing block %d\n", block); + for (int sector = 0; sector < 16; ++sector) { + for (uint32_t word = 0; word < 1024; ++word) { + uint32_t val = rand(); + if (block == start / 0x10000 && sector == 0 && word == 0) { + printf("first word: %08x\n", val); + } + buffer[word] = val; + } + uint32_t abs_sector = (block) * 16 + sector; + printf("Writing sector %d\n", abs_sector); + ESP_ERROR_CHECK( spi_flash_erase_sector((uint16_t) abs_sector) ); + ESP_ERROR_CHECK( spi_flash_write(abs_sector * SPI_FLASH_SEC_SIZE, (const uint8_t *) buffer, sizeof(buffer)) ); + } + } +} + +TEST_CASE("Can mmap into data address space", "[mmap]") +{ + + printf("Mapping %x (+%x)\n", start, end - start); + spi_flash_mmap_handle_t handle1; + const void *ptr1; + ESP_ERROR_CHECK( spi_flash_mmap(start, end - start, SPI_FLASH_MMAP_DATA, &ptr1, &handle1) ); + printf("mmap_res: handle=%d ptr=%p\n", handle1, ptr1); + + spi_flash_mmap_dump(); + + srand(0); + const uint32_t *data = (const uint32_t *) ptr1; + for (int block = 0; block < (end - start) / 0x10000; ++block) { + for (int sector = 0; sector < 16; ++sector) { + for (uint32_t word = 0; word < 1024; ++word) { + TEST_ASSERT_EQUAL_UINT32(rand(), data[(block * 16 + sector) * 1024 + word]); + } + } + } + printf("Mapping %x (+%x)\n", start - 0x10000, 0x20000); + spi_flash_mmap_handle_t handle2; + const void *ptr2; + ESP_ERROR_CHECK( spi_flash_mmap(start - 0x10000, 0x20000, SPI_FLASH_MMAP_DATA, &ptr2, &handle2) ); + printf("mmap_res: handle=%d ptr=%p\n", handle2, ptr2); + spi_flash_mmap_dump(); + + printf("Mapping %x (+%x)\n", start, 0x10000); + spi_flash_mmap_handle_t handle3; + const void *ptr3; + ESP_ERROR_CHECK( spi_flash_mmap(start, 0x10000, SPI_FLASH_MMAP_DATA, &ptr3, &handle3) ); + printf("mmap_res: handle=%d ptr=%p\n", handle3, ptr3); + spi_flash_mmap_dump(); + + printf("Unmapping handle1\n"); + spi_flash_munmap(handle1); + spi_flash_mmap_dump(); + + printf("Unmapping handle2\n"); + spi_flash_munmap(handle2); + spi_flash_mmap_dump(); + + printf("Unmapping handle3\n"); + spi_flash_munmap(handle3); +} diff --git a/components/spi_flash/test/test_spi_flash.c b/components/spi_flash/test/test_spi_flash.c new file mode 100644 index 0000000000..330e37bb82 --- /dev/null +++ b/components/spi_flash/test/test_spi_flash.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include + +#include +#include +#include + +struct flash_test_ctx { + uint32_t offset[2]; + bool fail[2]; + SemaphoreHandle_t done; +}; + +static void flash_test_task(void *arg) +{ + const uint32_t coreid = xPortGetCoreID(); + ets_printf("t%d\n", coreid); + struct flash_test_ctx *ctx = (struct flash_test_ctx *) arg; + vTaskDelay(100 / portTICK_PERIOD_MS); + const uint32_t sector = ctx->offset[coreid]; + ets_printf("es%d\n", coreid); + if (spi_flash_erase_sector(sector) != ESP_OK) { + ctx->fail[coreid] = true; + ets_printf("Erase failed\r\n"); + xSemaphoreGive(ctx->done); + vTaskDelete(NULL); + } + ets_printf("ed%d\n", coreid); + + vTaskDelay(0 / portTICK_PERIOD_MS); + + uint32_t val = 0xabcd1234; + const uint32_t n = 4096; + for (uint32_t offset = 0; offset < n; offset += 4) { + if (spi_flash_write(sector * SPI_FLASH_SEC_SIZE + offset, (const uint8_t *) &val, 4) != ESP_OK) { + ets_printf("Write failed at offset=%d\r\n", offset); + ctx->fail[coreid] = true; + break; + } + } + ets_printf("wd%d\n", coreid); + + vTaskDelay(0 / portTICK_PERIOD_MS); + + uint32_t val_read; + for (uint32_t offset = 0; offset < n; offset += 4) { + if (spi_flash_read(sector * SPI_FLASH_SEC_SIZE + offset, (uint8_t *) &val_read, 4) != ESP_OK) { + ets_printf("Read failed at offset=%d\r\n", offset); + ctx->fail[coreid] = true; + break; + } + if (val_read != val) { + ets_printf("Read invalid value=%08x at offset=%d\r\n", val_read, offset); + ctx->fail[coreid] = true; + break; + } + } + ets_printf("td%d\n", coreid); + xSemaphoreGive(ctx->done); + vTaskDelete(NULL); +} + +TEST_CASE("flash write and erase work both on PRO CPU and on APP CPU", "[spi_flash]") +{ + TaskHandle_t procpu_task; + TaskHandle_t appcpu_task; + struct flash_test_ctx ctx; + + ctx.offset[0] = 6; + ctx.offset[1] = 7; + ctx.fail[0] = 0; + ctx.fail[1] = 0; + ctx.done = xSemaphoreCreateBinary(); + + xTaskCreatePinnedToCore(flash_test_task, "1", 2048, &ctx, 3, &procpu_task, 0); + if (portNUM_PROCESSORS == 2) { + xTaskCreatePinnedToCore(flash_test_task, "2", 2048, &ctx, 3, &appcpu_task, 1); + } + + xSemaphoreTake(ctx.done, portMAX_DELAY); + if (portNUM_PROCESSORS == 2) { + xSemaphoreTake(ctx.done, portMAX_DELAY); + } + + TEST_ASSERT_EQUAL(false, ctx.fail[0]); + if (portNUM_PROCESSORS == 2) { + TEST_ASSERT_EQUAL(false, ctx.fail[1]); + } +} + diff --git a/make/component_wrapper.mk b/make/component_wrapper.mk index 3018c18b55..16c9c02b5f 100644 --- a/make/component_wrapper.mk +++ b/make/component_wrapper.mk @@ -32,9 +32,6 @@ include $(IDF_PATH)/make/common.mk # Some of the following defaults may be overriden by the component's component.mk makefile, # during the next step: -# Name of the component -COMPONENT_NAME := $(lastword $(subst /, ,$(realpath $(COMPONENT_PATH)))) - # Absolute path of the .a file COMPONENT_LIBRARY = lib$(COMPONENT_NAME).a diff --git a/make/project.mk b/make/project.mk index 870db55f97..0dfce4368a 100644 --- a/make/project.mk +++ b/make/project.mk @@ -94,6 +94,12 @@ COMPONENT_PATHS += $(abspath $(SRCDIRS)) # A component is buildable if it has a component.mk makefile in it COMPONENT_PATHS_BUILDABLE := $(foreach cp,$(COMPONENT_PATHS),$(if $(wildcard $(cp)/component.mk),$(cp))) +# If TEST_COMPONENTS is set on the command line, create variables for building unit tests +ifdef TEST_COMPONENTS +TEST_COMPONENT_PATHS := $(foreach comp,$(TEST_COMPONENTS),$(IDF_PATH)/components/$(comp)/test) +TEST_COMPONENT_NAMES := $(foreach comp,$(TEST_COMPONENTS),$(comp)_test) +endif + # Initialise project-wide variables which can be added to by # each component. # @@ -113,7 +119,7 @@ COMPONENT_SUBMODULES := # dependencies. # # See the component_project_vars.mk target in component_wrapper.mk -COMPONENT_PROJECT_VARS := $(addsuffix /component_project_vars.mk,$(notdir $(COMPONENT_PATHS_BUILDABLE))) +COMPONENT_PROJECT_VARS := $(addsuffix /component_project_vars.mk,$(notdir $(COMPONENT_PATHS_BUILDABLE) ) $(TEST_COMPONENT_NAMES)) COMPONENT_PROJECT_VARS := $(addprefix $(BUILD_DIR_BASE)/,$(COMPONENT_PROJECT_VARS)) # this line is -include instead of include to prevent a spurious error message on make 3.81 -include $(COMPONENT_PROJECT_VARS) @@ -140,7 +146,7 @@ endif LDFLAGS ?= -nostdlib \ -L$(IDF_PATH)/lib \ -L$(IDF_PATH)/ld \ - $(addprefix -L$(BUILD_DIR_BASE)/,$(COMPONENTS) $(SRCDIRS)) \ + $(addprefix -L$(BUILD_DIR_BASE)/,$(COMPONENTS) $(TEST_COMPONENT_NAMES) $(SRCDIRS) ) \ -u call_user_start_cpu0 \ $(EXTRA_LDFLAGS) \ -Wl,--gc-sections \ @@ -257,7 +263,7 @@ endif # A "component" library is any library in the LDFLAGS where # the name of the library is also a name of the component APP_LIBRARIES = $(patsubst -l%,%,$(filter -l%,$(LDFLAGS))) -COMPONENT_LIBRARIES = $(filter $(notdir $(COMPONENT_PATHS_BUILDABLE)),$(APP_LIBRARIES)) +COMPONENT_LIBRARIES = $(filter $(notdir $(COMPONENT_PATHS_BUILDABLE)) $(TEST_COMPONENT_NAMES),$(APP_LIBRARIES)) # ELF depends on the library archive files for COMPONENT_LIBRARIES # the rules to build these are emitted as part of GenerateComponentTarget below @@ -282,7 +288,7 @@ $(BUILD_DIR_BASE): # # Is recursively expanded by the GenerateComponentTargets macro define ComponentMake -+$(MAKE) -C $(BUILD_DIR_BASE)/$(2) -f $(IDF_PATH)/make/component_wrapper.mk COMPONENT_MAKEFILE=$(1)/component.mk ++$(MAKE) -C $(BUILD_DIR_BASE)/$(2) -f $(IDF_PATH)/make/component_wrapper.mk COMPONENT_MAKEFILE=$(1)/component.mk COMPONENT_NAME=$(2) endef # Generate top-level component-specific targets for each component @@ -325,6 +331,7 @@ $(BUILD_DIR_BASE)/$(2)/component_project_vars.mk: $(1)/component.mk $(COMMON_MAK endef $(foreach component,$(COMPONENT_PATHS_BUILDABLE),$(eval $(call GenerateComponentTargets,$(component),$(notdir $(component))))) +$(foreach component,$(TEST_COMPONENT_PATHS),$(eval $(call GenerateComponentTargets,$(component),$(lastword $(subst /, ,$(dir $(component))))_test))) app-clean: $(addsuffix -clean,$(notdir $(COMPONENT_PATHS_BUILDABLE))) $(summary) RM $(APP_ELF) diff --git a/tools/unit-test-app/Makefile b/tools/unit-test-app/Makefile new file mode 100644 index 0000000000..128e8a0804 --- /dev/null +++ b/tools/unit-test-app/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := unit-test-app + +include $(IDF_PATH)/make/project.mk + diff --git a/tools/unit-test-app/README.md b/tools/unit-test-app/README.md new file mode 100644 index 0000000000..cf45ce287b --- /dev/null +++ b/tools/unit-test-app/README.md @@ -0,0 +1,12 @@ +# Unit Test App + +ESP-IDF unit tests are run using Unit Test App. The app can be built with the unit tests for a specific component. Unit tests are in `test` subdirectories of respective components. + +# Building Unit Test App + +* Follow the setup instructions in the top-level esp-idf README. +* Set IDF_PATH environment variable to point to the path to the esp-idf top-level directory. +* Change into `tools/unit-test-app` directory +* `make menuconfig` to configure the Unit Test App. +* `make TEST_COMPONENTS=` with `TEST_COMPONENTS` set to names of the components to be included in the test app. +* Follow the printed instructions to flash, or run `make flash`. diff --git a/tools/unit-test-app/components/unity/component.mk b/tools/unit-test-app/components/unity/component.mk new file mode 100644 index 0000000000..ebd7a7d59b --- /dev/null +++ b/tools/unit-test-app/components/unity/component.mk @@ -0,0 +1,3 @@ +# +# Component Makefile +# diff --git a/tools/unit-test-app/components/unity/include/unity.h b/tools/unit-test-app/components/unity/include/unity.h new file mode 100644 index 0000000000..3ffc14c0b8 --- /dev/null +++ b/tools/unit-test-app/components/unity/include/unity.h @@ -0,0 +1,292 @@ +/* ========================================== + Unity Project - A Test Framework for C + Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +========================================== */ + +#ifndef UNITY_FRAMEWORK_H +#define UNITY_FRAMEWORK_H +#define UNITY + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define UNITY_INCLUDE_CONFIG_H +#include "unity_internals.h" + +void setUp(void); +void tearDown(void); + +/*------------------------------------------------------- + * Configuration Options + *------------------------------------------------------- + * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above. + + * Integers/longs/pointers + * - Unity attempts to automatically discover your integer sizes + * - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in + * - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in + * - define UNITY_EXCLUDE_SIZEOF to stop attempting to use sizeof in macros + * - If you cannot use the automatic methods above, you can force Unity by using these options: + * - define UNITY_SUPPORT_64 + * - define UNITY_INT_WIDTH + * - UNITY_LONG_WIDTH + * - UNITY_POINTER_WIDTH + + * Floats + * - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons + * - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT + * - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats + * - define UNITY_FLOAT_VERBOSE to print floating point values in errors (uses sprintf) + * - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons + * - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default) + * - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE + * - define UNITY_DOUBLE_TYPE to specify something other than double + * - define UNITY_DOUBLE_VERBOSE to print floating point values in errors (uses sprintf) + * - define UNITY_VERBOSE_NUMBER_MAX_LENGTH to change maximum length of printed numbers (used by sprintf) + + * Output + * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired + * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure + + * Optimization + * - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge + * - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests. + + * Test Cases + * - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script + + * Parameterized Tests + * - you'll want to create a define of TEST_CASE(...) which basically evaluates to nothing + + *------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message)) +#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL) +#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message)) +#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL) +#define TEST_ONLY() + +/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails. + * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ +#define TEST_PASS() longjmp(Unity.AbortFrame, 1) + +/*------------------------------------------------------- + * Test Asserts (simple) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE") +#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE") +#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE") +#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE") +#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL") +#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL") + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (_UU32)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (_UU32)(0), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((_UU32)1 << (bit)), (_UU32)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((_UU32)1 << (bit)), (_UU32)(0), (actual), __LINE__, NULL) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL) + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/*------------------------------------------------------- + * Test Asserts (with additional messages) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message)) + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (_UU32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (_UU32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((_UU32)1 << (bit)), (_UU32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((_UU32)1 << (bit)), (_UU32)(0), (actual), __LINE__, (message)) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message)) + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message)) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message)) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* end of UNITY_FRAMEWORK_H */ +#ifdef __cplusplus +} +#endif +#endif diff --git a/tools/unit-test-app/components/unity/include/unity_config.h b/tools/unit-test-app/components/unity/include/unity_config.h new file mode 100644 index 0000000000..b8e56a79c1 --- /dev/null +++ b/tools/unit-test-app/components/unity/include/unity_config.h @@ -0,0 +1,75 @@ +#ifndef UNITY_CONFIG_H +#define UNITY_CONFIG_H + +// This file gets included from unity.h via unity_internals.h +// It is inside #ifdef __cplusplus / extern "C" block, so we can +// only use C features here + +// Adapt Unity to our environment, disable FP support + +#include + +#define UNITY_EXCLUDE_FLOAT +#define UNITY_EXCLUDE_DOUBLE + +#define UNITY_OUTPUT_CHAR unity_putc +#define UNITY_OUTPUT_FLUSH unity_flush + +// Define helpers to register test cases from multiple files + +#define UNITY_EXPAND2(a, b) a ## b +#define UNITY_EXPAND(a, b) UNITY_EXPAND2(a, b) +#define UNITY_TEST_UID(what) UNITY_EXPAND(what, __LINE__) + +#define UNITY_TEST_REG_HELPER reg_helper ## UNITY_TEST_UID +#define UNITY_TEST_DESC_UID desc ## UNITY_TEST_UID +struct test_desc_t +{ + const char* name; + const char* desc; + void (*fn)(void); + const char* file; + int line; + struct test_desc_t* next; +}; + +void unity_testcase_register(struct test_desc_t* desc); + +void unity_run_menu(); + +void unity_run_tests_with_filter(const char* filter); + +void unity_run_all_tests(); + +/* Test case macro, a-la CATCH framework. + First argument is a free-form description, + second argument is (by convention) a list of identifiers, each one in square brackets. + Identifiers are used to group related tests, or tests with specific properties. + Use like: + + TEST_CASE("Frobnicator forbnicates", "[frobnicator][rom]") + { + // test goes here + } +*/ +#define TEST_CASE(name_, desc_) \ + static void UNITY_TEST_UID(test_func_) (void); \ + static void __attribute__((constructor)) UNITY_TEST_UID(test_reg_helper_) () \ + { \ + static struct test_desc_t UNITY_TEST_UID(test_desc_) = { \ + .name = name_, \ + .desc = desc_, \ + .fn = &UNITY_TEST_UID(test_func_), \ + .file = __FILE__, \ + .line = __LINE__ \ + }; \ + unity_testcase_register( & UNITY_TEST_UID(test_desc_) ); \ + }\ + static void UNITY_TEST_UID(test_func_) (void) + +// shorthand to check esp_err_t return code +#define TEST_ESP_OK(rc) TEST_ASSERT_EQUAL_INT32(ESP_OK, rc) +#define TEST_ESP_ERR(err, rc) TEST_ASSERT_EQUAL_INT32(err, rc) + + +#endif //UNITY_CONFIG_H diff --git a/tools/unit-test-app/components/unity/include/unity_internals.h b/tools/unit-test-app/components/unity/include/unity_internals.h new file mode 100644 index 0000000000..03d196f4f6 --- /dev/null +++ b/tools/unit-test-app/components/unity/include/unity_internals.h @@ -0,0 +1,772 @@ +/* ========================================== + Unity Project - A Test Framework for C + Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +========================================== */ + +#ifndef UNITY_INTERNALS_H +#define UNITY_INTERNALS_H + +#ifdef UNITY_INCLUDE_CONFIG_H +#include "unity_config.h" +#endif + +#include + +/* Unity Attempts to Auto-Detect Integer Types + * Attempt 1: UINT_MAX, ULONG_MAX, etc in + * Attempt 2: UINT_MAX, ULONG_MAX, etc in + * Attempt 3: Deduced from sizeof() macros */ +#ifndef UNITY_EXCLUDE_STDINT_H +#include +#endif + +#ifndef UNITY_EXCLUDE_LIMITS_H +#include +#endif + +#ifndef UNITY_EXCLUDE_SIZEOF +#ifndef UINT_MAX +#define UINT_MAX (sizeof(unsigned int) * 256 - 1) +#endif +#ifndef ULONG_MAX +#define ULONG_MAX (sizeof(unsigned long) * 256 - 1) +#endif +#ifndef UINTPTR_MAX +/* apparently this is not a constant expression: (sizeof(unsigned int *) * 256 - 1) so we have to just let this fall through */ +#endif +#endif + +#ifndef UNITY_EXCLUDE_MATH_H +#include +#endif + +/*------------------------------------------------------- + * Guess Widths If Not Specified + *-------------------------------------------------------*/ + +/* Determine the size of an int, if not already specificied. + * We cannot use sizeof(int), because it is not yet defined + * at this stage in the trnslation of the C program. + * Therefore, infer it from UINT_MAX if possible. */ +#ifndef UNITY_INT_WIDTH + #ifdef UINT_MAX + #if (UINT_MAX == 0xFFFF) + #define UNITY_INT_WIDTH (16) + #elif (UINT_MAX == 0xFFFFFFFF) + #define UNITY_INT_WIDTH (32) + #elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_INT_WIDTH (64) + #endif + #endif +#endif +#ifndef UNITY_INT_WIDTH + #define UNITY_INT_WIDTH (32) +#endif + +/* Determine the size of a long, if not already specified, + * by following the process used above to define + * UNITY_INT_WIDTH. */ +#ifndef UNITY_LONG_WIDTH + #ifdef ULONG_MAX + #if (ULONG_MAX == 0xFFFF) + #define UNITY_LONG_WIDTH (16) + #elif (ULONG_MAX == 0xFFFFFFFF) + #define UNITY_LONG_WIDTH (32) + #elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_LONG_WIDTH (64) + #endif + #endif +#endif +#ifndef UNITY_LONG_WIDTH + #define UNITY_LONG_WIDTH (32) +#endif + +/* Determine the size of a pointer, if not already specified, + * by following the process used above to define + * UNITY_INT_WIDTH. */ +#ifndef UNITY_POINTER_WIDTH + #ifdef UINTPTR_MAX + #if (UINTPTR_MAX+0 <= 0xFFFF) + #define UNITY_POINTER_WIDTH (16) + #elif (UINTPTR_MAX+0 <= 0xFFFFFFFF) + #define UNITY_POINTER_WIDTH (32) + #elif (UINTPTR_MAX+0 <= 0xFFFFFFFFFFFFFFFF) + #define UNITY_POINTER_WIDTH (64) + #endif + #endif +#endif +#ifndef UNITY_POINTER_WIDTH + #ifdef INTPTR_MAX + #if (INTPTR_MAX+0 <= 0x7FFF) + #define UNITY_POINTER_WIDTH (16) + #elif (INTPTR_MAX+0 <= 0x7FFFFFFF) + #define UNITY_POINTER_WIDTH (32) + #elif (INTPTR_MAX+0 <= 0x7FFFFFFFFFFFFFFF) + #define UNITY_POINTER_WIDTH (64) + #endif + #endif +#endif +#ifndef UNITY_POINTER_WIDTH + #define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH +#endif + +/*------------------------------------------------------- + * Int Support (Define types based on detected sizes) + *-------------------------------------------------------*/ + +#if (UNITY_INT_WIDTH == 32) + typedef unsigned char _UU8; + typedef unsigned short _UU16; + typedef unsigned int _UU32; + typedef signed char _US8; + typedef signed short _US16; + typedef signed int _US32; +#elif (UNITY_INT_WIDTH == 16) + typedef unsigned char _UU8; + typedef unsigned int _UU16; + typedef unsigned long _UU32; + typedef signed char _US8; + typedef signed int _US16; + typedef signed long _US32; +#else + #error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported) +#endif + +/*------------------------------------------------------- + * 64-bit Support + *-------------------------------------------------------*/ + +#ifndef UNITY_SUPPORT_64 +#if UNITY_LONG_WIDTH > 32 +#define UNITY_SUPPORT_64 +#endif +#endif +#ifndef UNITY_SUPPORT_64 +#if UNITY_POINTER_WIDTH > 32 +#define UNITY_SUPPORT_64 +#endif +#endif + +#ifndef UNITY_SUPPORT_64 + +/* No 64-bit Support */ +typedef _UU32 _U_UINT; +typedef _US32 _U_SINT; + +#else + +/* 64-bit Support */ +#if (UNITY_LONG_WIDTH == 32) + typedef unsigned long long _UU64; + typedef signed long long _US64; +#elif (UNITY_LONG_WIDTH == 64) + typedef unsigned long _UU64; + typedef signed long _US64; +#else + #error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported) +#endif +typedef _UU64 _U_UINT; +typedef _US64 _U_SINT; + +#endif + +/*------------------------------------------------------- + * Pointer Support + *-------------------------------------------------------*/ + +#if (UNITY_POINTER_WIDTH == 32) + typedef _UU32 _UP; +#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32 +#elif (UNITY_POINTER_WIDTH == 64) + typedef _UU64 _UP; +#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64 +#elif (UNITY_POINTER_WIDTH == 16) + typedef _UU16 _UP; +#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16 +#else + #error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported) +#endif + +#ifndef UNITY_PTR_ATTRIBUTE +#define UNITY_PTR_ATTRIBUTE +#endif + +#ifndef UNITY_INTERNAL_PTR +#define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void* +/* #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const _UU8* */ +#endif + +/*------------------------------------------------------- + * Float Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_FLOAT + +/* No Floating Point Support */ +#undef UNITY_INCLUDE_FLOAT +#undef UNITY_FLOAT_PRECISION +#undef UNITY_FLOAT_TYPE +#undef UNITY_FLOAT_VERBOSE + +#else + +#ifndef UNITY_INCLUDE_FLOAT +#define UNITY_INCLUDE_FLOAT +#endif + +/* Floating Point Support */ +#ifndef UNITY_FLOAT_PRECISION +#define UNITY_FLOAT_PRECISION (0.00001f) +#endif +#ifndef UNITY_FLOAT_TYPE +#define UNITY_FLOAT_TYPE float +#endif +typedef UNITY_FLOAT_TYPE _UF; + +#ifndef isinf +#define isinf(n) (((1.0f / f_zero) == n) ? 1 : 0) || (((-1.0f / f_zero) == n) ? 1 : 0) +#define UNITY_FLOAT_NEEDS_ZERO +#endif + +#ifndef isnan +#define isnan(n) ((n != n) ? 1 : 0) +#endif + +#ifndef isneg +#define isneg(n) ((n < 0.0f) ? 1 : 0) +#endif + +#ifndef ispos +#define ispos(n) ((n > 0.0f) ? 1 : 0) +#endif + +#endif + +/*------------------------------------------------------- + * Double Float Support + *-------------------------------------------------------*/ + +/* unlike FLOAT, we DON'T include by default */ +#ifndef UNITY_EXCLUDE_DOUBLE +#ifndef UNITY_INCLUDE_DOUBLE +#define UNITY_EXCLUDE_DOUBLE +#endif +#endif + +#ifdef UNITY_EXCLUDE_DOUBLE + +/* No Floating Point Support */ +#undef UNITY_DOUBLE_PRECISION +#undef UNITY_DOUBLE_TYPE +#undef UNITY_DOUBLE_VERBOSE + +#ifdef UNITY_INCLUDE_DOUBLE +#undef UNITY_INCLUDE_DOUBLE +#endif + +#else + +/* Double Floating Point Support */ +#ifndef UNITY_DOUBLE_PRECISION +#define UNITY_DOUBLE_PRECISION (1e-12f) +#endif +#ifndef UNITY_DOUBLE_TYPE +#define UNITY_DOUBLE_TYPE double +#endif +typedef UNITY_DOUBLE_TYPE _UD; + +#endif + +#ifdef UNITY_DOUBLE_VERBOSE +#ifndef UNITY_FLOAT_VERBOSE +#define UNITY_FLOAT_VERBOSE +#endif +#endif + +/*------------------------------------------------------- + * Output Method: stdout (DEFAULT) + *-------------------------------------------------------*/ +#ifndef UNITY_OUTPUT_CHAR +/* Default to using putchar, which is defined in stdio.h */ +#include +#define UNITY_OUTPUT_CHAR(a) (void)putchar(a) +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifndef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION +extern void UNITY_OUTPUT_CHAR(int); + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH +/* Default to using putchar, which is defined in stdio.h */ +#include +#define UNITY_OUTPUT_FLUSH() (void)fflush(stdout) +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifndef UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION +extern void UNITY_OUTPUT_FLUSH(void); + #endif +#endif + +#ifndef UNITY_PRINT_EOL +#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n') +#endif + +#ifndef UNITY_OUTPUT_START +#define UNITY_OUTPUT_START() +#endif + +#ifndef UNITY_OUTPUT_COMPLETE +#define UNITY_OUTPUT_COMPLETE() +#endif + +/*------------------------------------------------------- + * Footprint + *-------------------------------------------------------*/ + +#ifndef UNITY_LINE_TYPE +#define UNITY_LINE_TYPE _U_UINT +#endif + +#ifndef UNITY_COUNTER_TYPE +#define UNITY_COUNTER_TYPE _U_UINT +#endif + +/*------------------------------------------------------- + * Language Features Available + *-------------------------------------------------------*/ +#if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA) +# ifdef __GNUC__ /* includes clang */ +# if !(defined(__WIN32__) && defined(__clang__)) +# define UNITY_WEAK_ATTRIBUTE __attribute__((weak)) +# endif +# endif +#endif + +#ifdef UNITY_NO_WEAK +# undef UNITY_WEAK_ATTRIBUTE +# undef UNITY_WEAK_PRAGMA +#endif + + +/*------------------------------------------------------- + * Internal Structs Needed + *-------------------------------------------------------*/ + +typedef void (*UnityTestFunction)(void); + +#define UNITY_DISPLAY_RANGE_INT (0x10) +#define UNITY_DISPLAY_RANGE_UINT (0x20) +#define UNITY_DISPLAY_RANGE_HEX (0x40) +#define UNITY_DISPLAY_RANGE_AUTO (0x80) + +typedef enum +{ +#if (UNITY_INT_WIDTH == 16) + UNITY_DISPLAY_STYLE_INT = 2 + UNITY_DISPLAY_RANGE_INT + UNITY_DISPLAY_RANGE_AUTO, +#elif (UNITY_INT_WIDTH == 32) + UNITY_DISPLAY_STYLE_INT = 4 + UNITY_DISPLAY_RANGE_INT + UNITY_DISPLAY_RANGE_AUTO, +#elif (UNITY_INT_WIDTH == 64) + UNITY_DISPLAY_STYLE_INT = 8 + UNITY_DISPLAY_RANGE_INT + UNITY_DISPLAY_RANGE_AUTO, +#endif + UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT, +#endif + +#if (UNITY_INT_WIDTH == 16) + UNITY_DISPLAY_STYLE_UINT = 2 + UNITY_DISPLAY_RANGE_UINT + UNITY_DISPLAY_RANGE_AUTO, +#elif (UNITY_INT_WIDTH == 32) + UNITY_DISPLAY_STYLE_UINT = 4 + UNITY_DISPLAY_RANGE_UINT + UNITY_DISPLAY_RANGE_AUTO, +#elif (UNITY_INT_WIDTH == 64) + UNITY_DISPLAY_STYLE_UINT = 8 + UNITY_DISPLAY_RANGE_UINT + UNITY_DISPLAY_RANGE_AUTO, +#endif + UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT, +#endif + UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX, +#endif + UNITY_DISPLAY_STYLE_UNKNOWN +} UNITY_DISPLAY_STYLE_T; + +#ifndef UNITY_EXCLUDE_FLOAT +typedef enum _UNITY_FLOAT_TRAIT_T +{ + UNITY_FLOAT_IS_NOT_INF = 0, + UNITY_FLOAT_IS_INF, + UNITY_FLOAT_IS_NOT_NEG_INF, + UNITY_FLOAT_IS_NEG_INF, + UNITY_FLOAT_IS_NOT_NAN, + UNITY_FLOAT_IS_NAN, + UNITY_FLOAT_IS_NOT_DET, + UNITY_FLOAT_IS_DET, + UNITY_FLOAT_INVALID_TRAIT +} UNITY_FLOAT_TRAIT_T; +#endif + +struct _Unity +{ + const char* TestFile; + const char* CurrentTestName; +#ifndef UNITY_EXCLUDE_DETAILS + const char* CurrentDetail1; + const char* CurrentDetail2; +#endif + UNITY_LINE_TYPE CurrentTestLineNumber; + UNITY_COUNTER_TYPE NumberOfTests; + UNITY_COUNTER_TYPE TestFailures; + UNITY_COUNTER_TYPE TestIgnores; + UNITY_COUNTER_TYPE CurrentTestFailed; + UNITY_COUNTER_TYPE CurrentTestIgnored; + jmp_buf AbortFrame; +}; + +extern struct _Unity Unity; + +/*------------------------------------------------------- + * Test Suite Management + *-------------------------------------------------------*/ + +void UnityBegin(const char* filename); +int UnityEnd(void); +void UnityConcludeTest(void); +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum); + +/*------------------------------------------------------- + * Details Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_DETAILS +#define UNITY_CLR_DETAILS() +#define UNITY_SET_DETAIL(d1) +#define UNITY_SET_DETAILS(d1,d2) +#else +#define UNITY_CLR_DETAILS() { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; } +#define UNITY_SET_DETAIL(d1) { Unity.CurrentDetail1 = d1; Unity.CurrentDetail2 = 0; } +#define UNITY_SET_DETAILS(d1,d2) { Unity.CurrentDetail1 = d1; Unity.CurrentDetail2 = d2; } + +#ifndef UNITY_DETAIL1_NAME +#define UNITY_DETAIL1_NAME "Function" +#endif + +#ifndef UNITY_DETAIL2_NAME +#define UNITY_DETAIL2_NAME "Argument" +#endif +#endif + +/*------------------------------------------------------- + * Test Output + *-------------------------------------------------------*/ + +void UnityPrint(const char* string); +void UnityPrintMask(const _U_UINT mask, const _U_UINT number); +void UnityPrintNumberByStyle(const _U_SINT number, const UNITY_DISPLAY_STYLE_T style); +void UnityPrintNumber(const _U_SINT number); +void UnityPrintNumberUnsigned(const _U_UINT number); +void UnityPrintNumberHex(const _U_UINT number, const char nibbles); + +#ifdef UNITY_FLOAT_VERBOSE +void UnityPrintFloat(const _UF number); +#endif + +/*------------------------------------------------------- + * Test Assertion Fuctions + *------------------------------------------------------- + * Use the macros below this section instead of calling + * these directly. The macros have a consistent naming + * convention and will pull in file and line information + * for you. */ + +void UnityAssertEqualNumber(const _U_SINT expected, + const _U_SINT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const _UU32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertBits(const _U_SINT mask, + const _U_SINT expected, + const _U_SINT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const _UU32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringArray( const char** expected, + const char** actual, + const _UU32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const _UU32 length, + const _UU32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertNumbersWithin(const _U_UINT delta, + const _U_SINT expected, + const _U_SINT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityFail(const char* message, const UNITY_LINE_TYPE line); + +void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); + +#ifndef UNITY_EXCLUDE_FLOAT +void UnityAssertFloatsWithin(const _UF delta, + const _UF expected, + const _UF actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const _UF* expected, + UNITY_PTR_ATTRIBUTE const _UF* actual, + const _UU32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertFloatSpecial(const _UF actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +void UnityAssertDoublesWithin(const _UD delta, + const _UD expected, + const _UD actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const _UD* expected, + UNITY_PTR_ATTRIBUTE const _UD* actual, + const _UU32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertDoubleSpecial(const _UD actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +/*------------------------------------------------------- + * Error Strings We Might Need + *-------------------------------------------------------*/ + +extern const char UnityStrErrFloat[]; +extern const char UnityStrErrDouble[]; +extern const char UnityStrErr64[]; + +/*------------------------------------------------------- + * Test Running Macros + *-------------------------------------------------------*/ + +#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0) + +#define TEST_ABORT() {longjmp(Unity.AbortFrame, 1);} + +/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */ +#ifndef RUN_TEST +#ifdef __STDC_VERSION__ +#if __STDC_VERSION__ >= 199901L +#define RUN_TEST(...) UnityDefaultTestRun(RUN_TEST_FIRST(__VA_ARGS__), RUN_TEST_SECOND(__VA_ARGS__)) +#define RUN_TEST_FIRST(...) RUN_TEST_FIRST_HELPER(__VA_ARGS__, throwaway) +#define RUN_TEST_FIRST_HELPER(first, ...) (first), #first +#define RUN_TEST_SECOND(...) RUN_TEST_SECOND_HELPER(__VA_ARGS__, __LINE__, throwaway) +#define RUN_TEST_SECOND_HELPER(first, second, ...) (second) +#endif +#endif +#endif + +/* If we can't do the tricky version, we'll just have to require them to always include the line number */ +#ifndef RUN_TEST +#ifdef CMOCK +#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num) +#else +#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__) +#endif +#endif + +#define TEST_LINE_NUM (Unity.CurrentTestLineNumber) +#define TEST_IS_IGNORED (Unity.CurrentTestIgnored) +#define UNITY_NEW_TEST(a) \ + Unity.CurrentTestName = (a); \ + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \ + Unity.NumberOfTests++; + +#ifndef UNITY_BEGIN +#define UNITY_BEGIN() UnityBegin(__FILE__) +#endif + +#ifndef UNITY_END +#define UNITY_END() UnityEnd() +#endif + +#define UNITY_UNUSED(x) (void)(sizeof(x)) + +/*------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line)) + +/*------------------------------------------------------- + * Test Asserts + *-------------------------------------------------------*/ + +#define UNITY_TEST_ASSERT(condition, line, message) if (condition) {} else {UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), (message));} +#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (UNITY_LINE_TYPE)(line), (message)) + +#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US8 )(expected), (_U_SINT)(_US8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US16)(expected), (_U_SINT)(_US16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US32)(expected), (_U_SINT)(_US32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_UU8 )(expected), (_U_SINT)(_UU8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_UU16)(expected), (_U_SINT)(_UU16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_UU32)(expected), (_U_SINT)(_UU32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US8 )(expected), (_U_SINT)(_US8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US16)(expected), (_U_SINT)(_US16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US32)(expected), (_U_SINT)(_US32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((_U_SINT)(mask), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line)) + +#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU8 )(delta), (_U_SINT)(_US8 )(expected), (_U_SINT)(_US8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU16)(delta), (_U_SINT)(_US16)(expected), (_U_SINT)(_US16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU32)(delta), (_U_SINT)(_US32)(expected), (_U_SINT)(_US32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU8 )(delta), (_U_SINT)(_U_UINT)(_UU8 )(expected), (_U_SINT)(_U_UINT)(_UU8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU16)(delta), (_U_SINT)(_U_UINT)(_UU16)(expected), (_U_SINT)(_U_UINT)(_UU16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU32)(delta), (_U_SINT)(_U_UINT)(_UU32)(expected), (_U_SINT)(_U_UINT)(_UU32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU8 )(delta), (_U_SINT)(_U_UINT)(_UU8 )(expected), (_U_SINT)(_U_UINT)(_UU8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU16)(delta), (_U_SINT)(_U_UINT)(_UU16)(expected), (_U_SINT)(_U_UINT)(_UU16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_UU32)(delta), (_U_SINT)(_U_UINT)(_UU32)(expected), (_U_SINT)(_U_UINT)(_UU32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) + +#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_UP)(expected), (_U_SINT)(_UP)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) +#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (_UU32)(len), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(len), 1, (message), (UNITY_LINE_TYPE)(line)) + +#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(_UP*)(expected), (UNITY_INTERNAL_PTR)(_UP*)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) +#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((const char**)(expected), (const char**)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(len), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line)) + +#ifdef UNITY_SUPPORT_64 +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#else +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#endif + +#ifdef UNITY_EXCLUDE_FLOAT +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#else +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((_UF)(delta), (_UF)(expected), (_UF)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((_UF)(expected) * (_UF)UNITY_FLOAT_PRECISION, (_UF)(expected), (_UF)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray((_UF*)(expected), (_UF*)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +#ifdef UNITY_EXCLUDE_DOUBLE +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#else +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((_UD)(delta), (_UD)(expected), (_UD)(actual), (message), (UNITY_LINE_TYPE)line) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((_UD)(expected) * (_UD)UNITY_DOUBLE_PRECISION, (_UD)expected, (_UD)actual, (UNITY_LINE_TYPE)(line), message) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray((_UD*)(expected), (_UD*)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)line) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +/* End of UNITY_INTERNALS_H */ +#endif diff --git a/tools/unit-test-app/components/unity/license.txt b/tools/unit-test-app/components/unity/license.txt new file mode 100644 index 0000000000..d66fba53e5 --- /dev/null +++ b/tools/unit-test-app/components/unity/license.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/tools/unit-test-app/components/unity/unity.c b/tools/unit-test-app/components/unity/unity.c new file mode 100644 index 0000000000..4a99208d8a --- /dev/null +++ b/tools/unit-test-app/components/unity/unity.c @@ -0,0 +1,1306 @@ +/* ========================================================================= + Unity Project - A Test Framework for C + Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +============================================================================ */ + +#include "unity.h" +#include + +/* If omitted from header, declare overrideable prototypes here so they're ready for use */ +#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION +int UNITY_OUTPUT_CHAR(int); +#endif +#ifdef UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION +int UNITY_OUTPUT_FLUSH(void); +#endif + +/* Helpful macros for us to use here */ +#define UNITY_FAIL_AND_BAIL { Unity.CurrentTestFailed = 1; longjmp(Unity.AbortFrame, 1); } +#define UNITY_IGNORE_AND_BAIL { Unity.CurrentTestIgnored = 1; longjmp(Unity.AbortFrame, 1); } + +/* return prematurely if we are already in failure or ignore state */ +#define UNITY_SKIP_EXECUTION { if ((Unity.CurrentTestFailed != 0) || (Unity.CurrentTestIgnored != 0)) {return;} } + +struct _Unity Unity; + +static const char UnityStrOk[] = "OK"; +static const char UnityStrPass[] = "PASS"; +static const char UnityStrFail[] = "FAIL"; +static const char UnityStrIgnore[] = "IGNORE"; +static const char UnityStrNull[] = "NULL"; +static const char UnityStrSpacer[] = ". "; +static const char UnityStrExpected[] = " Expected "; +static const char UnityStrWas[] = " Was "; +static const char UnityStrElement[] = " Element "; +static const char UnityStrByte[] = " Byte "; +static const char UnityStrMemory[] = " Memory Mismatch."; +static const char UnityStrDelta[] = " Values Not Within Delta "; +static const char UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless."; +static const char UnityStrNullPointerForExpected[] = " Expected pointer to be NULL"; +static const char UnityStrNullPointerForActual[] = " Actual pointer was NULL"; +static const char UnityStrNot[] = "Not "; +static const char UnityStrInf[] = "Infinity"; +static const char UnityStrNegInf[] = "Negative Infinity"; +static const char UnityStrNaN[] = "NaN"; +static const char UnityStrDet[] = "Determinate"; +static const char UnityStrInvalidFloatTrait[] = "Invalid Float Trait"; +const char UnityStrErrFloat[] = "Unity Floating Point Disabled"; +const char UnityStrErrDouble[] = "Unity Double Precision Disabled"; +const char UnityStrErr64[] = "Unity 64-bit Support Disabled"; +static const char UnityStrBreaker[] = "-----------------------"; +static const char UnityStrResultsTests[] = " Tests "; +static const char UnityStrResultsFailures[] = " Failures "; +static const char UnityStrResultsIgnored[] = " Ignored "; +static const char UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " "; +static const char UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " "; + +#ifdef UNITY_FLOAT_NEEDS_ZERO +/* Dividing by these constants produces +/- infinity. + * The rationale is given in UnityAssertFloatIsInf's body. */ +static const _UF f_zero = 0.0f; +#endif + +/* compiler-generic print formatting masks */ +static const _U_UINT UnitySizeMask[] = +{ + 255u, /* 0xFF */ + 65535u, /* 0xFFFF */ + 65535u, + 4294967295u, /* 0xFFFFFFFF */ + 4294967295u, + 4294967295u, + 4294967295u +#ifdef UNITY_SUPPORT_64 + ,0xFFFFFFFFFFFFFFFF +#endif +}; + +/*----------------------------------------------- + * Pretty Printers & Test Result Output Handlers + *-----------------------------------------------*/ + +void UnityPrint(const char* string) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*pch) + { + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UnityPrintNumberHex((_U_UINT)*pch, 2); + } + pch++; + } + } +} + +void UnityPrintLen(const char* string, const _UU32 length); +void UnityPrintLen(const char* string, const _UU32 length) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*pch && (_UU32)(pch - string) < length) + { + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UnityPrintNumberHex((_U_UINT)*pch, 2); + } + pch++; + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumberByStyle(const _U_SINT number, const UNITY_DISPLAY_STYLE_T style) +{ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + UnityPrintNumber(number); + } + else if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT) + { + UnityPrintNumberUnsigned( (_U_UINT)number & UnitySizeMask[((_U_UINT)style & (_U_UINT)0x0F) - 1] ); + } + else + { + UnityPrintNumberHex((_U_UINT)number, (char)((style & 0x000F) << 1)); + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumber(const _U_SINT number_to_print) +{ + _U_UINT number = (_U_UINT)number_to_print; + + if (number_to_print < 0) + { + /* A negative number, including MIN negative */ + UNITY_OUTPUT_CHAR('-'); + number = (_U_UINT)(-number_to_print); + } + UnityPrintNumberUnsigned(number); +} + +/*----------------------------------------------- + * basically do an itoa using as little ram as possible */ +void UnityPrintNumberUnsigned(const _U_UINT number) +{ + _U_UINT divisor = 1; + + /* figure out initial divisor */ + while (number / divisor > 9) + { + divisor *= 10; + } + + /* now mod and print, then divide divisor */ + do + { + UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10))); + divisor /= 10; + } + while (divisor > 0); +} + +/*-----------------------------------------------*/ +void UnityPrintNumberHex(const _U_UINT number, const char nibbles_to_print) +{ + _U_UINT nibble; + char nibbles = nibbles_to_print; + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + + while (nibbles > 0) + { + nibble = (number >> (--nibbles << 2)) & 0x0000000F; + if (nibble <= 9) + { + UNITY_OUTPUT_CHAR((char)('0' + nibble)); + } + else + { + UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble)); + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintMask(const _U_UINT mask, const _U_UINT number) +{ + _U_UINT current_bit = (_U_UINT)1 << (UNITY_INT_WIDTH - 1); + _US32 i; + + for (i = 0; i < UNITY_INT_WIDTH; i++) + { + if (current_bit & mask) + { + if (current_bit & number) + { + UNITY_OUTPUT_CHAR('1'); + } + else + { + UNITY_OUTPUT_CHAR('0'); + } + } + else + { + UNITY_OUTPUT_CHAR('X'); + } + current_bit = current_bit >> 1; + } +} + +/*-----------------------------------------------*/ +#ifdef UNITY_FLOAT_VERBOSE +#include + +#ifndef UNITY_VERBOSE_NUMBER_MAX_LENGTH +# ifdef UNITY_DOUBLE_VERBOSE +# define UNITY_VERBOSE_NUMBER_MAX_LENGTH 317 +# else +# define UNITY_VERBOSE_NUMBER_MAX_LENGTH 47 +# endif +#endif + +void UnityPrintFloat(_UF number) +{ + char TempBuffer[UNITY_VERBOSE_NUMBER_MAX_LENGTH + 1]; + snprintf(TempBuffer, sizeof(TempBuffer), "%.6f", number); + UnityPrint(TempBuffer); +} +#endif + +/*-----------------------------------------------*/ + +void UnityPrintFail(void); +void UnityPrintFail(void) +{ + UnityPrint(UnityStrFail); +} + +void UnityPrintOk(void); +void UnityPrintOk(void) +{ + UnityPrint(UnityStrOk); +} + +/*-----------------------------------------------*/ +static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line); +static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line) +{ +#ifndef UNITY_FIXTURES + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((_U_SINT)line); + UNITY_OUTPUT_CHAR(':'); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#else + UNITY_UNUSED(file); + UNITY_UNUSED(line); +#endif +} + +/*-----------------------------------------------*/ +static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line); +static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line) +{ +#ifndef UNITY_FIXTURES + UnityTestResultsBegin(Unity.TestFile, line); +#else + UNITY_UNUSED(line); +#endif + UnityPrint(UnityStrFail); + UNITY_OUTPUT_CHAR(':'); +} + +/*-----------------------------------------------*/ +void UnityConcludeTest(void) +{ + if (Unity.CurrentTestIgnored) + { + Unity.TestIgnores++; + } + else if (!Unity.CurrentTestFailed) + { + UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber); + UnityPrint(UnityStrPass); + } + else + { + Unity.TestFailures++; + } + + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + UNITY_PRINT_EOL(); + UNITY_OUTPUT_FLUSH(); +} + +/*-----------------------------------------------*/ +static void UnityAddMsgIfSpecified(const char* msg); +static void UnityAddMsgIfSpecified(const char* msg) +{ + if (msg) + { + UnityPrint(UnityStrSpacer); +#ifndef UNITY_EXCLUDE_DETAILS + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + UnityPrint(UnityStrSpacer); + } +#endif + UnityPrint(msg); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual); +static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(expected); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(actual); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStringsLen(const char* expected, const char* actual, const _UU32 length) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(expected, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(actual, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + + + +/*----------------------------------------------- + * Assertion & Control Helpers + *-----------------------------------------------*/ + +static int UnityCheckArraysForNull(UNITY_INTERNAL_PTR expected, UNITY_INTERNAL_PTR actual, const UNITY_LINE_TYPE lineNumber, const char* msg) +{ + /* return true if they are both NULL */ + if ((expected == NULL) && (actual == NULL)) + return 1; + + /* throw error if just expected is NULL */ + if (expected == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForExpected); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + + /* throw error if just actual is NULL */ + if (actual == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForActual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + + /* return false if neither is NULL */ + return 0; +} + +/*----------------------------------------------- + * Assertion Functions + *-----------------------------------------------*/ + +void UnityAssertBits(const _U_SINT mask, + const _U_SINT expected, + const _U_SINT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_SKIP_EXECUTION; + + if ((mask & expected) != (mask & actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintMask((_U_UINT)mask, (_U_UINT)expected); + UnityPrint(UnityStrWas); + UnityPrintMask((_U_UINT)mask, (_U_UINT)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualNumber(const _U_SINT expected, + const _U_SINT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + UNITY_SKIP_EXECUTION; + + if (expected != actual) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#define UnityPrintPointlessAndBail() \ +{ \ + UnityTestResultsFailBegin(lineNumber); \ + UnityPrint(UnityStrPointless); \ + UnityAddMsgIfSpecified(msg); \ + UNITY_FAIL_AND_BAIL; } + +/*-----------------------------------------------*/ +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const _UU32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + _UU32 elements = num_elements; + UNITY_INTERNAL_PTR ptr_exp = (UNITY_INTERNAL_PTR)expected; + UNITY_INTERNAL_PTR ptr_act = (UNITY_INTERNAL_PTR)actual; + + UNITY_SKIP_EXECUTION; + + if (elements == 0) + { + UnityPrintPointlessAndBail(); + } + + if (UnityCheckArraysForNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg) == 1) + return; + + /* If style is UNITY_DISPLAY_STYLE_INT, we'll fall into the default case rather than the INT16 or INT32 (etc) case + * as UNITY_DISPLAY_STYLE_INT includes a flag for UNITY_DISPLAY_RANGE_AUTO, which the width-specific + * variants do not. Therefore remove this flag. */ + switch(style & (UNITY_DISPLAY_STYLE_T)(~UNITY_DISPLAY_RANGE_AUTO)) + { + case UNITY_DISPLAY_STYLE_HEX8: + case UNITY_DISPLAY_STYLE_INT8: + case UNITY_DISPLAY_STYLE_UINT8: + while (elements--) + { + if (*(UNITY_PTR_ATTRIBUTE const _US8*)ptr_exp != *(UNITY_PTR_ATTRIBUTE const _US8*)ptr_act) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(*(UNITY_PTR_ATTRIBUTE const _US8*)ptr_exp, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(*(UNITY_PTR_ATTRIBUTE const _US8*)ptr_act, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + ptr_exp = (UNITY_INTERNAL_PTR)((_UP)ptr_exp + 1); + ptr_act = (UNITY_INTERNAL_PTR)((_UP)ptr_act + 1); + } + break; + case UNITY_DISPLAY_STYLE_HEX16: + case UNITY_DISPLAY_STYLE_INT16: + case UNITY_DISPLAY_STYLE_UINT16: + while (elements--) + { + if (*(UNITY_PTR_ATTRIBUTE const _US16*)ptr_exp != *(UNITY_PTR_ATTRIBUTE const _US16*)ptr_act) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(*(UNITY_PTR_ATTRIBUTE const _US16*)ptr_exp, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(*(UNITY_PTR_ATTRIBUTE const _US16*)ptr_act, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + ptr_exp = (UNITY_INTERNAL_PTR)((_UP)ptr_exp + 2); + ptr_act = (UNITY_INTERNAL_PTR)((_UP)ptr_act + 2); + } + break; +#ifdef UNITY_SUPPORT_64 + case UNITY_DISPLAY_STYLE_HEX64: + case UNITY_DISPLAY_STYLE_INT64: + case UNITY_DISPLAY_STYLE_UINT64: + while (elements--) + { + if (*(UNITY_PTR_ATTRIBUTE const _US64*)ptr_exp != *(UNITY_PTR_ATTRIBUTE const _US64*)ptr_act) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(*(UNITY_PTR_ATTRIBUTE const _US64*)ptr_exp, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(*(UNITY_PTR_ATTRIBUTE const _US64*)ptr_act, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + ptr_exp = (UNITY_INTERNAL_PTR)((_UP)ptr_exp + 8); + ptr_act = (UNITY_INTERNAL_PTR)((_UP)ptr_act + 8); + } + break; +#endif + default: + while (elements--) + { + if (*(UNITY_PTR_ATTRIBUTE const _US32*)ptr_exp != *(UNITY_PTR_ATTRIBUTE const _US32*)ptr_act) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(*(UNITY_PTR_ATTRIBUTE const _US32*)ptr_exp, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(*(UNITY_PTR_ATTRIBUTE const _US32*)ptr_act, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + ptr_exp = (UNITY_INTERNAL_PTR)((_UP)ptr_exp + 4); + ptr_act = (UNITY_INTERNAL_PTR)((_UP)ptr_act + 4); + } + break; + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT +void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const _UF* expected, + UNITY_PTR_ATTRIBUTE const _UF* actual, + const _UU32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + _UU32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const _UF* ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const _UF* ptr_actual = actual; + _UF diff, tol; + + UNITY_SKIP_EXECUTION; + + if (elements == 0) + { + UnityPrintPointlessAndBail(); + } + + if (UnityCheckArraysForNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg) == 1) + return; + + while (elements--) + { + diff = *ptr_expected - *ptr_actual; + if (diff < 0.0f) + diff = 0.0f - diff; + tol = UNITY_FLOAT_PRECISION * *ptr_expected; + if (tol < 0.0f) + tol = 0.0f - tol; + + /* This first part of this condition will catch any NaN or Infinite values */ + if (isnan(diff) || isinf(diff) || (diff > tol)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); +#ifdef UNITY_FLOAT_VERBOSE + UnityPrint(UnityStrExpected); + UnityPrintFloat(*ptr_expected); + UnityPrint(UnityStrWas); + UnityPrintFloat(*ptr_actual); +#else + UnityPrint(UnityStrDelta); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + ptr_expected++; + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsWithin(const _UF delta, + const _UF expected, + const _UF actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + _UF diff = actual - expected; + _UF pos_delta = delta; + + UNITY_SKIP_EXECUTION; + + if (diff < 0.0f) + { + diff = 0.0f - diff; + } + if (pos_delta < 0.0f) + { + pos_delta = 0.0f - pos_delta; + } + + /* This first part of this condition will catch any NaN or Infinite values */ + if (isnan(diff) || isinf(diff) || (pos_delta < diff)) + { + UnityTestResultsFailBegin(lineNumber); +#ifdef UNITY_FLOAT_VERBOSE + UnityPrint(UnityStrExpected); + UnityPrintFloat(expected); + UnityPrint(UnityStrWas); + UnityPrintFloat(actual); +#else + UnityPrint(UnityStrDelta); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatSpecial(const _UF actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char* trait_names[] = { UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet }; + _U_SINT should_be_trait = ((_U_SINT)style & 1); + _U_SINT is_trait = !should_be_trait; + _U_SINT trait_index = (_U_SINT)(style >> 1); + + UNITY_SKIP_EXECUTION; + + switch(style) + { + /* To determine Inf / Neg Inf, we compare to an Inf / Neg Inf value we create on the fly + * We are using a variable to hold the zero value because some compilers complain about dividing by zero otherwise */ + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = isinf(actual) & ispos(actual); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = isinf(actual) & isneg(actual); + break; + + /* NaN is the only floating point value that does NOT equal itself. Therefore if Actual == Actual, then it is NOT NaN. */ + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = isnan(actual); + break; + + /* A determinate number is non infinite and not NaN. (therefore the opposite of the two above) */ + case UNITY_FLOAT_IS_DET: + case UNITY_FLOAT_IS_NOT_DET: + if (isinf(actual) | isnan(actual)) + is_trait = 0; + else + is_trait = 1; + break; + + default: + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + UnityPrint(UnityStrNot); + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifdef UNITY_FLOAT_VERBOSE + UnityPrintFloat(actual); +#else + if (should_be_trait) + UnityPrint(UnityStrNot); + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_FLOAT */ + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_DOUBLE +void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const _UD* expected, + UNITY_PTR_ATTRIBUTE const _UD* actual, + const _UU32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + _UU32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const _UD* ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const _UD* ptr_actual = actual; + _UD diff, tol; + + UNITY_SKIP_EXECUTION; + + if (elements == 0) + { + UnityPrintPointlessAndBail(); + } + + if (UnityCheckArraysForNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg) == 1) + return; + + while (elements--) + { + diff = *ptr_expected - *ptr_actual; + if (diff < 0.0) + diff = 0.0 - diff; + tol = UNITY_DOUBLE_PRECISION * *ptr_expected; + if (tol < 0.0) + tol = 0.0 - tol; + + /* This first part of this condition will catch any NaN or Infinite values */ + if (isnan(diff) || isinf(diff) || (diff > tol)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); +#ifdef UNITY_DOUBLE_VERBOSE + UnityPrint(UnityStrExpected); + UnityPrintFloat((float)(*ptr_expected)); + UnityPrint(UnityStrWas); + UnityPrintFloat((float)(*ptr_actual)); +#else + UnityPrint(UnityStrDelta); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + ptr_expected++; + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesWithin(const _UD delta, + const _UD expected, + const _UD actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + _UD diff = actual - expected; + _UD pos_delta = delta; + + UNITY_SKIP_EXECUTION; + + if (diff < 0.0) + { + diff = 0.0 - diff; + } + if (pos_delta < 0.0) + { + pos_delta = 0.0 - pos_delta; + } + + /* This first part of this condition will catch any NaN or Infinite values */ + if (isnan(diff) || isinf(diff) || (pos_delta < diff)) + { + UnityTestResultsFailBegin(lineNumber); +#ifdef UNITY_DOUBLE_VERBOSE + UnityPrint(UnityStrExpected); + UnityPrintFloat((float)expected); + UnityPrint(UnityStrWas); + UnityPrintFloat((float)actual); +#else + UnityPrint(UnityStrDelta); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ + +void UnityAssertDoubleSpecial(const _UD actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char* trait_names[] = { UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet }; + _U_SINT should_be_trait = ((_U_SINT)style & 1); + _U_SINT is_trait = !should_be_trait; + _U_SINT trait_index = (_U_SINT)(style >> 1); + + UNITY_SKIP_EXECUTION; + + switch(style) + { + /* To determine Inf / Neg Inf, we compare to an Inf / Neg Inf value we create on the fly + * We are using a variable to hold the zero value because some compilers complain about dividing by zero otherwise */ + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = isinf(actual) & ispos(actual); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = isinf(actual) & isneg(actual); + break; + + /* NaN is the only floating point value that does NOT equal itself. Therefore if Actual == Actual, then it is NOT NaN. */ + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = isnan(actual); + break; + + /* A determinate number is non infinite and not NaN. (therefore the opposite of the two above) */ + case UNITY_FLOAT_IS_DET: + case UNITY_FLOAT_IS_NOT_DET: + if (isinf(actual) | isnan(actual)) + is_trait = 0; + else + is_trait = 1; + break; + + default: + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + UnityPrint(UnityStrNot); + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifdef UNITY_DOUBLE_VERBOSE + UnityPrintFloat(actual); +#else + if (should_be_trait) + UnityPrint(UnityStrNot); + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + + +#endif /* not UNITY_EXCLUDE_DOUBLE */ + +/*-----------------------------------------------*/ +void UnityAssertNumbersWithin( const _U_UINT delta, + const _U_SINT expected, + const _U_SINT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + UNITY_SKIP_EXECUTION; + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (actual > expected) + Unity.CurrentTestFailed = ((_U_UINT)(actual - expected) > delta); + else + Unity.CurrentTestFailed = ((_U_UINT)(expected - actual) > delta); + } + else + { + if ((_U_UINT)actual > (_U_UINT)expected) + Unity.CurrentTestFailed = ((_U_UINT)(actual - expected) > delta); + else + Unity.CurrentTestFailed = ((_U_UINT)(expected - actual) > delta); + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintNumberByStyle((_U_SINT)delta, style); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + _UU32 i; + + UNITY_SKIP_EXECUTION; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; expected[i] || actual[i]; i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expected != actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStrings(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const _UU32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + _UU32 i; + + UNITY_SKIP_EXECUTION; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; (expected[i] || actual[i]) && i < length; i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expected != actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStringsLen(expected, actual, length); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + + +/*-----------------------------------------------*/ +void UnityAssertEqualStringArray( const char** expected, + const char** actual, + const _UU32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + _UU32 i, j = 0; + + UNITY_SKIP_EXECUTION; + + /* if no elements, it's an error */ + if (num_elements == 0) + { + UnityPrintPointlessAndBail(); + } + + if (UnityCheckArraysForNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg) == 1) + return; + + do + { + /* if both pointers not null compare the strings */ + if (expected[j] && actual[j]) + { + for (i = 0; expected[j][i] || actual[j][i]; i++) + { + if (expected[j][i] != actual[j][i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expected[j] != actual[j]) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(j); + } + UnityPrintExpectedAndActualStrings((const char*)(expected[j]), (const char*)(actual[j])); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + } while (++j < num_elements); +} + +/*-----------------------------------------------*/ +void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const _UU32 length, + const _UU32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_PTR_ATTRIBUTE const unsigned char* ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; + UNITY_PTR_ATTRIBUTE const unsigned char* ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char*)actual; + _UU32 elements = num_elements; + _UU32 bytes; + + UNITY_SKIP_EXECUTION; + + if ((elements == 0) || (length == 0)) + { + UnityPrintPointlessAndBail(); + } + + if (UnityCheckArraysForNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg) == 1) + return; + + while (elements--) + { + /* /////////////////////////////////// */ + bytes = length; + while (bytes--) + { + if (*ptr_exp != *ptr_act) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrMemory); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + } + UnityPrint(UnityStrByte); + UnityPrintNumberUnsigned(length - bytes - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + ptr_exp = (UNITY_INTERNAL_PTR)((_UP)ptr_exp + 1); + ptr_act = (UNITY_INTERNAL_PTR)((_UP)ptr_act + 1); + } + /* /////////////////////////////////// */ + + } +} + +/*----------------------------------------------- + * Control Functions + *-----------------------------------------------*/ + +void UnityFail(const char* msg, const UNITY_LINE_TYPE line) +{ + UNITY_SKIP_EXECUTION; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrintFail(); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + +#ifndef UNITY_EXCLUDE_DETAILS + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + UnityPrint(UnityStrSpacer); + } +#endif + if (msg[0] != ' ') + { + UNITY_OUTPUT_CHAR(' '); + } + UnityPrint(msg); + } + + UNITY_FAIL_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line) +{ + UNITY_SKIP_EXECUTION; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrIgnore); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_IGNORE_AND_BAIL; +} + +/*-----------------------------------------------*/ +#if defined(UNITY_WEAK_ATTRIBUTE) + UNITY_WEAK_ATTRIBUTE void setUp(void) { } + UNITY_WEAK_ATTRIBUTE void tearDown(void) { } +#elif defined(UNITY_WEAK_PRAGMA) +# pragma weak setUp + void setUp(void) { } +# pragma weak tearDown + void tearDown(void) { } +#endif +/*-----------------------------------------------*/ +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum) +{ + Unity.CurrentTestName = FuncName; + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum; + Unity.NumberOfTests++; + UNITY_CLR_DETAILS(); + if (TEST_PROTECT()) + { + setUp(); + Func(); + } + if (TEST_PROTECT() && !(Unity.CurrentTestIgnored)) + { + tearDown(); + } + UnityConcludeTest(); +} + +/*-----------------------------------------------*/ +void UnityBegin(const char* filename) +{ + Unity.TestFile = filename; + Unity.CurrentTestName = NULL; + Unity.CurrentTestLineNumber = 0; + Unity.NumberOfTests = 0; + Unity.TestFailures = 0; + Unity.TestIgnores = 0; + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + + UNITY_CLR_DETAILS(); + UNITY_OUTPUT_START(); +} + +/*-----------------------------------------------*/ +int UnityEnd(void) +{ + UNITY_PRINT_EOL(); + UnityPrint(UnityStrBreaker); + UNITY_PRINT_EOL(); + UnityPrintNumber((_U_SINT)(Unity.NumberOfTests)); + UnityPrint(UnityStrResultsTests); + UnityPrintNumber((_U_SINT)(Unity.TestFailures)); + UnityPrint(UnityStrResultsFailures); + UnityPrintNumber((_U_SINT)(Unity.TestIgnores)); + UnityPrint(UnityStrResultsIgnored); + UNITY_PRINT_EOL(); + if (Unity.TestFailures == 0U) + { + UnityPrintOk(); + } + else + { + UnityPrintFail(); +#ifdef UNITY_DIFFERENTIATE_FINAL_FAIL + UNITY_OUTPUT_CHAR('E'); UNITY_OUTPUT_CHAR('D'); +#endif + } + UNITY_PRINT_EOL(); + UNITY_OUTPUT_FLUSH(); + UNITY_OUTPUT_COMPLETE(); + return (int)(Unity.TestFailures); +} + +/*-----------------------------------------------*/ diff --git a/tools/unit-test-app/components/unity/unity_platform.c b/tools/unit-test-app/components/unity/unity_platform.c new file mode 100644 index 0000000000..4e1c0b8e07 --- /dev/null +++ b/tools/unit-test-app/components/unity/unity_platform.c @@ -0,0 +1,165 @@ +#include +#include +#include +#include "unity.h" +#include "rom/ets_sys.h" + +#define unity_printf ets_printf + +// Functions which are defined in ROM, linker script provides addresses for these: +int uart_tx_one_char(uint8_t c); +void uart_tx_wait_idle(uint8_t uart_no); +int UartRxString(uint8_t* dst, uint8_t max_length); + +// Pointers to the head and tail of linked list of test description structs: +static struct test_desc_t* s_unity_tests_first = NULL; +static struct test_desc_t* s_unity_tests_last = NULL; + + +void unity_putc(int c) +{ + if (c == '\n') + { + uart_tx_one_char('\n'); + uart_tx_one_char('\r'); + } + else if (c == '\r') + { + } + else + { + uart_tx_one_char(c); + } +} + +void unity_flush() +{ + uart_tx_wait_idle(0); // assume that output goes to UART0 +} + +void unity_testcase_register(struct test_desc_t* desc) +{ + if (!s_unity_tests_first) + { + s_unity_tests_first = desc; + } + else + { + s_unity_tests_last->next = desc; + } + s_unity_tests_last = desc; + desc->next = NULL; +} + +static void unity_run_single_test(const struct test_desc_t* test) +{ + Unity.TestFile = test->file; + Unity.CurrentDetail1 = test->desc; + UnityDefaultTestRun(test->fn, test->name, test->line); +} + +static void unity_run_single_test_by_index(int index) +{ + const struct test_desc_t* test; + for (test = s_unity_tests_first; test != NULL && index != 0; test = test->next, --index) + { + } + if (test != NULL) + { + unity_run_single_test(test); + } + +} + +static void unity_run_single_test_by_name(const char* filter) +{ + char tmp[256]; + strncpy(tmp, filter + 1, sizeof(tmp) - 1); + tmp[strlen(filter) - 2] = 0; + for (const struct test_desc_t* test = s_unity_tests_first; test != NULL; test = test->next) + { + if (strstr(test->name, tmp) != NULL) + { + unity_run_single_test(test); + } + } +} + +void unity_run_all_tests() +{ + for (const struct test_desc_t* test = s_unity_tests_first; test != NULL; test = test->next) + { + unity_run_single_test(test); + } +} + +void unity_run_tests_with_filter(const char* filter) +{ + for (const struct test_desc_t* test = s_unity_tests_first; test != NULL; test = test->next) + { + if (strstr(test->desc, filter) != NULL) + { + unity_run_single_test(test); + } + } +} + +static void trim_trailing_space(char* str) +{ + char* end = str + strlen(str) - 1; + while (end >= str && isspace((int) *end)) + { + *end = 0; + --end; + } +} + +void unity_run_menu() +{ + while (true) + { + int test_counter = 0; + unity_printf("\n\nHere's the test menu, pick your combo:\n"); + for (const struct test_desc_t* test = s_unity_tests_first; + test != NULL; + test = test->next, ++test_counter) + { + unity_printf("(%d)\t\"%s\" %s\n", test_counter + 1, test->name, test->desc); + } + + char cmdline[256]; + UartRxString((uint8_t*) cmdline, sizeof(cmdline) - 1); + trim_trailing_space(cmdline); + + if (strlen(cmdline) == 0) + { + continue; + } + + UNITY_BEGIN(); + + if (cmdline[0] == '*') + { + unity_run_all_tests(); + } + else if (cmdline[0] =='[') + { + unity_run_tests_with_filter(cmdline); + } + else if (cmdline[0] =='"') + { + unity_run_single_test_by_name(cmdline); + } + else + { + int test_index = strtol(cmdline, NULL, 10); + if (test_index >= 1 && test_index <= test_counter) + { + unity_run_single_test_by_index(test_index - 1); + } + } + + UNITY_END(); + } +} + diff --git a/tools/unit-test-app/main/app_main.c b/tools/unit-test-app/main/app_main.c new file mode 100644 index 0000000000..b00034adf1 --- /dev/null +++ b/tools/unit-test-app/main/app_main.c @@ -0,0 +1,18 @@ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "unity.h" + + +void unityTask(void *pvParameters) +{ + vTaskDelay(1000 / portTICK_PERIOD_MS); + unity_run_menu(); + while(1); +} + +void app_main() +{ + xTaskCreatePinnedToCore(unityTask, "unityTask", 4096, NULL, 5, NULL, 0); +} + diff --git a/tools/unit-test-app/main/component.mk b/tools/unit-test-app/main/component.mk new file mode 100644 index 0000000000..fd2dbe7b84 --- /dev/null +++ b/tools/unit-test-app/main/component.mk @@ -0,0 +1,5 @@ +# +# Main Makefile. This is basically the same as a component makefile. +# + +include $(IDF_PATH)/make/component_common.mk diff --git a/tools/unit-test-app/sdkconfig b/tools/unit-test-app/sdkconfig new file mode 100644 index 0000000000..cde49f3c8d --- /dev/null +++ b/tools/unit-test-app/sdkconfig @@ -0,0 +1,125 @@ +# +# Automatically generated file; DO NOT EDIT. +# Espressif IoT Development Framework Configuration +# + +# +# SDK tool configuration +# +CONFIG_TOOLPREFIX="xtensa-esp32-elf-" +CONFIG_PYTHON="python" + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_PORT="/dev/ttyUSB0" +# CONFIG_ESPTOOLPY_BAUD_115200B is not set +# CONFIG_ESPTOOLPY_BAUD_230400B is not set +CONFIG_ESPTOOLPY_BAUD_921600B=y +# CONFIG_ESPTOOLPY_BAUD_2MB is not set +# CONFIG_ESPTOOLPY_BAUD_OTHER is not set +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_BAUD=921600 +CONFIG_ESPTOOLPY_COMPRESSED=y +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_40M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="40m" + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_APP_OFFSET=0x10000 + +# +# Component config +# + +# +# ESP32-specific config +# +# CONFIG_ESP32_DEFAULT_CPU_FREQ_80 is not set +# CONFIG_ESP32_DEFAULT_CPU_FREQ_160 is not set +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 +# CONFIG_ESP32_ENABLE_STACK_WIFI is not set +# CONFIG_ESP32_ENABLE_STACK_BT is not set +CONFIG_ESP32_ENABLE_STACK_NONE=y +CONFIG_MEMMAP_SMP=y +# CONFIG_MEMMAP_TRACEMEM is not set +# CONFIG_MEMMAP_SPISRAM is not set +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2048 +CONFIG_MAIN_TASK_STACK_SIZE=4096 +CONFIG_NEWLIB_STDOUT_ADDCR=y + +# +# FreeRTOS +# +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_CORETIMER_0=y +# CONFIG_FREERTOS_CORETIMER_1 is not set +# CONFIG_FREERTOS_CORETIMER_2 is not set +CONFIG_FREERTOS_HZ=1000 +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=3 +# CONFIG_FREERTOS_PANIC_PRINT_HALT is not set +CONFIG_FREERTOS_PANIC_PRINT_REBOOT=y +# CONFIG_FREERTOS_PANIC_SILENT_REBOOT is not set +# CONFIG_FREERTOS_PANIC_GDBSTUB is not set +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y +# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set +# CONFIG_FREERTOS_ASSERT_DISABLE is not set +CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG=y +# CONFIG_ENABLE_MEMORY_DEBUG is not set +# CONFIG_FREERTOS_DEBUG_INTERNALS is not set + +# +# Log output +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_COLORS=y + +# +# LWIP +# +CONFIG_LWIP_MAX_SOCKETS=4 +CONFIG_LWIP_THREAD_LOCAL_STORAGE_INDEX=0 +# CONFIG_LWIP_SO_REUSE is not set + +# +# mbedTLS +# +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 +# CONFIG_MBEDTLS_DEBUG is not set + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set + +# +# TESTS +# +CONFIG_FP_TEST_ENABLE=y From 2393d829de9995eb70d6458c9aa40eac81897a71 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 21 Nov 2016 17:13:55 +0800 Subject: [PATCH 04/25] remove legacy definitions from esp_types.h --- components/esp32/include/esp_system.h | 2 +- components/esp32/include/esp_types.h | 48 --------------------------- components/esp32/include/rom/uart.h | 8 +++++ components/openssl/platform/ssl_pm.c | 2 +- 4 files changed, 10 insertions(+), 50 deletions(-) diff --git a/components/esp32/include/esp_system.h b/components/esp32/include/esp_system.h index d416e23d07..2b408eacc6 100644 --- a/components/esp32/include/esp_system.h +++ b/components/esp32/include/esp_system.h @@ -16,7 +16,7 @@ #define __ESP_SYSTEM_H__ #include - +#include #include "esp_err.h" #include "esp_deepsleep.h" diff --git a/components/esp32/include/esp_types.h b/components/esp32/include/esp_types.h index c142aee687..547024e3f7 100755 --- a/components/esp32/include/esp_types.h +++ b/components/esp32/include/esp_types.h @@ -22,52 +22,4 @@ #include #include -#define __ATTRIB_PACK __attribute__ ((packed)) -#define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2))) -#define __ATTRIB_NORETURN __attribute__ ((noreturn)) -#define __ATTRIB_ALIGN(x) __attribute__ ((aligned((x)))) -#define INLINE __inline__ - -#define LOCAL static - -/* probably should not put STATUS here */ -typedef enum { - OK = 0, - FAIL, - PENDING, - BUSY, - CANCEL, -} STATUS; - -//#define _LITTLE_ENDIAN 1234 -//#define _BYTE_ORDER == _LITTLE_ENDIAN - -#define ASSERT( x ) do { \ - if (!(x)) { \ - printf("%s %u\n", __FILE__, __LINE__); \ - while (1) { \ - asm volatile("nop"); \ - }; \ - } \ -} while (0) - -/* #if __GNUC_PREREQ__(4, 1) */ -#ifndef __GNUC__ -#if 1 -#define __offsetof(type, field) __builtin_offsetof(type, field) -#else -#define __offsetof(type, field) ((size_t)(&((type *)0)->field)) -#endif -#endif /* __GNUC__ */ - - -/* Macros for counting and rounding. */ -#ifndef howmany -#define howmany(x, y) (((x)+((y)-1))/(y)) -#endif - -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - __offsetof(type,member) );}) - #endif /* __ESP_TYPES_H__ */ diff --git a/components/esp32/include/rom/uart.h b/components/esp32/include/rom/uart.h index 8e3125133c..0c08590f57 100644 --- a/components/esp32/include/rom/uart.h +++ b/components/esp32/include/rom/uart.h @@ -161,6 +161,14 @@ typedef struct { int received; } UartDevice; +typedef enum { + OK = 0, + FAIL, + PENDING, + BUSY, + CANCEL, +} STATUS; + /** * @brief Init uart device struct value and reset uart0/uart1 rx. * Please do not call this function in SDK. diff --git a/components/openssl/platform/ssl_pm.c b/components/openssl/platform/ssl_pm.c index a5986dc3ee..522721ad7c 100644 --- a/components/openssl/platform/ssl_pm.c +++ b/components/openssl/platform/ssl_pm.c @@ -215,7 +215,7 @@ static int ssl_pm_reload_crt(SSL *ssl) * Perform the mbedtls SSL handshake instead of mbedtls_ssl_handshake. * We can add debug here. */ -LOCAL int mbedtls_handshake( mbedtls_ssl_context *ssl ) +static int mbedtls_handshake( mbedtls_ssl_context *ssl ) { int ret = 0; From 8b2f933a51905ea357cf91d37923049396a8625e Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 21 Nov 2016 17:15:37 +0800 Subject: [PATCH 05/25] Implement system_* APIs in IDF --- components/esp32/cpu_start.c | 4 +- components/esp32/cpu_util.c | 44 ++++ components/esp32/include/esp_system.h | 166 +++++----------- components/esp32/include/esp_wifi.h | 15 ++ components/esp32/include/esp_wifi_internal.h | 22 +- components/esp32/include/soc/cpu.h | 21 +- components/esp32/panic.c | 20 +- components/esp32/system_api.c | 199 +++++++++++++++++++ components/newlib/time.c | 26 +++ 9 files changed, 365 insertions(+), 152 deletions(-) create mode 100644 components/esp32/cpu_util.c create mode 100644 components/esp32/system_api.c diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index 1eb0a5355e..293be565df 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -116,9 +116,7 @@ void IRAM_ATTR call_start_cpu0() //Flush and enable icache for APP CPU Cache_Flush(1); Cache_Read_Enable(1); - //Un-stall the app cpu; the panic handler may have stalled it. - CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C1_M); - CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C0_M); + esp_cpu_unstall(1); //Enable clock gating and reset the app cpu. SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN); CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_C_REG, DPORT_APPCPU_RUNSTALL); diff --git a/components/esp32/cpu_util.c b/components/esp32/cpu_util.c new file mode 100644 index 0000000000..cff61ab796 --- /dev/null +++ b/components/esp32/cpu_util.c @@ -0,0 +1,44 @@ +// Copyright 2013-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_attr.h" +#include "soc/cpu.h" +#include "soc/soc.h" +#include "soc/rtc_cntl_reg.h" + +void IRAM_ATTR esp_cpu_stall(int cpu_id) +{ + if (cpu_id == 1) { + CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C1_M); + SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<|<----------- user data(1024 bytes) --------->| - * - * @attention Read and write unit for data stored in the RTC memory is 4 bytes. - * @attention src_addr is the block number (4 bytes per block). So when reading data - * at the beginning of the user data segment, src_addr will be 512/4 = 128, - * n will be data length. - * - * @param uint16 src : source address of rtc memory, src_addr >= 128 - * @param void *dst : data pointer - * @param uint16 n : data length, unit: byte - * - * @return true : succeed - * @return false : fail - */ -bool system_rtc_mem_read(uint16_t src, void *dst, uint16_t n); - -/** - * @brief Write user data to the RTC memory. - * - * During deep-sleep, only RTC is working. So users can store their data - * in RTC memory if it is needed. The user data segment below (1024 bytes) - * is used to store the user data. - * - * |<---- system data(512 bytes) ---->|<----------- user data(1024 bytes) --------->| - * - * @attention Read and write unit for data stored in the RTC memory is 4 bytes. - * @attention src_addr is the block number (4 bytes per block). So when storing data - * at the beginning of the user data segment, src_addr will be 512/4 = 128, - * n will be data length. - * - * @param uint16 src : source address of rtc memory, src_addr >= 128 - * @param void *dst : data pointer - * @param uint16 n : data length, unit: byte - * - * @return true : succeed - * @return false : fail - */ -bool system_rtc_mem_write(uint16_t dst, const void *src, uint16_t n); - -/** \defgroup System_boot_APIs Boot APIs - * @brief boot APIs - */ - -/** @addtogroup System_boot_APIs - * @{ - */ - -/** - * @} - */ - -/** \defgroup Hardware_MAC_APIs Hardware MAC APIs - * @brief Hardware MAC address APIs - * - * In WiFi MAC, only ESP32 station MAC is the hardware MAC, ESP32 softAP MAC is a software MAC - * calculated from ESP32 station MAC. - * So users need to call wifi_get_macaddr to query the ESP32 softAP MAC if ESP32 station MAC changed. - * - */ - -/** @addtogroup Hardware_MAC_APIs - * @{ - */ + * @brief Get one random 32-bit word from hardware RNG + * + * @return random value between 0 and UINT32_MAX + */ +uint32_t esp_random(void); /** * @brief Read hardware MAC address. * - * @param uint8 mac[6] : the hardware MAC address, length: 6 bytes. + * In WiFi MAC, only ESP32 station MAC is the hardware MAC, ESP32 softAP MAC is a software MAC + * calculated from ESP32 station MAC. + * So users need to call esp_wifi_get_macaddr to query the ESP32 softAP MAC if ESP32 station MAC changed. * - * @return esp_err_t + * @param mac hardware MAC address, length: 6 bytes. + * + * @return ESP_OK on success */ -esp_err_t system_efuse_read_mac(uint8_t mac[6]); - +esp_err_t esp_efuse_read_mac(uint8_t mac[6]); /** - * @} + * @brief Read hardware MAC address. + * + * Function has been renamed to esp_efuse_read_mac. + * This name will be removed in a future release. + * + * @param mac hardware MAC address, length: 6 bytes. + * @return ESP_OK on success */ +esp_err_t system_efuse_read_mac(uint8_t mac[6]) __attribute__ ((deprecated)); -/** - * @} - */ - #ifdef __cplusplus } #endif diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index 65a91929dd..572a7dc744 100644 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -186,6 +186,21 @@ esp_err_t esp_wifi_start(void); */ esp_err_t esp_wifi_stop(void); +/** + * @brief Restore WiFi stack persistent settings to default values + * + * This function will reset settings made using the following APIs: + * - esp_wifi_get_auto_connect, + * - esp_wifi_set_protocol, + * - esp_wifi_set_config related + * - esp_wifi_set_mode + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by eps_wifi_init + */ +esp_err_t esp_wifi_restore(void); + /** * @brief Connect the ESP32 WiFi station to the AP. * diff --git a/components/esp32/include/esp_wifi_internal.h b/components/esp32/include/esp_wifi_internal.h index 2015b5063d..09813bfa1b 100644 --- a/components/esp32/include/esp_wifi_internal.h +++ b/components/esp32/include/esp_wifi_internal.h @@ -43,10 +43,9 @@ extern "C" { /** * @brief get whether the wifi driver is allowed to transmit data or not * - * @param none - * - * @return true : upper layer should stop to transmit data to wifi driver - * @return false : upper layer can transmit data to wifi driver + * @return + * - true : upper layer should stop to transmit data to wifi driver + * - false : upper layer can transmit data to wifi driver */ bool esp_wifi_internal_tx_is_stop(void); @@ -54,8 +53,6 @@ bool esp_wifi_internal_tx_is_stop(void); * @brief free the rx buffer which allocated by wifi driver * * @param void* buffer: rx buffer pointer - * - * @return nonoe */ void esp_wifi_internal_free_rx_buffer(void* buffer); @@ -78,7 +75,6 @@ int esp_wifi_internal_tx(wifi_interface_t wifi_if, void *buffer, u16_t len); * @brief The WiFi RX callback function * * Each time the WiFi need to forward the packets to high layer, the callback function will be called - * */ typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void *eb); @@ -90,18 +86,18 @@ typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void *eb); * @param wifi_interface_t ifx : interface * @param wifi_rxcb_t fn : WiFi RX callback * - * @return ESP_OK : succeed - * @return others : fail + * @return + * - ESP_OK : succeed + * - others : fail */ esp_err_t esp_wifi_internal_reg_rxcb(wifi_interface_t ifx, wifi_rxcb_t fn); /** * @brief Notify WIFI driver that the station got ip successfully * - * @param none - * - * @return ESP_OK : succeed - * @return others : fail + * @return + * - ESP_OK : succeed + * - others : fail */ esp_err_t esp_wifi_internal_set_sta_ip(void); diff --git a/components/esp32/include/soc/cpu.h b/components/esp32/include/soc/cpu.h index ee2907493e..4457c81a22 100644 --- a/components/esp32/include/soc/cpu.h +++ b/components/esp32/include/soc/cpu.h @@ -51,7 +51,10 @@ static inline void cpu_write_itlb(unsigned vpn, unsigned attr) asm volatile ("witlb %1, %0; isync\n" :: "r" (vpn), "r" (attr)); } -/* Make page 0 access raise an exception. +/** + * @brief Configure memory region protection + * + * Make page 0 access raise an exception. * Also protect some other unused pages so we can catch weirdness. * Useful attribute values: * 0 — cached, RW @@ -70,9 +73,7 @@ static inline void cpu_configure_region_protection() cpu_write_itlb(0x20000000, 0); } - - -/* +/** * @brief Set CPU frequency to the value defined in menuconfig * * Called from cpu_start.c, not intended to be called from other places. @@ -81,4 +82,16 @@ static inline void cpu_configure_region_protection() */ void esp_set_cpu_freq(void); +/** + * @brief Stall CPU using RTC controller + * @param cpu_id ID of the CPU to stall (0 = PRO, 1 = APP) + */ +void esp_cpu_stall(int cpu_id); + +/** + * @brief Un-stall CPU using RTC controller + * @param cpu_id ID of the CPU to un-stall (0 = PRO, 1 = APP) + */ +void esp_cpu_unstall(int cpu_id); + #endif diff --git a/components/esp32/panic.c b/components/esp32/panic.c index c5d8aa669e..8f51994401 100644 --- a/components/esp32/panic.c +++ b/components/esp32/panic.c @@ -27,6 +27,7 @@ #include "soc/rtc_cntl_reg.h" #include "soc/timer_group_struct.h" #include "soc/timer_group_reg.h" +#include "soc/cpu.h" #include "esp_gdbstub.h" #include "esp_panic.h" @@ -108,21 +109,10 @@ static const char *edesc[]={ void commonErrorHandler(XtExcFrame *frame); //The fact that we've panic'ed probably means the other CPU is now running wild, possibly -//messing up the serial output, so we kill it here. -static void haltOtherCore() { - if (xPortGetCoreID()==0) { - //Kill app cpu - CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C1_M); - SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<> 8; + mac[1] = mac_high; + mac[2] = mac_low >> 24; + mac[3] = mac_low >> 16; + mac[4] = mac_low >> 8; + mac[5] = mac_low; + + efuse_crc = mac_high >> 16; + calc_crc = esp_crc8(mac, 6); + + if (efuse_crc != calc_crc) { + // Small range of MAC addresses are accepted even if CRC is invalid. + // These addresses are reserved for Espressif internal use. + if ((mac_high & 0xFFFF) == 0x18fe) { + if ((mac_low >= 0x346a85c7) && (mac_low <= 0x346a85f8)) { + return ESP_OK; + } + } else { + ESP_LOGE(TAG, "MAC address CRC error, efuse_crc = 0x%02x; calc_crc = 0x%02x", efuse_crc, calc_crc); + abort(); + } + } + return ESP_OK; +} + + +void IRAM_ATTR system_restart(void) +{ + esp_wifi_stop(); + + // Disable scheduler on this core. + vTaskSuspendAll(); + const uint32_t core_id = xPortGetCoreID(); + const uint32_t other_core_id = core_id == 0 ? 1 : 0; + esp_cpu_stall(other_core_id); + + // We need to disable TG0/TG1 watchdogs + // First enable RTC watchdog to be on the safe side + REG_WRITE(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE); + REG_WRITE(RTC_CNTL_WDTCONFIG0_REG, + RTC_CNTL_WDT_FLASHBOOT_MOD_EN_M | + (1 << RTC_CNTL_WDT_SYS_RESET_LENGTH_S) | + (1 << RTC_CNTL_WDT_CPU_RESET_LENGTH_S) ); + REG_WRITE(RTC_CNTL_WDTCONFIG1_REG, 128000); + + // Disable TG0/TG1 watchdogs + TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; + TIMERG0.wdt_config0.en = 0; + TIMERG0.wdt_wprotect=0; + TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; + TIMERG1.wdt_config0.en = 0; + TIMERG1.wdt_wprotect=0; + + // Disable all interrupts + xt_ints_off(0xFFFFFFFF); + + // Disable cache + Cache_Read_Disable(0); + Cache_Read_Disable(1); + + // Flush any data left in UART FIFO + uart_tx_flush(0); + uart_tx_flush(1); + uart_tx_flush(2); + + // Reset wifi/bluetooth (bb/mac) + SET_PERI_REG_MASK(DPORT_WIFI_RST_EN_REG, 0x1f); + REG_WRITE(DPORT_WIFI_RST_EN_REG, 0); + + // Reset timer/spi/uart + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, + DPORT_TIMERS_RST | DPORT_SPI_RST_1 | DPORT_UART_RST); + REG_WRITE(DPORT_PERIP_RST_EN_REG, 0); + + // Reset CPUs + if (core_id == 0) { + // Running on PRO CPU: APP CPU is stalled. Can reset both CPUs. + SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, + RTC_CNTL_SW_PROCPU_RST_M | RTC_CNTL_SW_APPCPU_RST_M); + } else { + // Running on APP CPU: need to reset PRO CPU and unstall it, + // then stall APP CPU + SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST_M); + esp_cpu_unstall(0); + esp_cpu_stall(1); + } + while(true) { + ; + } +} + +void system_restore(void) +{ + esp_wifi_restore(); +} + +#if 0 +void system_deep_sleep_instant(uint64_t time_in_us) +{ + u32 period, cycle_h, cycle_l; + + { + struct rst_info debug_data; + memset(&debug_data, 0, sizeof(struct rst_info)); + + WRITE_PERI_REG(RTC_STORE0, DEEP_SLEEP_AWAKE_FLAG); + debug_data.flag = DEEP_SLEEP_AWAKE_FLAG; + + system_write_rtc_mem(0, &debug_data, sizeof(struct rst_info)); + } + + rtc_set_cpu_freq(XTAL_AUTO, CPU_XTAL); + esp_set_deep_sleep_wake_stub(esp_wake_deep_sleep); + + period = rtc_slowck_cali(CALI_RTC_MUX, 128, XTAL_AUTO); + rtc_usec2rtc(time_in_us >> 32, time_in_us, period, &cycle_h, &cycle_l); + + rtc_slp_prep_lite(1, 0); + rtc_sleep(cycle_h, cycle_l, TIMER_EXPIRE_EN, 0); +} + +static uint64_t deep_sleep_time; + +static void system_deep_sleep_step2(void) +{ + system_deep_sleep_instant(deep_sleep_time); +} + +void system_deep_sleep(uint64 time_in_us) +{ + wifi_set_sleep_flag(1); + + deep_sleep_time = time_in_us; + + os_timer_disarm(&sta_con_timer); + os_timer_setfn(&sta_con_timer, (os_timer_func_t *)system_deep_sleep_step2, NULL); + os_timer_arm(&sta_con_timer, 100, 0); +} + +#endif + +uint32_t system_get_free_heap_size(void) +{ + return xPortGetFreeHeapSize(); +} + + +struct rst_info *system_get_rst_info(void) +{ + return NULL; +} + +const char* system_get_sdk_version(void) +{ + return "master"; +} + + diff --git a/components/newlib/time.c b/components/newlib/time.c index 3426a01bfb..1baa955759 100644 --- a/components/newlib/time.c +++ b/components/newlib/time.c @@ -184,3 +184,29 @@ int settimeofday(const struct timeval *tv, const struct timezone *tz) return -1; #endif } + +uint32_t system_get_time(void) +{ +#if defined( WITH_FRC1 ) || defined( WITH_RTC ) + return get_time_since_boot(); +#else + return 0; +#endif +} + +uint32_t system_get_current_time(void) __attribute__((alias("system_get_time"))); + +uint32_t system_relative_time(uint32_t current_time) +{ + return system_get_time() - current_time; +} + +uint64_t system_get_rtc_time(void) +{ +#ifdef WITH_RTC + return get_rtc_time_us(); +#else + return 0; +#endif +} + From 46a39b1e0fa507a1e233b62168b8819ce829b223 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 21 Nov 2016 22:56:11 +0800 Subject: [PATCH 06/25] catch log output from WiFi libs --- components/esp32/cpu_start.c | 2 +- components/esp32/lib_printf.c | 112 +++++++++++++++++++++++++++++++ components/log/include/esp_log.h | 3 - 3 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 components/esp32/lib_printf.c diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index 293be565df..f55bc0350e 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -152,6 +152,7 @@ void IRAM_ATTR call_start_cpu1() void start_cpu0_default(void) { + esp_setup_syscall_table(); //Enable trace memory and immediately start trace. #if CONFIG_MEMMAP_TRACEMEM #if CONFIG_MEMMAP_TRACEMEM_TWOBANKS @@ -172,7 +173,6 @@ void start_cpu0_default(void) #if CONFIG_TASK_WDT esp_task_wdt_init(); #endif - esp_setup_syscall_table(); esp_setup_time_syscalls(); esp_vfs_dev_uart_register(); esp_reent_init(_GLOBAL_REENT); diff --git a/components/esp32/lib_printf.c b/components/esp32/lib_printf.c new file mode 100644 index 0000000000..8a537ffbf9 --- /dev/null +++ b/components/esp32/lib_printf.c @@ -0,0 +1,112 @@ +// Copyright 2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include "esp_log.h" +#include "esp_attr.h" + +#define VPRINTF_STACK_BUFFER_SIZE 80 + +static int lib_printf(const char* tag, const char* format, va_list arg) +{ + char temp[VPRINTF_STACK_BUFFER_SIZE]; + int len = vsnprintf(temp, sizeof(temp) - 1, format, arg); + temp[sizeof(temp) - 1] = 0; + int i; + for (i = len - 1; i >= 0; --i) { + if (temp[i] != '\n' && temp[i] != '\r' && temp[i] != ' ') { + break; + } + temp[i] = 0; + } + if (i > 0) { + ESP_EARLY_LOGI(tag, "%s", temp); + } + va_end(arg); + return len; +} + +int phy_printf(const char* format, ...) +{ + va_list arg; + va_start(arg, format); + int res = lib_printf("phy", format, arg); + va_end(arg); + return res; +} + + +int rtc_printf(const char* format, ...) +{ + va_list arg; + va_start(arg, format); + int res = lib_printf("rtc", format, arg); + va_end(arg); + return res; +} + +int wpa_printf(const char* format, ...) +{ + va_list arg; + va_start(arg, format); + int res = lib_printf("wpa", format, arg); + va_end(arg); + return res; +} + +int wps_printf(const char* format, ...) +{ + va_list arg; + va_start(arg, format); + int res = lib_printf("wps", format, arg); + va_end(arg); + return res; +} + +int pp_printf(const char* format, ...) +{ + va_list arg; + va_start(arg, format); + int res = lib_printf("pp", format, arg); + va_end(arg); + return res; +} + +int sc_printf(const char* format, ...) +{ + va_list arg; + va_start(arg, format); + int res = lib_printf("smartconfig", format, arg); + va_end(arg); + return res; +} + +int core_printf(const char* format, ...) +{ + va_list arg; + va_start(arg, format); + int res = lib_printf("core", format, arg); + va_end(arg); + return res; +} + +int net80211_printf(const char* format, ...) +{ + va_list arg; + va_start(arg, format); + int res = lib_printf("net80211", format, arg); + va_end(arg); + return res; +} diff --git a/components/log/include/esp_log.h b/components/log/include/esp_log.h index f4b9aa2885..33bc10b42a 100644 --- a/components/log/include/esp_log.h +++ b/components/log/include/esp_log.h @@ -18,10 +18,7 @@ #include #include #include "sdkconfig.h" - -#ifdef BOOTLOADER_BUILD #include -#endif #ifdef __cplusplus extern "C" { From cf6fc7c7414458fe7afc3d895035831c15d3a4d5 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 21 Nov 2016 22:59:46 +0800 Subject: [PATCH 07/25] Add API for random number generator --- components/esp32/hw_random.c | 33 ++++++++++ components/esp32/include/soc/soc.h | 4 +- components/esp32/include/soc/wdev_reg.h | 18 ++++++ components/wpa_supplicant/component.mk | 2 +- .../wpa_supplicant/port/include/endian.h | 1 + components/wpa_supplicant/port/os_xtensa.c | 64 +++++++++++++++++++ 6 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 components/esp32/hw_random.c create mode 100644 components/esp32/include/soc/wdev_reg.h create mode 100644 components/wpa_supplicant/port/os_xtensa.c diff --git a/components/esp32/hw_random.c b/components/esp32/hw_random.c new file mode 100644 index 0000000000..2c6e2cf5f8 --- /dev/null +++ b/components/esp32/hw_random.c @@ -0,0 +1,33 @@ +// Copyright 2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include +#include +#include +#include "esp_attr.h" +#include "soc/wdev_reg.h" +#include "freertos/FreeRTOSConfig.h" +#include "xtensa/core-macros.h" + +uint32_t IRAM_ATTR esp_random(void) +{ + static uint32_t last_ccount = 0; + uint32_t ccount; + do { + ccount = XTHAL_GET_CCOUNT(); + } while (ccount - last_ccount < XT_CLOCK_FREQ / APB_CLK_FREQ * 16); + last_ccount = ccount; + return REG_READ(WDEV_RND_REG); +} diff --git a/components/esp32/include/soc/soc.h b/components/esp32/include/soc/soc.h index bec4c85cfc..61ec2e1f2d 100755 --- a/components/esp32/include/soc/soc.h +++ b/components/esp32/include/soc/soc.h @@ -129,10 +129,10 @@ //}} //Periheral Clock {{ -#define APB_CLK_FREQ_ROM 26*1000000 +#define APB_CLK_FREQ_ROM ( 26*1000000 ) #define CPU_CLK_FREQ_ROM APB_CLK_FREQ_ROM #define CPU_CLK_FREQ APB_CLK_FREQ -#define APB_CLK_FREQ 80*1000000 //unit: Hz +#define APB_CLK_FREQ ( 80*1000000 ) //unit: Hz #define UART_CLK_FREQ APB_CLK_FREQ #define WDT_CLK_FREQ APB_CLK_FREQ #define TIMER_CLK_FREQ (80000000>>4) //80MHz divided by 16 diff --git a/components/esp32/include/soc/wdev_reg.h b/components/esp32/include/soc/wdev_reg.h new file mode 100644 index 0000000000..7189c9ec39 --- /dev/null +++ b/components/esp32/include/soc/wdev_reg.h @@ -0,0 +1,18 @@ +// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +/* Hardware random number generator register */ +#define WDEV_RND_REG 0x60035144 diff --git a/components/wpa_supplicant/component.mk b/components/wpa_supplicant/component.mk index b01eb83be9..daac5ca70e 100644 --- a/components/wpa_supplicant/component.mk +++ b/components/wpa_supplicant/component.mk @@ -1,4 +1,4 @@ COMPONENT_ADD_INCLUDEDIRS := include port/include -COMPONENT_SRCDIRS := src/crypto +COMPONENT_SRCDIRS := src/crypto port CFLAGS += -DEMBEDDED_SUPP -D__ets__ -Wno-strict-aliasing diff --git a/components/wpa_supplicant/port/include/endian.h b/components/wpa_supplicant/port/include/endian.h index e2df616b79..5e6a876fda 100644 --- a/components/wpa_supplicant/port/include/endian.h +++ b/components/wpa_supplicant/port/include/endian.h @@ -119,6 +119,7 @@ typedef __uint64_t uint64_t; #endif /* _BYTE_ORDER == _LITTLE_ENDIAN */ /* Alignment-agnostic encode/decode bytestream to/from little/big endian. */ +#define INLINE __inline__ static INLINE uint16_t be16dec(const void *pp) diff --git a/components/wpa_supplicant/port/os_xtensa.c b/components/wpa_supplicant/port/os_xtensa.c new file mode 100644 index 0000000000..9ecde1f113 --- /dev/null +++ b/components/wpa_supplicant/port/os_xtensa.c @@ -0,0 +1,64 @@ +/* + * wpa_supplicant/hostapd / Internal implementation of OS specific functions + * Copyright (c) 2005-2006, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + * + * This file is an example of operating system specific wrapper functions. + * This version implements many of the functions internally, so it can be used + * to fill in missing functions from the target system C libraries. + * + * Some of the functions are using standard C library calls in order to keep + * this file in working condition to allow the functions to be tested on a + * Linux target. Please note that OS_NO_C_LIB_DEFINES needs to be defined for + * this file to work correctly. Note that these implementations are only + * examples and are not optimized for speed. + */ + +#include "crypto/common.h" +#include "os.h" +#include +#include +#include +#include "esp_system.h" + +int os_get_time(struct os_time *t) +{ + return gettimeofday((struct timeval*) t, NULL); +} + +unsigned long os_random(void) +{ + return esp_random(); +} + +unsigned long r_rand(void) __attribute__((alias("os_random"))); + + +int os_get_random(unsigned char *buf, size_t len) +{ + int i, j; + unsigned long tmp; + + for (i = 0; i < ((len + 3) & ~3) / 4; i++) { + tmp = r_rand(); + + for (j = 0; j < 4; j++) { + if ((i * 4 + j) < len) { + buf[i * 4 + j] = (uint8_t)(tmp >> (j * 8)); + } else { + break; + } + } + } + + return 0; +} + From df6edb50e9905ba60588d8175cd357127602d552 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 21 Nov 2016 23:05:23 +0800 Subject: [PATCH 08/25] implement esp_deep_sleep, fix build issues --- .gitlab-ci.yml | 4 + components/bt/bt.c | 2 +- components/esp32/cpu_freq.c | 25 +--- components/esp32/deepsleep.c | 19 +++ components/esp32/include/esp_deepsleep.h | 37 +++-- components/esp32/include/esp_system.h | 15 +- components/esp32/include/rom/ets_sys.h | 8 ++ components/esp32/include/rom/uart.h | 9 +- components/esp32/include/xtensa/core-macros.h | 2 +- components/esp32/lib | 2 +- components/esp32/phy_init.c | 4 +- components/esp32/rtc.h | 130 ++++++++++++++++++ components/esp32/system_api.c | 65 ++------- .../01_hello_world/main/hello_world_main.c | 2 +- examples/06_sntp/main/sntp_main.c | 2 +- examples/07_nvs_rw_value/main/nvs_rw_value.c | 2 +- examples/08_nvs_rw_blob/main/nvs_rw_blob.c | 2 +- 17 files changed, 222 insertions(+), 108 deletions(-) create mode 100644 components/esp32/rtc.h diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 814279ce15..94e9b6dc7b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,6 +46,10 @@ build_template_app: - sed -i.bak -e's/CONFIG_OPTIMIZATION_LEVEL_DEBUG\=y/CONFIG_OPTIMIZATION_LEVEL_RELEASE=y/' sdkconfig - make defconfig - make all V=1 + # Check if there are any stray printf/ets_printf references in WiFi libs + - cd ../components/esp32/lib + - test $(xtensa-esp32-elf-nm *.a | grep -w printf | wc -l) -eq 0 + - test $(xtensa-esp32-elf-nm *.a | grep -w ets_printf | wc -l) -eq 0 .build_gitlab: &build_template diff --git a/components/bt/bt.c b/components/bt/bt.c index 23f8aea92e..633ff9823b 100644 --- a/components/bt/bt.c +++ b/components/bt/bt.c @@ -115,7 +115,7 @@ static struct osi_funcs_t osi_funcs = { ._mutex_create = mutex_create_wrapper, ._mutex_lock = mutex_lock_wrapper, ._mutex_unlock = mutex_unlock_wrapper, - ._read_efuse_mac = system_efuse_read_mac, + ._read_efuse_mac = esp_efuse_read_mac, }; static void bt_controller_task(void *pvParam) diff --git a/components/esp32/cpu_freq.c b/components/esp32/cpu_freq.c index 327ea63867..c68dd4f078 100644 --- a/components/esp32/cpu_freq.c +++ b/components/esp32/cpu_freq.c @@ -16,25 +16,8 @@ #include "rom/ets_sys.h" #include "rom/uart.h" #include "sdkconfig.h" - -typedef enum{ - XTAL_40M = 40, - XTAL_26M = 26, - XTAL_24M = 24, - XTAL_AUTO = 0 -} xtal_freq_t; - -typedef enum{ - CPU_80M = 1, - CPU_160M = 2, - CPU_240M = 3, -} cpu_freq_t; - -extern void phy_get_romfunc_addr(); - -// TODO: these functions need to be moved from librtc to ESP-IDF -extern void rtc_init_lite(); -extern void rtc_set_cpu_freq(xtal_freq_t xtal_freq, cpu_freq_t cpu_freq); +#include "phy.h" +#include "rtc.h" /* * This function is not exposed as an API at this point, @@ -52,7 +35,7 @@ void esp_set_cpu_freq(void) // wait uart tx finish, otherwise some uart output will be lost uart_tx_wait_idle(0); - rtc_init_lite(); + rtc_init_lite(XTAL_AUTO); cpu_freq_t freq = CPU_80M; switch(freq_mhz) { case 240: @@ -73,7 +56,7 @@ void esp_set_cpu_freq(void) // wait uart tx finish, otherwise some uart output will be lost uart_tx_wait_idle(0); - rtc_set_cpu_freq(XTAL_AUTO, freq); + rtc_set_cpu_freq(freq); ets_update_cpu_frequency(freq_mhz); } diff --git a/components/esp32/deepsleep.c b/components/esp32/deepsleep.c index 742ff8cf40..b8b73a3b1f 100644 --- a/components/esp32/deepsleep.c +++ b/components/esp32/deepsleep.c @@ -10,6 +10,7 @@ #include "soc/dport_reg.h" #include "esp_attr.h" #include "esp_deepsleep.h" +#include "rtc.h" /* Updating RTC_MEMORY_CRC_REG register via set_rtc_memory_crc() is not thread-safe. */ @@ -46,3 +47,21 @@ void RTC_IRAM_ATTR esp_default_wake_deep_sleep(void) { } void __attribute__((weak, alias("esp_default_wake_deep_sleep"))) esp_wake_deep_sleep(void); + +void esp_deep_sleep(uint64_t time_in_us) +{ + rtc_set_cpu_freq(CPU_XTAL); + if (esp_get_deep_sleep_wake_stub() == NULL) { + esp_set_deep_sleep_wake_stub(esp_wake_deep_sleep); + } + uint32_t period = rtc_slowck_cali(CALI_RTC_MUX, 128); + uint32_t cycle_l, cycle_h; + rtc_usec2rtc(time_in_us >> 32, time_in_us, period, &cycle_h, &cycle_l); + rtc_slp_prep_lite(1, 0); + rtc_sleep(cycle_h, cycle_l, TIMER_EXPIRE_EN, 0); + while (1) { + ; + } +} + +void system_deep_sleep(uint64_t) __attribute__((alias("esp_deep_sleep"))); diff --git a/components/esp32/include/esp_deepsleep.h b/components/esp32/include/esp_deepsleep.h index 59b3129185..051ad14c3c 100644 --- a/components/esp32/include/esp_deepsleep.h +++ b/components/esp32/include/esp_deepsleep.h @@ -30,25 +30,34 @@ extern "C" { */ /** - * @brief Set the chip to deep-sleep mode. - * - * The device will automatically wake up after the deep-sleep time set - * by the users. Upon waking up, the device boots up from user_init. - * - * @attention The parameter time_in_us to be "uint64" is for further development. - * Only the low 32 bits of parameter time_in_us are avalable now. - * - * @param uint64 time_in_us : deep-sleep time, only the low 32bits are avalable now. unit: microsecond - * - * @return null - */ -void system_deep_sleep(uint64_t time_in_us); + * @brief Enter deep-sleep mode + * + * The device will automatically wake up after the deep-sleep time + * Upon waking up, the device calls deep sleep wake stub, and then proceeds + * to load application. + * + * This function does not return. + * + * @param time_in_us deep-sleep time, unit: microsecond + */ +void esp_deep_sleep(uint64_t time_in_us) __attribute__((noreturn)); + + +/** + * @brief Enter deep-sleep mode + * + * Function has been renamed to esp_deep_sleep. + * This name is deprecated and will be removed in a future version. + * + * @param time_in_us deep-sleep time, unit: microsecond + */ +void system_deep_sleep(uint64_t time_in_us) __attribute__((noreturn, deprecated)); /** * @brief Default stub to run on wake from deep sleep. * * Allows for executing code immediately on wake from sleep, before - * the software bootloader or esp-idf app has started up. + * the software bootloader or ESP-IDF app has started up. * * This function is weak-linked, so you can implement your own version * to run code immediately when the chip wakes from diff --git a/components/esp32/include/esp_system.h b/components/esp32/include/esp_system.h index e4fcbbf403..40ebd8403c 100644 --- a/components/esp32/include/esp_system.h +++ b/components/esp32/include/esp_system.h @@ -54,7 +54,7 @@ void esp_restart(void) __attribute__ ((noreturn)); * Function has been renamed to esp_restart. * This name will be removed in a future release. */ -void system_restart(void) __attribute((deprecated, noreturn)); +void system_restart(void) __attribute__ ((deprecated, noreturn)); /** * @brief Get system time, unit: microsecond. @@ -74,7 +74,6 @@ uint32_t system_get_time(void) __attribute__ ((deprecated)); */ uint32_t esp_get_free_heap_size(void); - /** * @brief Get the size of available heap. * @@ -103,7 +102,7 @@ uint32_t esp_random(void); * * @return ESP_OK on success */ -esp_err_t esp_efuse_read_mac(uint8_t mac[6]); +esp_err_t esp_efuse_read_mac(uint8_t* mac); /** * @brief Read hardware MAC address. @@ -116,6 +115,16 @@ esp_err_t esp_efuse_read_mac(uint8_t mac[6]); */ esp_err_t system_efuse_read_mac(uint8_t mac[6]) __attribute__ ((deprecated)); +/** + * Get SDK version + * + * This function is deprecated and will be removed in a future release. + * + * @return constant string "master" + */ +const char* system_get_sdk_version(void) __attribute__ ((deprecated)); + + #ifdef __cplusplus } diff --git a/components/esp32/include/rom/ets_sys.h b/components/esp32/include/rom/ets_sys.h index c412c9b41f..690691675a 100644 --- a/components/esp32/include/rom/ets_sys.h +++ b/components/esp32/include/rom/ets_sys.h @@ -605,6 +605,14 @@ void intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num); #define ETS_MEM_BAR() asm volatile ( "" : : : "memory" ) +typedef enum { + OK = 0, + FAIL, + PENDING, + BUSY, + CANCEL, +} STATUS; + /** * @} */ diff --git a/components/esp32/include/rom/uart.h b/components/esp32/include/rom/uart.h index 0c08590f57..aa3cf59217 100644 --- a/components/esp32/include/rom/uart.h +++ b/components/esp32/include/rom/uart.h @@ -17,6 +17,7 @@ #include "esp_types.h" #include "esp_attr.h" +#include "ets_sys.h" #ifdef __cplusplus extern "C" { @@ -161,14 +162,6 @@ typedef struct { int received; } UartDevice; -typedef enum { - OK = 0, - FAIL, - PENDING, - BUSY, - CANCEL, -} STATUS; - /** * @brief Init uart device struct value and reset uart0/uart1 rx. * Please do not call this function in SDK. diff --git a/components/esp32/include/xtensa/core-macros.h b/components/esp32/include/xtensa/core-macros.h index 663d29478a..c8f7e34762 100755 --- a/components/esp32/include/xtensa/core-macros.h +++ b/components/esp32/include/xtensa/core-macros.h @@ -42,7 +42,7 @@ * share the name with the existing functions from hal.h. * Including this header file will define XTHAL_USE_CACHE_MACROS * which directs hal.h not to use the functions. - * + */ /* * Single-cache-line operations in C-callable inline assembly. diff --git a/components/esp32/lib b/components/esp32/lib index e2e5781dc2..5182dd9dab 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit e2e5781dc27e638c5e63f85bc23590dd21af1619 +Subproject commit 5182dd9dab9ec37e69711de33bb0c200502c4c03 diff --git a/components/esp32/phy_init.c b/components/esp32/phy_init.c index 32d8f64edf..6154beae90 100644 --- a/components/esp32/phy_init.c +++ b/components/esp32/phy_init.c @@ -179,7 +179,7 @@ static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle, return ESP_ERR_INVALID_SIZE; } uint8_t sta_mac[6]; - system_efuse_read_mac(sta_mac); + esp_efuse_read_mac(sta_mac); if (memcmp(sta_mac, cal_data_mac, sizeof(sta_mac)) != 0) { ESP_LOGE(TAG, "%s: calibration data MAC check failed: expected " \ MACSTR ", found " MACSTR, @@ -210,7 +210,7 @@ static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle, return err; } uint8_t sta_mac[6]; - system_efuse_read_mac(sta_mac); + esp_efuse_read_mac(sta_mac); err = nvs_set_blob(handle, PHY_CAL_MAC_KEY, sta_mac, sizeof(sta_mac)); if (err != ESP_OK) { return err; diff --git a/components/esp32/rtc.h b/components/esp32/rtc.h new file mode 100644 index 0000000000..2ac3139c21 --- /dev/null +++ b/components/esp32/rtc.h @@ -0,0 +1,130 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#include +#include "soc/soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef enum{ + XTAL_40M = 40, + XTAL_26M = 26, + XTAL_24M = 24, + XTAL_AUTO = 0 +} xtal_freq_t; + +typedef enum{ + CPU_XTAL = 0, + CPU_80M = 1, + CPU_160M = 2, + CPU_240M = 3, + CPU_2M = 4 +} cpu_freq_t; + +typedef enum { + CALI_RTC_MUX = 0, + CALI_8MD256 = 1, + CALI_32K_XTAL = 2 +} cali_clk_t; + +/** + * This function must be called to initialize RTC library + * @param xtal_freq Frequency of main crystal + */ +void rtc_init_lite(xtal_freq_t xtal_freq); + +/** + * Switch CPU frequency + * @param cpu_freq new CPU frequency + */ +void rtc_set_cpu_freq(cpu_freq_t cpu_freq); + +/** + * @brief Return RTC slow clock's period + * @param cali_clk clock to calibrate + * @param slow_clk_cycles number of slow clock cycles to average + * @param xtal_freq chip's main XTAL freq + * @return average slow clock period in microseconds, Q13.19 fixed point format + */ +uint32_t rtc_slowck_cali(cali_clk_t cali_clk, uint32_t slow_clk_cycles); + +/** + * @brief Convert from microseconds to slow clock cycles + * @param time_in_us_h Time in microseconds, higher 32 bit part + * @param time_in_us_l Time in microseconds, lower 32 bit part + * @param slow_clk_period Period of slow clock in microseconds, Q13.19 fixed point format (as returned by rtc_slowck_cali). + * @param[out] cylces_h output, higher 32 bit part of number of slow clock cycles + * @param[out] cycles_l output, lower 32 bit part of number of slow clock cycles + */ +void rtc_usec2rtc(uint32_t time_in_us_h, uint32_t time_in_us_l, uint32_t slow_clk_period, uint32_t *cylces_h, uint32_t *cycles_l); + + +#define DEEP_SLEEP_PD_NORMAL BIT(0) /*!< Base deep sleep mode */ +#define DEEP_SLEEP_PD_RTC_PERIPH BIT(1) /*!< Power down RTC peripherals */ +#define DEEP_SLEEP_PD_RTC_SLOW_MEM BIT(2) /*!< Power down RTC SLOW memory */ +#define DEEP_SLEEP_PD_RTC_FAST_MEM BIT(3) /*!< Power down RTC FAST memory */ + +/** + * @brief Prepare for entering sleep mode + * @param deep_slp DEEP_SLEEP_PD_ flags combined with OR (DEEP_SLEEP_PD_NORMAL must be included) + * @param cpu_lp_mode for deep sleep, should be 0 + */ +void rtc_slp_prep_lite(uint32_t deep_slp, uint32_t cpu_lp_mode); + + +#define RTC_EXT_EVENT0_TRIG BIT(0) +#define RTC_EXT_EVENT1_TRIG BIT(1) +#define RTC_GPIO_TRIG BIT(2) +#define RTC_TIMER_EXPIRE BIT(3) +#define RTC_SDIO_TRIG BIT(4) +#define RTC_MAC_TRIG BIT(5) +#define RTC_UART0_TRIG BIT(6) +#define RTC_UART1_TRIG BIT(7) +#define RTC_TOUCH_TRIG BIT(8) +#define RTC_SAR_TRIG BIT(9) +#define RTC_BT_TRIG BIT(10) + + +#define RTC_EXT_EVENT0_TRIG_EN RTC_EXT_EVENT0_TRIG +#define RTC_EXT_EVENT1_TRIG_EN RTC_EXT_EVENT1_TRIG +#define RTC_GPIO_TRIG_EN RTC_GPIO_TRIG +#define RTC_TIMER_EXPIRE_EN RTC_TIMER_EXPIRE +#define RTC_SDIO_TRIG_EN RTC_SDIO_TRIG +#define RTC_MAC_TRIG_EN RTC_MAC_TRIG +#define RTC_UART0_TRIG_EN RTC_UART0_TRIG +#define RTC_UART1_TRIG_EN RTC_UART1_TRIG +#define RTC_TOUCH_TRIG_EN RTC_TOUCH_TRIG +#define RTC_SAR_TRIG_EN RTC_SAR_TRIG +#define RTC_BT_TRIG_EN RTC_BT_TRIG + +/** + * @brief Enter sleep mode for given number of cycles + * @param cycles_h higher 32 bit part of number of slow clock cycles + * @param cycles_l lower 32 bit part of number of slow clock cycles + * @param wakeup_opt wake up reason to enable (RTC_xxx_EN flags combined with OR) + * @param reject_opt reserved, should be 0 + * @return TBD + */ +uint32_t rtc_sleep(uint32_t cycles_h, uint32_t cycles_l, uint32_t wakeup_opt, uint32_t reject_opt); + + +#ifdef __cplusplus +} +#endif + diff --git a/components/esp32/system_api.c b/components/esp32/system_api.c index 0d46e1e7aa..36a5f806da 100644 --- a/components/esp32/system_api.c +++ b/components/esp32/system_api.c @@ -32,7 +32,11 @@ static const char* TAG = "system_api"; -esp_err_t system_efuse_read_mac(uint8_t mac[6]) +void system_init() +{ +} + +esp_err_t esp_efuse_read_mac(uint8_t* mac) { uint8_t efuse_crc; uint8_t calc_crc; @@ -64,8 +68,10 @@ esp_err_t system_efuse_read_mac(uint8_t mac[6]) return ESP_OK; } +esp_err_t system_efuse_read_mac(uint8_t mac[6]) __attribute__((alias("esp_efuse_read_mac"))); -void IRAM_ATTR system_restart(void) + +void IRAM_ATTR esp_restart(void) { esp_wifi_stop(); @@ -130,66 +136,19 @@ void IRAM_ATTR system_restart(void) } } +void system_restart(void) __attribute__((alias("esp_restart"))); + void system_restore(void) { esp_wifi_restore(); } -#if 0 -void system_deep_sleep_instant(uint64_t time_in_us) -{ - u32 period, cycle_h, cycle_l; - - { - struct rst_info debug_data; - memset(&debug_data, 0, sizeof(struct rst_info)); - - WRITE_PERI_REG(RTC_STORE0, DEEP_SLEEP_AWAKE_FLAG); - debug_data.flag = DEEP_SLEEP_AWAKE_FLAG; - - system_write_rtc_mem(0, &debug_data, sizeof(struct rst_info)); - } - - rtc_set_cpu_freq(XTAL_AUTO, CPU_XTAL); - esp_set_deep_sleep_wake_stub(esp_wake_deep_sleep); - - period = rtc_slowck_cali(CALI_RTC_MUX, 128, XTAL_AUTO); - rtc_usec2rtc(time_in_us >> 32, time_in_us, period, &cycle_h, &cycle_l); - - rtc_slp_prep_lite(1, 0); - rtc_sleep(cycle_h, cycle_l, TIMER_EXPIRE_EN, 0); -} - -static uint64_t deep_sleep_time; - -static void system_deep_sleep_step2(void) -{ - system_deep_sleep_instant(deep_sleep_time); -} - -void system_deep_sleep(uint64 time_in_us) -{ - wifi_set_sleep_flag(1); - - deep_sleep_time = time_in_us; - - os_timer_disarm(&sta_con_timer); - os_timer_setfn(&sta_con_timer, (os_timer_func_t *)system_deep_sleep_step2, NULL); - os_timer_arm(&sta_con_timer, 100, 0); -} - -#endif - -uint32_t system_get_free_heap_size(void) +uint32_t esp_get_free_heap_size(void) { return xPortGetFreeHeapSize(); } - -struct rst_info *system_get_rst_info(void) -{ - return NULL; -} +uint32_t system_get_free_heap_size(void) __attribute__((alias("esp_get_free_heap_size"))); const char* system_get_sdk_version(void) { diff --git a/examples/01_hello_world/main/hello_world_main.c b/examples/01_hello_world/main/hello_world_main.c index 1ff190acef..0e872522fa 100644 --- a/examples/01_hello_world/main/hello_world_main.c +++ b/examples/01_hello_world/main/hello_world_main.c @@ -21,7 +21,7 @@ void hello_task(void *pvParameter) } printf("Restarting now.\n"); fflush(stdout); - system_restart(); + esp_restart(); } void app_main() diff --git a/examples/06_sntp/main/sntp_main.c b/examples/06_sntp/main/sntp_main.c index 83f33b9656..6827fa9378 100644 --- a/examples/06_sntp/main/sntp_main.c +++ b/examples/06_sntp/main/sntp_main.c @@ -88,7 +88,7 @@ void app_main() const int deep_sleep_sec = 10; ESP_LOGI(TAG, "Entering deep sleep for %d seconds", deep_sleep_sec); - system_deep_sleep(1000000LL * deep_sleep_sec); + esp_deep_sleep(1000000LL * deep_sleep_sec); } static void obtain_time(void) diff --git a/examples/07_nvs_rw_value/main/nvs_rw_value.c b/examples/07_nvs_rw_value/main/nvs_rw_value.c index 978c48edb8..dac2d4077e 100644 --- a/examples/07_nvs_rw_value/main/nvs_rw_value.c +++ b/examples/07_nvs_rw_value/main/nvs_rw_value.c @@ -76,5 +76,5 @@ void app_main() } printf("Restarting now.\n"); fflush(stdout); - system_restart(); + esp_restart(); } diff --git a/examples/08_nvs_rw_blob/main/nvs_rw_blob.c b/examples/08_nvs_rw_blob/main/nvs_rw_blob.c index 3fbdfcacd6..7c13c15ba7 100644 --- a/examples/08_nvs_rw_blob/main/nvs_rw_blob.c +++ b/examples/08_nvs_rw_blob/main/nvs_rw_blob.c @@ -170,7 +170,7 @@ void app_main() if (err != ESP_OK) printf("Error (%d) saving run time blob to NVS!\n", err); printf("Restarting...\n"); fflush(stdout); - system_restart(); + esp_restart(); } } vTaskDelay(200 / portTICK_RATE_MS); From 2a73783bc656f208c4277f837593acb200a203c1 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 15 Nov 2016 00:46:53 +0100 Subject: [PATCH 09/25] StaticQueue_t needs to have the same size as xQUEUE. Without this change, building FreeRTOS with static allocation enabled succeeds, but trying to create a queue from a static buffer causes an assert because the size of static and dynamic queues differ. --- components/freertos/include/freertos/FreeRTOS.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/components/freertos/include/freertos/FreeRTOS.h b/components/freertos/include/freertos/FreeRTOS.h index f6c9aa497d..67bdc6db12 100644 --- a/components/freertos/include/freertos/FreeRTOS.h +++ b/components/freertos/include/freertos/FreeRTOS.h @@ -927,7 +927,6 @@ typedef struct xSTATIC_QUEUE StaticList_t xDummy3[ 2 ]; UBaseType_t uxDummy4[ 3 ]; - BaseType_t ucDummy5[ 2 ]; #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) uint8_t ucDummy6; @@ -943,12 +942,12 @@ typedef struct xSTATIC_QUEUE #endif struct { - volatile uint32_t mux; + volatile uint32_t ucDummy10; #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG - const char *lastLockedFn; - int lastLockedLine; + void *pvDummy8; + UBaseType_t uxDummy11; #endif - } mux; + } sDummy12; } StaticQueue_t; typedef StaticQueue_t StaticSemaphore_t; From 5ac7810480c77af66963c047dee3997d8101bc6e Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 23 Nov 2016 08:49:15 +1100 Subject: [PATCH 10/25] build system: Fix null-terminating of text files for embedding on OS X Ref github #112 --- make/component_wrapper.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/component_wrapper.mk b/make/component_wrapper.mk index 3018c18b55..48bf0ecace 100644 --- a/make/component_wrapper.mk +++ b/make/component_wrapper.mk @@ -198,7 +198,7 @@ embed_bin/$$(notdir $(1)): $(call resolvepath,$(1),$(COMPONENT_PATH)) | embed_bi embed_txt/$$(notdir $(1)): $(call resolvepath,$(1),$(COMPONENT_PATH)) | embed_txt cp $$< $$@ - echo -ne '\0' >> $$@ # null-terminate text files + printf '\0' >> $$@ # null-terminate text files # messing about with the embed_X subdirectory then using 'cd' for objcopy is because the # full path passed to OBJCOPY makes it into the name of the symbols in the .o file From 180f4d092917183fb27508f1ca7fb1eabf1b7d23 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 23 Nov 2016 09:42:35 +1100 Subject: [PATCH 11/25] FreeRTOS: Use C11 _Static_assert to verify static "dummy" structs at compile time Includes a tweak to make Static_task_t equal size to TCB_t when using MPU_WRAPPERS . Matches tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE macro in tasks.c. This isn't actually a bug (if static task allocation is off, there is no use for Static_task_t), but it allows us to make consistent compile-time checks that Static_task_t == TCB_t. --- components/freertos/include/freertos/FreeRTOS.h | 3 ++- components/freertos/include/freertos/list.h | 13 +++++++++++++ components/freertos/queue.c | 5 +++++ components/freertos/tasks.c | 4 ++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/components/freertos/include/freertos/FreeRTOS.h b/components/freertos/include/freertos/FreeRTOS.h index 67bdc6db12..4c60308f78 100644 --- a/components/freertos/include/freertos/FreeRTOS.h +++ b/components/freertos/include/freertos/FreeRTOS.h @@ -895,7 +895,8 @@ typedef struct xSTATIC_TCB uint32_t ulDummy18; uint32_t ucDummy19; #endif - #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + #if( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) \ + || ( portUSING_MPU_WRAPPERS == 1 ) ) uint8_t uxDummy20; #endif diff --git a/components/freertos/include/freertos/list.h b/components/freertos/include/freertos/list.h index b63df7f724..8606deba5a 100644 --- a/components/freertos/include/freertos/list.h +++ b/components/freertos/include/freertos/list.h @@ -190,6 +190,10 @@ struct xLIST_ITEM }; typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */ +#if __GNUC_PREREQ(4, 6) +_Static_assert(sizeof(StaticListItem_t) == sizeof(ListItem_t), "StaticListItem_t != ListItem_t"); +#endif + struct xMINI_LIST_ITEM { listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ @@ -199,6 +203,11 @@ struct xMINI_LIST_ITEM }; typedef struct xMINI_LIST_ITEM MiniListItem_t; +#if __GNUC_PREREQ(4, 6) +_Static_assert(sizeof(StaticMiniListItem_t) == sizeof(MiniListItem_t), "StaticMiniListItem_t != MiniListItem_t"); +#endif + + /* * Definition of the type of queue used by the scheduler. */ @@ -211,6 +220,10 @@ typedef struct xLIST listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ } List_t; +#if __GNUC_PREREQ(4, 6) +_Static_assert(sizeof(StaticList_t) == sizeof(List_t), "StaticList_t != List_t"); +#endif + /* * Access macro to set the owner of a list item. The owner of a list item * is the object (usually a TCB) that contains the list item. diff --git a/components/freertos/queue.c b/components/freertos/queue.c index f404a243e6..7c491f6952 100644 --- a/components/freertos/queue.c +++ b/components/freertos/queue.c @@ -179,6 +179,11 @@ typedef struct QueueDefinition name below to enable the use of older kernel aware debuggers. */ typedef xQUEUE Queue_t; +#if __GNUC_PREREQ(4, 6) +_Static_assert(sizeof(StaticQueue_t) == sizeof(Queue_t), "StaticQueue_t != Queue_t"); +#endif + + /*-----------------------------------------------------------*/ /* diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 26103ee236..16cce3b967 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -242,6 +242,10 @@ typedef struct tskTaskControlBlock below to enable the use of older kernel aware debuggers. */ typedef tskTCB TCB_t; +#if __GNUC_PREREQ(4, 6) +_Static_assert(sizeof(StaticTask_t) == sizeof(TCB_t), "StaticTask_t != TCB_t"); +#endif + /* * Some kernel aware debuggers require the data the debugger needs access to to * be global, rather than file scope. From 1d05f41a70583a4631d6a7520a8772b216df05f6 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 23 Nov 2016 10:47:40 +1100 Subject: [PATCH 12/25] UART driver: Fix crash in ISR due to "UART" static array moved to flash Ref: http://esp32.com/viewtopic.php?f=13&t=546&sid=76ff371ae2b259441a2cf355e96d74b9#p2275 This is a really subtle bug, gcc noticed the UART array elements are read-only so implicitly moved the elements to .rodata as if it was const. However this array is accessed from the UART ISR, so has to be in IRAM or DRAM. --- components/driver/uart.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/driver/uart.c b/components/driver/uart.c index 02610e7b49..59b4904dcd 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -84,7 +84,8 @@ typedef struct { static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0}; -static uart_dev_t* UART[UART_NUM_MAX] = {&UART0, &UART1, &UART2}; +/* DRAM_ATTR is required to avoid UART array placed in flash, due to accessed from ISR */ +static DRAM_ATTR uart_dev_t* const UART[UART_NUM_MAX] = {&UART0, &UART1, &UART2}; static portMUX_TYPE uart_spinlock[UART_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED}; esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit) From 83a3ce882f568692400914b410863b45877f4562 Mon Sep 17 00:00:00 2001 From: antti Date: Wed, 23 Nov 2016 11:29:36 +0800 Subject: [PATCH 13/25] add updated nvs flash test --- components/nvs_flash/test/test_nvs.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/components/nvs_flash/test/test_nvs.c b/components/nvs_flash/test/test_nvs.c index c523026432..db97879bc2 100644 --- a/components/nvs_flash/test/test_nvs.c +++ b/components/nvs_flash/test/test_nvs.c @@ -9,32 +9,26 @@ #include "esp_spi_flash.h" #include -#define NVS_FLASH_SECTOR 6 -#define NVS_FLASH_SECTOR_COUNT_MIN 3 -#define NVS_FLASH_SECTOR_COUNT_MAX 10 TEST_CASE("various nvs tests", "[nvs]") { nvs_handle handle_1; - TEST_ESP_ERR(nvs_open("namespace1", NVS_READWRITE, &handle_1), ESP_ERR_NVS_NOT_INITIALIZED); - for (uint16_t i = NVS_FLASH_SECTOR; i < NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN; ++i) { - spi_flash_erase_sector(i); - } - TEST_ESP_OK(nvs_flash_init_custom(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)); + TEST_ESP_OK(nvs_flash_init()); + TEST_ESP_ERR(nvs_open("test_namespace1", NVS_READONLY, &handle_1), ESP_ERR_NVS_NOT_FOUND); - TEST_ESP_ERR(nvs_open("namespace1", NVS_READONLY, &handle_1), ESP_ERR_NVS_NOT_FOUND); + TEST_ESP_ERR(nvs_set_i32(handle_1, "foo", 0x12345678), ESP_ERR_NVS_INVALID_HANDLE); + nvs_close(handle_1); - // TEST_ESP_ERR(nvs_set_i32(handle_1, "foo", 0x12345678), ESP_ERR_NVS_READ_ONLY); - // nvs_close(handle_1); - - TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle_1)); + TEST_ESP_OK(nvs_open("test_namespace2", NVS_READWRITE, &handle_1)); + TEST_ESP_OK(nvs_erase_all(handle_1)); TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x12345678)); TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x23456789)); nvs_handle handle_2; - TEST_ESP_OK(nvs_open("namespace2", NVS_READWRITE, &handle_2)); + TEST_ESP_OK(nvs_open("test_namespace3", NVS_READWRITE, &handle_2)); + TEST_ESP_OK(nvs_erase_all(handle_2)); TEST_ESP_OK(nvs_set_i32(handle_2, "foo", 0x3456789a)); - const char *str = "value 0123456789abcdef0123456789abcdef"; + const char* str = "value 0123456789abcdef0123456789abcdef"; TEST_ESP_OK(nvs_set_str(handle_2, "key", str)); int32_t v1; @@ -51,4 +45,7 @@ TEST_CASE("various nvs tests", "[nvs]") TEST_ESP_OK(nvs_get_str(handle_2, "key", buf, &buf_len)); TEST_ASSERT_EQUAL_INT32(0, strcmp(buf, str)); + + nvs_close(handle_1); + nvs_close(handle_2); } From 15d96eccdba963bb98e6c7efbac04c009a8c0652 Mon Sep 17 00:00:00 2001 From: antti Date: Wed, 23 Nov 2016 11:42:12 +0800 Subject: [PATCH 14/25] add build all unit tests in project.mk and update doc --- make/project.mk | 12 +++++++++--- tools/unit-test-app/README.md | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/make/project.mk b/make/project.mk index 0dfce4368a..181152f118 100644 --- a/make/project.mk +++ b/make/project.mk @@ -94,10 +94,16 @@ COMPONENT_PATHS += $(abspath $(SRCDIRS)) # A component is buildable if it has a component.mk makefile in it COMPONENT_PATHS_BUILDABLE := $(foreach cp,$(COMPONENT_PATHS),$(if $(wildcard $(cp)/component.mk),$(cp))) -# If TEST_COMPONENTS is set on the command line, create variables for building unit tests +# If TESTS_ALL set to 1, set TEST_COMPONENTS to all components +ifeq ($(TESTS_ALL),1) +TEST_COMPONENTS := $(COMPONENTS) +endif + +# If TEST_COMPONENTS is set, create variables for building unit tests ifdef TEST_COMPONENTS -TEST_COMPONENT_PATHS := $(foreach comp,$(TEST_COMPONENTS),$(IDF_PATH)/components/$(comp)/test) -TEST_COMPONENT_NAMES := $(foreach comp,$(TEST_COMPONENTS),$(comp)_test) +override TEST_COMPONENTS := $(foreach comp,$(TEST_COMPONENTS),$(wildcard $(IDF_PATH)/components/$(comp)/test)) +TEST_COMPONENT_PATHS := $(TEST_COMPONENTS) +TEST_COMPONENT_NAMES := $(foreach comp,$(TEST_COMPONENTS),$(lastword $(subst /, ,$(dir $(comp))))_test) endif # Initialise project-wide variables which can be added to by diff --git a/tools/unit-test-app/README.md b/tools/unit-test-app/README.md index cf45ce287b..eff3e12f4a 100644 --- a/tools/unit-test-app/README.md +++ b/tools/unit-test-app/README.md @@ -8,5 +8,5 @@ ESP-IDF unit tests are run using Unit Test App. The app can be built with the un * Set IDF_PATH environment variable to point to the path to the esp-idf top-level directory. * Change into `tools/unit-test-app` directory * `make menuconfig` to configure the Unit Test App. -* `make TEST_COMPONENTS=` with `TEST_COMPONENTS` set to names of the components to be included in the test app. +* `make TEST_COMPONENTS=` with `TEST_COMPONENTS` set to names of the components to be included in the test app. Or `make TESTS_ALL=1` to build the test app with all the tests for components having `test` subdirectory. * Follow the printed instructions to flash, or run `make flash`. From 50f178c1ce0b60b37506ac348c7988d64bc22a19 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 23 Nov 2016 12:55:49 +0800 Subject: [PATCH 15/25] esp32: add some implementation comments --- components/esp32/hw_random.c | 8 ++++++++ components/esp32/lib_printf.c | 12 ++++++++++++ components/esp32/rtc.h | 12 ++++++++++++ 3 files changed, 32 insertions(+) diff --git a/components/esp32/hw_random.c b/components/esp32/hw_random.c index 2c6e2cf5f8..11c7af936b 100644 --- a/components/esp32/hw_random.c +++ b/components/esp32/hw_random.c @@ -23,6 +23,14 @@ uint32_t IRAM_ATTR esp_random(void) { + /* The PRNG which implements WDEV_RANDOM register gets 2 bits + * of extra entropy from a hardware randomness source every APB clock cycle. + * To make sure entropy is not drained faster than it is added, + * this function needs to wait for at least 16 APB clock cycles after reading + * previous word. This implementation may actually wait a bit longer + * due to extra time spent in arithmetic and branch statements. + */ + static uint32_t last_ccount = 0; uint32_t ccount; do { diff --git a/components/esp32/lib_printf.c b/components/esp32/lib_printf.c index 8a537ffbf9..135faa4f9c 100644 --- a/components/esp32/lib_printf.c +++ b/components/esp32/lib_printf.c @@ -12,6 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. +/** + * @file lib_printf.c + * + * This file contains library-specific printf functions + * used by WiFi libraries in the `lib` directory. + * These function are used to catch any output which gets printed + * by libraries, and redirect it to ESP_LOG macros. + * + * Eventually WiFi libraries will use ESP_LOG functions internally + * and these definitions will be removed. + */ + #include #include #include "esp_log.h" diff --git a/components/esp32/rtc.h b/components/esp32/rtc.h index 2ac3139c21..e1cf33522d 100644 --- a/components/esp32/rtc.h +++ b/components/esp32/rtc.h @@ -12,6 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. +/** + * @file rtc.h + * @brief Declarations of APIs provided by librtc.a + * + * This file is not in the include directory of esp32 component, so it is not + * part of the public API. As the source code of librtc.a is gradually moved + * into the ESP-IDF, some of these APIs will be exposed to applications. + * + * For now, only esp_deep_sleep function declared in esp_deepsleep.h + * is part of public API. + */ + #pragma once #include #include From 9ccb104895a9d4a8f7ced68ac239e9b726d73f9b Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 23 Nov 2016 14:22:49 +0800 Subject: [PATCH 16/25] CI: fix unit test artifact path --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1d68d2f601..679e472f4b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -88,7 +88,7 @@ build_esp_idf_tests: - cd tools/unit-test-app - git checkout ${CI_BUILD_REF_NAME} || echo "Using default branch..." - make defconfig - - make + - make TESTS_ALL=1 build_examples: <<: *build_template @@ -288,7 +288,7 @@ deploy_docs: variables: # jobs MUST set CONFIG_FILE in before_script, and overwrite the variables above if necessary LOCAL_ENV_CONFIG_PATH: /home/gitlab-runner/LocalConfig/ESP32_IDF - BIN_PATH: "$CI_PROJECT_DIR/esp-idf-tests/build/" + BIN_PATH: "$CI_PROJECT_DIR/tools/unit-test-app/build/" LOG_PATH: "$CI_PROJECT_DIR/$CI_BUILD_REF" APP_NAME: "ut" TEST_CASE_FILE_PATH: "$CI_PROJECT_DIR/components/idf_test/unit_test" From ca76f532836aeae2b9e9b68e747de91d1f050180 Mon Sep 17 00:00:00 2001 From: antti Date: Wed, 23 Nov 2016 16:22:34 +0800 Subject: [PATCH 17/25] remove fp unit test Kconfig --- components/esp32/test/Kconfig | 9 --------- components/esp32/test/test_fp.c | 2 -- 2 files changed, 11 deletions(-) delete mode 100644 components/esp32/test/Kconfig diff --git a/components/esp32/test/Kconfig b/components/esp32/test/Kconfig deleted file mode 100644 index af5e5b45e7..0000000000 --- a/components/esp32/test/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -menu "TESTS" - -config FP_TEST_ENABLE - bool "Enable test fp" - default "y" - help - For FPGA single core CPU which has no floating point support, floating point test should be disabled. - -endmenu diff --git a/components/esp32/test/test_fp.c b/components/esp32/test/test_fp.c index 5c2573b227..1b88e9722c 100644 --- a/components/esp32/test/test_fp.c +++ b/components/esp32/test/test_fp.c @@ -4,7 +4,6 @@ #include "freertos/task.h" #include "unity.h" -#if CONFIG_FP_TEST_ENABLE static float addsf(float a, float b) { float result; @@ -192,4 +191,3 @@ TEST_CASE("context switch saves FP registers", "[fp]") } TEST_ASSERT(state.fail == 0); } -#endif From 13e7e692395e33871b112f9b2dd2bb6b8fa4dc73 Mon Sep 17 00:00:00 2001 From: antti Date: Wed, 23 Nov 2016 16:22:51 +0800 Subject: [PATCH 18/25] remove unexisting tests in unit test CIConfig --- .../idf_test/unit_test/CIConfigs/UT_Function_SYS_01.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/components/idf_test/unit_test/CIConfigs/UT_Function_SYS_01.yml b/components/idf_test/unit_test/CIConfigs/UT_Function_SYS_01.yml index c3561aa0c5..f4755dfec4 100644 --- a/components/idf_test/unit_test/CIConfigs/UT_Function_SYS_01.yml +++ b/components/idf_test/unit_test/CIConfigs/UT_Function_SYS_01.yml @@ -2,7 +2,6 @@ Config: {execute count: 1, execute order: in order} DUT: [UT1] Filter: - Add: - ID: [SYS_OS_0102, SYS_MISC_0103, SYS_MISC_0102, SYS_MISC_0105, SYS_MISC_0104, - SYS_MISC_0107, SYS_MISC_0106, SYS_MISC_0109, SYS_MISC_0108, SYS_MISC_0112, SYS_MISC_0113, - SYS_MISC_0110, SYS_MISC_0111, SYS_MISC_0115, SYS_LIB_0103, SYS_LIB_0102, SYS_LIB_0101, - SYS_LIB_0106, SYS_LIB_0105, SYS_LIB_0104] + ID: [SYS_OS_0102, SYS_MISC_0102, SYS_MISC_0107, SYS_MISC_0106, SYS_MISC_0109, + SYS_MISC_0108, SYS_MISC_0112, SYS_MISC_0113, SYS_MISC_0110, SYS_MISC_0111, SYS_LIB_0103, + SYS_LIB_0102, SYS_LIB_0101, SYS_LIB_0106, SYS_LIB_0105, SYS_LIB_0104] From 7571b8c2e4cc86f4746376288cbd255bc479d609 Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Wed, 23 Nov 2016 18:10:45 +0800 Subject: [PATCH 19/25] driver: PCNT minor changes --- components/driver/include/driver/pcnt.h | 44 ++++++++++++++----------- components/driver/ledc.c | 1 + components/driver/pcnt.c | 31 ++++++++--------- docs/api/pcnt.rst | 44 +++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 34 deletions(-) create mode 100644 docs/api/pcnt.rst diff --git a/components/driver/include/driver/pcnt.h b/components/driver/include/driver/pcnt.h index c49dc387ce..47bf25fe76 100644 --- a/components/driver/include/driver/pcnt.h +++ b/components/driver/include/driver/pcnt.h @@ -13,13 +13,10 @@ #include "soc/gpio_sig_map.h" #include "driver/gpio.h" - #ifdef __cplusplus extern "C" { #endif -#define PCNT_PIN_NOT_USED (-1) - typedef enum { PCNT_MODE_KEEP = 0, /*!< Control mode: won't change counter mode*/ PCNT_MODE_REVERSE = 1, /*!< Control mode: invert counter mode(increase -> decrease, decrease -> increase);*/ @@ -35,14 +32,14 @@ typedef enum { } pcnt_count_mode_t; typedef enum { - PCNT_UNIT0 = 0, /*!< PCNT unit0 */ - PCNT_UNIT1 = 1, /*!< PCNT unit1 */ - PCNT_UNIT2 = 2, /*!< PCNT unit2 */ - PCNT_UNIT3 = 3, /*!< PCNT unit3 */ - PCNT_UNIT4 = 4, /*!< PCNT unit4 */ - PCNT_UNIT5 = 5, /*!< PCNT unit5 */ - PCNT_UNIT6 = 6, /*!< PCNT unit6 */ - PCNT_UNIT7 = 7, /*!< PCNT unit7 */ + PCNT_UNIT_0 = 0, /*!< PCNT unit0 */ + PCNT_UNIT_1 = 1, /*!< PCNT unit1 */ + PCNT_UNIT_2 = 2, /*!< PCNT unit2 */ + PCNT_UNIT_3 = 3, /*!< PCNT unit3 */ + PCNT_UNIT_4 = 4, /*!< PCNT unit4 */ + PCNT_UNIT_5 = 5, /*!< PCNT unit5 */ + PCNT_UNIT_6 = 6, /*!< PCNT unit6 */ + PCNT_UNIT_7 = 7, /*!< PCNT unit7 */ PCNT_UNIT_MAX, } pcnt_unit_t; @@ -55,8 +52,8 @@ typedef enum{ typedef enum { PCNT_EVT_L_LIM = 0, /*!< PCNT watch point event: Minimum counter value */ PCNT_EVT_H_LIM = 1, /*!< PCNT watch point event: Maximum counter value*/ - PCNT_EVT_THRES0 = 2, /*!< PCNT watch point event: threshold0 value event*/ - PCNT_EVT_THRES1 = 3, /*!< PCNT watch point event: threshold1 value event*/ + PCNT_EVT_THRES_0 = 2, /*!< PCNT watch point event: threshold0 value event*/ + PCNT_EVT_THRES_1 = 3, /*!< PCNT watch point event: threshold1 value event*/ PCNT_EVT_ZERO = 4, /*!< PCNT watch point event: counter value zero event*/ PCNT_EVT_MAX } pcnt_evt_type_t; @@ -268,6 +265,8 @@ esp_err_t pcnt_filter_disable(pcnt_unit_t unit); * @param unit PCNT unit number * @param filter_val PCNT signal filter value, counter in APB_CLK cycles. * Any pulses lasting shorter than this will be ignored when the filter is enabled. + * @note + * filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023. * * @return * - ESP_OK Success @@ -301,13 +300,18 @@ esp_err_t pcnt_get_filter_value(pcnt_unit_t unit, uint16_t *filter_val); * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t pcnt_set_mode(pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode); +esp_err_t pcnt_set_mode(pcnt_unit_t unit, pcnt_channel_t channel, + pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode, + pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode); -/***************************EXAMPLE********************************** +/** + * @addtogroup pcnt-examples * + * @{ * - * ----------------EXAMPLE OF LEDC SETTING --------------------- + * EXAMPLE OF PCNT CONFIGURATION + * ============================== * @code{c} * //1. Config PCNT unit * pcnt_config_t pcnt_config = { @@ -324,15 +328,17 @@ esp_err_t pcnt_set_mode(pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mod * pcnt_unit_config(&pcnt_config); //init unit * @endcode * + * EXAMPLE OF PCNT EVENT SETTING + * ============================== * @code{c} * //2. Configure PCNT watchpoint event. - * pcnt_set_event_value(PCNT_UNIT0, PCNT_EVT_THRES1, 5); //set thres1 value - * pcnt_event_enable(PCNT_UNIT0, PCNT_EVT_THRES1); //enable thres1 event + * pcnt_set_event_value(PCNT_UNIT_0, PCNT_EVT_THRES_1, 5); //set thres1 value + * pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_THRES_1); //enable thres1 event * @endcode * * For more examples please refer to PCNT example code in IDF_PATH/examples * - *--------------------------END OF EXAMPLE -------------------------- + * @} */ #ifdef __cplusplus diff --git a/components/driver/ledc.c b/components/driver/ledc.c index 41eb82cbdd..cd57d8fcc2 100644 --- a/components/driver/ledc.c +++ b/components/driver/ledc.c @@ -191,6 +191,7 @@ esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf) LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG); LEDC_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "ledc GPIO output number error", ESP_ERR_INVALID_ARG); LEDC_CHECK(timer_select <= LEDC_TIMER_3, "ledc timer error", ESP_ERR_INVALID_ARG); + periph_module_enable(PERIPH_LEDC_MODULE); esp_err_t ret = ESP_OK; /*set channel parameters*/ /* channel parameters decide how the waveform looks like in one period*/ diff --git a/components/driver/pcnt.c b/components/driver/pcnt.c index bfcdb7da1e..b39d53a800 100644 --- a/components/driver/pcnt.c +++ b/components/driver/pcnt.c @@ -22,6 +22,7 @@ #define PCNT_PARAM_ERR_STR "PCNT PARAM ERROR" #define PCNT_COUNT_MODE_ERR_STR "PCNT COUNTER MODE ERROR" #define PCNT_CTRL_MODE_ERR_STR "PCNT CTRL MODE ERROR" +#define PCNT_EVT_TYPE_ERR_STR "PCNT value type error" #define PCNT_CHECK(a,str,ret_val) if(!(a)) { \ ESP_LOGE(PCNT_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \ return (ret_val); \ @@ -112,7 +113,7 @@ esp_err_t pcnt_set_pin(pcnt_unit_t unit, pcnt_channel_t channel, int pulse_io, i esp_err_t pcnt_get_counter_value(pcnt_unit_t pcnt_unit, int16_t* count) { PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); - PCNT_CHECK(count != NULL, "PCNT ADDRESS ERROR", ESP_ERR_INVALID_ARG); + PCNT_CHECK(count != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG); *count = (int16_t) PCNT.cnt_unit[pcnt_unit].cnt_val; return ESP_OK; } @@ -165,14 +166,14 @@ esp_err_t pcnt_intr_disable(pcnt_unit_t pcnt_unit) esp_err_t pcnt_event_enable(pcnt_unit_t unit, pcnt_evt_type_t evt_type) { PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); - PCNT_CHECK(evt_type < PCNT_EVT_MAX, "PCNT value type error", ESP_ERR_INVALID_ARG); + PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG); if(evt_type == PCNT_EVT_L_LIM) { PCNT.conf_unit[unit].conf0.thr_l_lim_en = 1; } else if(evt_type == PCNT_EVT_H_LIM) { PCNT.conf_unit[unit].conf0.thr_h_lim_en = 1; - } else if(evt_type == PCNT_EVT_THRES0) { + } else if(evt_type == PCNT_EVT_THRES_0) { PCNT.conf_unit[unit].conf0.thr_thres0_en = 1; - } else if(evt_type == PCNT_EVT_THRES1) { + } else if(evt_type == PCNT_EVT_THRES_1) { PCNT.conf_unit[unit].conf0.thr_thres1_en = 1; } else if(evt_type == PCNT_EVT_ZERO) { PCNT.conf_unit[unit].conf0.thr_zero_en = 1; @@ -183,14 +184,14 @@ esp_err_t pcnt_event_enable(pcnt_unit_t unit, pcnt_evt_type_t evt_type) esp_err_t pcnt_event_disable(pcnt_unit_t unit, pcnt_evt_type_t evt_type) { PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); - PCNT_CHECK(evt_type < PCNT_EVT_MAX, "PCNT value type error", ESP_ERR_INVALID_ARG); + PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG); if(evt_type == PCNT_EVT_L_LIM) { PCNT.conf_unit[unit].conf0.thr_l_lim_en = 0; } else if(evt_type == PCNT_EVT_H_LIM) { PCNT.conf_unit[unit].conf0.thr_h_lim_en = 0; - } else if(evt_type == PCNT_EVT_THRES0) { + } else if(evt_type == PCNT_EVT_THRES_0) { PCNT.conf_unit[unit].conf0.thr_thres0_en = 0; - } else if(evt_type == PCNT_EVT_THRES1) { + } else if(evt_type == PCNT_EVT_THRES_1) { PCNT.conf_unit[unit].conf0.thr_thres1_en = 0; } else if(evt_type == PCNT_EVT_ZERO) { PCNT.conf_unit[unit].conf0.thr_zero_en = 0; @@ -201,14 +202,14 @@ esp_err_t pcnt_event_disable(pcnt_unit_t unit, pcnt_evt_type_t evt_type) esp_err_t pcnt_set_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value) { PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); - PCNT_CHECK(evt_type < PCNT_EVT_MAX, "PCNT value type error", ESP_ERR_INVALID_ARG); + PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG); if(evt_type == PCNT_EVT_L_LIM) { PCNT.conf_unit[unit].conf2.cnt_l_lim = value; } else if(evt_type == PCNT_EVT_H_LIM) { PCNT.conf_unit[unit].conf2.cnt_h_lim = value; - } else if(evt_type == PCNT_EVT_THRES0) { + } else if(evt_type == PCNT_EVT_THRES_0) { PCNT.conf_unit[unit].conf1.cnt_thres0 = value; - } else if(evt_type == PCNT_EVT_THRES1) { + } else if(evt_type == PCNT_EVT_THRES_1) { PCNT.conf_unit[unit].conf1.cnt_thres1 = value; } return ESP_OK; @@ -217,16 +218,16 @@ esp_err_t pcnt_set_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16 esp_err_t pcnt_get_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value) { PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); - PCNT_CHECK(evt_type < PCNT_EVT_MAX, "PCNT value type error", ESP_ERR_INVALID_ARG); - PCNT_CHECK(value != NULL, "PCNT ADDRESS ERROR", ESP_ERR_INVALID_ARG); + PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(value != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG); if(evt_type == PCNT_EVT_L_LIM) { *value = (int16_t) PCNT.conf_unit[unit].conf2.cnt_l_lim; } else if(evt_type == PCNT_EVT_H_LIM) { *value = (int16_t) PCNT.conf_unit[unit].conf2.cnt_h_lim; - } else if(evt_type == PCNT_EVT_THRES0) { + } else if(evt_type == PCNT_EVT_THRES_0) { *value = (int16_t) PCNT.conf_unit[unit].conf1.cnt_thres0; - } else if(evt_type == PCNT_EVT_THRES1) { + } else if(evt_type == PCNT_EVT_THRES_1) { *value = (int16_t) PCNT.conf_unit[unit].conf1.cnt_thres1; } else { *value = 0; @@ -245,7 +246,7 @@ esp_err_t pcnt_set_filter_value(pcnt_unit_t unit, uint16_t filter_val) esp_err_t pcnt_get_filter_value(pcnt_unit_t unit, uint16_t *filter_val) { PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); - PCNT_CHECK(filter_val != NULL, "PCNT ADDRESS ERROR", ESP_ERR_INVALID_ARG); + PCNT_CHECK(filter_val != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG); *filter_val = PCNT.conf_unit[unit].conf0.filter_thres; return ESP_OK; diff --git a/docs/api/pcnt.rst b/docs/api/pcnt.rst new file mode 100644 index 0000000000..177027f62e --- /dev/null +++ b/docs/api/pcnt.rst @@ -0,0 +1,44 @@ +Macros +^^^^^^ + + +Type Definitions +^^^^^^^^^^^^^^^^ + + +Enumerations +^^^^^^^^^^^^ + +.. doxygenenum:: pcnt_ctrl_mode_t +.. doxygenenum:: pcnt_count_mode_t +.. doxygenenum:: pcnt_unit_t +.. doxygenenum:: pcnt_channel_t +.. doxygenenum:: pcnt_evt_type_t + +Structures +^^^^^^^^^^ + +.. doxygenstruct:: pcnt_config_t + +Functions +^^^^^^^^^ + +.. doxygenfunction:: pcnt_unit_config +.. doxygenfunction:: pcnt_get_counter_value +.. doxygenfunction:: pcnt_counter_pause +.. doxygenfunction:: pcnt_counter_resume +.. doxygenfunction:: pcnt_counter_clear +.. doxygenfunction:: pcnt_intr_enable +.. doxygenfunction:: pcnt_intr_disable +.. doxygenfunction:: pcnt_event_enable +.. doxygenfunction:: pcnt_event_disable +.. doxygenfunction:: pcnt_set_event_value +.. doxygenfunction:: pcnt_get_event_value +.. doxygenfunction:: pcnt_isr_register +.. doxygenfunction:: pcnt_set_pin +.. doxygenfunction:: pcnt_filter_enable +.. doxygenfunction:: pcnt_filter_disable +.. doxygenfunction:: pcnt_set_filter_value +.. doxygenfunction:: pcnt_get_filter_value +.. doxygenfunction:: pcnt_set_mode + From a97e076decd3c7aaec80552fde64f7dd6dd612e1 Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Wed, 23 Nov 2016 19:07:30 +0800 Subject: [PATCH 20/25] add pcnt.rst --- .../driver/include/driver/periph_ctrl.h | 1 + components/driver/periph_ctrl.c | 8 +++++++ docs/api/pcnt.rst | 22 +++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/components/driver/include/driver/periph_ctrl.h b/components/driver/include/driver/periph_ctrl.h index d7a98284b7..8c404e5b13 100644 --- a/components/driver/include/driver/periph_ctrl.h +++ b/components/driver/include/driver/periph_ctrl.h @@ -40,6 +40,7 @@ typedef enum { PERIPH_UHCI0_MODULE, PERIPH_UHCI1_MODULE, PERIPH_RMT_MODULE, + PERIPH_PCNT_MODULE, } periph_module_t; /** diff --git a/components/driver/periph_ctrl.c b/components/driver/periph_ctrl.c index a687a2aee2..7fc4091aa5 100644 --- a/components/driver/periph_ctrl.c +++ b/components/driver/periph_ctrl.c @@ -107,6 +107,10 @@ void periph_module_disable(periph_module_t periph) { portENTER_CRITICAL(&periph_spinlock); switch(periph) { + case PERIPH_RMT_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_RMT_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_RMT_RST); + break; case PERIPH_LEDC_MODULE: CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_LEDC_CLK_EN); SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_LEDC_RST); @@ -171,6 +175,10 @@ void periph_module_disable(periph_module_t periph) CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UHCI1_CLK_EN); SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UHCI1_RST); break; + case PERIPH_PCNT_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PCNT_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PCNT_RST); + break; default: break; } diff --git a/docs/api/pcnt.rst b/docs/api/pcnt.rst index 177027f62e..a3f654909d 100644 --- a/docs/api/pcnt.rst +++ b/docs/api/pcnt.rst @@ -1,3 +1,25 @@ +PCNT +======== + +Overview +-------- + +The PCNT (Pulse Counter) module is designed to count the number of rising and/or falling edges of an input signal. Each pulse counter unit has a 16-bit signed counter register and two channels that can be configured to either increment or decrement the counter. Each channel has a signal input that accepts signal edges to be detected, as well as a control input that can be used to enable or disable the signal input. The inputs have optional filters that can be used to discard unwanted glitches in the signal. + +Application Example +------------------- + +PCNT counter with control signal and event interrupt example: `examples/12_pcnt `_. + +API Reference +------------- + +Header Files +^^^^^^^^^^^^ + + * `driver/pcnt.h `_ + + Macros ^^^^^^ From 452bee718182b8e0a53ce82fd4783673b38a78f3 Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Wed, 23 Nov 2016 21:25:06 +0800 Subject: [PATCH 21/25] update docs/index.rst --- docs/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.rst b/docs/index.rst index 829ce0334e..6858bdfbdc 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -102,6 +102,7 @@ Contents: api/uart api/ledc api/rmt + Pulse Counter SPI Flash and Partition APIs Logging Non-Volatile Storage From 79646f41b596f56cc26aa1c3df9697c71867df4a Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 24 Nov 2016 08:08:09 +1100 Subject: [PATCH 22/25] Fixes for stdlib.h inclusion Refs: http://esp32.com/viewtopic.php?f=13&t=550 http://esp32.com/viewtopic.php?f=13&t=551 rmt.c should include stdlib.h for malloc, esp_bignum,c & https_request_main.c for abort(). FreeRTOSConfig.h is only including stdlib if CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION is set. However, it is included for abort() so needs to be included whenever CONFIG_FREERTOS_ASSERT_FAIL_ABORT is set. This change includes unconditionally in FreeRTOSConfig.h. This is to avoid this kind of bug where compiler errors are dependent on config. I suggest we don't change this to be more selective until we have 'make randomconfig' style tests in CI. --- components/driver/rmt.c | 1 + components/freertos/include/freertos/FreeRTOSConfig.h | 3 +-- components/mbedtls/port/esp_bignum.c | 1 + examples/04_https_request/main/https_request_main.c | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/components/driver/rmt.c b/components/driver/rmt.c index 21bc8696b0..9fc36d49c2 100644 --- a/components/driver/rmt.c +++ b/components/driver/rmt.c @@ -13,6 +13,7 @@ // limitations under the License. #include #include +#include #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "freertos/xtensa_api.h" diff --git a/components/freertos/include/freertos/FreeRTOSConfig.h b/components/freertos/include/freertos/FreeRTOSConfig.h index 13ce73e0a8..4f1012657a 100644 --- a/components/freertos/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/include/freertos/FreeRTOSConfig.h @@ -108,6 +108,7 @@ /* configASSERT behaviour */ #ifndef __ASSEMBLER__ +#include /* for abort() */ #include "rom/ets_sys.h" #if defined(CONFIG_FREERTOS_ASSERT_DISABLE) @@ -126,8 +127,6 @@ #endif #if CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION -#include -#include "rom/ets_sys.h" #define UNTESTED_FUNCTION() { ets_printf("Untested FreeRTOS function %s\r\n", __FUNCTION__); configASSERT(false); } while(0) #else #define UNTESTED_FUNCTION() diff --git a/components/mbedtls/port/esp_bignum.c b/components/mbedtls/port/esp_bignum.c index 7570820e3b..ec2e420398 100644 --- a/components/mbedtls/port/esp_bignum.c +++ b/components/mbedtls/port/esp_bignum.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "mbedtls/bignum.h" #include "rom/bigint.h" #include "soc/hwcrypto_reg.h" diff --git a/examples/04_https_request/main/https_request_main.c b/examples/04_https_request/main/https_request_main.c index 2ad56681d0..1f7112bc86 100644 --- a/examples/04_https_request/main/https_request_main.c +++ b/examples/04_https_request/main/https_request_main.c @@ -22,6 +22,7 @@ * limitations under the License. */ #include +#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" From f97f198c9de4e44e80bacb429c54e7178e421373 Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Thu, 24 Nov 2016 12:01:21 +0800 Subject: [PATCH 23/25] driver: improve pulse counter code 1. Modify some comments in pcnt.h 2. Modify api/pcnt.rst 3. Improve example code. 4. Add status definitions in pcnt_reg.h --- components/driver/include/driver/pcnt.h | 32 ++++++++---- components/esp32/include/soc/pcnt_reg.h | 30 +++++++++++ docs/api/pcnt.rst | 4 +- examples/12_pcnt/main/pcnt_test.c | 67 +++++++++++++++++++++---- 4 files changed, 110 insertions(+), 23 deletions(-) diff --git a/components/driver/include/driver/pcnt.h b/components/driver/include/driver/pcnt.h index 47bf25fe76..deff781839 100644 --- a/components/driver/include/driver/pcnt.h +++ b/components/driver/include/driver/pcnt.h @@ -17,6 +17,8 @@ extern "C" { #endif +#define PCNT_PIN_NOT_USED (-1) /*!< Pin are not used */ + typedef enum { PCNT_MODE_KEEP = 0, /*!< Control mode: won't change counter mode*/ PCNT_MODE_REVERSE = 1, /*!< Control mode: invert counter mode(increase -> decrease, decrease -> increase);*/ @@ -59,7 +61,7 @@ typedef enum { } pcnt_evt_type_t; /** - * @brief PCNT configure struct + * @brief Pulse Counter configure struct */ typedef struct { int pulse_gpio_num; /*!< Pulse input gpio_num, if you want to use gpio16, pulse_gpio_num = 16, a negative value will be ignored */ @@ -75,9 +77,9 @@ typedef struct { } pcnt_config_t; /** - * @brief Configure PCNT unit + * @brief Configure Pulse Counter unit * - * @param pcnt_config Pointer of PCNT unit configure parameter + * @param pcnt_config Pointer of Pulse Counter unit configure parameter * * @return * - ESP_OK Success @@ -88,7 +90,7 @@ esp_err_t pcnt_unit_config(pcnt_config_t *pcnt_config); /** * @brief Get pulse counter value * - * @param pcnt_unit PCNT unit number + * @param pcnt_unit Pulse Counter unit number * @param count Pointer to accept counter value * * @return @@ -133,7 +135,8 @@ esp_err_t pcnt_counter_clear(pcnt_unit_t pcnt_unit); /** * @brief Enable PCNT interrupt for PCNT unit * @note - * Five watch point events share the same interrupt source for each unit. + * Each Pulse counter unit has five watch point events that share the same interrupt. + * Configure events with pcnt_event_enable() and pcnt_event_disable() * * @param pcnt_unit PCNT unit number * @@ -158,8 +161,8 @@ esp_err_t pcnt_intr_disable(pcnt_unit_t pcnt_unit); * @brief Enable PCNT event of PCNT unit * * @param unit PCNT unit number - * @param evt_type PCNT watch point event type, five events share a same interrupt source - * + * @param evt_type Watch point event type. + * All enabled events share the same interrupt (one interrupt per pulse counter unit). * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error @@ -170,8 +173,8 @@ esp_err_t pcnt_event_enable(pcnt_unit_t unit, pcnt_evt_type_t evt_type); * @brief Disable PCNT event of PCNT unit * * @param unit PCNT unit number - * @param evt_type PCNT watch point event type, five events share a same interrupt source - * + * @param evt_type Watch point event type. + * All enabled events share the same interrupt (one interrupt per pulse counter unit). * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error @@ -182,7 +185,9 @@ esp_err_t pcnt_event_disable(pcnt_unit_t unit, pcnt_evt_type_t evt_type); * @brief Set PCNT event value of PCNT unit * * @param unit PCNT unit number - * @param evt_type PCNT watch point event type, five events share a same interrupt source + * @param evt_type Watch point event type. + * All enabled events share the same interrupt (one interrupt per pulse counter unit). + * * @param value Counter value for PCNT event * * @return @@ -195,7 +200,8 @@ esp_err_t pcnt_set_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16 * @brief Get PCNT event value of PCNT unit * * @param unit PCNT unit number - * @param evt_type PCNT watch point event type, five events share a same interrupt source + * @param evt_type Watch point event type. + * All enabled events share the same interrupt (one interrupt per pulse counter unit). * @param value Pointer to accept counter value for PCNT event * * @return @@ -229,7 +235,11 @@ esp_err_t pcnt_isr_register(uint32_t pcnt_intr_num, void (*fn)(void*), void * ar * @param unit PCNT unit number * @param channel PCNT channel number * @param pulse_io Pulse signal input GPIO + * @note + * Set to PCNT_PIN_NOT_USED if unused. * @param ctrl_io Control signal input GPIO + * @note + * Set to PCNT_PIN_NOT_USED if unused. * * @return * - ESP_OK Success diff --git a/components/esp32/include/soc/pcnt_reg.h b/components/esp32/include/soc/pcnt_reg.h index 7a3a78bf2d..9809faf736 100644 --- a/components/esp32/include/soc/pcnt_reg.h +++ b/components/esp32/include/soc/pcnt_reg.h @@ -1319,6 +1319,36 @@ #define PCNT_CORE_STATUS_U0_M ((PCNT_CORE_STATUS_U0_V)<<(PCNT_CORE_STATUS_U0_S)) #define PCNT_CORE_STATUS_U0_V 0xFFFFFFFF #define PCNT_CORE_STATUS_U0_S 0 +/*0: positive value to zero; 1: negative value to zero; 2: counter value negative ; 3: counter value positive*/ +#define PCNT_STATUS_CNT_MODE 0x3 +#define PCNT_STATUS_CNT_MODE_M ((PCNT_STATUS_CNT_MODE_V)<<(PCNT_STATUS_CNT_MODE_S)) +#define PCNT_STATUS_CNT_MODE_V 0x3 +#define PCNT_STATUS_CNT_MODE_S 0 +/* counter value equals to thresh1*/ +#define PCNT_STATUS_THRES1 BIT(2) +#define PCNT_STATUS_THRES1_M BIT(2) +#define PCNT_STATUS_THRES1_V 0x1 +#define PCNT_STATUS_THRES1_S 2 +/* counter value equals to thresh0*/ +#define PCNT_STATUS_THRES0 BIT(3) +#define PCNT_STATUS_THRES0_M BIT(3) +#define PCNT_STATUS_THRES0_V 0x1 +#define PCNT_STATUS_THRES0_S 3 +/* counter value reaches h_lim*/ +#define PCNT_STATUS_L_LIM BIT(4) +#define PCNT_STATUS_L_LIM_M BIT(4) +#define PCNT_STATUS_L_LIM_V 0x1 +#define PCNT_STATUS_L_LIM_S 4 +/* counter value reaches l_lim*/ +#define PCNT_STATUS_H_LIM BIT(5) +#define PCNT_STATUS_H_LIM_M BIT(5) +#define PCNT_STATUS_H_LIM_V 0x1 +#define PCNT_STATUS_H_LIM_S 5 +/* counter value equals to zero*/ +#define PCNT_STATUS_ZERO BIT(6) +#define PCNT_STATUS_ZERO_M BIT(6) +#define PCNT_STATUS_ZERO_V 0x1 +#define PCNT_STATUS_ZERO_S 6 #define PCNT_U1_STATUS_REG (DR_REG_PCNT_BASE + 0x0094) /* PCNT_CORE_STATUS_U1 : RO ;bitpos:[31:0] ;default: 32'h0 ; */ diff --git a/docs/api/pcnt.rst b/docs/api/pcnt.rst index a3f654909d..848fa55267 100644 --- a/docs/api/pcnt.rst +++ b/docs/api/pcnt.rst @@ -1,4 +1,4 @@ -PCNT +Pulse Counter ======== Overview @@ -9,7 +9,7 @@ The PCNT (Pulse Counter) module is designed to count the number of rising and/or Application Example ------------------- -PCNT counter with control signal and event interrupt example: `examples/12_pcnt `_. +Pulse counter with control signal and event interrupt example: `examples/12_pcnt `_. API Reference ------------- diff --git a/examples/12_pcnt/main/pcnt_test.c b/examples/12_pcnt/main/pcnt_test.c index 2980dde4bc..1da4cca56e 100644 --- a/examples/12_pcnt/main/pcnt_test.c +++ b/examples/12_pcnt/main/pcnt_test.c @@ -11,7 +11,9 @@ */ #include #include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" #include "freertos/task.h" +#include "freertos/queue.h" #include "driver/periph_ctrl.h" #include "driver/ledc.h" #include "driver/gpio.h" @@ -45,28 +47,49 @@ static const char* TAG = "PCNT_TEST"; #define PCNT_INPUT_CTRL_IO (5) #define LEDC_OUPUT_IO (18) +xQueueHandle pcnt_evt_queue; /*A queue to handle pulse counter event*/ + + +typedef struct { + int unit; /*pulse counter unit*/ + uint32_t status; /*pulse counter internal status*/ +} pcnt_evt_t; + void IRAM_ATTR pcnt_intr_handler(void* arg) { uint32_t intr_status = PCNT.int_st.val; int i; + pcnt_evt_t evt; + portBASE_TYPE HPTaskAwoken = pdFALSE; + for(i = 0; i < PCNT_UNIT_MAX; i++) { if(intr_status & (BIT(i))) { - ESP_EARLY_LOGI(TAG, "EVENT[%d] intr\n", i); - PCNT.int_clr.val |= BIT(i); + evt.unit = i; + evt.status = PCNT.status_unit[i].val; + PCNT.int_clr.val = BIT(i); + /*H LIM EVT*/ if(PCNT.status_unit[i].h_lim_lat) { - ESP_EARLY_LOGI(TAG, "H LIM EVT\n"); + //do something } + /*L LIM EVT*/ if(PCNT.status_unit[i].l_lim_lat) { - ESP_EARLY_LOGI(TAG, "L LIM EVT\n"); + //do something } + /*THRES0 EVT*/ if(PCNT.status_unit[i].thres0_lat) { - ESP_EARLY_LOGI(TAG, "THRES0 EVT\n"); + //do something } + /*THRES1 EVT*/ if(PCNT.status_unit[i].thres1_lat) { - ESP_EARLY_LOGI(TAG, "THRES1 EVT\n"); + //do something } + /*ZERO EVT*/ if(PCNT.status_unit[i].zero_lat) { - ESP_EARLY_LOGI(TAG, "ZERO EVT\n"); + //do something + } + xQueueSendFromISR(pcnt_evt_queue, &evt, &HPTaskAwoken); + if(HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR(); } } } @@ -165,15 +188,39 @@ void app_main() { /*Init LEDC for pulse input signal */ ledc_init(); + /*Init PCNT event queue */ + pcnt_evt_queue = xQueueCreate(10, sizeof(pcnt_evt_t)); /*Init PCNT functions*/ pcnt_init(); int16_t count = 0; + pcnt_evt_t evt; + portBASE_TYPE res; while(1) { - pcnt_get_counter_value(PCNT_TEST_UNIT, &count); - printf("Current counter value :%d\n", count); - vTaskDelay(1000 / portTICK_RATE_MS); + res = xQueueReceive(pcnt_evt_queue, &evt, 1000 / portTICK_RATE_MS); + if(res == pdTRUE) { + pcnt_get_counter_value(PCNT_TEST_UNIT, &count); + printf("Event PCNT unit[%d]; cnt: %d\n", evt.unit, count); + if(evt.status & PCNT_STATUS_THRES1_M) { + printf("THRES1 EVT\n"); + } + if(evt.status & PCNT_STATUS_THRES0_M) { + printf("THRES0 EVT\n"); + } + if(evt.status & PCNT_STATUS_L_LIM_M) { + printf("L_LIM EVT\n"); + } + if(evt.status & PCNT_STATUS_H_LIM_M) { + printf("H_LIM EVT\n"); + } + if(evt.status & PCNT_STATUS_ZERO_M) { + printf("ZERO EVT\n"); + } + } else { + pcnt_get_counter_value(PCNT_TEST_UNIT, &count); + printf("Current counter value :%d\n", count); + } } } From 79482bbee7e74fdb754ccccf33370a4f13a4a727 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 24 Nov 2016 13:56:18 +0800 Subject: [PATCH 24/25] uart: use same argument names in get/set functions https://github.com/espressif/esp-idf/issues/105 --- components/driver/include/driver/uart.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/components/driver/include/driver/uart.h b/components/driver/include/driver/uart.h index 905c288260..1ddfcad9fa 100644 --- a/components/driver/include/driver/uart.h +++ b/components/driver/include/driver/uart.h @@ -167,25 +167,25 @@ esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bi * @brief Set UART stop bits. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param bit_num UART stop bits + * @param stop_bits UART stop bits * * @return * - ESP_OK Success * - ESP_FAIL Fail */ -esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t bit_num); +esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bits); /** * @brief Set UART stop bits. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param stop_bit Pointer to accept value of UART stop bits. + * @param stop_bits Pointer to accept value of UART stop bits. * * @return * - ESP_FAIL Parameter error * - ESP_OK Success, result will be put in (*stop_bit) */ -esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bit); +esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bits); /** * @brief Set UART parity. @@ -216,13 +216,13 @@ esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode); * @brief Set UART baud rate. * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param baud_rate UART baud-rate. + * @param baudrate UART baud rate. * * @return * - ESP_FAIL Parameter error * - ESP_OK Success */ -esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate); +esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baudrate); /** * @brief Get UART bit-rate. @@ -241,7 +241,7 @@ esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate); * @brief Set UART line inverse mode * * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param inverse_mask Choose the wires that need to be inversed. + * @param inverse_mask Choose the wires that need to be inverted. * Inverse_mask should be chosen from UART_INVERSE_RXD/UART_INVERSE_TXD/UART_INVERSE_RTS/UART_INVERSE_CTS, combine with OR operation. * * @return From 422e95db9c2d73867730256093ab647dcec6e911 Mon Sep 17 00:00:00 2001 From: Xia Xiaotian Date: Thu, 24 Nov 2016 17:30:33 +0800 Subject: [PATCH 25/25] system_apis: update wifi lib and librtc.a 1. some refractor to debug info in wifi lib(da6280b3) 2. fix bug of hung at phy_int in librtc.a(1bb9ce1d) --- components/esp32/lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp32/lib b/components/esp32/lib index 5182dd9dab..aa74ce2761 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 5182dd9dab9ec37e69711de33bb0c200502c4c03 +Subproject commit aa74ce27618c931fef8bdbdb683f80f4b364ba53