Merge branch 'master' into feature/btdm_bluedroid

# Conflicts:
#	components/esp32/cpu_freq.c
#	components/esp32/lib
This commit is contained in:
Tian Hao 2016-11-29 18:38:37 +08:00
commit 5a9801aca7
113 changed files with 7505 additions and 1053 deletions

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
@ -88,7 +92,7 @@ build_esp_idf_tests:
- cd tools/unit-test-app
- git checkout ${CI_BUILD_REF_NAME} || echo "Using default branch..."
- make defconfig
- make
- make TESTS_ALL=1
build_examples:
<<: *build_template
@ -288,7 +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

@ -0,0 +1,5 @@
#
# Component Makefile
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

View File

@ -0,0 +1,381 @@
// 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 <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include "esp_err.h"
#include "esp_partition.h"
#include "esp_spi_flash.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "sdkconfig.h"
#include "esp_ota_ops.h"
#include "rom/queue.h"
#include "rom/crc.h"
#include "esp_log.h"
#define OTA_MAX(a,b) ((a) >= (b) ? (a) : (b))
#define OTA_MIN(a,b) ((a) <= (b) ? (a) : (b))
#define SUB_TYPE_ID(i) (i & 0x0F)
typedef struct ota_ops_entry_ {
uint32_t handle;
esp_partition_t part;
uint32_t erased_size;
uint32_t wrote_size;
LIST_ENTRY(ota_ops_entry_) entries;
} ota_ops_entry_t;
/* OTA selection structure (two copies in the OTA data partition.)
Size of 32 bytes is friendly to flash encryption */
typedef struct {
uint32_t ota_seq;
uint8_t seq_label[24];
uint32_t crc; /* CRC32 of ota_seq field only */
} ota_select;
static LIST_HEAD(ota_ops_entries_head, ota_ops_entry_) s_ota_ops_entries_head =
LIST_HEAD_INITIALIZER(s_ota_ops_entries_head);
static uint32_t s_ota_ops_last_handle = 0;
static ota_select s_ota_select[2];
const static char *TAG = "esp_ota_ops";
esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp_ota_handle_t *out_handle)
{
esp_err_t ret = ESP_OK;
if ((partition == NULL) || (out_handle == NULL)) {
return ESP_ERR_INVALID_ARG;
}
ota_ops_entry_t *new_entry = (ota_ops_entry_t *) calloc(sizeof(ota_ops_entry_t), 1);
if (new_entry == 0) {
return ESP_ERR_NO_MEM;
}
// if input image size is 0 or OTA_SIZE_UNKNOWN, will erase all areas in this partition
if ((image_size == 0) || (image_size == OTA_SIZE_UNKNOWN)) {
ret = esp_partition_erase_range(partition, 0, partition->size);
} else {
ret = esp_partition_erase_range(partition, 0, (image_size / SPI_FLASH_SEC_SIZE + 1) * SPI_FLASH_SEC_SIZE);
}
if (ret != ESP_OK) {
free(new_entry);
new_entry = NULL;
return ret;
}
LIST_INSERT_HEAD(&s_ota_ops_entries_head, new_entry, entries);
if ((image_size == 0) || (image_size == OTA_SIZE_UNKNOWN)) {
new_entry->erased_size = partition->size;
} else {
new_entry->erased_size = image_size;
}
memcpy(&new_entry->part, partition, sizeof(esp_partition_t));
new_entry->handle = ++s_ota_ops_last_handle;
*out_handle = new_entry->handle;
return ESP_OK;
}
esp_err_t esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)
{
esp_err_t ret;
ota_ops_entry_t *it;
if (data == NULL) {
ESP_LOGE(TAG, "write data is invalid");
return ESP_ERR_INVALID_ARG;
}
// find ota handle in linked list
for (it = LIST_FIRST(&s_ota_ops_entries_head); it != NULL; it = LIST_NEXT(it, entries)) {
if (it->handle == handle) {
// must erase the partition before writing to it
assert(it->erased_size > 0 && "must erase the partition before writing to it");
ret = esp_partition_write(&it->part, it->wrote_size, data, size);
if(ret == ESP_OK){
it->wrote_size += size;
}
return ret;
}
}
//if go to here ,means don't find the handle
ESP_LOGE(TAG,"not found the handle")
return ESP_ERR_INVALID_ARG;
}
esp_err_t esp_ota_end(esp_ota_handle_t handle)
{
esp_err_t ret;
ota_ops_entry_t *it;
size_t image_size;
for (it = LIST_FIRST(&s_ota_ops_entries_head); it != NULL; it = LIST_NEXT(it, entries)) {
if (it->handle == handle) {
// an ota handle need to be ended after erased and wrote data in it
if ((it->erased_size == 0) || (it->wrote_size == 0)) {
return ESP_ERR_INVALID_ARG;
}
#ifdef CONFIG_SECUREBOOTLOADER
if (esp_image_basic_verify(it->part.address, &image_size) != ESP_OK) {
return ESP_ERR_OTA_VALIDATE_FAILED;
}
ret = esp_secure_boot_verify_signature(it->part.address, image_size);
if (ret != ESP_OK) {
return ESP_ERR_OTA_VALIDATE_FAILED;
}
#endif
LIST_REMOVE(it, entries);
break;
}
}
if (it == NULL) {
return ESP_ERR_NOT_FOUND;
}
free(it);
return ESP_OK;
}
static uint32_t ota_select_crc(const ota_select *s)
{
return crc32_le(UINT32_MAX, (uint8_t *)&s->ota_seq, 4);
}
static bool ota_select_valid(const ota_select *s)
{
return s->ota_seq != UINT32_MAX && s->crc == ota_select_crc(s);
}
static esp_err_t rewrite_ota_seq(uint32_t seq, uint8_t sec_id, const esp_partition_t *ota_data_partition)
{
esp_err_t ret;
if (sec_id == 0 || sec_id == 1) {
s_ota_select[sec_id].ota_seq = seq;
s_ota_select[sec_id].crc = ota_select_crc(&s_ota_select[sec_id]);
ret = spi_flash_erase_range(ota_data_partition->address, SPI_FLASH_SEC_SIZE);
if (ret != ESP_OK) {
return ret;
} else {
return esp_partition_write(ota_data_partition, SPI_FLASH_SEC_SIZE * sec_id, &s_ota_select[sec_id].ota_seq, sizeof(ota_select));
}
} else {
return ESP_ERR_INVALID_ARG;
}
}
static uint8_t get_ota_partition_count(void)
{
uint16_t ota_app_count = 0;
while (esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_app_count, NULL) != NULL) {
assert(ota_app_count < 16 && "must erase the partition before writing to it");
ota_app_count++;
}
return ota_app_count;
}
static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype)
{
esp_err_t ret;
const esp_partition_t *find_partition = NULL;
uint16_t ota_app_count = 0;
uint32_t i = 0;
uint32_t seq;
static spi_flash_mmap_memory_t ota_data_map;
const void *result = NULL;
find_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
if (find_partition != NULL) {
ota_app_count = get_ota_partition_count();
//esp32_idf use two sector for store information about which partition is running
//it defined the two sector as ota data partition,two structure ota_select is saved in the two sector
//named data in first sector as s_ota_select[0], second sector data as s_ota_select[1]
//e.g.
//if s_ota_select[0].ota_seq == s_ota_select[1].ota_seq == 0xFFFFFFFF,means ota info partition is in init status
//so it will boot factory application(if there is),if there's no factory application,it will boot ota[0] application
//if s_ota_select[0].ota_seq != 0 and s_ota_select[1].ota_seq != 0,it will choose a max seq ,and get value of max_seq%max_ota_app_number
//and boot a subtype (mask 0x0F) value is (max_seq - 1)%max_ota_app_number,so if want switch to run ota[x],can use next formulas.
//for example, if s_ota_select[0].ota_seq = 4, s_ota_select[1].ota_seq = 5, and there are 8 ota application,
//current running is (5-1)%8 = 4,running ota[4],so if we want to switch to run ota[7],
//we should add s_ota_select[0].ota_seq (is 4) to 4 ,(8-1)%8=7,then it will boot ota[7]
//if A=(B - C)%D
//then B=(A + C)%D + D*n ,n= (0,1,2...)
//so current ota app sub type id is x , dest bin subtype is y,total ota app count is n
//seq will add (x + n*1 + 1 - seq)%n
if (SUB_TYPE_ID(subtype) >= ota_app_count) {
return ESP_ERR_NOT_FOUND;
}
ret = esp_partition_mmap(find_partition, 0, find_partition->size, SPI_FLASH_MMAP_DATA, &result, &ota_data_map);
if (ret != ESP_OK) {
result = NULL;
return ret;
} else {
memcpy(&s_ota_select[0], result, sizeof(ota_select));
memcpy(&s_ota_select[1], result + SPI_FLASH_SEC_SIZE, sizeof(ota_select));
spi_flash_munmap(ota_data_map);
}
if (ota_select_valid(&s_ota_select[0]) && ota_select_valid(&s_ota_select[1])) {
seq = OTA_MAX(s_ota_select[0].ota_seq, s_ota_select[1].ota_seq);
while (seq > (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count) {
i++;
}
if (s_ota_select[0].ota_seq >= s_ota_select[1].ota_seq) {
return rewrite_ota_seq((SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, 0, find_partition);
} else {
return rewrite_ota_seq((SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, 1, find_partition);
}
} else if (ota_select_valid(&s_ota_select[0])) {
while (s_ota_select[0].ota_seq > (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count) {
i++;
}
return rewrite_ota_seq((SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, 1, find_partition);
} else if (ota_select_valid(&s_ota_select[1])) {
while (s_ota_select[1].ota_seq > (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count) {
i++;
}
return rewrite_ota_seq((SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, 0, find_partition);
} else if (s_ota_select[0].ota_seq == 0xFFFFFFFF && s_ota_select[1].ota_seq == 0xFFFFFFFF) {
return rewrite_ota_seq(SUB_TYPE_ID(subtype) + 1, 0, find_partition);
} else {
return ESP_ERR_OTA_SELECT_INFO_INVALID;
}
} else {
return ESP_ERR_NOT_FOUND;
}
}
esp_err_t esp_ota_set_boot_partition(const esp_partition_t *partition)
{
const esp_partition_t *find_partition = NULL;
size_t image_size;
if (partition == NULL) {
return ESP_ERR_INVALID_ARG;
}
#ifdef CONFIG_SECUREBOOTLOADER
if (esp_image_basic_verify(partition->address, &image_size) != ESP_OK) {
return ESP_ERR_OTA_VALIDATE_FAILED;
}
ret = esp_secure_boot_verify_signature(partition->address, image_size);
if (ret != ESP_OK) {
return ESP_ERR_OTA_VALIDATE_FAILED;
}
#endif
// if set boot partition to factory bin ,just format ota info partition
if (partition->type == ESP_PARTITION_TYPE_APP) {
if (partition->subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY) {
find_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
if (find_partition != NULL) {
return esp_partition_erase_range(find_partition, find_partition->address, find_partition->size);
} else {
return ESP_ERR_NOT_FOUND;
}
} else {
// try to find this partition in flash,if not find it ,return error
find_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
if (find_partition != NULL) {
return esp_rewrite_ota_data(partition->subtype);
} else {
return ESP_ERR_NOT_FOUND;
}
}
} else {
return ESP_ERR_INVALID_ARG;
}
}
const esp_partition_t *esp_ota_get_boot_partition(void)
{
esp_err_t ret;
const esp_partition_t *find_partition = NULL;
static spi_flash_mmap_memory_t ota_data_map;
const void *result = NULL;
uint16_t ota_app_count = 0;
find_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
if (find_partition == NULL) {
ESP_LOGE(TAG, "not found ota data");
return NULL;
}
ret = esp_partition_mmap(find_partition, 0, find_partition->size, SPI_FLASH_MMAP_DATA, &result, &ota_data_map);
if (ret != ESP_OK) {
spi_flash_munmap(ota_data_map);
ESP_LOGE(TAG, "mmap ota data filed");
return NULL;
} else {
memcpy(&s_ota_select[0], result, sizeof(ota_select));
memcpy(&s_ota_select[1], result + 0x1000, sizeof(ota_select));
spi_flash_munmap(ota_data_map);
}
ota_app_count = get_ota_partition_count();
ESP_LOGD(TAG, "found ota bin max = %d", ota_app_count);
if (s_ota_select[0].ota_seq == 0xFFFFFFFF && s_ota_select[1].ota_seq == 0xFFFFFFFF) {
ESP_LOGD(TAG, "finding factory bin......");
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
} else if (ota_select_valid(&s_ota_select[0]) && ota_select_valid(&s_ota_select[1])) {
ESP_LOGD(TAG, "finding ota_%d bin......", \
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ((OTA_MAX(s_ota_select[0].ota_seq, s_ota_select[1].ota_seq) - 1) % ota_app_count));
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, \
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ((OTA_MAX(s_ota_select[0].ota_seq, s_ota_select[1].ota_seq) - 1) % ota_app_count), NULL);
} else if (ota_select_valid(&s_ota_select[0])) {
ESP_LOGD(TAG, "finding ota_%d bin......", \
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + (s_ota_select[0].ota_seq - 1) % ota_app_count);
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, \
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + (s_ota_select[0].ota_seq - 1) % ota_app_count, NULL);
} else if (ota_select_valid(&s_ota_select[1])) {
ESP_LOGD(TAG, "finding ota_%d bin......", \
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + (s_ota_select[1].ota_seq - 1) % ota_app_count);
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, \
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + (s_ota_select[1].ota_seq - 1) % ota_app_count, NULL);
} else {
ESP_LOGE(TAG, "not found current bin");
return NULL;
}
}

View File

@ -0,0 +1,106 @@
// 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 _OTA_OPS_H
#define _OTA_OPS_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "esp_err.h"
#include "esp_partition.h"
#include "esp_spi_flash.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define OTA_SIZE_UNKNOWN 0xffffffff
#define ESP_ERR_OTA_BASE 0x1500 /*!< base error code for ota_ops api */
#define ESP_ERR_OTA_PARTITION_CONFLICT (ESP_ERR_OTA_BASE + 0x01) /*!< want to write or erase current running partition */
#define ESP_ERR_OTA_SELECT_INFO_INVALID (ESP_ERR_OTA_BASE + 0x02) /*!< ota data partition info is error */
#define ESP_ERR_OTA_VALIDATE_FAILED (ESP_ERR_OTA_BASE + 0x03) /*!< validate ota image failed */
/**
* @brief Opaque handle for application update obtained from app_ops.
*/
typedef uint32_t esp_ota_handle_t;
/**
* @brief format input partition in flash to 0xFF as input image size,
* if unkown image size ,pass 0x0 or 0xFFFFFFFF, it will erase all the
* partition ,Otherwise, erase the required range
*
* @param partition Pointer to partition structure which need to be updated
* Must be non-NULL.
* @param image_size size of image need to be updated
* @param out_handle handle which should be used for esp_ota_write or esp_ota_end call
* @return: ESP_OK if format ota image OK
* ESP_ERR_OTA_PARTITION_CONFLICT operate current running bin
* ESP_ERR_OTA_SELECT_INFO_INVALID ota bin select info invalid
*/
esp_err_t esp_ota_begin(const esp_partition_t* partition, size_t image_size, esp_ota_handle_t* out_handle);
/**
* @brief Write data to input input partition
*
* @param handle Handle obtained from esp_ota_begin
* @param data Pointer to data write to flash
* @param size data size of recieved data
*
* @return: ESP_OK if write flash data OK
* ESP_ERR_OTA_PARTITION_CONFLICT operate current running bin
* ESP_ERR_OTA_SELECT_INFO_INVALID ota bin select info invalid
*/
esp_err_t esp_ota_write(esp_ota_handle_t handle, const void* data, size_t size);
/**
* @brief Finish the update and validate written data
*
* @param handle Handle obtained from esp_ota_begin
*
* @return: ESP_OK if validate ota image pass
* ESP_ERR_OTA_VALIDATE_FAILED validate the ota image is invalid
*/
esp_err_t esp_ota_end(esp_ota_handle_t handle);
/**
* @brief Set next boot partition, call system_restart() will switch to run it
*
* @note if you want switch to run a bin file
* has never been checked before,please validate it's signature firstly
*
* @param partition Pointer to partition structure which need to boot
*
* @return: ESP_OK if set next boot partition OK
* ESP_ERR_OTA_SELECT_INFO_INVALID ota bin select info invalid
*/
esp_err_t esp_ota_set_boot_partition(const esp_partition_t* partition);
/**
* @brief Get partition info of current running image
*
* @return pointer to esp_partition_t structure, or NULL if no partition is found or
* operate flash failed,This pointer is valid for the lifetime of the application.
*/
const esp_partition_t* esp_ota_get_boot_partition(void);
#ifdef __cplusplus
}
#endif
#endif /* OTA_OPS_H */

View File

@ -25,7 +25,6 @@
typedef SHA_CTX sha_context;
#else
#include "hwcrypto/sha.h"
typedef esp_sha_context sha_context;
#endif
typedef struct {
@ -42,7 +41,9 @@ extern const uint8_t signature_verification_key_end[] asm("_binary_signature_ver
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
sha_context sha;
#ifdef BOOTLOADER_BUILD
SHA_CTX sha;
#endif
uint8_t digest[32];
ptrdiff_t keylen;
const uint8_t *data;
@ -83,12 +84,8 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
ets_sha_finish(&sha, SHA2_256, digest);
ets_sha_disable();
#else
/* Use thread-safe esp-idf SHA layer */
esp_sha256_init(&sha);
esp_sha256_start(&sha, false);
esp_sha256_update(&sha, data, length);
esp_sha256_finish(&sha, digest);
esp_sha256_free(&sha);
/* Use thread-safe esp-idf SHA function */
esp_sha(SHA2_256, data, length, digest);
#endif
keylen = signature_verification_key_end - signature_verification_key_start;

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

@ -0,0 +1,349 @@
// 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.
#ifndef _DRIVER_TIMER_H_
#define _DRIVER_TIMER_H_
#include "esp_err.h"
#include "esp_attr.h"
#include "soc/soc.h"
#include "soc/timer_group_reg.h"
#include "soc/timer_group_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
#define TIMER_BASE_CLK (APB_CLK_FREQ)
/**
* @brief Selects a Timer-Group out of 2 available groups
*/
typedef enum {
TIMER_GROUP_0 = 0, /*!<Hw timer group 0*/
TIMER_GROUP_1 = 1, /*!<Hw timer group 1*/
TIMER_GROUP_MAX,
} timer_group_t;
/**
* @brief Select a hardware timer from timer groups
*/
typedef enum {
TIMER_0 = 0, /*!<Select timer0 of GROUPx*/
TIMER_1 = 1, /*!<Select timer1 of GROUPx*/
TIMER_MAX,
} timer_idx_t;
/**
* @brief Decides the direction of counter
*/
typedef enum {
TIMER_COUNT_DOWN = 0, /*!< Descending Count from cnt.high|cnt.low*/
TIMER_COUNT_UP = 1, /*!< Ascending Count from Zero*/
TIMER_COUNT_MAX
} timer_count_dir_t;
/**
* @brief Decides whether timer is on or paused
*/
typedef enum {
TIMER_PAUSE = 0, /*!<Pause timer counter*/
TIMER_START = 1, /*!<Start timer counter*/
} timer_start_t;
/**
* @brief Decides whether to enable alarm mode
*/
typedef enum {
TIMER_ALARM_DIS = 0, /*!< Disable timer alarm*/
TIMER_ALARM_EN = 1, /*!< Enable timer alarm*/
TIMER_ALARM_MAX
} timer_alarm_t;
/**
* @brief Select interrupt type if running in alarm mode.
*/
typedef enum {
TIMER_INTR_LEVEL = 0, /*!< Interrupt mode: level mode*/
//TIMER_INTR_EDGE = 1, /*!< Interrupt mode: edge mode, Not supported Now*/
TIMER_INTR_MAX
} timer_intr_mode_t;
/**
* @brief Select if Alarm needs to be loaded by software or automatically reload by hardware.
*/
typedef enum {
TIMER_AUTORELOAD_DIS = 0, /*!< Disable auto-reload: hardware will not load counter value after an alarm event*/
TIMER_AUTORELOAD_EN = 1, /*!< Enable auto-reload: hardware will load counter value after an alarm event*/
TIMER_AUTORELOAD_MAX,
} timer_autoreload_t;
/**
* @brief timer configure struct
*/
typedef struct {
bool alarm_en; /*!< Timer alarm enable */
bool counter_en; /*!< Counter enable */
timer_count_dir_t counter_dir; /*!< Counter direction */
timer_intr_mode_t intr_type; /*!< Interrupt mode */
bool auto_reload; /*!< Timer auto-reload */
uint16_t divider; /*!< Counter clock divider*/
} timer_config_t;
/**
* @brief Read the counter value of hardware timer.
*
* @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
* @param timer_val Pointer to accept timer counter value.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_get_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t* timer_val);
/**
* @brief Read the counter value of hardware timer, in unit of a given scale.
*
* @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
* @param time Pointer, type of double*, to accept timer counter value, in seconds.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_get_counter_time_sec(timer_group_t group_num, timer_idx_t timer_num, double* time);
/**
* @brief Set counter value to hardware timer.
*
* @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
* @param load_val Counter value to write to the hardware timer.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_set_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t load_val);
/**
* @brief Start the counter of hardware timer.
*
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_start(timer_group_t group_num, timer_idx_t timer_num);
/**
* @brief Pause the counter of hardware timer.
*
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_pause(timer_group_t group_num, timer_idx_t timer_num);
/**
* @brief Set counting mode for hardware timer.
*
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
* @param counter_dir Counting direction of timer, count-up or count-down
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_set_counter_mode(timer_group_t group_num, timer_idx_t timer_num, timer_count_dir_t counter_dir);
/**
* @brief Enable or disable counter reload function when alarm event occurs.
*
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
* @param reload Counter reload mode.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_set_auto_reload(timer_group_t group_num, timer_idx_t timer_num, timer_autoreload_t reload);
/**
* @brief Set hardware timer source clock divider. Timer groups clock are divider from APB clock.
*
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
* @param divider Timer clock divider value.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_set_divider(timer_group_t group_num, timer_idx_t timer_num, uint16_t divider);
/**
* @brief Set timer alarm value.
*
* @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
* @param alarm_value A 64-bit value to set the alarm value.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_set_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_value);
/**
* @brief Get timer alarm value.
*
* @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
* @param alarm_value Pointer of A 64-bit value to accept the alarm value.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_get_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t* alarm_value);
/**
* @brief Get timer alarm value.
*
* @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
* @param alarm_en To enable or disable timer alarm function.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_alarm_t alarm_en);
/**
* @brief register Timer 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 group_num Timer group number
* @param timer_num Timer index of timer group
* @param timer_intr_num TIMER interrupt number, check the info in soc.h, and please see the core-isa.h for more details
* @param intr_type Timer interrupt type
* @param fn Interrupt handler function.
* @note
* Code inside the handler function can only call functions in IRAM, so cannot call other timer APIs.
* Use direct register access to access timers from inside the ISR.
*
* @param arg Parameter for handler function
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Function pointer error.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num, int timer_intr_num, timer_intr_mode_t intr_type, void (*fn)(void*), void * arg);
/** @brief Initializes and configure the timer.
*
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
* @param config Pointer to timer initialization parameters.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, timer_config_t* config);
/** @brief Get timer configure value.
*
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
* @param config Pointer of struct to accept timer parameters.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_get_config(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config);
/** @brief Enable timer group interrupt, by enable mask
*
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
* @param en_mask Timer interrupt enable mask.
* Use TIMG_T0_INT_ENA_M to enable t0 interrupt
* Use TIMG_T1_INT_ENA_M to enable t1 interrupt
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_group_intr_enable(timer_group_t group_num, uint32_t en_mask);
/** @brief Disable timer group interrupt, by disable mask
*
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
* @param disable_mask Timer interrupt disable mask.
* Use TIMG_T0_INT_ENA_M to disable t0 interrupt
* Use TIMG_T1_INT_ENA_M to disable t1 interrupt
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_group_intr_disable(timer_group_t group_num, uint32_t disable_mask);
/** @brief Enable timer interrupt
*
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
* @param timer_num Timer index.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_enable_intr(timer_group_t group_num, timer_idx_t timer_num);
/** @brief Disable timer interrupt
*
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
* @param timer_num Timer index.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t timer_disable_intr(timer_group_t group_num, timer_idx_t timer_num);
#ifdef __cplusplus
}
#endif
#endif /* _TIMER_H_ */

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

@ -137,29 +137,32 @@ esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf)
return ESP_ERR_INVALID_ARG;
}
if(timer_num > LEDC_TIMER_3) {
ESP_LOGE(LEDC_TAG, "Time Select %u", timer_num);
ESP_LOGE(LEDC_TAG, "invalid timer #%u", timer_num);
return ESP_ERR_INVALID_ARG;
}
esp_err_t ret = ESP_OK;
uint32_t precision = (0x1 << bit_num); //2**depth
uint64_t div_param = ((uint64_t) LEDC_APB_CLK_HZ << 8) / freq_hz / precision; //8bit fragment
int timer_clk_src;
/*Fail ,because the div_num overflow or too small*/
if(div_param <= 256 || div_param > LEDC_DIV_NUM_HSTIMER0_V) { //REF TICK
/*Selet the reference tick*/
uint32_t precision = (0x1 << bit_num); // 2**depth
// Try calculating divisor based on LEDC_APB_CLK
ledc_clk_src_t timer_clk_src = LEDC_APB_CLK;
// div_param is a Q10.8 fixed point value
uint64_t div_param = ((uint64_t) LEDC_APB_CLK_HZ << 8) / freq_hz / precision;
if (div_param < 256) {
// divisor is too low
ESP_LOGE(LEDC_TAG, "requested frequency and bit depth can not be achieved, try reducing freq_hz or bit_num. div_param=%d", (uint32_t) div_param);
ret = ESP_FAIL;
}
if (div_param > LEDC_DIV_NUM_HSTIMER0_V) {
// APB_CLK results in divisor which too high. Try using REF_TICK as clock source.
timer_clk_src = LEDC_REF_TICK;
div_param = ((uint64_t) LEDC_REF_CLK_HZ << 8) / freq_hz / precision;
if(div_param <= 256 || div_param > LEDC_DIV_NUM_HSTIMER0_V) {
ESP_LOGE(LEDC_TAG, "div param err,div_param=%u", (uint32_t)div_param);
if(div_param < 256 || div_param > LEDC_DIV_NUM_HSTIMER0_V) {
ESP_LOGE(LEDC_TAG, "requested frequency and bit depth can not be achieved, try increasing freq_hz or bit_num. div_param=%d", (uint32_t) div_param);
ret = ESP_FAIL;
}
timer_clk_src = LEDC_REF_TICK;
} else { //APB TICK
timer_clk_src = LEDC_APB_CLK;
}
/*set timer parameters*/
/*timer settings decide the clk of counter and the period of PWM*/
// set timer parameters
ledc_timer_set(speed_mode, timer_num, div_param, bit_num, timer_clk_src);
/* reset timer.*/
// reset timer
ledc_timer_rst(speed_mode, timer_num);
return ret;
}
@ -174,7 +177,8 @@ esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc
if(speed_mode == LEDC_HIGH_SPEED_MODE) {
gpio_matrix_out(gpio_num, LEDC_HS_SIG_OUT0_IDX + ledc_channel, 0, 0);
} else {
ESP_LOGE(LEDC_TAG, "low speed mode is not implemented");
return ESP_ERR_NOT_SUPPORTED;
}
return ESP_OK;
}
@ -191,6 +195,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;
}

275
components/driver/timer.c Normal file
View File

@ -0,0 +1,275 @@
// 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 <string.h>
#include "esp_log.h"
#include "esp_err.h"
#include "esp_intr.h"
#include "freertos/FreeRTOS.h"
#include "freertos/xtensa_api.h"
#include "driver/timer.h"
#include "driver/periph_ctrl.h"
static const char* TIMER_TAG = "TIMER_GROUP";
#define TIMER_CHECK(a, str, ret_val) if (!(a)) { \
ESP_LOGE(TIMER_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
return (ret_val); \
}
#define TIMER_GROUP_NUM_ERROR "TIMER GROUP NUM ERROR"
#define TIMER_NUM_ERROR "HW TIMER NUM ERROR"
#define TIMER_PARAM_ADDR_ERROR "HW TIMER PARAM ADDR ERROR"
#define TIMER_COUNT_DIR_ERROR "HW TIMER COUNTER DIR ERROR"
#define TIMER_AUTORELOAD_ERROR "HW TIMER AUTORELOAD ERROR"
#define TIMER_SCALE_ERROR "HW TIMER SCALE ERROR"
#define TIMER_ALARM_ERROR "HW TIMER ALARM ERROR"
static timg_dev_t *TG[2] = {&TIMERG0, &TIMERG1};
static portMUX_TYPE timer_spinlock[TIMER_GROUP_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED};
#define TIMER_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux);
#define TIMER_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux);
esp_err_t timer_get_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t* timer_val)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_val != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
portENTER_CRITICAL(&timer_spinlock[group_num]);
TG[group_num]->hw_timer[timer_num].update = 1;
*timer_val = ((uint64_t) TG[group_num]->hw_timer[timer_num].cnt_high << 32)
| (TG[group_num]->hw_timer[timer_num].cnt_low);
portEXIT_CRITICAL(&timer_spinlock[group_num]);
return ESP_OK;
}
esp_err_t timer_get_counter_time_sec(timer_group_t group_num, timer_idx_t timer_num, double* time)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(time != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
uint64_t timer_val;
esp_err_t err = timer_get_counter_value(group_num, timer_num, &timer_val);
if (err == ESP_OK) {
uint16_t div = TG[group_num]->hw_timer[timer_num].config.divider;
*time = (double)timer_val * div / TIMER_BASE_CLK;
}
return err;
}
esp_err_t timer_set_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t load_val)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
TG[group_num]->hw_timer[timer_num].load_high = (uint32_t) (load_val >> 32);
TG[group_num]->hw_timer[timer_num].load_low = (uint32_t) load_val;
TG[group_num]->hw_timer[timer_num].reload = 1;
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
return ESP_OK;
}
esp_err_t timer_start(timer_group_t group_num, timer_idx_t timer_num)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
TG[group_num]->hw_timer[timer_num].config.enable = 1;
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
return ESP_OK;
}
esp_err_t timer_pause(timer_group_t group_num, timer_idx_t timer_num)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
TG[group_num]->hw_timer[timer_num].config.enable = 0;
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
return ESP_OK;
}
esp_err_t timer_set_counter_mode(timer_group_t group_num, timer_idx_t timer_num, timer_count_dir_t counter_dir)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(counter_dir < TIMER_COUNT_MAX, TIMER_COUNT_DIR_ERROR, ESP_ERR_INVALID_ARG);
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
TG[group_num]->hw_timer[timer_num].config.increase = counter_dir;
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
return ESP_OK;
}
esp_err_t timer_set_auto_reload(timer_group_t group_num, timer_idx_t timer_num, timer_autoreload_t reload)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(reload < TIMER_AUTORELOAD_MAX, TIMER_AUTORELOAD_ERROR, ESP_ERR_INVALID_ARG);
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
TG[group_num]->hw_timer[timer_num].config.autoreload = reload;
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
return ESP_OK;
}
esp_err_t timer_set_divider(timer_group_t group_num, timer_idx_t timer_num, uint16_t divider)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
int timer_en = TG[group_num]->hw_timer[timer_num].config.enable;
TG[group_num]->hw_timer[timer_num].config.enable = 0;
TG[group_num]->hw_timer[timer_num].config.divider = divider;
TG[group_num]->hw_timer[timer_num].config.enable = timer_en;
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
return ESP_OK;
}
esp_err_t timer_set_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_value)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
TG[group_num]->hw_timer[timer_num].alarm_high = (uint32_t) (alarm_value >> 32);
TG[group_num]->hw_timer[timer_num].alarm_low = (uint32_t) alarm_value;
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
return ESP_OK;
}
esp_err_t timer_get_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t* alarm_value)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(alarm_value != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
portENTER_CRITICAL(&timer_spinlock[group_num]);
*alarm_value = ((uint64_t) TG[group_num]->hw_timer[timer_num].alarm_high << 32)
| (TG[group_num]->hw_timer[timer_num].alarm_low);
portEXIT_CRITICAL(&timer_spinlock[group_num]);
return ESP_OK;
}
esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_alarm_t alarm_en)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(alarm_en < TIMER_ALARM_MAX, TIMER_ALARM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
TG[group_num]->hw_timer[timer_num].config.alarm_en = alarm_en;
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
return ESP_OK;
}
esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num, int timer_intr_num,
timer_intr_mode_t intr_type, void (*fn)(void*), void * arg)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(fn != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
ESP_INTR_DISABLE(timer_intr_num);
int intr_source = 0;
switch(group_num) {
case TIMER_GROUP_0:
default:
if(intr_type == TIMER_INTR_LEVEL) {
intr_source = ETS_TG0_T0_LEVEL_INTR_SOURCE + timer_num;
} else {
intr_source = ETS_TG0_T0_EDGE_INTR_SOURCE + timer_num;
}
break;
case TIMER_GROUP_1:
if(intr_type == TIMER_INTR_LEVEL) {
intr_source = ETS_TG1_T0_LEVEL_INTR_SOURCE + timer_num;
} else {
intr_source = ETS_TG1_T0_EDGE_INTR_SOURCE + timer_num;
}
break;
}
intr_matrix_set(xPortGetCoreID(), intr_source, timer_intr_num);
xt_set_interrupt_handler(timer_intr_num, fn, arg);
ESP_INTR_ENABLE(timer_intr_num);
return ESP_OK;
}
esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(config != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
if(group_num == 0) {
periph_module_enable(PERIPH_TIMG0_MODULE);
} else if(group_num == 1) {
periph_module_enable(PERIPH_TIMG1_MODULE);
}
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
TG[group_num]->hw_timer[timer_num].config.autoreload = config->auto_reload;
TG[group_num]->hw_timer[timer_num].config.divider = config->divider;
TG[group_num]->hw_timer[timer_num].config.enable = config->counter_en;
TG[group_num]->hw_timer[timer_num].config.increase = config->counter_dir;
TG[group_num]->hw_timer[timer_num].config.alarm_en = config->alarm_en;
TG[group_num]->hw_timer[timer_num].config.level_int_en = (config->intr_type == TIMER_INTR_LEVEL ? 1 : 0);
TG[group_num]->hw_timer[timer_num].config.edge_int_en = (config->intr_type == TIMER_INTR_LEVEL ? 0 : 1);
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
return ESP_OK;
}
esp_err_t timer_get_config(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(config != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
config->alarm_en = TG[group_num]->hw_timer[timer_num].config.alarm_en;
config->auto_reload = TG[group_num]->hw_timer[timer_num].config.autoreload;
config->counter_dir = TG[group_num]->hw_timer[timer_num].config.increase;
config->counter_dir = TG[group_num]->hw_timer[timer_num].config.divider;
config->counter_en = TG[group_num]->hw_timer[timer_num].config.enable;
if(TG[group_num]->hw_timer[timer_num].config.level_int_en) {
config->intr_type =TIMER_INTR_LEVEL;
}
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
return ESP_OK;
}
esp_err_t timer_group_intr_enable(timer_group_t group_num, uint32_t en_mask)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
portENTER_CRITICAL(&timer_spinlock[group_num]);
TG[group_num]->int_ena.val |= en_mask;
portEXIT_CRITICAL(&timer_spinlock[group_num]);
return ESP_OK;
}
esp_err_t timer_group_intr_disable(timer_group_t group_num, uint32_t disable_mask)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
portENTER_CRITICAL(&timer_spinlock[group_num]);
TG[group_num]->int_ena.val &= (~disable_mask);
portEXIT_CRITICAL(&timer_spinlock[group_num]);
return ESP_OK;
}
esp_err_t timer_enable_intr(timer_group_t group_num, timer_idx_t timer_num)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
return timer_group_intr_enable(group_num, BIT(timer_num));
}
esp_err_t timer_disable_intr(timer_group_t group_num, timer_idx_t timer_num)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
return timer_group_intr_disable(group_num, BIT(timer_num));
}

