添加智能灯固件代码

This commit is contained in:
kerwincui
2021-07-13 17:14:51 +08:00
parent 332f74dd17
commit ecc0b91b8b
2568 changed files with 229441 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(app_trace_to_host)

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 := app_trace_to_host
include $(IDF_PATH)/make/project.mk

View File

@@ -0,0 +1,216 @@
| Supported Targets | ESP32 |
| ----------------- | ----- |
# Application Level Tracing Example (Logging to Host)
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use the [Application Level Tracing Library](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/app_trace.html#) (henceforth referred to as **App Trace**) to log messages to a host via JTAG instead of the normal method of logging via UART.
UART logs are time consuming and can significantly slow down the function that calls it. Therefore, it is generally a bad idea to use UART logs in time-critical functions. Logging to host via JTAG is significantly faster and can be used in time-critical functions. For more details regarding logging to host via JTAG, refer to the [Logging to Host Documentation](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/app_trace.html#app-trace-logging-to-host).
This example demonstrates JTAG logging to host in the context of polling for a [zero crossing](https://en.wikipedia.org/wiki/Zero_crossing). The ESP32 will continuously sample a 50 to 60 Hz sinusoidal signal (using the ADC) and log the sampled values (via JTAG). Due to the higher speed of JTAG logging, the polling rate of the ADC should be high enough to detect a zero crossing.
This example utilizes the following ESP-IDF features:
* [DAC driver](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/dac.html) to generate the 50 Hz sinusoidal signal.
* [ADC driver](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/adc.html) to sample the sinusoidal signal.
* [Application Level Tracing Library](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/app_trace.html#) to log ADC samples to host.
* [OpenOCD](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/jtag-debugging/index.html#setup-of-openocd) to interface with the ESP32 and receive the log output over JTAG.
## How to use example
### Hardware Required
To run this example, you need an ESP32 dev board connected to a JTAG adapter, which can come in the following forms:
* [ESP-WROVER-KIT](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/modules-and-boards.html#esp-wrover-kit-v4-1) which integrates an on-board JTAG adapter. Ensure that the [required jumpers to enable JTAG are connected](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/get-started-wrover-kit.html#setup-options) on the WROVER-KIT.
* ESP32 core board (e.g. ESP32-DevKitC) can also work as long as you connect it to an external JTAG adapter (e.g. FT2232H, J-LINK).
This example will assume that that an ESP-WROVER-KIT is used.
#### Pin Assignment:
The sinusoidal signal of 50 to 60 Hz ranging from 0 V ~ 3.1 V should be input into `GPIO34` (`ADC1_CHANNEL_6`). Users may provide this signal themselves, our use the DAC generated signal by bridging GPIO34 with `GPIO25` (`DAC_CHANNEL_1`).
| DAC Output | ADC Input |
| ------------------ | ------------------ |
| Channel 1 (GPIO25) | Channel 6 (GPIO34) |
#### Extra Connections:
1. Connect the JTAG interface to ESP32 board, and power up both the JTAG and ESP32. For details about how to set up JTAG interface, please see [JTAG Debugging](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/jtag-debugging/index.html).
2. After connecting JTAG interface, you need to [Run OpenOCD](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/jtag-debugging/index.html#run-openocd).
3. Open a separate terminal window and run telnet by entering the command below. The telnet terminal window is used to feed commands to OpenOCD:
```bash
telnet localhost 4444
```
### Configure the project
```
idf.py menuconfig
```
* By default, the DAC will generate 130 Hz signal ranging from 0 V ~ 3.1 V. To generate a 50 Hz signal, the RTC 8 MHz clock will need to use a non-standard divider. This is achieved by enabling the `Example Configuration > Set custom RTC 8 MHz clock divider to lower CW frequency` configuration option.
* To enable application tracing, select the `(X) Trace memory` option under `Component config > Application Level Tracing`. This option should have been selected by default.
### Build, Flash, and Run
Build the project and flash it to the board, then run monitor tool to view serial output:
```
idf.py -p PORT flash monitor
```
(Replace PORT with the name of the serial port to use.)
**Start App Trace:** In the telnet session window, trigger OpenOCD to start App Trace on the ESP32 by entering the command below. This command will collect 9000 bytes of JTAG log data and save them to `adc.log` file in `~/esp/openocd-esp32` folder.
```bash
esp apptrace start file://adc.log 0 9000 5 0 0
```
**Note:** For more details on OpenOCD commands regarding App Trace, refer to the [OpenOCD Application Level Tracing Commands](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/app_trace.html#openocd-application-level-tracing-commands)
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example Output
The example will continuously sample the ADC for 20ms per iteration, and will alternate between JTAG and UART logging per iteration. However, the JTAG logs should be captured by OpenOCD, thus will not appear in the monitor's output. Therefore, the monitor should only display the iterations where UART logging was used (i.e. every alternate iteration) such as the following:
```
I (4289) example: Sampling ADC and sending data to the host...
I (4309) example: Collected 427 samples in 20 ms.
I (4309) example: Sampling ADC and sending data to the UART...
I (4309) example: Sample:1, Value:2224
I (4309) example: Sample:2, Value:840
I (4309) example: Sample:3, Value:3503
I (4319) example: Sample:4, Value:27
I (4319) example: Sample:5, Value:4095
I (4329) example: Collected 5 samples in 20 ms.
```
**Note:** The UART log above was produced with the CPU running at 240 MHz.
To access the JTAG logs, the `adc.log` file should be decoded. This can be done by using the `logtrace_proc.py` script as such:
```bash
$IDF_PATH/tools/esp_app_trace/logtrace_proc.py ~/esp/openocd-esp32/adc.log ~/esp/app_trace_to_host/build/app_trace_to_host_test.elf
```
The `logtrace_proc.py` script should produce the following output when decoding:
```
Parse trace file '/user-home/esp/openocd-esp32/adc.log'...
Unprocessed 7 bytes of log record args!
Parsing completed.
====================================================================
I (59369) example: Sample:1, Value:3717
I (59369) example: Sample:2, Value:3647
I (59369) example: Sample:3, Value:3575
I (59369) example: Sample:4, Value:3491
...
I (59379) example: Sample:398, Value:78
I (59379) example: Sample:399, Value:58
I (59379) example: Sample:400, Value:22
I (59379) example: Sample:401, Value:14
I (59379) example: Sample:402, Value:0
I (59379) example: Sample:403, Value:0
I (59379) example: Sample:404, Value:0
I (59379) example: Sample:405, Value:0
I (59379) example: Sample:406, Value:0
I (59379) example: Sample:407, Value:0
I (59379) example: Sample:408, Value:0
I (59379) example: Sample:409, Value:0
I (59379) example: Sample:410, Value:0
I (59379) example: Sample:411, Value:0
I (59379) example: Sample:412, Value:0
I (59379) example: Sample:413, Value:0
I (59379) example: Sample:414, Value:16
I (59379) example: Sample:415, Value:32
I (59379) example: Sample:416, Value:40
I (59379) example: Sample:417, Value:74
I (59379) example: Sample:418, Value:89
I (59379) example: Sample:419, Value:113
I (59379) example: Sample:420, Value:160
I (59379) example: Sample:421, Value:192
I (59379) example: Sample:422, Value:221
I (59379) example: Sample:423, Value:256
I (59379) example: Sample:424, Value:298
I (59379) example: Sample:425, Value:345
I (59379) example: Sample:426, Value:386
I (59379) example: Sample:427, Value:432
I (61409) example: Sample:1, Value:2653
====================================================================
Log records count: 428
```
## Troubleshooting
### Unable to flash when OpenOCD is connected to ESP32
One likely cause would be an incorrect SPI flash voltage when starting OpenOCD. Suppose an ESP32 board/module with a 3.3 V powered SPI flash is being used, but the `board/esp32-wrover.cfg` configuration file is selected when starting OpenOCD which can set the SPI flash voltage to 1.8 V. In this situation, the SPI flash will not work after OpenOCD connects to the ESP32 as OpenOCD has changed the SPI flash voltage. Therefore, you might not be able to flash ESP32 when OpenOCD is connected.
To work around this issue, users are suggested to use `board/esp32-wrover.cfg` for ESP32 boards/modules operating with an SPI flash voltage of 1.8 V, and `board/esp-wroom-32.cfg` for 3.3 V. Refer to [ESP32 Modules and Boards](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/modules-and-boards.html) and [Set SPI Flash Voltage](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/jtag-debugging/tips-and-quirks.html#why-to-set-spi-flash-voltage-in-openocd-configuration) for more details.
(For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you as soon as possible.)
The log should be identical to those printed via UART (complete with timestamps), but almost two orders of magnitude faster.
## Example Breakdown
The following code snippet demonstrates a loop of the sampling and logging the ADC over a 20 ms period in order to capture one full period of a 50 Hz signal.
```c
int sampling_period = 20;
int i = 0;
uint32_t sampling_start = esp_log_timestamp(); //this clock counts milliseconds
do {
ESP_LOGI(TAG, "Sample:%d, Value:%d", ++i, adc1_get_raw(ADC1_TEST_CHANNEL));
} while (esp_log_timestamp() - sampling_start < sampling_period);
```
If `ESP_LOGI()` is routed via UART (occurs by default), the log output produced will likely resemble the output shown below. Notice that due to UART logging is time consuming, thus the ADC is only sampled five times, which is too infrequent to consistently detect a zero crossing (where the zero crossing is `4096/2 = 2048` i.e., the mid point of the 12-bit ADC).
```bash
I (4309) example: Sample:1, Value:2224
I (4309) example: Sample:2, Value:840
I (4309) example: Sample:3, Value:3503
I (4319) example: Sample:4, Value:27
I (4319) example: Sample:5, Value:4095
I (4329) example: Collected 5 samples in 20 ms.
```
However, by logging via JTAG, the logging is much quicker hence allows a much higher sampling frequency (over 400 times) as shown the the log output below thus would be able to detect a zero crossing more consistently.
```c
esp_log_set_vprintf(esp_apptrace_vprintf);
```
```bash
...
I (59379) example: Sample:423, Value:256
I (59379) example: Sample:424, Value:298
I (59379) example: Sample:425, Value:345
I (59379) example: Sample:426, Value:386
I (59379) example: Sample:427, Value:432
I (61409) example: Sample:1, Value:2653
====================================================================
Log records count: 428
```
This example has demonstrated powerful functionality of logging to host via JTAG interface. With standard UART communication at a baud rate of 115200, printing out a single line log message takes approximately 4 ms. This also means that logged tasks cannot run more frequently than every 4 ms. By providing the same logging over JTAG, logging performance is improved 80 fold.

View File

@@ -0,0 +1,50 @@
from __future__ import unicode_literals
import os
import re
import ttfw_idf
@ttfw_idf.idf_example_test(env_tag="test_jtag_arm")
def test_examples_app_trace_to_host(env, extra_data):
rel_project_path = os.path.join('examples', 'system', 'app_trace_to_host')
dut = env.get_dut('app_trace_to_host', rel_project_path)
idf_path = dut.app.get_sdk_path()
proj_path = os.path.join(idf_path, rel_project_path)
with ttfw_idf.OCDProcess(os.path.join(proj_path, 'openocd.log')):
with ttfw_idf.TelnetProcess(os.path.join(proj_path, 'telnet.log')) as telnet_p:
dut.start_app()
dut.expect_all('example: Enabling ADC1 on channel 6 / GPIO34.',
'example: Enabling CW generator on DAC channel 1',
'example: Custom divider of RTC 8 MHz clock has been set.',
'example: Sampling ADC and sending data to the host...',
re.compile(r'example: Collected \d+ samples in 20 ms.'),
'example: Sampling ADC and sending data to the UART...',
re.compile(r'example: Sample:\d, Value:\d+'),
re.compile(r'example: Collected \d+ samples in 20 ms.'),
timeout=20)
telnet_p.pexpect_proc.sendline('esp apptrace start file://adc.log 0 9000 5 0 0')
telnet_p.pexpect_proc.expect_exact('App trace params: from 2 cores, size 9000 bytes, '
'stop_tmo 5 s, poll period 0 ms, wait_rst 0, skip 0 bytes')
telnet_p.pexpect_proc.expect_exact('Targets connected.')
telnet_p.pexpect_proc.expect_exact('Targets disconnected.')
telnet_p.pexpect_proc.expect_exact('Tracing is STOPPED. Size is 9000 of 9000 @')
telnet_p.pexpect_proc.expect_exact('Data: blocks incomplete 0, lost bytes: 0')
with ttfw_idf.CustomProcess(' '.join([os.path.join(idf_path, 'tools/esp_app_trace/logtrace_proc.py'),
'adc.log',
os.path.join(dut.app.get_binary_path(rel_project_path),
'app_trace_to_host.elf')]),
logfile='logtrace_proc.log') as logtrace:
logtrace.pexpect_proc.expect_exact('Parse trace file')
logtrace.pexpect_proc.expect_exact('Parsing completed.')
logtrace.pexpect_proc.expect_exact('====================================================================')
logtrace.pexpect_proc.expect(re.compile(r'example: Sample:\d+, Value:\d+'))
logtrace.pexpect_proc.expect_exact('====================================================================')
logtrace.pexpect_proc.expect(re.compile(r'Log records count: \d+'))
if __name__ == '__main__':
test_examples_app_trace_to_host()

View File

@@ -0,0 +1,2 @@
idf_component_register(SRCS "app_trace_to_host_example_main.c"
INCLUDE_DIRS ".")

View File

@@ -0,0 +1,20 @@
menu "Example Configuration"
config CUSTOM_RTC_CLK_8M_DIV
bool "Set custom RTC 8 MHz clock divider to lower CW frequency (CHECK HELP FIRST)"
default "n"
help
Set custom / non standard divider for RTC 8 MHz clock.
This is to lower minimum frequency of cosine waveform generator (CW)
in order to provide sinusoidal signal at about 50 or 60 Hz.
WARNINIG: setting non standard divider for the RTC 8 MHz clock
will affect functionality of RTC peripherals other than CW.
This includes ADC sampling, and will in general make
all RTC register access slower.
DO NOT use this option / change default RTC 8 MHz clock divider
in your applications, if you are not sure what you are doing.
endmenu

View File

@@ -0,0 +1,125 @@
/* Application Trace to Host Example
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/task.h"
#include "esp_app_trace.h"
#include "esp_log.h"
#include "soc/rtc_periph.h"
#include "soc/sens_periph.h"
#include "driver/adc.h"
#include "driver/dac.h"
#define ADC1_TEST_CHANNEL (ADC1_CHANNEL_6)
#define TEST_SAMPLING_PERIOD 20
/*
* When setting custom divider of RTC 8 MHz clock in menuconfig,
* use the following values to set the CW frequency:
* ~ 50 Hz (entered below)
* RTC_CLK_8M_DIV 7
* CW_FREQUENCY_STEP 3
* ~ 60 Hz
* RTC_CLK_8M_DIV 1
* CW_FREQUENCY_STEP 1
*/
#ifdef CONFIG_CUSTOM_RTC_CLK_8M_DIV
#define RTC_CLK_8M_DIV 7
#define CW_FREQUENCY_STEP 3
#else
#define CW_FREQUENCY_STEP 1
#endif
static const char *TAG = "example";
/*
* Enable cosine waveform generator (CW)
* on channel 1 / GPIO25 to provide sinusoidal signal
* It can be used instead of a live signal for testing
* of speed of logging to the host
* sequentially with data retrieval from ADC
*/
static void enable_cosine_generator(void)
{
// Enable tone generator common to both DAC channels 1 and 2
SET_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_SW_TONE_EN);
// Enable / connect tone tone generator on / to channel 1
SET_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN1_M);
// Invert MSB, otherwise part of the waveform will be inverted
SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_INV1, 2, SENS_DAC_INV1_S);
// Set the frequency of waveform on CW output
#ifdef CONFIG_CUSTOM_RTC_CLK_8M_DIV
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, RTC_CLK_8M_DIV);
ESP_LOGI(TAG, "Custom divider of RTC 8 MHz clock has been set.");
#endif
SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL1_REG, SENS_SW_FSTEP, CW_FREQUENCY_STEP, SENS_SW_FSTEP_S);
dac_output_enable(DAC_CHANNEL_1);
}
/*
* Sample data an ADC1 channel 6 / GPIO34
* over specific 'sampling_period' in milliseconds.
* Print out sampling result using standard ESP_LOGI() function.
* Return the number of samples collected.
*/
static int adc1_sample_and_show(int sampling_period)
{
int i = 0;
uint32_t sampling_start = esp_log_timestamp();
do {
ESP_LOGI(TAG, "Sample:%d, Value:%d", ++i, adc1_get_raw(ADC1_TEST_CHANNEL));
} while (esp_log_timestamp() - sampling_start < sampling_period);
return i;
}
/*
* Main program loop that is sampling data on ADC
* and logging results with application tracing to the host
* as well as for comparison printing out sampling result to UART
*/
void app_main(void)
{
ESP_LOGI(TAG, "Enabling ADC1 on channel 6 / GPIO34.");
#if CONFIG_IDF_TARGET_ESP32
adc1_config_width(ADC_WIDTH_BIT_12);
#elif CONFIG_IDF_TARGET_ESP32S2
adc1_config_width(ADC_WIDTH_BIT_13);
#endif
adc1_config_channel_atten(ADC1_TEST_CHANNEL, ADC_ATTEN_DB_11);
ESP_LOGI(TAG, "Enabling CW generator on DAC channel 1 / GPIO25.");
enable_cosine_generator();
while (1) {
/*
* Logging with the Application Trace
*/
ESP_LOGI(TAG, "Sampling ADC and sending data to the host...");
// Route LOGx() to the host
esp_log_set_vprintf(esp_apptrace_vprintf);
int samples_collected = adc1_sample_and_show(TEST_SAMPLING_PERIOD);
// Route LOGx() back to UART
esp_log_set_vprintf(vprintf);
// Flush collected data to the host
esp_apptrace_flush(ESP_APPTRACE_DEST_TRAX, 100000);
ESP_LOGI(TAG, "Collected %d samples in %d ms.\n", samples_collected, TEST_SAMPLING_PERIOD);
/*
* Logging to UART
*/
ESP_LOGI(TAG, "Sampling ADC and sending data to the UART...");
samples_collected = adc1_sample_and_show(TEST_SAMPLING_PERIOD);
ESP_LOGI(TAG, "Collected %d samples in %d ms.\n", samples_collected, TEST_SAMPLING_PERIOD);
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}

View File

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

View File

@@ -0,0 +1 @@
CONFIG_CUSTOM_RTC_CLK_8M_DIV=y

View File

@@ -0,0 +1,5 @@
# Enable application tracing by default
CONFIG_APPTRACE_DEST_TRAX=y
CONFIG_APPTRACE_ENABLE=y
# Disable WiFi stack by default
CONFIG_WIFI_ENABLED=n