mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'master' into driver_merge_tmp/merge_timer
# Conflicts: # docs/index.rst
This commit is contained in:
commit
a5ad8090cf
5
.gitignore
vendored
5
.gitignore
vendored
@ -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
|
||||
|
@ -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
|
||||
@ -78,18 +82,17 @@ 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
|
||||
- make TESTS_ALL=1
|
||||
|
||||
build_examples:
|
||||
<<: *build_template
|
||||
@ -131,7 +134,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:
|
||||
@ -289,7 +292,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"
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
359
components/driver/include/driver/pcnt.h
Normal file
359
components/driver/include/driver/pcnt.h
Normal file
@ -0,0 +1,359 @@
|
||||
#ifndef __PCNT_H__
|
||||
#define __PCNT_H__
|
||||
|
||||
#include <esp_types.h>
|
||||
#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) /*!< 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);*/
|
||||
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_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;
|
||||
|
||||
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_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;
|
||||
|
||||
/**
|
||||
* @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 */
|
||||
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 Pulse Counter unit
|
||||
*
|
||||
* @param pcnt_config Pointer of Pulse Counter 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 Pulse Counter 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
|
||||
* 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
|
||||
*
|
||||
* @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 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
|
||||
*/
|
||||
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 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
|
||||
*/
|
||||
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 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
|
||||
* - 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 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
|
||||
* - 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
|
||||
* @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
|
||||
* - 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.
|
||||
* @note
|
||||
* filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023.
|
||||
*
|
||||
* @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);
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup pcnt-examples
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* EXAMPLE OF PCNT CONFIGURATION
|
||||
* ==============================
|
||||
* @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
|
||||
*
|
||||
* EXAMPLE OF PCNT EVENT SETTING
|
||||
* ==============================
|
||||
* @code{c}
|
||||
* //2. Configure PCNT watchpoint 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
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
@ -40,6 +40,7 @@ typedef enum {
|
||||
PERIPH_UHCI0_MODULE,
|
||||
PERIPH_UHCI1_MODULE,
|
||||
PERIPH_RMT_MODULE,
|
||||
PERIPH_PCNT_MODULE,
|
||||
} periph_module_t;
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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*/
|
||||
|
278
components/driver/pcnt.c
Normal file
278
components/driver/pcnt.c
Normal file
@ -0,0 +1,278 @@
|
||||
// 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_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); \
|
||||
}
|
||||
|
||||
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_ERR_STR, 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_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_THRES_0) {
|
||||
PCNT.conf_unit[unit].conf0.thr_thres0_en = 1;
|
||||
} 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;
|
||||
}
|
||||
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_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_THRES_0) {
|
||||
PCNT.conf_unit[unit].conf0.thr_thres0_en = 0;
|
||||
} 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;
|
||||
}
|
||||
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_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_THRES_0) {
|
||||
PCNT.conf_unit[unit].conf1.cnt_thres0 = value;
|
||||
} else if(evt_type == PCNT_EVT_THRES_1) {
|
||||
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_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_THRES_0) {
|
||||
*value = (int16_t) PCNT.conf_unit[unit].conf1.cnt_thres0;
|
||||
} else if(evt_type == PCNT_EVT_THRES_1) {
|
||||
*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_ERR_STR, 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;
|
||||
}
|
||||
|
@ -93,6 +93,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;
|
||||
}
|
||||
@ -103,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);
|
||||
@ -167,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;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
#include <esp_types.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
@ -154,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
|
||||
@ -174,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);
|
||||
|
44
components/esp32/cpu_util.c
Normal file
44
components/esp32/cpu_util.c
Normal file
@ -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<<RTC_CNTL_SW_STALL_APPCPU_C1_S);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C0_M);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_APPCPU_C0_S);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_PROCPU_C1_M);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<<RTC_CNTL_SW_STALL_PROCPU_C1_S);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_PROCPU_C0_S);
|
||||
}
|
||||
}
|
||||
|
||||
void IRAM_ATTR esp_cpu_unstall(int cpu_id)
|
||||
{
|
||||
if (cpu_id == 1) {
|
||||
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);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_PROCPU_C1_M);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M);
|
||||
}
|
||||
}
|
@ -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")));
|
||||
|
41
components/esp32/hw_random.c
Normal file
41
components/esp32/hw_random.c
Normal file
@ -0,0 +1,41 @@
|
||||
// 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 <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#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)
|
||||
{
|
||||
/* 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 {
|
||||
ccount = XTHAL_GET_CCOUNT();
|
||||
} while (ccount - last_ccount < XT_CLOCK_FREQ / APB_CLK_FREQ * 16);
|
||||
last_ccount = ccount;
|
||||
return REG_READ(WDEV_RND_REG);
|
||||
}
|
@ -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
|
||||
|
@ -16,7 +16,7 @@
|
||||
#define __ESP_SYSTEM_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_deepsleep.h"
|
||||
|
||||
@ -24,166 +24,107 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup System_APIs System APIs
|
||||
* @brief System APIs
|
||||
*/
|
||||
|
||||
/** @addtogroup System_APIs
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @attention application don't need to call this function anymore. It do nothing and will
|
||||
* be removed in future version.
|
||||
*/
|
||||
void system_init(void) __attribute__ ((deprecated));
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get information of the SDK version.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return Information of the SDK version.
|
||||
*/
|
||||
const char *system_get_sdk_version(void);
|
||||
|
||||
/**
|
||||
* @brief Reset to default settings.
|
||||
*
|
||||
* Reset to default settings of the following APIs : wifi_station_set_auto_connect,
|
||||
* wifi_set_phy_mode, wifi_softap_set_config related, wifi_station_set_config
|
||||
* related, and wifi_set_opmode.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return null
|
||||
* Function has been deprecated, please use esp_wifi_restore instead.
|
||||
* This name will be removed in a future release.
|
||||
*/
|
||||
void system_restore(void);
|
||||
void system_restore(void) __attribute__ ((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Restart PRO and APP CPUs.
|
||||
*
|
||||
* This function can be called both from PRO and APP CPUs.
|
||||
* After successful restart, CPU reset reason will be SW_CPU_RESET.
|
||||
* Peripherals (except for WiFi, BT, UART0, SPI1, and legacy timers) are not reset.
|
||||
* This function does not return.
|
||||
*/
|
||||
void esp_restart(void) __attribute__ ((noreturn));
|
||||
|
||||
/**
|
||||
* @brief Restart system.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return null
|
||||
* Function has been renamed to esp_restart.
|
||||
* This name will be removed in a future release.
|
||||
*/
|
||||
void system_restart(void);
|
||||
void system_restart(void) __attribute__ ((deprecated, noreturn));
|
||||
|
||||
/**
|
||||
* @brief Get system time, unit: microsecond.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return System time, unit: microsecond.
|
||||
* This function is deprecated. Use 'gettimeofday' function for 64-bit precision.
|
||||
* This definition will be removed in a future release.
|
||||
*/
|
||||
uint32_t system_get_time(void);
|
||||
uint32_t system_get_time(void) __attribute__ ((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Get the size of available heap.
|
||||
*
|
||||
* @param null
|
||||
* Note that the returned value may be larger than the maximum contiguous block
|
||||
* which can be allocated.
|
||||
*
|
||||
* @return Available heap size.
|
||||
* @return Available heap size, in bytes.
|
||||
*/
|
||||
uint32_t system_get_free_heap_size(void);
|
||||
uint32_t esp_get_free_heap_size(void);
|
||||
|
||||
/**
|
||||
* @brief Get RTC time, unit: RTC clock cycle.
|
||||
* @brief Get the size of available heap.
|
||||
*
|
||||
* @param null
|
||||
* Function has been renamed to esp_get_free_heap_size.
|
||||
* This name will be removed in a future release.
|
||||
*
|
||||
* @return RTC time.
|
||||
* @return Available heap size, in bytes.
|
||||
*/
|
||||
uint64_t system_get_rtc_time(void);
|
||||
uint32_t system_get_free_heap_size(void) __attribute__ ((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Read user data from the RTC memory.
|
||||
*
|
||||
* The user data segment (1024 bytes, as shown below) is used to store 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 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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @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));
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
* 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
|
||||
}
|
||||
|
@ -22,52 +22,4 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#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__ */
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "esp_types.h"
|
||||
#include "esp_attr.h"
|
||||
#include "ets_sys.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -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
|
||||
|
@ -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 ; */
|
||||
|
@ -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.*/
|
||||
|
@ -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
|
||||
|
18
components/esp32/include/soc/wdev_reg.h
Normal file
18
components/esp32/include/soc/wdev_reg.h
Normal file
@ -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
|
@ -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.
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit e2e5781dc27e638c5e63f85bc23590dd21af1619
|
||||
Subproject commit aa74ce27618c931fef8bdbdb683f80f4b364ba53
|
124
components/esp32/lib_printf.c
Normal file
124
components/esp32/lib_printf.c
Normal file
@ -0,0 +1,124 @@
|
||||
// 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.
|
||||
|
||||
/**
|
||||
* @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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#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;
|
||||
}
|
@ -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<<RTC_CNTL_SW_STALL_APPCPU_C1_S);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C0_M);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_APPCPU_C0_S);
|
||||
} else {
|
||||
//Kill pro cpu
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_PROCPU_C1_M);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<<RTC_CNTL_SW_STALL_PROCPU_C1_S);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_PROCPU_C0_S);
|
||||
}
|
||||
//messing up the serial output, so we stall it here.
|
||||
static void haltOtherCore()
|
||||
{
|
||||
esp_cpu_stall( xPortGetCoreID() == 0 ? 1 : 0 );
|
||||
}
|
||||
|
||||
//Returns true when a debugger is attached using JTAG.
|
||||
|
@ -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;
|
||||
|
142
components/esp32/rtc.h
Normal file
142
components/esp32/rtc.h
Normal file
@ -0,0 +1,142 @@
|
||||
// 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.
|
||||
|
||||
/**
|
||||
* @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 <stdint.h>
|
||||
#include <stddef.h>
|
||||
#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
|
||||
|
158
components/esp32/system_api.c
Normal file
158
components/esp32/system_api.c
Normal file
@ -0,0 +1,158 @@
|
||||
// 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_system.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_wifi_internal.h"
|
||||
#include "esp_log.h"
|
||||
#include "rom/efuse.h"
|
||||
#include "rom/cache.h"
|
||||
#include "rom/uart.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
|
||||
static const char* TAG = "system_api";
|
||||
|
||||
void system_init()
|
||||
{
|
||||
}
|
||||
|
||||
esp_err_t esp_efuse_read_mac(uint8_t* mac)
|
||||
{
|
||||
uint8_t efuse_crc;
|
||||
uint8_t calc_crc;
|
||||
uint32_t mac_low = REG_READ(EFUSE_BLK0_RDATA1_REG);
|
||||
uint32_t mac_high = REG_READ(EFUSE_BLK0_RDATA2_REG);
|
||||
|
||||
mac[0] = mac_high >> 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;
|
||||
}
|
||||
|
||||
esp_err_t system_efuse_read_mac(uint8_t mac[6]) __attribute__((alias("esp_efuse_read_mac")));
|
||||
|
||||
|
||||
void IRAM_ATTR esp_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_restart(void) __attribute__((alias("esp_restart")));
|
||||
|
||||
void system_restore(void)
|
||||
{
|
||||
esp_wifi_restore();
|
||||
}
|
||||
|
||||
uint32_t esp_get_free_heap_size(void)
|
||||
{
|
||||
return xPortGetFreeHeapSize();
|
||||
}
|
||||
|
||||
uint32_t system_get_free_heap_size(void) __attribute__((alias("esp_get_free_heap_size")));
|
||||
|
||||
const char* system_get_sdk_version(void)
|
||||
{
|
||||
return "master";
|
||||
}
|
||||
|
||||
|
17
components/esp32/test/component.mk
Normal file
17
components/esp32/test/component.mk
Normal file
@ -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
|
BIN
components/esp32/test/logo.jpg
Normal file
BIN
components/esp32/test/logo.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
293
components/esp32/test/test_ahb_arb.c
Normal file
293
components/esp32/test/test_ahb_arb.c
Normal file
@ -0,0 +1,293 @@
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#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<<GPIO_GPIO_FUNC0_OUT_SEL_S));
|
||||
|
||||
//GPIO_SET_GPIO_FUNC11_OUT_INV_SEL(1); //old
|
||||
WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG, READ_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG) | GPIO_FUNC11_OUT_INV_SEL);
|
||||
|
||||
//Reset I2S subsystem
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
|
||||
|
||||
WRITE_PERI_REG(I2S_CONF_REG(0), 0);//I2S_SIG_LOOPBACK);
|
||||
WRITE_PERI_REG(I2S_CONF2_REG(0), 0);
|
||||
|
||||
WRITE_PERI_REG(I2S_SAMPLE_RATE_CONF_REG(0),
|
||||
(16 << I2S_RX_BITS_MOD_S) |
|
||||
(16 << I2S_TX_BITS_MOD_S) |
|
||||
(1 << I2S_RX_BCK_DIV_NUM_S) |
|
||||
(1 << I2S_TX_BCK_DIV_NUM_S));
|
||||
WRITE_PERI_REG(I2S_CLKM_CONF_REG(0),
|
||||
I2S_CLKA_ENA | I2S_CLK_EN |
|
||||
(1 << I2S_CLKM_DIV_A_S) |
|
||||
(1 << I2S_CLKM_DIV_B_S) |
|
||||
(1 << I2S_CLKM_DIV_NUM_S));
|
||||
WRITE_PERI_REG(I2S_FIFO_CONF_REG(0),
|
||||
(32 << I2S_TX_DATA_NUM_S) | //Low watermark for IRQ
|
||||
(32 << I2S_RX_DATA_NUM_S));
|
||||
|
||||
WRITE_PERI_REG(I2S_CONF1_REG(0), I2S_RX_PCM_BYPASS | I2S_TX_PCM_BYPASS);
|
||||
|
||||
WRITE_PERI_REG(I2S_CONF_CHAN_REG(0), (2 << I2S_TX_CHAN_MOD_S) | (2 << I2S_RX_CHAN_MOD_S));
|
||||
|
||||
//Invert WS to active-low
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RIGHT_FIRST | I2S_RX_RIGHT_FIRST);
|
||||
WRITE_PERI_REG(I2S_TIMING_REG(0), 0);
|
||||
}
|
||||
|
||||
|
||||
static volatile lldesc_t dmaDesc[2];
|
||||
|
||||
static void finishDma()
|
||||
{
|
||||
//No need to finish if no DMA transfer going on
|
||||
if (!(READ_PERI_REG(I2S_FIFO_CONF_REG(0))&I2S_DSCR_EN)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Wait till fifo done
|
||||
while (!(READ_PERI_REG(I2S_INT_RAW_REG(0))&I2S_TX_REMPTY_INT_RAW)) ;
|
||||
//Wait for last bytes to leave i2s xmit thing
|
||||
//ToDo: poll bit in next hw
|
||||
// for (i=0; i<(1<<8); i++);
|
||||
while (!(READ_PERI_REG(I2S_STATE_REG(0))&I2S_TX_IDLE));
|
||||
|
||||
//Reset I2S for next transfer
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_START | I2S_RX_START);
|
||||
CLEAR_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_START | I2S_INLINK_START);
|
||||
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_RESET | I2S_RX_FIFO_RESET);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_RESET | I2S_RX_FIFO_RESET);
|
||||
|
||||
// for (i=0; i<(1<<8); i++);
|
||||
while ((READ_PERI_REG(I2S_STATE_REG(0))&I2S_TX_FIFO_RESET_BACK));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This is a very, very, very hacked up LCD routine which ends up basically doing a memcpy from sbuf to rbuf.
|
||||
*/
|
||||
static void sendRecvBufDma(uint16_t *sbuf, uint16_t *rbuf, int len)
|
||||
{
|
||||
//Fill DMA descriptor
|
||||
dmaDesc[0].length = len * 2;
|
||||
dmaDesc[0].size = len * 2;
|
||||
dmaDesc[0].owner = 1;
|
||||
dmaDesc[0].sosf = 0;
|
||||
dmaDesc[0].buf = (uint8_t *)sbuf;
|
||||
dmaDesc[0].offset = 0; //unused in hw
|
||||
dmaDesc[0].empty = 0;
|
||||
dmaDesc[0].eof = 1;
|
||||
dmaDesc[1].length = len * 2;
|
||||
dmaDesc[1].size = len * 2;
|
||||
dmaDesc[1].owner = 1;
|
||||
dmaDesc[1].sosf = 0;
|
||||
dmaDesc[1].buf = (uint8_t *)rbuf;
|
||||
dmaDesc[1].offset = 0; //unused in hw
|
||||
dmaDesc[1].empty = 0;
|
||||
dmaDesc[1].eof = 1;
|
||||
|
||||
//Reset DMA
|
||||
SET_PERI_REG_MASK(I2S_LC_CONF_REG(0), I2S_IN_RST | I2S_OUT_RST | I2S_AHBM_RST | I2S_AHBM_FIFO_RST);
|
||||
CLEAR_PERI_REG_MASK(I2S_LC_CONF_REG(0), I2S_IN_RST | I2S_OUT_RST | I2S_AHBM_RST | I2S_AHBM_FIFO_RST);
|
||||
|
||||
//Reset I2S FIFO
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_FIFO_RESET);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_FIFO_RESET);
|
||||
|
||||
//Set desc addr
|
||||
CLEAR_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_ADDR);
|
||||
SET_PERI_REG_MASK(I2S_OUT_LINK_REG(0), ((uint32_t)(&dmaDesc[0]))&I2S_OUTLINK_ADDR);
|
||||
CLEAR_PERI_REG_MASK(I2S_IN_LINK_REG(0), I2S_INLINK_ADDR);
|
||||
SET_PERI_REG_MASK(I2S_IN_LINK_REG(0), ((uint32_t)(&dmaDesc[1]))&I2S_INLINK_ADDR);
|
||||
|
||||
SET_PERI_REG_MASK(I2S_FIFO_CONF_REG(0), I2S_DSCR_EN); //Enable DMA mode
|
||||
|
||||
WRITE_PERI_REG(I2S_RXEOF_NUM_REG(0), len);
|
||||
|
||||
//Enable and configure DMA
|
||||
WRITE_PERI_REG(I2S_LC_CONF_REG(0), I2S_OUT_DATA_BURST_EN |
|
||||
I2S_OUT_EOF_MODE | I2S_OUTDSCR_BURST_EN | I2S_OUT_DATA_BURST_EN |
|
||||
I2S_INDSCR_BURST_EN | I2S_MEM_TRANS_EN);
|
||||
|
||||
//Start transmission
|
||||
SET_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_START);
|
||||
SET_PERI_REG_MASK(I2S_IN_LINK_REG(0), I2S_INLINK_START);
|
||||
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_START | I2S_RX_START);
|
||||
//Clear int flags
|
||||
WRITE_PERI_REG(I2S_INT_CLR_REG(0), 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
|
||||
#define DMALEN (2048-2)
|
||||
|
||||
static void tskLcd(void *pvParameters)
|
||||
{
|
||||
uint16_t *sbuf = malloc(DMALEN * 2);
|
||||
uint16_t *rbuf = malloc(DMALEN * 2);
|
||||
uint16_t xorval = 0;
|
||||
int x;
|
||||
lcdIfaceInit();
|
||||
// lcdFlush();
|
||||
while (1) {
|
||||
for (x = 0; x < DMALEN; x++) {
|
||||
sbuf[x] = x ^ xorval;
|
||||
}
|
||||
for (x = 0; x < DMALEN; x++) {
|
||||
rbuf[x] = 0; //clear rbuf
|
||||
}
|
||||
sendRecvBufDma(sbuf, rbuf, DMALEN);
|
||||
vTaskDelay(20 / portTICK_PERIOD_MS);
|
||||
finishDma();
|
||||
for (x = 0; x < DMALEN; x++) if (rbuf[x] != (x ^ xorval)) {
|
||||
printf("Rxbuf err! pos %d val %x xor %x", x, (int)rbuf[x], (int)xorval);
|
||||
}
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
xorval++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void test_s32c1i_lock(volatile int *lockvar, int lockval, int unlockval, volatile int *ctr);
|
||||
|
||||
static volatile int ctr = 0, state = 0;
|
||||
static volatile int lock = 0;
|
||||
|
||||
static void tskOne(void *pvParameters)
|
||||
{
|
||||
int x;
|
||||
int err = 0, run = 0;
|
||||
while (1) {
|
||||
ctr = 0; lock = 0;
|
||||
state = 1;
|
||||
for (x = 0; x < 16 * 1024; x++) {
|
||||
test_s32c1i_lock(&lock, 1, 0, &ctr);
|
||||
}
|
||||
vTaskDelay(60 / portTICK_PERIOD_MS);
|
||||
state = 2;
|
||||
if (ctr != 16 * 1024 * 2) {
|
||||
printf("Lock malfunction detected! Ctr=0x%x instead of %x\n", ctr, 16 * 1024 * 2);
|
||||
err++;
|
||||
}
|
||||
run++;
|
||||
printf("Run %d err %d\n", run, err);
|
||||
vTaskDelay(20 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
#define FB2ADDR 0x40098000
|
||||
|
||||
static void tskTwo(void *pvParameters)
|
||||
{
|
||||
int x;
|
||||
int *p = (int *)FB2ADDR;
|
||||
int *s = (int *)test_s32c1i_lock;
|
||||
void (*test_s32c1i_lock2)(volatile int * lockvar, int lockval, int unlockval, volatile int * ctr) = (void *)FB2ADDR;
|
||||
volatile int w;
|
||||
int delay;
|
||||
for (x = 0; x < 100; x++) {
|
||||
*p++ = *s++; //copy routine to different pool
|
||||
}
|
||||
|
||||
while (1) {
|
||||
while (state != 1) ;
|
||||
for (x = 0; x < 16 * 1024; x++) {
|
||||
test_s32c1i_lock2(&lock, 2, 0, &ctr);
|
||||
//Some random delay to increase chance of weirdness
|
||||
if ((x & 0x1f) == 0) {
|
||||
delay = rand() & 0x1f;
|
||||
for (w = 0; w < delay; w++);
|
||||
}
|
||||
}
|
||||
while (state != 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("S32C1I vs AHB test (needs I2S)", "[hw]")
|
||||
{
|
||||
int i;
|
||||
TaskHandle_t th[3];
|
||||
state = 0;
|
||||
|
||||
printf("Creating tasks\n");
|
||||
xTaskCreatePinnedToCore(tskTwo , "tsktwo" , 2048, NULL, 3, &th[1], 1);
|
||||
xTaskCreatePinnedToCore(tskOne , "tskone" , 2048, NULL, 3, &th[0], 0);
|
||||
xTaskCreatePinnedToCore(tskLcd , "tsklcd" , 2048, NULL, 3, &th[2], 0);
|
||||
|
||||
// Let stuff run for 20s
|
||||
while (1) {
|
||||
vTaskDelay(20000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
//Shut down all the tasks
|
||||
for (i = 0; i < 3; i++) {
|
||||
vTaskDelete(th[i]);
|
||||
}
|
||||
}
|
||||
|
51
components/esp32/test/test_ahb_arb_asm.S
Normal file
51
components/esp32/test/test_ahb_arb_asm.S
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
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_s32c1i_lock
|
||||
.type test_s32c1i_lock,@function
|
||||
//Args:
|
||||
//a2 - lock addr
|
||||
//a3 - val to lock with
|
||||
//a4 - val to unlock with
|
||||
//a5 - addr to increase
|
||||
test_s32c1i_lock:
|
||||
entry a1, 64
|
||||
wsr a4, SCOMPARE1
|
||||
lockloop:
|
||||
mov a6, a3
|
||||
s32c1i a6, a2, 0
|
||||
bne a4, a6, lockloop
|
||||
|
||||
l32i a6, a5, 0
|
||||
//Give other CPU the time to mess up the inc if the lock somehow malfunctions
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
addi a6, a6, 1
|
||||
s32i a6, a5, 0
|
||||
|
||||
|
||||
//No need to actually let this loop but hey, a hang indicates an error, right?
|
||||
wsr a3, SCOMPARE1
|
||||
unlockloop:
|
||||
mov a6, a4
|
||||
s32c1i a6, a2, 0
|
||||
bne a3, a6, unlockloop
|
||||
|
||||
retw
|
132
components/esp32/test/test_fastbus.c
Normal file
132
components/esp32/test/test_fastbus.c
Normal file
@ -0,0 +1,132 @@
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdio.h>
|
||||
#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);
|
||||
}
|
||||
|
32
components/esp32/test/test_fastbus_asm.S
Normal file
32
components/esp32/test/test_fastbus_asm.S
Normal file
@ -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
|
193
components/esp32/test/test_fp.c
Normal file
193
components/esp32/test/test_fp.c
Normal file
@ -0,0 +1,193 @@
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "unity.h"
|
||||
|
||||
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);
|
||||
}
|
77
components/esp32/test/test_miniz.c
Normal file
77
components/esp32/test/test_miniz.c
Normal file
@ -0,0 +1,77 @@
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#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);
|
||||
}
|
91
components/esp32/test/test_tjpgd.c
Normal file
91
components/esp32/test/test_tjpgd.c
Normal file
@ -0,0 +1,91 @@
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "rom/tjpgd.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#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);
|
||||
}
|
205
components/esp32/test/test_unal_dma.c
Normal file
205
components/esp32/test/test_unal_dma.c
Normal file
@ -0,0 +1,205 @@
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#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<<GPIO_GPIO_FUNC0_OUT_SEL_S));
|
||||
|
||||
//GPIO_SET_GPIO_FUNC11_OUT_INV_SEL(1); //old
|
||||
WRITE_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG, READ_PERI_REG(GPIO_FUNC11_OUT_SEL_CFG_REG) | GPIO_FUNC11_OUT_INV_SEL);
|
||||
|
||||
//Reset I2S subsystem
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET);
|
||||
|
||||
WRITE_PERI_REG(I2S_CONF_REG(0), 0);//I2S_I2S_SIG_LOOPBACK);
|
||||
WRITE_PERI_REG(I2S_CONF2_REG(0), 0);
|
||||
|
||||
WRITE_PERI_REG(I2S_SAMPLE_RATE_CONF_REG(0),
|
||||
(16 << I2S_RX_BITS_MOD_S) |
|
||||
(16 << I2S_TX_BITS_MOD_S) |
|
||||
(1 << I2S_RX_BCK_DIV_NUM_S) |
|
||||
(1 << I2S_TX_BCK_DIV_NUM_S));
|
||||
WRITE_PERI_REG(I2S_CLKM_CONF_REG(0),
|
||||
I2S_CLKA_ENA | I2S_CLK_EN |
|
||||
(1 << I2S_CLKM_DIV_A_S) |
|
||||
(1 << I2S_CLKM_DIV_B_S) |
|
||||
(1 << I2S_CLKM_DIV_NUM_S));
|
||||
WRITE_PERI_REG(I2S_FIFO_CONF_REG(0),
|
||||
(32 << I2S_TX_DATA_NUM_S) | //Low watermark for IRQ
|
||||
(32 << I2S_RX_DATA_NUM_S));
|
||||
|
||||
WRITE_PERI_REG(I2S_CONF1_REG(0), I2S_RX_PCM_BYPASS | I2S_TX_PCM_BYPASS);
|
||||
|
||||
WRITE_PERI_REG(I2S_CONF_CHAN_REG(0), (2 << I2S_TX_CHAN_MOD_S) | (2 << I2S_RX_CHAN_MOD_S));
|
||||
|
||||
//Invert WS to active-low
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RIGHT_FIRST | I2S_RX_RIGHT_FIRST);
|
||||
WRITE_PERI_REG(I2S_TIMING_REG(0), 0);
|
||||
|
||||
//--
|
||||
//Fill DMA descriptor
|
||||
dmaDesc[0].length = len;
|
||||
dmaDesc[0].size = len;
|
||||
dmaDesc[0].owner = 1;
|
||||
dmaDesc[0].sosf = 0;
|
||||
dmaDesc[0].buf = (uint8_t *)in;
|
||||
dmaDesc[0].offset = 0; //unused in hw
|
||||
dmaDesc[0].empty = 0;
|
||||
dmaDesc[0].eof = 1;
|
||||
dmaDesc[1].length = len;
|
||||
dmaDesc[1].size = len;
|
||||
dmaDesc[1].owner = 1;
|
||||
dmaDesc[1].sosf = 0;
|
||||
dmaDesc[1].buf = (uint8_t *)out;
|
||||
dmaDesc[1].offset = 0; //unused in hw
|
||||
dmaDesc[1].empty = 0;
|
||||
dmaDesc[1].eof = 1;
|
||||
|
||||
//Reset DMA
|
||||
SET_PERI_REG_MASK(I2S_LC_CONF_REG(0), I2S_IN_RST | I2S_OUT_RST | I2S_AHBM_RST | I2S_AHBM_FIFO_RST);
|
||||
CLEAR_PERI_REG_MASK(I2S_LC_CONF_REG(0), I2S_IN_RST | I2S_OUT_RST | I2S_AHBM_RST | I2S_AHBM_FIFO_RST);
|
||||
|
||||
//Reset I2S FIFO
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_FIFO_RESET);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET | I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_FIFO_RESET);
|
||||
|
||||
//Set desc addr
|
||||
CLEAR_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_ADDR);
|
||||
SET_PERI_REG_MASK(I2S_OUT_LINK_REG(0), ((uint32_t)(&dmaDesc[0]))&I2S_OUTLINK_ADDR);
|
||||
CLEAR_PERI_REG_MASK(I2S_IN_LINK_REG(0), I2S_INLINK_ADDR);
|
||||
SET_PERI_REG_MASK(I2S_IN_LINK_REG(0), ((uint32_t)(&dmaDesc[1]))&I2S_INLINK_ADDR);
|
||||
|
||||
SET_PERI_REG_MASK(I2S_FIFO_CONF_REG(0), I2S_DSCR_EN); //Enable DMA mode
|
||||
|
||||
WRITE_PERI_REG(I2S_RXEOF_NUM_REG(0), len);
|
||||
|
||||
//Enable and configure DMA
|
||||
WRITE_PERI_REG(I2S_LC_CONF_REG(0), I2S_OUT_DATA_BURST_EN |
|
||||
I2S_OUT_EOF_MODE | I2S_OUTDSCR_BURST_EN | I2S_OUT_DATA_BURST_EN |
|
||||
I2S_INDSCR_BURST_EN | I2S_MEM_TRANS_EN);
|
||||
|
||||
//Start transmission
|
||||
SET_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_START);
|
||||
SET_PERI_REG_MASK(I2S_IN_LINK_REG(0), I2S_INLINK_START);
|
||||
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_START | I2S_RX_START);
|
||||
//Clear int flags
|
||||
WRITE_PERI_REG(I2S_INT_CLR_REG(0), 0xFFFFFFFF);
|
||||
//--
|
||||
//No need to finish if no DMA transfer going on
|
||||
if (!(READ_PERI_REG(I2S_FIFO_CONF_REG(0))&I2S_DSCR_EN)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Wait till fifo done
|
||||
while (!(READ_PERI_REG(I2S_INT_RAW_REG(0))&I2S_TX_REMPTY_INT_RAW)) ;
|
||||
//Wait for last bytes to leave i2s xmit thing
|
||||
//ToDo: poll bit in next hw
|
||||
for (i = 0; i < (1 << 8); i++);
|
||||
while (!(READ_PERI_REG(I2S_STATE_REG(0))&I2S_TX_IDLE));
|
||||
|
||||
//Reset I2S for next transfer
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_START | I2S_RX_START);
|
||||
CLEAR_PERI_REG_MASK(I2S_OUT_LINK_REG(0), I2S_OUTLINK_START | I2S_INLINK_START);
|
||||
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_RESET | I2S_RX_FIFO_RESET);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_TX_RESET | I2S_TX_FIFO_RESET | I2S_RX_RESET | I2S_RX_FIFO_RESET);
|
||||
|
||||
// for (i=0; i<(1<<8); i++);
|
||||
while ((READ_PERI_REG(I2S_STATE_REG(0))&I2S_TX_FIFO_RESET_BACK));
|
||||
|
||||
}
|
||||
|
||||
|
||||
int mymemcmp(char *a, char *b, int len)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < len; x++) {
|
||||
if (a[x] != b[x]) {
|
||||
printf("Not equal at byte %d. a=%x, b=%x\n", x, (int)a[x], (int)b[x]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_CASE("Unaligned DMA test (needs I2S)", "[hw]")
|
||||
{
|
||||
int x;
|
||||
char src[2049], dest[2049];
|
||||
for (x = 0; x < sizeof(src); x++) {
|
||||
src[x] = x & 0xff;
|
||||
}
|
||||
|
||||
printf("Aligned dma\n");
|
||||
memset(dest, 0, 2049);
|
||||
dmaMemcpy(src, dest, 2048 + 1);
|
||||
TEST_ASSERT(mymemcmp(src, dest, 2048) == 0);
|
||||
printf("Src unaligned\n");
|
||||
dmaMemcpy(src + 1, dest, 2048 + 1);
|
||||
TEST_ASSERT(mymemcmp(src + 1, dest, 2048) == 0);
|
||||
printf("Dst unaligned\n");
|
||||
dmaMemcpy(src, dest + 1, 2048 + 2);
|
||||
TEST_ASSERT(mymemcmp(src, dest + 1, 2048) == 0);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
@ -927,7 +928,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 +943,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;
|
||||
|
@ -108,6 +108,7 @@
|
||||
|
||||
/* configASSERT behaviour */
|
||||
#ifndef __ASSEMBLER__
|
||||
#include <stdlib.h> /* 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 <stdlib.h>
|
||||
#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()
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
@ -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.
|
||||
|
5
components/freertos/test/component.mk
Normal file
5
components/freertos/test/component.mk
Normal file
@ -0,0 +1,5 @@
|
||||
#
|
||||
#Component Makefile
|
||||
#
|
||||
|
||||
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
|
229
components/freertos/test/test_freertos.c
Normal file
229
components/freertos/test/test_freertos.c
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
Test for multicore FreeRTOS. This test spins up threads, fiddles with queues etc.
|
||||
*/
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdio.h>
|
||||
#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);
|
||||
}
|
||||
|
105
components/freertos/test/test_freertos_eventgroups.c
Normal file
105
components/freertos/test/test_freertos_eventgroups.c
Normal file
@ -0,0 +1,105 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
22
components/freertos/test/test_freertos_task_delete.c
Normal file
22
components/freertos/test/test_freertos_task_delete.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#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");
|
||||
}
|
60
components/freertos/test/test_newlib_reent.c
Normal file
60
components/freertos/test/test_newlib_reent.c
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
Test for multicore FreeRTOS. This test spins up threads, fiddles with queues etc.
|
||||
*/
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#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);
|
||||
}
|
||||
|
26
components/freertos/test/test_panic.c
Normal file
26
components/freertos/test/test_panic.c
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
Test for multicore FreeRTOS. This test spins up threads, fiddles with queues etc.
|
||||
*/
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdio.h>
|
||||
#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;
|
||||
}
|
||||
|
197
components/freertos/test/test_ringbuf.c
Normal file
197
components/freertos/test/test_ringbuf.c
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
Test for multicore FreeRTOS ringbuffer.
|
||||
*/
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdio.h>
|
||||
#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 <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
58
components/freertos/test/test_tls_deletecb.c
Normal file
58
components/freertos/test/test_tls_deletecb.c
Normal file
@ -0,0 +1,58 @@
|
||||
#include <esp_types.h>
|
||||
#include <stdio.h>
|
||||
#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);
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -18,10 +18,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
#include <rom/ets_sys.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <malloc.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include "mbedtls/bignum.h"
|
||||
#include "rom/bigint.h"
|
||||
#include "soc/hwcrypto_reg.h"
|
||||
|
5
components/mbedtls/test/component.mk
Normal file
5
components/mbedtls/test/component.mk
Normal file
@ -0,0 +1,5 @@
|
||||
#
|
||||
#Component Makefile
|
||||
#
|
||||
|
||||
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
|
134
components/mbedtls/test/test_mbedtls.c
Normal file
134
components/mbedtls/test/test_mbedtls.c
Normal file
@ -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 <string.h>
|
||||
#include <stdio.h>
|
||||
#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 );
|
||||
}
|
5
components/newlib/test/component.mk
Normal file
5
components/newlib/test/component.mk
Normal file
@ -0,0 +1,5 @@
|
||||
#
|
||||
#Component Makefile
|
||||
#
|
||||
|
||||
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
|
102
components/newlib/test/test_newlib.c
Normal file
102
components/newlib/test/test_newlib.c
Normal file
@ -0,0 +1,102 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#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"));
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
|
5
components/nvs_flash/test/component.mk
Normal file
5
components/nvs_flash/test/component.mk
Normal file
@ -0,0 +1,5 @@
|
||||
#
|
||||
#Component Makefile
|
||||
#
|
||||
|
||||
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
|
51
components/nvs_flash/test/test_nvs.c
Normal file
51
components/nvs_flash/test/test_nvs.c
Normal file
@ -0,0 +1,51 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "unity.h"
|
||||
#include "nvs.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
TEST_CASE("various nvs tests", "[nvs]")
|
||||
{
|
||||
nvs_handle handle_1;
|
||||
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_set_i32(handle_1, "foo", 0x12345678), ESP_ERR_NVS_INVALID_HANDLE);
|
||||
nvs_close(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("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";
|
||||
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));
|
||||
|
||||
nvs_close(handle_1);
|
||||
nvs_close(handle_2);
|
||||
}
|
@ -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;
|
||||
|
||||
|
5
components/partition_table/test/component.mk
Normal file
5
components/partition_table/test/component.mk
Normal file
@ -0,0 +1,5 @@
|
||||
#
|
||||
#Component Makefile
|
||||
#
|
||||
|
||||
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
|
95
components/partition_table/test/test_partition.c
Normal file
95
components/partition_table/test/test_partition.c
Normal file
@ -0,0 +1,95 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#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);
|
||||
}
|
5
components/spi_flash/test/component.mk
Normal file
5
components/spi_flash/test/component.mk
Normal file
@ -0,0 +1,5 @@
|
||||
#
|
||||
#Component Makefile
|
||||
#
|
||||
|
||||
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
|
83
components/spi_flash/test/test_mmap.c
Normal file
83
components/spi_flash/test/test_mmap.c
Normal file
@ -0,0 +1,83 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <freertos/semphr.h>
|
||||
|
||||
#include <unity.h>
|
||||
#include <esp_spi_flash.h>
|
||||
#include <esp_attr.h>
|
||||
|
||||
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);
|
||||
}
|
92
components/spi_flash/test/test_spi_flash.c
Normal file
92
components/spi_flash/test/test_spi_flash.c
Normal file
@ -0,0 +1,92 @@
|
||||
#include <stdio.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <freertos/semphr.h>
|
||||
|
||||
#include <unity.h>
|
||||
#include <esp_spi_flash.h>
|
||||
#include <esp_attr.h>
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
64
components/wpa_supplicant/port/os_xtensa.c
Normal file
64
components/wpa_supplicant/port/os_xtensa.c
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* wpa_supplicant/hostapd / Internal implementation of OS specific functions
|
||||
* Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#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;
|
||||
}
|
||||
|
66
docs/api/pcnt.rst
Normal file
66
docs/api/pcnt.rst
Normal file
@ -0,0 +1,66 @@
|
||||
Pulse Counter
|
||||
========
|
||||
|
||||
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
|
||||
-------------------
|
||||
|
||||
Pulse counter with control signal and event interrupt example: `examples/12_pcnt <https://github.com/espressif/esp-idf/tree/master/examples/12_pcnt>`_.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
Header Files
|
||||
^^^^^^^^^^^^
|
||||
|
||||
* `driver/pcnt.h <https://github.com/espressif/esp-idf/blob/master/components/driver/include/driver/pcnt.h>`_
|
||||
|
||||
|
||||
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
|
||||
|
@ -97,12 +97,12 @@ Contents:
|
||||
Wi-Fi <api/esp_wifi>
|
||||
Bluetooth <api/bt>
|
||||
Watchdogs <api/wdts>
|
||||
|
||||
GPIO <api/gpio>
|
||||
UART <api/uart>
|
||||
LED Control <api/ledc>
|
||||
Remote Control <api/rmt>
|
||||
Timer <api/timer>
|
||||
Pulse Counter <api/pcnt>
|
||||
SPI Flash and Partition APIs <api/spi_flash>
|
||||
Logging <api/log>
|
||||
Non-Volatile Storage <api/nvs_flash>
|
||||
|
@ -21,7 +21,7 @@ void hello_task(void *pvParameter)
|
||||
}
|
||||
printf("Restarting now.\n");
|
||||
fflush(stdout);
|
||||
system_restart();
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
void app_main()
|
||||
|
@ -22,6 +22,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
@ -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)
|
||||
|
@ -76,5 +76,5 @@ void app_main()
|
||||
}
|
||||
printf("Restarting now.\n");
|
||||
fflush(stdout);
|
||||
system_restart();
|
||||
esp_restart();
|
||||
}
|
||||
|
@ -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);
|
||||
|
9
examples/12_pcnt/Makefile
Normal file
9
examples/12_pcnt/Makefile
Normal file
@ -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
|
||||
|
3
examples/12_pcnt/main/component.mk
Normal file
3
examples/12_pcnt/main/component.mk
Normal file
@ -0,0 +1,3 @@
|
||||
#
|
||||
# Main Makefile. This is basically the same as a component makefile.
|
||||
#
|
226
examples/12_pcnt/main/pcnt_test.c
Normal file
226
examples/12_pcnt/main/pcnt_test.c
Normal file
@ -0,0 +1,226 @@
|
||||
/* 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 <stdio.h>
|
||||
#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"
|
||||
#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 output 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 your 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_UNIT_0
|
||||
#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)
|
||||
|
||||
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))) {
|
||||
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) {
|
||||
//do something
|
||||
}
|
||||
/*L LIM EVT*/
|
||||
if(PCNT.status_unit[i].l_lim_lat) {
|
||||
//do something
|
||||
}
|
||||
/*THRES0 EVT*/
|
||||
if(PCNT.status_unit[i].thres0_lat) {
|
||||
//do something
|
||||
}
|
||||
/*THRES1 EVT*/
|
||||
if(PCNT.status_unit[i].thres1_lat) {
|
||||
//do something
|
||||
}
|
||||
/*ZERO EVT*/
|
||||
if(PCNT.status_unit[i].zero_lat) {
|
||||
//do something
|
||||
}
|
||||
xQueueSendFromISR(pcnt_evt_queue, &evt, &HPTaskAwoken);
|
||||
if(HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ledc_init(void)
|
||||
{
|
||||
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_THRES_1, PCNT_THRESH1_VAL);
|
||||
/*Enable watch point event of thresh1*/
|
||||
pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_THRES_1);
|
||||
/*Set value for watch point thresh0*/
|
||||
pcnt_set_event_value(PCNT_TEST_UNIT, PCNT_EVT_THRES_0, PCNT_THRESH0_VAL);
|
||||
/*Enable watch point event of thresh0*/
|
||||
pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_THRES_0);
|
||||
/*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 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user