Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
20a3b4c0cd
101 changed files with 8203 additions and 1133 deletions
|
|
@ -22,10 +22,10 @@ build-examples: $(EXAMPLES_BUILD)
|
|||
rebuild-examples: $(EXAMPLES_REBUILD)
|
||||
|
||||
%.dummybuild:
|
||||
make -C $(dir $@)
|
||||
$(MAKE) -C $(dir $@)
|
||||
|
||||
%.dummyrebuild:
|
||||
make -C $(dir $@) rebuild
|
||||
$(MAKE) -C $(dir $@) rebuild
|
||||
|
||||
.PHONY: warning rebuild-examples build-examples
|
||||
.NOTPARALLEL:
|
||||
|
|
|
|||
3
examples/bmp180_i2c/Makefile
Normal file
3
examples/bmp180_i2c/Makefile
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
PROGRAM=BMP180_Reader
|
||||
EXTRA_COMPONENTS = extras/i2c extras/bmp180
|
||||
include ../../common.mk
|
||||
7
examples/bmp180_i2c/README.md
Normal file
7
examples/bmp180_i2c/README.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# I2C / BMP180 Example
|
||||
|
||||
This example references two addtional drivers [i2c](https://github.com/kanflo/esp-open-rtos-driver-i2c) and [bmp180](https://github.com/Angus71/esp-open-rtos-driver-bmp180), which are provided in the `../../extras` folder.
|
||||
|
||||
If you plan to use one or both of this drivers in your own projects, please check the main development pages for updated versions or reported issues.
|
||||
|
||||
To run this example connect the BMP085/BMP180 SCL to GPIO0 and SDA to GPIO2.
|
||||
132
examples/bmp180_i2c/bmp180_i2c.c
Normal file
132
examples/bmp180_i2c/bmp180_i2c.c
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/* Simple example for I2C / BMP180 / Timer & Event Handling
|
||||
*
|
||||
* This sample code is in the public domain.
|
||||
*/
|
||||
#include "espressif/esp_common.h"
|
||||
#include "espressif/sdk_private.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "timers.h"
|
||||
#include "queue.h"
|
||||
|
||||
// BMP180 driver
|
||||
#include "bmp180/bmp180.h"
|
||||
|
||||
#define MY_EVT_TIMER 0x01
|
||||
#define MY_EVT_BMP180 0x02
|
||||
|
||||
#define SCL_PIN GPIO_ID_PIN((0))
|
||||
#define SDA_PIN GPIO_ID_PIN((2))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t event_type;
|
||||
bmp180_result_t bmp180_data;
|
||||
} my_event_t;
|
||||
|
||||
// Communication Queue
|
||||
static xQueueHandle mainqueue;
|
||||
static xTimerHandle timerHandle;
|
||||
|
||||
// Own BMP180 User Inform Implementation
|
||||
bool bmp180_i2c_informUser(const xQueueHandle* resultQueue, uint8_t cmd, bmp180_temp_t temperature, bmp180_press_t pressure)
|
||||
{
|
||||
my_event_t ev;
|
||||
|
||||
ev.event_type = MY_EVT_BMP180;
|
||||
ev.bmp180_data.cmd = cmd;
|
||||
ev.bmp180_data.temperature = temperature;
|
||||
ev.bmp180_data.pressure = pressure;
|
||||
|
||||
return (xQueueSend(*resultQueue, &ev, 0) == pdTRUE);
|
||||
}
|
||||
|
||||
// Timer call back
|
||||
static void bmp180_i2c_timer_cb(xTimerHandle xTimer)
|
||||
{
|
||||
my_event_t ev;
|
||||
ev.event_type = MY_EVT_TIMER;
|
||||
|
||||
xQueueSend(mainqueue, &ev, 0);
|
||||
}
|
||||
|
||||
// Check for communiction events
|
||||
void bmp180_task(void *pvParameters)
|
||||
{
|
||||
// Received pvParameters is communication queue
|
||||
xQueueHandle *com_queue = (xQueueHandle *)pvParameters;
|
||||
|
||||
printf("%s: Started user interface task\n", __FUNCTION__);
|
||||
|
||||
while(1)
|
||||
{
|
||||
my_event_t ev;
|
||||
|
||||
xQueueReceive(*com_queue, &ev, portMAX_DELAY);
|
||||
|
||||
switch(ev.event_type)
|
||||
{
|
||||
case MY_EVT_TIMER:
|
||||
printf("%s: Received Timer Event\n", __FUNCTION__);
|
||||
|
||||
bmp180_trigger_measurement(com_queue);
|
||||
break;
|
||||
case MY_EVT_BMP180:
|
||||
printf("%s: Received BMP180 Event temp:=%d.%d°C press=%d.%02dhPa\n", __FUNCTION__, \
|
||||
(int32_t)ev.bmp180_data.temperature, abs((int32_t)(ev.bmp180_data.temperature*10)%10), \
|
||||
ev.bmp180_data.pressure/100, ev.bmp180_data.pressure%100 );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Setup HW
|
||||
void user_setup(void)
|
||||
{
|
||||
// Set UART Parameter
|
||||
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
|
||||
|
||||
// Give the UART some time to settle
|
||||
sdk_os_delay_us(500);
|
||||
}
|
||||
|
||||
void user_init(void)
|
||||
{
|
||||
// Setup HW
|
||||
user_setup();
|
||||
|
||||
// Just some infomations
|
||||
printf("\n");
|
||||
printf("SDK version : %s\n", sdk_system_get_sdk_version());
|
||||
printf("GIT version : %s\n", GITSHORTREV);
|
||||
|
||||
// Use our user inform implementation
|
||||
bmp180_informUser = bmp180_i2c_informUser;
|
||||
|
||||
// Init BMP180 Interface
|
||||
bmp180_init(SCL_PIN, SDA_PIN);
|
||||
|
||||
// Create Main Communication Queue
|
||||
mainqueue = xQueueCreate(10, sizeof(my_event_t));
|
||||
|
||||
// Create user interface task
|
||||
xTaskCreate(bmp180_task, (signed char *)"bmp180_task", 256, &mainqueue, 2, NULL);
|
||||
|
||||
// Create Timer (Trigger a measurement every second)
|
||||
timerHandle = xTimerCreate((signed char *)"BMP180 Trigger", 1000/portTICK_RATE_MS, pdTRUE, NULL, bmp180_i2c_timer_cb);
|
||||
|
||||
if (timerHandle != NULL)
|
||||
{
|
||||
if (xTimerStart(timerHandle, 0) != pdPASS)
|
||||
{
|
||||
printf("%s: Unable to start Timer ...\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%s: Unable to create Timer ...\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@ void buttonPollTask(void *pvParameters)
|
|||
{
|
||||
taskYIELD();
|
||||
}
|
||||
printf("Polled for button press at %ldms\r\n", xTaskGetTickCount()*portTICK_RATE_MS);
|
||||
printf("Polled for button press at %dms\r\n", xTaskGetTickCount()*portTICK_RATE_MS);
|
||||
vTaskDelay(200 / portTICK_RATE_MS);
|
||||
}
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ void buttonIntTask(void *pvParameters)
|
|||
xQueueReceive(*tsqueue, &button_ts, portMAX_DELAY);
|
||||
button_ts *= portTICK_RATE_MS;
|
||||
if(last < button_ts-200) {
|
||||
printf("Button interrupt fired at %ldms\r\n", button_ts);
|
||||
printf("Button interrupt fired at %dms\r\n", button_ts);
|
||||
last = button_ts;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
5
examples/cpp_01_tasks/Makefile
Normal file
5
examples/cpp_01_tasks/Makefile
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Simple makefile for simple example
|
||||
PROGRAM=cpp_01_tasks
|
||||
OTA=0
|
||||
EXTRA_COMPONENTS=extras/cpp_support
|
||||
include ../../common.mk
|
||||
106
examples/cpp_01_tasks/cpp_tasks.cpp
Normal file
106
examples/cpp_01_tasks/cpp_tasks.cpp
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* ESP8266 FreeRTOS Firmware
|
||||
* Copyright (c) 2015 Michael Jacobsen (github.com/mikejac)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* https://github.com/SuperHouse/esp-open-rtos
|
||||
*
|
||||
*/
|
||||
|
||||
#include "task.hpp"
|
||||
#include "queue.hpp"
|
||||
|
||||
#include "espressif/esp_common.h"
|
||||
|
||||
/******************************************************************************************************************
|
||||
* task_1_t
|
||||
*
|
||||
*/
|
||||
class task_1_t: public esp_open_rtos::thread::task_t
|
||||
{
|
||||
public:
|
||||
esp_open_rtos::thread::queue_t<uint32_t> queue;
|
||||
|
||||
private:
|
||||
void task()
|
||||
{
|
||||
printf("task_1_t::task(): start\n");
|
||||
|
||||
uint32_t count = 0;
|
||||
|
||||
while(true) {
|
||||
sleep(1000);
|
||||
queue.post(count);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
};
|
||||
/******************************************************************************************************************
|
||||
* task_2_t
|
||||
*
|
||||
*/
|
||||
class task_2_t: public esp_open_rtos::thread::task_t
|
||||
{
|
||||
public:
|
||||
esp_open_rtos::thread::queue_t<uint32_t> queue;
|
||||
|
||||
private:
|
||||
void task()
|
||||
{
|
||||
printf("task_2_t::task(): start\n");
|
||||
|
||||
while(true) {
|
||||
uint32_t count;
|
||||
|
||||
if(queue.receive(count, 1500) == 0) {
|
||||
printf("task_2_t::task(): got %u\n", count);
|
||||
}
|
||||
else {
|
||||
printf("task_2_t::task(): no msg\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
/******************************************************************************************************************
|
||||
* globals
|
||||
*
|
||||
*/
|
||||
task_1_t task_1;
|
||||
task_2_t task_2;
|
||||
|
||||
esp_open_rtos::thread::queue_t<uint32_t> MyQueue;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
extern "C" void user_init(void)
|
||||
{
|
||||
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
|
||||
|
||||
MyQueue.queue_create(10);
|
||||
|
||||
task_1.queue = MyQueue;
|
||||
task_2.queue = MyQueue;
|
||||
|
||||
task_1.task_create("tsk1");
|
||||
task_2.task_create("tsk2");
|
||||
}
|
||||
|
|
@ -20,8 +20,8 @@ IRAM void dump_frc1_seq(void)
|
|||
uint32_t f1_a = TIMER(0).COUNT;
|
||||
uint32_t f1_b = TIMER(0).COUNT;
|
||||
uint32_t f1_c = TIMER(0).COUNT;
|
||||
printf("FRC1 sequence 0x%08lx 0x%08lx 0x%08lx\r\n", f1_a, f1_b, f1_c);
|
||||
printf("FRC1 deltas %ld %ld \r\n", f1_b-f1_a, f1_c-f1_b);
|
||||
printf("FRC1 sequence 0x%08x 0x%08x 0x%08x\r\n", f1_a, f1_b, f1_c);
|
||||
printf("FRC1 deltas %d %d \r\n", f1_b-f1_a, f1_c-f1_b);
|
||||
}
|
||||
|
||||
IRAM void dump_frc2_seq(void)
|
||||
|
|
@ -37,8 +37,8 @@ IRAM void dump_frc2_seq(void)
|
|||
uint32_t f2_a = TIMER(1).COUNT;
|
||||
uint32_t f2_b = TIMER(1).COUNT;
|
||||
uint32_t f2_c = TIMER(1).COUNT;
|
||||
printf("FRC2 sequence 0x%08lx 0x%08lx 0x%08lx\r\n", f2_a, f2_b, f2_c);
|
||||
printf("FRC2 deltas %ld %ld \r\n", f2_b-f2_a, f2_c-f2_b);
|
||||
printf("FRC2 sequence 0x%08x 0x%08x 0x%08x\r\n", f2_a, f2_b, f2_c);
|
||||
printf("FRC2 deltas %d %d \r\n", f2_b-f2_a, f2_c-f2_b);
|
||||
}
|
||||
|
||||
IRAM void dump_timer_regs(const char *msg)
|
||||
|
|
@ -56,7 +56,7 @@ IRAM void dump_timer_regs(const char *msg)
|
|||
for(int i = 0; i < DUMP_SZ; i++) {
|
||||
if(i % 4 == 0)
|
||||
printf("%s0x%02x: ", i ? "\r\n" : "", i*4);
|
||||
printf("%08lx ", chunk[i]);
|
||||
printf("%08x ", chunk[i]);
|
||||
}
|
||||
printf("\r\n");
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ static volatile uint32_t frc1_last_count_val;
|
|||
void timerRegTask(void *pvParameters)
|
||||
{
|
||||
while(1) {
|
||||
printf("state at task tick count %ld:\r\n", xTaskGetTickCount());
|
||||
printf("state at task tick count %d:\r\n", xTaskGetTickCount());
|
||||
dump_timer_regs("");
|
||||
|
||||
/*
|
||||
|
|
@ -87,10 +87,10 @@ void timerRegTask(void *pvParameters)
|
|||
printf("INUM_MAX count %d\r\n", max_count);
|
||||
*/
|
||||
|
||||
printf("frc1 handler called %ld times, last value 0x%08lx\r\n", frc1_handler_call_count,
|
||||
printf("frc1 handler called %d times, last value 0x%08x\r\n", frc1_handler_call_count,
|
||||
frc1_last_count_val);
|
||||
|
||||
printf("frc2 handler called %ld times, last value 0x%08lx\r\n", frc2_handler_call_count,
|
||||
printf("frc2 handler called %d times, last value 0x%08x\r\n", frc2_handler_call_count,
|
||||
frc2_last_count_val);
|
||||
|
||||
vTaskDelay(500 / portTICK_RATE_MS);
|
||||
|
|
|
|||
2
examples/experiments/unaligned_load/Makefile
Normal file
2
examples/experiments/unaligned_load/Makefile
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
PROGRAM=unaligned_load
|
||||
include ../../../common.mk
|
||||
432
examples/experiments/unaligned_load/unaligned_load.c
Normal file
432
examples/experiments/unaligned_load/unaligned_load.c
Normal file
|
|
@ -0,0 +1,432 @@
|
|||
/* Very basic example that just demonstrates we can run at all!
|
||||
*/
|
||||
#include "esp/rom.h"
|
||||
#include "esp/timer.h"
|
||||
#include "espressif/esp_common.h"
|
||||
#include "espressif/sdk_private.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
|
||||
#include "string.h"
|
||||
#include "strings.h"
|
||||
|
||||
#define TESTSTRING "O hai there! %d %d %d"
|
||||
|
||||
const char *dramtest = TESTSTRING;
|
||||
const __attribute__((section(".iram1.notrodata"))) char iramtest[] = TESTSTRING;
|
||||
const __attribute__((section(".text.notrodata"))) char iromtest[] = TESTSTRING;
|
||||
|
||||
INLINED uint32_t get_ccount (void)
|
||||
{
|
||||
uint32_t ccount;
|
||||
asm volatile ("rsr.ccount %0" : "=a" (ccount));
|
||||
return ccount;
|
||||
}
|
||||
|
||||
typedef void (* test_with_fn_t)(const char *string);
|
||||
|
||||
char buf[64];
|
||||
|
||||
void test_memcpy_aligned(const char *string)
|
||||
{
|
||||
memcpy(buf, string, 16);
|
||||
}
|
||||
|
||||
void test_memcpy_unaligned(const char *string)
|
||||
{
|
||||
memcpy(buf, string, 15);
|
||||
}
|
||||
|
||||
void test_memcpy_unaligned2(const char *string)
|
||||
{
|
||||
memcpy(buf, string+1, 15);
|
||||
}
|
||||
|
||||
void test_strcpy(const char *string)
|
||||
{
|
||||
strcpy(buf, string);
|
||||
}
|
||||
|
||||
void test_sprintf(const char *string)
|
||||
{
|
||||
sprintf(buf, string, 1, 2, 3);
|
||||
}
|
||||
|
||||
void test_sprintf_arg(const char *string)
|
||||
{
|
||||
sprintf(buf, "%s", string);
|
||||
}
|
||||
|
||||
void test_naive_strcpy(const char *string)
|
||||
{
|
||||
char *to = buf;
|
||||
while((*to++ = *string++))
|
||||
;
|
||||
}
|
||||
|
||||
void test_naive_strcpy_a0(const char *string)
|
||||
{
|
||||
asm volatile (
|
||||
" mov a8, %0 \n"
|
||||
" mov a9, %1 \n"
|
||||
"tns_loop%=: l8ui a0, a9, 0 \n"
|
||||
" addi.n a9, a9, 1 \n"
|
||||
" s8i a0, a8, 0 \n"
|
||||
" addi.n a8, a8, 1 \n"
|
||||
" bnez a0, tns_loop%=\n"
|
||||
: : "r" (buf), "r" (string) : "a0", "a8", "a9");
|
||||
}
|
||||
|
||||
void test_naive_strcpy_a2(const char *string)
|
||||
{
|
||||
asm volatile (
|
||||
" mov a8, %0 \n"
|
||||
" mov a9, %1 \n"
|
||||
"tns_loop%=: l8ui a2, a9, 0 \n"
|
||||
" addi.n a9, a9, 1 \n"
|
||||
" s8i a2, a8, 0 \n"
|
||||
" addi.n a8, a8, 1 \n"
|
||||
" bnez a2, tns_loop%=\n"
|
||||
: : "r" (buf), "r" (string) : "a2", "a8", "a9");
|
||||
}
|
||||
|
||||
void test_naive_strcpy_a3(const char *string)
|
||||
{
|
||||
asm volatile (
|
||||
" mov a8, %0 \n"
|
||||
" mov a9, %1 \n"
|
||||
"tns_loop%=: l8ui a3, a9, 0 \n"
|
||||
" addi.n a9, a9, 1 \n"
|
||||
" s8i a3, a8, 0 \n"
|
||||
" addi.n a8, a8, 1 \n"
|
||||
" bnez a3, tns_loop%=\n"
|
||||
: : "r" (buf), "r" (string) : "a3", "a8", "a9");
|
||||
}
|
||||
|
||||
void test_naive_strcpy_a4(const char *string)
|
||||
{
|
||||
asm volatile (
|
||||
" mov a8, %0 \n"
|
||||
" mov a9, %1 \n"
|
||||
"tns_loop%=: l8ui a4, a9, 0 \n"
|
||||
" addi.n a9, a9, 1 \n"
|
||||
" s8i a4, a8, 0 \n"
|
||||
" addi.n a8, a8, 1 \n"
|
||||
" bnez a4, tns_loop%=\n"
|
||||
: : "r" (buf), "r" (string) : "a4", "a8", "a9");
|
||||
}
|
||||
|
||||
void test_naive_strcpy_a5(const char *string)
|
||||
{
|
||||
asm volatile (
|
||||
" mov a8, %0 \n"
|
||||
" mov a9, %1 \n"
|
||||
"tns_loop%=: l8ui a5, a9, 0 \n"
|
||||
" addi.n a9, a9, 1 \n"
|
||||
" s8i a5, a8, 0 \n"
|
||||
" addi.n a8, a8, 1 \n"
|
||||
" bnez a5, tns_loop%=\n"
|
||||
: : "r" (buf), "r" (string) : "a5", "a8", "a9");
|
||||
}
|
||||
|
||||
void test_naive_strcpy_a6(const char *string)
|
||||
{
|
||||
asm volatile (
|
||||
" mov a8, %0 \n"
|
||||
" mov a9, %1 \n"
|
||||
"tns_loop%=: l8ui a6, a9, 0 \n"
|
||||
" addi.n a9, a9, 1 \n"
|
||||
" s8i a6, a8, 0 \n"
|
||||
" addi.n a8, a8, 1 \n"
|
||||
" bnez a6, tns_loop%=\n"
|
||||
: : "r" (buf), "r" (string) : "a6", "a8", "a9");
|
||||
}
|
||||
|
||||
void test_l16si(const char *string)
|
||||
{
|
||||
/* This follows most of the l16si path, but as the
|
||||
values in the string are all 7 bit none of them get sign extended.
|
||||
|
||||
See separate test_sign_extension function which validates
|
||||
sign extension works as expected.
|
||||
*/
|
||||
int16_t *src_int16 = (int16_t *)string;
|
||||
int32_t *dst_int32 = (int32_t *)buf;
|
||||
dst_int32[0] = src_int16[0];
|
||||
dst_int32[1] = src_int16[1];
|
||||
dst_int32[2] = src_int16[2];
|
||||
}
|
||||
|
||||
#define TEST_REPEATS 1000
|
||||
|
||||
void test_noop(const char *string)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint32_t IRAM run_test(const char *string, test_with_fn_t testfn, const char *testfn_label, uint32_t nullvalue, bool evict_cache)
|
||||
{
|
||||
printf(" .. against %30s: ", testfn_label);
|
||||
vPortEnterCritical();
|
||||
uint32_t before = get_ccount();
|
||||
for(int i = 0; i < TEST_REPEATS; i++) {
|
||||
testfn(string);
|
||||
if(evict_cache) {
|
||||
Cache_Read_Disable();
|
||||
Cache_Read_Enable(0,0,1);
|
||||
}
|
||||
}
|
||||
uint32_t after = get_ccount();
|
||||
vPortExitCritical();
|
||||
uint32_t instructions = (after-before)/TEST_REPEATS - nullvalue;
|
||||
printf("%5d instructions\r\n", instructions);
|
||||
return instructions;
|
||||
}
|
||||
|
||||
void test_string(const char *string, char *label, bool evict_cache)
|
||||
{
|
||||
printf("Testing %s (%p) '%s'\r\n", label, string, string);
|
||||
printf("Formats as: '");
|
||||
printf(string, 1, 2, 3);
|
||||
printf("'\r\n");
|
||||
uint32_t nullvalue = run_test(string, test_noop, "null op", 0, evict_cache);
|
||||
run_test(string, test_memcpy_aligned, "memcpy - aligned len", nullvalue, evict_cache);
|
||||
run_test(string, test_memcpy_unaligned, "memcpy - unaligned len", nullvalue, evict_cache);
|
||||
run_test(string, test_memcpy_unaligned2, "memcpy - unaligned start&len", nullvalue, evict_cache);
|
||||
run_test(string, test_strcpy, "strcpy", nullvalue, evict_cache);
|
||||
run_test(string, test_naive_strcpy, "naive strcpy", nullvalue, evict_cache);
|
||||
run_test(string, test_naive_strcpy_a0, "naive strcpy (a0)", nullvalue, evict_cache);
|
||||
run_test(string, test_naive_strcpy_a2, "naive strcpy (a2)", nullvalue, evict_cache);
|
||||
run_test(string, test_naive_strcpy_a3, "naive strcpy (a3)", nullvalue, evict_cache);
|
||||
run_test(string, test_naive_strcpy_a4, "naive strcpy (a4)", nullvalue, evict_cache);
|
||||
run_test(string, test_naive_strcpy_a5, "naive strcpy (a5)", nullvalue, evict_cache);
|
||||
run_test(string, test_naive_strcpy_a6, "naive strcpy (a6)", nullvalue, evict_cache);
|
||||
run_test(string, test_sprintf, "sprintf", nullvalue, evict_cache);
|
||||
run_test(string, test_sprintf_arg, "sprintf format arg", nullvalue, evict_cache);
|
||||
run_test(string, test_l16si, "load as l16si", nullvalue, evict_cache);
|
||||
}
|
||||
|
||||
static void test_isr();
|
||||
static void test_sign_extension();
|
||||
static void test_system_interaction();
|
||||
void sanity_tests(void);
|
||||
|
||||
void user_init(void)
|
||||
{
|
||||
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
|
||||
|
||||
gpio_enable(2, GPIO_OUTPUT); /* used for LED debug */
|
||||
gpio_write(2, 1); /* active low */
|
||||
|
||||
printf("\r\n\r\nSDK version:%s\r\n", sdk_system_get_sdk_version());
|
||||
sanity_tests();
|
||||
test_string(dramtest, "DRAM", 0);
|
||||
test_string(iramtest, "IRAM", 0);
|
||||
test_string(iromtest, "Cached flash", 0);
|
||||
test_string(iromtest, "'Uncached' flash", 1);
|
||||
|
||||
test_isr();
|
||||
test_sign_extension();
|
||||
|
||||
xTaskHandle taskHandle;
|
||||
xTaskCreate(test_system_interaction, (signed char *)"interactionTask", 256, &taskHandle, 2, NULL);
|
||||
}
|
||||
|
||||
static volatile bool frc1_ran;
|
||||
static volatile bool frc1_finished;
|
||||
static volatile char frc1_buf[80];
|
||||
|
||||
static void frc1_interrupt_handler(void)
|
||||
{
|
||||
frc1_ran = true;
|
||||
timer_set_run(FRC1, false);
|
||||
strcpy((char *)frc1_buf, iramtest);
|
||||
frc1_finished = true;
|
||||
}
|
||||
|
||||
static void test_isr()
|
||||
{
|
||||
printf("Testing behaviour inside ISRs...\r\n");
|
||||
timer_set_interrupts(FRC1, false);
|
||||
timer_set_run(FRC1, false);
|
||||
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler);
|
||||
timer_set_frequency(FRC1, 1000);
|
||||
timer_set_interrupts(FRC1, true);
|
||||
timer_set_run(FRC1, true);
|
||||
sdk_os_delay_us(2000);
|
||||
|
||||
if(!frc1_ran)
|
||||
printf("ERROR: FRC1 timer exception never fired.\r\n");
|
||||
else if(!frc1_finished)
|
||||
printf("ERROR: FRC1 timer exception never finished.\r\n");
|
||||
else if(strcmp((char *)frc1_buf, iramtest))
|
||||
printf("ERROR: FRC1 strcpy from IRAM failed.\r\n");
|
||||
else
|
||||
printf("PASSED\r\n");
|
||||
}
|
||||
|
||||
const volatile __attribute__((section(".iram1.notliterals"))) int16_t unsigned_shorts[] = { -3, -4, -5, -32767, 44 };
|
||||
|
||||
static void test_sign_extension()
|
||||
{
|
||||
/* this step seems to be necessary so the compiler will actually generate l16si */
|
||||
int16_t *shorts_p = (int16_t *)unsigned_shorts;
|
||||
if(shorts_p[0] == -3 && shorts_p[1] == -4 && shorts_p[2] == -5 && shorts_p[3] == -32767 && shorts_p[4] == 44)
|
||||
{
|
||||
printf("l16si sign extension PASSED.\r\n");
|
||||
} else {
|
||||
printf("ERROR: l16si sign extension failed. Got values %d %d %d %d %d\r\n", shorts_p[0], shorts_p[1], shorts_p[2], shorts_p[3], shorts_p[4]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* test that running unaligned loads in a running FreeRTOS system doesn't break things
|
||||
|
||||
The following tests run inside a FreeRTOS task, after everything else.
|
||||
*/
|
||||
static void test_system_interaction()
|
||||
{
|
||||
uint32_t start = xTaskGetTickCount();
|
||||
printf("Starting system/timer interaction test (takes approx 30 seconds)...\n");
|
||||
for(int i = 0; i < 200*1000; i++) {
|
||||
test_naive_strcpy_a0(iromtest);
|
||||
test_naive_strcpy_a2(iromtest);
|
||||
test_naive_strcpy_a3(iromtest);
|
||||
test_naive_strcpy_a4(iromtest);
|
||||
test_naive_strcpy_a5(iromtest);
|
||||
test_naive_strcpy_a6(iromtest);
|
||||
/*
|
||||
const volatile char *string = iromtest;
|
||||
volatile char *to = dest;
|
||||
while((*to++ = *string++))
|
||||
;
|
||||
*/
|
||||
}
|
||||
uint32_t ticks = xTaskGetTickCount() - start;
|
||||
printf("Timer interaction test PASSED after %dms.\n", ticks*portTICK_RATE_MS);
|
||||
while(1) {}
|
||||
}
|
||||
|
||||
/* The following "sanity tests" are designed to try to execute every code path
|
||||
* of the LoadStoreError handler, with a variety of offsets and data values
|
||||
* designed to catch any mask/shift errors, sign-extension bugs, etc */
|
||||
|
||||
/* (Contrary to expectations, 'mov a15, a15' in Xtensa is not technically a
|
||||
* no-op, but is officially "undefined and reserved for future use", so we need
|
||||
* a special case in the case where reg == "a15" so we don't end up generating
|
||||
* those opcodes. GCC is smart enough to optimize away the whole conditional
|
||||
* and just insert the correct asm block, since `reg` is a static argument.) */
|
||||
#define LOAD_VIA_REG(op, reg, addr, var) \
|
||||
if (strcmp(reg, "a15")) { \
|
||||
asm volatile ( \
|
||||
"mov a15, " reg "\n\t" \
|
||||
op " " reg ", %1, 0\n\t" \
|
||||
"mov %0, " reg "\n\t" \
|
||||
"mov " reg ", a15\n\t" \
|
||||
: "=r" (var) : "r" (addr) : "a15" ); \
|
||||
} else { \
|
||||
asm volatile ( \
|
||||
op " " reg ", %1, 0\n\t" \
|
||||
"mov %0, " reg "\n\t" \
|
||||
: "=r" (var) : "r" (addr) : "a15" ); \
|
||||
}
|
||||
|
||||
#define TEST_LOAD(op, reg, addr, value) \
|
||||
{ \
|
||||
int32_t result; \
|
||||
LOAD_VIA_REG(op, reg, addr, result); \
|
||||
if (result != value) sanity_test_failed(op, reg, addr, value, result); \
|
||||
}
|
||||
|
||||
void sanity_test_failed(const char *testname, const char *reg, const void *addr, int32_t value, int32_t result) {
|
||||
uint32_t actual_data = *(uint32_t *)((uint32_t)addr & 0xfffffffc);
|
||||
|
||||
printf("*** SANITY TEST FAILED: '%s %s' from %p (underlying 32-bit value: 0x%x): Expected 0x%08x (%d), got 0x%08x (%d)\n", testname, reg, addr, actual_data, value, value, result, result);
|
||||
}
|
||||
|
||||
const __attribute__((section(".iram1.notrodata"))) char sanity_test_data[] = {
|
||||
0x01, 0x55, 0x7e, 0x2a, 0x81, 0xd5, 0xfe, 0xaa
|
||||
};
|
||||
|
||||
void sanity_test_l8ui(const void *addr, int32_t value) {
|
||||
TEST_LOAD("l8ui", "a0", addr, value);
|
||||
TEST_LOAD("l8ui", "a1", addr, value);
|
||||
TEST_LOAD("l8ui", "a2", addr, value);
|
||||
TEST_LOAD("l8ui", "a3", addr, value);
|
||||
TEST_LOAD("l8ui", "a4", addr, value);
|
||||
TEST_LOAD("l8ui", "a5", addr, value);
|
||||
TEST_LOAD("l8ui", "a6", addr, value);
|
||||
TEST_LOAD("l8ui", "a7", addr, value);
|
||||
TEST_LOAD("l8ui", "a8", addr, value);
|
||||
TEST_LOAD("l8ui", "a9", addr, value);
|
||||
TEST_LOAD("l8ui", "a10", addr, value);
|
||||
TEST_LOAD("l8ui", "a11", addr, value);
|
||||
TEST_LOAD("l8ui", "a12", addr, value);
|
||||
TEST_LOAD("l8ui", "a13", addr, value);
|
||||
TEST_LOAD("l8ui", "a14", addr, value);
|
||||
TEST_LOAD("l8ui", "a15", addr, value);
|
||||
}
|
||||
|
||||
void sanity_test_l16ui(const void *addr, int32_t value) {
|
||||
TEST_LOAD("l16ui", "a0", addr, value);
|
||||
TEST_LOAD("l16ui", "a1", addr, value);
|
||||
TEST_LOAD("l16ui", "a2", addr, value);
|
||||
TEST_LOAD("l16ui", "a3", addr, value);
|
||||
TEST_LOAD("l16ui", "a4", addr, value);
|
||||
TEST_LOAD("l16ui", "a5", addr, value);
|
||||
TEST_LOAD("l16ui", "a6", addr, value);
|
||||
TEST_LOAD("l16ui", "a7", addr, value);
|
||||
TEST_LOAD("l16ui", "a8", addr, value);
|
||||
TEST_LOAD("l16ui", "a9", addr, value);
|
||||
TEST_LOAD("l16ui", "a10", addr, value);
|
||||
TEST_LOAD("l16ui", "a11", addr, value);
|
||||
TEST_LOAD("l16ui", "a12", addr, value);
|
||||
TEST_LOAD("l16ui", "a13", addr, value);
|
||||
TEST_LOAD("l16ui", "a14", addr, value);
|
||||
TEST_LOAD("l16ui", "a15", addr, value);
|
||||
}
|
||||
|
||||
void sanity_test_l16si(const void *addr, int32_t value) {
|
||||
TEST_LOAD("l16si", "a0", addr, value);
|
||||
TEST_LOAD("l16si", "a1", addr, value);
|
||||
TEST_LOAD("l16si", "a2", addr, value);
|
||||
TEST_LOAD("l16si", "a3", addr, value);
|
||||
TEST_LOAD("l16si", "a4", addr, value);
|
||||
TEST_LOAD("l16si", "a5", addr, value);
|
||||
TEST_LOAD("l16si", "a6", addr, value);
|
||||
TEST_LOAD("l16si", "a7", addr, value);
|
||||
TEST_LOAD("l16si", "a8", addr, value);
|
||||
TEST_LOAD("l16si", "a9", addr, value);
|
||||
TEST_LOAD("l16si", "a10", addr, value);
|
||||
TEST_LOAD("l16si", "a11", addr, value);
|
||||
TEST_LOAD("l16si", "a12", addr, value);
|
||||
TEST_LOAD("l16si", "a13", addr, value);
|
||||
TEST_LOAD("l16si", "a14", addr, value);
|
||||
TEST_LOAD("l16si", "a15", addr, value);
|
||||
}
|
||||
|
||||
void sanity_tests(void) {
|
||||
printf("== Performing sanity tests (sanity_test_data @ %p)...\n", sanity_test_data);
|
||||
|
||||
sanity_test_l8ui(sanity_test_data + 0, 0x01);
|
||||
sanity_test_l8ui(sanity_test_data + 1, 0x55);
|
||||
sanity_test_l8ui(sanity_test_data + 2, 0x7e);
|
||||
sanity_test_l8ui(sanity_test_data + 3, 0x2a);
|
||||
sanity_test_l8ui(sanity_test_data + 4, 0x81);
|
||||
sanity_test_l8ui(sanity_test_data + 5, 0xd5);
|
||||
sanity_test_l8ui(sanity_test_data + 6, 0xfe);
|
||||
sanity_test_l8ui(sanity_test_data + 7, 0xaa);
|
||||
|
||||
sanity_test_l16ui(sanity_test_data + 0, 0x5501);
|
||||
sanity_test_l16ui(sanity_test_data + 2, 0x2a7e);
|
||||
sanity_test_l16ui(sanity_test_data + 4, 0xd581);
|
||||
sanity_test_l16ui(sanity_test_data + 6, 0xaafe);
|
||||
|
||||
sanity_test_l16si(sanity_test_data + 0, 0x5501);
|
||||
sanity_test_l16si(sanity_test_data + 2, 0x2a7e);
|
||||
sanity_test_l16si(sanity_test_data + 4, -10879);
|
||||
sanity_test_l16si(sanity_test_data + 6, -21762);
|
||||
|
||||
printf("== Sanity tests completed.\n");
|
||||
}
|
||||
4
examples/http_get_mbedtls/Makefile
Normal file
4
examples/http_get_mbedtls/Makefile
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
PROGRAM=http_get_mbedtls
|
||||
COMPONENTS = FreeRTOS lwip core extras/mbedtls
|
||||
|
||||
include ../../common.mk
|
||||
39
examples/http_get_mbedtls/cert.c
Normal file
39
examples/http_get_mbedtls/cert.c
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* This is the root certificate for the CA trust chain of
|
||||
www.howsmyssl.com in PEM format, as dumped via:
|
||||
|
||||
openssl s_client -showcerts -connect www.howsmyssl.com:443 </dev/null
|
||||
|
||||
The root cert is the last cert in the chain output by the server.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
const char *server_root_cert = "-----BEGIN CERTIFICATE-----\r\n"
|
||||
"MIIEWTCCA0GgAwIBAgIDAjpjMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT\r\n"
|
||||
"MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i\r\n"
|
||||
"YWwgQ0EwHhcNMTIwODI3MjA0MDQwWhcNMjIwNTIwMjA0MDQwWjBEMQswCQYDVQQG\r\n"
|
||||
"EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg\r\n"
|
||||
"U1NMIENBIC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5J/lP\r\n"
|
||||
"2Pa3FT+Pzc7WjRxr/X/aVCFOA9jK0HJSFbjJgltYeYT/JHJv8ml/vJbZmnrDPqnP\r\n"
|
||||
"UCITDoYZ2+hJ74vm1kfy/XNFCK6PrF62+J589xD/kkNm7xzU7qFGiBGJSXl6Jc5L\r\n"
|
||||
"avDXHHYaKTzJ5P0ehdzgMWUFRxasCgdLLnBeawanazpsrwUSxLIRJdY+lynwg2xX\r\n"
|
||||
"HNil78zs/dYS8T/bQLSuDxjTxa9Akl0HXk7+Yhc3iemLdCai7bgK52wVWzWQct3Y\r\n"
|
||||
"TSHUQCNcj+6AMRaraFX0DjtU6QRN8MxOgV7pb1JpTr6mFm1C9VH/4AtWPJhPc48O\r\n"
|
||||
"bxoj8cnI2d+87FLXAgMBAAGjggFUMIIBUDAfBgNVHSMEGDAWgBTAephojYn7qwVk\r\n"
|
||||
"DBF9qn1luMrMTjAdBgNVHQ4EFgQUEUrQcznVW2kIXLo9v2SaqIscVbwwEgYDVR0T\r\n"
|
||||
"AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2gK4Yp\r\n"
|
||||
"aHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwNAYIKwYB\r\n"
|
||||
"BQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5nZW90cnVzdC5jb20w\r\n"
|
||||
"TAYDVR0gBEUwQzBBBgpghkgBhvhFAQc2MDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93\r\n"
|
||||
"d3cuZ2VvdHJ1c3QuY29tL3Jlc291cmNlcy9jcHMwKgYDVR0RBCMwIaQfMB0xGzAZ\r\n"
|
||||
"BgNVBAMTElZlcmlTaWduTVBLSS0yLTI1NDANBgkqhkiG9w0BAQUFAAOCAQEAPOU9\r\n"
|
||||
"WhuiNyrjRs82lhg8e/GExVeGd0CdNfAS8HgY+yKk3phLeIHmTYbjkQ9C47ncoNb/\r\n"
|
||||
"qfixeZeZ0cNsQqWSlOBdDDMYJckrlVPg5akMfUf+f1ExRF73Kh41opQy98nuwLbG\r\n"
|
||||
"mqzemSFqI6A4ZO6jxIhzMjtQzr+t03UepvTp+UJrYLLdRf1dVwjOLVDmEjIWE4ry\r\n"
|
||||
"lKKbR6iGf9mY5ffldnRk2JG8hBYo2CVEMH6C2Kyx5MDkFWzbtiQnAioBEoW6MYhY\r\n"
|
||||
"R3TjuNJkpsMyWS4pS0XxW4lJLoKaxhgVRNAuZAEVaDj59vlmAwxVG52/AECu8Egn\r\n"
|
||||
"TOCAXi25KhV6vGb4NQ==\r\n"
|
||||
"-----END CERTIFICATE-----\r\n";
|
||||
|
||||
|
||||
347
examples/http_get_mbedtls/http_get_mbedtls.c
Normal file
347
examples/http_get_mbedtls/http_get_mbedtls.c
Normal file
|
|
@ -0,0 +1,347 @@
|
|||
/* http_get_mbedtls - HTTPS version of the http_get example, using mbed TLS.
|
||||
*
|
||||
* Retrieves a JSON response from the howsmyssl.com API via HTTPS over TLS v1.2.
|
||||
*
|
||||
* Validates the server's certificate using the root CA loaded (in PEM format) in cert.c.
|
||||
*
|
||||
* Adapted from the ssl_client1 example in mbedtls.
|
||||
*
|
||||
* Original Copyright (C) 2006-2015, ARM Limited, All Rights Reserved, Apache 2.0 License.
|
||||
* Additions Copyright (C) 2015 Angus Gratton, Apache 2.0 License.
|
||||
*/
|
||||
#include "espressif/esp_common.h"
|
||||
#include "espressif/sdk_private.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/api.h"
|
||||
|
||||
#include "ssid_config.h"
|
||||
|
||||
/* mbedtls/config.h MUST appear before all other mbedtls headers, or
|
||||
you'll get the default config.
|
||||
|
||||
(Although mostly that isn't a big problem, you just might get
|
||||
errors at link time if functions don't exist.) */
|
||||
#include "mbedtls/config.h"
|
||||
|
||||
#include "mbedtls/net.h"
|
||||
#include "mbedtls/debug.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/certs.h"
|
||||
|
||||
#define WEB_SERVER "howsmyssl.com"
|
||||
#define WEB_PORT "443"
|
||||
#define WEB_URL "https://www.howsmyssl.com/a/check"
|
||||
|
||||
#define GET_REQUEST "GET "WEB_URL" HTTP/1.1\n\n"
|
||||
|
||||
/* Root cert for howsmyssl.com, stored in cert.c */
|
||||
extern const char *server_root_cert;
|
||||
|
||||
/* MBEDTLS_DEBUG_C disabled by default to save substantial bloating of
|
||||
* firmware, define it in
|
||||
* examples/http_get_mbedtls/include/mbedtls/config.h if you'd like
|
||||
* debugging output.
|
||||
*/
|
||||
#ifdef MBEDTLS_DEBUG_C
|
||||
|
||||
|
||||
/* Increase this value to see more TLS debug details,
|
||||
0 prints nothing, 1 will print any errors, 4 will print _everything_
|
||||
*/
|
||||
#define DEBUG_LEVEL 4
|
||||
|
||||
static void my_debug(void *ctx, int level,
|
||||
const char *file, int line,
|
||||
const char *str)
|
||||
{
|
||||
((void) level);
|
||||
|
||||
/* Shorten 'file' from the whole file path to just the filename
|
||||
|
||||
This is a bit wasteful because the macros are compiled in with
|
||||
the full _FILE_ path in each case, so the firmware is bloated out
|
||||
by a few kb. But there's not a lot we can do about it...
|
||||
*/
|
||||
char *file_sep = rindex(file, '/');
|
||||
if(file_sep)
|
||||
file = file_sep+1;
|
||||
|
||||
printf("%s:%04d: %s", file, line, str);
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif
|
||||
|
||||
void http_get_task(void *pvParameters)
|
||||
{
|
||||
int successes = 0, failures = 0, ret;
|
||||
printf("HTTP get task starting...\n");
|
||||
|
||||
uint32_t flags;
|
||||
unsigned char buf[1024];
|
||||
const char *pers = "ssl_client1";
|
||||
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
mbedtls_ssl_context ssl;
|
||||
mbedtls_x509_crt cacert;
|
||||
mbedtls_ssl_config conf;
|
||||
mbedtls_net_context server_fd;
|
||||
|
||||
/*
|
||||
* 0. Initialize the RNG and the session data
|
||||
*/
|
||||
mbedtls_ssl_init(&ssl);
|
||||
mbedtls_x509_crt_init(&cacert);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
printf("\n . Seeding the random number generator...");
|
||||
fflush(stdout);
|
||||
|
||||
mbedtls_ssl_config_init(&conf);
|
||||
|
||||
mbedtls_entropy_init(&entropy);
|
||||
if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
|
||||
(const unsigned char *) pers,
|
||||
strlen(pers))) != 0)
|
||||
{
|
||||
printf(" failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret);
|
||||
while(1) {} /* todo: replace with abort() */
|
||||
}
|
||||
|
||||
printf(" ok\n");
|
||||
|
||||
/*
|
||||
* 0. Initialize certificates
|
||||
*/
|
||||
printf(" . Loading the CA root certificate ...");
|
||||
fflush(stdout);
|
||||
|
||||
ret = mbedtls_x509_crt_parse(&cacert, (uint8_t*)server_root_cert, strlen(server_root_cert)+1);
|
||||
if(ret < 0)
|
||||
{
|
||||
printf(" failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret);
|
||||
while(1) {} /* todo: replace with abort() */
|
||||
}
|
||||
|
||||
printf(" ok (%d skipped)\n", ret);
|
||||
|
||||
/* Hostname set here should match CN in server certificate */
|
||||
if((ret = mbedtls_ssl_set_hostname(&ssl, WEB_SERVER)) != 0)
|
||||
{
|
||||
printf(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
|
||||
while(1) {} /* todo: replace with abort() */
|
||||
}
|
||||
|
||||
/*
|
||||
* 2. Setup stuff
|
||||
*/
|
||||
printf(" . Setting up the SSL/TLS structure...");
|
||||
fflush(stdout);
|
||||
|
||||
if((ret = mbedtls_ssl_config_defaults(&conf,
|
||||
MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
|
||||
{
|
||||
printf(" failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
printf(" ok\n");
|
||||
|
||||
/* OPTIONAL is not optimal for security, in this example it will print
|
||||
a warning if CA verification fails but it will continue to connect.
|
||||
*/
|
||||
mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
|
||||
mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
|
||||
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
|
||||
#ifdef MBEDTLS_DEBUG_C
|
||||
mbedtls_debug_set_threshold(DEBUG_LEVEL);
|
||||
mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);
|
||||
#endif
|
||||
|
||||
if((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0)
|
||||
{
|
||||
printf(" failed\n ! mbedtls_ssl_setup returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Wait until we can resolve the DNS for the server, as an indication
|
||||
our network is probably working...
|
||||
*/
|
||||
printf("Waiting for server DNS to resolve... ");
|
||||
fflush(stdout);
|
||||
err_t dns_err;
|
||||
ip_addr_t host_ip;
|
||||
do {
|
||||
vTaskDelay(500 / portTICK_RATE_MS);
|
||||
dns_err = netconn_gethostbyname(WEB_SERVER, &host_ip);
|
||||
} while(dns_err != ERR_OK);
|
||||
printf("done.\n");
|
||||
|
||||
while(1) {
|
||||
mbedtls_net_init(&server_fd);
|
||||
printf("top of loop, free heap = %u\n", xPortGetFreeHeapSize());
|
||||
/*
|
||||
* 1. Start the connection
|
||||
*/
|
||||
printf(" . Connecting to %s:%s...", WEB_SERVER, WEB_PORT);
|
||||
fflush(stdout);
|
||||
|
||||
if((ret = mbedtls_net_connect(&server_fd, WEB_SERVER,
|
||||
WEB_PORT, MBEDTLS_NET_PROTO_TCP)) != 0)
|
||||
{
|
||||
printf(" failed\n ! mbedtls_net_connect returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
printf(" ok\n");
|
||||
|
||||
mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
|
||||
|
||||
/*
|
||||
* 4. Handshake
|
||||
*/
|
||||
printf(" . Performing the SSL/TLS handshake...");
|
||||
fflush(stdout);
|
||||
|
||||
while((ret = mbedtls_ssl_handshake(&ssl)) != 0)
|
||||
{
|
||||
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
|
||||
{
|
||||
printf(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
printf(" ok\n");
|
||||
|
||||
/*
|
||||
* 5. Verify the server certificate
|
||||
*/
|
||||
printf(" . Verifying peer X.509 certificate...");
|
||||
|
||||
/* In real life, we probably want to bail out when ret != 0 */
|
||||
if((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0)
|
||||
{
|
||||
char vrfy_buf[512];
|
||||
|
||||
printf(" failed\n");
|
||||
|
||||
mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", flags);
|
||||
|
||||
printf("%s\n", vrfy_buf);
|
||||
}
|
||||
else
|
||||
printf(" ok\n");
|
||||
|
||||
/*
|
||||
* 3. Write the GET request
|
||||
*/
|
||||
printf(" > Write to server:");
|
||||
fflush(stdout);
|
||||
|
||||
int len = sprintf((char *) buf, GET_REQUEST);
|
||||
|
||||
while((ret = mbedtls_ssl_write(&ssl, buf, len)) <= 0)
|
||||
{
|
||||
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
|
||||
{
|
||||
printf(" failed\n ! mbedtls_ssl_write returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
len = ret;
|
||||
printf(" %d bytes written\n\n%s", len, (char *) buf);
|
||||
|
||||
/*
|
||||
* 7. Read the HTTP response
|
||||
*/
|
||||
printf(" < Read from server:");
|
||||
fflush(stdout);
|
||||
|
||||
do
|
||||
{
|
||||
len = sizeof(buf) - 1;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
ret = mbedtls_ssl_read(&ssl, buf, len);
|
||||
|
||||
if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)
|
||||
continue;
|
||||
|
||||
if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(ret < 0)
|
||||
{
|
||||
printf("failed\n ! mbedtls_ssl_read returned %d\n\n", ret);
|
||||
break;
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
printf("\n\nEOF\n\n");
|
||||
break;
|
||||
}
|
||||
|
||||
len = ret;
|
||||
printf(" %d bytes read\n\n%s", len, (char *) buf);
|
||||
} while(1);
|
||||
|
||||
mbedtls_ssl_close_notify(&ssl);
|
||||
|
||||
exit:
|
||||
mbedtls_ssl_session_reset(&ssl);
|
||||
mbedtls_net_free(&server_fd);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
char error_buf[100];
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
printf("\n\nLast error was: %d - %s\n\n", ret, error_buf);
|
||||
failures++;
|
||||
} else {
|
||||
successes++;
|
||||
}
|
||||
|
||||
printf("\n\nsuccesses = %d failures = %d\n", successes, failures);
|
||||
for(int countdown = successes ? 10 : 5; countdown >= 0; countdown--) {
|
||||
printf("%d... ", countdown);
|
||||
fflush(stdout);
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
}
|
||||
printf("\nStarting again!\n");
|
||||
}
|
||||
}
|
||||
|
||||
void user_init(void)
|
||||
{
|
||||
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
|
||||
printf("SDK version:%s\n", sdk_system_get_sdk_version());
|
||||
|
||||
struct sdk_station_config config = {
|
||||
.ssid = WIFI_SSID,
|
||||
.password = WIFI_PASS,
|
||||
};
|
||||
|
||||
/* required to call wifi_set_opmode before station_set_config */
|
||||
sdk_wifi_set_opmode(STATION_MODE);
|
||||
sdk_wifi_station_set_config(&config);
|
||||
|
||||
xTaskCreate(&http_get_task, (signed char *)"get_task", 2048, NULL, 2, NULL);
|
||||
}
|
||||
27
examples/http_get_mbedtls/include/mbedtls/config.h
Normal file
27
examples/http_get_mbedtls/include/mbedtls/config.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* Special mbedTLS config file for http_get_mbedtls example,
|
||||
overrides supported cipher suite list.
|
||||
|
||||
Overriding the set of cipher suites saves small amounts of ROM and
|
||||
RAM, and is a good practice in general if you know what server(s)
|
||||
you want to connect to.
|
||||
|
||||
However it's extra important here because the howsmyssl API sends
|
||||
back the list of ciphers we send it as a JSON list in the, and we
|
||||
only have a 4096kB receive buffer. If the server supported maximum
|
||||
fragment length option then we wouldn't have this problem either,
|
||||
but we do so this is a good workaround.
|
||||
|
||||
The ciphers chosen below are common ECDHE ciphers, the same ones
|
||||
Firefox uses when connecting to a TLSv1.2 server.
|
||||
*/
|
||||
#ifndef MBEDTLS_CONFIG_H
|
||||
|
||||
/* include_next picks up default config from extras/mbedtls/include/mbedtls/config.h */
|
||||
#include_next<mbedtls/config.h>
|
||||
|
||||
#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|
||||
|
||||
/* uncomment next line to include debug output from example */
|
||||
//#define MBEDTLS_DEBUG_C
|
||||
|
||||
#endif
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
PROGRAM=http_get_ssl
|
||||
include ../../common.mk
|
||||
|
|
@ -1,223 +0,0 @@
|
|||
/* http_get_ssl - HTTPS version of the http_get example.
|
||||
*
|
||||
* Retrieves a web page over HTTPS (TLS) using GET.
|
||||
*
|
||||
* Does not validate server certificate.
|
||||
*
|
||||
* This sample code is in the public domain.,
|
||||
*/
|
||||
#include "espressif/esp_common.h"
|
||||
#include "espressif/sdk_private.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "lwip/dns.h"
|
||||
|
||||
#include "ssl.h"
|
||||
|
||||
#include "ssid_config.h"
|
||||
|
||||
#define WEB_SERVER "192.168.0.18"
|
||||
#define WEB_PORT "8000"
|
||||
#define WEB_URL "/test"
|
||||
|
||||
static void display_cipher(SSL *ssl);
|
||||
static void display_session_id(SSL *ssl);
|
||||
|
||||
void http_get_task(void *pvParameters)
|
||||
{
|
||||
int successes = 0, failures = 0;
|
||||
SSL_CTX *ssl_ctx;
|
||||
uint32_t options = SSL_SERVER_VERIFY_LATER|SSL_DISPLAY_CERTS;
|
||||
printf("HTTP get task starting...\r\n");
|
||||
|
||||
printf("free heap = %u\r\n", xPortGetFreeHeapSize());
|
||||
if ((ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_CLNT_SESS)) == NULL)
|
||||
{
|
||||
printf("Error: SSL Client context is invalid\n");
|
||||
while(1) {}
|
||||
}
|
||||
printf("Got SSL context.");
|
||||
|
||||
while(1) {
|
||||
const struct addrinfo hints = {
|
||||
.ai_family = AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
};
|
||||
struct addrinfo *res;
|
||||
|
||||
printf("top of loop, free heap = %u\r\n", xPortGetFreeHeapSize());
|
||||
|
||||
printf("Running DNS lookup for %s...\r\n", WEB_SERVER);
|
||||
int err = getaddrinfo(WEB_SERVER, WEB_PORT, &hints, &res);
|
||||
|
||||
if(err != 0 || res == NULL) {
|
||||
printf("DNS lookup failed err=%d res=%p\r\n", err, res);
|
||||
if(res)
|
||||
freeaddrinfo(res);
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
failures++;
|
||||
continue;
|
||||
}
|
||||
/* Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */
|
||||
struct in_addr *addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
|
||||
printf("DNS lookup succeeded. IP=%s\r\n", inet_ntoa(*addr));
|
||||
|
||||
int s = socket(res->ai_family, res->ai_socktype, 0);
|
||||
if(s < 0) {
|
||||
printf("... Failed to allocate socket.\r\n");
|
||||
freeaddrinfo(res);
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
failures++;
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("... allocated socket\r\n");
|
||||
|
||||
if(connect(s, res->ai_addr, res->ai_addrlen) != 0) {
|
||||
close(s);
|
||||
freeaddrinfo(res);
|
||||
printf("... socket connect failed.\r\n");
|
||||
vTaskDelay(4000 / portTICK_RATE_MS);
|
||||
failures++;
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("... connected. starting TLS session...\r\n");
|
||||
freeaddrinfo(res);
|
||||
|
||||
SSL *ssl = ssl_client_new(ssl_ctx, s, NULL, 0);
|
||||
printf("initial status %p %d\r\n", ssl, ssl_handshake_status(ssl));
|
||||
if((err = ssl_handshake_status(ssl)) != SSL_OK) {
|
||||
ssl_free(ssl);
|
||||
close(s);
|
||||
printf("SSL handshake failed. :( %d\r\n", err);
|
||||
vTaskDelay(4000 / portTICK_RATE_MS);
|
||||
failures++;
|
||||
continue;
|
||||
}
|
||||
|
||||
const char *common_name = ssl_get_cert_dn(ssl,
|
||||
SSL_X509_CERT_COMMON_NAME);
|
||||
if (common_name)
|
||||
{
|
||||
printf("Common Name:\t\t\t%s\n", common_name);
|
||||
}
|
||||
|
||||
display_session_id(ssl);
|
||||
display_cipher(ssl);
|
||||
|
||||
const char *req =
|
||||
"GET "WEB_URL"\r\n"
|
||||
"User-Agent: esp-open-rtos/0.1 esp8266\r\n"
|
||||
"\r\n";
|
||||
if (ssl_write(ssl, (uint8_t *)req, strlen(req)) < 0) {
|
||||
printf("... socket send failed\r\n");
|
||||
ssl_free(ssl);
|
||||
close(s);
|
||||
vTaskDelay(4000 / portTICK_RATE_MS);
|
||||
failures++;
|
||||
continue;
|
||||
}
|
||||
printf("... socket send success\r\n");
|
||||
|
||||
uint8_t *recv_buf;
|
||||
int r;
|
||||
do {
|
||||
r = ssl_read(ssl, &recv_buf);
|
||||
for(int i = 0; i < r; i++)
|
||||
printf("%c", recv_buf[i]);
|
||||
} while(r > 0);
|
||||
|
||||
printf("... done reading from socket. Last read return=%d errno=%d\r\n", r, errno);
|
||||
if(r != 0)
|
||||
failures++;
|
||||
else
|
||||
successes++;
|
||||
ssl_free(ssl);
|
||||
close(s);
|
||||
printf("successes = %d failures = %d\r\n", successes, failures);
|
||||
for(int countdown = 10; countdown >= 0; countdown--) {
|
||||
printf("%d... ", countdown);
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
}
|
||||
printf("\r\nStarting again!\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void user_init(void)
|
||||
{
|
||||
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
|
||||
printf("SDK version:%s\n", sdk_system_get_sdk_version());
|
||||
|
||||
struct sdk_station_config config = {
|
||||
.ssid = WIFI_SSID,
|
||||
.password = WIFI_PASS,
|
||||
};
|
||||
|
||||
/* required to call wifi_set_opmode before station_set_config */
|
||||
sdk_wifi_set_opmode(STATION_MODE);
|
||||
sdk_wifi_station_set_config(&config);
|
||||
|
||||
xTaskCreate(&http_get_task, (signed char *)"get_task", 2048, NULL, 2, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display what session id we have.
|
||||
*/
|
||||
static void display_session_id(SSL *ssl)
|
||||
{
|
||||
int i;
|
||||
const uint8_t *session_id = ssl_get_session_id(ssl);
|
||||
int sess_id_size = ssl_get_session_id_size(ssl);
|
||||
|
||||
if (sess_id_size > 0)
|
||||
{
|
||||
printf("-----BEGIN SSL SESSION PARAMETERS-----\n");
|
||||
for (i = 0; i < sess_id_size; i++)
|
||||
{
|
||||
printf("%02x", session_id[i]);
|
||||
}
|
||||
|
||||
printf("\n-----END SSL SESSION PARAMETERS-----\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display what cipher we are using
|
||||
*/
|
||||
static void display_cipher(SSL *ssl)
|
||||
{
|
||||
printf("CIPHER is ");
|
||||
switch (ssl_get_cipher_id(ssl))
|
||||
{
|
||||
case SSL_AES128_SHA:
|
||||
printf("AES128-SHA");
|
||||
break;
|
||||
|
||||
case SSL_AES256_SHA:
|
||||
printf("AES256-SHA");
|
||||
break;
|
||||
|
||||
case SSL_RC4_128_SHA:
|
||||
printf("RC4-SHA");
|
||||
break;
|
||||
|
||||
case SSL_RC4_128_MD5:
|
||||
printf("RC4-MD5");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unknown - %d", ssl_get_cipher_id(ssl));
|
||||
break;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ void user_init(void)
|
|||
|
||||
printf("Image addresses in flash:\r\n");
|
||||
for(int i = 0; i <conf.count; i++) {
|
||||
printf("%c%d: offset 0x%08lx\r\n", i == conf.current_rom ? '*':' ', i, conf.roms[i]);
|
||||
printf("%c%d: offset 0x%08x\r\n", i == conf.current_rom ? '*':' ', i, conf.roms[i]);
|
||||
}
|
||||
|
||||
struct sdk_station_config config = {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ void task2(void *pvParameters)
|
|||
while(1) {
|
||||
uint32_t count;
|
||||
if(xQueueReceive(*queue, &count, 1000)) {
|
||||
printf("Got %lu\n", count);
|
||||
printf("Got %u\n", count);
|
||||
} else {
|
||||
printf("No msg :(\n");
|
||||
}
|
||||
|
|
|
|||
3
examples/simple_cplusplus/Makefile
Normal file
3
examples/simple_cplusplus/Makefile
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Simple makefile for simple example
|
||||
PROGRAM=simple
|
||||
include ../../common.mk
|
||||
64
examples/simple_cplusplus/simple.cpp
Normal file
64
examples/simple_cplusplus/simple.cpp
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/* A very basic C++ example, really just proof of concept for C++
|
||||
|
||||
This sample code is in the public domain.
|
||||
*/
|
||||
#include "espressif/esp_common.h"
|
||||
#include "espressif/sdk_private.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
|
||||
class Counter
|
||||
{
|
||||
private:
|
||||
uint32_t _count;
|
||||
public:
|
||||
Counter(uint32_t initial_count)
|
||||
{
|
||||
this->_count = initial_count;
|
||||
printf("Counter initialised with count %d\r\n", initial_count);
|
||||
}
|
||||
|
||||
void Increment()
|
||||
{
|
||||
_count++;
|
||||
}
|
||||
|
||||
uint32_t getCount()
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
};
|
||||
|
||||
static Counter static_counter(99);
|
||||
|
||||
void task1(void *pvParameters)
|
||||
{
|
||||
Counter local_counter = Counter(12);
|
||||
Counter *new_counter = new Counter(24);
|
||||
while(1) {
|
||||
Counter *counter = NULL;
|
||||
switch(rand() % 3) {
|
||||
case 0:
|
||||
counter = &local_counter;
|
||||
break;
|
||||
case 1:
|
||||
counter = &static_counter;
|
||||
break;
|
||||
default:
|
||||
counter = new_counter;
|
||||
break;
|
||||
}
|
||||
counter->Increment();
|
||||
printf("local counter %d static counter %d newly allocated counter %d\r\n", local_counter.getCount(),
|
||||
static_counter.getCount(), new_counter->getCount());
|
||||
vTaskDelay(100);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void user_init(void)
|
||||
{
|
||||
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
|
||||
printf("SDK version:%s\n", sdk_system_get_sdk_version());
|
||||
xTaskCreate(task1, (signed char *)"tsk1", 256, NULL, 2, NULL);
|
||||
}
|
||||
|
|
@ -1,2 +1,3 @@
|
|||
PROGRAM=hmac_test
|
||||
EXTRA_COMPONENTS=extras/mbedtls
|
||||
include ../../../common.mk
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include "espressif/esp_common.h"
|
||||
#include "espressif/sdk_private.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "ssl.h"
|
||||
#include "mbedtls/md.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
|
@ -31,9 +31,7 @@ static const uint8_t aa_80_times[] = {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0x
|
|||
0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
|
||||
0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa};
|
||||
|
||||
/* NOTE: Vectors 6 & 7 currently cause a fault as the axTLS
|
||||
routines don't support keys longer than the block size. */
|
||||
const uint8_t NUM_MD5_VECTORS = 5;
|
||||
const uint8_t NUM_MD5_VECTORS = 7;
|
||||
|
||||
static const struct test_vector md5_vectors[] = {
|
||||
{ /* vector 1*/
|
||||
|
|
@ -88,15 +86,30 @@ static const struct test_vector md5_vectors[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static void print_blob(const char *label, const uint8_t *data, const uint32_t len)
|
||||
{
|
||||
printf("%s:", label);
|
||||
for(int i = 0; i < len; i++) {
|
||||
if(i % 16 == 0)
|
||||
printf("\n%02x:", i);
|
||||
printf(" %02x", data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_md5(void)
|
||||
{
|
||||
printf("\r\nTesting MD5 vectors...\r\n");
|
||||
uint8_t test_digest[16];
|
||||
|
||||
const mbedtls_md_info_t *md5_hmac = mbedtls_md_info_from_type(MBEDTLS_MD_MD5);
|
||||
|
||||
for(int i = 0; i < NUM_MD5_VECTORS; i++) {
|
||||
const struct test_vector *vector = &md5_vectors[i];
|
||||
printf("Test case %d: ", i+1);
|
||||
hmac_md5(vector->data, vector->data_len, vector->key, vector->key_len, test_digest);
|
||||
if(memcmp(test_digest, vector->digest, 16)) {
|
||||
|
||||
uint8_t test_digest[16];
|
||||
mbedtls_md_hmac(md5_hmac, vector->key, vector->key_len, vector->data, vector->data_len, test_digest);
|
||||
|
||||
if(memcmp(vector->digest, test_digest, 16)) {
|
||||
uint8_t first = 0;
|
||||
for(first = 0; first < 16; first++) {
|
||||
if(test_digest[first] != vector->digest[first]) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue