Merge branch 'master' into driver_merge_tmp/merge_timer

# Conflicts:
#	docs/index.rst
This commit is contained in:
Wangjialin 2016-11-25 01:07:19 +08:00
commit a5ad8090cf
114 changed files with 7049 additions and 293 deletions

5
.gitignore vendored
View file

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

View file

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

View file

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

View file

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

View 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

View file

@ -40,6 +40,7 @@ typedef enum {
PERIPH_UHCI0_MODULE,
PERIPH_UHCI1_MODULE,
PERIPH_RMT_MODULE,
PERIPH_PCNT_MODULE,
} periph_module_t;
/**

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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;
/**
* @}
*/

View file

@ -17,6 +17,7 @@
#include "esp_types.h"
#include "esp_attr.h"
#include "ets_sys.h"
#ifdef __cplusplus
extern "C" {

View file

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

View file

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

View file

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

View file

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

View 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

View file

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

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

View file

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

View file

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

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

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

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

View 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

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

View 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

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

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

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,5 @@
#
#Component Makefile
#
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

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

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

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

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

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

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

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,5 @@
#
#Component Makefile
#
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

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

View file

@ -0,0 +1,5 @@
#
#Component Makefile
#
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

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

View file

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

View file

@ -0,0 +1,5 @@
#
#Component Makefile
#
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

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

View file

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

View file

@ -0,0 +1,5 @@
#
#Component Makefile
#
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

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

View file

@ -0,0 +1,5 @@
#
#Component Makefile
#
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

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

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

View file

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

View file

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

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

View file

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

View file

@ -21,7 +21,7 @@ void hello_task(void *pvParameter)
}
printf("Restarting now.\n");
fflush(stdout);
system_restart();
esp_restart();
}
void app_main()

View file

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

View file

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

View file

@ -76,5 +76,5 @@ void app_main()
}
printf("Restarting now.\n");
fflush(stdout);
system_restart();
esp_restart();
}

View file

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

View 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

View file

@ -0,0 +1,3 @@
#
# Main Makefile. This is basically the same as a component makefile.
#

View 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