View File

@ -4,7 +4,7 @@
COMPONENT_SRCDIRS := . hwcrypto
LIBS := core net80211 phy rtc pp wpa smartconfig coexist wps
LIBS := core net80211 phy rtc pp wpa smartconfig coexist wps wpa2
LINKER_SCRIPTS += -T esp32_out.ld -T esp32.common.ld -T esp32.rom.ld -T esp32.peripherals.ld

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(xtal_freq_t xtal_freq);
extern void rtc_set_cpu_freq(cpu_freq_t cpu_freq);
#include "phy.h"
#include "rtc.h"
/*
* This function is not exposed as an API at this point,

View File

@ -117,9 +117,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);
@ -155,6 +153,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
@ -175,7 +174,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

@ -28,6 +28,7 @@
#include <string.h>
#include "hwcrypto/aes.h"
#include "rom/aes.h"
#include "soc/dport_reg.h"
#include <sys/lock.h>
static _lock_t aes_lock;
@ -36,14 +37,23 @@ void esp_aes_acquire_hardware( void )
{
/* newlib locks lazy initialize on ESP-IDF */
_lock_acquire(&aes_lock);
ets_aes_enable();
/* Enable AES hardware */
REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES);
/* Clear reset on digital signature & secure boot units,
otherwise AES unit is held in reset also. */
REG_CLR_BIT(DPORT_PERI_RST_EN_REG,
DPORT_PERI_EN_AES
| DPORT_PERI_EN_DIGITAL_SIGNATURE
| DPORT_PERI_EN_SECUREBOOT);
}
void esp_aes_release_hardware( void )
{
uint8_t zero[256/8] = { 0 };
ets_aes_setkey_enc(zero, AES256);
ets_aes_disable();
/* Disable AES hardware */
REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_AES);
/* Don't return other units to reset, as this pulls
reset on RSA & SHA units, respectively. */
REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES);
_lock_release(&aes_lock);
}

View File

@ -26,242 +26,264 @@
*/
#include <string.h>
#include <stdio.h>
#include <sys/lock.h>
#include <byteswap.h>
#include <assert.h>
#include "hwcrypto/sha.h"
#include "rom/ets_sys.h"
#include "soc/dport_reg.h"
#include "soc/hwcrypto_reg.h"
static _lock_t sha_lock;
void esp_sha_acquire_hardware( void )
{
/* newlib locks lazy initialize on ESP-IDF */
_lock_acquire(&sha_lock);
ets_sha_enable();
inline static uint32_t SHA_LOAD_REG(esp_sha_type sha_type) {
return SHA_1_LOAD_REG + sha_type * 0x10;
}
void esp_sha_release_hardware( void )
{
/* Want to empty internal SHA buffers where possible,
need to check if this is sufficient for this. */
SHA_CTX zero = { 0 };
ets_sha_init(&zero);
ets_sha_disable();
_lock_release(&sha_lock);
inline static uint32_t SHA_BUSY_REG(esp_sha_type sha_type) {
return SHA_1_BUSY_REG + sha_type * 0x10;
}
/* Generic esp_shaX_update implementation */
static void esp_sha_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen, size_t block_size)
inline static uint32_t SHA_START_REG(esp_sha_type sha_type) {
return SHA_1_START_REG + sha_type * 0x10;
}
inline static uint32_t SHA_CONTINUE_REG(esp_sha_type sha_type) {
return SHA_1_CONTINUE_REG + sha_type * 0x10;
}
/* Single lock for SHA engine memory block
*/
static _lock_t memory_block_lock;
typedef struct {
_lock_t lock;
bool in_use;
} sha_engine_state;
/* Pointer to state of each concurrent SHA engine.
Indexes:
0 = SHA1
1 = SHA2_256
2 = SHA2_384 or SHA2_512
*/
static sha_engine_state engine_states[3];
/* Index into the sha_engine_state array */
inline static size_t sha_engine_index(esp_sha_type type) {
switch(type) {
case SHA1:
return 0;
case SHA2_256:
return 1;
default:
return 2;
}
}
/* Return digest length (in bytes) for a given SHA type */
inline static size_t sha_length(esp_sha_type type) {
switch(type) {
case SHA1:
return 20;
case SHA2_256:
return 32;
case SHA2_384:
return 48;
case SHA2_512:
return 64;
default:
return 0;
}
}
/* Return block size (in bytes) for a given SHA type */
inline static size_t block_length(esp_sha_type type) {
switch(type) {
case SHA1:
case SHA2_256:
return 64;
case SHA2_384:
case SHA2_512:
return 128;
default:
return 0;
}
}
void esp_sha_lock_memory_block(void)
{
/* Feed the SHA engine one block at a time */
_lock_acquire(&memory_block_lock);
}
void esp_sha_unlock_memory_block(void)
{
_lock_release(&memory_block_lock);
}
/* Lock to hold when changing SHA engine state,
allows checking of sha_engines_all_idle()
*/
static _lock_t state_change_lock;
inline static bool sha_engines_all_idle() {
return !engine_states[0].in_use
&& !engine_states[1].in_use
&& !engine_states[2].in_use;
}
static void esp_sha_lock_engine_inner(sha_engine_state *engine);
bool esp_sha_try_lock_engine(esp_sha_type sha_type)
{
sha_engine_state *engine = &engine_states[sha_engine_index(sha_type)];
if(_lock_try_acquire(&engine->lock) != 0) {
/* This SHA engine is already in use */
return false;
} else {
esp_sha_lock_engine_inner(engine);
return true;
}
}
void esp_sha_lock_engine(esp_sha_type sha_type)
{
sha_engine_state *engine = &engine_states[sha_engine_index(sha_type)];
_lock_acquire(&engine->lock);
esp_sha_lock_engine_inner(engine);
}
static void esp_sha_lock_engine_inner(sha_engine_state *engine)
{
_lock_acquire(&state_change_lock);
if (sha_engines_all_idle()) {
/* Enable SHA hardware */
REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA);
/* also clear reset on secure boot, otherwise SHA is held in reset */
REG_CLR_BIT(DPORT_PERI_RST_EN_REG,
DPORT_PERI_EN_SHA
| DPORT_PERI_EN_SECUREBOOT);
ets_sha_enable();
}
_lock_release(&state_change_lock);
assert( !engine->in_use && "in_use flag should be cleared" );
engine->in_use = true;
}
void esp_sha_unlock_engine(esp_sha_type sha_type)
{
sha_engine_state *engine = &engine_states[sha_engine_index(sha_type)];
_lock_acquire(&state_change_lock);
assert( engine->in_use && "in_use flag should be set" );
engine->in_use = false;
if (sha_engines_all_idle()) {
/* Disable SHA hardware */
/* Don't assert reset on secure boot, otherwise AES is held in reset */
REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_SHA);
REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA);
}
_lock_release(&state_change_lock);
_lock_release(&engine->lock);
}
void esp_sha_wait_idle(void)
{
while(REG_READ(SHA_1_BUSY_REG) == 1) {}
while(REG_READ(SHA_256_BUSY_REG) == 1) {}
while(REG_READ(SHA_384_BUSY_REG) == 1) {}
while(REG_READ(SHA_512_BUSY_REG) == 1) {}
}
void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state)
{
sha_engine_state *engine = &engine_states[sha_engine_index(sha_type)];
assert(engine->in_use && "SHA engine should be locked" );
esp_sha_lock_memory_block();
esp_sha_wait_idle();
REG_WRITE(SHA_LOAD_REG(sha_type), 1);
while(REG_READ(SHA_BUSY_REG(sha_type)) == 1) { }
uint32_t *digest_state_words = (uint32_t *)digest_state;
uint32_t *reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE);
if(sha_type == SHA2_384 || sha_type == SHA2_512) {
/* for these ciphers using 64-bit states, swap each pair of words */
for(int i = 0; i < sha_length(sha_type)/4; i += 2) {
digest_state_words[i+1] = reg_addr_buf[i];
digest_state_words[i]= reg_addr_buf[i+1];
}
} else {
memcpy(digest_state_words, reg_addr_buf, sha_length(sha_type));
}
asm volatile ("memw");
esp_sha_unlock_memory_block();
}
void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block)
{
sha_engine_state *engine = &engine_states[sha_engine_index(sha_type)];
assert(engine->in_use && "SHA engine should be locked" );
esp_sha_lock_memory_block();
esp_sha_wait_idle();
/* Fill the data block */
uint32_t *reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE);
uint32_t *data_words = (uint32_t *)data_block;
for (int i = 0; i < block_length(sha_type) / 4; i++) {
reg_addr_buf[i] = __bswap_32(data_words[i]);
}
asm volatile ("memw");
if(is_first_block) {
REG_WRITE(SHA_START_REG(sha_type), 1);
} else {
REG_WRITE(SHA_CONTINUE_REG(sha_type), 1);
}
esp_sha_unlock_memory_block();
/* Note: deliberately not waiting for this operation to complete,
as a performance tweak - delay waiting until the next time we need the SHA
unit, instead.
*/
}
void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output)
{
size_t block_len = block_length(sha_type);
esp_sha_lock_engine(sha_type);
SHA_CTX ctx;
ets_sha_init(&ctx);
while(ilen > 0) {
size_t chunk_len = (ilen > block_size) ? block_size : ilen;
ets_sha_update(&ctx->context, ctx->context_type, input, chunk_len * 8);
size_t chunk_len = (ilen > block_len) ? block_len : ilen;
esp_sha_lock_memory_block();
esp_sha_wait_idle();
ets_sha_update(&ctx, sha_type, input, chunk_len * 8);
esp_sha_unlock_memory_block();
input += chunk_len;
ilen -= chunk_len;
}
esp_sha_lock_memory_block();
esp_sha_wait_idle();
ets_sha_finish(&ctx, sha_type, output);
esp_sha_unlock_memory_block();
esp_sha_unlock_engine(sha_type);
}
void esp_sha1_init( esp_sha_context *ctx )
{
bzero( ctx, sizeof( esp_sha_context ) );
}
void esp_sha1_free( esp_sha_context *ctx )
{
if ( ctx == NULL ) {
return;
}
bzero( ctx, sizeof( esp_sha_context ) );
}
void esp_sha1_clone( esp_sha_context *dst, const esp_sha_context *src )
{
*dst = *src;
}
/*
* SHA-1 context setup
*/
void esp_sha1_start( esp_sha_context *ctx )
{
ctx->context_type = SHA1;
esp_sha_acquire_hardware();
ets_sha_init(&ctx->context);
}
/*
* SHA-1 process buffer
*/
void esp_sha1_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen )
{
esp_sha_update(ctx, input, ilen, 64);
}
/*
* SHA-1 final digest
*/
void esp_sha1_finish( esp_sha_context *ctx, unsigned char output[20] )
{
ets_sha_finish(&ctx->context, ctx->context_type, output);
esp_sha_release_hardware();
}
/* Full SHA-1 calculation */
void esp_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] )
{
esp_sha_context ctx;
esp_sha1_init( &ctx );
esp_sha1_start( &ctx );
esp_sha1_update( &ctx, input, ilen );
esp_sha1_finish( &ctx, output );
esp_sha1_free( &ctx );
}
void esp_sha256_init( esp_sha_context *ctx )
{
bzero( ctx, sizeof( esp_sha_context ) );
}
void esp_sha256_free( esp_sha_context *ctx )
{
if ( ctx == NULL ) {
return;
}
bzero( ctx, sizeof( esp_sha_context ) );
}
void esp_sha256_clone( esp_sha_context *dst, const esp_sha_context *src )
{
*dst = *src;
}
/*
* SHA-256 context setup
*/
void esp_sha256_start( esp_sha_context *ctx, int is224 )
{
if ( is224 == 0 ) {
/* SHA-256 */
ctx->context_type = SHA2_256;
esp_sha_acquire_hardware();
ets_sha_init(&ctx->context);
} else {
/* SHA-224 is not supported! */
ctx->context_type = SHA_INVALID;
}
}
/*
* SHA-256 process buffer
*/
void esp_sha256_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen )
{
if( ctx->context_type == SHA2_256 ) {
esp_sha_update(ctx, input, ilen, 64);
}
/* SHA-224 is a no-op */
}
/*
* SHA-256 final digest
*/
void esp_sha256_finish( esp_sha_context *ctx, unsigned char output[32] )
{
if ( ctx->context_type == SHA2_256 ) {
ets_sha_finish(&ctx->context, ctx->context_type, output);
esp_sha_release_hardware();
} else {
/* No hardware SHA-224 support, but mbedTLS API doesn't allow failure.
For now, zero the output to make it clear it's not valid. */
bzero( output, 28 );
}
}
/*
* Full SHA-256 calculation
*/
void esp_sha256( const unsigned char *input, size_t ilen, unsigned char output[32], int is224 )
{
esp_sha_context ctx;
esp_sha256_init( &ctx );
esp_sha256_start( &ctx, is224 );
esp_sha256_update( &ctx, input, ilen );
esp_sha256_finish( &ctx, output );
esp_sha256_free( &ctx );
}
/////
void esp_sha512_init( esp_sha_context *ctx )
{
memset( ctx, 0, sizeof( esp_sha_context ) );
}
void esp_sha512_free( esp_sha_context *ctx )
{
if ( ctx == NULL ) {
return;
}
bzero( ctx, sizeof( esp_sha_context ) );
}
void esp_sha512_clone( esp_sha_context *dst, const esp_sha_context *src )
{
*dst = *src;
}
/*
* SHA-512 context setup
*/
void esp_sha512_start( esp_sha_context *ctx, int is384 )
{
if ( is384 == 0 ) {
/* SHA-512 */
ctx->context_type = SHA2_512;
} else {
/* SHA-384 */
ctx->context_type = SHA2_384;
}
esp_sha_acquire_hardware();
ets_sha_init(&ctx->context);
}
/*
* SHA-512 process buffer
*/
void esp_sha512_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen )
{
esp_sha_update(ctx, input, ilen, 128);
}
/*
* SHA-512 final digest
*/
void esp_sha512_finish( esp_sha_context *ctx, unsigned char output[64] )
{
ets_sha_finish(&ctx->context, ctx->context_type, output);
esp_sha_release_hardware();
}
/*
* Full SHA-512 calculation
*/
void esp_sha512( const unsigned char *input, size_t ilen, unsigned char output[64], int is384 )
{
esp_sha_context ctx;
esp_sha512_init( &ctx );
esp_sha512_start( &ctx, is384 );
esp_sha512_update( &ctx, input, ilen );
esp_sha512_finish( &ctx, output );
esp_sha512_free( &ctx );
}
////

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

