提交 1d759380 编写于 作者: M me-no-dev

Major IDF and Arduino Update

WiFi and BlueTooth can now be started and stopped at will.
basic functions added to esp32-hal to start and stop the BT radio
SimpleBLE class added to show the most basic functionality
Example to show how to switch between BT, WiFi or Both
上级 b5ac95b2
ARDUINO_LIB_DIRS := libraries/WiFi/src libraries/SPI/src libraries/Wire/src libraries/Preferences/src
ARDUINO_LIB_DIRS := libraries/WiFi/src libraries/SPI/src libraries/Wire/src libraries/Preferences/src libraries/SimpleBLE/src libraries/WiFiClientSecure/src
COMPONENT_ADD_INCLUDEDIRS := cores/esp32 variants/esp32 $(ARDUINO_LIB_DIRS)
COMPONENT_PRIV_INCLUDEDIRS := cores/esp32/libb64
......
// 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 "esp32-hal-bt.h"
#include "bt.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.h"
bool btStarted(){
return (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED);
}
bool btStart(){
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED){
return true;
}
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE){
esp_bt_controller_init();
while(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE){}
}
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED){
if (esp_bt_controller_enable(ESP_BT_MODE_BTDM)) {
log_e("BT Enable failed");
return false;
}
}
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED){
return true;
}
log_e("BT Start failed");
return false;
}
bool btStop(){
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE){
return true;
}
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED){
if (esp_bt_controller_disable(ESP_BT_MODE_BTDM)) {
log_e("BT Disable failed");
return false;
}
while(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED);
}
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED){
return true;
}
log_e("BT Stop failed");
return false;
}
// 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.
#ifndef _ESP32_ESP32_HAL_BT_H_
#define _ESP32_ESP32_HAL_BT_H_
#include "esp32-hal.h"
#ifdef __cplusplus
extern "C" {
#endif
bool btStarted();
bool btStart();
bool btStop();
#ifdef __cplusplus
}
#endif
#endif /* _ESP32_ESP32_HAL_BT_H_ */
......@@ -19,49 +19,6 @@
#include "esp_attr.h"
#include "nvs_flash.h"
#if !CONFIG_ESP32_PHY_AUTO_INIT
#include "esp_phy_init.h"
#include "rom/rtc.h"
void arduino_phy_init()
{
static bool initialized = false;
if(initialized){
return;
}
esp_phy_calibration_mode_t calibration_mode = PHY_RF_CAL_PARTIAL;
if (rtc_get_reset_reason(0) == DEEPSLEEP_RESET) {
calibration_mode = PHY_RF_CAL_NONE;
}
const esp_phy_init_data_t* init_data = esp_phy_get_init_data();
if (init_data == NULL) {
printf("failed to obtain PHY init data\n");
abort();
}
esp_phy_calibration_data_t* cal_data =
(esp_phy_calibration_data_t*) calloc(sizeof(esp_phy_calibration_data_t), 1);
if (cal_data == NULL) {
printf("failed to allocate memory for RF calibration data\n");
abort();
}
esp_err_t err = esp_phy_load_cal_data_from_nvs(cal_data);
if (err != ESP_OK) {
printf("failed to load RF calibration data, falling back to full calibration\n");
calibration_mode = PHY_RF_CAL_FULL;
}
esp_phy_init(init_data, calibration_mode, cal_data);
if (calibration_mode != PHY_RF_CAL_NONE) {
err = esp_phy_store_cal_data_to_nvs(cal_data);
} else {
err = ESP_OK;
}
esp_phy_release_init_data(init_data);
free(cal_data); // PHY maintains a copy of calibration data, so we can free this
initialized = true;
}
#endif
void yield()
{
vPortYield();
......@@ -106,18 +63,10 @@ void initVariant() {}
void init() __attribute__((weak));
void init() {}
void initWiFi() __attribute__((weak));
void initWiFi() {}
void initBT() __attribute__((weak));
void initBT() {}
void initArduino(){
nvs_flash_init();
init();
initVariant();
initWiFi();
initBT();
}
//used by hal log
......
......@@ -58,6 +58,7 @@ void yield(void);
#include "esp32-hal-ledc.h"
#include "esp32-hal-sigmadelta.h"
#include "esp32-hal-timer.h"
#include "esp32-hal-bt.h"
#include "esp_system.h"
uint32_t micros();
......
// 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.
// Sketch shows how SimpleBLE to advertise the name of the device and change it on button press
// Usefull if you want to advertise some short message
// Button is attached between GPIO 0 and GND and modes are switched with each press
#include "SimpleBLE.h"
SimpleBLE ble;
void onButton(){
String out = "BLE32 at: ";
out += String(millis() / 1000);
Serial.println(out);
ble.begin(out);
}
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
pinMode(0, INPUT_PULLUP);
Serial.print("ESP32 SDK: ");
Serial.println(ESP.getSdkVersion());
ble.begin("ESP32 SimpleBLE");
Serial.println("Press the button to change the device name");
}
void loop() {
static uint8_t lastPinState = 1;
uint8_t pinState = digitalRead(0);
if(!pinState && lastPinState){
onButton();
}
lastPinState = pinState;
while(Serial.available()) Serial.write(Serial.read());
}
name=SimpleBLE
version=1.0
author=Hristo Gochkov
maintainer=Hristo Gochkov <hristo@espressif.com>
sentence=Provides really simple BLE advertizer with just on and off
paragraph=
category=Communication
url=
architectures=esp32
// 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 "SimpleBLE.h"
#include "esp32-hal-log.h"
/* HCI Command opcode group field(OGF) */
#define HCI_GRP_HOST_CONT_BASEBAND_CMDS (0x03 << 10) /* 0x0C00 */
#define HCI_GRP_BLE_CMDS (0x08 << 10)
/* HCI Command opcode command field(OCF) */
#define HCI_RESET (0x0003 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_BLE_WRITE_ADV_ENABLE (0x000A | HCI_GRP_BLE_CMDS)
#define HCI_BLE_WRITE_ADV_PARAMS (0x0006 | HCI_GRP_BLE_CMDS)
#define HCI_BLE_WRITE_ADV_DATA (0x0008 | HCI_GRP_BLE_CMDS)
#define HCI_H4_CMD_PREAMBLE_SIZE (4)
#define HCIC_PARAM_SIZE_WRITE_ADV_ENABLE (1)
#define HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS (15)
#define HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA (31)
/* EIR/AD data type definitions */
#define BT_DATA_FLAGS 0x01 /* AD flags */
#define BT_DATA_UUID16_SOME 0x02 /* 16-bit UUID, more available */
#define BT_DATA_UUID16_ALL 0x03 /* 16-bit UUID, all listed */
#define BT_DATA_UUID32_SOME 0x04 /* 32-bit UUID, more available */
#define BT_DATA_UUID32_ALL 0x05 /* 32-bit UUID, all listed */
#define BT_DATA_UUID128_SOME 0x06 /* 128-bit UUID, more available */
#define BT_DATA_UUID128_ALL 0x07 /* 128-bit UUID, all listed */
#define BT_DATA_NAME_SHORTENED 0x08 /* Shortened name */
#define BT_DATA_NAME_COMPLETE 0x09 /* Complete name */
#define BT_DATA_TX_POWER 0x0a /* Tx Power */
#define BT_DATA_SOLICIT16 0x14 /* Solicit UUIDs, 16-bit */
#define BT_DATA_SOLICIT128 0x15 /* Solicit UUIDs, 128-bit */
#define BT_DATA_SVC_DATA16 0x16 /* Service data, 16-bit UUID */
#define BT_DATA_GAP_APPEARANCE 0x19 /* GAP appearance */
#define BT_DATA_SOLICIT32 0x1f /* Solicit UUIDs, 32-bit */
#define BT_DATA_SVC_DATA32 0x20 /* Service data, 32-bit UUID */
#define BT_DATA_SVC_DATA128 0x21 /* Service data, 128-bit UUID */
#define BT_DATA_MANUFACTURER_DATA 0xff /* Manufacturer Specific Data */
/* Advertising types */
#define BLE_GAP_ADV_TYPE_ADV_IND 0x00
#define BLE_GAP_ADV_TYPE_ADV_DIRECT_IND 0x01
#define BLE_GAP_ADV_TYPE_ADV_SCAN_IND 0x02
#define BLE_GAP_ADV_TYPE_ADV_NONCONN_IND 0x03
/* Advertising Discovery Flags */
#define BLE_GAP_ADV_FLAG_LE_LIMITED_DISC_MODE (0x01)
#define BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE (0x02)
#define BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED (0x04)
#define BLE_GAP_ADV_FLAG_LE_BR_EDR_CONTROLLER (0x08)
#define BLE_GAP_ADV_FLAG_LE_BR_EDR_HOST (0x10)
#define BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE (BLE_GAP_ADV_FLAG_LE_LIMITED_DISC_MODE | BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED)
#define BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE (BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE | BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED)
/* Advertising Filter Policies */
#define BLE_GAP_ADV_FP_ANY 0x00
#define BLE_GAP_ADV_FP_FILTER_SCANREQ 0x01
#define BLE_GAP_ADV_FP_FILTER_CONNREQ 0x02
#define BLE_GAP_ADV_FP_FILTER_BOTH 0x03
/* Advertising Device Address Types */
#define BLE_GAP_ADDR_TYPE_PUBLIC 0x00
#define BLE_GAP_ADDR_TYPE_RANDOM_STATIC 0x01
#define BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE 0x02
#define BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE 0x03
/* GAP Advertising Channel Maps */
#define GAP_ADVCHAN_37 0x01
#define GAP_ADVCHAN_38 0x02
#define GAP_ADVCHAN_39 0x04
#define GAP_ADVCHAN_ALL GAP_ADVCHAN_37 | GAP_ADVCHAN_38 | GAP_ADVCHAN_39
/* GAP Filter Policies */
#define BLE_GAP_ADV_FP_ANY 0x00
#define BLE_GAP_ADV_FP_FILTER_SCANREQ 0x01
#define BLE_GAP_ADV_FP_FILTER_CONNREQ 0x02
#define BLE_GAP_ADV_FP_FILTER_BOTH 0x03
#define BD_ADDR_LEN (6) /* Device address length */
/*
* BLE System
*
* */
/* HCI H4 message type definitions */
enum {
H4_TYPE_COMMAND = 1,
H4_TYPE_ACL = 2,
H4_TYPE_SCO = 3,
H4_TYPE_EVENT = 4
};
volatile bool _vhci_host_send_available = false;
volatile bool _vhci_host_command_running = false;
static uint16_t _vhci_host_command = 0x0000;
static uint8_t _vhci_host_command_result = 0x00;
//controller is ready to receive command
static void _on_tx_ready(void)
{
_vhci_host_send_available = true;
}
/*
static void _dump_buf(const char * txt, uint8_t *data, uint16_t len){
log_printf("%s[%u]:", txt, len);
for (uint16_t i=0; i<len; i++)
log_printf(" %02x", data[i]);
log_printf("\n");
}
*/
//controller has a packet
static int _on_rx_data(uint8_t *data, uint16_t len)
{
if(len == 7 && *data == 0x04){
//baseband response
uint16_t cmd = (((uint16_t)data[5] << 8) | data[4]);
uint8_t res = data[6];
if(_vhci_host_command_running && _vhci_host_command == cmd){
//_dump_buf("BLE: res", data, len);
_vhci_host_command_result = res;
_vhci_host_command_running = false;
return 0;
} else if(cmd == 0){
log_e("error %u", res);
}
}
//_dump_buf("BLE: rx", data, len);
return 0;
}
static esp_vhci_host_callback_t vhci_host_cb = {
_on_tx_ready,
_on_rx_data
};
static bool _esp_ble_start()
{
if(btStart()){
esp_vhci_host_register_callback(&vhci_host_cb);
uint8_t i = 0;
while(!esp_vhci_host_check_send_available() && i++ < 100){
delay(10);
}
if(i >= 100){
log_e("esp_vhci_host_check_send_available failed");
return false;
}
_vhci_host_send_available = true;
} else
log_e("BT Failed");
return true;
}
static bool _esp_ble_stop()
{
if(btStarted()){
_vhci_host_send_available = false;
btStop();
esp_vhci_host_register_callback(NULL);
}
return true;
}
//public
static uint8_t ble_send_cmd(uint16_t cmd, uint8_t * data, uint8_t len){
static uint8_t buf[36];
if(len > 32){
//too much data
return 2;
}
uint16_t i = 0;
while(!_vhci_host_send_available && i++ < 1000){
delay(1);
}
if(i >= 1000){
log_e("_vhci_host_send_available failed");
return 1;
}
uint8_t outlen = len + HCI_H4_CMD_PREAMBLE_SIZE;
buf[0] = H4_TYPE_COMMAND;
buf[1] = (uint8_t)(cmd & 0xFF);
buf[2] = (uint8_t)(cmd >> 8);
buf[3] = len;
if(len){
memcpy(buf+4, data, len);
}
_vhci_host_send_available = false;
_vhci_host_command_running = true;
_vhci_host_command = cmd;
//log_printf("BLE: cmd: 0x%04X, data[%u]:", cmd, len);
//for (uint16_t i=0; i<len; i++) log_printf(" %02x", buf[i+4]);
//log_printf("\n");
esp_vhci_host_send_packet(buf, outlen);
while(_vhci_host_command_running);
int res = _vhci_host_command_result;
//log_printf("BLE: cmd: 0x%04X, res: %u\n", cmd, res);
return res;
}
/*
* BLE Arduino
*
* */
enum {
UNIT_0_625_MS = 625, /* Number of microseconds in 0.625 milliseconds. */
UNIT_1_25_MS = 1250, /* Number of microseconds in 1.25 milliseconds. */
UNIT_10_MS = 10000 /* Number of microseconds in 10 milliseconds. */
};
/* BLE Advertising parameters struct */
typedef struct ble_gap_adv_params_s {
uint8_t type;
uint8_t own_addr_type;
uint8_t addr_type;
uint8_t addr[BD_ADDR_LEN];
uint8_t fp; // filter policy
uint16_t interval_min; // minimum advertising interval between 0x0020 and 0x4000 in 0.625 ms units (20ms to 10.24s)
uint16_t interval_max;
uint8_t chn_map;
} ble_adv_params_t;
#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION))
#define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);}
#define UINT8_TO_STREAM(p, u8) {*(p)++ = (uint8_t)(u8);}
#define BDADDR_TO_STREAM(p, a) {int i; for (i = 0; i < BD_ADDR_LEN; i++) *(p)++ = (uint8_t) a[BD_ADDR_LEN - 1 - i];}
#define ARRAY_TO_STREAM(p, a, len) {int i; for (i = 0; i < len; i++) *(p)++ = (uint8_t) a[i];}
SimpleBLE::SimpleBLE()
{
uint8_t peerAddr[BD_ADDR_LEN] = {0x80, 0x81, 0x82, 0x83, 0x84, 0x85};
_ble_adv_param = (ble_adv_params_t*)malloc(sizeof(ble_adv_params_t));
memset(_ble_adv_param, 0x00, sizeof(ble_adv_params_t));
_ble_adv_param->type = BLE_GAP_ADV_TYPE_ADV_NONCONN_IND;//not connectable
_ble_adv_param->chn_map = GAP_ADVCHAN_ALL; // 37, 38, 39 channels
_ble_adv_param->fp = 0;//any
_ble_adv_param->interval_min = 512;
_ble_adv_param->interval_max = 1024;
_ble_adv_param->addr_type = 0;//public
memcpy(_ble_adv_param->addr, peerAddr, BD_ADDR_LEN);
local_name = "esp32";
}
SimpleBLE::~SimpleBLE(void)
{
free(_ble_adv_param);
_esp_ble_stop();
}
bool SimpleBLE::begin(String localName)
{
if(!_esp_ble_start()){
return false;
}
ble_send_cmd(HCI_RESET, NULL, 0);
if(localName.length()){
local_name = localName;
}
_ble_send_adv_param();
_ble_send_adv_data();
uint8_t adv_enable = 1;
ble_send_cmd(HCI_BLE_WRITE_ADV_ENABLE, &adv_enable, HCIC_PARAM_SIZE_WRITE_ADV_ENABLE);
return true;
}
void SimpleBLE::end()
{
uint8_t adv_enable = 0;
ble_send_cmd(HCI_BLE_WRITE_ADV_ENABLE, &adv_enable, HCIC_PARAM_SIZE_WRITE_ADV_ENABLE);
ble_send_cmd(HCI_RESET, NULL, 0);
_esp_ble_stop();
}
void SimpleBLE::_ble_send_adv_param(void)
{
uint8_t dbuf[HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS];
uint8_t *buf = dbuf;
UINT16_TO_STREAM (buf, _ble_adv_param->interval_min);
UINT16_TO_STREAM (buf, _ble_adv_param->interval_max);
UINT8_TO_STREAM (buf, _ble_adv_param->type);
UINT8_TO_STREAM (buf, _ble_adv_param->own_addr_type);
UINT8_TO_STREAM (buf, _ble_adv_param->addr_type);
ARRAY_TO_STREAM (buf, _ble_adv_param->addr, BD_ADDR_LEN);
UINT8_TO_STREAM (buf, _ble_adv_param->chn_map);
UINT8_TO_STREAM (buf, _ble_adv_param->fp);
ble_send_cmd(HCI_BLE_WRITE_ADV_PARAMS, dbuf, HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS);
}
void SimpleBLE::_ble_send_adv_data(void)
{
uint8_t adv_data[HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1] = {
0x03, 0x02, BT_DATA_FLAGS, BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE
};
//zerofill the buffer
memset(adv_data+4, 0x00, HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA-4);
uint8_t adv_data_len = 4;
// Advertising data device local name
uint8_t name_len = (uint8_t) local_name.length();
adv_data[adv_data_len++] = name_len + 1;
adv_data[adv_data_len++] = BT_DATA_NAME_COMPLETE;
for (int i=0; i<name_len; i++) {
adv_data[adv_data_len++] = (uint8_t) local_name.charAt(i);
}
//send data
adv_data[0] = adv_data_len - 1;
ble_send_cmd(HCI_BLE_WRITE_ADV_DATA, (uint8_t *)adv_data, HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1);
}
// 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.
#ifndef _SIMPLE_BLE_H_
#define _SIMPLE_BLE_H_
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "bt.h"
#include "Arduino.h"
struct ble_gap_adv_params_s;
class SimpleBLE {
public:
SimpleBLE(void);
~SimpleBLE(void);
/**
* Start BLE Advertising
*
* @param[in] localName local name to advertise
*
* @return true on success
*
*/
bool begin(String localName=String());
/**
* Stop BLE Advertising
*
* @return none
*/
void end(void);
private:
struct ble_gap_adv_params_s * _ble_adv_param;
String local_name;
void _ble_send_adv_param(void);
void _ble_send_adv_data(void);
private:
};
#endif
// 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.
// Sketch shows how to switch between WiFi and BlueTooth or use both
// Button is attached between GPIO 0 and GND and modes are switched with each press
#include "WiFi.h"
#define STA_SSID "your-ssid"
#define STA_PASS "your-pass"
#define AP_SSID "esp32"
enum { STEP_BTON, STEP_BTOFF, STEP_STA, STEP_AP, STEP_AP_STA, STEP_OFF, STEP_BT_STA, STEP_END };
void onButton(){
static uint32_t step = STEP_BTON;
switch(step){
case STEP_BTON://BT Only
Serial.println("** Starting BT");
btStart();
break;
case STEP_BTOFF://All Off
Serial.println("** Stopping BT");
btStop();
break;
case STEP_STA://STA Only
Serial.println("** Starting STA");
WiFi.begin(STA_SSID, STA_PASS);
break;
case STEP_AP://AP Only
Serial.println("** Stopping STA");
WiFi.mode(WIFI_AP);
Serial.println("** Starting AP");
WiFi.softAP(AP_SSID);
break;
case STEP_AP_STA://AP+STA
Serial.println("** Starting STA");
WiFi.begin(STA_SSID, STA_PASS);
break;
case STEP_OFF://All Off
Serial.println("** Stopping WiFi");
WiFi.mode(WIFI_OFF);
break;
case STEP_BT_STA://BT+STA
Serial.println("** Starting STA+BT");
WiFi.begin(STA_SSID, STA_PASS);
btStart();
break;
case STEP_END://All Off
Serial.println("** Stopping WiFi+BT");
WiFi.mode(WIFI_OFF);
btStop();
break;
default:
break;
}
if(step == STEP_END){
step = STEP_BTON;
} else {
step++;
}
//little debounce
delay(100);
}
void WiFiEvent(WiFiEvent_t event){
switch(event) {
case SYSTEM_EVENT_AP_START:
Serial.println("AP Started");
WiFi.softAPsetHostname(AP_SSID);
break;
case SYSTEM_EVENT_AP_STOP:
Serial.println("AP Stopped");
break;
case SYSTEM_EVENT_STA_START:
Serial.println("STA Started");
WiFi.setHostname(AP_SSID);
break;
case SYSTEM_EVENT_STA_CONNECTED:
Serial.println("STA Connected");
WiFi.enableIpV6();
break;
case SYSTEM_EVENT_AP_STA_GOT_IP6:
Serial.print("STA IPv6: ");
Serial.println(WiFi.localIPv6());
break;
case SYSTEM_EVENT_STA_GOT_IP:
Serial.print("STA IPv4: ");
Serial.println(WiFi.localIP());
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
Serial.println("STA Disconnected");
break;
case SYSTEM_EVENT_STA_STOP:
Serial.println("STA Stopped");
break;
default:
break;
}
}
void setup() {
Serial.begin(115200);
pinMode(0, INPUT_PULLUP);
WiFi.onEvent(WiFiEvent);
Serial.print("ESP32 SDK: ");
Serial.println(ESP.getSdkVersion());
Serial.println("Press the button to select the next mode");
}
void loop() {
static uint8_t lastPinState = 1;
uint8_t pinState = digitalRead(0);
if(!pinState && lastPinState){
onButton();
}
lastPinState = pinState;
}
......@@ -42,74 +42,70 @@ extern "C" {
#include "lwip/dns.h"
#include "esp_ipc.h"
#include "esp32-hal-log.h"
/**
* Boot and start WiFi
* This method get's called on boot if you use any of the WiFi methods.
* If you do not link to this library, WiFi will not be started.
* */
static bool _esp_wifi_initalized = false;
extern void initWiFi()
{
#if !CONFIG_ESP32_PHY_AUTO_INIT
arduino_phy_init();
#endif
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
tcpip_adapter_init();
esp_event_loop_init(&WiFiGenericClass::_eventCallback, NULL);
esp_wifi_init(&cfg);
esp_wifi_set_storage(WIFI_STORAGE_FLASH);
_esp_wifi_initalized = true;
}
} //extern "C"
#include "esp32-hal-log.h"
#undef min
#undef max
#include <vector>
static bool _esp_wifi_start()
{
static bool started = false;
esp_err_t err;
if(!_esp_wifi_initalized){
initWiFi();
if(!_esp_wifi_initalized){
log_w("not initialized");
static bool wifiLowLevelInit(){
static bool lowLevelInitDone = false;
if(!lowLevelInitDone){
tcpip_adapter_init();
esp_event_loop_init(&WiFiGenericClass::_eventCallback, NULL);
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_err_t err = esp_wifi_init(&cfg);
if(err){
log_e("esp_wifi_init %d", err);
return false;
}
esp_wifi_set_storage(WIFI_STORAGE_FLASH);
esp_wifi_set_mode(WIFI_MODE_NULL);
lowLevelInitDone = true;
}
if(started){
return true;
}
static bool wifiLowLevelDeinit(){
//deinit not working yet!
//esp_wifi_deinit();
return true;
}
static bool _esp_wifi_started = false;
static bool espWiFiStart(){
if(_esp_wifi_started){
return true;
}
started = true;
err = esp_wifi_start();
if (err != ESP_OK) {
log_e("%d", err);
if(!wifiLowLevelInit()){
return false;
}
#if CONFIG_AUTOCONNECT_WIFI
wifi_mode_t mode = WIFI_MODE_NULL;
bool auto_connect = false;
err = esp_wifi_get_mode(&mode);
esp_err_t err = esp_wifi_start();
if (err != ESP_OK) {
log_e("esp_wifi_get_mode: %d", err);
log_e("esp_wifi_start %d", err);
wifiLowLevelDeinit();
return false;
}
_esp_wifi_started = true;
return true;
}
err = esp_wifi_get_auto_connect(&auto_connect);
if ((mode == WIFI_MODE_STA || mode == WIFI_MODE_APSTA) && auto_connect) {
err = esp_wifi_connect();
if (err != ESP_OK) {
log_e("esp_wifi_connect: %d", err);
return false;
}
static bool espWiFiStop(){
esp_err_t err;
if(!_esp_wifi_started){
return true;
}
#endif
return true;
err = esp_wifi_stop();
if(err){
log_e("Could not stop WiFi! %u", err);
return false;
}
_esp_wifi_started = false;
return wifiLowLevelDeinit();
}
// -----------------------------------------------------------------------------------------------------------------------
......@@ -246,7 +242,16 @@ bool WiFiGenericClass::mode(wifi_mode_t m)
if(cm == m) {
return true;
}
return esp_wifi_set_mode(m) == ESP_OK;
esp_err_t err;
err = esp_wifi_set_mode(m);
if(err){
log_e("Could not set mode! %u", err);
return false;
}
if(m){
return espWiFiStart();
}
return espWiFiStop();
}
/**
......@@ -255,10 +260,10 @@ bool WiFiGenericClass::mode(wifi_mode_t m)
*/
wifi_mode_t WiFiGenericClass::getMode()
{
uint8_t mode;
if(!_esp_wifi_start()){
if(!wifiLowLevelInit()){
return WIFI_MODE_MAX;
}
uint8_t mode;
esp_wifi_get_mode((wifi_mode_t*)&mode);
return (wifi_mode_t)mode;
}
......
......@@ -30,7 +30,7 @@ compiler.S.flags=-c -g3 -x assembler-with-cpp -MMD -mlongcalls
compiler.c.elf.cmd=xtensa-esp32-elf-gcc
compiler.c.elf.flags=-nostdlib "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" -T esp32_out.ld -T esp32.common.ld -T esp32.rom.ld -T esp32.peripherals.ld -u call_user_start_cpu0 -Wl,--gc-sections -Wl,-static -Wl,--undefined=uxTopUsedPriority
compiler.c.elf.libs=-lgcc -lstdc++ -lapp_update -lbootloader_support -lbt -lbtdm_app -lc -lc_nano -lcoap -lcoexist -lcore -lcxx -ldriver -lesp32 -lethernet -lexpat -lfatfs -lfreertos -lhal -ljson -llog -llwip -lm -lmbedtls -lmdns -lmicro-ecc -lnet80211 -lnewlib -lnghttp -lnvs_flash -lopenssl -lphy -lpp -lrtc -lsdmmc -lsmartconfig -lspi_flash -ltcpip_adapter -lulp -lvfs -lwpa -lwpa2 -lwpa_supplicant -lwps -lxtensa-debug-module
compiler.c.elf.libs=-lgcc -lstdc++ -lapp_update -lbootloader_support -lbt -lbtdm_app -lc -lc_nano -lcoap -lcoexist -lcore -lcxx -ldriver -lesp32 -lethernet -lexpat -lfatfs -lfreertos -lhal -ljson -llog -llwip -lm -lmbedtls -lmdns -lmicro-ecc -lnet80211 -lnewlib -lnghttp -lnvs_flash -lopenssl -lphy -lpp -lrtc -lrtc_clk -lsdmmc -lsmartconfig -lspi_flash -ltcpip_adapter -lulp -lvfs -lwpa -lwpa2 -lwpa_supplicant -lwps -lxtensa-debug-module
compiler.as.cmd=xtensa-esp32-elf-as
......
......@@ -4,9 +4,12 @@
#
# Converts partition tables to/from CSV and binary formats.
#
# See the sdkng README.md file for details about how to use this tool.
import struct
# See http://esp-idf.readthedocs.io/en/latest/partition-tables.html for explanation of
# partition table structure and uses.
import argparse
import os
import re
import struct
import sys
MAX_PARTITION_LENGTH = 0xC00 # 3K for partition data (96 entries) leaves 1K in a 4K sector for signature
......@@ -163,7 +166,13 @@ class PartitionDefinition(object):
def from_csv(cls, line):
""" Parse a line from the CSV """
line_w_defaults = line + ",,,," # lazy way to support default fields
fields = [ f.strip() for f in line_w_defaults.split(",") ]
def expand_vars(f):
f = os.path.expandvars(f)
m = re.match(r'(?<!\\)\$([A-Za-z_][A-Za-z0-9_]*)', f)
if m:
raise InputError("unknown variable '%s'" % m.group(1))
return f
fields = [ expand_vars(f.strip()) for f in line_w_defaults.split(",") ]
res = PartitionDefinition()
res.name = fields[0]
......@@ -346,5 +355,5 @@ if __name__ == '__main__':
try:
main()
except InputError as e:
print(e)
print >>sys.stderr, e
sys.exit(2)
......@@ -87,7 +87,7 @@ env.Prepend(
],
LIBS=[
"gcc", "stdc++", "app_update", "bootloader_support", "bt", "btdm_app", "c", "c_nano", "coap", "coexist", "core", "cxx", "driver", "esp32", "ethernet", "expat", "fatfs", "freertos", "hal", "json", "log", "lwip", "m", "mbedtls", "mdns", "micro-ecc", "net80211", "newlib", "nghttp", "nvs_flash", "openssl", "phy", "pp", "rtc", "sdmmc", "smartconfig", "spi_flash", "tcpip_adapter", "ulp", "vfs", "wpa", "wpa2", "wpa_supplicant", "wps", "xtensa-debug-module"
"gcc", "stdc++", "app_update", "bootloader_support", "bt", "btdm_app", "c", "c_nano", "coap", "coexist", "core", "cxx", "driver", "esp32", "ethernet", "expat", "fatfs", "freertos", "hal", "json", "log", "lwip", "m", "mbedtls", "mdns", "micro-ecc", "net80211", "newlib", "nghttp", "nvs_flash", "openssl", "phy", "pp", "rtc", "rtc_clk", "sdmmc", "smartconfig", "spi_flash", "tcpip_adapter", "ulp", "vfs", "wpa", "wpa2", "wpa_supplicant", "wps", "xtensa-debug-module"
],
UPLOADERFLAGS=[
......
......@@ -23,14 +23,63 @@
extern "C" {
#endif
/**
* @brief Bluetooth mode for controller enable/disable
*/
typedef enum {
ESP_BT_MODE_ILDE = 0x00, /*!< Bluetooth is not run */
ESP_BT_MODE_BLE = 0x01, /*!< Run BLE mode */
ESP_BT_MODE_CLASSIC_BT = 0x02, /*!< Run Classic BT mode */
ESP_BT_MODE_BTDM = 0x03, /*!< Run dual mode */
} esp_bt_mode_t;
/**
* @brief Bluetooth controller enable/disable/initialised/de-initialised status
*/
typedef enum {
ESP_BT_CONTROLLER_STATUS_IDLE = 0,
ESP_BT_CONTROLLER_STATUS_INITED,
ESP_BT_CONTROLLER_STATUS_ENABLED,
ESP_BT_CONTROLLER_STATUS_NUM,
} esp_bt_controller_status_t;
/**
* @brief Initialize BT controller
* @brief Initialize BT controller to allocate task and other resource.
*
* This function should be called only once, before any other BT functions are called.
*/
void esp_bt_controller_init(void);
/**
* @brief De-initialize BT controller to free resource and delete task.
*
* This function should be called only once, after any other BT functions are called.
* This function is not whole completed, esp_bt_controller_init cannot called after this function.
*/
void esp_bt_controller_deinit(void);
/**
* @brief Enable BT controller
* @param mode : the mode(BLE/BT/BTDM) to enable.
* Now only support BTDM.
* @return ESP_OK - success, other - failed
*/
esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode);
/**
* @brief Disable BT controller
* @param mode : the mode(BLE/BT/BTDM) to disable.
* Now only support BTDM.
* @return ESP_OK - success, other - failed
*/
esp_err_t esp_bt_controller_disable(esp_bt_mode_t mode);
/**
* @brief Get BT controller is initialised/de-initialised/enabled/disabled
* @return status value
*/
esp_bt_controller_status_t esp_bt_controller_get_status(void);
/** @brief esp_vhci_host_callback
* used for vhci call host function to notify what host need to do
*/
......
......@@ -66,6 +66,7 @@
#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 240
#define CONFIG_MBEDTLS_HARDWARE_AES 1
#define CONFIG_FREERTOS_HZ 1000
#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1
#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1
#define CONFIG_MONITOR_BAUD_115200B 1
#define CONFIG_LOG_BOOTLOADER_LEVEL 1
......
......@@ -49,11 +49,11 @@ typedef enum {
} adc1_channel_t;
/**
* @brief Configuration ADC1 capture width.
* @brief Configure ADC1 capture width.
*
* The configuration is in effect for all channels of ADC1
* The configuration is for all channels of ADC1
*
* @param width_bit ADC1
* @param width_bit Bit capture width for ADC1
*
* @return
* - ESP_OK success
......@@ -62,10 +62,29 @@ typedef enum {
esp_err_t adc1_config_width(adc_bits_width_t width_bit);
/**
* @brief Configuration ADC1 capture attenuation of channels.
* @brief Configure the ADC1 channel, including setting attenuation.
*
* @param channel the ADC1 channel
* @param atten attenuation
* @note This function also configures the input GPIO pin mux to
* connect it to the ADC1 channel. It must be called before calling
* adc1_get_voltage() for this channel.
*
* The default ADC full-scale voltage is 1.1V. To read higher voltages (up to the pin maximum voltage,
* usually 3.3V) requires setting >0dB signal attenuation for that ADC channel.
*
* When VDD_A is 3.3V:
*
* - 0dB attenuaton (ADC_ATTEN_0db) gives full-scale voltage 1.1V
* - 2.5dB attenuation (ADC_ATTEN_2_5db) gives full-scale voltage 1.5V
* - 6dB attenuation (ADC_ATTEN_6db) gives full-scale voltage 2.2V
* - 11dB attenuation (ADC_ATTEN_11db) gives full-scale voltage 3.9V (see note below)
*
* @note The full-scale voltage is the voltage corresponding to a maximum reading (depending on ADC1 configured
* bit width, this value is: 4095 for 12-bits, 2047 for 11-bits, 1023 for 10-bits, 511 for 9 bits.)
*
* @note At 11dB attenuation the maximum voltage is limited by VDD_A, not the full scale voltage.
*
* @param channel ADC1 channel to configure
* @param atten Attenuation level
*
* @return
* - ESP_OK success
......@@ -74,46 +93,38 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit);
esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten);
/**
* @brief ADC1 get the value of the voltage.
* @brief Take an ADC1 reading on a single channel
*
* @note Call adc1_config_width() before the first time this
* function is called.
*
* @note For a given channel, adc1_config_channel_atten(channel)
* must be called before the first time this function is called.
*
* @param channel the ADC1 channel
* @param channel ADC1 channel to read
*
* @return
* - -1 Parameter error
* - Other the value of ADC1 channel
* - -1: Parameter error
* - Other: ADC1 channel reading.
*/
int adc1_get_voltage(adc1_channel_t channel);
/**
* @brief Hall Sensor output value.
* @note
* The Hall Sensor uses Channel_0 and Channel_3 of ADC1.
* So, firstly: please configure ADC1 module by calling adc1_config_width before calling hall_sensor_read.
We recommend that the WIDTH ADC1 be configured as 12Bit, because the values of hall_sensor_read are small and almost the same if WIDTH ADC1 is configured as 9Bit, 10Bit or 11Bit.
* secondly: when you use the hall sensor, please do not use Channel_0 and Channel_3 of ADC1 as
* ADC channels.
*
* @return the value of hall sensor
* @brief Read Hall Sensor
*
* @note The Hall Sensor uses channels 0 and 3 of ADC1. Do not configure
* these channels for use as ADC channels.
*
* @note The ADC1 module must be enabled by calling
* adc1_config_width() before calling hall_sensor_read(). ADC1
* should be configured for 12 bit readings, as the hall sensor
* readings are low values and do not cover the full range of the
* ADC.
*
* @return The hall sensor reading.
*/
int hall_sensor_read();
/**
*----------EXAMPLE TO USE ADC1------------ *
* @code{c}
* adc1_config_width(ADC_WIDTH_12Bit);//config adc1 width
* adc1_config_channel_atten(ADC1_CHANNEL_0,ADC_ATTEN_0db);//config channel0 attenuation
* int val=adc1_get_voltage(ADC1_CHANNEL_0);//get the val of channel0
* @endcode
**/
/**
*----------EXAMPLE TO USE HALL SENSOR------------ *
* @code{c}
* adc1_config_width(ADC_WIDTH_12Bit);//config adc1 width
* int val=hall_sensor_read();
* @endcode
**/
#ifdef __cplusplus
}
#endif
......
......@@ -29,12 +29,15 @@ typedef enum {
} dac_channel_t;
/**
* @brief Set Dac output voltage.
* @brief Set DAC output voltage.
*
* Dac width is 8bit ,and the voltage max is vdd
* DAC output is 8-bit. Maximum (255) corresponds to VDD.
*
* @param channel dac channel
* @param dac_value dac output value
* @note When this function is called, function for the DAC
* channel's GPIO pin is reconfigured for RTC DAC function.
*
* @param channel DAC channel
* @param dac_value DAC output value
*
* @return
* - ESP_OK success
......@@ -42,13 +45,6 @@ typedef enum {
*/
esp_err_t dac_out_voltage(dac_channel_t channel, uint8_t dac_value);
/**
*----------EXAMPLE TO USE DAC------------ *
* @code{c}
* dac_out_voltage(DAC_CHANNEL_1,200);//the dac out voltage ≈ 200*vdd/255
* @endcode
**/
#ifdef __cplusplus
}
#endif
......
......@@ -302,9 +302,9 @@ int gpio_get_level(gpio_num_t gpio_num);
esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode);
/**
* @brief GPIO set pull
* @brief Configure GPIO pull-up/pull-down resistors
*
* User this Function,configure GPIO pull mode,such as pull-up,pull-down
* Only pins that support both input & output have integrated pull-up and pull-down resistors. Input-only GPIOs 34-39 do not.
*
* @param gpio_num GPIO number. If you want to set pull up or down mode for e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
* @param pull GPIO pull up/down mode.
......@@ -317,7 +317,7 @@ esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode);
esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull);
/**
* @brief enable GPIO wake-up function.
* @brief Enable GPIO wake-up function.
*
* @param gpio_num GPIO number.
*
......@@ -341,15 +341,23 @@ esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type);
esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num);
/**
* @brief register GPIO interrupt handler, the handler is an ISR.
* @brief Register GPIO interrupt handler, the handler is an ISR.
* The handler will be attached to the same CPU core that this function is running on.
*
* This ISR function is called whenever any GPIO interrupt occurs. See
* the alternative gpio_install_isr_service() and
* gpio_isr_handler_add() API in order to have the driver support
* per-GPIO ISRs.
*
* @param fn Interrupt handler function.
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
* @param arg Parameter for handler function
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
* be returned here.
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will be returned here.
*
* \verbatim embed:rst:leading-asterisk
* To disable or remove the ISR, pass the returned handle to the :doc:`interrupt allocation functions </api/system/intr_alloc>`.
* \endverbatim
*
* @return
* - ESP_OK Success ;
......@@ -402,7 +410,9 @@ esp_err_t gpio_pulldown_en(gpio_num_t gpio_num);
esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num);
/**
* @brief Install a GPIO ISR service, so we can assign different ISR handler for different pins
* @brief Install the driver's GPIO ISR handler service, which allows per-pin GPIO interrupt handlers.
*
* This function is incompatible with gpio_isr_register() - if that function is used, a single global ISR is registered for all GPIO interrupts. If this function is used, the ISR service provides a global GPIO ISR and individual pin handlers are registered via the gpio_isr_register() function.
*
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
......@@ -415,17 +425,24 @@ esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num);
esp_err_t gpio_install_isr_service(int intr_alloc_flags);
/**
* @brief Un-install GPIO ISR service, free the resources.
* @brief Uninstall the driver's GPIO ISR service, freeing related resources.
*/
void gpio_uninstall_isr_service();
/**
* @brief Add ISR handler for the corresponding GPIO.
* @brief Add ISR handler for the corresponding GPIO pin.
*
* Call this function after using gpio_install_isr_service() to
* install the driver's GPIO ISR handler service.
*
* The pin ISR handlers no longer need to be declared with IRAM_ATTR,
* unless you pass the ESP_INTR_FLAG_IRAM flag when allocating the
* ISR in gpio_install_isr_service().
*
* Interrupt handlers no longer need to be declared with IRAM_ATTR, unless you pass the ESP_INTR_FLAG_IRAM flag
* when allocating the ISR in gpio_install_isr_service().
* This ISR handler will be called from an ISR. So there probably is some stack size limit, and this limit
* is smaller compared to a "raw" interrupt handler due to another level of indirection.
* This ISR handler will be called from an ISR. So there is a stack
* size limit (configurable as "ISR stack size" in menuconfig). This
* limit is smaller compared to a global GPIO interrupt handler due
* to the additional level of indirection.
*
* @param gpio_num GPIO number
* @param isr_handler ISR handler function for the corresponding GPIO number.
......@@ -439,7 +456,7 @@ void gpio_uninstall_isr_service();
esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num, gpio_isr_t isr_handler, void* args);
/**
* @brief Remove ISR handler for the corresponding GPIO.
* @brief Remove ISR handler for the corresponding GPIO pin.
*
* @param gpio_num GPIO number
*
......
......@@ -32,9 +32,6 @@
extern "C" {
#endif
#define I2S_PIN_NO_CHANGE (-1)
/**
* @brief I2S bit width per sample.
*
......@@ -147,6 +144,8 @@ typedef struct {
size_t size; /*!< I2S data size for I2S_DATA event*/
} i2s_event_t;
#define I2S_PIN_NO_CHANGE (-1) /*!< Use in i2s_pin_config_t for pins which should not be changed */
/**
* @brief I2S pin number for i2s_set_pin
*
......@@ -160,15 +159,18 @@ typedef struct {
typedef intr_handle_t i2s_isr_handle_t;
/**
* @brief Set I2S pin number
* @brief Set I2S pin number
*
* @note
* Internal signal can be output to multiple GPIO pads
* Only one GPIO pad can connect with input signal
* @note
* The I2S peripheral output signals can be connected to multiple GPIO pads.
* However, the I2S peripheral input signal can only be connected to one GPIO pad.
*
* @param i2s_num I2S_NUM_0 or I2S_NUM_1
*
* @param pin I2S Pin struct, or NULL for 2-channels, 8-bits DAC pin configuration (GPIO25 & GPIO26)
* @param pin I2S Pin structure, or NULL to set 2-channel 8-bit internal DAC pin configuration (GPIO25 & GPIO26)
*
* Inside the pin configuration structure, set I2S_PIN_NO_CHANGE for any pin where
* the current configuration should not be changed.
*
* @return
* - ESP_OK Success
......@@ -177,15 +179,17 @@ typedef intr_handle_t i2s_isr_handle_t;
esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin);
/**
* @brief i2s install and start driver
* @brief Install and start I2S driver.
*
* @param i2s_num I2S_NUM_0, I2S_NUM_1
*
* @param i2s_num I2S_NUM_0, I2S_NUM_1
* @param i2s_config I2S configurations - see i2s_config_t struct
*
* @param i2s_config I2S configurations - see i2s_config_t struct
* @param queue_size I2S event queue size/depth.
*
* @param queue_size I2S event queue size/depth.
* @param i2s_queue I2S event queue handle, if set NULL, driver will not use an event queue.
*
* @param i2s_queue I2S event queue handle, if set NULL, driver will not use an event queue.
* This function must be called before any I2S driver read/write operations.
*
* @return
* - ESP_OK Success
......@@ -205,68 +209,88 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config,
esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num);
/**
* @brief i2s read data buffer to i2s dma buffer
* @brief Write data to I2S DMA transmit buffer.
*
* @param i2s_num I2S_NUM_0, I2S_NUM_1
*
* @param src source address to write
* @param src Source address to write from
*
* @param size Size of data in bytes
*
* @param size size of data (size in bytes)
* @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this
* many ticks pass without space becoming available in the DMA
* transmit buffer, then the function will return (note that if the
* data is written to the DMA buffer in pieces, the overall operation
* may still take longer than this timeout.) Pass portMAX_DELAY for no
* timeout.
*
* @param ticks_to_wait Write timeout
* Format of the data in source buffer is determined by the I2S
* configuration (see i2s_config_t).
*
* @return number of written bytes
* @return Number of bytes written, or ESP_FAIL (-1) for parameter error. If a timeout occurred, bytes written will be less than total size.
*/
int i2s_write_bytes(i2s_port_t i2s_num, const char *src, size_t size, TickType_t ticks_to_wait);
/**
* @brief i2s write data buffer to i2s dma buffer
* @brief Read data from I2S DMA receive buffer
*
* @param i2s_num I2S_NUM_0, I2S_NUM_1
*
* @param dest destination address to read
* @param dest Destination address to read into
*
* @param size size of data (size in bytes)
* @param size Size of data in bytes
*
* @param ticks_to_wait Read timeout
* @param ticks_to_wait RX buffer wait timeout in RTOS ticks. If this many ticks pass without bytes becoming available in the DMA receive buffer, then the function will return (note that if data is read from the DMA buffer in pieces, the overall operation may still take longer than this timeout.) Pass portMAX_DELAY for no timeout.
*
* @return number of read bytes
* Format of the data in source buffer is determined by the I2S
* configuration (see i2s_config_t).
*
* @return Number of bytes read, or ESP_FAIL (-1) for parameter error. If a timeout occurred, bytes read will be less than total size.
*/
int i2s_read_bytes(i2s_port_t i2s_num, char* dest, size_t size, TickType_t ticks_to_wait);
/**
* @brief i2s push 1 sample to i2s dma buffer, with the size parameter equal to one sample's size in bytes = bits_per_sample/8.
* @brief Push (write) a single sample to the I2S DMA TX buffer.
*
* Size of the sample is determined by the channel_format (mono or stereo)) & bits_per_sample configuration (see i2s_config_t).
*
* @param i2s_num I2S_NUM_0, I2S_NUM_1
*
* @param sample destination address to write (depend on bits_per_sample, size of sample (in bytes) = 2*bits_per_sample/8)
* @param sample Pointer to buffer containing sample to write. Size of buffer (in bytes) = (number of channels) * bits_per_sample / 8.
*
* @param ticks_to_wait Push timeout
* @param ticks_to_wait Push timeout in RTOS ticks. If space is not available in the DMA TX buffer within this period, no data is written and function returns 0.
*
* @return number of push bytes
* @return Number of bytes successfully pushed to DMA buffer, or ESP_FAIL (-1) for parameter error. Will be either zero or the size of configured sample buffer.
*/
int i2s_push_sample(i2s_port_t i2s_num, const char *sample, TickType_t ticks_to_wait);
/**
* @brief Pop 1 sample to i2s dma buffer, with the size parameter equal to one sample's size in bytes = bits_per_sample/8.
* @brief Pop (read) a single sample from the I2S DMA RX buffer.
*
* Size of the sample is determined by the channel_format (mono or stereo)) & bits_per_sample configuration (see i2s_config_t).
*
* @param i2s_num I2S_NUM_0, I2S_NUM_1
*
* @param sample destination address to write (depend on bits_per_sample, size of sample (in bytes) = 2*bits_per_sample/8)
* @param sample Buffer sample data will be read into. Size of buffer (in bytes) = (number of channels) * bits_per_sample / 8.
*
* @param ticks_to_wait Pop timeout
* @param ticks_to_wait Pop timeout in RTOS ticks. If a sample is not available in the DMA buffer within this period, no data is read and function returns zero.
*
* @return number of pop bytes
* @return Number of bytes successfully read from DMA buffer, or ESP_FAIL (-1) for parameter error. Byte count will be either zero or the size of the configured sample buffer.
*/
int i2s_pop_sample(i2s_port_t i2s_num, char *sample, TickType_t ticks_to_wait);
/**
* @brief Set clock rate used for I2S RX and TX
* @brief Set sample rate used for I2S RX and TX.
*
* The bit clock rate is determined by the sample rate and i2s_config_t configuration parameters (number of channels, bits_per_sample).
*
* `bit_clock = rate * (number of channels) * bits_per_sample`
*
* @param i2s_num I2S_NUM_0, I2S_NUM_1
*
* @param rate I2S clock (ex: 8000, 44100...)
* @param rate I2S sample rate (ex: 8000, 44100...)
*
* @return
* - ESP_OK Success
......@@ -275,29 +299,36 @@ int i2s_pop_sample(i2s_port_t i2s_num, char *sample, TickType_t ticks_to_wait);
esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate);
/**
* @brief Start driver
* @brief Stop I2S driver
*
* Disables I2S TX/RX, until i2s_start() is called.
*
* @param i2s_num I2S_NUM_0, I2S_NUM_1
*
* @return
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t i2s_start(i2s_port_t i2s_num);
esp_err_t i2s_stop(i2s_port_t i2s_num);
/**
* @brief Stop driver
* @brief Start I2S driver
*
* It is not necessary to call this function after i2s_driver_install() (it is started automatically), however it is necessary to call it after i2s_stop().
*
*
* @param i2s_num I2S_NUM_0, I2S_NUM_1
*
* @return
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t i2s_stop(i2s_port_t i2s_num);
esp_err_t i2s_start(i2s_port_t i2s_num);
/**
* @brief Set the TX DMA buffer contents to all zeroes
* @brief Zero the contents of the TX DMA buffer.
*
* Pushes zero-byte samples into the TX DMA buffer, until it is full.
*
* @param i2s_num I2S_NUM_0, I2S_NUM_1
*
......@@ -307,72 +338,6 @@ esp_err_t i2s_stop(i2s_port_t i2s_num);
*/
esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num);
/***************************EXAMPLE**********************************
*
*
* ----------------EXAMPLE OF I2S SETTING ---------------------
* @code{c}
*
* #include "freertos/queue.h"
* #define I2S_INTR_NUM 17 //choose one interrupt number from soc.h
* int i2s_num = 0; //i2s port number
* i2s_config_t i2s_config = {
* .mode = I2S_MODE_MASTER | I2S_MODE_TX,
* .sample_rate = 44100,
* .bits_per_sample = 16, //16, 32
* .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //format LEFT_RIGHT
* .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
* .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
* .dma_buf_count = 8,
* .dma_buf_len = 64
* };
*
* i2s_pin_config_t pin_config = {
* .bck_io_num = 26,
* .ws_io_num = 25,
* .data_out_num = 22,
* .data_in_num = I2S_PIN_NO_CHANGE
* };
*
* i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver
*
* i2s_set_pin(i2s_num, &pin_config);
*
* i2s_set_sample_rates(i2s_num, 22050); //set sample rates
*
*
* i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver
*@endcode
*
* ----------------EXAMPLE USING I2S WITH DAC ---------------------
* @code{c}
*
* #include "freertos/queue.h"
* #define I2S_INTR_NUM 17 //choose one interrupt number from soc.h
* int i2s_num = 0; //i2s port number
* i2s_config_t i2s_config = {
* .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
* .sample_rate = 44100,
* .bits_per_sample = 8, // Only 8-bit DAC support
* .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //
* .communication_format = I2S_COMM_FORMAT_I2S_MSB,
* .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
* .dma_buf_count = 8,
* .dma_buf_len = 64
* };
*
*
* i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver
*
* i2s_set_pin(i2s_num, NULL); //for internal DAC
*
* i2s_set_sample_rates(i2s_num, 22050); //set sample rates
*
* i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver
*@endcode
*-----------------------------------------------------------------------------*
***************************END OF EXAMPLE**********************************/
#ifdef __cplusplus
}
#endif
......
......@@ -24,7 +24,10 @@ extern "C" {
#endif
/**
* @brief Pullup/pulldown information for a single GPIO pad
* @brief Pin function information for a single GPIO pad's RTC functions.
*
* This is an internal function of the driver, and is not usually useful
* for external use.
*/
typedef struct {
uint32_t reg; /*!< Register of RTC pad, or 0 if not an RTC GPIO */
......@@ -46,10 +49,29 @@ typedef enum {
RTC_GPIO_MODE_DISABLED, /*!< Pad (output + input) disable */
} rtc_gpio_mode_t;
#define RTC_GPIO_IS_VALID_GPIO(gpio_num) ((gpio_num < GPIO_PIN_COUNT && rtc_gpio_desc[gpio_num].reg != 0)) //to decide whether it is a valid GPIO number
/**
* @brief Provides access to a constant table of RTC I/O pin
* function information.
*
* This is an internal function of the driver, and is not usually useful
* for external use.
*/
extern const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT];
/**
* @brief Determine if the specified GPIO is a valid RTC GPIO.
*
* @param gpio_num GPIO number
* @return true if GPIO is valid for RTC GPIO use. talse otherwise.
*/
inline static bool rtc_gpio_is_valid_gpio(gpio_num_t gpio_num)
{
return gpio_num < GPIO_PIN_COUNT
&& rtc_gpio_desc[gpio_num].reg != 0;
}
#define RTC_GPIO_IS_VALID_GPIO(gpio_num) rtc_gpio_is_valid_gpio(gpio_num) // Deprecated, use rtc_gpio_is_valid_gpio()
/**
* @brief Init a GPIO as RTC GPIO
*
......
......@@ -469,8 +469,6 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_
* @brief Install UART driver.
*
* UART ISR handler will be attached to the same CPU core that this function is running on.
* 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 uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
* @param rx_buffer_size UART RX ring buffer size, rx_buffer_size should be greater than UART_FIFO_LEN.
......@@ -644,7 +642,6 @@ esp_err_t uart_enable_pattern_det_intr(uart_port_t uart_num, char pattern_chr, u
* @code{c}
* //1. Setup UART
* #include "freertos/queue.h"
* #define UART_INTR_NUM 17 //choose one interrupt number from soc.h
* //a. Set UART parameter
* int uart_num = 0; //uart port number
* uart_config_t uart_config = {
......
......@@ -25,6 +25,11 @@ extern "C" {
*/
esp_err_t coex_init(void);
/**
* @brief De-init software coexist
*/
void coex_deinit(void);
/**
* @brief Get software coexist enable or not
*
......
......@@ -164,6 +164,14 @@ void esp_deep_sleep_start() __attribute__((noreturn));
* Call to this function is equivalent to a call to esp_deep_sleep_enable_timer_wakeup
* followed by a call to esp_deep_sleep_start.
*
* esp_deep_sleep does not shut down WiFi, BT, and higher level protocol
* connections gracefully.
* Make sure relevant WiFi and BT stack functions are called to close any
* connections and deinitialize the peripherals. These include:
* - esp_bluedroid_disable
* - esp_bt_controller_disable
* - esp_wifi_stop
*
* This function does not return.
*
* @param time_in_us deep-sleep time, unit: microsecond
......
......@@ -14,6 +14,7 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#ifdef __cplusplus
......@@ -192,7 +193,7 @@ void esp_phy_release_init_data(const esp_phy_init_data_t* data);
* mechanism for loading calibration data, disable
* "Initialize PHY in startup code" option in menuconfig and call esp_phy_init
* function from the application. For an example usage of esp_phy_init and
* this function, see do_phy_init function in cpu_start.c
* this function, see esp_phy_store_cal_data_to_nvs function in cpu_start.c
*
* @param out_cal_data pointer to calibration data structure to be filled with
* loaded data.
......@@ -220,28 +221,39 @@ esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_dat
esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_data);
/**
* @brief Initialize PHY module
* @brief Initialize PHY and RF module
*
* PHY module should be initialized in order to use WiFi or BT.
* If "Initialize PHY in startup code" option is set in menuconfig,
* this function will be called automatically before app_main is called,
* using parameters obtained from esp_phy_get_init_data.
*
* Applications which don't need to enable PHY on every start up should
* disable this menuconfig option and call esp_phy_init before calling
* esp_wifi_init or esp_bt_controller_init. See do_phy_init function in
* cpu_start.c for an example of using this function.
* PHY and RF module should be initialized in order to use WiFi or BT.
* Now PHY and RF initializing job is done automatically when start WiFi or BT. Users should not
* call this API in their application.
*
* @param init_data PHY parameters. Default set of parameters can
* be obtained by calling esp_phy_get_default_init_data
* function.
* @param mode Calibration mode (Full, partial, or no calibration)
* @param[inout] calibration_data
* @param is_sleep WiFi wakes up from sleep or not
* @return ESP_OK on success.
* @return ESP_FAIL on fail.
*/
esp_err_t esp_phy_init(const esp_phy_init_data_t* init_data,
esp_phy_calibration_mode_t mode, esp_phy_calibration_data_t* calibration_data);
esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data,
esp_phy_calibration_mode_t mode, esp_phy_calibration_data_t* calibration_data, bool is_sleep);
/**
* @brief De-initialize PHY and RF module
*
* PHY module should be de-initialized in order to shutdown WiFi or BT.
* Now PHY and RF de-initializing job is done automatically when stop WiFi or BT. Users should not
* call this API in their application.
*
* @return ESP_OK on success.
*/
esp_err_t esp_phy_rf_deinit(void);
/**
* @brief Load calibration data from NVS and initialize PHY and RF module
*/
void esp_phy_load_cal_and_init(void);
#ifdef __cplusplus
}
......
......@@ -130,6 +130,7 @@ esp_err_t esp_wifi_init(wifi_init_config_t *config);
* Free all resource allocated in esp_wifi_init and stop WiFi task
*
* @attention 1. This API should be called if you want to remove WiFi driver from the system
* @attention 2. This API can not be called yet and will be done in the future.
*
* @return ESP_OK: succeed
*/
......
......@@ -268,10 +268,10 @@
* 2 1 extern level
* 3 1 extern level
* 4 1 extern level WBB
* 5 1 extern level BT Controller
* 5 1 extern level BT/BLE Controller
* 6 1 timer FreeRTOS Tick(L1) FreeRTOS Tick(L1)
* 7 1 software Reserved Reserved
* 8 1 extern level BLE Controller
* 8 1 extern level BT/BLE BB(RX/TX)
* 9 1 extern level
* 10 1 extern edge Internal Timer
* 11 3 profiling
......
......@@ -58,16 +58,19 @@ typedef struct {
} ff_diskio_impl_t;
/**
* Register diskio driver for given drive number.
* Register or unregister diskio driver for given drive number.
*
* When FATFS library calls one of disk_xxx functions for driver number pdrv,
* corresponding function in discio_impl for given pdrv will be called.
*
* @param pdrv drive number
* @param discio_impl pointer to ff_diskio_impl_t structure with diskio functions
* @param discio_impl pointer to ff_diskio_impl_t structure with diskio functions
* or NULL to unregister and free previously registered drive
*/
void ff_diskio_register(BYTE pdrv, const ff_diskio_impl_t* discio_impl);
#define ff_diskio_unregister(pdrv_) ff_diskio_register(pdrv_, NULL)
/**
* Register SD/MMC diskio driver
*
......@@ -76,6 +79,16 @@ void ff_diskio_register(BYTE pdrv, const ff_diskio_impl_t* discio_impl);
*/
void ff_diskio_register_sdmmc(BYTE pdrv, sdmmc_card_t* card);
/**
* Get next available drive number
*
* @param out_pdrv pointer to the byte to set if successful
*
* @return ESP_OK on success
* ESP_ERR_NOT_FOUND if all drives are attached
*/
esp_err_t ff_diskio_get_drive(BYTE* out_pdrv);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
......
......@@ -51,11 +51,31 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive,
* @note FATFS structure returned by esp_vfs_fat_register is destroyed after
* this call. Make sure to call f_mount function to unmount it before
* calling esp_vfs_fat_unregister.
* This function is left for compatibility and will be changed in
* future versions to accept base_path and replace the method below
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if FATFS is not registered in VFS
*/
esp_err_t esp_vfs_fat_unregister();
esp_err_t esp_vfs_fat_unregister() __attribute__((deprecated));
/**
* @brief Un-register FATFS from VFS
*
* @note FATFS structure returned by esp_vfs_fat_register is destroyed after
* this call. Make sure to call f_mount function to unmount it before
* calling esp_vfs_fat_unregister_ctx.
* Difference between this function and the one above is that this one
* will release the correct drive, while the one above will release
* the last registered one
*
* @param base_path path prefix where FATFS is registered. This is the same
* used when esp_vfs_fat_register was called
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if FATFS is not registered in VFS
*/
esp_err_t esp_vfs_fat_unregister_path(const char* base_path);
/**
* @brief Configuration arguments for esp_vfs_fat_sdmmc_mount function
......
......@@ -216,6 +216,9 @@ static inline uint32_t xPortGetCoreID() {
return id;
}
/* Get tick rate per second */
uint32_t xPortGetTickRateHz(void);
#ifdef __cplusplus
}
#endif
......
......@@ -83,7 +83,12 @@ SECTIONS
*libesp32.a:core_dump.o(.literal .text .literal.* .text.*)
*libphy.a:(.literal .text .literal.* .text.*)
*librtc.a:(.literal .text .literal.* .text.*)
*libpp.a:(.literal .text .literal.* .text.*)
*librtc_clk.a:(.literal .text .literal.* .text.*)
*libpp.a:pp.o(.literal .text .literal.* .text.*)
*libpp.a:lmac.o(.literal .text .literal.* .text.*)
*libpp.a:wdev.o(.literal .text .literal.* .text.*)
*libcore.a:ets_timer.o(.literal .text .literal.* .text.*)
*libnet80211.a:ieee80211_misc.o(.literal .text .literal.* .text.*)
*libhal.a:(.literal .text .literal.* .text.*)
*libcoexist.a:(.literal .text .literal.* .text.*)
_iram_text_end = ABSOLUTE(.);
......
无法预览此类型文件
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册