@ -114,8 +114,6 @@ typedef struct {
typedef enum {
WIFI_PS_NONE, /**< No power save */
WIFI_PS_MODEM, /**< Modem power save */
WIFI_PS_LIGHT, /**< Light power save */
WIFI_PS_MAC, /**< MAC power save */
} wifi_ps_type_t;
#define WIFI_PROTOCOL_11B 1

View File

@ -0,0 +1,166 @@
// 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 ESP_WPA2_H
#define ESP_WPA2_H
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable wpa2 enterprise authentication.
*
* @attention wpa2 enterprise authentication can only be used when ESP32 station is enabled.
* wpa2 enterprise authentication can only support TLS, PEAP-MSCHAPv2 and TTLS-MSCHAPv2 method.
*
* @return ESP_ERR_WIFI_OK: succeed.
* ESP_ERR_WIFI_NO_MEM: fail(internal memory malloc fail)
*/
esp_err_t esp_wifi_sta_wpa2_ent_enable(void);
/**
* @brief Disable wpa2 enterprise authentication.
*
* @attention wpa2 enterprise authentication can only be used when ESP32 station is enabled.
* wpa2 enterprise authentication can only support TLS, PEAP-MSCHAPv2 and TTLS-MSCHAPv2 method.
*
* @return ESP_ERR_WIFI_OK: succeed.
*/
esp_err_t esp_wifi_sta_wpa2_ent_disable(void);
/**
* @brief Set username for PEAP/TTLS method.
*
* @attention The API only passes the parameter username to the global pointer variable in wpa2 enterprise module.
*
* @param username: point to address where stores the username;
* len: length of username, limited to 1~127
*
* @return ESP_ERR_WIFI_OK: succeed
* ESP_ERR_WIFI_ARG: fail(len <= 0 or len >= 128)
* ESP_ERR_WIFI_NO_MEM: fail(internal memory malloc fail)
*/
esp_err_t esp_wifi_sta_wpa2_ent_set_username(unsigned char *username, int len);
/**
* @brief Clear username for PEAP/TTLS method.
*/
void esp_wifi_sta_wpa2_ent_clear_username(void);
/**
* @brief Set password for PEAP/TTLS method..
*
* @attention The API only passes the parameter password to the global pointer variable in wpa2 enterprise module.
*
* @param password: point to address where stores the password;
* len: length of password(len > 0)
*
* @return ESP_ERR_WIFI_OK: succeed
* ESP_ERR_WIFI_ARG: fail(len <= 0)
* ESP_ERR_WIFI_NO_MEM: fail(internal memory malloc fail)
*/
esp_err_t esp_wifi_sta_wpa2_ent_set_password(unsigned char *password, int len);
/**
* @brief Clear password for PEAP/TTLS method..
*/
void esp_wifi_sta_wpa2_ent_clear_password(void);
/**
* @brief Set new password for MSCHAPv2 method..
*
* @attention The API only passes the parameter password to the global pointer variable in wpa2 enterprise module.
* The new password is used to substitute the old password when eap-mschapv2 failure request message with error code ERROR_PASSWD_EXPIRED is received.
*
* @param password: point to address where stores the password;
* len: length of password
*
* @return ESP_ERR_WIFI_OK: succeed
* ESP_ERR_WIFI_ARG: fail(len <= 0)
* ESP_ERR_WIFI_NO_MEM: fail(internal memory malloc fail)
*/
esp_err_t esp_wifi_sta_wpa2_ent_set_new_password(unsigned char *password, int len);
/**
* @brief Clear new password for MSCHAPv2 method..
*/
void esp_wifi_sta_wpa2_ent_clear_new_password(void);
/**
* @brief Set CA certificate for PEAP/TTLS method.
*
* @attention The API only passes the parameter ca_cert to the global pointer variable in wpa2 enterprise module.
* The ca_cert should be zero terminated.
*
* @param ca_cert: point to address where stores the CA certificate;
* len: length of ca_cert
*
* @return ESP_ERR_WIFI_OK: succeed
*/
esp_err_t esp_wifi_sta_wpa2_ent_set_ca_cert(unsigned char *ca_cert, int len);
/**
* @brief Clear CA certificate for PEAP/TTLS method.
*/
void esp_wifi_sta_wpa2_ent_clear_ca_cert(void);
/**
* @brief Set client certificate and key.
*
* @attention The API only passes the parameter client_cert, private_key and private_key_passwd to the global pointer variable in wpa2 enterprise module.
* The client_cert, private_key and private_key_passwd should be zero terminated.
*
* @param client_cert: point to address where stores the client certificate;
* client_cert_len: length of client certificate;
* private_key: point to address where stores the private key;
* private_key_len: length of private key;
* private_key_password: point to address where stores the private key password;
* private_key_password_len: length of private key password;
*
* @return ESP_ERR_WIFI_OK: succeed
*/
esp_err_t esp_wifi_sta_wpa2_ent_set_cert_key(unsigned char *client_cert, int client_cert_len, unsigned char *private_key, int private_key_len, unsigned char *private_key_passwd, int private_key_passwd_len);
/**
* @brief Clear client certificate and key.
*/
void esp_wifi_sta_wpa2_ent_clear_cert_key(void);
/**
* @brief Set wpa2 enterprise certs time check(disable or not).
*
* @param true: disable wpa2 enterprise certs time check
* false: enable wpa2 enterprise certs time check
*
* @return ESP_OK: succeed
*/
esp_err_t esp_wifi_sta_wpa2_ent_set_disable_time_check(bool disable);
/**
* @brief Get wpa2 enterprise certs time check(disable or not).
*
* @param disable: store disable value
*
* @return ESP_OK: succeed
*/
esp_err_t esp_wifi_sta_wpa2_ent_get_disable_time_check(bool *disable);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,246 +1,203 @@
/*
* ESP32 hardware accelerated SHA1/256/512 implementation
* based on mbedTLS FIPS-197 compliant version.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*
*/
// 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 _ESP_SHA_H_
#define _ESP_SHA_H_
#include "rom/sha.h"
#include "esp_types.h"
/** @brief Low-level support functions for the hardware SHA engine
*
* @note If you're looking for a SHA API to use, try mbedtls component
* mbedtls/shaXX.h. That API supports hardware acceleration.
*
* The API in this header provides some building blocks for implementing a
* full SHA API such as the one in mbedtls, and also a basic SHA function esp_sha().
*
* Some technical details about the hardware SHA engine:
*
* - SHA accelerator engine calculates one digest at a time, per SHA
* algorithm type. It initialises and maintains the digest state
* internally. It is possible to read out an in-progress SHA digest
* state, but it is not possible to restore a SHA digest state
* into the engine.
*
* - The memory block SHA_TEXT_BASE is shared between all SHA digest
* engines, so all engines must be idle before this memory block is
* modified.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief SHA-1 context structure
*/
typedef struct {
/* both types defined in rom/sha.h */
SHA_CTX context;
enum SHA_TYPE context_type;
} esp_sha_context;
/* Defined in rom/sha.h */
typedef enum SHA_TYPE esp_sha_type;
/**
* \brief Lock access to SHA hardware unit
/** @brief Calculate SHA1 or SHA2 sum of some data, using hardware SHA engine
*
* SHA hardware unit can only be used by one
* consumer at a time.
* @note For more versatile SHA calculations, where data doesn't need
* to be passed all at once, try the mbedTLS mbedtls/shaX.h APIs. The
* hardware-accelerated mbedTLS implementation is also faster when
* hashing large amounts of data.
*
* esp_sha_xxx API calls automatically manage locking & unlocking of
* hardware, this function is only needed if you want to call
* ets_sha_xxx functions directly.
*/
void esp_sha_acquire_hardware( void );
/**
* \brief Unlock access to SHA hardware unit
* @note It is not necessary to lock any SHA hardware before calling
* this function, thread safety is managed internally.
*
* esp_sha_xxx API calls automatically manage locking & unlocking of
* hardware, this function is only needed if you want to call
* ets_sha_xxx functions directly.
*/
void esp_sha_release_hardware( void );
/**
* \brief Initialize SHA-1 context
* @note If a TLS connection is open then this function may block
* indefinitely waiting for a SHA engine to become available. Use the
* mbedTLS SHA API to avoid this problem.
*
* \param ctx SHA-1 context to be initialized
*/
void esp_sha1_init( esp_sha_context *ctx );
/**
* \brief Clear SHA-1 context
* @param sha_type SHA algorithm to use.
*
* \param ctx SHA-1 context to be cleared
*/
void esp_sha1_free( esp_sha_context *ctx );
/**
* \brief Clone (the state of) a SHA-1 context
* @param input Input data buffer.
*
* \param dst The destination context
* \param src The context to be cloned
*/
void esp_sha1_clone( esp_sha_context *dst, const esp_sha_context *src );
/**
* \brief SHA-1 context setup
* @param ilen Length of input data in bytes.
*
* \param ctx context to be initialized
* @param output Buffer for output SHA digest. Output is 20 bytes for
* sha_type SHA1, 32 bytes for sha_type SHA2_256, 48 bytes for
* sha_type SHA2_384, 64 bytes for sha_type SHA2_512.
*/
void esp_sha1_start( esp_sha_context *ctx );
void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output);
/**
* \brief SHA-1 process buffer
/* @brief Begin to execute a single SHA block operation
*
* \param ctx SHA-1 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void esp_sha1_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-1 final digest
* @note This is a piece of a SHA algorithm, rather than an entire SHA
* algorithm.
*
* \param ctx SHA-1 context
* \param output SHA-1 checksum result
*/
void esp_sha1_finish( esp_sha_context *ctx, unsigned char output[20] );
/**
* \brief Calculate SHA-1 of input buffer
* @note Call esp_sha_try_lock_engine() before calling this
* function. Do not call esp_sha_lock_memory_block() beforehand, this
* is done inside the function.
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-1 checksum result
*/
void esp_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] );
/**
* \brief SHA-256 context structure
*/
/**
* \brief Initialize SHA-256 context
* @param sha_type SHA algorithm to use.
*
* \param ctx SHA-256 context to be initialized
*/
void esp_sha256_init( esp_sha_context *ctx );
/**
* \brief Clear SHA-256 context
* @param data_block Pointer to block of data. Block size is
* determined by algorithm (SHA1/SHA2_256 = 64 bytes,
* SHA2_384/SHA2_512 = 128 bytes)
*
* \param ctx SHA-256 context to be cleared
*/
void esp_sha256_free( esp_sha_context *ctx );
/**
* \brief Clone (the state of) a SHA-256 context
* @param is_first_block If this parameter is true, the SHA state will
* be initialised (with the initial state of the given SHA algorithm)
* before the block is calculated. If false, the existing state of the
* SHA engine will be used.
*
* \param dst The destination context
* \param src The context to be cloned
* @return As a performance optimisation, this function returns before
* the SHA block operation is complete. Both this function and
* esp_sha_read_state() will automatically wait for any previous
* operation to complete before they begin. If using the SHA registers
* directly in another way, call esp_sha_wait_idle() after calling this
* function but before accessing the SHA registers.
*/
void esp_sha256_clone( esp_sha_context *dst, const esp_sha_context *src );
void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block);
/**
* \brief SHA-256 context setup
/** @brief Read out the current state of the SHA digest loaded in the engine.
*
* \param ctx context to be initialized
* \param is224 0 = use SHA256, 1 = use SHA224
*/
void esp_sha256_start( esp_sha_context *ctx, int is224 );
/**
* \brief SHA-256 process buffer
* @note This is a piece of a SHA algorithm, rather than an entire SHA algorithm.
*
* \param ctx SHA-256 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void esp_sha256_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-256 final digest
* @note Call esp_sha_try_lock_engine() before calling this
* function. Do not call esp_sha_lock_memory_block() beforehand, this
* is done inside the function.
*
* \param ctx SHA-256 context
* \param output SHA-224/256 checksum result
*/
void esp_sha256_finish( esp_sha_context *ctx, unsigned char output[32] );
/**
* \brief Calculate SHA-256 of input buffer
* If the SHA suffix padding block has been executed already, the
* value that is read is the SHA digest (in big endian
* format). Otherwise, the value that is read is an interim SHA state.
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-224/256 checksum result
* \param is224 0 = use SHA256, 1 = use SHA224
*/
void esp_sha256( const unsigned char *input, size_t ilen, unsigned char output[32], int is224 );
//
/**
* \brief SHA-512 context structure
*/
/**
* \brief Initialize SHA-512 context
* @note If sha_type is SHA2_384, only 48 bytes of state will be read.
* This is enough for the final SHA2_384 digest, but if you want the
* interim SHA-384 state (to continue digesting) then pass SHA2_512 instead.
*
* @param sha_type SHA algorithm in use.
*
* @param state Pointer to a memory buffer to hold the SHA state. Size
* is 20 bytes (SHA1), 32 bytes (SHA2_256), 48 bytes (SHA2_384) or 64 bytes (SHA2_512).
*
* \param ctx SHA-512 context to be initialized
*/
void esp_sha512_init( esp_sha_context *ctx );
void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state);
/**
* \brief Clear SHA-512 context
* @brief Obtain exclusive access to a particular SHA engine
*
* \param ctx SHA-512 context to be cleared
* @param sha_type Type of SHA engine to use.
*
* Blocks until engine is available. Note: Can block indefinitely
* while a TLS connection is open, suggest using
* esp_sha_try_lock_engine() and failing over to software SHA.
*/
void esp_sha512_free( esp_sha_context *ctx );
void esp_sha_lock_engine(esp_sha_type sha_type);
/**
* \brief Clone (the state of) a SHA-512 context
* @brief Try and obtain exclusive access to a particular SHA engine
*
* \param dst The destination context
* \param src The context to be cloned
* @param sha_type Type of SHA engine to use.
*
* @return Returns true if the SHA engine is locked for exclusive
* use. Call esp_sha_unlock_sha_engine() when done. Returns false if
* the SHA engine is already in use, caller should use software SHA
* algorithm for this digest.
*/
void esp_sha512_clone( esp_sha_context *dst, const esp_sha_context *src );
bool esp_sha_try_lock_engine(esp_sha_type sha_type);
/**
* \brief SHA-512 context setup
* @brief Unlock an engine previously locked with esp_sha_lock_engine() or esp_sha_try_lock_engine()
*
* \param ctx context to be initialized
* \param is384 0 = use SHA512, 1 = use SHA384
* @param sha_type Type of engine to release.
*/
void esp_sha512_start( esp_sha_context *ctx, int is384 );
void esp_sha_unlock_engine(esp_sha_type sha_type);
/**
* \brief SHA-512 process buffer
* @brief Acquire exclusive access to the SHA shared memory block at SHA_TEXT_BASE
*
* \param ctx SHA-512 context
* \param input buffer holding the data
* \param ilen length of the input data
* This memory block is shared across all the SHA algorithm types.
*
* Caller should have already locked a SHA engine before calling this function.
*
* Note that it is possible to obtain exclusive access to the memory block even
* while it is in use by the SHA engine. Caller should use esp_sha_wait_idle()
* to ensure the SHA engine is not reading from the memory block in hardware.
*
* @note You do not need to lock the memory block before calling esp_sha_block() or esp_sha_read_digest_state(), these functions handle memory block locking internally.
*
* Call esp_sha_unlock_memory_block() when done.
*/
void esp_sha512_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen );
void esp_sha_lock_memory_block(void);
/**
* \brief SHA-512 final digest
* @brief Release exclusive access to the SHA register memory block at SHA_TEXT_BASE
*
* \param ctx SHA-512 context
* \param output SHA-384/512 checksum result
*/
void esp_sha512_finish( esp_sha_context *ctx, unsigned char output[64] );
/**
* \brief Calculate SHA-512 of input buffer.
* Caller should have already locked a SHA engine before calling this function.
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-384/512 checksum result
* \param is384 0 = use SHA512, 1 = use SHA384
* Call following esp_sha_lock_memory_block().
*/
void esp_sha512( const unsigned char *input, size_t ilen, unsigned char output[64], int is384 );
void esp_sha_unlock_memory_block(void);
//
/** @brief Wait for the SHA engine to finish any current operation
*
* @note This function does not ensure exclusive access to any SHA
* engine. Caller should use esp_sha_try_lock_engine() and
* esp_sha_lock_memory_block() as required.
*
* @note Functions declared in this header file wait for SHA engine
* completion automatically, so you don't need to use this API for
* these. However if accessing SHA registers directly, you will need
* to call this before accessing SHA registers if using the
* esp_sha_block() function.
*
* @note This function busy-waits, so wastes CPU resources.
* Best to delay calling until you are about to need it.
*
*/
void esp_sha_wait_idle(void);
#ifdef __cplusplus
}

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

@ -1,9 +1,10 @@
/*
ROM functions for hardware SHA support.
It is not recommended to use these functions directly,
use the wrapper functions in hwcrypto/sha.h instead.
It is not recommended to use these functions directly. If using
them from esp-idf then use the esp_sha_lock_engine() and
esp_sha_lock_memory_block() functions in hwcrypto/sha.h to ensure
exclusive access.
*/
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
@ -38,6 +39,8 @@ enum SHA_TYPE {
SHA2_256,
SHA2_384,
SHA2_512,
SHA_INVALID = -1,
};

View File

@ -384,7 +384,8 @@ SpiFlashOpResult SPIParamCfg(uint32_t deviceId, uint32_t chip_size, uint32_t blo
SpiFlashOpResult SPIEraseChip(void);
/**
* @brief Erase a block of flash.
* @brief Erase a 32KB block of flash
* Uses SPI flash command 52h.
* Please do not call this function in SDK.
*
* @param uint32_t block_num : Which block to erase.
@ -411,6 +412,12 @@ SpiFlashOpResult SPIEraseSector(uint32_t sector_num);
* @brief Erase some sectors.
* Please do not call this function in SDK.
*
* @note If calling this function, first set
* g_rom_flashchip.block_size = 32768; or call SPIParamCfg()
* with appropriate parameters. This is due to a ROM bug, the
* block erase command in use is a 32KB erase but after reset
* the block_size field is incorrectly set to 65536.
*
* @param uint32_t start_addr : Start addr to erase, should be sector aligned.
*
* @param uint32_t area_len : Length to erase, should be sector aligned.

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

@ -94,6 +94,16 @@
#define DPORT_PERI_RST_EN_V 0xFFFFFFFF
#define DPORT_PERI_RST_EN_S 0
/* The following bits apply to DPORT_PERI_CLK_EN_REG, DPORT_PERI_RST_EN_REG
*/
#define DPORT_PERI_EN_AES (1<<0)
#define DPORT_PERI_EN_SHA (1<<1)
#define DPORT_PERI_EN_RSA (1<<2)
/* NB: Secure boot reset will hold SHA & AES in reset */
#define DPORT_PERI_EN_SECUREBOOT (1<<3)
/* NB: Digital signature reset will hold AES & RSA in reset */
#define DPORT_PERI_EN_DIGITAL_SIGNATURE (1<<4)
#define DPORT_WIFI_BB_CFG_REG (DR_REG_DPORT_BASE + 0x024)
/* DPORT_WIFI_BB_CFG : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
/*description: */

View File

@ -30,8 +30,31 @@
#define RSA_MULT_MODE_REG (DR_REG_RSA_BASE + 0x80c)
#define RSA_MULT_START_REG (DR_REG_RSA_BASE + 0x810)
#define RSA_INTERRUPT_REG (DR_REG_RSA_BASE + 0X814)
#define RSA_INTERRUPT_REG (DR_REG_RSA_BASE + 0x814)
#define RSA_CLEAN_ADDR (DR_REG_RSA_BASE + 0X818)
#define RSA_CLEAN_REG (DR_REG_RSA_BASE + 0x818)
/* SHA acceleration registers */
#define SHA_TEXT_BASE ((DR_REG_SHA_BASE) + 0x00)
#define SHA_1_START_REG ((DR_REG_SHA_BASE) + 0x80)
#define SHA_1_CONTINUE_REG ((DR_REG_SHA_BASE) + 0x84)
#define SHA_1_LOAD_REG ((DR_REG_SHA_BASE) + 0x88)
#define SHA_1_BUSY_REG ((DR_REG_SHA_BASE) + 0x8c)
#define SHA_256_START_REG ((DR_REG_SHA_BASE) + 0x90)
#define SHA_256_CONTINUE_REG ((DR_REG_SHA_BASE) + 0x94)
#define SHA_256_LOAD_REG ((DR_REG_SHA_BASE) + 0x98)
#define SHA_256_BUSY_REG ((DR_REG_SHA_BASE) + 0x9c)
#define SHA_384_START_REG ((DR_REG_SHA_BASE) + 0xa0)
#define SHA_384_CONTINUE_REG ((DR_REG_SHA_BASE) + 0xa4)
#define SHA_384_LOAD_REG ((DR_REG_SHA_BASE) + 0xa8)
#define SHA_384_BUSY_REG ((DR_REG_SHA_BASE) + 0xac)
#define SHA_512_START_REG ((DR_REG_SHA_BASE) + 0xb0)
#define SHA_512_CONTINUE_REG ((DR_REG_SHA_BASE) + 0xb4)
#define SHA_512_LOAD_REG ((DR_REG_SHA_BASE) + 0xb8)
#define SHA_512_BUSY_REG ((DR_REG_SHA_BASE) + 0xbc)
#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
@ -142,6 +142,7 @@
#define DR_REG_DPORT_BASE 0x3ff00000
#define DR_REG_RSA_BASE 0x3ff02000
#define DR_REG_SHA_BASE 0x3ff03000
#define DR_REG_UART_BASE 0x3ff40000
#define DR_REG_SPI1_BASE 0x3ff42000
#define DR_REG_SPI0_BASE 0x3ff43000

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.

View File

@ -28,6 +28,7 @@
#include "esp_freertos_hooks.h"
#include "soc/timer_group_struct.h"
#include "soc/timer_group_reg.h"
#include "driver/timer.h"
#include "esp_int_wdt.h"
@ -85,7 +86,7 @@ void esp_int_wdt_init() {
TIMERG1.wdt_feed=1;
TIMERG1.wdt_wprotect=0;
TIMERG1.int_clr_timers.wdt=1;
TIMERG1.int_ena.wdt=1;
timer_group_intr_enable(TIMER_GROUP_1, TIMG_WDT_INT_ENA_M);
esp_register_freertos_tick_hook(tick_hook);
ESP_INTR_DISABLE(WDT_INT_NUM);
intr_matrix_set(xPortGetCoreID(), ETS_TG1_WDT_LEVEL_INTR_SOURCE, WDT_INT_NUM);
@ -97,4 +98,4 @@ void esp_int_wdt_init() {
#endif
#endif

@ -1 +1 @@
Subproject commit 93fcc0324cd9b4de8ae381a876d371dfd4eff8e3
Subproject commit 4ec70a8ac92828d68bd24acbb27fc179817b14ed

View File

@ -0,0 +1,133 @@
// 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 wpa2_printf(const char* format, ...)
{
va_list arg;
va_start(arg, format);
int res = lib_printf("wpa2", 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

@ -32,6 +32,7 @@
#include "soc/timer_group_struct.h"
#include "soc/timer_group_reg.h"
#include "esp_log.h"
#include "driver/timer.h"
#include "esp_task_wdt.h"
@ -204,9 +205,9 @@ void esp_task_wdt_init() {
intr_matrix_set(xPortGetCoreID(), ETS_TG0_WDT_LEVEL_INTR_SOURCE, ETS_T0_WDT_INUM);
xt_set_interrupt_handler(ETS_T0_WDT_INUM, task_wdt_isr, NULL);
TIMERG0.int_clr_timers.wdt=1;
TIMERG0.int_ena.wdt=1;
timer_group_intr_enable(TIMER_GROUP_0, TIMG_WDT_INT_ENA_M);
ESP_INTR_ENABLE(ETS_T0_WDT_INUM);
}
#endif
#endif

View File

@ -1,9 +0,0 @@
menu "TESTS"
config FP_TEST_ENABLE
bool "Enable test fp"
default "y"
help
For FPGA single core CPU which has no floating point support, floating point test should be disabled.
endmenu

View File

@ -4,7 +4,6 @@
#include "freertos/task.h"
#include "unity.h"
#if CONFIG_FP_TEST_ENABLE
static float addsf(float a, float b)
{
float result;
@ -192,4 +191,3 @@ TEST_CASE("context switch saves FP registers", "[fp]")
}
TEST_ASSERT(state.fail == 0);
}
#endif

View File

@ -609,9 +609,9 @@ void *xRingbufferReceiveUpToFromISR(RingbufHandle_t ringbuf, size_t *item_size,
void vRingbufferReturnItem(RingbufHandle_t ringbuf, void *item)
{
ringbuf_t *rb=(ringbuf_t *)ringbuf;
portENTER_CRITICAL_ISR(&rb->mux);
portENTER_CRITICAL(&rb->mux);
rb->returnItemToRingbufImpl(rb, item);
portEXIT_CRITICAL_ISR(&rb->mux);
portEXIT_CRITICAL(&rb->mux);
xSemaphoreGive(rb->free_space_sem);
}

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

@ -128,6 +128,7 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
len = q->tot_len;
if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) {
ESP_STATS_INC(esp.rx_rawmbox_post_fail);
netbuf_delete(buf);
return 0;
} else {
@ -203,6 +204,7 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
len = p->tot_len;
if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) {
ESP_STATS_INC(esp.rx_udpmbox_post_fail);
netbuf_delete(buf);
return;
} else {
@ -262,6 +264,7 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
}
if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) {
ESP_STATS_INC(esp.rx_tcpmbox_post_fail);
/* don't deallocate p: it is presented to us later again from tcp_fasttmr! */
return ERR_MEM;
} else {
@ -391,12 +394,16 @@ err_tcp(void *arg, err_t err)
/* pass NULL-message to recvmbox to wake up pending recv */
if (sys_mbox_valid(&conn->recvmbox)) {
/* use trypost to prevent deadlock */
sys_mbox_trypost(&conn->recvmbox, NULL);
if (sys_mbox_trypost(&conn->recvmbox, NULL) != ERR_OK){
ESP_STATS_INC(esp.err_tcp_rxmbox_post_fail);
}
}
/* pass NULL-message to acceptmbox to wake up pending accept */
if (sys_mbox_valid(&conn->acceptmbox)) {
/* use trypost to preven deadlock */
sys_mbox_trypost(&conn->acceptmbox, NULL);
if (sys_mbox_trypost(&conn->acceptmbox, NULL) != ERR_OK) {
ESP_STATS_INC(esp.err_tcp_rxmbox_post_fail);
}
}
if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) ||
@ -476,6 +483,7 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
newconn->last_err = err;
if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) {
ESP_STATS_INC(esp.acceptmbox_post_fail);
/* When returning != ERR_OK, the pcb is aborted in tcp_process(),
so do nothing here! */
/* remove all references to this netconn from the pcb */

View File

@ -18,6 +18,9 @@
#include "lwip/tcp.h"
#include "lwip/udp.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/stats.h"
#include "lwip/priv/memp_priv.h"
#include "lwip/memp.h"
#define DBG_LWIP_IP_SHOW(info, ip) printf("%s type=%d ip=%x\n", (info), (ip).type, (ip).u_addr.ip4.addr)
#define DBG_LWIP_IP_PCB_SHOW(pcb) \
@ -127,3 +130,42 @@ void dbg_lwip_udp_rxtx_show(void)
printf("TBC\n");
}
void dbg_lwip_stats_show(void)
{
TCP_STATS_DISPLAY();
UDP_STATS_DISPLAY();
ICMP_STATS_DISPLAY();
IGMP_STATS_DISPLAY();
IP_STATS_DISPLAY();
IPFRAG_STATS_DISPLAY();
ETHARP_STATS_DISPLAY();
LINK_STATS_DISPLAY();
MEM_STATS_DISPLAY();
SYS_STATS_DISPLAY();
IP6_STATS_DISPLAY();
ICMP6_STATS_DISPLAY();
IP6_FRAG_STATS_DISPLAY();
MLD6_STATS_DISPLAY();
ND6_STATS_DISPLAY();
ESP_STATS_DISPLAY();
}
#if (ESP_CNT_DEBUG == 1)
uint32_t g_lwip_mem_cnt[MEMP_MAX][2];
extern const struct memp_desc * const memp_pools[MEMP_MAX];
void dbg_lwip_cnt_show(void)
{
int i=0;
printf("-----lwip memory counter-----\n");
printf("%6s %8s %8s\n", "index", "alloc", "free");
for (i=0; i<MEMP_MAX; i++){
printf("%6u %8u %8u\n", i, g_lwip_mem_cnt[i][0], g_lwip_mem_cnt[i][1]);
}
}
#endif

View File

@ -56,9 +56,6 @@
#define TCPIP_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_TCPIP_MSG_API, name)
/* global variables */
#if ESP_PERF
uint32_t g_rx_post_mbox_fail_cnt = 0;
#endif
static tcpip_init_done_fn tcpip_init_done;
static void *tcpip_init_done_arg;
static sys_mbox_t mbox;
@ -223,9 +220,7 @@ tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
msg->msg.inp.netif = inp;
msg->msg.inp.input_fn = input_fn;
if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
#if ESP_PERF
g_rx_post_mbox_fail_cnt ++;
#endif
ESP_STATS_INC(esp.tcpip_inpkt_post_fail);
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
return ERR_MEM;
}
@ -282,6 +277,7 @@ tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
sys_mbox_post(&mbox, msg);
} else {
if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
ESP_STATS_INC(esp.tcpip_cb_post_fail);
memp_free(MEMP_TCPIP_MSG_API, msg);
return ERR_MEM;
}
@ -497,8 +493,13 @@ tcpip_init(tcpip_init_done_fn initfunc, void *arg)
#if ESP_LWIP
#if ESP_DUAL_CORE
sys_thread_t xLwipTaskHandle = 0;
xTaskCreatePinnedToCore(tcpip_thread, TCPIP_THREAD_NAME, TCPIP_THREAD_STACKSIZE, NULL, TCPIP_THREAD_PRIO, NULL, 1);
#else
sys_thread_t xLwipTaskHandle = sys_thread_new(TCPIP_THREAD_NAME
, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
#endif
printf("tcpip_task_hdlxxx : %x, prio:%d,stack:%d\n",
(u32_t)xLwipTaskHandle,TCPIP_THREAD_PRIO,TCPIP_THREAD_STACKSIZE);

View File

@ -180,5 +180,23 @@ stats_display(void)
}
#endif /* LWIP_STATS_DISPLAY */
#if ESP_STATS
void stats_display_esp(struct stats_esp *esp)
{
LWIP_PLATFORM_DIAG(("\nESP\n\t"));
LWIP_PLATFORM_DIAG(("esp.rx_rawmbox_post_fail: %"U32_F"\n\t", (u32_t)esp->rx_rawmbox_post_fail));
LWIP_PLATFORM_DIAG(("esp.rx_udpmbox_post_fail: %"U32_F"\n\t", (u32_t)esp->rx_udpmbox_post_fail));
LWIP_PLATFORM_DIAG(("esp.rx_tcpmbox_post_fail: %"U32_F"\n\t", (u32_t)esp->rx_tcpmbox_post_fail));
LWIP_PLATFORM_DIAG(("esp.err_tcp_rxmbox_post_fail: %"U32_F"\n\t", (u32_t)esp->err_tcp_rxmbox_post_fail));
LWIP_PLATFORM_DIAG(("esp.err_tcp_acceptmbox_post_fail: %"U32_F"\n\t", (u32_t)esp->err_tcp_acceptmbox_post_fail));
LWIP_PLATFORM_DIAG(("esp.acceptmbox_post_fail: %"U32_F"\n\t", (u32_t)esp->acceptmbox_post_fail));
LWIP_PLATFORM_DIAG(("esp.free_mbox_post_fail: %"U32_F"\n\t", (u32_t)esp->free_mbox_post_fail));
LWIP_PLATFORM_DIAG(("esp.tcpip_inpkt_post_fail: %"U32_F"\n\t", (u32_t)esp->tcpip_inpkt_post_fail));
LWIP_PLATFORM_DIAG(("esp.tcpip_cb_post_fail: %"U32_F"\n\t", (u32_t)esp->tcpip_cb_post_fail));
LWIP_PLATFORM_DIAG(("esp.wlanif_input_pbuf_fail: %"U32_F"\n\t", (u32_t)esp->wlanif_input_pbuf_fail));
LWIP_PLATFORM_DIAG(("esp.wlanif_outut_pbuf_fail: %"U32_F"\n\t", (u32_t)esp->wlanif_outut_pbuf_fail));
}
#endif
#endif /* LWIP_STATS */

View File

@ -1389,59 +1389,58 @@ tcp_kill_timewait(void)
}
#if ESP_LWIP
/**
* Kills the oldest connection that is in FIN_WAIT_2 state.
* Called from tcp_alloc() if no more connections are available.
*/
static void tcp_kill_finwait2(void)
{
struct tcp_pcb *pcb, *inactive;
u32_t inactivity;
/* Go through the list of FIN_WAIT_2 pcbs and get the oldest pcb. */
inactivity = 0;
inactive = NULL;
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->state == FIN_WAIT_2) {
if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) {
inactivity = tcp_ticks - pcb->tmr;
inactive = pcb;
}
}
}
if (inactive != NULL) {
tcp_pcb_remove(&tcp_active_pcbs, inactive);
memp_free(MEMP_TCP_PCB, inactive);
}
}
typedef struct {
u8_t time_wait;
u8_t closing;
u8_t fin_wait2;
u8_t last_ack;
u8_t fin_wait1;
u8_t listen;
u8_t bound;
u8_t total;
}tcp_pcb_num_t;
/**
* Kills the oldest connection that is in LAST_ACK state.
* Called from tcp_alloc() if no more connections are available.
*/
static void tcp_kill_lastack(void)
void tcp_pcb_num_cal(tcp_pcb_num_t *tcp_pcb_num)
{
struct tcp_pcb *pcb, *inactive;
u32_t inactivity;
/* Go through the list of LAST_ACK pcbs and get the oldest pcb. */
inactivity = 0;
inactive = NULL;
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->state == LAST_ACK) {
if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) {
inactivity = tcp_ticks - pcb->tmr;
inactive = pcb;
}
}
}
if (inactive != NULL) {
tcp_pcb_remove(&tcp_active_pcbs, inactive);
memp_free(MEMP_TCP_PCB, inactive);
}
struct tcp_pcb_listen *listen;
struct tcp_pcb *pcb;
if (!tcp_pcb_num){
return;
}
memset(tcp_pcb_num, 0, sizeof(*tcp_pcb_num));
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
tcp_pcb_num->total ++;
tcp_pcb_num->time_wait ++;
}
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next){
tcp_pcb_num->total ++;
if (pcb->state == FIN_WAIT_2){
tcp_pcb_num->fin_wait2 ++;
} else if (pcb->state == LAST_ACK) {
tcp_pcb_num->last_ack ++;
} else if (pcb->state == CLOSING) {
tcp_pcb_num->closing ++;
} else if (pcb->state == FIN_WAIT_1){
tcp_pcb_num->fin_wait1 ++;
}
}
for (listen = tcp_listen_pcbs.listen_pcbs; listen != NULL; listen = listen->next){
tcp_pcb_num->total ++;
tcp_pcb_num->listen ++;
}
for (pcb = tcp_bound_pcbs; pcb != NULL; pcb = pcb->next){
tcp_pcb_num->total ++;
tcp_pcb_num->bound ++;
}
}
#endif
/**
* Allocate a new tcp_pcb structure.
*
@ -1455,34 +1454,34 @@ tcp_alloc(u8_t prio)
u32_t iss;
#if ESP_LWIP
/*Kills the oldest connection that is in TIME_WAIT state.*/
u8_t time_wait_num = 0;
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
time_wait_num ++;
tcp_pcb_num_t tcp_pcb_num;
tcp_pcb_num_cal(&tcp_pcb_num);
if (tcp_pcb_num.total >= MEMP_NUM_TCP_PCB){
if (tcp_pcb_num.time_wait > 0){
tcp_kill_timewait();
} else if (tcp_pcb_num.last_ack > 0){
tcp_kill_state(LAST_ACK);
} else if (tcp_pcb_num.closing > 0){
tcp_kill_state(CLOSING);
} else if (tcp_pcb_num.fin_wait2 > 0){
tcp_kill_state(FIN_WAIT_2);
} else if (tcp_pcb_num.fin_wait1 > 0){
tcp_kill_state(FIN_WAIT_1);
} else {
tcp_kill_prio(prio);
}
}
if (time_wait_num >= MEMP_NUM_TCP_PCB)
tcp_kill_timewait();
/*Kills the oldest connection that is in FIN_WAIT_2 state.*/
time_wait_num = 0;
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next){
if (pcb->state == FIN_WAIT_2)
time_wait_num ++;
tcp_pcb_num_cal(&tcp_pcb_num);
if (tcp_pcb_num.total >= MEMP_NUM_TCP_PCB){
LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: no available tcp pcb %d %d %d %d %d %d %d %d\n",
tcp_pcb_num.total, tcp_pcb_num.time_wait, tcp_pcb_num.last_ack, tcp_pcb_num.closing,
tcp_pcb_num.fin_wait2, tcp_pcb_num.fin_wait1, tcp_pcb_num.listen, tcp_pcb_num.bound));
return NULL;
}
if (time_wait_num >= MEMP_NUM_TCP_PCB)
tcp_kill_finwait2();
/*Kills the oldest connection that is in LAST_ACK state.*/
time_wait_num = 0;
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next){
if (pcb->state == LAST_ACK)
time_wait_num ++;
}
if (time_wait_num >= MEMP_NUM_TCP_PCB)
tcp_kill_lastack();
#endif
pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);

View File

@ -176,7 +176,8 @@ tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno,
struct tcp_seg *seg;
u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags);
if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) {
seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG);
if (seg == NULL) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no memory.\n"));
pbuf_free(p);
return NULL;

View File

@ -20,5 +20,6 @@ void dbg_lwip_tcp_pcb_show(void);
void dbg_lwip_udp_pcb_show(void);
void dbg_lwip_tcp_rxtx_show(void);
void dbg_lwip_udp_rxtx_show(void);
void dbg_lwip_mem_cnt_show(void);
#endif

View File

@ -71,8 +71,25 @@ extern const struct memp_desc* const memp_pools[MEMP_MAX];
#include "lwip/mem.h"
#define memp_init()
#if ESP_CNT_DEBUG
static inline void* memp_malloc(int type)
{
ESP_CNT_MEM_MALLOC_INC(type);
return mem_malloc(memp_pools[type]->size);
}
static inline void memp_free(int type, void *mem)
{
ESP_CNT_MEM_FREE_INC(type);
mem_free(mem);
}
//#define memp_malloc(type) mem_malloc(memp_pools[type]->size); ESP_CNT_MEM_MALLOC_INC(type)
//#define memp_free(type, mem) mem_free(mem); ESP_CNT_MEM_FREE_INC(type)
#else
#define memp_malloc(type) mem_malloc(memp_pools[type]->size)
#define memp_free(type, mem) mem_free(mem)
#endif
#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \
const struct memp_desc memp_ ## name = { \

View File

@ -140,6 +140,16 @@ struct memp_desc {
#endif /* MEMP_MEM_MALLOC */
};
#if (ESP_CNT_DEBUG == 1)
extern uint32_t g_lwip_mem_cnt[MEMP_MAX][2];
#define ESP_CNT_MEM_MALLOC_INC(type) g_lwip_mem_cnt[type][0]++
#define ESP_CNT_MEM_FREE_INC(type) g_lwip_mem_cnt[type][1]++
#else
#define ESP_CNT_MEM_MALLOC_INC(type)
#define ESP_CNT_MEM_FREE_INC(type)
#endif
#ifdef LWIP_DEBUG
#define DECLARE_LWIP_MEMPOOL_DESC(desc) (desc),
#else

View File

@ -213,6 +213,23 @@ struct stats_mib2_netif_ctrs {
u32_t ifouterrors;
};
struct stats_esp {
/* mbox post fail stats */
u32_t rx_rawmbox_post_fail;
u32_t rx_udpmbox_post_fail;
u32_t rx_tcpmbox_post_fail;
u32_t err_tcp_rxmbox_post_fail;
u32_t err_tcp_acceptmbox_post_fail;
u32_t acceptmbox_post_fail;
u32_t free_mbox_post_fail;
u32_t tcpip_inpkt_post_fail;
u32_t tcpip_cb_post_fail;
/* memory malloc/free/failed stats */
u32_t wlanif_input_pbuf_fail;
u32_t wlanif_outut_pbuf_fail;
};
struct stats_ {
#if LINK_STATS
struct stats_proto link;
@ -265,6 +282,9 @@ struct stats_ {
#if MIB2_STATS
struct stats_mib2 mib2;
#endif
#if ESP_STATS
struct stats_esp esp;
#endif
};
extern struct stats_ lwip_stats;
@ -438,6 +458,14 @@ void stats_init(void);
#define MIB2_STATS_INC(x)
#endif
#if ESP_STATS
#define ESP_STATS_INC(x) STATS_INC(x)
#define ESP_STATS_DISPLAY() stats_display_esp(&lwip_stats.esp);
#else
#define ESP_STATS_INC(x)
#define ESP_STATS_DISPLAY()
#endif
/* Display of statistics */
#if LWIP_STATS_DISPLAY
void stats_display(void);
@ -446,6 +474,7 @@ void stats_display_igmp(struct stats_igmp *igmp, const char *name);
void stats_display_mem(struct stats_mem *mem, const char *name);
void stats_display_memp(struct stats_mem *mem, int index);
void stats_display_sys(struct stats_sys *sys);
void stats_display_esp(struct stats_esp *esp);
#else /* LWIP_STATS_DISPLAY */
#define stats_display()
#define stats_display_proto(proto, name)
@ -453,6 +482,7 @@ void stats_display_sys(struct stats_sys *sys);
#define stats_display_mem(mem, name)
#define stats_display_memp(mem, index)
#define stats_display_sys(sys)
#define stats_display_esp(esp)
#endif /* LWIP_STATS_DISPLAY */
#ifdef __cplusplus

View File

@ -379,22 +379,21 @@
* The queue size value itself is platform-dependent, but is passed to
* sys_mbox_new() when tcpip_init is called.
*/
#define TCPIP_MBOX_SIZE 16
#define TCPIP_MBOX_SIZE 32
/**
* DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a
* NETCONN_UDP. The queue size value itself is platform-dependent, but is passed
* to sys_mbox_new() when the recvmbox is created.
*/
#define DEFAULT_UDP_RECVMBOX_SIZE 16
#define DEFAULT_UDP_RECVMBOX_SIZE 6
/**
* DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a
* NETCONN_TCP. The queue size value itself is platform-dependent, but is passed
* to sys_mbox_new() when the recvmbox is created.
*/
#define DEFAULT_TCP_RECVMBOX_SIZE 16
//#define DEFAULT_TCP_RECVMBOX_SIZE 6
#define DEFAULT_TCP_RECVMBOX_SIZE 6
/**
* DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections.
@ -556,6 +555,7 @@
*/
#define TCPIP_DEBUG LWIP_DBG_OFF
/* Enable all Espressif-only options */
#define ESP_LWIP 1
@ -571,6 +571,8 @@
#define ESP_IP4_ATON 1
#define ESP_LIGHT_SLEEP 1
#define ESP_L2_TO_L3_COPY CONFIG_L2_TO_L3_COPY
#define ESP_CNT_DEBUG 0
#define ESP_DUAL_CORE 0
#define TCP_WND_DEFAULT (4*TCP_MSS)
#define TCP_SND_BUF_DEFAULT (2*TCP_MSS)

View File

@ -37,6 +37,7 @@
#include "lwip/sys.h"
#include "lwip/mem.h"
#include "arch/sys_arch.h"
#include "lwip/stats.h"
/* This is the number of threads that can be started with sys_thread_new() */
#define SYS_THREAD_MAX 4
@ -370,6 +371,7 @@ sys_mbox_free(sys_mbox_t *mbox)
if (post_null){
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free: post null to mbox\n"));
if (sys_mbox_trypost( mbox, NULL) != ERR_OK){
ESP_STATS_INC(esp.free_mbox_post_fail);
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free: post null mbox fail\n"));
} else {
post_null = false;

View File

@ -161,12 +161,9 @@ wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb)
goto _exit;
#if (ESP_L2_TO_L3_COPY == 1)
//p = pbuf_alloc(PBUF_IP, len, PBUF_POOL);
p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
if (p == NULL) {
#if ESP_PERF
g_rx_alloc_pbuf_fail_cnt++;
#endif
ESP_STATS_INC(esp.wlanif_input_pbuf_fail);
esp_wifi_internal_free_rx_buffer(eb);
return;
}
@ -175,9 +172,7 @@ wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb)
#else
p = pbuf_alloc(PBUF_RAW, len, PBUF_REF);
if (p == NULL){
#if ESP_PERF
g_rx_alloc_pbuf_fail_cnt++;
#endif
ESP_STATS_INC(esp.wlanif_input_pbuf_fail);
return;
}
p->payload = buffer;
@ -241,7 +236,7 @@ wlanif_init(struct netif *netif)
* The last argument should be replaced with your link speed, in units
* of bits per second.
*/
NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100);
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;

View File

@ -69,4 +69,16 @@ config MBEDTLS_MPI_INTERRUPT_NUM
CPU interrupt number for MPI interrupt to connect to. Must be otherwise unused.
Eventually this assignment will be handled automatically at runtime.
config MBEDTLS_HARDWARE_SHA
bool "Enable hardware SHA acceleration"
default y
help
Enable hardware accelerated SHA1, SHA256, SHA384 & SHA512 in mbedTLS.
Due to a hardware limitation, hardware acceleration is only
guaranteed if SHA digests are calculated one at a time. If more
than one SHA digest is calculated at the same time, only will
be calculated fully in hardware and the rest will be calculated
(at least partially calculated) in software.
endmenu

View File

@ -5,4 +5,3 @@
COMPONENT_ADD_INCLUDEDIRS := port/include include
COMPONENT_SRCDIRS := library port

View File

@ -34,6 +34,8 @@
#include "esp_intr.h"
#include "esp_attr.h"
#include "soc/dport_reg.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
@ -72,7 +74,16 @@ void esp_mpi_acquire_hardware( void )
{
/* newlib locks lazy initialize on ESP-IDF */
_lock_acquire(&mpi_lock);
ets_bigint_enable();
REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA);
/* also clear reset on digital signature, otherwise RSA is held in reset */
REG_CLR_BIT(DPORT_PERI_RST_EN_REG,
DPORT_PERI_EN_RSA
| DPORT_PERI_EN_DIGITAL_SIGNATURE);
REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
while(REG_READ(RSA_CLEAN_REG) != 1);
#ifdef CONFIG_MBEDTLS_MPI_USE_INTERRUPT
rsa_isr_initialise();
#endif
@ -80,7 +91,12 @@ void esp_mpi_acquire_hardware( void )
void esp_mpi_release_hardware( void )
{
ets_bigint_disable();
REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
/* don't reset digital signature unit, as this resets AES also */
REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_RSA);
REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA);
_lock_release(&mpi_lock);
}

View File

@ -0,0 +1,395 @@
/*
* SHA-1 implementation with hardware ESP32 support added.
* Uses mbedTLS software implementation for failover when concurrent
* SHA operations are in use.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE LTD
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*
*/
/*
* The SHA-1 standard was published by NIST in 1993.
*
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA1_C) && defined(MBEDTLS_SHA1_ALT)
#include "mbedtls/sha1.h"
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#include "hwcrypto/sha.h"
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
}
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
void mbedtls_sha1_init( mbedtls_sha1_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_sha1_context ) );
}
void mbedtls_sha1_free( mbedtls_sha1_context *ctx )
{
if( ctx == NULL )
return;
if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) {
esp_sha_unlock_engine(SHA1);
}
mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) );
}
void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
const mbedtls_sha1_context *src )
{
*dst = *src;
if (src->mode == ESP_MBEDTLS_SHA1_HARDWARE) {
/* Copy hardware digest state out to cloned state,
which will be a software digest.
*/
esp_sha_read_digest_state(SHA1, dst->state);
dst->mode = ESP_MBEDTLS_SHA1_SOFTWARE;
}
}
/*
* SHA-1 context setup
*/
void mbedtls_sha1_starts( mbedtls_sha1_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) {
esp_sha_unlock_engine(SHA1);
}
ctx->mode = ESP_MBEDTLS_SHA1_UNUSED;
}
static void mbedtls_sha1_software_process( mbedtls_sha1_context *ctx, const unsigned char data[64] );
void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] )
{
bool first_block = false;
if (ctx->mode == ESP_MBEDTLS_SHA1_UNUSED) {
/* try to use hardware for this digest */
if (esp_sha_try_lock_engine(SHA1)) {
ctx->mode = ESP_MBEDTLS_SHA1_HARDWARE;
first_block = true;
} else {
ctx->mode = ESP_MBEDTLS_SHA1_SOFTWARE;
}
}
if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) {
esp_sha_block(SHA1, data, first_block);
} else {
mbedtls_sha1_software_process(ctx, data);
}
}
static void mbedtls_sha1_software_process( mbedtls_sha1_context *ctx, const unsigned char data[64] )
{
uint32_t temp, W[16], A, B, C, D, E;
GET_UINT32_BE( W[ 0], data, 0 );
GET_UINT32_BE( W[ 1], data, 4 );
GET_UINT32_BE( W[ 2], data, 8 );
GET_UINT32_BE( W[ 3], data, 12 );
GET_UINT32_BE( W[ 4], data, 16 );
GET_UINT32_BE( W[ 5], data, 20 );
GET_UINT32_BE( W[ 6], data, 24 );
GET_UINT32_BE( W[ 7], data, 28 );
GET_UINT32_BE( W[ 8], data, 32 );
GET_UINT32_BE( W[ 9], data, 36 );
GET_UINT32_BE( W[10], data, 40 );
GET_UINT32_BE( W[11], data, 44 );
GET_UINT32_BE( W[12], data, 48 );
GET_UINT32_BE( W[13], data, 52 );
GET_UINT32_BE( W[14], data, 56 );
GET_UINT32_BE( W[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define R(t) \
( \
temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \
W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \
( W[t & 0x0F] = S(temp,1) ) \
)
#define P(a,b,c,d,e,x) \
{ \
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define K 0x5A827999
P( A, B, C, D, E, W[0] );
P( E, A, B, C, D, W[1] );
P( D, E, A, B, C, W[2] );
P( C, D, E, A, B, W[3] );
P( B, C, D, E, A, W[4] );
P( A, B, C, D, E, W[5] );
P( E, A, B, C, D, W[6] );
P( D, E, A, B, C, W[7] );
P( C, D, E, A, B, W[8] );
P( B, C, D, E, A, W[9] );
P( A, B, C, D, E, W[10] );
P( E, A, B, C, D, W[11] );
P( D, E, A, B, C, W[12] );
P( C, D, E, A, B, W[13] );
P( B, C, D, E, A, W[14] );
P( A, B, C, D, E, W[15] );
P( E, A, B, C, D, R(16) );
P( D, E, A, B, C, R(17) );
P( C, D, E, A, B, R(18) );
P( B, C, D, E, A, R(19) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0x6ED9EBA1
P( A, B, C, D, E, R(20) );
P( E, A, B, C, D, R(21) );
P( D, E, A, B, C, R(22) );
P( C, D, E, A, B, R(23) );
P( B, C, D, E, A, R(24) );
P( A, B, C, D, E, R(25) );
P( E, A, B, C, D, R(26) );
P( D, E, A, B, C, R(27) );
P( C, D, E, A, B, R(28) );
P( B, C, D, E, A, R(29) );
P( A, B, C, D, E, R(30) );
P( E, A, B, C, D, R(31) );
P( D, E, A, B, C, R(32) );
P( C, D, E, A, B, R(33) );
P( B, C, D, E, A, R(34) );
P( A, B, C, D, E, R(35) );
P( E, A, B, C, D, R(36) );
P( D, E, A, B, C, R(37) );
P( C, D, E, A, B, R(38) );
P( B, C, D, E, A, R(39) );
#undef K
#undef F
#define F(x,y,z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC
P( A, B, C, D, E, R(40) );
P( E, A, B, C, D, R(41) );
P( D, E, A, B, C, R(42) );
P( C, D, E, A, B, R(43) );
P( B, C, D, E, A, R(44) );
P( A, B, C, D, E, R(45) );
P( E, A, B, C, D, R(46) );
P( D, E, A, B, C, R(47) );
P( C, D, E, A, B, R(48) );
P( B, C, D, E, A, R(49) );
P( A, B, C, D, E, R(50) );
P( E, A, B, C, D, R(51) );
P( D, E, A, B, C, R(52) );
P( C, D, E, A, B, R(53) );
P( B, C, D, E, A, R(54) );
P( A, B, C, D, E, R(55) );
P( E, A, B, C, D, R(56) );
P( D, E, A, B, C, R(57) );
P( C, D, E, A, B, R(58) );
P( B, C, D, E, A, R(59) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0xCA62C1D6
P( A, B, C, D, E, R(60) );
P( E, A, B, C, D, R(61) );
P( D, E, A, B, C, R(62) );
P( C, D, E, A, B, R(63) );
P( B, C, D, E, A, R(64) );
P( A, B, C, D, E, R(65) );
P( E, A, B, C, D, R(66) );
P( D, E, A, B, C, R(67) );
P( C, D, E, A, B, R(68) );
P( B, C, D, E, A, R(69) );
P( A, B, C, D, E, R(70) );
P( E, A, B, C, D, R(71) );
P( D, E, A, B, C, R(72) );
P( C, D, E, A, B, R(73) );
P( B, C, D, E, A, R(74) );
P( A, B, C, D, E, R(75) );
P( E, A, B, C, D, R(76) );
P( D, E, A, B, C, R(77) );
P( C, D, E, A, B, R(78) );
P( B, C, D, E, A, R(79) );
#undef K
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
/*
* SHA-1 process buffer
*/
void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen )
{
size_t fill;
uint32_t left;
if( ilen == 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (uint32_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left), input, fill );
mbedtls_sha1_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
mbedtls_sha1_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
static const unsigned char sha1_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-1 final digest
*/
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] )
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
mbedtls_sha1_update( ctx, sha1_padding, padn );
mbedtls_sha1_update( ctx, msglen, 8 );
/* if state is in hardware, read it out */
if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) {
esp_sha_read_digest_state(SHA1, ctx->state);
esp_sha_unlock_engine(SHA1);
ctx->mode = ESP_MBEDTLS_SHA1_SOFTWARE;
}
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );
PUT_UINT32_BE( ctx->state[3], output, 12 );
PUT_UINT32_BE( ctx->state[4], output, 16 );
}
#endif /* MBEDTLS_SHA1_C && MBEDTLS_SHA1_ALT */

View File

@ -0,0 +1,367 @@
/*
* SHA-256 implementation with hardware ESP32 support added.
* Uses mbedTLS software implementation for failover when concurrent
* SHA operations are in use.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE LTD
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*
*/
/*
* The SHA-256 Secure Hash Standard was published by NIST in 2002.
*
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA256_C) && defined(MBEDTLS_SHA256_ALT)
#include "mbedtls/sha256.h"
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#include "hwcrypto/sha.h"
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
do { \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
} while( 0 )
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
do { \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
} while( 0 )
#endif
void mbedtls_sha256_init( mbedtls_sha256_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_sha256_context ) );
}
void mbedtls_sha256_free( mbedtls_sha256_context *ctx )
{
if( ctx == NULL )
return;
if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) {
esp_sha_unlock_engine(SHA2_256);
}
mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) );
}
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src )
{
*dst = *src;
if (src->mode == ESP_MBEDTLS_SHA256_HARDWARE) {
/* Copy hardware digest state out to cloned state,
which will become a software digest.
*/
esp_sha_read_digest_state(SHA2_256, dst->state);
dst->mode = ESP_MBEDTLS_SHA256_SOFTWARE;
}
}
/*
* SHA-256 context setup
*/
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
if( is224 == 0 )
{
/* SHA-256 */
ctx->state[0] = 0x6A09E667;
ctx->state[1] = 0xBB67AE85;
ctx->state[2] = 0x3C6EF372;
ctx->state[3] = 0xA54FF53A;
ctx->state[4] = 0x510E527F;
ctx->state[5] = 0x9B05688C;
ctx->state[6] = 0x1F83D9AB;
ctx->state[7] = 0x5BE0CD19;
}
else
{
/* SHA-224 */
ctx->state[0] = 0xC1059ED8;
ctx->state[1] = 0x367CD507;
ctx->state[2] = 0x3070DD17;
ctx->state[3] = 0xF70E5939;
ctx->state[4] = 0xFFC00B31;
ctx->state[5] = 0x68581511;
ctx->state[6] = 0x64F98FA7;
ctx->state[7] = 0xBEFA4FA4;
}
ctx->is224 = is224;
if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) {
esp_sha_unlock_engine(SHA2_256);
}
ctx->mode = ESP_MBEDTLS_SHA256_UNUSED;
}
#if !defined(MBEDTLS_SHA256_PROCESS_ALT)
static const uint32_t K[] =
{
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
};
#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define R(t) \
( \
W[t] = S1(W[t - 2]) + W[t - 7] + \
S0(W[t - 15]) + W[t - 16] \
)
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
static void mbedtls_sha256_software_process( mbedtls_sha256_context *ctx, const unsigned char data[64] );
void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] )
{
bool first_block = false;
if (ctx->mode == ESP_MBEDTLS_SHA256_UNUSED) {
/* try to use hardware for this digest */
if (!ctx->is224 && esp_sha_try_lock_engine(SHA2_256)) {
ctx->mode = ESP_MBEDTLS_SHA256_HARDWARE;
first_block = true;
} else {
ctx->mode = ESP_MBEDTLS_SHA256_SOFTWARE;
}
}
if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) {
esp_sha_block(SHA2_256, data, first_block);
} else {
mbedtls_sha256_software_process(ctx, data);
}
}
static void mbedtls_sha256_software_process( mbedtls_sha256_context *ctx, const unsigned char data[64] )
{
uint32_t temp1, temp2, W[64];
uint32_t A[8];
unsigned int i;
for( i = 0; i < 8; i++ )
A[i] = ctx->state[i];
#if defined(MBEDTLS_SHA256_SMALLER)
for( i = 0; i < 64; i++ )
{
if( i < 16 )
GET_UINT32_BE( W[i], data, 4 * i );
else
R( i );
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] );
temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3];
A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1;
}
#else /* MBEDTLS_SHA256_SMALLER */
for( i = 0; i < 16; i++ )
GET_UINT32_BE( W[i], data, 4 * i );
for( i = 0; i < 16; i += 8 )
{
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] );
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] );
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] );
P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] );
P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] );
P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] );
P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] );
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] );
}
for( i = 16; i < 64; i += 8 )
{
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] );
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] );
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] );
P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] );
P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] );
P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] );
P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] );
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] );
}
#endif /* MBEDTLS_SHA256_SMALLER */
for( i = 0; i < 8; i++ )
ctx->state[i] += A[i];
}
#endif /* !MBEDTLS_SHA256_PROCESS_ALT */
/*
* SHA-256 process buffer
*/
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
size_t ilen )
{
size_t fill;
uint32_t left;
if( ilen == 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (uint32_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left), input, fill );
mbedtls_sha256_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
mbedtls_sha256_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
static const unsigned char sha256_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-256 final digest
*/
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] )
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
mbedtls_sha256_update( ctx, sha256_padding, padn );
mbedtls_sha256_update( ctx, msglen, 8 );
/* if state is in hardware, read it out */
if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) {
esp_sha_read_digest_state(SHA2_256, ctx->state);
esp_sha_unlock_engine(SHA2_256);
ctx->mode = ESP_MBEDTLS_SHA256_SOFTWARE;
}
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );
PUT_UINT32_BE( ctx->state[3], output, 12 );
PUT_UINT32_BE( ctx->state[4], output, 16 );
PUT_UINT32_BE( ctx->state[5], output, 20 );
PUT_UINT32_BE( ctx->state[6], output, 24 );
if( ctx->is224 == 0 )
PUT_UINT32_BE( ctx->state[7], output, 28 );
}
#endif /* MBEDTLS_SHA256_C && MBEDTLS_SHA256_ALT */

View File

@ -0,0 +1,412 @@
/*
* SHA-512 implementation with hardware ESP32 support added.
* Uses mbedTLS software implementation for failover when concurrent
* SHA operations are in use.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE LTD
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*
*/
/*
* The SHA-512 Secure Hash Standard was published by NIST in 2002.
*
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_SHA512_ALT)
#include "mbedtls/sha512.h"
#if defined(_MSC_VER) || defined(__WATCOMC__)
#define UL64(x) x##ui64
#else
#define UL64(x) x##ULL
#endif
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#include "hwcrypto/sha.h"
inline static esp_sha_type sha_type(const mbedtls_sha512_context *ctx)
{
return ctx->is384 ? SHA2_384 : SHA2_512;
}
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}
/*
* 64-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT64_BE
#define GET_UINT64_BE(n,b,i) \
{ \
(n) = ( (uint64_t) (b)[(i) ] << 56 ) \
| ( (uint64_t) (b)[(i) + 1] << 48 ) \
| ( (uint64_t) (b)[(i) + 2] << 40 ) \
| ( (uint64_t) (b)[(i) + 3] << 32 ) \
| ( (uint64_t) (b)[(i) + 4] << 24 ) \
| ( (uint64_t) (b)[(i) + 5] << 16 ) \
| ( (uint64_t) (b)[(i) + 6] << 8 ) \
| ( (uint64_t) (b)[(i) + 7] ); \
}
#endif /* GET_UINT64_BE */
#ifndef PUT_UINT64_BE
#define PUT_UINT64_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
(b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 7] = (unsigned char) ( (n) ); \
}
#endif /* PUT_UINT64_BE */
void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_sha512_context ) );
}
void mbedtls_sha512_free( mbedtls_sha512_context *ctx )
{
if( ctx == NULL )
return;
if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
esp_sha_unlock_engine(sha_type(ctx));
}
mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) );
}
void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
const mbedtls_sha512_context *src )
{
*dst = *src;
if (src->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
/* Copy hardware digest state out to cloned state,
which will be a software digest.
Always read 512 bits of state, even for SHA-384
(SHA-384 state is identical to SHA-512, only
digest is truncated.)
*/
esp_sha_read_digest_state(SHA2_512, dst->state);
dst->mode = ESP_MBEDTLS_SHA512_SOFTWARE;
}
}
/*
* SHA-512 context setup
*/
void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
if( is384 == 0 )
{
/* SHA-512 */
ctx->state[0] = UL64(0x6A09E667F3BCC908);
ctx->state[1] = UL64(0xBB67AE8584CAA73B);
ctx->state[2] = UL64(0x3C6EF372FE94F82B);
ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
ctx->state[4] = UL64(0x510E527FADE682D1);
ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
ctx->state[7] = UL64(0x5BE0CD19137E2179);
}
else
{
/* SHA-384 */
ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
ctx->state[1] = UL64(0x629A292A367CD507);
ctx->state[2] = UL64(0x9159015A3070DD17);
ctx->state[3] = UL64(0x152FECD8F70E5939);
ctx->state[4] = UL64(0x67332667FFC00B31);
ctx->state[5] = UL64(0x8EB44A8768581511);
ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
}
ctx->is384 = is384;
if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
esp_sha_unlock_engine(sha_type(ctx));
}
ctx->mode = ESP_MBEDTLS_SHA512_UNUSED;
}
/*
* Round constants
*/
static const uint64_t K[80] =
{
UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
};
static void mbedtls_sha512_software_process( mbedtls_sha512_context *ctx, const unsigned char data[128] );
void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] )
{
bool first_block = false;
if (ctx->mode == ESP_MBEDTLS_SHA512_UNUSED) {
/* try to use hardware for this digest */
if (esp_sha_try_lock_engine(sha_type(ctx))) {
ctx->mode = ESP_MBEDTLS_SHA512_HARDWARE;
first_block = true;
} else {
ctx->mode = ESP_MBEDTLS_SHA512_SOFTWARE;
}
}
if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
esp_sha_block(sha_type(ctx), data, first_block);
} else {
mbedtls_sha512_software_process(ctx, data);
}
}
static void mbedtls_sha512_software_process( mbedtls_sha512_context *ctx, const unsigned char data[128] )
{
int i;
uint64_t temp1, temp2, W[80];
uint64_t A, B, C, D, E, F, G, H;
#define SHR(x,n) (x >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
for( i = 0; i < 16; i++ )
{
GET_UINT64_BE( W[i], data, i << 3 );
}
for( ; i < 80; i++ )
{
W[i] = S1(W[i - 2]) + W[i - 7] +
S0(W[i - 15]) + W[i - 16];
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
i = 0;
do
{
P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
}
while( i < 80 );
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[5] += F;
ctx->state[6] += G;
ctx->state[7] += H;
}
/*
* SHA-512 process buffer
*/
void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input,
size_t ilen )
{
size_t fill;
unsigned int left;
if( ilen == 0 )
return;
left = (unsigned int) (ctx->total[0] & 0x7F);
fill = 128 - left;
ctx->total[0] += (uint64_t) ilen;
if( ctx->total[0] < (uint64_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left), input, fill );
mbedtls_sha512_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 128 )
{
mbedtls_sha512_process( ctx, input );
input += 128;
ilen -= 128;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
static const unsigned char sha512_padding[128] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-512 final digest
*/
void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] )
{
size_t last, padn;
uint64_t high, low;
unsigned char msglen[16];
high = ( ctx->total[0] >> 61 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT64_BE( high, msglen, 0 );
PUT_UINT64_BE( low, msglen, 8 );
last = (size_t)( ctx->total[0] & 0x7F );
padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
mbedtls_sha512_update( ctx, sha512_padding, padn );
mbedtls_sha512_update( ctx, msglen, 16 );
/* if state is in hardware, read it out */
if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
esp_sha_read_digest_state(sha_type(ctx), ctx->state);
esp_sha_unlock_engine(sha_type(ctx));
ctx->mode = ESP_MBEDTLS_SHA512_SOFTWARE;
}
PUT_UINT64_BE( ctx->state[0], output, 0 );
PUT_UINT64_BE( ctx->state[1], output, 8 );
PUT_UINT64_BE( ctx->state[2], output, 16 );
PUT_UINT64_BE( ctx->state[3], output, 24 );
PUT_UINT64_BE( ctx->state[4], output, 32 );
PUT_UINT64_BE( ctx->state[5], output, 40 );
if( ctx->is384 == 0 )
{
PUT_UINT64_BE( ctx->state[6], output, 48 );
PUT_UINT64_BE( ctx->state[7], output, 56 );
}
}
#endif /* MBEDTLS_SHA512_C && MBEDTLS_SHA512_ALT */

View File

@ -243,11 +243,14 @@
#define MBEDTLS_AES_ALT
#endif
/* Currently hardware SHA does not work with TLS handshake,
due to concurrency issue. Internal TW#7111. */
//#define MBEDTLS_SHA1_ALT
//#define MBEDTLS_SHA256_ALT
//#define MBEDTLS_SHA512_ALT
/* MBEDTLS_SHAxx_ALT to enable hardware SHA support
with software fallback.
*/
#ifdef CONFIG_MBEDTLS_HARDWARE_SHA
#define MBEDTLS_SHA1_ALT
#define MBEDTLS_SHA256_ALT
#define MBEDTLS_SHA512_ALT
#endif
/* The following MPI (bignum) functions have ESP32 hardware support,
Uncommenting these macros will use the hardware-accelerated

View File

@ -1,16 +1,25 @@
// 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.
/*
* SHA-1 implementation with hardware ESP32 support added.
* Uses mbedTLS software implementation for failover when concurrent
* SHA operations are in use.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE LTD
* SPDX-License-Identifier: Apache-2.0
*
* 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 _SHA1_ALT_H_
#define _SHA1_ALT_H_
@ -20,17 +29,73 @@ extern "C" {
#if defined(MBEDTLS_SHA1_ALT)
#include "hwcrypto/sha.h"
typedef enum {
ESP_MBEDTLS_SHA1_UNUSED, /* first block hasn't been processed yet */
ESP_MBEDTLS_SHA1_HARDWARE, /* using hardware SHA engine */
ESP_MBEDTLS_SHA1_SOFTWARE, /* using software SHA */
} esp_mbedtls_sha1_mode;
typedef esp_sha_context mbedtls_sha1_context;
/**
* \brief SHA-1 context structure
*/
typedef struct
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[5]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
esp_mbedtls_sha1_mode mode;
}
mbedtls_sha1_context;
#define mbedtls_sha1_init esp_sha1_init
#define mbedtls_sha1_starts esp_sha1_start
#define mbedtls_sha1_clone esp_sha1_clone
#define mbedtls_sha1_update esp_sha1_update
#define mbedtls_sha1_finish esp_sha1_finish
#define mbedtls_sha1_free esp_sha1_free
#define mbedtls_sha1_process(...)
/**
* \brief Initialize SHA-1 context
*
* \param ctx SHA-1 context to be initialized
*/
void mbedtls_sha1_init( mbedtls_sha1_context *ctx );
/**
* \brief Clear SHA-1 context
*
* \param ctx SHA-1 context to be cleared
*/
void mbedtls_sha1_free( mbedtls_sha1_context *ctx );
/**
* \brief Clone (the state of) a SHA-1 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
const mbedtls_sha1_context *src );
/**
* \brief SHA-1 context setup
*
* \param ctx context to be initialized
*/
void mbedtls_sha1_starts( mbedtls_sha1_context *ctx );
/**
* \brief SHA-1 process buffer
*
* \param ctx SHA-1 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-1 final digest
*
* \param ctx SHA-1 context
* \param output SHA-1 checksum result
*/
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] );
/* Internal use */
void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] );
#endif

View File

@ -1,16 +1,25 @@
// 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.
/*
* SHA-256 implementation with hardware ESP32 support added.
* Uses mbedTLS software implementation for failover when concurrent
* SHA operations are in use.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE LTD
* SPDX-License-Identifier: Apache-2.0
*
* 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 _SHA256_ALT_H_
#define _SHA256_ALT_H_
@ -20,17 +29,76 @@ extern "C" {
#if defined(MBEDTLS_SHA256_ALT)
#include "hwcrypto/sha.h"
typedef enum {
ESP_MBEDTLS_SHA256_UNUSED, /* first block hasn't been processed yet */
ESP_MBEDTLS_SHA256_HARDWARE, /* using hardware SHA engine */
ESP_MBEDTLS_SHA256_SOFTWARE, /* using software SHA */
} esp_mbedtls_sha256_mode;
typedef esp_sha_context mbedtls_sha256_context;
/**
* \brief SHA-256 context structure
*/
typedef struct
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[8]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
int is224; /*!< 0 => SHA-256, else SHA-224 */
esp_mbedtls_sha256_mode mode;
}
mbedtls_sha256_context;
#define mbedtls_sha256_init esp_sha256_init
#define mbedtls_sha256_clone esp_sha256_clone
#define mbedtls_sha256_starts esp_sha256_start
#define mbedtls_sha256_update esp_sha256_update
#define mbedtls_sha256_finish esp_sha256_finish
#define mbedtls_sha256_free esp_sha256_free
#define mbedtls_sha256_process(...)
/**
* \brief Initialize SHA-256 context
*
* \param ctx SHA-256 context to be initialized
*/
void mbedtls_sha256_init( mbedtls_sha256_context *ctx );
/**
* \brief Clear SHA-256 context
*
* \param ctx SHA-256 context to be cleared
*/
void mbedtls_sha256_free( mbedtls_sha256_context *ctx );
/**
* \brief Clone (the state of) a SHA-256 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src );
/**
* \brief SHA-256 context setup
*
* \param ctx context to be initialized
* \param is224 0 = use SHA256, 1 = use SHA224
*/
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 );
/**
* \brief SHA-256 process buffer
*
* \param ctx SHA-256 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
size_t ilen );
/**
* \brief SHA-256 final digest
*
* \param ctx SHA-256 context
* \param output SHA-224/256 checksum result
*/
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] );
/* Internal use */
void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] );
#endif

View File

@ -1,16 +1,25 @@
// 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.
/*
* SHA-512 implementation with hardware ESP32 support added.
* Uses mbedTLS software implementation for failover when concurrent
* SHA operations are in use.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE LTD
* SPDX-License-Identifier: Apache-2.0
*
* 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 _SHA512_ALT_H_
#define _SHA512_ALT_H_
@ -19,17 +28,77 @@ extern "C" {
#endif
#if defined(MBEDTLS_SHA512_ALT)
#include "hwcrypto/sha.h"
typedef esp_sha_context mbedtls_sha512_context;
typedef enum {
ESP_MBEDTLS_SHA512_UNUSED, /* first block hasn't been processed yet */
ESP_MBEDTLS_SHA512_HARDWARE, /* using hardware SHA engine */
ESP_MBEDTLS_SHA512_SOFTWARE, /* using software SHA */
} esp_mbedtls_sha512_mode;
#define mbedtls_sha512_init esp_sha512_init
#define mbedtls_sha512_clone esp_sha512_clone
#define mbedtls_sha512_starts esp_sha512_start
#define mbedtls_sha512_update esp_sha512_update
#define mbedtls_sha512_finish esp_sha512_finish
#define mbedtls_sha512_free esp_sha512_free
#define mbedtls_sha512_process(...)
/**
* \brief SHA-512 context structure
*/
typedef struct
{
uint64_t total[2]; /*!< number of bytes processed */
uint64_t state[8]; /*!< intermediate digest state */
unsigned char buffer[128]; /*!< data block being processed */
int is384; /*!< 0 => SHA-512, else SHA-384 */
esp_mbedtls_sha512_mode mode;
}
mbedtls_sha512_context;
/**
* \brief Initialize SHA-512 context
*
* \param ctx SHA-512 context to be initialized
*/
void mbedtls_sha512_init( mbedtls_sha512_context *ctx );
/**
* \brief Clear SHA-512 context
*
* \param ctx SHA-512 context to be cleared
*/
void mbedtls_sha512_free( mbedtls_sha512_context *ctx );
/**
* \brief Clone (the state of) a SHA-512 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
const mbedtls_sha512_context *src );
/**
* \brief SHA-512 context setup
*
* \param ctx context to be initialized
* \param is384 0 = use SHA512, 1 = use SHA384
*/
void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 );
/**
* \brief SHA-512 process buffer
*
* \param ctx SHA-512 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input,
size_t ilen );
/**
* \brief SHA-512 final digest
*
* \param ctx SHA-512 context
* \param output SHA-384/512 checksum result
*/
void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] );
/* Internal use */
void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] );
#endif

View File

@ -1,27 +1,25 @@
/* mbedTLS internal tests wrapped into Unity
/* mbedTLS self-tests as unit tests
Focus on testing functionality where we use ESP32 hardware
accelerated crypto features.
See also test_hwcrypto.c
See also test_hwcrypto.c in esp32 component, which tests hardware crypto without mbedTLS.
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/sha1.h"
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
#include "mbedtls/aes.h"
#include "mbedtls/bignum.h"
#include "mbedtls/rsa.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.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.");
}
#include "sdkconfig.h"
TEST_CASE("mbedtls AES self-tests", "[aes]")
{
@ -33,102 +31,8 @@ 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 )
TEST_CASE("mbedtls RSA self-tests", "[bignum]")
{
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 );
TEST_ASSERT_FALSE_MESSAGE(mbedtls_rsa_self_test(1), "RSA self-tests should pass.");
}

View File

@ -0,0 +1,168 @@
/* mbedTLS bignum (MPI) self-tests as unit tests
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/bignum.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "unity.h"
#include "sdkconfig.h"
/* Debugging function to print an MPI number to stdout. Happens to
print output that can be copy-pasted directly into a Python shell.
*/
void mbedtls_mpi_printf(const char *name, const mbedtls_mpi *X)
{
static char buf[1024];
size_t n;
memset(buf, 0, sizeof(buf));
mbedtls_mpi_write_string(X, 16, buf, sizeof(buf)-1, &n);
if(n) {
printf("%s = 0x%s\n", name, buf);
} else {
printf("%s = TOOLONG\n", name);
}
}
/* Assert E = A * B */
static void test_bignum_mult(const char *a_str, const char *b_str, const char *e_str, size_t mod_bits)
{
mbedtls_mpi A, B, X, E, M;
char x_buf[1024] = { 0 };
size_t x_buf_len = 0;
mbedtls_mpi_init(&A);
mbedtls_mpi_init(&B);
mbedtls_mpi_init(&X);
mbedtls_mpi_init(&E);
TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&A, 16, a_str));
TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&B, 16, b_str));
/* E = A * B */
TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&E, 16, e_str));
TEST_ASSERT_FALSE(mbedtls_mpi_mul_mpi(&X, &A, &B));
mbedtls_mpi_write_string(&X, 16, x_buf, sizeof(x_buf)-1, &x_buf_len);
TEST_ASSERT_EQUAL_STRING_MESSAGE(e_str, x_buf, "mbedtls_mpi_mul_mpi result wrong");
/* if mod_bits arg is set, also do a esp_mpi_mul_mod() call */
if (mod_bits > 0) {
mbedtls_mpi_init(&M);
for(int i = 0; i < mod_bits; i++) {
mbedtls_mpi_set_bit(&M, i, 1);
}
TEST_ASSERT_FALSE(esp_mpi_mul_mpi_mod(&X, &A, &B, &M));
mbedtls_mpi_write_string(&X, 16, x_buf, sizeof(x_buf)-1, &x_buf_len);
TEST_ASSERT_EQUAL_STRING_MESSAGE(e_str, x_buf, "esp_mpi_mul_mpi_mod result wrong");
mbedtls_mpi_free(&M);
}
mbedtls_mpi_free(&A);
mbedtls_mpi_free(&B);
mbedtls_mpi_free(&X);
mbedtls_mpi_free(&E);
}
TEST_CASE("test MPI multiplication", "[bignum]")
{
/* Run some trivial numbers tests w/ various high modulo bit counts,
should make no difference to the result
*/
for(int i = 512; i <= 4096; i+= 512) {
test_bignum_mult("10", "100", "1000",
i);
}
test_bignum_mult("60006FA8D3E3BD746BE39B860FFAADB4F108E15CF2ED8F685FB0E86CC4CB107A488720B41C3F1E18550F00619CD3CA8442296ECB54D2F52ECEE5346D310195700000000",
"BF474CA7",
"047BB102CAF58A48D3D97E4231BC0B753051D8232B9B939A2A4E310F88E65FEFD7762FC2DE0E2BAD6AA51A391DFFABD120653A312E4998F42E2C03AA404EE63B67275BC100000000",
1024);
test_bignum_mult("49493AC229831EC01EEB01EAF3BBEBC44768EADF9ABC30C87D1791F5E04245756ED4965361EC0599626884DF079B6B5738985CE76BD66FAA67E3AAAD60775D5C9D44C09FDF9E27C033696C007BE1C540D718CA148BA01FFA4A358541E9E9F02F72BE37AFAB037DAEA5E3669A770400D2F4A5DBBD83A83919D05E3DD64787BC80000000",
"B878CC29",
"34CF37013066D5BDA2C86CF1FE7BDA66604E0D55DAFF9864B6E727BFF5871012B0AB73D28D4E100BA1E4607AA2A247C912FDBC435C6BF7C5F8E00278AE1381B1E5F6E3D52D2CBE819F0D65CB37370666D156E7A7B1FD4698D8C9D3165FC8A83F9293C839521993619CCF8180E521300C4306206C9121D629754F1FCC7839BF6DFAF33080000000",
3072);
test_bignum_mult("24BF6185468786FDD303083D25E64EFC66CA472BC44D253102F8B4A9D3BFA75091386C0077937FE33FA3252D28855837AE1B484A8A9A45F7EE8C0C634F9E8CDDF79C5CE07EE72C7F123142198164234CABB724CF78B8173B9F880FC86322407AF1FEDFDDE2BEB674CA15F3E81A1521E071513A1E85B5DFA031F21ECAE9A34D",
"010001",
"24BF8644A80CCD855A00DB402E2374E2B5C6ADF60B78E97E2829B7A288697B103888FD38E393F776BF8664D04DB280BD0652F665D2E4D0923483FAEF5C01DC7C847A547CDBC7AB663EB0544AC37DA4B0CF03D0869D878FF3B6C3AF5072EAA39D3279D1DCC29C9933808ABDFE0DFD3BF59331AB6FBFD46556119250BD086E36A34D",
1536);
test_bignum_mult("-5D88B669C417EDD02213723546A906B7E9DA7683780E9B54856A2147467ADA316F8819D69486FC8056FE1E8EA7DEC5D5EF12340B95C4FC966F4B348D35893620",
"9AE7FBC99546432DF71896FC239EADAEF38D18D2B2F0E2DD275AA977E2BF4411F5A3B2A5D33605AEBBCCBA7FEB9F2D2FA74206CEC169D74BF5A8C50D6F48EA08",
"-38990016EB21810E3B5E6AEE339AEE72BB7CD629C4C9270A3D832701A2949BC82B2BE5A7F900C0C9937464699862821976095187D646884E8FBF01DE8C3442F3BC97B670AF573EFB74A9BBEBE4432EE74B0A83BBCDF59485D332B1FF49EB461A3A8B12C38FD72C7772D75EC6EBA5633199540C47678BD2F4ADEEA40830C2F100",
2048);
/* 1 << 2050 * 0X1234 */
test_bignum_mult("400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"1234",
"48D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
3072);
/* multiply a 1178 bit number by a 2050 bit number */
test_bignum_mult("AAAAAAAAAA75124938ABBECD0EEEEE333333333333333333333FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAAAAAAABBBBBBBBBBBBBBBBBBBB000000000000000000000000000000000004988A5293848932948872398400000000000FFFFFFFFFFF0000000000000EDFABC0204048975876873487387478327482374871327482347328742837483247283748234723874238",
"390587293875124938ABBECD0EEEEE3333333333333333333333333333333399999888000AAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBB00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000EDFABC0204048975876873487387478327482374871327482347328742837483247283748234723874238478327400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003012111111111111111100000000000000000000000111111111111111111111111",
"02603AF70D0421C1AD82CE623F28F70B128118D06D00C27D433EC25BA86E6105C3890A0B1973B8BE068CA68E159A21078785DDB37F94216FBF4AEC939958AF4B8CEA2A48895CECA87562FC846EAAE0C866AF9D41EEABFB1D579F5828E9666A15E2AF946F16A189B5C645872FDCA247D309AB0BCAFB0D112881186FCFFEDC87061B4AE4A375E9BBCF579A7BC87A8EAC8C6F66E107986FC603F920F5E1A0FD8C619D88D90066FFFC8F4DB77437EBD7E3BD7E398C4C01F93426E347E039DCA7B0A73C0C90A9C4271BB761ADFF88971D190CE5DA98EFC5D7390D33BC034908AF81D784A4D7F32D0902E0C5DABC706635D5A28FC0E3A364EDEB21E8E117041D0E4B51CA6F9684F434057E7FCF2AF6BD050334B1D11E043B0967154E57354B681161D3C618974D5A7E0385755B80B931AE9B59DD4402BAEC206F04B8440741B3C4CA6D9F7DAF0AE6B3BF1B24B76C2F12B9E9A7C50D32E2093608FC9A30CBD852329E64A9AE0BC3F513899EBFA28629C1DF38081FB8C6630408F70D7B9A37701ABA4176C8B7DCB8CC78BD7783B861A7FC50862E75191DB8",
4096);
}
static void test_bignum_modexp(const char *z_str, const char *x_str, const char *y_str, const char *m_str)
{
mbedtls_mpi Z, X, Y, M;
char z_buf[400] = { 0 };
size_t z_buf_len = 0;
mbedtls_mpi_init(&Z);
mbedtls_mpi_init(&X);
mbedtls_mpi_init(&Y);
mbedtls_mpi_init(&M);
TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&X, 16, x_str));
TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&Y, 16, y_str));
TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&M, 16, m_str));
//mbedtls_mpi_printf("X", &X);
//mbedtls_mpi_printf("X", &Y);
//mbedtls_mpi_printf("M", &M);
/* Z = (X ^ Y) mod M */
TEST_ASSERT_FALSE(mbedtls_mpi_exp_mod(&Z, &X, &Y, &M, NULL));
mbedtls_mpi_write_string(&Z, 16, z_buf, sizeof(z_buf)-1, &z_buf_len);
TEST_ASSERT_EQUAL_STRING_MESSAGE(z_str, z_buf, "mbedtls_mpi_exp_mod incorrect");
}
TEST_CASE("test MPI modexp", "[bignum]")
{
test_bignum_modexp("01000000", "1000", "2", "FFFFFFFF");
test_bignum_modexp("014B5A90", "1234", "2", "FFFFFFF");
test_bignum_modexp("01234321", "1111", "2", "FFFFFFFF");
test_bignum_modexp("02", "5", "1", "3");
test_bignum_modexp("22", "55", "1", "33");
test_bignum_modexp("0222", "555", "1", "333");
test_bignum_modexp("2222", "5555", "1", "3333");
test_bignum_modexp("11", "5555", "1", "33");
test_bignum_modexp("55", "1111", "1", "77");
test_bignum_modexp("88", "1111", "2", "BB");
test_bignum_modexp("01000000", "2", "128",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
/* failures below here... */
test_bignum_modexp("0ABCDEF12345", "ABCDEF12345", "1", "FFFFFFFFFFFF");
test_bignum_modexp("0ABCDE", "ABCDE", "1", "FFFFF");
test_bignum_modexp("04", "2", "2", "9");
}

View File

@ -0,0 +1,250 @@
/* mbedTLS SHA unit tests
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/sha1.h"
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "unity.h"
#include "sdkconfig.h"
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_sha256_self_test(1), "SHA256 self-tests should pass.");
TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha512_self_test(1), "SHA512 self-tests should pass.");
TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha512_self_test(1), "SHA512 self-tests should pass.");
}
static const unsigned char *one_hundred_as = (unsigned char *)
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
static const unsigned char *one_hundred_bs = (unsigned char *)
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
static const uint8_t sha256_thousand_as[32] = {
0x41, 0xed, 0xec, 0xe4, 0x2d, 0x63, 0xe8, 0xd9, 0xbf, 0x51, 0x5a, 0x9b, 0xa6, 0x93, 0x2e, 0x1c,
0x20, 0xcb, 0xc9, 0xf5, 0xa5, 0xd1, 0x34, 0x64, 0x5a, 0xdb, 0x5d, 0xb1, 0xb9, 0x73, 0x7e, 0xa3 };
static const uint8_t sha256_thousand_bs[32] = {
0xf6, 0xf1, 0x18, 0xe1, 0x20, 0xe5, 0x2b, 0xe0, 0xbd, 0x0c, 0xfd, 0xf2, 0x79, 0x4c, 0xd1, 0x2c, 0x07, 0x68, 0x6c, 0xc8, 0x71, 0x23, 0x5a, 0xc2, 0xf1, 0x14, 0x59, 0x37, 0x8e, 0x6d, 0x23, 0x5b
};
static const uint8_t sha512_thousand_bs[64] = {
0xa6, 0x68, 0x68, 0xa3, 0x73, 0x53, 0x2a, 0x5c, 0xc3, 0x3f, 0xbf, 0x43, 0x4e, 0xba, 0x10, 0x86, 0xb3, 0x87, 0x09, 0xe9, 0x14, 0x3f, 0xbf, 0x37, 0x67, 0x8d, 0x43, 0xd9, 0x9b, 0x95, 0x08, 0xd5, 0x80, 0x2d, 0xbe, 0x9d, 0xe9, 0x1a, 0x54, 0xab, 0x9e, 0xbc, 0x8a, 0x08, 0xa0, 0x1a, 0x89, 0xd8, 0x72, 0x68, 0xdf, 0x52, 0x69, 0x7f, 0x1c, 0x70, 0xda, 0xe8, 0x3f, 0xe5, 0xae, 0x5a, 0xfc, 0x9d
};
static const uint8_t sha384_thousand_bs[48] = {
0x6d, 0xe5, 0xf5, 0x88, 0x57, 0x60, 0x83, 0xff, 0x7c, 0x94, 0x61, 0x5f, 0x8d, 0x96, 0xf2, 0x76, 0xd5, 0x3f, 0x77, 0x0c, 0x8e, 0xc1, 0xbf, 0xb6, 0x04, 0x27, 0xa4, 0xba, 0xea, 0x6c, 0x68, 0x44, 0xbd, 0xb0, 0x9c, 0xef, 0x6a, 0x09, 0x28, 0xe8, 0x1f, 0xfc, 0x95, 0x03, 0x69, 0x99, 0xab, 0x1a
};
static const uint8_t sha1_thousand_as[20] = {
0x29, 0x1e, 0x9a, 0x6c, 0x66, 0x99, 0x49, 0x49, 0xb5, 0x7b, 0xa5,
0xe6, 0x50, 0x36, 0x1e, 0x98, 0xfc, 0x36, 0xb1, 0xba };
TEST_CASE("mbedtls SHA interleaving", "[mbedtls]")
{
mbedtls_sha1_context sha1_ctx;
mbedtls_sha256_context sha256_ctx;
mbedtls_sha512_context sha512_ctx;
unsigned char sha1[20], sha256[32], sha512[64];
mbedtls_sha1_init(&sha1_ctx);
mbedtls_sha256_init(&sha256_ctx);
mbedtls_sha512_init(&sha512_ctx);
mbedtls_sha1_starts(&sha1_ctx);
mbedtls_sha256_starts(&sha256_ctx, false);
mbedtls_sha512_starts(&sha512_ctx, false);
for (int i = 0; i < 10; i++) {
mbedtls_sha1_update(&sha1_ctx, one_hundred_as, 100);
mbedtls_sha256_update(&sha256_ctx, one_hundred_as, 100);
mbedtls_sha512_update(&sha512_ctx, one_hundred_bs, 100);
}
mbedtls_sha1_finish(&sha1_ctx, sha1);
mbedtls_sha256_finish(&sha256_ctx, sha256);
mbedtls_sha512_finish(&sha512_ctx, sha512);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 calculation");
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 calculation");
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha1_thousand_as, sha1, 20, "SHA1 calculation");
}
static xSemaphoreHandle done_sem;
static void tskRunSHA1Test(void *pvParameters)
{
mbedtls_sha1_context sha1_ctx;
unsigned char sha1[20];
for (int i = 0; i < 1000; i++) {
mbedtls_sha1_init(&sha1_ctx);
mbedtls_sha1_starts(&sha1_ctx);
for (int j = 0; j < 10; j++) {
mbedtls_sha1_update(&sha1_ctx, (unsigned char *)one_hundred_as, 100);
}
mbedtls_sha1_finish(&sha1_ctx, sha1);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha1_thousand_as, sha1, 20, "SHA1 calculation");
}
xSemaphoreGive(done_sem);
vTaskDelete(NULL);
}
static void tskRunSHA256Test(void *pvParameters)
{
mbedtls_sha256_context sha256_ctx;
unsigned char sha256[32];
for (int i = 0; i < 1000; i++) {
mbedtls_sha256_init(&sha256_ctx);
mbedtls_sha256_starts(&sha256_ctx, false);
for (int j = 0; j < 10; j++) {
mbedtls_sha256_update(&sha256_ctx, (unsigned char *)one_hundred_bs, 100);
}
mbedtls_sha256_finish(&sha256_ctx, sha256);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_bs, sha256, 32, "SHA256 calculation");
}
xSemaphoreGive(done_sem);
vTaskDelete(NULL);
}
TEST_CASE("mbedtls SHA multithreading", "[mbedtls]")
{
done_sem = xSemaphoreCreateCounting(4, 0);
xTaskCreate(tskRunSHA1Test, "SHA1Task1", 8192, NULL, 3, NULL);
xTaskCreate(tskRunSHA1Test, "SHA1Task2", 8192, NULL, 3, NULL);
xTaskCreate(tskRunSHA256Test, "SHA256Task1", 8192, NULL, 3, NULL);
xTaskCreate(tskRunSHA256Test, "SHA256Task2", 8192, NULL, 3, NULL);
for(int i = 0; i < 4; i++) {
if(!xSemaphoreTake(done_sem, 10000/portTICK_PERIOD_MS)) {
TEST_FAIL_MESSAGE("done_sem not released by test task");
}
}
vSemaphoreDelete(done_sem);
}
void tskRunSHASelftests(void *param)
{
for (int i = 0; i < 5; i++) {
if(mbedtls_sha1_self_test(1)) {
printf("SHA1 self-tests failed.\n");
while(1) {}
}
if(mbedtls_sha256_self_test(1)) {
printf("SHA256 self-tests failed.\n");
while(1) {}
}
if(mbedtls_sha512_self_test(1)) {
printf("SHA512 self-tests failed.\n");
while(1) {}
}
if(mbedtls_sha512_self_test(1)) {
printf("SHA512 self-tests failed.\n");
while(1) {}
}
}
xSemaphoreGive(done_sem);
vTaskDelete(NULL);
}
TEST_CASE("mbedtls SHA self-tests multithreaded", "[mbedtls]")
{
done_sem = xSemaphoreCreateCounting(2, 0);
xTaskCreate(tskRunSHASelftests, "SHASelftests1", 8192, NULL, 3, NULL);
xTaskCreate(tskRunSHASelftests, "SHASelftests2", 8192, NULL, 3, NULL);
for(int i = 0; i < 2; i++) {
if(!xSemaphoreTake(done_sem, 10000/portTICK_PERIOD_MS)) {
TEST_FAIL_MESSAGE("done_sem not released by test task");
}
}
vSemaphoreDelete(done_sem);
}
TEST_CASE("mbedtls SHA512 clone", "[mbedtls]")
{
mbedtls_sha512_context ctx;
mbedtls_sha512_context clone;
unsigned char sha512[64];
mbedtls_sha512_init(&ctx);
mbedtls_sha512_starts(&ctx, false);
for (int i = 0; i < 5; i++) {
mbedtls_sha512_update(&ctx, one_hundred_bs, 100);
}
mbedtls_sha512_clone(&clone, &ctx);
for (int i = 0; i < 5; i++) {
mbedtls_sha512_update(&ctx, one_hundred_bs, 100);
mbedtls_sha512_update(&clone, one_hundred_bs, 100);
}
mbedtls_sha512_finish(&ctx, sha512);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 original calculation");
mbedtls_sha512_finish(&clone, sha512);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 cloned calculation");
}
TEST_CASE("mbedtls SHA384 clone", "[mbedtls]")
{
mbedtls_sha512_context ctx;
mbedtls_sha512_context clone;
unsigned char sha384[48];
mbedtls_sha512_init(&ctx);
mbedtls_sha512_starts(&ctx, true);
for (int i = 0; i < 5; i++) {
mbedtls_sha512_update(&ctx, one_hundred_bs, 100);
}
mbedtls_sha512_clone(&clone, &ctx);
for (int i = 0; i < 5; i++) {
mbedtls_sha512_update(&ctx, one_hundred_bs, 100);
mbedtls_sha512_update(&clone, one_hundred_bs, 100);
}
mbedtls_sha512_finish(&ctx, sha384);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha384_thousand_bs, sha384, 48, "SHA512 original calculation");
mbedtls_sha512_finish(&clone, sha384);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha384_thousand_bs, sha384, 48, "SHA512 cloned calculation");
}
TEST_CASE("mbedtls SHA256 clone", "[mbedtls]")
{
mbedtls_sha256_context ctx;
mbedtls_sha256_context clone;
unsigned char sha256[64];
mbedtls_sha256_init(&ctx);
mbedtls_sha256_starts(&ctx, false);
for (int i = 0; i < 5; i++) {
mbedtls_sha256_update(&ctx, one_hundred_as, 100);
}
mbedtls_sha256_clone(&clone, &ctx);
for (int i = 0; i < 5; i++) {
mbedtls_sha256_update(&ctx, one_hundred_as, 100);
mbedtls_sha256_update(&clone, one_hundred_as, 100);
}
mbedtls_sha256_finish(&ctx, sha256);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 original calculation");
mbedtls_sha256_finish(&clone, sha256);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 cloned calculation");
}

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

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

@ -31,6 +31,9 @@
#include "esp_log.h"
#include "cache_utils.h"
/* bytes erased by SPIEraseBlock() ROM function */
#define BLOCK_ERASE_SIZE 32768
#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
static const char* TAG = "spi_flash";
static spi_flash_counters_t s_flash_stats;
@ -100,7 +103,7 @@ esp_err_t IRAM_ATTR spi_flash_erase_range(uint32_t start_addr, uint32_t size)
}
size_t start = start_addr / SPI_FLASH_SEC_SIZE;
size_t end = start + size / SPI_FLASH_SEC_SIZE;
const size_t sectors_per_block = 16;
const size_t sectors_per_block = BLOCK_ERASE_SIZE / SPI_FLASH_SEC_SIZE;
COUNTER_START();
spi_flash_disable_interrupts_caches_and_other_cpu();
SpiFlashOpResult rc;
@ -129,34 +132,90 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t dest_addr, const void *src, size_t si
// Destination alignment is also checked in ROM code, but we can give
// better error code here
// TODO: add handling of unaligned destinations
if (dest_addr % 4 != 0) {
return ESP_ERR_INVALID_ARG;
}
if (size % 4 != 0) {
return ESP_ERR_INVALID_SIZE;
}
if ((uint32_t) src < 0x3ff00000) {
// if source address is in DROM, we won't be able to read it
// from within SPIWrite
// TODO: consider buffering source data using heap and writing it anyway?
return ESP_ERR_INVALID_ARG;
}
uint8_t *temp_write_buf = NULL;
uint8_t pad_head = 0;
uint8_t pad_end = 0;
SpiFlashOpResult rc;
// Out of bound writes are checked in ROM code, but we can give better
// error code here
if (dest_addr + size > g_rom_flashchip.chip_size) {
return ESP_ERR_INVALID_SIZE;
}
COUNTER_START();
spi_flash_disable_interrupts_caches_and_other_cpu();
SpiFlashOpResult rc;
rc = spi_flash_unlock();
if (rc == SPI_FLASH_RESULT_OK) {
rc = SPIWrite((uint32_t) dest_addr, (const uint32_t*) src, (int32_t) size);
COUNTER_ADD_BYTES(write, size);
while(size >= 1024) {
// max need pad byte num for 1024 is 4
temp_write_buf = (uint8_t*)malloc(1024 + 4);
if(temp_write_buf == NULL) {
return ESP_ERR_NO_MEM;
}
if(dest_addr%4 != 0) {
pad_head = dest_addr%4;
pad_end = 4 - pad_head;
}
memset(temp_write_buf,0xFF,pad_head);
memcpy(temp_write_buf + pad_head ,src,1024);
memset(temp_write_buf + pad_head + 1024, 0xFF,pad_end);
COUNTER_START();
spi_flash_disable_interrupts_caches_and_other_cpu();
rc = spi_flash_unlock();
if (rc == SPI_FLASH_RESULT_OK) {
rc = SPIWrite((uint32_t) (dest_addr - pad_head), (const uint32_t*) temp_write_buf, (int32_t) (1024 + pad_head + pad_end));
COUNTER_ADD_BYTES(write, 1024 + pad_head + pad_end);
}
COUNTER_STOP(write);
spi_flash_enable_interrupts_caches_and_other_cpu();
if(rc != ESP_OK) {
free(temp_write_buf);
temp_write_buf = NULL;
return spi_flash_translate_rc(rc);
}
free(temp_write_buf);
temp_write_buf = NULL;
size -= 1024;
dest_addr += 1024;
src = (uint8_t*)src + 1024;
}
spi_flash_enable_interrupts_caches_and_other_cpu();
COUNTER_STOP(write);
return spi_flash_translate_rc(rc);
if(size > 0) {
// max need pad byte num for rand size is 6
temp_write_buf = (uint8_t*)malloc(size + 6);
if(temp_write_buf == NULL) {
return ESP_ERR_NO_MEM;
}
if(dest_addr%4 != 0) {
pad_head = dest_addr%4;
}
if ((pad_head + size)%4 != 0){
pad_end = 4 - (pad_head + size) % 4;
}
memset(temp_write_buf,0xFF,pad_head);
memcpy(temp_write_buf + pad_head, src, size);
memset(temp_write_buf + pad_head + size, 0xFF,pad_end);
COUNTER_START();
spi_flash_disable_interrupts_caches_and_other_cpu();
rc = spi_flash_unlock();
if (rc == SPI_FLASH_RESULT_OK) {
rc = SPIWrite((uint32_t) (dest_addr - pad_head), (const uint32_t*) temp_write_buf, (int32_t) (size + pad_head + pad_end));
COUNTER_ADD_BYTES(write, size + pad_head + pad_end);
}
COUNTER_STOP(write);
spi_flash_enable_interrupts_caches_and_other_cpu();
if(rc != ESP_OK) {
free(temp_write_buf);
temp_write_buf = NULL;
return spi_flash_translate_rc(rc);
}
free(temp_write_buf);
temp_write_buf = NULL;
size = 0;
dest_addr += size;
src = (uint8_t*)src + size;
return spi_flash_translate_rc(rc);
}
return spi_flash_translate_rc(SPI_FLASH_RESULT_OK);
}
esp_err_t IRAM_ATTR spi_flash_read(size_t src_addr, void *dest, size_t size)

View File

@ -208,6 +208,10 @@ esp_err_t esp_partition_write(const esp_partition_t* partition,
size_t dst_offset, const void* src, size_t size)
{
assert(partition != NULL);
//todo : need add ecrypt write support ,size must be 32-bytes align
if(partition->encrypted == true) {
return ESP_FAIL;
}
if (dst_offset > partition->size) {
return ESP_ERR_INVALID_ARG;
}

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

@ -0,0 +1,60 @@
/*
* WPA Supplicant / shared MSCHAPV2 helper functions
*
*
*/
#ifndef MS_FUNCS_H
#define MS_FUNCS_H
int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
const u8 *username, size_t username_len,
const u8 *password, size_t password_len,
u8 *response);
int generate_nt_response_pwhash(const u8 *auth_challenge,
const u8 *peer_challenge,
const u8 *username, size_t username_len,
const u8 *password_hash,
u8 *response);
int generate_authenticator_response(const u8 *password, size_t password_len,
const u8 *peer_challenge,
const u8 *auth_challenge,
const u8 *username, size_t username_len,
const u8 *nt_response, u8 *response);
int generate_authenticator_response_pwhash(
const u8 *password_hash,
const u8 *peer_challenge, const u8 *auth_challenge,
const u8 *username, size_t username_len,
const u8 *nt_response, u8 *response);
int nt_challenge_response(const u8 *challenge, const u8 *password,
size_t password_len, u8 *response);
void challenge_response(const u8 *challenge, const u8 *password_hash,
u8 *response);
int nt_password_hash(const u8 *password, size_t password_len,
u8 *password_hash);
int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash);
int get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
u8 *master_key);
int get_asymetric_start_key(const u8 *master_key, u8 *session_key,
size_t session_key_len, int is_send,
int is_server);
int encrypt_pw_block_with_password_hash(
const u8 *password, size_t password_len,
const u8 *password_hash, u8 *pw_block);
int __must_check encry_pw_block_with_password_hash(
const u8 *password, size_t password_len,
const u8 *password_hash, u8 *pw_block);
int __must_check new_password_encrypted_with_old_nt_password_hash(
const u8 *new_password, size_t new_password_len,
const u8 *old_password, size_t old_password_len,
u8 *encrypted_pw_block);
void nt_password_hash_encrypted_with_block(const u8 *password_hash,
const u8 *block, u8 *cypher);
int old_nt_password_hash_encrypted_with_new_nt_password_hash(
const u8 *new_password, size_t new_password_len,
const u8 *old_password, size_t old_password_len,
u8 *encrypted_password_hash);
#endif /* MS_FUNCS_H */

View File

@ -19,6 +19,19 @@
#endif /* ets */
#include "os.h"
/* Define platform specific variable type macros */
#if defined(ESP_PLATFORM)
#include <stdint.h>
typedef uint64_t u64;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
typedef int64_t s64;
typedef int32_t s32;
typedef int16_t s16;
typedef int8_t s8;
#endif /*ESP_PLATFORM*/
#if defined(__XTENSA__)
#include <machine/endian.h>
#define __BYTE_ORDER BYTE_ORDER

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

View File

@ -0,0 +1,494 @@
/*
* DES and 3DES-EDE ciphers
*
* Modifications to LibTomCrypt implementation:
* Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "wpa/includes.h"
#include "wpa/common.h"
#include "crypto/crypto.h"
//#include "des_i.h"
/*
* This implementation is based on a DES implementation included in
* LibTomCrypt. The version here is modified to fit in wpa_supplicant/hostapd
* coding style.
*/
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
*/
/**
DES code submitted by Dobes Vandermeer
*/
#define ROLc(x, y) \
((((unsigned long) (x) << (unsigned long) ((y) & 31)) | \
(((unsigned long) (x) & 0xFFFFFFFFUL) >> \
(unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
#define RORc(x, y) \
(((((unsigned long) (x) & 0xFFFFFFFFUL) >> \
(unsigned long) ((y) & 31)) | \
((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & \
0xFFFFFFFFUL)
static const u32 bytebit[8] =
{
0200, 0100, 040, 020, 010, 04, 02, 01
};
static const u32 bigbyte[24] =
{
0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL,
0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL,
0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL,
0x800UL, 0x400UL, 0x200UL, 0x100UL,
0x80UL, 0x40UL, 0x20UL, 0x10UL,
0x8UL, 0x4UL, 0x2UL, 0x1L
};
/* Use the key schedule specific in the standard (ANSI X3.92-1981) */
static const u8 pc1[56] = {
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
};
static const u8 totrot[16] = {
1, 2, 4, 6,
8, 10, 12, 14,
15, 17, 19, 21,
23, 25, 27, 28
};
static const u8 pc2[48] = {
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
};
static const u32 SP1[64] =
{
0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL,
0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL,
0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL,
0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL,
0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL,
0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL,
0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL,
0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL,
0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL,
0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL,
0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL,
0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL,
0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL,
0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL,
0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL,
0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL
};
static const u32 SP2[64] =
{
0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL,
0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL,
0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL,
0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL,
0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL,
0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL,
0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL,
0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL,
0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL,
0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL,
0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL,
0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL,
0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL,
0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL,
0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL,
0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL
};
static const u32 SP3[64] =
{
0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL,
0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL,
0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL,
0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL,
0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL,
0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL,
0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL,
0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL,
0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL,
0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL,
0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL,
0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL,
0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL,
0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL,
0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL,
0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL
};
static const u32 SP4[64] =
{
0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL,
0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL,
0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL,
0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL,
0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL,
0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL,
0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL,
0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL,
0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL,
0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL,
0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL,
0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL,
0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL,
0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL
};
static const u32 SP5[64] =
{
0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL,
0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL,
0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL,
0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL,
0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL,
0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL,
0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL,
0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL,
0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL,
0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL,
0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL,
0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL,
0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL,
0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL,
0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL,
0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL
};
static const u32 SP6[64] =
{
0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL,
0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL,
0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL,
0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL,
0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL,
0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL,
0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL,
0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL,
0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL,
0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL,
0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL,
0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL,
0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL,
0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL
};
static const u32 SP7[64] =
{
0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL,
0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL,
0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL,
0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL,
0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL,
0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL,
0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL,
0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL,
0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL,
0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL,
0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL,
0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL,
0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL,
0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL,
0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL,
0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL
};
static const u32 SP8[64] =
{
0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL,
0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL,
0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL,
0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL,
0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL,
0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL,
0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL,
0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL,
0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL,
0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL,
0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL,
0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL,
0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL,
0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL,
0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL,
0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL
};
static void cookey(const u32 *raw1, u32 *keyout)
{
u32 *cook;
const u32 *raw0;
u32 dough[32];
int i;
cook = dough;
for (i = 0; i < 16; i++, raw1++) {
raw0 = raw1++;
*cook = (*raw0 & 0x00fc0000L) << 6;
*cook |= (*raw0 & 0x00000fc0L) << 10;
*cook |= (*raw1 & 0x00fc0000L) >> 10;
*cook++ |= (*raw1 & 0x00000fc0L) >> 6;
*cook = (*raw0 & 0x0003f000L) << 12;
*cook |= (*raw0 & 0x0000003fL) << 16;
*cook |= (*raw1 & 0x0003f000L) >> 4;
*cook++ |= (*raw1 & 0x0000003fL);
}
os_memcpy(keyout, dough, sizeof(dough));
}
static void deskey(const u8 *key, int decrypt, u32 *keyout)
{
u32 i, j, l, m, n, kn[32];
u8 pc1m[56], pcr[56];
for (j = 0; j < 56; j++) {
l = (u32) pc1[j];
m = l & 7;
pc1m[j] = (u8)
((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0);
}
for (i = 0; i < 16; i++) {
if (decrypt)
m = (15 - i) << 1;
else
m = i << 1;
n = m + 1;
kn[m] = kn[n] = 0L;
for (j = 0; j < 28; j++) {
l = j + (u32) totrot[i];
if (l < 28)
pcr[j] = pc1m[l];
else
pcr[j] = pc1m[l - 28];
}
for (/* j = 28 */; j < 56; j++) {
l = j + (u32) totrot[i];
if (l < 56)
pcr[j] = pc1m[l];
else
pcr[j] = pc1m[l - 28];
}
for (j = 0; j < 24; j++) {
if ((int) pcr[(int) pc2[j]] != 0)
kn[m] |= bigbyte[j];
if ((int) pcr[(int) pc2[j + 24]] != 0)
kn[n] |= bigbyte[j];
}
}
cookey(kn, keyout);
}
static void desfunc(u32 *block, const u32 *keys)
{
u32 work, right, leftt;
int cur_round;
leftt = block[0];
right = block[1];
work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
right ^= work;
leftt ^= (work << 4);
work = ((leftt >> 16) ^ right) & 0x0000ffffL;
right ^= work;
leftt ^= (work << 16);
work = ((right >> 2) ^ leftt) & 0x33333333L;
leftt ^= work;
right ^= (work << 2);
work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
leftt ^= work;
right ^= (work << 8);
right = ROLc(right, 1);
work = (leftt ^ right) & 0xaaaaaaaaL;
leftt ^= work;
right ^= work;
leftt = ROLc(leftt, 1);
for (cur_round = 0; cur_round < 8; cur_round++) {
work = RORc(right, 4) ^ *keys++;
leftt ^= SP7[work & 0x3fL]
^ SP5[(work >> 8) & 0x3fL]
^ SP3[(work >> 16) & 0x3fL]
^ SP1[(work >> 24) & 0x3fL];
work = right ^ *keys++;
leftt ^= SP8[ work & 0x3fL]
^ SP6[(work >> 8) & 0x3fL]
^ SP4[(work >> 16) & 0x3fL]
^ SP2[(work >> 24) & 0x3fL];
work = RORc(leftt, 4) ^ *keys++;
right ^= SP7[ work & 0x3fL]
^ SP5[(work >> 8) & 0x3fL]
^ SP3[(work >> 16) & 0x3fL]
^ SP1[(work >> 24) & 0x3fL];
work = leftt ^ *keys++;
right ^= SP8[ work & 0x3fL]
^ SP6[(work >> 8) & 0x3fL]
^ SP4[(work >> 16) & 0x3fL]
^ SP2[(work >> 24) & 0x3fL];
}
right = RORc(right, 1);
work = (leftt ^ right) & 0xaaaaaaaaL;
leftt ^= work;
right ^= work;
leftt = RORc(leftt, 1);
work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
right ^= work;
leftt ^= (work << 8);
/* -- */
work = ((leftt >> 2) ^ right) & 0x33333333L;
right ^= work;
leftt ^= (work << 2);
work = ((right >> 16) ^ leftt) & 0x0000ffffL;
leftt ^= work;
right ^= (work << 16);
work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
leftt ^= work;
right ^= (work << 4);
block[0] = right;
block[1] = leftt;
}
/* wpa_supplicant/hostapd specific wrapper */
void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
{
u8 pkey[8], next, tmp;
int i;
u32 ek[32], work[2];
/* Add parity bits to the key */
next = 0;
for (i = 0; i < 7; i++) {
tmp = key[i];
pkey[i] = (tmp >> i) | next | 1;
next = tmp << (7 - i);
}
pkey[i] = next | 1;
deskey(pkey, 0, ek);
work[0] = WPA_GET_BE32(clear);
work[1] = WPA_GET_BE32(clear + 4);
desfunc(work, ek);
WPA_PUT_BE32(cypher, work[0]);
WPA_PUT_BE32(cypher + 4, work[1]);
os_memset(pkey, 0, sizeof(pkey));
os_memset(ek, 0, sizeof(ek));
}
/*
void des_key_setup(const u8 *key, u32 *ek, u32 *dk)
{
deskey(key, 0, ek);
deskey(key, 1, dk);
}
void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt)
{
u32 work[2];
work[0] = WPA_GET_BE32(plain);
work[1] = WPA_GET_BE32(plain + 4);
desfunc(work, ek);
WPA_PUT_BE32(crypt, work[0]);
WPA_PUT_BE32(crypt + 4, work[1]);
}
void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain)
{
u32 work[2];
work[0] = WPA_GET_BE32(crypt);
work[1] = WPA_GET_BE32(crypt + 4);
desfunc(work, dk);
WPA_PUT_BE32(plain, work[0]);
WPA_PUT_BE32(plain + 4, work[1]);
}
void des3_key_setup(const u8 *key, struct des3_key_s *dkey)
{
deskey(key, 0, dkey->ek[0]);
deskey(key + 8, 1, dkey->ek[1]);
deskey(key + 16, 0, dkey->ek[2]);
deskey(key, 1, dkey->dk[2]);
deskey(key + 8, 0, dkey->dk[1]);
deskey(key + 16, 1, dkey->dk[0]);
}
void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt)
{
u32 work[2];
work[0] = WPA_GET_BE32(plain);
work[1] = WPA_GET_BE32(plain + 4);
desfunc(work, key->ek[0]);
desfunc(work, key->ek[1]);
desfunc(work, key->ek[2]);
WPA_PUT_BE32(crypt, work[0]);
WPA_PUT_BE32(crypt + 4, work[1]);
}
void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain)
{
u32 work[2];
work[0] = WPA_GET_BE32(crypt);
work[1] = WPA_GET_BE32(crypt + 4);
desfunc(work, key->dk[0]);
desfunc(work, key->dk[1]);
desfunc(work, key->dk[2]);
WPA_PUT_BE32(plain, work[0]);
WPA_PUT_BE32(plain + 4, work[1]);
}*/

View File

@ -0,0 +1,201 @@
/*
* MD4 hash implementation
*
* This software may be distributed under the terms of BSD license.
*/
#include "crypto/includes.h"
#include "crypto/common.h"
#include "crypto/crypto.h"
#define MD4_BLOCK_LENGTH 64
#define MD4_DIGEST_LENGTH 16
typedef struct MD4Context {
u32 state[4];
u64 count;
u8 buffer[MD4_BLOCK_LENGTH];
} MD4_CTX;
static void MD4Init(MD4_CTX *ctx);
static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len);
static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx);
int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{
MD4_CTX ctx;
size_t i;
MD4Init(&ctx);
for (i = 0; i < num_elem; i++)
MD4Update(&ctx, addr[i], len[i]);
MD4Final(mac, &ctx);
return 0;
}
#define MD4_DIGEST_STRING_LENGTH (MD4_DIGEST_LENGTH * 2 + 1)
static void MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH]);
#define PUT_64BIT_LE(cp, value) do { \
(cp)[7] = (value) >> 56; \
(cp)[6] = (value) >> 48; \
(cp)[5] = (value) >> 40; \
(cp)[4] = (value) >> 32; \
(cp)[3] = (value) >> 24; \
(cp)[2] = (value) >> 16; \
(cp)[1] = (value) >> 8; \
(cp)[0] = (value); } while (0)
#define PUT_32BIT_LE(cp, value) do { \
(cp)[3] = (value) >> 24; \
(cp)[2] = (value) >> 16; \
(cp)[1] = (value) >> 8; \
(cp)[0] = (value); } while (0)
static u8 PADDING[MD4_BLOCK_LENGTH] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static void MD4Init(MD4_CTX *ctx)
{
ctx->count = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xefcdab89;
ctx->state[2] = 0x98badcfe;
ctx->state[3] = 0x10325476;
}
static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len)
{
size_t have, need;
have = (size_t)((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1));
need = MD4_BLOCK_LENGTH - have;
ctx->count += (u64)len << 3;
if (len >= need) {
if (have != 0) {
os_memcpy(ctx->buffer + have, input, need);
MD4Transform(ctx->state, ctx->buffer);
input += need;
len -= need;
have = 0;
}
while (len >= MD4_BLOCK_LENGTH) {
MD4Transform(ctx->state, input);
input += MD4_BLOCK_LENGTH;
len -= MD4_BLOCK_LENGTH;
}
}
if (len != 0)
os_memcpy(ctx->buffer + have, input, len);
}
static void MD4Pad(MD4_CTX *ctx)
{
u8 count[8];
size_t padlen;
PUT_64BIT_LE(count, ctx->count);
padlen = MD4_BLOCK_LENGTH -
((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1));
if (padlen < 1 + 8)
padlen += MD4_BLOCK_LENGTH;
MD4Update(ctx, PADDING, padlen - 8);
MD4Update(ctx, count, 8);
}
static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx)
{
int i;
MD4Pad(ctx);
if (digest != NULL) {
for (i = 0; i < 4; i ++)
PUT_32BIT_LE(digest + i * 4, ctx->state[i]);
os_memset(ctx, 0, sizeof(*ctx));
}
}
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) ((x & y) | (x & z) | (y & z))
#define F3(x, y, z) (x ^ y ^ z)
#define MD4SETP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s) )
static void MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH])
{
u32 a, b, c, d, in[MD4_BLOCK_LENGTH / 4];
os_memcpy(in, block, sizeof(in));
a = state[0];
b = state[1];
c = state[2];
d = state[3];
MD4SETP(F1, a, b, c, d, in[ 0], 3);
MD4SETP(F1, d, a, b, c, in[ 1], 7);
MD4SETP(F1, c, d, a, b, in[ 2], 11);
MD4SETP(F1, b, c, d, a, in[ 3], 19);
MD4SETP(F1, a, b, c, d, in[ 4], 3);
MD4SETP(F1, d, a, b, c, in[ 5], 7);
MD4SETP(F1, c, d, a, b, in[ 6], 11);
MD4SETP(F1, b, c, d, a, in[ 7], 19);
MD4SETP(F1, a, b, c, d, in[ 8], 3);
MD4SETP(F1, d, a, b, c, in[ 9], 7);
MD4SETP(F1, c, d, a, b, in[10], 11);
MD4SETP(F1, b, c, d, a, in[11], 19);
MD4SETP(F1, a, b, c, d, in[12], 3);
MD4SETP(F1, d, a, b, c, in[13], 7);
MD4SETP(F1, c, d, a, b, in[14], 11);
MD4SETP(F1, b, c, d, a, in[15], 19);
MD4SETP(F2, a, b, c, d, in[ 0] + 0x5a827999, 3);
MD4SETP(F2, d, a, b, c, in[ 4] + 0x5a827999, 5);
MD4SETP(F2, c, d, a, b, in[ 8] + 0x5a827999, 9);
MD4SETP(F2, b, c, d, a, in[12] + 0x5a827999, 13);
MD4SETP(F2, a, b, c, d, in[ 1] + 0x5a827999, 3);
MD4SETP(F2, d, a, b, c, in[ 5] + 0x5a827999, 5);
MD4SETP(F2, c, d, a, b, in[ 9] + 0x5a827999, 9);
MD4SETP(F2, b, c, d, a, in[13] + 0x5a827999, 13);
MD4SETP(F2, a, b, c, d, in[ 2] + 0x5a827999, 3);
MD4SETP(F2, d, a, b, c, in[ 6] + 0x5a827999, 5);
MD4SETP(F2, c, d, a, b, in[10] + 0x5a827999, 9);
MD4SETP(F2, b, c, d, a, in[14] + 0x5a827999, 13);
MD4SETP(F2, a, b, c, d, in[ 3] + 0x5a827999, 3);
MD4SETP(F2, d, a, b, c, in[ 7] + 0x5a827999, 5);
MD4SETP(F2, c, d, a, b, in[11] + 0x5a827999, 9);
MD4SETP(F2, b, c, d, a, in[15] + 0x5a827999, 13);
MD4SETP(F3, a, b, c, d, in[ 0] + 0x6ed9eba1, 3);
MD4SETP(F3, d, a, b, c, in[ 8] + 0x6ed9eba1, 9);
MD4SETP(F3, c, d, a, b, in[ 4] + 0x6ed9eba1, 11);
MD4SETP(F3, b, c, d, a, in[12] + 0x6ed9eba1, 15);
MD4SETP(F3, a, b, c, d, in[ 2] + 0x6ed9eba1, 3);
MD4SETP(F3, d, a, b, c, in[10] + 0x6ed9eba1, 9);
MD4SETP(F3, c, d, a, b, in[ 6] + 0x6ed9eba1, 11);
MD4SETP(F3, b, c, d, a, in[14] + 0x6ed9eba1, 15);
MD4SETP(F3, a, b, c, d, in[ 1] + 0x6ed9eba1, 3);
MD4SETP(F3, d, a, b, c, in[ 9] + 0x6ed9eba1, 9);
MD4SETP(F3, c, d, a, b, in[ 5] + 0x6ed9eba1, 11);
MD4SETP(F3, b, c, d, a, in[13] + 0x6ed9eba1, 15);
MD4SETP(F3, a, b, c, d, in[ 3] + 0x6ed9eba1, 3);
MD4SETP(F3, d, a, b, c, in[11] + 0x6ed9eba1, 9);
MD4SETP(F3, c, d, a, b, in[ 7] + 0x6ed9eba1, 11);
MD4SETP(F3, b, c, d, a, in[15] + 0x6ed9eba1, 15);
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
}

View File

@ -0,0 +1,528 @@
/*
* WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
* Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "wpa/includes.h"
#include "wpa/common.h"
#include "crypto/sha1.h"
#include "crypto/ms_funcs.h"
#include "crypto/crypto.h"
/**
* utf8_to_ucs2 - Convert UTF-8 string to UCS-2 encoding
* @utf8_string: UTF-8 string (IN)
* @utf8_string_len: Length of utf8_string (IN)
* @ucs2_buffer: UCS-2 buffer (OUT)
* @ucs2_buffer_size: Length of UCS-2 buffer (IN)
* @ucs2_string_size: Number of 2-byte words in the resulting UCS-2 string
* Returns: 0 on success, -1 on failure
*/
static int utf8_to_ucs2(const u8 *utf8_string, size_t utf8_string_len,
u8 *ucs2_buffer, size_t ucs2_buffer_size,
size_t *ucs2_string_size)
{
size_t i, j;
for (i = 0, j = 0; i < utf8_string_len; i++) {
u8 c = utf8_string[i];
if (j >= ucs2_buffer_size) {
/* input too long */
return -1;
}
if (c <= 0x7F) {
WPA_PUT_LE16(ucs2_buffer + j, c);
j += 2;
} else if (i == utf8_string_len - 1 ||
j >= ucs2_buffer_size - 1) {
/* incomplete surrogate */
return -1;
} else {
u8 c2 = utf8_string[++i];
if ((c & 0xE0) == 0xC0) {
/* two-byte encoding */
WPA_PUT_LE16(ucs2_buffer + j,
((c & 0x1F) << 6) | (c2 & 0x3F));
j += 2;
} else if (i == utf8_string_len ||
j >= ucs2_buffer_size - 1) {
/* incomplete surrogate */
return -1;
} else {
/* three-byte encoding */
u8 c3 = utf8_string[++i];
WPA_PUT_LE16(ucs2_buffer + j,
((c & 0xF) << 12) |
((c2 & 0x3F) << 6) | (c3 & 0x3F));
}
}
}
if (ucs2_string_size)
*ucs2_string_size = j / 2;
return 0;
}
/**
* challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2
* @peer_challenge: 16-octet PeerChallenge (IN)
* @auth_challenge: 16-octet AuthenticatorChallenge (IN)
* @username: 0-to-256-char UserName (IN)
* @username_len: Length of username
* @challenge: 8-octet Challenge (OUT)
* Returns: 0 on success, -1 on failure
*/
static int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
const u8 *username, size_t username_len,
u8 *challenge)
{
u8 hash[SHA1_MAC_LEN];
const unsigned char *addr[3];
size_t len[3];
addr[0] = peer_challenge;
len[0] = 16;
addr[1] = auth_challenge;
len[1] = 16;
addr[2] = username;
len[2] = username_len;
if (sha1_vector(3, addr, len, hash))
return -1;
os_memcpy(challenge, hash, 8);
return 0;
}
/**
* nt_password_hash - NtPasswordHash() - RFC 2759, Sect. 8.3
* @password: 0-to-256-unicode-char Password (IN; UTF-8)
* @password_len: Length of password
* @password_hash: 16-octet PasswordHash (OUT)
* Returns: 0 on success, -1 on failure
*/
int nt_password_hash(const u8 *password, size_t password_len,
u8 *password_hash)
{
u8 buf[512], *pos;
size_t len, max_len;
max_len = sizeof(buf);
if (utf8_to_ucs2(password, password_len, buf, max_len, &len) < 0)
return -1;
len *= 2;
pos = buf;
return md4_vector(1, (const u8 **) &pos, &len, password_hash);
}
/**
* hash_nt_password_hash - HashNtPasswordHash() - RFC 2759, Sect. 8.4
* @password_hash: 16-octet PasswordHash (IN)
* @password_hash_hash: 16-octet PasswordHashHash (OUT)
* Returns: 0 on success, -1 on failure
*/
int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash)
{
size_t len = 16;
return md4_vector(1, &password_hash, &len, password_hash_hash);
}
/**
* challenge_response - ChallengeResponse() - RFC 2759, Sect. 8.5
* @challenge: 8-octet Challenge (IN)
* @password_hash: 16-octet PasswordHash (IN)
* @response: 24-octet Response (OUT)
*/
void challenge_response(const u8 *challenge, const u8 *password_hash,
u8 *response)
{
u8 zpwd[7];
des_encrypt(challenge, password_hash, response);
des_encrypt(challenge, password_hash + 7, response + 8);
zpwd[0] = password_hash[14];
zpwd[1] = password_hash[15];
os_memset(zpwd + 2, 0, 5);
des_encrypt(challenge, zpwd, response + 16);
}
/**
* generate_nt_response - GenerateNTResponse() - RFC 2759, Sect. 8.1
* @auth_challenge: 16-octet AuthenticatorChallenge (IN)
* @peer_challenge: 16-octet PeerChallenge (IN)
* @username: 0-to-256-char UserName (IN)
* @username_len: Length of username
* @password: 0-to-256-unicode-char Password (IN; UTF-8)
* @password_len: Length of password
* @response: 24-octet Response (OUT)
* Returns: 0 on success, -1 on failure
*/
int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
const u8 *username, size_t username_len,
const u8 *password, size_t password_len,
u8 *response)
{
u8 challenge[8];
u8 password_hash[16];
if (challenge_hash(peer_challenge, auth_challenge, username,
username_len, challenge))
return -1;
if (nt_password_hash(password, password_len, password_hash))
return -1;
challenge_response(challenge, password_hash, response);
return 0;
}
/**
* generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1
* @auth_challenge: 16-octet AuthenticatorChallenge (IN)
* @peer_challenge: 16-octet PeerChallenge (IN)
* @username: 0-to-256-char UserName (IN)
* @username_len: Length of username
* @password_hash: 16-octet PasswordHash (IN)
* @response: 24-octet Response (OUT)
* Returns: 0 on success, -1 on failure
*/
int generate_nt_response_pwhash(const u8 *auth_challenge,
const u8 *peer_challenge,
const u8 *username, size_t username_len,
const u8 *password_hash,
u8 *response)
{
u8 challenge[8];
if (challenge_hash(peer_challenge, auth_challenge,
username, username_len,
challenge))
return -1;
challenge_response(challenge, password_hash, response);
return 0;
}
/**
* generate_authenticator_response_pwhash - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
* @password_hash: 16-octet PasswordHash (IN)
* @nt_response: 24-octet NT-Response (IN)
* @peer_challenge: 16-octet PeerChallenge (IN)
* @auth_challenge: 16-octet AuthenticatorChallenge (IN)
* @username: 0-to-256-char UserName (IN)
* @username_len: Length of username
* @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
* encoded as a 42-octet ASCII string (S=hexdump_of_response)
* Returns: 0 on success, -1 on failure
*/
int generate_authenticator_response_pwhash(
const u8 *password_hash,
const u8 *peer_challenge, const u8 *auth_challenge,
const u8 *username, size_t username_len,
const u8 *nt_response, u8 *response)
{
static const u8 magic1[39] = {
0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
};
static const u8 magic2[41] = {
0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
0x6E
};
u8 password_hash_hash[16], challenge[8];
const unsigned char *addr1[3];
const size_t len1[3] = { 16, 24, sizeof(magic1) };
const unsigned char *addr2[3];
const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) };
addr1[0] = password_hash_hash;
addr1[1] = nt_response;
addr1[2] = magic1;
addr2[0] = response;
addr2[1] = challenge;
addr2[2] = magic2;
if (hash_nt_password_hash(password_hash, password_hash_hash))
return -1;
if (sha1_vector(3, addr1, len1, response))
return -1;
if (challenge_hash(peer_challenge, auth_challenge, username,
username_len, challenge))
return -1;
return sha1_vector(3, addr2, len2, response);
}
/**
* generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
* @password: 0-to-256-unicode-char Password (IN; UTF-8)
* @password_len: Length of password
* @nt_response: 24-octet NT-Response (IN)
* @peer_challenge: 16-octet PeerChallenge (IN)
* @auth_challenge: 16-octet AuthenticatorChallenge (IN)
* @username: 0-to-256-char UserName (IN)
* @username_len: Length of username
* @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
* encoded as a 42-octet ASCII string (S=hexdump_of_response)
* Returns: 0 on success, -1 on failure
*/
int generate_authenticator_response(const u8 *password, size_t password_len,
const u8 *peer_challenge,
const u8 *auth_challenge,
const u8 *username, size_t username_len,
const u8 *nt_response, u8 *response)
{
u8 password_hash[16];
if (nt_password_hash(password, password_len, password_hash))
return -1;
return generate_authenticator_response_pwhash(
password_hash, peer_challenge, auth_challenge,
username, username_len, nt_response, response);
}
/**
* nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5
* @challenge: 8-octet Challenge (IN)
* @password: 0-to-256-unicode-char Password (IN; UTF-8)
* @password_len: Length of password
* @response: 24-octet Response (OUT)
* Returns: 0 on success, -1 on failure
*/
int nt_challenge_response(const u8 *challenge, const u8 *password,
size_t password_len, u8 *response)
{
u8 password_hash[16];
if (nt_password_hash(password, password_len, password_hash))
return -1;
challenge_response(challenge, password_hash, response);
return 0;
}
/**
* get_master_key - GetMasterKey() - RFC 3079, Sect. 3.4
* @password_hash_hash: 16-octet PasswordHashHash (IN)
* @nt_response: 24-octet NTResponse (IN)
* @master_key: 16-octet MasterKey (OUT)
* Returns: 0 on success, -1 on failure
*/
int get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
u8 *master_key)
{
static const u8 magic1[27] = {
0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
};
const unsigned char *addr[3];
const size_t len[3] = { 16, 24, sizeof(magic1) };
u8 hash[SHA1_MAC_LEN];
addr[0] = password_hash_hash;
addr[1] = nt_response;
addr[2] = magic1;
if (sha1_vector(3, addr, len, hash))
return -1;
os_memcpy(master_key, hash, 16);
return 0;
}
/**
* get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4
* @master_key: 16-octet MasterKey (IN)
* @session_key: 8-to-16 octet SessionKey (OUT)
* @session_key_len: SessionKeyLength (Length of session_key) (IN)
* @is_send: IsSend (IN, BOOLEAN)
* @is_server: IsServer (IN, BOOLEAN)
* Returns: 0 on success, -1 on failure
*/
int get_asymetric_start_key(const u8 *master_key, u8 *session_key,
size_t session_key_len, int is_send,
int is_server)
{
static const u8 magic2[84] = {
0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
0x6b, 0x65, 0x79, 0x2e
};
static const u8 magic3[84] = {
0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
0x6b, 0x65, 0x79, 0x2e
};
static const u8 shs_pad1[40] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const u8 shs_pad2[40] = {
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
};
u8 digest[SHA1_MAC_LEN];
const unsigned char *addr[4];
const size_t len[4] = { 16, 40, 84, 40 };
addr[0] = master_key;
addr[1] = shs_pad1;
if (is_send) {
addr[2] = is_server ? magic3 : magic2;
} else {
addr[2] = is_server ? magic2 : magic3;
}
addr[3] = shs_pad2;
if (sha1_vector(4, addr, len, digest))
return -1;
if (session_key_len > SHA1_MAC_LEN)
session_key_len = SHA1_MAC_LEN;
os_memcpy(session_key, digest, session_key_len);
return 0;
}
#define PWBLOCK_LEN 516
/**
* encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10
* @password: 0-to-256-unicode-char Password (IN; UTF-8)
* @password_len: Length of password
* @password_hash: 16-octet PasswordHash (IN)
* @pw_block: 516-byte PwBlock (OUT)
* Returns: 0 on success, -1 on failure
*/
int encrypt_pw_block_with_password_hash(
const u8 *password, size_t password_len,
const u8 *password_hash, u8 *pw_block)
{
size_t ucs2_len, offset;
u8 *pos;
os_memset(pw_block, 0, PWBLOCK_LEN);
if (utf8_to_ucs2(password, password_len, pw_block, 512, &ucs2_len) < 0)
return -1;
if (ucs2_len > 256)
return -1;
offset = (256 - ucs2_len) * 2;
if (offset != 0) {
os_memmove(pw_block + offset, pw_block, ucs2_len * 2);
if (os_get_random(pw_block, offset) < 0)
return -1;
}
/*
* PasswordLength is 4 octets, but since the maximum password length is
* 256, only first two (in little endian byte order) can be non-zero.
*/
pos = &pw_block[2 * 256];
WPA_PUT_LE16(pos, password_len * 2);
rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN);
return 0;
}
/**
* new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9
* @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8)
* @new_password_len: Length of new_password
* @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8)
* @old_password_len: Length of old_password
* @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT)
* Returns: 0 on success, -1 on failure
*/
int new_password_encrypted_with_old_nt_password_hash(
const u8 *new_password, size_t new_password_len,
const u8 *old_password, size_t old_password_len,
u8 *encrypted_pw_block)
{
u8 password_hash[16];
if (nt_password_hash(old_password, old_password_len, password_hash))
return -1;
if (encrypt_pw_block_with_password_hash(new_password, new_password_len,
password_hash,
encrypted_pw_block))
return -1;
return 0;
}
/**
* nt_password_hash_encrypted_with_block - NtPasswordHashEncryptedWithBlock() - RFC 2759, Sect 8.13
* @password_hash: 16-octer PasswordHash (IN)
* @block: 16-octet Block (IN)
* @cypher: 16-octer Cypher (OUT)
*/
void nt_password_hash_encrypted_with_block(const u8 *password_hash,
const u8 *block, u8 *cypher)
{
des_encrypt(password_hash, block, cypher);
des_encrypt(password_hash + 8, block + 7, cypher + 8);
}
/**
* old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12
* @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8)
* @new_password_len: Length of new_password
* @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8)
* @old_password_len: Length of old_password
* @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT)
* Returns: 0 on success, -1 on failure
*/
int old_nt_password_hash_encrypted_with_new_nt_password_hash(
const u8 *new_password, size_t new_password_len,
const u8 *old_password, size_t old_password_len,
u8 *encrypted_password_hash)
{
u8 old_password_hash[16], new_password_hash[16];
if (nt_password_hash(old_password, old_password_len,
old_password_hash) ||
nt_password_hash(new_password, new_password_len,
new_password_hash))
return -1;
nt_password_hash_encrypted_with_block(old_password_hash,
new_password_hash,
encrypted_password_hash);
return 0;
}

View File

@ -23,7 +23,8 @@ INPUT = ../components/esp32/include/esp_wifi.h \
../components/vfs/include \
../components/spi_flash/include \
../components/esp32/include/esp_int_wdt.h \
../components/esp32/include/esp_task_wdt.h
../components/esp32/include/esp_task_wdt.h \
../components/app_update/include/esp_ota_ops.h
## Get warnings for functions that have no documentation for their parameters or return value
##

46
docs/api/ota.rst Normal file
View File

@ -0,0 +1,46 @@
OTA
===
Overview
--------
`Instructions`_
Application Example
-------------------
`Instructions`_
API Reference
-------------
`Instructions`_
.. _Instructions: template.html
Header Files
^^^^^^^^^^^^
* `app_update/include/esp_ota_ops.h <https://github.com/espressif/esp-idf/blob/master/components/app_update/include/esp_ota_ops.h>`_
Macros
------
.. doxygendefine:: ESP_ERR_OTA_BASE
.. doxygendefine:: ESP_ERR_OTA_PARTITION_CONFLICT
.. doxygendefine:: ESP_ERR_OTA_SELECT_INFO_INVALID
.. doxygendefine:: ESP_ERR_OTA_VALIDATE_FAILED
Type Definitions
^^^^^^^^^^^^^^^^
.. doxygentypedef:: esp_ota_handle_t
Functions
^^^^^^^^^
.. doxygenfunction:: esp_ota_begin
.. doxygenfunction:: esp_ota_write
.. doxygenfunction:: esp_ota_end
.. doxygenfunction:: esp_ota_set_boot_partition
.. doxygenfunction:: esp_ota_get_boot_partition

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

73
docs/api/timer.rst Normal file
View File

@ -0,0 +1,73 @@
TIMER
========
Overview
--------
ESP32 chip contains two hardware timer groups, each containing two general-purpose hardware timers.
They are all 64-bit generic timers based on 16-bit prescalers and 64-bit auto-reload-capable up/down counters.
Application Example
-------------------
64-bit hardware timer example: `examples/13_timer_group <https://github.com/espressif/esp-idf/tree/master/examples/13_timer_group>`_.
API Reference
-------------
Header Files
^^^^^^^^^^^^
* `components/driver/timer.h <https://github.com/espressif/esp-idf/blob/master/components/driver/include/driver/timer.h>`_
Macros
^^^^^^
.. doxygendefine:: TIMER_BASE_CLK
Type Definitions
^^^^^^^^^^^^^^^^
Enumerations
^^^^^^^^^^^^
.. doxygenenum:: timer_group_t
.. doxygenenum:: timer_idx_t
.. doxygenenum:: timer_count_dir_t
.. doxygenenum:: timer_start_t
.. doxygenenum:: timer_alarm_t
.. doxygenenum:: timer_intr_mode_t
.. doxygenenum:: timer_autoreload_t
Structures
^^^^^^^^^^
.. doxygenstruct:: timer_config_t
:members:
Functions
^^^^^^^^^
.. doxygenfunction:: timer_get_counter_value
.. doxygenfunction:: timer_get_counter_time_sec
.. doxygenfunction:: timer_set_counter_value
.. doxygenfunction:: timer_start
.. doxygenfunction:: timer_pause
.. doxygenfunction:: timer_set_counter_mode
.. doxygenfunction:: timer_set_auto_reload
.. doxygenfunction:: timer_set_divider
.. doxygenfunction:: timer_set_alarm_value
.. doxygenfunction:: timer_get_alarm_value
.. doxygenfunction:: timer_set_alarm
.. doxygenfunction:: timer_isr_register
.. doxygenfunction:: timer_init
.. doxygenfunction:: timer_get_config
.. doxygenfunction:: timer_group_intr_enable
.. doxygenfunction:: timer_group_intr_disable
.. doxygenfunction:: timer_enable_intr
.. doxygenfunction:: timer_disable_intr

View File

@ -244,6 +244,7 @@ The following variables can be set inside ``component.mk`` to control the build
settings. Component-specific additions can be made via ``CXXFLAGS
+=``. It is also possible (although not recommended) to override
this variable completely for a component.
- ``FLAGS_basename`` allows you to set compilation flags to apply to a single source file only. For example, this can useful for disabling warnings in a single upstream source file. The ``basename`` portion is the directory (relative to ``COMPONENT_PATH``) and the base filename (without extension) of the source file. For example, if a file inside ``COMPONENT_PATH`` is ``library/alpha/widget.c`` then you can set variable ``FLAGS_library/alpha/widget := -DTEST`` to pass the TEST macro when compiling this source file only.
Component Configuration
-----------------------

View File

@ -97,11 +97,13 @@ Contents:
Wi-Fi <api/esp_wifi>
Bluetooth <api/bt>
Watchdogs <api/wdts>
api/gpio
api/uart
api/ledc
api/rmt
OTA <api/ota>
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()

Some files were not shown because too many files have changed in this diff Show More