From d6855818296b769a4f6c2b9fd4a7bffb203d0ddb Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 10 Aug 2015 11:52:26 +1000 Subject: [PATCH 01/56] Syscall hander: Fix a3 save address (SDK doesn't use syscall exception so bug probably never hit?) --- core/exception_vectors.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index 9085ca2..43dbd12 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -230,7 +230,7 @@ UserIntExit: UserSyscallHandler: addi sp, sp, -0x10 s32i a2, sp, 0x08 - s32i a2, sp, 0x0c + s32i a3, sp, 0x0c rsr.epc1 a2 addi a3, a2, 0x3 wsr.epc1 a3 From 25e124a612d928e428fe4f98cdc87db9eabfe5bc Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 10 Aug 2015 11:53:37 +1000 Subject: [PATCH 02/56] ld: Link memmove into IRAM (used by sprintf, etc.) --- ld/eagle.app.v6.ld | 1 + 1 file changed, 1 insertion(+) diff --git a/ld/eagle.app.v6.ld b/ld/eagle.app.v6.ld index ae5c23b..73342e6 100644 --- a/ld/eagle.app.v6.ld +++ b/ld/eagle.app.v6.ld @@ -241,6 +241,7 @@ SECTIONS *libc.a:*memcpy.o(.literal .text .literal.* .text.*) *libc.a:*memset.o(.literal .text .literal.* .text.*) *libc.a:*memcmp.o(.literal .text .literal.* .text.*) + *libc.a:*memmove.o(.literal .text .literal.* .text.*) *libc.a:*rand.o(.literal .text .literal.* .text.*) *libc.a:*bzero.o(.literal .text .literal.* .text.*) *libc.a:*lock.o(.literal .text .literal.* .text.*) From bfd38cd1e2282d37e942efddcbef4d587131c03e Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 10 Aug 2015 11:51:46 +1000 Subject: [PATCH 03/56] Experimental support for storing const strings in SPI flash or IRAM As discussed in #11 Known limitations: - Only supports l8ui/l16ui - Unoptimised load routine - Not called from DoubleExceptionHandler but should be - Doesn't restore state properly when falling through to fatal exception handler --- core/exception_vectors.S | 128 ++++++++++++++++++ examples/experiments/unaligned_load/Makefile | 2 + .../unaligned_load/unaligned_load.c | 117 ++++++++++++++++ 3 files changed, 247 insertions(+) create mode 100644 examples/experiments/unaligned_load/Makefile create mode 100644 examples/experiments/unaligned_load/unaligned_load.c diff --git a/core/exception_vectors.S b/core/exception_vectors.S index 43dbd12..3b4a559 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -173,12 +173,14 @@ CallNMIExceptionHandler: /* Some UserException causes, see table Table 4–64 in ISA reference */ #define CAUSE_SYSCALL 1 +#define CAUSE_LOADSTORE 3 #define CAUSE_LVL1INT 4 .type CallUserExceptionHandler, @function CallUserExceptionHandler: rsr.exccause a0 beqi a0, CAUSE_SYSCALL, UserSyscallHandler + beqi a0, CAUSE_LOADSTORE, UserLoadStoreExceptionHandler mov a0, sp addi sp, sp, -0x50 s32i a0, sp, 0x10 @@ -242,6 +244,132 @@ UserSyscallHandler: rsr.excsave1 a0 rfe + + .section .bss + .global LoadStoreErrorFlag + .align 4 +LoadStoreErrorFlag: + .long 0 + .long 0 + .long 0 + .long 0 + + .section .data + .align 4 +PRINT_ADDR: + .string "0x%08lx '%c'\r\n" +PRINT_MULTI: + .string "a3=0x%08lx a4=0x%08lx a5=0x%08lx a6=0x%08lx a7=0x%08lx\r\n" + + .text + .section .vecbase.text + .literal_position + .align 4 + .global UserLoadStoreExceptionHandler +/* "Fix" LoadStoreException exceptions thatare l8/l16 from an Instruction region */ +UserLoadStoreExceptionHandler: + addi sp, sp, -0x40 + s32i a2, sp, 0x08 + rsr.excsave1 a2 /* a0 value */ + s32i a2, sp, 0x00 + addi a2, sp, 0x40 + s32i a2, sp, 0x04 /* original sp value */ + s32i a3, sp, 0x0c + s32i a4, sp, 0x10 + s32i a5, sp, 0x14 + s32i a6, sp, 0x18 + s32i a7, sp, 0x1c + s32i a8, sp, 0x20 + s32i a9, sp, 0x24 + s32i a10, sp, 0x28 + s32i a11, sp, 0x2c + s32i a12, sp, 0x30 + s32i a13, sp, 0x34 + s32i a14, sp, 0x38 + s32i a15, sp, 0x3c + + /* Check the top nibble of the faulting address is 4, otherwise + we can't help out here */ + rsr.excvaddr a2 + extui a2, a2, 28, 4 + bnei a2, 0x4, .Lcant_fix + + /* Load the instruction we failed to execute */ + rsr.epc1 a3 + movi a4, ~3 + and a2, a3, a4 + l32i a4, a2, 0 + l32i a5, a2, 4 + ssa8l a3 + src a4, a5, a4 + /* a4 is now the instruction that failed */ + + /* example l8ui instr 040c72 */ + movi a2, 0x00F00F /* l8ui/l16ui opcode mask */ + and a3, a4, a2 + movi a8, 0xFF + movi a5, 0x000002 /* l8ui opcode after masking */ + beq a3, a5, .Lcan_fix + + movi a8, 0xFFFF + movi a5, 0x001002 /* l16ui opcode after masking */ + beq a3, a5, .Lcan_fix + +.Lcant_fix: + /* not an l8ui or an l16ui, or not in the instruction space, so bomb out +TODO: the exception dump will have some wrong values in it */ + movi a2, PRINT_ADDR + movi a3, 0xafafafaf + call0 printf + call0 sdk_user_fatal_exception_handler +.Lcan_fix: + /* verified an 8- or 16-bit read in an instruction address space. + + a4 holds instruction, a8 holds mask + */ + extui a2, a4, 4, 4 /* a2 is destination register 0-15 */ + slli a2, a2, 2 /* a2 is now offset of destination register, relative to stack pointer */ + + rsr.sar a6 + rsr.excvaddr a3 + ssa8l a3 /* sar is the shift to extract a3's byte */ + movi a4, ~3 + and a4, a3, a4 /* a4 is word aligned read address */ + + l32i a5, a4, 0 /* perform the actual read */ + srl a5, a5 + and a5, a5, a8 /* mask off bits we need for an l8/l16 */ + + wsr.sar a6 + + add a6, sp, a2 + s32i a5, a6, 0 /* overwrite correct value on register slot @ stack+a2 */ + + /* Footer*/ + //Increment PC + rsr.epc1 a2 + addi a3, a2, 0x3 + wsr.epc1 a3 + + // Restore registers + l32i a0, sp, 0x00 + l32i a2, sp, 0x08 + l32i a3, sp, 0x0c + l32i a4, sp, 0x10 + l32i a5, sp, 0x14 + l32i a6, sp, 0x18 + l32i a7, sp, 0x1c + l32i a8, sp, 0x20 + l32i a9, sp, 0x24 + l32i a10, sp, 0x28 + l32i a11, sp, 0x2c + l32i a12, sp, 0x30 + l32i a13, sp, 0x34 + l32i a14, sp, 0x38 + l32i a15, sp, 0x3c + l32i sp, sp, 0x04 + rfe + .global _xt_user_exit .type _xt_user_exit, @function _xt_user_exit: diff --git a/examples/experiments/unaligned_load/Makefile b/examples/experiments/unaligned_load/Makefile new file mode 100644 index 0000000..158bfb3 --- /dev/null +++ b/examples/experiments/unaligned_load/Makefile @@ -0,0 +1,2 @@ +PROGRAM=unaligned_load +include ../../../common.mk diff --git a/examples/experiments/unaligned_load/unaligned_load.c b/examples/experiments/unaligned_load/unaligned_load.c new file mode 100644 index 0000000..033c7be --- /dev/null +++ b/examples/experiments/unaligned_load/unaligned_load.c @@ -0,0 +1,117 @@ +/* Very basic example that just demonstrates we can run at all! + */ +#include "esp/rom.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++)) + ; +} + +#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("%5ld 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_sprintf, "sprintf", nullvalue, evict_cache); + run_test(string, test_sprintf_arg, "sprintf format arg", nullvalue, evict_cache); +} + +void user_init(void) +{ + sdk_uart_div_modify(0, UART_CLK_FREQ / 115200); + printf("\r\n\r\nSDK version:%s\r\n", sdk_system_get_sdk_version()); + test_string(dramtest, "DRAM", 0); + test_string(iramtest, "IRAM", 0); + test_string(iromtest, "Cached flash", 0); + test_string(iromtest, "'Uncached' flash", 1); +} From 773a046dc34a77f45c1e5127bdc26c68930eb6bf Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 11 Aug 2015 14:23:41 +1000 Subject: [PATCH 04/56] Unaligned loader: clean up, reduce number of registers --- core/exception_vectors.S | 85 +++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 44 deletions(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index 3b4a559..bfda81e 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -270,10 +270,6 @@ PRINT_MULTI: UserLoadStoreExceptionHandler: addi sp, sp, -0x40 s32i a2, sp, 0x08 - rsr.excsave1 a2 /* a0 value */ - s32i a2, sp, 0x00 - addi a2, sp, 0x40 - s32i a2, sp, 0x04 /* original sp value */ s32i a3, sp, 0x0c s32i a4, sp, 0x10 s32i a5, sp, 0x14 @@ -287,33 +283,24 @@ UserLoadStoreExceptionHandler: s32i a13, sp, 0x34 s32i a14, sp, 0x38 s32i a15, sp, 0x3c - - /* Check the top nibble of the faulting address is 4, otherwise - we can't help out here */ - rsr.excvaddr a2 - extui a2, a2, 28, 4 - bnei a2, 0x4, .Lcant_fix + rsr.sar a0 // save sar in a0 /* Load the instruction we failed to execute */ - rsr.epc1 a3 - movi a4, ~3 - and a2, a3, a4 - l32i a4, a2, 0 - l32i a5, a2, 4 - ssa8l a3 - src a4, a5, a4 - /* a4 is now the instruction that failed */ + rsr.epc1 a2 + ssa8l a2 // sar is now correct shift to read a3 + movi a3, ~3 + and a2, a2, a3 // a2 now 4-byte aligned address of instruction + l32i a3, a2, 0 + l32i a4, a2, 4 + src a2, a4, a3 // a2 now instruction that failed - /* example l8ui instr 040c72 */ - movi a2, 0x00F00F /* l8ui/l16ui opcode mask */ - and a3, a4, a2 - movi a8, 0xFF - movi a5, 0x000002 /* l8ui opcode after masking */ - beq a3, a5, .Lcan_fix + /* Check if a2 matches l8ui or l16ui */ + movi a3, 0x00F00F /* opcode mask */ + and a3, a2, a3 + beqi a3, 0x000002, .Lcan_fix_8bit /* l8ui opcode after masking */ - movi a8, 0xFFFF - movi a5, 0x001002 /* l16ui opcode after masking */ - beq a3, a5, .Lcan_fix + movi a4, 0x001002 /* l16ui opcode after masking */ + beq a3, a4, .Lcan_fix_16bit .Lcant_fix: /* not an l8ui or an l16ui, or not in the instruction space, so bomb out @@ -322,28 +309,36 @@ TODO: the exception dump will have some wrong values in it */ movi a3, 0xafafafaf call0 printf call0 sdk_user_fatal_exception_handler + +.Lcan_fix_16bit: + movi a5, 0xFFFF + j .Lcan_fix +.Lcan_fix_8bit: + movi a5, 0xFF .Lcan_fix: - /* verified an 8- or 16-bit read in an instruction address space. - - a4 holds instruction, a8 holds mask + /* verified an 8- or 16-bit read + a2 holds instruction, a5 holds mask to apply to read value */ - extui a2, a4, 4, 4 /* a2 is destination register 0-15 */ - slli a2, a2, 2 /* a2 is now offset of destination register, relative to stack pointer */ + extui a2, a2, 4, 4 /* a2 now destination register 0-15 */ + slli a2, a2, 2 /* a2 now offset of destination register, relative to stack pointer */ - rsr.sar a6 - rsr.excvaddr a3 - ssa8l a3 /* sar is the shift to extract a3's byte */ + rsr.excvaddr a3 // read faulting address + ssa8l a3 /* sar is now shift to extract a3's byte */ movi a4, ~3 - and a4, a3, a4 /* a4 is word aligned read address */ + and a3, a3, a4 /* a3 now word aligned read address */ - l32i a5, a4, 0 /* perform the actual read */ - srl a5, a5 - and a5, a5, a8 /* mask off bits we need for an l8/l16 */ + /* Sanity check the top nibble of the faulting address is 4, otherwise + we can't help out here */ + extui a4, a3, 28, 4 + bnei a4, 0x4, .Lcant_fix - wsr.sar a6 + l32i a3, a3, 0 /* perform the actual read */ + srl a3, a3 /* shift right correct distance */ + and a3, a3, a5 /* mask off bits we need for an l8/l16 */ - add a6, sp, a2 - s32i a5, a6, 0 /* overwrite correct value on register slot @ stack+a2 */ + /* write read value to register slot */ + add a5, sp, a2 + s32i a3, a5, 0 /* Footer*/ //Increment PC @@ -351,8 +346,10 @@ TODO: the exception dump will have some wrong values in it */ addi a3, a2, 0x3 wsr.epc1 a3 +.Lexit: + wsr.sar a0 // restore saved sar // Restore registers - l32i a0, sp, 0x00 + rsr.excsave1 a0 // restore a0 saved in exception vector l32i a2, sp, 0x08 l32i a3, sp, 0x0c l32i a4, sp, 0x10 @@ -367,7 +364,7 @@ TODO: the exception dump will have some wrong values in it */ l32i a13, sp, 0x34 l32i a14, sp, 0x38 l32i a15, sp, 0x3c - l32i sp, sp, 0x04 + addi sp, sp, 0x40 rfe .global _xt_user_exit From 8ea4ae27e20766362f72b76b65d422296ad7bdcc Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 11 Aug 2015 15:03:53 +1000 Subject: [PATCH 05/56] Unaligned loader: Support l16si --- core/exception_vectors.S | 20 +++++++++++++++++-- .../unaligned_load/unaligned_load.c | 12 +++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index bfda81e..eda3389 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -302,6 +302,8 @@ UserLoadStoreExceptionHandler: movi a4, 0x001002 /* l16ui opcode after masking */ beq a3, a4, .Lcan_fix_16bit + movi a4, 0x009002 /* l16si opcode after masking */ + beq a3, a4, .Lcan_fix_16bit_signed .Lcant_fix: /* not an l8ui or an l16ui, or not in the instruction space, so bomb out TODO: the exception dump will have some wrong values in it */ @@ -310,6 +312,9 @@ TODO: the exception dump will have some wrong values in it */ call0 printf call0 sdk_user_fatal_exception_handler +.Lcan_fix_16bit_signed: + movi a5, 0x7FFF + j .Lcan_fix .Lcan_fix_16bit: movi a5, 0xFFFF j .Lcan_fix @@ -334,11 +339,15 @@ TODO: the exception dump will have some wrong values in it */ l32i a3, a3, 0 /* perform the actual read */ srl a3, a3 /* shift right correct distance */ - and a3, a3, a5 /* mask off bits we need for an l8/l16 */ + and a4, a3, a5 /* mask off bits we need for an l8/l16 */ + + bbci a5, 15, .Lextend_sign +.Lafter_extend_sign: + /* a4 holds the correctly read value */ /* write read value to register slot */ add a5, sp, a2 - s32i a3, a5, 0 + s32i a4, a5, 0 /* Footer*/ //Increment PC @@ -367,6 +376,13 @@ TODO: the exception dump will have some wrong values in it */ addi sp, sp, 0x40 rfe +.Lextend_sign: /* apply 16-bit sign extension if necessary + a3 holds raw value, a4 holds masked */ + bbci a3, 15, .Lafter_extend_sign /* sign bit not set, do nothing */ + movi a3, (1<<31) + or a4, a3, a4 /* set sign bit */ + j .Lafter_extend_sign + .global _xt_user_exit .type _xt_user_exit, @function _xt_user_exit: diff --git a/examples/experiments/unaligned_load/unaligned_load.c b/examples/experiments/unaligned_load/unaligned_load.c index 033c7be..c65a818 100644 --- a/examples/experiments/unaligned_load/unaligned_load.c +++ b/examples/experiments/unaligned_load/unaligned_load.c @@ -64,6 +64,17 @@ void test_naive_strcpy(const char *string) ; } +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 */ + 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) @@ -104,6 +115,7 @@ void test_string(const char *string, char *label, bool evict_cache) run_test(string, test_naive_strcpy, "naive strcpy", 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); } void user_init(void) From 3b3f5ea771f6e3aa0ceb2563e84d95c7281c6a89 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 11 Aug 2015 15:29:53 +1000 Subject: [PATCH 06/56] Unaligned loads: Only save working registers, use jump table to load non-working registers --- core/exception_vectors.S | 76 ++++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index eda3389..b96f60a 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -273,16 +273,6 @@ UserLoadStoreExceptionHandler: s32i a3, sp, 0x0c s32i a4, sp, 0x10 s32i a5, sp, 0x14 - s32i a6, sp, 0x18 - s32i a7, sp, 0x1c - s32i a8, sp, 0x20 - s32i a9, sp, 0x24 - s32i a10, sp, 0x28 - s32i a11, sp, 0x2c - s32i a12, sp, 0x30 - s32i a13, sp, 0x34 - s32i a14, sp, 0x38 - s32i a15, sp, 0x3c rsr.sar a0 // save sar in a0 /* Load the instruction we failed to execute */ @@ -324,8 +314,6 @@ TODO: the exception dump will have some wrong values in it */ /* verified an 8- or 16-bit read a2 holds instruction, a5 holds mask to apply to read value */ - extui a2, a2, 4, 4 /* a2 now destination register 0-15 */ - slli a2, a2, 2 /* a2 now offset of destination register, relative to stack pointer */ rsr.excvaddr a3 // read faulting address ssa8l a3 /* sar is now shift to extract a3's byte */ @@ -344,11 +332,19 @@ TODO: the exception dump will have some wrong values in it */ bbci a5, 15, .Lextend_sign .Lafter_extend_sign: /* a4 holds the correctly read value */ + extui a2, a2, 4, 4 /* a2 now destination register 0-15 */ - /* write read value to register slot */ + /* test if a4 needs to be written directly to a register (ie not a working register) */ + bgei a2, 6, .Lwrite_value_direct_reg + /* test if a4 needs to be written to a0 */ + beqz a2, .Lwrite_value_a0_reg + + /* otherwise, a4 needs to be written to a saved working register 'slot' on the stack */ + slli a2, a2, 2 add a5, sp, a2 s32i a4, a5, 0 +.Lafter_write_value: /* Footer*/ //Increment PC rsr.epc1 a2 @@ -363,16 +359,6 @@ TODO: the exception dump will have some wrong values in it */ l32i a3, sp, 0x0c l32i a4, sp, 0x10 l32i a5, sp, 0x14 - l32i a6, sp, 0x18 - l32i a7, sp, 0x1c - l32i a8, sp, 0x20 - l32i a9, sp, 0x24 - l32i a10, sp, 0x28 - l32i a11, sp, 0x2c - l32i a12, sp, 0x30 - l32i a13, sp, 0x34 - l32i a14, sp, 0x38 - l32i a15, sp, 0x3c addi sp, sp, 0x40 rfe @@ -383,6 +369,50 @@ TODO: the exception dump will have some wrong values in it */ or a4, a3, a4 /* set sign bit */ j .Lafter_extend_sign +.Lwrite_value_direct_reg: + /* Directly update register index a2, in range 6-15, using value in a4 */ + addi a2, a2, -6 + slli a2, a2, 3 /* offset from a6, x8 */ + movi a3, .Ldirect_reg_jumptable + add a2, a2, a3 + jx a2 + .align 8 +.Ldirect_reg_jumptable: + mov a6, a4 + j .Lafter_write_value + .align 8 + mov a7, a4 + j .Lafter_write_value + .align 8 + mov a8, a4 + j .Lafter_write_value + .align 8 + mov a9, a4 + j .Lafter_write_value + .align 8 + mov a10, a4 + j .Lafter_write_value + .align 8 + mov a11, a4 + j .Lafter_write_value + .align 8 + mov a12, a4 + j .Lafter_write_value + .align 8 + mov a13, a4 + j .Lafter_write_value + .align 8 + mov a14, a4 + j .Lafter_write_value + .align 8 + mov a15, a4 + j .Lafter_write_value + +.Lwrite_value_a0_reg: + /* a0 is saved in excsave1,so just update this with value */ + wsr.excsave1 a4 + j .Lafter_write_value + .global _xt_user_exit .type _xt_user_exit, @function _xt_user_exit: From e3b24df043dc8370d7865604d12644672616b7b6 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 11 Aug 2015 16:25:11 +1000 Subject: [PATCH 07/56] Unaligned load: Shave a few more instructions off --- core/exception_vectors.S | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index b96f60a..dcdee1d 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -268,7 +268,7 @@ PRINT_MULTI: .global UserLoadStoreExceptionHandler /* "Fix" LoadStoreException exceptions thatare l8/l16 from an Instruction region */ UserLoadStoreExceptionHandler: - addi sp, sp, -0x40 + addi sp, sp, -0x18 s32i a2, sp, 0x08 s32i a3, sp, 0x0c s32i a4, sp, 0x10 @@ -284,7 +284,7 @@ UserLoadStoreExceptionHandler: l32i a4, a2, 4 src a2, a4, a3 // a2 now instruction that failed - /* Check if a2 matches l8ui or l16ui */ + /* Check if a2 matches l8ui, l16ui or l16si opcodes */ movi a3, 0x00F00F /* opcode mask */ and a3, a2, a3 beqi a3, 0x000002, .Lcan_fix_8bit /* l8ui opcode after masking */ @@ -320,18 +320,17 @@ TODO: the exception dump will have some wrong values in it */ movi a4, ~3 and a3, a3, a4 /* a3 now word aligned read address */ - /* Sanity check the top nibble of the faulting address is 4, otherwise - we can't help out here */ - extui a4, a3, 28, 4 - bnei a4, 0x4, .Lcant_fix - l32i a3, a3, 0 /* perform the actual read */ srl a3, a3 /* shift right correct distance */ and a4, a3, a5 /* mask off bits we need for an l8/l16 */ - bbci a5, 15, .Lextend_sign + bbci a5, 14, .Lafter_extend_sign /* 8-bit, no sign extension */ + bbsi a5, 15, .Lafter_extend_sign /* 16-bit unsigned, no sign extension */ + bbci a3, 15, .Lafter_extend_sign /* sign bit not set, no sign extension */ + movi a3, (1<<31) + or a4, a3, a4 /* set 32-bit sign bit */ .Lafter_extend_sign: - /* a4 holds the correctly read value */ + /* a2 holds instruction, a4 holds the correctly read value */ extui a2, a2, 4, 4 /* a2 now destination register 0-15 */ /* test if a4 needs to be written directly to a register (ie not a working register) */ @@ -339,9 +338,8 @@ TODO: the exception dump will have some wrong values in it */ /* test if a4 needs to be written to a0 */ beqz a2, .Lwrite_value_a0_reg - /* otherwise, a4 needs to be written to a saved working register 'slot' on the stack */ - slli a2, a2, 2 - add a5, sp, a2 + /* otherwise, a4 can be written to a saved working register 'slot' on the stack */ + addx4 a5, a2, sp s32i a4, a5, 0 .Lafter_write_value: @@ -359,7 +357,7 @@ TODO: the exception dump will have some wrong values in it */ l32i a3, sp, 0x0c l32i a4, sp, 0x10 l32i a5, sp, 0x14 - addi sp, sp, 0x40 + addi sp, sp, 0x18 rfe .Lextend_sign: /* apply 16-bit sign extension if necessary From 7f338e66cbe66e32c58fa8bd2a1769fcea0b58b6 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 11 Aug 2015 16:25:35 +1000 Subject: [PATCH 08/56] Unaligned load: Remove debugging variables --- core/exception_vectors.S | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index dcdee1d..00c511d 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -245,22 +245,6 @@ UserSyscallHandler: rfe - .section .bss - .global LoadStoreErrorFlag - .align 4 -LoadStoreErrorFlag: - .long 0 - .long 0 - .long 0 - .long 0 - - .section .data - .align 4 -PRINT_ADDR: - .string "0x%08lx '%c'\r\n" -PRINT_MULTI: - .string "a3=0x%08lx a4=0x%08lx a5=0x%08lx a6=0x%08lx a7=0x%08lx\r\n" - .text .section .vecbase.text .literal_position @@ -295,11 +279,8 @@ UserLoadStoreExceptionHandler: movi a4, 0x009002 /* l16si opcode after masking */ beq a3, a4, .Lcan_fix_16bit_signed .Lcant_fix: - /* not an l8ui or an l16ui, or not in the instruction space, so bomb out -TODO: the exception dump will have some wrong values in it */ - movi a2, PRINT_ADDR - movi a3, 0xafafafaf - call0 printf + /* not an opcode we can try to fix, so bomb out + TODO: the exception dump will have some wrong values in it */ call0 sdk_user_fatal_exception_handler .Lcan_fix_16bit_signed: From 1aaef737df3e82e423a223bd854f45582f27a9a4 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 10 Sep 2015 21:10:49 +1000 Subject: [PATCH 09/56] Fix printf format string changed in merge --- examples/experiments/unaligned_load/unaligned_load.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/experiments/unaligned_load/unaligned_load.c b/examples/experiments/unaligned_load/unaligned_load.c index c65a818..e7c7c8e 100644 --- a/examples/experiments/unaligned_load/unaligned_load.c +++ b/examples/experiments/unaligned_load/unaligned_load.c @@ -97,7 +97,7 @@ uint32_t IRAM run_test(const char *string, test_with_fn_t testfn, const char *te uint32_t after = get_ccount(); vPortExitCritical(); uint32_t instructions = (after-before)/TEST_REPEATS - nullvalue; - printf("%5ld instructions\r\n", instructions); + printf("%5d instructions\r\n", instructions); return instructions; } From a5a179beef0ab6aacd02420a997bc4a1f63f70a6 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 10 Sep 2015 15:02:47 +1000 Subject: [PATCH 10/56] Extended unaligned load support to work from DoubleExceptionVector Allows handling bad loads that occur inside level 1 exception handlers. --- core/exception_vectors.S | 99 ++++++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 30 deletions(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index 00c511d..a771667 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -15,6 +15,12 @@ Additions Copyright (C) Superhouse Automation Pty Ltd BSD Licensed as described in the file LICENSE */ + +/* Some UserException causes, see table Table 4–64 in ISA reference */ +#define CAUSE_SYSCALL 1 +#define CAUSE_LOADSTORE 3 +#define CAUSE_LVL1INT 4 + .text .section .vecbase.text, "x" .align 256 @@ -48,15 +54,15 @@ KernelExceptionVector: .align 16 UserExceptionVector: wsr.excsave1 a0 - call0 CallUserExceptionHandler - rfe /* CallUserExceptionHandler should call rfe itself */ - .align 16 -.L_EmptyVectorEntry2: - nop + rsr.exccause a0 + beqi a0, CAUSE_SYSCALL, UserSyscallHandler + beqi a0, CAUSE_LOADSTORE, UserExceptionLoadStoreHandler + j UserExceptionHandler + /* Empty exception slot goes here, but previous slot is large enough we can skip it */ .align 16 DoubleExceptionVector: break 1, 4 - call0 sdk_user_fatal_exception_handler + j DoubleExceptionHandler .align 16 .L_UnusedResetVector: /* reset vector slot doesn't get used, as vecbase goes back to mask ROM on reset */ @@ -171,24 +177,16 @@ CallNMIExceptionHandler: LOAD_REG a1, 1 rfi 0x3 -/* Some UserException causes, see table Table 4–64 in ISA reference */ -#define CAUSE_SYSCALL 1 -#define CAUSE_LOADSTORE 3 -#define CAUSE_LVL1INT 4 - - .type CallUserExceptionHandler, @function -CallUserExceptionHandler: - rsr.exccause a0 - beqi a0, CAUSE_SYSCALL, UserSyscallHandler - beqi a0, CAUSE_LOADSTORE, UserLoadStoreExceptionHandler - mov a0, sp + .type UserExceptionHandler, @function +UserExceptionHandler: + mov a0, sp /* a0 was saved in UserExceptionVector */ addi sp, sp, -0x50 s32i a0, sp, 0x10 rsr.ps a0 s32i a0, sp, 0x08 rsr.epc1 a0 s32i a0, sp, 0x04 - rsr.excsave1 a0 /* a0 was saved in UserExceptionVector */ + rsr.excsave1 a0 s32i a0, sp, 0x0c movi a0, _xt_user_exit s32i a0, sp, 0x0 @@ -244,24 +242,51 @@ UserSyscallHandler: rsr.excsave1 a0 rfe + .text + .section .vecbase.text + .literal_position + .align 4 +DoubleExceptionHandler: + rsr.exccause a0 + beqi a0, CAUSE_LOADSTORE, DoubleExceptionLoadStoreHandler + call0 sdk_user_fatal_exception_handler .text .section .vecbase.text .literal_position .align 4 - .global UserLoadStoreExceptionHandler -/* "Fix" LoadStoreException exceptions thatare l8/l16 from an Instruction region */ -UserLoadStoreExceptionHandler: + +/* "Fix" LoadStoreException exceptions that are l8/l16 from an Instruction region, + DoubleException exception variant (ie load happened in a level1 exception handler). */ +DoubleExceptionLoadStoreHandler: addi sp, sp, -0x18 s32i a2, sp, 0x08 + rsr.epc2 a2 + j InnerLoadStoreExceptionHandler + + .text + .section .vecbase.text + .literal_position + .align 4 + +/* "Fix" LoadStoreException exceptions that are l8/l16 from an Instruction region, + normal exception variant. */ +UserExceptionLoadStoreHandler: + addi sp, sp, -0x18 + s32i a2, sp, 0x08 + rsr.epc1 a2 +/* Inner UserLoadStoreExceptionHandler handlers. Works for both level1 & level 2 interrupt level. + * + * Called from level-specific handler above which sets up stack and loads epcX into a2. + */ +InnerLoadStoreExceptionHandler: s32i a3, sp, 0x0c s32i a4, sp, 0x10 s32i a5, sp, 0x14 rsr.sar a0 // save sar in a0 - /* Load the instruction we failed to execute */ - rsr.epc1 a2 - ssa8l a2 // sar is now correct shift to read a3 + /* Examine the instruction we failed to execute (in a2) */ + ssa8l a2 // sar is now correct shift for aligned read movi a3, ~3 and a2, a2, a3 // a2 now 4-byte aligned address of instruction l32i a3, a2, 0 @@ -324,16 +349,18 @@ UserLoadStoreExceptionHandler: s32i a4, a5, 0 .Lafter_write_value: - /* Footer*/ - //Increment PC + /* test PS.INTLEVEL (1=User, 2=Double) to see which interrupt level we restore from + */ + rsr.ps a2 + bbsi a2, 1, .Lincrement_PC_intlevel2 +.Lincrement_PC_intlevel1: rsr.epc1 a2 addi a3, a2, 0x3 wsr.epc1 a3 - -.Lexit: wsr.sar a0 // restore saved sar - // Restore registers rsr.excsave1 a0 // restore a0 saved in exception vector +.Lafter_increment_PC: + // Restore registers l32i a2, sp, 0x08 l32i a3, sp, 0x0c l32i a4, sp, 0x10 @@ -341,6 +368,14 @@ UserLoadStoreExceptionHandler: addi sp, sp, 0x18 rfe +.Lincrement_PC_intlevel2: + rsr.epc2 a2 + addi a3, a2, 0x3 + wsr.epc2 a3 + wsr.sar a0 // restore saved sar + rsr.excsave2 a0 // restore a0 saved in exception vector + j .Lafter_increment_PC + .Lextend_sign: /* apply 16-bit sign extension if necessary a3 holds raw value, a4 holds masked */ bbci a3, 15, .Lafter_extend_sign /* sign bit not set, do nothing */ @@ -388,10 +423,14 @@ UserLoadStoreExceptionHandler: j .Lafter_write_value .Lwrite_value_a0_reg: - /* a0 is saved in excsave1,so just update this with value */ + /* a0 is saved in excsave1,so just update this with value + TODO: This won't work with interrupt level 2 + */ wsr.excsave1 a4 j .Lafter_write_value +/* End of InnerUserLoadStoreExceptionHandler */ + .global _xt_user_exit .type _xt_user_exit, @function _xt_user_exit: From 45d4e0da2d231f7975ca51d5a8d22cfc51a8c1a1 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 10 Sep 2015 21:35:18 +1000 Subject: [PATCH 11/56] Exception vectors: Rearrange to use absolute offets instead of .align hacks --- core/exception_vectors.S | 44 +++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index a771667..7e8241c 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -12,7 +12,7 @@ Part of esp-open-rtos Original vector contents Copyright (C) 2014-2015 Espressif Systems - Additions Copyright (C) Superhouse Automation Pty Ltd + Additions Copyright (C) Superhouse Automation Pty Ltd and Angus Gratton BSD Licensed as described in the file LICENSE */ @@ -23,9 +23,9 @@ .text .section .vecbase.text, "x" - .align 256 .global VecBase .type VecBase, @function /* it's not really a function, but treat it like one */ + .org 0 VecBase: /* IMPORTANT: exception vector literals will go here, but we can't have more than 4 otherwise we push DebugExceptionVector past @@ -33,40 +33,43 @@ VecBase: and also keep the VecBase offsets easy to read, but this works for now. */ .literal_position - .align 16 + .org 0x10 DebugExceptionVector: wsr.excsave2 a0 call0 sdk_user_fatal_exception_handler rfi 2 - .align 16 + + .org 0x20 NMIExceptionVector: wsr.excsave3 a0 call0 CallNMIExceptionHandler rfi 3 /* CallNMIExceptionHandler should call rfi itself */ - .align 16 + + .org 0x30 KernelExceptionVector: break 1, 0 call0 sdk_user_fatal_exception_handler rfe - .align 16 -.L_EmptyVectorEntry: - nop - .align 16 + + .org 0x50 UserExceptionVector: wsr.excsave1 a0 rsr.exccause a0 beqi a0, CAUSE_SYSCALL, UserSyscallHandler beqi a0, CAUSE_LOADSTORE, UserExceptionLoadStoreHandler j UserExceptionHandler - /* Empty exception slot goes here, but previous slot is large enough we can skip it */ - .align 16 + + .org 0x70 DoubleExceptionVector: break 1, 4 - j DoubleExceptionHandler - .align 16 -.L_UnusedResetVector: - /* reset vector slot doesn't get used, as vecbase goes back to mask ROM on reset */ - nop + rsr.exccause a0 + beqi a0, CAUSE_LOADSTORE, DoubleExceptionLoadStoreHandler + call0 sdk_user_fatal_exception_handler + +/* Reset vector would go here at offset 0x80 but should be unused, + as vecbase goes back to mask ROM vectors on reset */ + +/***** end of exception vectors *****/ .section .bss NMIHandlerStack: /* stack space for NMI handler */ @@ -242,15 +245,6 @@ UserSyscallHandler: rsr.excsave1 a0 rfe - .text - .section .vecbase.text - .literal_position - .align 4 -DoubleExceptionHandler: - rsr.exccause a0 - beqi a0, CAUSE_LOADSTORE, DoubleExceptionLoadStoreHandler - call0 sdk_user_fatal_exception_handler - .text .section .vecbase.text .literal_position From 0432ae374547f65eedababcf91bca77f047b7ba5 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 14 Sep 2015 17:19:09 +1000 Subject: [PATCH 12/56] Use GPIO2 for led_debug.S --- core/exception_vectors.S | 3 ++- core/led_debug.s | 8 +++++--- examples/experiments/unaligned_load/unaligned_load.c | 4 ++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index 7e8241c..9d700b2 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -16,6 +16,8 @@ BSD Licensed as described in the file LICENSE */ +#include "led_debug.s" + /* Some UserException causes, see table Table 4–64 in ISA reference */ #define CAUSE_SYSCALL 1 #define CAUSE_LOADSTORE 3 @@ -314,7 +316,6 @@ InnerLoadStoreExceptionHandler: /* verified an 8- or 16-bit read a2 holds instruction, a5 holds mask to apply to read value */ - rsr.excvaddr a3 // read faulting address ssa8l a3 /* sar is now shift to extract a3's byte */ movi a4, ~3 diff --git a/core/led_debug.s b/core/led_debug.s index 8196c9e..28caf65 100644 --- a/core/led_debug.s +++ b/core/led_debug.s @@ -4,6 +4,8 @@ * * To have this work from initial reset, without needing an iomux call * first, choose a pin where iomux defaults to GPIO (ie 0,2,4,5) + * + * Current sets on=LOW, as the GPIO2 pin is active low */ LED_GPIO=2 GPIO_DIR_SET = 0x6000030c @@ -19,11 +21,11 @@ GPIO_OUT_CLEAR = 0x60000308 .endm // Turn LED on. rega, regb will be clobbered -.macro led_on rega, regb +.macro led_off rega, regb led_op \rega, \regb, GPIO_OUT_SET .endm -// Turn LED off. rega, regb will be clobbered -.macro led_off rega, regb +// Turn LED on. rega, regb will be clobbered +.macro led_on rega, regb led_op \rega, \regb, GPIO_OUT_CLEAR .endm diff --git a/examples/experiments/unaligned_load/unaligned_load.c b/examples/experiments/unaligned_load/unaligned_load.c index e7c7c8e..dd45a44 100644 --- a/examples/experiments/unaligned_load/unaligned_load.c +++ b/examples/experiments/unaligned_load/unaligned_load.c @@ -121,6 +121,10 @@ void test_string(const char *string, char *label, bool evict_cache) 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()); test_string(dramtest, "DRAM", 0); test_string(iramtest, "IRAM", 0); From 9c15b757d329e4bd971a6ab8a283e415db2cde81 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 14 Sep 2015 17:22:50 +1000 Subject: [PATCH 13/56] Exception handlers: remove unused NMIHandlerAddress --- core/exception_vectors.S | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index 9d700b2..1ba2eee 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -76,15 +76,10 @@ DoubleExceptionVector: .section .bss NMIHandlerStack: /* stack space for NMI handler */ .skip 4*0x100 +.LNMIHandlerStackTop: NMIRegisterSaved: /* register space for saving NMI registers */ .skip 4*(0x16 + 6) -/* this symbol is _Pri_3_HandlerAddress in the RTOS SDK, appears totally - unused (stays zero at all times) */ - .global NMIHandlerAddress -NMIHandlerAddress: - .long 0 - /* Save register relative to a0 */ .macro SAVE_REG register, regnum s32i \register, a0, (0x20 + 4 * \regnum) @@ -112,11 +107,9 @@ call_user_start: CallNMIExceptionHandler: movi a0, NMIRegisterSaved SAVE_REG a2, 2 - movi a2, NMIHandlerAddress - l32i a2, a2, 0 SAVE_REG sp, 1 SAVE_REG a3, 3 - xsr.excsave3 a2 /* excsave3 is now NMIHandlerAddress, a2 is former a0 */ + rsr.excsave3 a2 /* a2 is now former a0 */ SAVE_REG a4, 4 SAVE_REG a2, 0 rsr.epc1 a3 @@ -138,7 +131,7 @@ CallNMIExceptionHandler: SAVE_REG a13, 13 SAVE_REG a14, 14 SAVE_REG a15, 15 - movi sp, NMIRegisterSaved /* also top of NMIHandlerStack */ + movi sp, .LNMIHandlerStackTop movi a0, 0 movi a2, 0x23 /* argument for handler */ wsr.ps a2 From 0e0c5d89b8671373298d88a383b490814384346f Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 14 Sep 2015 17:43:29 +1000 Subject: [PATCH 14/56] NMI exception handler: Fix reserving too much RAM for registers --- core/exception_vectors.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index 1ba2eee..5d5b74e 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -78,7 +78,7 @@ NMIHandlerStack: /* stack space for NMI handler */ .skip 4*0x100 .LNMIHandlerStackTop: NMIRegisterSaved: /* register space for saving NMI registers */ - .skip 4*(0x16 + 6) + .skip 4*(16 + 6) /* Save register relative to a0 */ .macro SAVE_REG register, regnum From 259c9b643fdc5f81b0e13f43812dd400523279bc Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 14 Sep 2015 18:17:45 +1000 Subject: [PATCH 15/56] Exception vectors: Remove no-op syscallhandler --- core/exception_vectors.S | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index 5d5b74e..9df4f0d 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -57,7 +57,6 @@ KernelExceptionVector: UserExceptionVector: wsr.excsave1 a0 rsr.exccause a0 - beqi a0, CAUSE_SYSCALL, UserSyscallHandler beqi a0, CAUSE_LOADSTORE, UserExceptionLoadStoreHandler j UserExceptionHandler @@ -224,22 +223,6 @@ UserIntDone: UserIntExit: call0 sdk__xt_int_exit /* calls rfi */ -/* As far as I can tell, the syscall handler is basically a no-op */ -UserSyscallHandler: - addi sp, sp, -0x10 - s32i a2, sp, 0x08 - s32i a3, sp, 0x0c - rsr.epc1 a2 - addi a3, a2, 0x3 - wsr.epc1 a3 - l32i a2, sp, 0x8 - l32i a3, sp, 0xc - addi sp, sp, 0x10 - movi a0, 0x7f - movnez a2, a0, a2 - rsr.excsave1 a0 - rfe - .text .section .vecbase.text .literal_position From 26e1ce325ea5834dda3cea7f54d15ea3080db370 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 14 Sep 2015 18:30:11 +1000 Subject: [PATCH 16/56] Fix sign extension as suggested by @foogod Also removes a branch from l8ui path, saves some cycles --- core/exception_vectors.S | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index 9df4f0d..588a6a7 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -301,11 +301,7 @@ InnerLoadStoreExceptionHandler: srl a3, a3 /* shift right correct distance */ and a4, a3, a5 /* mask off bits we need for an l8/l16 */ - bbci a5, 14, .Lafter_extend_sign /* 8-bit, no sign extension */ - bbsi a5, 15, .Lafter_extend_sign /* 16-bit unsigned, no sign extension */ - bbci a3, 15, .Lafter_extend_sign /* sign bit not set, no sign extension */ - movi a3, (1<<31) - or a4, a3, a4 /* set 32-bit sign bit */ + bbsi a5, 14, .Lmaybe_extend_sign .Lafter_extend_sign: /* a2 holds instruction, a4 holds the correctly read value */ extui a2, a2, 4, 4 /* a2 now destination register 0-15 */ @@ -347,11 +343,12 @@ InnerLoadStoreExceptionHandler: rsr.excsave2 a0 // restore a0 saved in exception vector j .Lafter_increment_PC -.Lextend_sign: /* apply 16-bit sign extension if necessary - a3 holds raw value, a4 holds masked */ - bbci a3, 15, .Lafter_extend_sign /* sign bit not set, do nothing */ - movi a3, (1<<31) - or a4, a3, a4 /* set sign bit */ +.Lmaybe_extend_sign: /* apply 16-bit sign extension if necessary + a3 holds raw value, a4 holds masked */ + bbsi a5, 15, .Lafter_extend_sign /* 16-bit unsigned, no sign extension */ + bbci a3, 15, .Lafter_extend_sign /* sign bit not set, no sign extension */ + movi a3, 0xFFFF0000 + or a4, a3, a4 /* set 32-bit sign bits */ j .Lafter_extend_sign .Lwrite_value_direct_reg: From 3911a94cc861ecb661612f246be0d53295cadcfa Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 15 Sep 2015 07:37:38 +1000 Subject: [PATCH 17/56] Remove one more branch from l8ui code path Thanks for @foogod for the heads-up on this. --- core/exception_vectors.S | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index 588a6a7..c573d67 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -265,29 +265,16 @@ InnerLoadStoreExceptionHandler: l32i a4, a2, 4 src a2, a4, a3 // a2 now instruction that failed - /* Check if a2 matches l8ui, l16ui or l16si opcodes */ - movi a3, 0x00F00F /* opcode mask */ + /* Check if a2 matches l16ui, l16si or l8ui opcode */ + movi a3, 0x00700F /* opcode mask */ and a3, a2, a3 - beqi a3, 0x000002, .Lcan_fix_8bit /* l8ui opcode after masking */ - movi a4, 0x001002 /* l16ui opcode after masking */ + movi a4, 0x001002 /* l16si or l16ui opcode after masking */ beq a3, a4, .Lcan_fix_16bit - movi a4, 0x009002 /* l16si opcode after masking */ - beq a3, a4, .Lcan_fix_16bit_signed -.Lcant_fix: - /* not an opcode we can try to fix, so bomb out - TODO: the exception dump will have some wrong values in it */ - call0 sdk_user_fatal_exception_handler - -.Lcan_fix_16bit_signed: - movi a5, 0x7FFF - j .Lcan_fix -.Lcan_fix_16bit: - movi a5, 0xFFFF - j .Lcan_fix -.Lcan_fix_8bit: + bnei a3, 0x000002, .Lcant_fix /* no l8ui opcode, then can't fix */ movi a5, 0xFF + .Lcan_fix: /* verified an 8- or 16-bit read a2 holds instruction, a5 holds mask to apply to read value @@ -335,6 +322,15 @@ InnerLoadStoreExceptionHandler: addi sp, sp, 0x18 rfe +.Lcan_fix_16bit: + movi a5, 0xFFFF + j .Lcan_fix + +.Lcant_fix: + /* not an opcode we can try to fix, so bomb out + TODO: the exception dump will have some wrong values in it */ + call0 sdk_user_fatal_exception_handler + .Lincrement_PC_intlevel2: rsr.epc2 a2 addi a3, a2, 0x3 From c7a7dfdf828158c7539c3b8c49a6381aee8f0558 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 15 Sep 2015 11:22:59 +1000 Subject: [PATCH 18/56] Remove the unaligned load handler to its own source file as it was getting quite complex The downside here is needing to use #include so the 'beq' in the exception vector can land on it directly, save an instruction. There might be a better way to do this, but it seems hard to "curate" the order that symbols appear in each section. --- common.mk | 1 + core/exception_unaligned_load.S.inc | 191 ++++++++++++++++++++++++++++ core/exception_vectors.S | 180 ++------------------------ 3 files changed, 201 insertions(+), 171 deletions(-) create mode 100644 core/exception_unaligned_load.S.inc diff --git a/common.mk b/common.mk index f1d6477..a893e29 100644 --- a/common.mk +++ b/common.mk @@ -241,6 +241,7 @@ $$($(1)_OBJ_DIR)%.o: $$($(1)_REAL_ROOT)%.S $$($(1)_MAKEFILE) $(wildcard $(ROOT)* $(vecho) "AS $$<" $(Q) mkdir -p $$(dir $$@) $$($(1)_CC_ARGS) -c $$< -o $$@ + $$($(1)_CC_ARGS) -MM -MT $$@ -MF $$(@:.o=.d) $$< # the component is shown to depend on both obj and source files so we get a meaningful error message # for missing explicitly named source files diff --git a/core/exception_unaligned_load.S.inc b/core/exception_unaligned_load.S.inc new file mode 100644 index 0000000..5963746 --- /dev/null +++ b/core/exception_unaligned_load.S.inc @@ -0,0 +1,191 @@ +/* Xtensa Exception unaligned load handler + + Completes l8/l16 load instructions from Instruction address space, + that the architecture require to be 4 byte aligned word reads. + + Called from either UserExceptionVector or DoubleExceptionVector + depending on where the exception happened. + + Fast path (no branches) is for l8ui. + + Part of esp-open-rtos + Copyright (C) Angus Gratton + BSD Licensed as described in the file LICENSE +*/ + .text + .section .vecbase.text, "x" + .literal_position + +/* "Fix" LoadStoreException exceptions that are l8/l16 from an Instruction region, + normal exception variant. */ +UserExceptionLoadStoreHandler: + addi sp, sp, -0x18 + s32i a2, sp, 0x08 + rsr.epc1 a2 +/* Inner UserLoadStoreExceptionHandler handlers. Works for both level1 & level 2 interrupt level. + * + * Called from level-specific handler above which sets up stack and loads epcX into a2. + */ +InnerLoadStoreExceptionHandler: + s32i a3, sp, 0x0c + s32i a4, sp, 0x10 + s32i a5, sp, 0x14 + rsr.sar a0 // save sar in a0 + + /* Examine the instruction we failed to execute (in a2) */ + ssa8l a2 // sar is now correct shift for aligned read + movi a3, ~3 + and a2, a2, a3 // a2 now 4-byte aligned address of instruction + l32i a3, a2, 0 + l32i a4, a2, 4 + src a2, a4, a3 // a2 now instruction that failed + + /* Check if a2 matches l16ui, l16si or l8ui opcode */ + movi a3, 0x00700F /* opcode mask */ + and a3, a2, a3 + + movi a4, 0x001002 /* l16si or l16ui opcode after masking */ + beq a3, a4, .Lcan_fix_16bit + + bnei a3, 0x000002, .Lcant_fix /* no l8ui opcode, then can't fix */ + movi a5, 0xFF + +.Lcan_fix: + /* verified an 8- or 16-bit read + a2 holds instruction, a5 holds mask to apply to read value + */ + rsr.excvaddr a3 // read faulting address + ssa8l a3 /* sar is now shift to extract a3's byte */ + movi a4, ~3 + and a3, a3, a4 /* a3 now word aligned read address */ + + l32i a3, a3, 0 /* perform the actual read */ + srl a3, a3 /* shift right correct distance */ + and a4, a3, a5 /* mask off bits we need for an l8/l16 */ + + bbsi a5, 14, .Lmaybe_extend_sign +.Lafter_extend_sign: + /* a2 holds instruction, a4 holds the correctly read value */ + extui a2, a2, 4, 4 /* a2 now destination register 0-15 */ + + /* test if a4 needs to be written directly to a register (ie not a working register) */ + bgei a2, 6, .Lwrite_value_direct_reg + /* test if a4 needs to be written to a0 */ + beqz a2, .Lwrite_value_a0_reg + + /* otherwise, a4 can be written to a saved working register 'slot' on the stack */ + addx4 a5, a2, sp + s32i a4, a5, 0 + +.Lafter_write_value: + /* test PS.INTLEVEL (1=User, 2=Double) to see which interrupt level we restore from + */ + rsr.ps a2 + bbsi a2, 1, .Lincrement_PC_intlevel2 +.Lincrement_PC_intlevel1: + rsr.epc1 a2 + addi a3, a2, 0x3 + wsr.epc1 a3 + wsr.sar a0 // restore saved sar + rsr.excsave1 a0 // restore a0 saved in exception vector +.Lafter_increment_PC: + // Restore registers + l32i a2, sp, 0x08 + l32i a3, sp, 0x0c + l32i a4, sp, 0x10 + l32i a5, sp, 0x14 + addi sp, sp, 0x18 + rfe + + + .literal_position +/* "Fix" LoadStoreException exceptions that are l8/l16 from an Instruction region, + DoubleException exception variant (ie load happened in a level1 exception handler). */ +DoubleExceptionLoadStoreHandler: + addi sp, sp, -0x18 + s32i a2, sp, 0x08 + rsr.epc2 a2 + j InnerLoadStoreExceptionHandler + +/* Load mask for an l16si/16ui instruction that needs loading + + First test for a signed vs unsigned load. + + a2 is the instruction, need to load a5 with the mask to use */ +.Lcan_fix_16bit: + bbsi a2, 15, .Lcan_fix_16bit_signed + movi a5, 0xFFFF + j .Lcan_fix +.Lcan_fix_16bit_signed: + movi a5, 0x7FFF + j .Lcan_fix + +/* not an opcode we can try to fix, so bomb out + TODO: the exception dump will have some wrong values in it */ +.Lcant_fix: + call0 sdk_user_fatal_exception_handler + +/* increment PC for a DoubleException */ +.Lincrement_PC_intlevel2: + rsr.epc2 a2 + addi a3, a2, 0x3 + wsr.epc2 a3 + wsr.sar a0 // restore saved sar + rsr.excsave2 a0 // restore a0 saved in exception vector + j .Lafter_increment_PC + +.Lmaybe_extend_sign: /* apply 16-bit sign extension if necessary + a3 holds raw value, a4 holds masked */ + bbsi a5, 15, .Lafter_extend_sign /* 16-bit unsigned, no sign extension */ + bbci a3, 15, .Lafter_extend_sign /* sign bit not set, no sign extension */ + movi a3, 0xFFFF0000 + or a4, a3, a4 /* set 32-bit sign bits */ + j .Lafter_extend_sign + +.Lwrite_value_direct_reg: + /* Directly update register index a2, in range 6-15, using value in a4 */ + addi a2, a2, -6 + slli a2, a2, 3 /* offset from a6, x8 */ + movi a3, .Ldirect_reg_jumptable + add a2, a2, a3 + jx a2 + .align 8 +.Ldirect_reg_jumptable: + mov a6, a4 + j .Lafter_write_value + .align 8 + mov a7, a4 + j .Lafter_write_value + .align 8 + mov a8, a4 + j .Lafter_write_value + .align 8 + mov a9, a4 + j .Lafter_write_value + .align 8 + mov a10, a4 + j .Lafter_write_value + .align 8 + mov a11, a4 + j .Lafter_write_value + .align 8 + mov a12, a4 + j .Lafter_write_value + .align 8 + mov a13, a4 + j .Lafter_write_value + .align 8 + mov a14, a4 + j .Lafter_write_value + .align 8 + mov a15, a4 + j .Lafter_write_value + +.Lwrite_value_a0_reg: + /* a0 is saved in excsave1,so just update this with value + TODO: This won't work with interrupt level 2 + */ + wsr.excsave1 a4 + j .Lafter_write_value + +/* End of InnerUserLoadStoreExceptionHandler */ diff --git a/core/exception_vectors.S b/core/exception_vectors.S index c573d67..270b711 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -72,6 +72,11 @@ DoubleExceptionVector: /***** end of exception vectors *****/ +/* We include this here so UserExceptionLoadStoreHandler is within + the range of a 'beq' instruction jump. +*/ +#include "exception_unaligned_load.S.inc" + .section .bss NMIHandlerStack: /* stack space for NMI handler */ .skip 4*0x100 @@ -223,178 +228,11 @@ UserIntDone: UserIntExit: call0 sdk__xt_int_exit /* calls rfi */ +/* _xt_user_exit is used to exit interrupt context. + TODO: Find a better place for this to live. +*/ .text - .section .vecbase.text - .literal_position - .align 4 - -/* "Fix" LoadStoreException exceptions that are l8/l16 from an Instruction region, - DoubleException exception variant (ie load happened in a level1 exception handler). */ -DoubleExceptionLoadStoreHandler: - addi sp, sp, -0x18 - s32i a2, sp, 0x08 - rsr.epc2 a2 - j InnerLoadStoreExceptionHandler - - .text - .section .vecbase.text - .literal_position - .align 4 - -/* "Fix" LoadStoreException exceptions that are l8/l16 from an Instruction region, - normal exception variant. */ -UserExceptionLoadStoreHandler: - addi sp, sp, -0x18 - s32i a2, sp, 0x08 - rsr.epc1 a2 -/* Inner UserLoadStoreExceptionHandler handlers. Works for both level1 & level 2 interrupt level. - * - * Called from level-specific handler above which sets up stack and loads epcX into a2. - */ -InnerLoadStoreExceptionHandler: - s32i a3, sp, 0x0c - s32i a4, sp, 0x10 - s32i a5, sp, 0x14 - rsr.sar a0 // save sar in a0 - - /* Examine the instruction we failed to execute (in a2) */ - ssa8l a2 // sar is now correct shift for aligned read - movi a3, ~3 - and a2, a2, a3 // a2 now 4-byte aligned address of instruction - l32i a3, a2, 0 - l32i a4, a2, 4 - src a2, a4, a3 // a2 now instruction that failed - - /* Check if a2 matches l16ui, l16si or l8ui opcode */ - movi a3, 0x00700F /* opcode mask */ - and a3, a2, a3 - - movi a4, 0x001002 /* l16si or l16ui opcode after masking */ - beq a3, a4, .Lcan_fix_16bit - - bnei a3, 0x000002, .Lcant_fix /* no l8ui opcode, then can't fix */ - movi a5, 0xFF - -.Lcan_fix: - /* verified an 8- or 16-bit read - a2 holds instruction, a5 holds mask to apply to read value - */ - rsr.excvaddr a3 // read faulting address - ssa8l a3 /* sar is now shift to extract a3's byte */ - movi a4, ~3 - and a3, a3, a4 /* a3 now word aligned read address */ - - l32i a3, a3, 0 /* perform the actual read */ - srl a3, a3 /* shift right correct distance */ - and a4, a3, a5 /* mask off bits we need for an l8/l16 */ - - bbsi a5, 14, .Lmaybe_extend_sign -.Lafter_extend_sign: - /* a2 holds instruction, a4 holds the correctly read value */ - extui a2, a2, 4, 4 /* a2 now destination register 0-15 */ - - /* test if a4 needs to be written directly to a register (ie not a working register) */ - bgei a2, 6, .Lwrite_value_direct_reg - /* test if a4 needs to be written to a0 */ - beqz a2, .Lwrite_value_a0_reg - - /* otherwise, a4 can be written to a saved working register 'slot' on the stack */ - addx4 a5, a2, sp - s32i a4, a5, 0 - -.Lafter_write_value: - /* test PS.INTLEVEL (1=User, 2=Double) to see which interrupt level we restore from - */ - rsr.ps a2 - bbsi a2, 1, .Lincrement_PC_intlevel2 -.Lincrement_PC_intlevel1: - rsr.epc1 a2 - addi a3, a2, 0x3 - wsr.epc1 a3 - wsr.sar a0 // restore saved sar - rsr.excsave1 a0 // restore a0 saved in exception vector -.Lafter_increment_PC: - // Restore registers - l32i a2, sp, 0x08 - l32i a3, sp, 0x0c - l32i a4, sp, 0x10 - l32i a5, sp, 0x14 - addi sp, sp, 0x18 - rfe - -.Lcan_fix_16bit: - movi a5, 0xFFFF - j .Lcan_fix - -.Lcant_fix: - /* not an opcode we can try to fix, so bomb out - TODO: the exception dump will have some wrong values in it */ - call0 sdk_user_fatal_exception_handler - -.Lincrement_PC_intlevel2: - rsr.epc2 a2 - addi a3, a2, 0x3 - wsr.epc2 a3 - wsr.sar a0 // restore saved sar - rsr.excsave2 a0 // restore a0 saved in exception vector - j .Lafter_increment_PC - -.Lmaybe_extend_sign: /* apply 16-bit sign extension if necessary - a3 holds raw value, a4 holds masked */ - bbsi a5, 15, .Lafter_extend_sign /* 16-bit unsigned, no sign extension */ - bbci a3, 15, .Lafter_extend_sign /* sign bit not set, no sign extension */ - movi a3, 0xFFFF0000 - or a4, a3, a4 /* set 32-bit sign bits */ - j .Lafter_extend_sign - -.Lwrite_value_direct_reg: - /* Directly update register index a2, in range 6-15, using value in a4 */ - addi a2, a2, -6 - slli a2, a2, 3 /* offset from a6, x8 */ - movi a3, .Ldirect_reg_jumptable - add a2, a2, a3 - jx a2 - .align 8 -.Ldirect_reg_jumptable: - mov a6, a4 - j .Lafter_write_value - .align 8 - mov a7, a4 - j .Lafter_write_value - .align 8 - mov a8, a4 - j .Lafter_write_value - .align 8 - mov a9, a4 - j .Lafter_write_value - .align 8 - mov a10, a4 - j .Lafter_write_value - .align 8 - mov a11, a4 - j .Lafter_write_value - .align 8 - mov a12, a4 - j .Lafter_write_value - .align 8 - mov a13, a4 - j .Lafter_write_value - .align 8 - mov a14, a4 - j .Lafter_write_value - .align 8 - mov a15, a4 - j .Lafter_write_value - -.Lwrite_value_a0_reg: - /* a0 is saved in excsave1,so just update this with value - TODO: This won't work with interrupt level 2 - */ - wsr.excsave1 a4 - j .Lafter_write_value - -/* End of InnerUserLoadStoreExceptionHandler */ - + .section .text .global _xt_user_exit .type _xt_user_exit, @function _xt_user_exit: From 7ebebf6d2286c7586a631cd6ba4bd6cf61e8f024 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 15 Sep 2015 11:44:56 +1000 Subject: [PATCH 19/56] unaligned_load: Add doubleexceptionvector behaviour test --- .../unaligned_load/unaligned_load.c | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/examples/experiments/unaligned_load/unaligned_load.c b/examples/experiments/unaligned_load/unaligned_load.c index dd45a44..e70538b 100644 --- a/examples/experiments/unaligned_load/unaligned_load.c +++ b/examples/experiments/unaligned_load/unaligned_load.c @@ -1,6 +1,7 @@ /* 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" @@ -118,6 +119,8 @@ void test_string(const char *string, char *label, bool evict_cache) run_test(string, test_l16si, "load as l16si", nullvalue, evict_cache); } +static void test_doubleexceptions(); + void user_init(void) { sdk_uart_div_modify(0, UART_CLK_FREQ / 115200); @@ -130,4 +133,39 @@ void user_init(void) test_string(iramtest, "IRAM", 0); test_string(iromtest, "Cached flash", 0); test_string(iromtest, "'Uncached' flash", 1); + + test_doubleexceptions(); +} + +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_doubleexceptions() +{ + printf("Testing DoubleException behaviour...\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"); } From 7d779389ab86c42d04131af2d304ff78cfa4c0dc Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 15 Sep 2015 12:00:06 +1000 Subject: [PATCH 20/56] unaligned_load: Fix sign extension, add test case for sign extension H/T to @foogod again for this. --- core/exception_unaligned_load.S.inc | 2 +- .../unaligned_load/unaligned_load.c | 28 ++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/core/exception_unaligned_load.S.inc b/core/exception_unaligned_load.S.inc index 5963746..553fe84 100644 --- a/core/exception_unaligned_load.S.inc +++ b/core/exception_unaligned_load.S.inc @@ -138,7 +138,7 @@ DoubleExceptionLoadStoreHandler: a3 holds raw value, a4 holds masked */ bbsi a5, 15, .Lafter_extend_sign /* 16-bit unsigned, no sign extension */ bbci a3, 15, .Lafter_extend_sign /* sign bit not set, no sign extension */ - movi a3, 0xFFFF0000 + movi a3, 0xFFFF8000 or a4, a3, a4 /* set 32-bit sign bits */ j .Lafter_extend_sign diff --git a/examples/experiments/unaligned_load/unaligned_load.c b/examples/experiments/unaligned_load/unaligned_load.c index e70538b..ddf251b 100644 --- a/examples/experiments/unaligned_load/unaligned_load.c +++ b/examples/experiments/unaligned_load/unaligned_load.c @@ -68,7 +68,11 @@ void test_naive_strcpy(const char *string) 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 */ + 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]; @@ -119,7 +123,8 @@ void test_string(const char *string, char *label, bool evict_cache) run_test(string, test_l16si, "load as l16si", nullvalue, evict_cache); } -static void test_doubleexceptions(); +static void test_doubleexception(); +static void test_sign_extension(); void user_init(void) { @@ -134,7 +139,8 @@ void user_init(void) test_string(iromtest, "Cached flash", 0); test_string(iromtest, "'Uncached' flash", 1); - test_doubleexceptions(); + test_doubleexception(); + test_sign_extension(); } static volatile bool frc1_ran; @@ -149,7 +155,7 @@ static void frc1_interrupt_handler(void) frc1_finished = true; } -static void test_doubleexceptions() +static void test_doubleexception() { printf("Testing DoubleException behaviour...\r\n"); timer_set_interrupts(FRC1, false); @@ -169,3 +175,17 @@ static void test_doubleexceptions() 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 worked as expected.\r\n"); + } else { + printf("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]); + } +} From 9cd23e08a4f5ea8d39140ea3002667883db4e71a Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 15 Sep 2015 15:00:56 +1000 Subject: [PATCH 21/56] Fix performance regression in 3911a94cc --- core/exception_unaligned_load.S.inc | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/core/exception_unaligned_load.S.inc b/core/exception_unaligned_load.S.inc index 553fe84..5540f72 100644 --- a/core/exception_unaligned_load.S.inc +++ b/core/exception_unaligned_load.S.inc @@ -40,14 +40,10 @@ InnerLoadStoreExceptionHandler: l32i a4, a2, 4 src a2, a4, a3 // a2 now instruction that failed - /* Check if a2 matches l16ui, l16si or l8ui opcode */ - movi a3, 0x00700F /* opcode mask */ + /* check for l8ui opcode 0x000002, or branch to check l16 */ + movi a3, 0x00700F /* opcode mask for l8ui/l16si/l16ui */ and a3, a2, a3 - - movi a4, 0x001002 /* l16si or l16ui opcode after masking */ - beq a3, a4, .Lcan_fix_16bit - - bnei a3, 0x000002, .Lcant_fix /* no l8ui opcode, then can't fix */ + bnei a3, 0x000002, .Lcheck_fix_16bit movi a5, 0xFF .Lcan_fix: @@ -107,12 +103,15 @@ DoubleExceptionLoadStoreHandler: rsr.epc2 a2 j InnerLoadStoreExceptionHandler -/* Load mask for an l16si/16ui instruction that needs loading +/* Check the load instruction a2 for an l16si/16ui instruction First test for a signed vs unsigned load. a2 is the instruction, need to load a5 with the mask to use */ -.Lcan_fix_16bit: +.Lcheck_fix_16bit: + movi a4, 0x001002 /* l16si or l16ui opcode after masking */ + bne a3, a4, .Lcant_fix + bbsi a2, 15, .Lcan_fix_16bit_signed movi a5, 0xFFFF j .Lcan_fix From f47aa77982509d14bcc84cd47ec38f588b6ac832 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 15 Sep 2015 15:09:42 +1000 Subject: [PATCH 22/56] Moved DoubleLoadStorageHandler to end of functions, improve fast path l8ui performance This allows a conditional branch that previously required a full jump instruction not to require it. --- core/exception_unaligned_load.S.inc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/exception_unaligned_load.S.inc b/core/exception_unaligned_load.S.inc index 5540f72..03c9830 100644 --- a/core/exception_unaligned_load.S.inc +++ b/core/exception_unaligned_load.S.inc @@ -94,15 +94,6 @@ InnerLoadStoreExceptionHandler: rfe - .literal_position -/* "Fix" LoadStoreException exceptions that are l8/l16 from an Instruction region, - DoubleException exception variant (ie load happened in a level1 exception handler). */ -DoubleExceptionLoadStoreHandler: - addi sp, sp, -0x18 - s32i a2, sp, 0x08 - rsr.epc2 a2 - j InnerLoadStoreExceptionHandler - /* Check the load instruction a2 for an l16si/16ui instruction First test for a signed vs unsigned load. @@ -187,4 +178,13 @@ DoubleExceptionLoadStoreHandler: wsr.excsave1 a4 j .Lafter_write_value + .literal_position +/* "Fix" LoadStoreException exceptions that are l8/l16 from an Instruction region, + DoubleException exception variant (ie load happened in a level1 exception handler). */ +DoubleExceptionLoadStoreHandler: + addi sp, sp, -0x18 + s32i a2, sp, 0x08 + rsr.epc2 a2 + j InnerLoadStoreExceptionHandler + /* End of InnerUserLoadStoreExceptionHandler */ From 4c89a0574b97a893dc7984431a5a4257298907d3 Mon Sep 17 00:00:00 2001 From: Alex Stewart Date: Sat, 19 Sep 2015 15:16:44 -0700 Subject: [PATCH 23/56] Add sanity-test suite to unaligned_load.c Tests are designed to methodically exercise all code paths/opcodes/offsets/etc. --- .../unaligned_load/unaligned_load.c | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/examples/experiments/unaligned_load/unaligned_load.c b/examples/experiments/unaligned_load/unaligned_load.c index ddf251b..3cfe471 100644 --- a/examples/experiments/unaligned_load/unaligned_load.c +++ b/examples/experiments/unaligned_load/unaligned_load.c @@ -125,6 +125,7 @@ void test_string(const char *string, char *label, bool evict_cache) static void test_doubleexception(); static void test_sign_extension(); +void sanity_tests(void); void user_init(void) { @@ -134,6 +135,7 @@ void user_init(void) 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); @@ -189,3 +191,126 @@ static void test_sign_extension() printf("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]); } } + +/* 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"); +} From a3d7732da8d25b40e23b41d4264eb3e578b74803 Mon Sep 17 00:00:00 2001 From: Alex Stewart Date: Sat, 19 Sep 2015 20:03:22 -0700 Subject: [PATCH 24/56] unaligned_load.c: Added more naive_strcpy tests Added tests for naive_strcpy using a variety of different regs, as execution time can depend on which register is being used. --- .../unaligned_load/unaligned_load.c | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/examples/experiments/unaligned_load/unaligned_load.c b/examples/experiments/unaligned_load/unaligned_load.c index 3cfe471..d2d132f 100644 --- a/examples/experiments/unaligned_load/unaligned_load.c +++ b/examples/experiments/unaligned_load/unaligned_load.c @@ -65,6 +65,84 @@ void test_naive_strcpy(const char *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 @@ -118,6 +196,12 @@ void test_string(const char *string, char *label, bool 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); From 372827ac4217f0df39cc9b688d5d75a3d0d97a4f Mon Sep 17 00:00:00 2001 From: Michael Jacobsen Date: Thu, 30 Jul 2015 19:34:13 +0200 Subject: [PATCH 25/56] Mostly updated header files for use in C++ --- axtls/include/version.h | 2 +- common.mk | 17 ++++++++++++----- core/include/common_macros.h | 6 +++++- include/espressif/esp8266/esp8266.h | 8 ++++++++ include/espressif/esp_misc.h | 8 ++++++++ include/espressif/esp_softap.h | 8 ++++++++ include/espressif/esp_sta.h | 8 ++++++++ include/espressif/esp_system.h | 8 ++++++++ include/espressif/esp_timer.h | 8 ++++++++ include/espressif/esp_wifi.h | 10 +++++++++- include/espressif/sdk_private.h | 9 +++++++++ include/espressif/spi_flash.h | 10 ++++++++++ ld/eagle.app.v6.ld | 3 +++ 13 files changed, 97 insertions(+), 8 deletions(-) diff --git a/axtls/include/version.h b/axtls/include/version.h index 43c7194..8fee21b 100644 --- a/axtls/include/version.h +++ b/axtls/include/version.h @@ -5,6 +5,6 @@ #ifndef _VERSION_H -#define AXTLS_VERSION "esp-open-rtos axTLS "GITSHORTREV +#define AXTLS_VERSION "esp-open-rtos axTLS " GITSHORTREV #endif diff --git a/common.mk b/common.mk index a893e29..00a77dd 100644 --- a/common.mk +++ b/common.mk @@ -94,14 +94,19 @@ OWN_LIBC ?= 1 # Note: you will need a recent esp ENTRY_SYMBOL ?= call_user_start -CFLAGS = -Wall -Werror -Wl,-EL -nostdlib -mlongcalls -mtext-section-literals -std=gnu99 $(CPPFLAGS) +# Common flags for both C & C++_ +C_CXX_FLAGS = -Wall -Werror -Wl,-EL -nostdlib -mlongcalls -mtext-section-literals $(CPPFLAGS) +# Flags for C only +CFLAGS = $(C_CXX_FLAGS) -std=gnu99 +# Flags for C++ only +CXXFLAGS = $(C_CXX_FLAGS) -fno-exceptions LDFLAGS = -nostdlib -Wl,--no-check-sections -Wl,-L$(BUILD_DIR)sdklib -Wl,-L$(ROOT)lib -u $(ENTRY_SYMBOL) -Wl,-static -Wl,-Map=build/${PROGRAM}.map $(EXTRA_LDFLAGS) ifeq ($(FLAVOR),debug) - CFLAGS += -g -O0 + C_CXX_FLAGS += -g -O0 LDFLAGS += -g -O0 else - CFLAGS += -g -O2 + C_CXX_FLAGS += -g -O2 LDFLAGS += -g -O2 endif @@ -138,8 +143,8 @@ endif LINKER_SCRIPTS_PROCESSED = $(addprefix $(LD_DIR),$(LINKER_SCRIPTS)) # derive various parts of compiler/linker arguments -SDK_LIB_ARGS = $(addprefix -l,$(SDK_LIBS)) -LIB_ARGS = $(addprefix -l,$(LIBS)) +SDK_LIB_ARGS = $(addprefix -l,$(SDK_LIBS)) +LIB_ARGS = $(addprefix -l,$(LIBS)) PROGRAM_OUT = $(BUILD_DIR)$(PROGRAM).out LDFLAGS += $(addprefix -T,$(LINKER_SCRIPTS_PROCESSED)) @@ -228,7 +233,9 @@ $(1)_MAKEFILE ?= $(lastword $(MAKEFILE_LIST)) ### determine compiler arguments ### $(1)_CFLAGS ?= $(CFLAGS) +$(1)_CXXFLAGS ?= $(CXXFLAGS) $(1)_CC_ARGS = $(Q) $(CC) $$(addprefix -I,$$(INC_DIRS)) $$(addprefix -I,$$($(1)_INC_DIR)) $$($(1)_CFLAGS) +$(1)_CXX_ARGS = $(Q) $(C++) $$(addprefix -I,$$(INC_DIRS)) $$(addprefix -I,$$($(1)_INC_DIR)) $$($(1)_CXXFLAGS) $(1)_AR = $(call lc,$(BUILD_DIR)$(1).a) $$($(1)_OBJ_DIR)%.o: $$($(1)_REAL_ROOT)%.c $$($(1)_MAKEFILE) $(wildcard $(ROOT)*.mk) | $$($(1)_SRC_DIR) diff --git a/core/include/common_macros.h b/core/include/common_macros.h index b0c7a08..b0d89e1 100644 --- a/core/include/common_macros.h +++ b/core/include/common_macros.h @@ -45,7 +45,11 @@ Important to note: IROM flash can only be accessed via 32-bit word aligned reads. It's up to the user of this attribute to ensure this. */ -#define IROM __attribute__((section(".irom0.literal"))) const +#ifdef __cplusplus + #define IROM __attribute__((section(".irom0.literal"))) +#else + #define IROM __attribute__((section(".irom0.literal"))) const +#endif #define INLINED inline static __attribute__((always_inline)) __attribute__((unused)) diff --git a/include/espressif/esp8266/esp8266.h b/include/espressif/esp8266/esp8266.h index 2d8b21b..4bf1a7a 100644 --- a/include/espressif/esp8266/esp8266.h +++ b/include/espressif/esp8266/esp8266.h @@ -6,6 +6,10 @@ #ifndef __ESP8266_H__ #define __ESP8266_H__ +#ifdef __cplusplus +extern "C" { +#endif + #include "ets_sys.h" #include "eagle_soc.h" #include "gpio_register.h" @@ -14,5 +18,9 @@ #include "timer_register.h" #include "uart_register.h" +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/espressif/esp_misc.h b/include/espressif/esp_misc.h index d8ce65e..6490fa5 100644 --- a/include/espressif/esp_misc.h +++ b/include/espressif/esp_misc.h @@ -8,6 +8,10 @@ #include "lwip/ip_addr.h" +#ifdef __cplusplus +extern "C" { +#endif + #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" @@ -23,4 +27,8 @@ void sdk_os_delay_us(uint16_t us); void sdk_os_install_putc1(void (*p)(char c)); void sdk_os_putc(char c); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/espressif/esp_softap.h b/include/espressif/esp_softap.h index 44f06cc..8a81aef 100644 --- a/include/espressif/esp_softap.h +++ b/include/espressif/esp_softap.h @@ -6,6 +6,10 @@ #ifndef __ESP_SOFTAP_H__ #define __ESP_SOFTAP_H__ +#ifdef __cplusplus +extern "C" { +#endif + struct sdk_softap_config { uint8_t ssid[32]; uint8_t password[64]; @@ -20,4 +24,8 @@ struct sdk_softap_config { bool sdk_wifi_softap_get_config(struct sdk_softap_config *config); bool sdk_wifi_softap_set_config(struct sdk_softap_config *config); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/espressif/esp_sta.h b/include/espressif/esp_sta.h index 8b9059a..0c94a6c 100644 --- a/include/espressif/esp_sta.h +++ b/include/espressif/esp_sta.h @@ -10,6 +10,10 @@ #include "queue.h" +#ifdef __cplusplus +extern "C" { +#endif + struct sdk_station_config { uint8_t ssid[32]; uint8_t password[64]; @@ -68,4 +72,8 @@ enum { uint8_t sdk_wifi_station_get_connect_status(void); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/espressif/esp_system.h b/include/espressif/esp_system.h index 93eea64..e37263e 100644 --- a/include/espressif/esp_system.h +++ b/include/espressif/esp_system.h @@ -6,6 +6,10 @@ #ifndef __ESP_SYSTEM_H__ #define __ESP_SYSTEM_H__ +#ifdef __cplusplus +extern "C" { +#endif + enum sdk_rst_reason { DEFAULT_RST = 0, WDT_RST = 1, @@ -54,4 +58,8 @@ bool sdk_system_rtc_mem_write(uint8_t dst, const void *src, uint16_t n); void sdk_system_uart_swap(void); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/espressif/esp_timer.h b/include/espressif/esp_timer.h index 6f05547..0ceb131 100644 --- a/include/espressif/esp_timer.h +++ b/include/espressif/esp_timer.h @@ -6,6 +6,10 @@ #ifndef __ESP_TIMER_H__ #define __ESP_TIMER_H__ +#ifdef __cplusplus +extern "C" { +#endif + /* timer related */ typedef void sdk_os_timer_func_t(void *timer_arg); @@ -19,4 +23,8 @@ typedef struct _os_timer_t { void *timer_arg; } sdk_os_timer_t; +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/espressif/esp_wifi.h b/include/espressif/esp_wifi.h index 5dae103..5d9ba19 100644 --- a/include/espressif/esp_wifi.h +++ b/include/espressif/esp_wifi.h @@ -13,6 +13,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + enum { NULL_MODE = 0, STATION_MODE, @@ -67,7 +71,11 @@ enum sdk_phy_mode { PHY_MODE_11N = 3 }; -enum phy_mode sdk_wifi_get_phy_mode(void); +enum sdk_phy_mode sdk_wifi_get_phy_mode(void); bool sdk_wifi_set_phy_mode(enum sdk_phy_mode mode); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/espressif/sdk_private.h b/include/espressif/sdk_private.h index 4340999..fa643a7 100644 --- a/include/espressif/sdk_private.h +++ b/include/espressif/sdk_private.h @@ -15,6 +15,11 @@ #define SDK_PRIVATE_H #include + +#ifdef __cplusplus +extern "C" { +#endif + struct ip_addr; /********************************************* @@ -49,4 +54,8 @@ void sdk_system_station_got_ip_set(struct ip_addr *ip_addr, struct ip_addr *sn_m */ void sdk_system_pp_recycle_rx_pkt(void *eb); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/espressif/spi_flash.h b/include/espressif/spi_flash.h index 1805cc7..224bce4 100644 --- a/include/espressif/spi_flash.h +++ b/include/espressif/spi_flash.h @@ -6,6 +6,10 @@ #ifndef __SPI_FLASH_H__ #define __SPI_FLASH_H__ +#ifdef __cplusplus +extern "C" { +#endif + typedef enum { SPI_FLASH_RESULT_OK, SPI_FLASH_RESULT_ERR, @@ -21,6 +25,7 @@ sdk_SpiFlashOpResult sdk_spi_flash_erase_sector(uint16_t sec); sdk_SpiFlashOpResult sdk_spi_flash_write(uint32_t des_addr, uint32_t *src_addr, uint32_t size); sdk_SpiFlashOpResult sdk_spi_flash_read(uint32_t src_addr, uint32_t *des_addr, uint32_t size); + /* SDK uses this structure internally to account for flash size. chip_size field is initialised during startup from the flash size @@ -42,4 +47,9 @@ typedef struct { extern sdk_flashchip_t sdk_flashchip; + +#ifdef __cplusplus +} +#endif + #endif diff --git a/ld/eagle.app.v6.ld b/ld/eagle.app.v6.ld index 412441d..566ad67 100644 --- a/ld/eagle.app.v6.ld +++ b/ld/eagle.app.v6.ld @@ -166,11 +166,14 @@ SECTIONS *(.gnu.linkonce.e.*) *(.gnu.version_r) *(.eh_frame) + . = (. + 3) & ~ 3; /* C++ constructor and destructor tables, properly ordered: */ + __init_array_start = ABSOLUTE(.); KEEP (*crtbegin.o(.ctors)) KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) + __init_array_end = ABSOLUTE(.); KEEP (*crtbegin.o(.dtors)) KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) KEEP (*(SORT(.dtors.*))) From cc97067fa1e1ff207434f43072da8916677b05ba Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 10 Aug 2015 15:51:57 +1000 Subject: [PATCH 26/56] Add C++ support to Makefile, and proof-of-concept simple.cpp example This is a work in progress based on @mikejac's work. Missing: * No 'new' operator. * I don't think STL is currently supported. --- FreeRTOS/Source/portable/esp8266/port.c | 11 ++++++ common.mk | 14 +++++-- core/sdk_compat.c | 15 +++++++ examples/simple_cplusplus/Makefile | 3 ++ examples/simple_cplusplus/simple.cpp | 52 +++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 examples/simple_cplusplus/Makefile create mode 100644 examples/simple_cplusplus/simple.cpp diff --git a/FreeRTOS/Source/portable/esp8266/port.c b/FreeRTOS/Source/portable/esp8266/port.c index 1632fe1..71c6658 100644 --- a/FreeRTOS/Source/portable/esp8266/port.c +++ b/FreeRTOS/Source/portable/esp8266/port.c @@ -178,6 +178,9 @@ void xPortSysTickHandle (void) //OpenNMI(); } +static bool sdk_compat_initialised; +void sdk_compat_initialise(void); + /* * See header file for description. */ @@ -186,6 +189,14 @@ portBASE_TYPE xPortStartScheduler( void ) _xt_isr_attach(INUM_SOFT, SV_ISR); _xt_isr_unmask(BIT(INUM_SOFT)); + /* ENORMOUS HACK: Call the sdk_compat_initialise() function. + This can be removed happily once we have open source startup code. + */ + if(!sdk_compat_initialised) { + sdk_compat_initialised = true; + sdk_compat_initialise(); + } + /* Initialize system tick timer interrupt and schedule the first tick. */ sdk__xt_tick_timer_init(); diff --git a/common.mk b/common.mk index 00a77dd..7361f70 100644 --- a/common.mk +++ b/common.mk @@ -220,13 +220,15 @@ $(1)_DEFAULT_ROOT := $(dir $(lastword $(MAKEFILE_LIST))) $(1)_ROOT ?= $$($(1)_DEFAULT_ROOT) $(1)_OBJ_DIR = $(call lc,$(BUILD_DIR)$(1)/) ### determine source files and object files ### -$(1)_SRC_FILES ?= $$(foreach sdir,$$($(1)_SRC_DIR), \ - $$(wildcard $$(sdir)/*.c) $$(wildcard $$(sdir)/*.S)) \ +$(1)_SRC_FILES ?= $$(foreach sdir,$$($(1)_SRC_DIR), \ + $$(wildcard $$(sdir)/*.c) $$(wildcard $$(sdir)/*.S) \ + $$(wildcard $$(sdir)/*.cpp)) \ $$($(1)_EXTRA_SRC_FILES) $(1)_REAL_SRC_FILES = $$(foreach sfile,$$($(1)_SRC_FILES),$$(realpath $$(sfile))) $(1)_REAL_ROOT = $$(realpath $$($(1)_ROOT)) # patsubst here substitutes real component root path for the relative OBJ_DIR path, making things short again -$(1)_OBJ_FILES_C = $$(patsubst $$($(1)_REAL_ROOT)%.c,$$($(1)_OBJ_DIR)%.o,$$($(1)_REAL_SRC_FILES)) +$(1)_OBJ_FILES_CXX = $$(patsubst $$($(1)_REAL_ROOT)%.cpp,$$($(1)_OBJ_DIR)%.o,$$($(1)_REAL_SRC_FILES)) +$(1)_OBJ_FILES_C = $$(patsubst $$($(1)_REAL_ROOT)%.c,$$($(1)_OBJ_DIR)%.o,$$($(1)_OBJ_FILES_CXX)) $(1)_OBJ_FILES = $$(patsubst $$($(1)_REAL_ROOT)%.S,$$($(1)_OBJ_DIR)%.o,$$($(1)_OBJ_FILES_C)) # the last included makefile is our component's component.mk makefile (rebuild the component if it changes) $(1)_MAKEFILE ?= $(lastword $(MAKEFILE_LIST)) @@ -244,6 +246,12 @@ $$($(1)_OBJ_DIR)%.o: $$($(1)_REAL_ROOT)%.c $$($(1)_MAKEFILE) $(wildcard $(ROOT)* $$($(1)_CC_ARGS) -c $$< -o $$@ $$($(1)_CC_ARGS) -MM -MT $$@ -MF $$(@:.o=.d) $$< +$$($(1)_OBJ_DIR)%.o: $$($(1)_REAL_ROOT)%.cpp $$($(1)_MAKEFILE) $(wildcard $(ROOT)*.mk) | $$($(1)_SRC_DIR) + $(vecho) "C++ $$<" + $(Q) mkdir -p $$(dir $$@) + $$($(1)_CXX_ARGS) -c $$< -o $$@ + $$($(1)_CXX_ARGS) -MM -MT $$@ -MF $$(@:.o=.d) $$< + $$($(1)_OBJ_DIR)%.o: $$($(1)_REAL_ROOT)%.S $$($(1)_MAKEFILE) $(wildcard $(ROOT)*.mk) | $$($(1)_SRC_DIR) $(vecho) "AS $$<" $(Q) mkdir -p $$(dir $$@) diff --git a/core/sdk_compat.c b/core/sdk_compat.c index d141708..b6bb6b3 100644 --- a/core/sdk_compat.c +++ b/core/sdk_compat.c @@ -14,3 +14,18 @@ void IRAM *zalloc(size_t nbytes) { return calloc(1, nbytes); } + +extern void (*__init_array_start)(void); +extern void (*__init_array_end)(void); + +/* Do things which should be done as part of the startup code, but aren't. + + Can be replaced with _start() once we have open source startup code. +*/ +void sdk_compat_initialise() +{ + /* Call C++ constructors or C functions marked with __attribute__((constructor)) */ + void (**p)(void); + for ( p = &__init_array_start; p != &__init_array_end; ++p) + (*p)(); +} diff --git a/examples/simple_cplusplus/Makefile b/examples/simple_cplusplus/Makefile new file mode 100644 index 0000000..717b163 --- /dev/null +++ b/examples/simple_cplusplus/Makefile @@ -0,0 +1,3 @@ +# Simple makefile for simple example +PROGRAM=simple +include ../../common.mk diff --git a/examples/simple_cplusplus/simple.cpp b/examples/simple_cplusplus/simple.cpp new file mode 100644 index 0000000..dada441 --- /dev/null +++ b/examples/simple_cplusplus/simple.cpp @@ -0,0 +1,52 @@ +/* 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 %ld\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); + while(1) { + Counter &counter = rand() % 2 ? static_counter : local_counter; + counter.Increment(); + printf("local counter %ld static counter %ld\r\n", local_counter.getCount(), + static_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); +} From 94fabc6ceb58b7acf4f4085f110b8e8e7adfe3a7 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 13 Aug 2015 08:32:34 +1000 Subject: [PATCH 27/56] Add basic C++ new/delete operators, as contributed by @mikejac in #24 --- core/cplusplus_operators.cpp | 25 +++++++++++++++++++++++++ examples/simple_cplusplus/simple.cpp | 20 ++++++++++++++++---- 2 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 core/cplusplus_operators.cpp diff --git a/core/cplusplus_operators.cpp b/core/cplusplus_operators.cpp new file mode 100644 index 0000000..86f4477 --- /dev/null +++ b/core/cplusplus_operators.cpp @@ -0,0 +1,25 @@ +/* Part of esp-open-rtos + * BSD Licensed as described in the file LICENSE + */ +#include +#include + +void *operator new(size_t size) +{ + return malloc(size); +} + +void *operator new[](size_t size) +{ + return malloc(size); +} + +void operator delete(void * ptr) +{ + free(ptr); +} + +void operator delete[](void * ptr) +{ + free(ptr); +} diff --git a/examples/simple_cplusplus/simple.cpp b/examples/simple_cplusplus/simple.cpp index dada441..8d964fa 100644 --- a/examples/simple_cplusplus/simple.cpp +++ b/examples/simple_cplusplus/simple.cpp @@ -35,11 +35,23 @@ static Counter static_counter(99); void task1(void *pvParameters) { Counter local_counter = Counter(12); + Counter *new_counter = new Counter(24); while(1) { - Counter &counter = rand() % 2 ? static_counter : local_counter; - counter.Increment(); - printf("local counter %ld static counter %ld\r\n", local_counter.getCount(), - static_counter.getCount()); + 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 %ld static counter %ld newly allocated counter %ld\r\n", local_counter.getCount(), + static_counter.getCount(), new_counter->getCount()); vTaskDelay(100); } } From 627b78331accc07aa62af94dc23fce319ceff6c8 Mon Sep 17 00:00:00 2001 From: Michael Jacobsen Date: Wed, 19 Aug 2015 08:38:15 +0200 Subject: [PATCH 28/56] Added C++ base components and example --- common.mk | 4 +- examples/cpp_01_tasks/Makefile | 3 + examples/cpp_01_tasks/main.cpp | 100 +++++++++++++++++++++++++++ extras/cplusplus/component.mk | 3 + extras/cplusplus/cplusplus.hpp | 68 +++++++++++++++++++ extras/thread/component.mk | 3 + extras/thread/mutex.hpp | 90 +++++++++++++++++++++++++ extras/thread/queue.hpp | 120 +++++++++++++++++++++++++++++++++ extras/thread/task.hpp | 99 +++++++++++++++++++++++++++ extras/timer/component.mk | 3 + extras/timer/countdown.hpp | 95 ++++++++++++++++++++++++++ 11 files changed, 586 insertions(+), 2 deletions(-) create mode 100644 examples/cpp_01_tasks/Makefile create mode 100644 examples/cpp_01_tasks/main.cpp create mode 100644 extras/cplusplus/component.mk create mode 100644 extras/cplusplus/cplusplus.hpp create mode 100644 extras/thread/component.mk create mode 100644 extras/thread/mutex.hpp create mode 100644 extras/thread/queue.hpp create mode 100644 extras/thread/task.hpp create mode 100644 extras/timer/component.mk create mode 100644 extras/timer/countdown.hpp diff --git a/common.mk b/common.mk index 7361f70..2880752 100644 --- a/common.mk +++ b/common.mk @@ -99,7 +99,7 @@ C_CXX_FLAGS = -Wall -Werror -Wl,-EL -nostdlib -mlongcalls -mtext-section-lit # Flags for C only CFLAGS = $(C_CXX_FLAGS) -std=gnu99 # Flags for C++ only -CXXFLAGS = $(C_CXX_FLAGS) -fno-exceptions +CXXFLAGS = $(C_CXX_FLAGS) -fno-exceptions -fno-rtti LDFLAGS = -nostdlib -Wl,--no-check-sections -Wl,-L$(BUILD_DIR)sdklib -Wl,-L$(ROOT)lib -u $(ENTRY_SYMBOL) -Wl,-static -Wl,-Map=build/${PROGRAM}.map $(EXTRA_LDFLAGS) ifeq ($(FLAVOR),debug) @@ -177,7 +177,7 @@ IMGTOOL_ARGS=-$(IMGTOOL_FLASH_SIZE) -$(FLASH_MODE) -$(FLASH_SPEED) # Placing $(PROGRAM_DIR) and $(PROGRAM_DIR)include first allows # programs to have their own copies of header config files for components # , which is useful for overriding things. -INC_DIRS = $(PROGRAM_DIR) $(PROGRAM_DIR)include $(ROOT)include +INC_DIRS = $(PROGRAM_DIR) $(PROGRAM_DIR)include $(ROOT)include $(ROOT)extras ifeq ($(OWN_LIBC),1) INC_DIRS += $(ROOT)libc/xtensa-lx106-elf/include diff --git a/examples/cpp_01_tasks/Makefile b/examples/cpp_01_tasks/Makefile new file mode 100644 index 0000000..458932f --- /dev/null +++ b/examples/cpp_01_tasks/Makefile @@ -0,0 +1,3 @@ +# Simple makefile for simple example +PROGRAM=cpp_01_tasks +include ../../common.mk diff --git a/examples/cpp_01_tasks/main.cpp b/examples/cpp_01_tasks/main.cpp new file mode 100644 index 0000000..133d1c5 --- /dev/null +++ b/examples/cpp_01_tasks/main.cpp @@ -0,0 +1,100 @@ +/* + * ESP8266 FreeRTOS Firmware + * Copyright (C) 2015 Michael Jacobsen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * https://github.com/SuperHouse/esp-open-rtos + * + */ + +#include "cplusplus/cplusplus.hpp" +#include "thread/task.hpp" +#include "thread/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 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 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 %lu\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 MyQueue; + +/** + * + */ +extern "C" void user_init(void) +{ + sdk_uart_div_modify(0, UART_CLK_FREQ / 115200); + + MyQueue.create(10); + + task_1.queue = MyQueue; + task_2.queue = MyQueue; + + task_1.task_create("tsk1"); + task_2.task_create("tsk2"); +} \ No newline at end of file diff --git a/extras/cplusplus/component.mk b/extras/cplusplus/component.mk new file mode 100644 index 0000000..3f5673d --- /dev/null +++ b/extras/cplusplus/component.mk @@ -0,0 +1,3 @@ +# Component makefile for extras/cplusplus + +INC_DIRS += $(ROOT)extras diff --git a/extras/cplusplus/cplusplus.hpp b/extras/cplusplus/cplusplus.hpp new file mode 100644 index 0000000..cc58031 --- /dev/null +++ b/extras/cplusplus/cplusplus.hpp @@ -0,0 +1,68 @@ +/* + * ESP8266 FreeRTOS Firmware + * Copyright (C) 2015 Michael Jacobsen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * https://github.com/SuperHouse/esp-open-rtos + * + */ + +#ifndef COM_THOLUSI_ESP_OPEN_RTOS_CPLUSPLUS_HPP +#define COM_THOLUSI_ESP_OPEN_RTOS_CPLUSPLUS_HPP + +#include + +/****************************************************************************************************************** + * C++ new and delete operators + * + */ + +/** + * + * @param size + * @return + */ +inline void *operator new(size_t size) +{ + return malloc(size); +} +/** + * + * @param size + * @return + */ +inline void *operator new[](size_t size) +{ + return malloc(size); +} +/** + * + * @param ptr + */ +inline void operator delete(void * ptr) +{ + free(ptr); +} +/** + * + * @param ptr + */ +inline void operator delete[](void * ptr) +{ + free(ptr); +} + +#endif /* COM_THOLUSI_ESP_OPEN_RTOS_CPLUSPLUS_HPP */ + diff --git a/extras/thread/component.mk b/extras/thread/component.mk new file mode 100644 index 0000000..46193ef --- /dev/null +++ b/extras/thread/component.mk @@ -0,0 +1,3 @@ +# Component makefile for extras/thread + +INC_DIRS += $(ROOT)extras diff --git a/extras/thread/mutex.hpp b/extras/thread/mutex.hpp new file mode 100644 index 0000000..d3db1da --- /dev/null +++ b/extras/thread/mutex.hpp @@ -0,0 +1,90 @@ +/* + * ESP8266 FreeRTOS Firmware + * Copyright (C) 2015 Michael Jacobsen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * https://github.com/SuperHouse/esp-open-rtos + * + */ + +#ifndef COM_THOLUSI_ESP_OPEN_RTOS_MUTEX_HPP +#define COM_THOLUSI_ESP_OPEN_RTOS_MUTEX_HPP + +#include "semphr.h" + +namespace esp_open_rtos { +namespace thread { + +/****************************************************************************************************************** + * class mutex_t + * + */ +class mutex_t +{ +public: + /** + * + */ + inline mutex_t() + { + mutex = xSemaphoreCreateMutex(); + } + /** + * + */ + inline ~mutex_t() + { + vQueueDelete(mutex); + } + /** + * + * @return + */ + inline int lock() + { + return (xSemaphoreTake(mutex, portMAX_DELAY) == pdTRUE) ? 0 : -1; + } + /** + * + * @param ms + * @return + */ + inline int try_lock(unsigned long ms) + { + return (xSemaphoreTake(mutex, ms / portTICK_RATE_MS) == pdTRUE) ? 0 : -1; + } + /** + * + * @return + */ + inline int unlock() + { + return (xSemaphoreGive(mutex) == pdTRUE) ? 0 : -1; + } + +private: + xSemaphoreHandle mutex; + + // Disable copy construction and assignment. + mutex_t (const mutex_t&); + const mutex_t &operator = (const mutex_t&); +}; + +} //namespace thread { +} //namespace esp_open_rtos { + + +#endif /* COM_THOLUSI_ESP_OPEN_RTOS_MUTEX_HPP */ + diff --git a/extras/thread/queue.hpp b/extras/thread/queue.hpp new file mode 100644 index 0000000..fd14166 --- /dev/null +++ b/extras/thread/queue.hpp @@ -0,0 +1,120 @@ +/* + * ESP8266 FreeRTOS Firmware + * Copyright (C) 2015 Michael Jacobsen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * https://github.com/SuperHouse/esp-open-rtos + * + */ + +#ifndef COM_THOLUSI_ESP_OPEN_RTOS_QUEUE_HPP +#define COM_THOLUSI_ESP_OPEN_RTOS_QUEUE_HPP + +#include "FreeRTOS.h" +#include "queue.h" + +namespace esp_open_rtos { +namespace thread { + +/****************************************************************************************************************** + * class queue_t + * + */ +template +class queue_t +{ +public: + /** + * + */ + inline queue_t() + { + queue = 0; + } + /** + * + * @param uxQueueLength + * @param uxItemSize + * @return + */ + inline int create(unsigned portBASE_TYPE uxQueueLength) + { + queue = xQueueCreate(uxQueueLength, sizeof(Data)); + + if(queue == NULL) { + return -1; + } + else { + return 0; + } + } + /** + * + * @param data + * @param ms + * @return + */ + inline void destroy() + { + vQueueDelete(queue); + queue = 0; + } + /** + * + * @param data + * @param ms + * @return + */ + inline int post(const Data& data, unsigned long ms = 0) + { + return (xQueueSend(queue, &data, ms / portTICK_RATE_MS) == pdTRUE) ? 0 : -1; + } + /** + * + * @param data + * @param ms + * @return + */ + inline int receive(Data& data, unsigned long ms = 0) + { + return (xQueueReceive(queue, &data, ms / portTICK_RATE_MS) == pdTRUE) ? 0 : -1; + } + /** + * + * @param other + * @return + */ + const queue_t &operator = (const queue_t& other) + { + if(this != &other) { // protect against invalid self-assignment + queue = other.queue; + } + + return *this; + } + +private: + xQueueHandle queue; + + // Disable copy construction. + queue_t (const queue_t&); +}; + +} //namespace thread { +} //namespace esp_open_rtos { + + +#endif /* COM_THOLUSI_ESP_OPEN_RTOS_QUEUE_HPP */ + diff --git a/extras/thread/task.hpp b/extras/thread/task.hpp new file mode 100644 index 0000000..dc527f0 --- /dev/null +++ b/extras/thread/task.hpp @@ -0,0 +1,99 @@ +/* + * ESP8266 FreeRTOS Firmware + * Copyright (C) 2015 Michael Jacobsen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * https://github.com/SuperHouse/esp-open-rtos + * + */ + +#ifndef COM_THOLUSI_ESP_OPEN_RTOS_TASK_HPP +#define COM_THOLUSI_ESP_OPEN_RTOS_TASK_HPP + +#include "FreeRTOS.h" +#include "task.h" + +namespace esp_open_rtos { +namespace thread { + +/****************************************************************************************************************** + * task_t + * + */ +class task_t +{ +public: + /** + * + */ + task_t() + {} + /** + * + * @param pcName + * @param usStackDepth + * @param uxPriority + * @return + */ + int task_create(const char* const pcName, unsigned short usStackDepth = 256, unsigned portBASE_TYPE uxPriority = 2) + { + return xTaskCreate(task_t::_task, (signed char *)pcName, usStackDepth, this, uxPriority, NULL); + } + +protected: + /** + * + * @param ms + */ + void sleep(unsigned long ms) + { + vTaskDelay(ms / portTICK_RATE_MS); + } + /** + * + * @return + */ + inline unsigned long millis() + { + return xTaskGetTickCount() * portTICK_RATE_MS; + } + +private: + /** + * + */ + virtual void task() = 0; + /** + * + * @param pvParameters + */ + static void _task(void* pvParameters) + { + if(pvParameters != 0) { + ((task_t*)(pvParameters))->task(); + } + } + + // no copy and no = operator + task_t(const task_t&); + task_t &operator=(const task_t&); +}; + +} //namespace thread { +} //namespace esp_open_rtos { + + +#endif /* COM_THOLUSI_ESP_OPEN_RTOS_TASK_HPP */ + diff --git a/extras/timer/component.mk b/extras/timer/component.mk new file mode 100644 index 0000000..255ebae --- /dev/null +++ b/extras/timer/component.mk @@ -0,0 +1,3 @@ +# Component makefile for extras/timer + +INC_DIRS += $(ROOT)extras diff --git a/extras/timer/countdown.hpp b/extras/timer/countdown.hpp new file mode 100644 index 0000000..ff1a2bf --- /dev/null +++ b/extras/timer/countdown.hpp @@ -0,0 +1,95 @@ +/* + * ESP8266 FreeRTOS Firmware + * Copyright (C) 2015 Michael Jacobsen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * https://github.com/SuperHouse/esp-open-rtos + * + */ + +#ifndef COM_THOLUSI_ESP_OPEN_RTOS_TIMER_HPP +#define COM_THOLUSI_ESP_OPEN_RTOS_TIMER_HPP + +#include "FreeRTOS.h" +#include "task.h" + +namespace esp_open_rtos { +namespace timer { + +#define __millis() (xTaskGetTickCount() * portTICK_RATE_MS) + +/****************************************************************************************************************** + * countdown_t + * + */ +class countdown_t +{ +public: + /** + * + */ + countdown_t() + { + interval_end_ms = 0L; + } + /** + * + * @param ms + */ + countdown_t(int ms) + { + countdown_ms(ms); + } + /** + * + * @return + */ + bool expired() + { + return (interval_end_ms > 0L) && (__millis() >= interval_end_ms); + } + /** + * + * @param ms + */ + void countdown_ms(unsigned long ms) + { + interval_end_ms = __millis() + ms; + } + /** + * + * @param seconds + */ + void countdown(int seconds) + { + countdown_ms((unsigned long)seconds * 1000L); + } + /** + * + * @return + */ + int left_ms() + { + return interval_end_ms - __millis(); + } + +private: + portTickType interval_end_ms; +}; + +} // namespace timer { +} // namespace esp_open_rtos { + +#endif From 63bbf92a76a47e31d27845e5a82be4614a9444e0 Mon Sep 17 00:00:00 2001 From: Michael Jacobsen Date: Wed, 19 Aug 2015 08:44:41 +0200 Subject: [PATCH 29/56] Header files adjustments --- extras/cplusplus/cplusplus.hpp | 6 +++--- extras/thread/mutex.hpp | 6 +++--- extras/thread/queue.hpp | 6 +++--- extras/thread/task.hpp | 6 +++--- extras/timer/countdown.hpp | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/extras/cplusplus/cplusplus.hpp b/extras/cplusplus/cplusplus.hpp index cc58031..a78e146 100644 --- a/extras/cplusplus/cplusplus.hpp +++ b/extras/cplusplus/cplusplus.hpp @@ -19,8 +19,8 @@ * */ -#ifndef COM_THOLUSI_ESP_OPEN_RTOS_CPLUSPLUS_HPP -#define COM_THOLUSI_ESP_OPEN_RTOS_CPLUSPLUS_HPP +#ifndef ESP_OPEN_RTOS_CPLUSPLUS_HPP +#define ESP_OPEN_RTOS_CPLUSPLUS_HPP #include @@ -64,5 +64,5 @@ inline void operator delete[](void * ptr) free(ptr); } -#endif /* COM_THOLUSI_ESP_OPEN_RTOS_CPLUSPLUS_HPP */ +#endif /* ESP_OPEN_RTOS_CPLUSPLUS_HPP */ diff --git a/extras/thread/mutex.hpp b/extras/thread/mutex.hpp index d3db1da..b4e56a4 100644 --- a/extras/thread/mutex.hpp +++ b/extras/thread/mutex.hpp @@ -19,8 +19,8 @@ * */ -#ifndef COM_THOLUSI_ESP_OPEN_RTOS_MUTEX_HPP -#define COM_THOLUSI_ESP_OPEN_RTOS_MUTEX_HPP +#ifndef ESP_OPEN_RTOS_MUTEX_HPP +#define ESP_OPEN_RTOS_MUTEX_HPP #include "semphr.h" @@ -86,5 +86,5 @@ private: } //namespace esp_open_rtos { -#endif /* COM_THOLUSI_ESP_OPEN_RTOS_MUTEX_HPP */ +#endif /* ESP_OPEN_RTOS_MUTEX_HPP */ diff --git a/extras/thread/queue.hpp b/extras/thread/queue.hpp index fd14166..e02bec6 100644 --- a/extras/thread/queue.hpp +++ b/extras/thread/queue.hpp @@ -19,8 +19,8 @@ * */ -#ifndef COM_THOLUSI_ESP_OPEN_RTOS_QUEUE_HPP -#define COM_THOLUSI_ESP_OPEN_RTOS_QUEUE_HPP +#ifndef ESP_OPEN_RTOS_QUEUE_HPP +#define ESP_OPEN_RTOS_QUEUE_HPP #include "FreeRTOS.h" #include "queue.h" @@ -116,5 +116,5 @@ private: } //namespace esp_open_rtos { -#endif /* COM_THOLUSI_ESP_OPEN_RTOS_QUEUE_HPP */ +#endif /* ESP_OPEN_RTOS_QUEUE_HPP */ diff --git a/extras/thread/task.hpp b/extras/thread/task.hpp index dc527f0..a8a5c5b 100644 --- a/extras/thread/task.hpp +++ b/extras/thread/task.hpp @@ -19,8 +19,8 @@ * */ -#ifndef COM_THOLUSI_ESP_OPEN_RTOS_TASK_HPP -#define COM_THOLUSI_ESP_OPEN_RTOS_TASK_HPP +#ifndef ESP_OPEN_RTOS_TASK_HPP +#define ESP_OPEN_RTOS_TASK_HPP #include "FreeRTOS.h" #include "task.h" @@ -95,5 +95,5 @@ private: } //namespace esp_open_rtos { -#endif /* COM_THOLUSI_ESP_OPEN_RTOS_TASK_HPP */ +#endif /* ESP_OPEN_RTOS_TASK_HPP */ diff --git a/extras/timer/countdown.hpp b/extras/timer/countdown.hpp index ff1a2bf..71dd55c 100644 --- a/extras/timer/countdown.hpp +++ b/extras/timer/countdown.hpp @@ -19,8 +19,8 @@ * */ -#ifndef COM_THOLUSI_ESP_OPEN_RTOS_TIMER_HPP -#define COM_THOLUSI_ESP_OPEN_RTOS_TIMER_HPP +#ifndef ESP_OPEN_RTOS_TIMER_HPP +#define ESP_OPEN_RTOS_TIMER_HPP #include "FreeRTOS.h" #include "task.h" From 028451fa8477905b249c3d8dfe2dab8d8b2a95a4 Mon Sep 17 00:00:00 2001 From: Michael Jacobsen Date: Thu, 20 Aug 2015 10:04:59 +0200 Subject: [PATCH 30/56] Updated license --- examples/cpp_01_tasks/main.cpp | 31 +++++++++++++++++++------------ extras/cplusplus/cplusplus.hpp | 33 ++++++++++++++++++++------------- extras/thread/mutex.hpp | 31 +++++++++++++++++++------------ extras/thread/queue.hpp | 31 +++++++++++++++++++------------ extras/thread/task.hpp | 31 +++++++++++++++++++------------ extras/timer/countdown.hpp | 31 +++++++++++++++++++------------ 6 files changed, 115 insertions(+), 73 deletions(-) diff --git a/examples/cpp_01_tasks/main.cpp b/examples/cpp_01_tasks/main.cpp index 133d1c5..0b9fe1f 100644 --- a/examples/cpp_01_tasks/main.cpp +++ b/examples/cpp_01_tasks/main.cpp @@ -1,20 +1,27 @@ /* + * The MIT License (MIT) + * * ESP8266 FreeRTOS Firmware - * Copyright (C) 2015 Michael Jacobsen + * Copyright (c) 2015 Michael Jacobsen (github.com/mikejac) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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: * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 * */ diff --git a/extras/cplusplus/cplusplus.hpp b/extras/cplusplus/cplusplus.hpp index a78e146..bf006a8 100644 --- a/extras/cplusplus/cplusplus.hpp +++ b/extras/cplusplus/cplusplus.hpp @@ -1,24 +1,31 @@ /* + * The MIT License (MIT) + * * ESP8266 FreeRTOS Firmware - * Copyright (C) 2015 Michael Jacobsen + * Copyright (c) 2015 Michael Jacobsen (github.com/mikejac) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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: * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 * */ - + #ifndef ESP_OPEN_RTOS_CPLUSPLUS_HPP #define ESP_OPEN_RTOS_CPLUSPLUS_HPP diff --git a/extras/thread/mutex.hpp b/extras/thread/mutex.hpp index b4e56a4..714c585 100644 --- a/extras/thread/mutex.hpp +++ b/extras/thread/mutex.hpp @@ -1,20 +1,27 @@ /* + * The MIT License (MIT) + * * ESP8266 FreeRTOS Firmware - * Copyright (C) 2015 Michael Jacobsen + * Copyright (c) 2015 Michael Jacobsen (github.com/mikejac) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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: * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 * */ diff --git a/extras/thread/queue.hpp b/extras/thread/queue.hpp index e02bec6..a24f302 100644 --- a/extras/thread/queue.hpp +++ b/extras/thread/queue.hpp @@ -1,20 +1,27 @@ /* + * The MIT License (MIT) + * * ESP8266 FreeRTOS Firmware - * Copyright (C) 2015 Michael Jacobsen + * Copyright (c) 2015 Michael Jacobsen (github.com/mikejac) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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: * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 * */ diff --git a/extras/thread/task.hpp b/extras/thread/task.hpp index a8a5c5b..cb1cb45 100644 --- a/extras/thread/task.hpp +++ b/extras/thread/task.hpp @@ -1,20 +1,27 @@ /* + * The MIT License (MIT) + * * ESP8266 FreeRTOS Firmware - * Copyright (C) 2015 Michael Jacobsen + * Copyright (c) 2015 Michael Jacobsen (github.com/mikejac) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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: * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 * */ diff --git a/extras/timer/countdown.hpp b/extras/timer/countdown.hpp index 71dd55c..87c8f3f 100644 --- a/extras/timer/countdown.hpp +++ b/extras/timer/countdown.hpp @@ -1,20 +1,27 @@ /* + * The MIT License (MIT) + * * ESP8266 FreeRTOS Firmware - * Copyright (C) 2015 Michael Jacobsen + * Copyright (c) 2015 Michael Jacobsen (github.com/mikejac) * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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: * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 * */ From 602d3e2d986c6c1afa9ee6cee9a9228ea951fe3a Mon Sep 17 00:00:00 2001 From: Michael Jacobsen Date: Fri, 21 Aug 2015 08:30:52 +0200 Subject: [PATCH 31/56] Header files re-arrangement --- common.mk | 2 +- examples/cpp_01_tasks/Makefile | 2 ++ examples/cpp_01_tasks/main.cpp | 6 +++--- extras/cpp_support/component.mk | 8 ++++++++ extras/{timer => cpp_support/include}/countdown.hpp | 0 extras/{cplusplus => cpp_support/include}/cplusplus.hpp | 0 extras/{thread => cpp_support/include}/mutex.hpp | 0 extras/{thread => cpp_support/include}/queue.hpp | 0 extras/{thread => cpp_support/include}/task.hpp | 0 9 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 extras/cpp_support/component.mk rename extras/{timer => cpp_support/include}/countdown.hpp (100%) rename extras/{cplusplus => cpp_support/include}/cplusplus.hpp (100%) rename extras/{thread => cpp_support/include}/mutex.hpp (100%) rename extras/{thread => cpp_support/include}/queue.hpp (100%) rename extras/{thread => cpp_support/include}/task.hpp (100%) diff --git a/common.mk b/common.mk index 2880752..e6e6c84 100644 --- a/common.mk +++ b/common.mk @@ -177,7 +177,7 @@ IMGTOOL_ARGS=-$(IMGTOOL_FLASH_SIZE) -$(FLASH_MODE) -$(FLASH_SPEED) # Placing $(PROGRAM_DIR) and $(PROGRAM_DIR)include first allows # programs to have their own copies of header config files for components # , which is useful for overriding things. -INC_DIRS = $(PROGRAM_DIR) $(PROGRAM_DIR)include $(ROOT)include $(ROOT)extras +INC_DIRS = $(PROGRAM_DIR) $(PROGRAM_DIR)include $(ROOT)include ifeq ($(OWN_LIBC),1) INC_DIRS += $(ROOT)libc/xtensa-lx106-elf/include diff --git a/examples/cpp_01_tasks/Makefile b/examples/cpp_01_tasks/Makefile index 458932f..f9254cf 100644 --- a/examples/cpp_01_tasks/Makefile +++ b/examples/cpp_01_tasks/Makefile @@ -1,3 +1,5 @@ # Simple makefile for simple example PROGRAM=cpp_01_tasks +OTA=0 +EXTRA_COMPONENTS=extras/cpp_support include ../../common.mk diff --git a/examples/cpp_01_tasks/main.cpp b/examples/cpp_01_tasks/main.cpp index 0b9fe1f..219be74 100644 --- a/examples/cpp_01_tasks/main.cpp +++ b/examples/cpp_01_tasks/main.cpp @@ -26,9 +26,9 @@ * */ -#include "cplusplus/cplusplus.hpp" -#include "thread/task.hpp" -#include "thread/queue.hpp" +#include "cplusplus.hpp" +#include "task.hpp" +#include "queue.hpp" #include "espressif/esp_common.h" diff --git a/extras/cpp_support/component.mk b/extras/cpp_support/component.mk new file mode 100644 index 0000000..6bc4ada --- /dev/null +++ b/extras/cpp_support/component.mk @@ -0,0 +1,8 @@ +# Component makefile for extras/cpp_support +INC_DIRS += $(ROOT)extras/cpp_support/include + +# args for passing into compile rule generation +# extras/mqtt-client_INC_DIR = $(ROOT)extras/mqtt-client +# extras/mqtt-client_SRC_DIR = $(ROOT)extras/mqtt-client + +# $(eval $(call component_compile_rules,extras/mqtt-client)) diff --git a/extras/timer/countdown.hpp b/extras/cpp_support/include/countdown.hpp similarity index 100% rename from extras/timer/countdown.hpp rename to extras/cpp_support/include/countdown.hpp diff --git a/extras/cplusplus/cplusplus.hpp b/extras/cpp_support/include/cplusplus.hpp similarity index 100% rename from extras/cplusplus/cplusplus.hpp rename to extras/cpp_support/include/cplusplus.hpp diff --git a/extras/thread/mutex.hpp b/extras/cpp_support/include/mutex.hpp similarity index 100% rename from extras/thread/mutex.hpp rename to extras/cpp_support/include/mutex.hpp diff --git a/extras/thread/queue.hpp b/extras/cpp_support/include/queue.hpp similarity index 100% rename from extras/thread/queue.hpp rename to extras/cpp_support/include/queue.hpp diff --git a/extras/thread/task.hpp b/extras/cpp_support/include/task.hpp similarity index 100% rename from extras/thread/task.hpp rename to extras/cpp_support/include/task.hpp From fbb01c81ad3edac407e59d14ad19cc2b231cf38a Mon Sep 17 00:00:00 2001 From: Michael Jacobsen Date: Sun, 23 Aug 2015 10:21:42 +0200 Subject: [PATCH 32/56] Header files adjustment (MQTT changes split from original commit - @projectgus.) --- examples/cpp_01_tasks/main.cpp | 4 ++-- extras/cpp_support/include/mutex.hpp | 20 ++++++++++++++++++-- extras/cpp_support/include/queue.hpp | 7 ++----- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/examples/cpp_01_tasks/main.cpp b/examples/cpp_01_tasks/main.cpp index 219be74..1295327 100644 --- a/examples/cpp_01_tasks/main.cpp +++ b/examples/cpp_01_tasks/main.cpp @@ -95,9 +95,9 @@ esp_open_rtos::thread::queue_t MyQueue; */ extern "C" void user_init(void) { - sdk_uart_div_modify(0, UART_CLK_FREQ / 115200); + sdk_uart_div_modify(0, UART_CLK_FREQ / 115200); - MyQueue.create(10); + MyQueue.queue_create(10); task_1.queue = MyQueue; task_2.queue = MyQueue; diff --git a/extras/cpp_support/include/mutex.hpp b/extras/cpp_support/include/mutex.hpp index 714c585..aaf29db 100644 --- a/extras/cpp_support/include/mutex.hpp +++ b/extras/cpp_support/include/mutex.hpp @@ -46,14 +46,30 @@ public: */ inline mutex_t() { - mutex = xSemaphoreCreateMutex(); + mutex = 0; + } + /** + * + * @return + */ + inline int mutex_create() + { + mutex = xSemaphoreCreateMutex(); + + if(mutex == NULL) { + return -1; + } + else { + return 0; + } } /** * */ - inline ~mutex_t() + inline void mutex_destroy() { vQueueDelete(mutex); + mutex = 0; } /** * diff --git a/extras/cpp_support/include/queue.hpp b/extras/cpp_support/include/queue.hpp index a24f302..047ce29 100644 --- a/extras/cpp_support/include/queue.hpp +++ b/extras/cpp_support/include/queue.hpp @@ -56,7 +56,7 @@ public: * @param uxItemSize * @return */ - inline int create(unsigned portBASE_TYPE uxQueueLength) + inline int queue_create(unsigned portBASE_TYPE uxQueueLength) { queue = xQueueCreate(uxQueueLength, sizeof(Data)); @@ -69,11 +69,8 @@ public: } /** * - * @param data - * @param ms - * @return */ - inline void destroy() + inline void queue_destroy() { vQueueDelete(queue); queue = 0; From 6416fe7329947c58882f5662b65fb67243c69ef3 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 26 Aug 2015 10:36:40 +1000 Subject: [PATCH 33/56] Post-merge cleanup of extras/cpp_support --- core/cplusplus_operators.cpp | 25 ------------------- examples/cpp_01_tasks/main.cpp | 4 +-- extras/cplusplus/component.mk | 3 --- .../{cplusplus.hpp => cpp_operators.hpp} | 0 4 files changed, 2 insertions(+), 30 deletions(-) delete mode 100644 core/cplusplus_operators.cpp delete mode 100644 extras/cplusplus/component.mk rename extras/cpp_support/include/{cplusplus.hpp => cpp_operators.hpp} (100%) diff --git a/core/cplusplus_operators.cpp b/core/cplusplus_operators.cpp deleted file mode 100644 index 86f4477..0000000 --- a/core/cplusplus_operators.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* Part of esp-open-rtos - * BSD Licensed as described in the file LICENSE - */ -#include -#include - -void *operator new(size_t size) -{ - return malloc(size); -} - -void *operator new[](size_t size) -{ - return malloc(size); -} - -void operator delete(void * ptr) -{ - free(ptr); -} - -void operator delete[](void * ptr) -{ - free(ptr); -} diff --git a/examples/cpp_01_tasks/main.cpp b/examples/cpp_01_tasks/main.cpp index 1295327..cf751d6 100644 --- a/examples/cpp_01_tasks/main.cpp +++ b/examples/cpp_01_tasks/main.cpp @@ -26,7 +26,7 @@ * */ -#include "cplusplus.hpp" +#include "cpp_operators.hpp" #include "task.hpp" #include "queue.hpp" @@ -104,4 +104,4 @@ extern "C" void user_init(void) task_1.task_create("tsk1"); task_2.task_create("tsk2"); -} \ No newline at end of file +} diff --git a/extras/cplusplus/component.mk b/extras/cplusplus/component.mk deleted file mode 100644 index 3f5673d..0000000 --- a/extras/cplusplus/component.mk +++ /dev/null @@ -1,3 +0,0 @@ -# Component makefile for extras/cplusplus - -INC_DIRS += $(ROOT)extras diff --git a/extras/cpp_support/include/cplusplus.hpp b/extras/cpp_support/include/cpp_operators.hpp similarity index 100% rename from extras/cpp_support/include/cplusplus.hpp rename to extras/cpp_support/include/cpp_operators.hpp From 7be365ef0814cd33a0f7e6eed29ab65abef6b199 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 26 Aug 2015 10:49:00 +1000 Subject: [PATCH 34/56] gpio.h: Explicit cast to enum type (needed for g++) --- core/include/esp/gpio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/include/esp/gpio.h b/core/include/esp/gpio.h index 1f1ce14..679fff2 100644 --- a/core/include/esp/gpio.h +++ b/core/include/esp/gpio.h @@ -124,7 +124,7 @@ INLINED void gpio_set_interrupt(const uint8_t gpio_num, const gpio_inttype_t int /* Return the interrupt type set for a pin */ INLINED gpio_inttype_t gpio_get_interrupt(const uint8_t gpio_num) { - return FIELD2VAL(GPIO_CONF_INTTYPE, GPIO.CONF[gpio_num]); + return (gpio_inttype_t)FIELD2VAL(GPIO_CONF_INTTYPE, GPIO.CONF[gpio_num]); } #endif From 1c8017484c97272c4769851583b867a8f1eefd78 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 26 Aug 2015 11:07:06 +1000 Subject: [PATCH 35/56] Move c++ operators back to link-time resolutions, part of 'core' This reverts commit e9b1df5cb5615dcaba9bcf0a36b1343b20a3cba4. --- core/cplusplus_operators.cpp | 25 +++++++ examples/cpp_01_tasks/main.cpp | 3 +- extras/cplusplus/component.mk | 3 + extras/cpp_support/include/cpp_operators.hpp | 75 -------------------- 4 files changed, 29 insertions(+), 77 deletions(-) create mode 100644 core/cplusplus_operators.cpp create mode 100644 extras/cplusplus/component.mk delete mode 100644 extras/cpp_support/include/cpp_operators.hpp diff --git a/core/cplusplus_operators.cpp b/core/cplusplus_operators.cpp new file mode 100644 index 0000000..86f4477 --- /dev/null +++ b/core/cplusplus_operators.cpp @@ -0,0 +1,25 @@ +/* Part of esp-open-rtos + * BSD Licensed as described in the file LICENSE + */ +#include +#include + +void *operator new(size_t size) +{ + return malloc(size); +} + +void *operator new[](size_t size) +{ + return malloc(size); +} + +void operator delete(void * ptr) +{ + free(ptr); +} + +void operator delete[](void * ptr) +{ + free(ptr); +} diff --git a/examples/cpp_01_tasks/main.cpp b/examples/cpp_01_tasks/main.cpp index cf751d6..160a0c8 100644 --- a/examples/cpp_01_tasks/main.cpp +++ b/examples/cpp_01_tasks/main.cpp @@ -26,7 +26,6 @@ * */ -#include "cpp_operators.hpp" #include "task.hpp" #include "queue.hpp" @@ -104,4 +103,4 @@ extern "C" void user_init(void) task_1.task_create("tsk1"); task_2.task_create("tsk2"); -} +} \ No newline at end of file diff --git a/extras/cplusplus/component.mk b/extras/cplusplus/component.mk new file mode 100644 index 0000000..3f5673d --- /dev/null +++ b/extras/cplusplus/component.mk @@ -0,0 +1,3 @@ +# Component makefile for extras/cplusplus + +INC_DIRS += $(ROOT)extras diff --git a/extras/cpp_support/include/cpp_operators.hpp b/extras/cpp_support/include/cpp_operators.hpp deleted file mode 100644 index bf006a8..0000000 --- a/extras/cpp_support/include/cpp_operators.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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 - * - */ - -#ifndef ESP_OPEN_RTOS_CPLUSPLUS_HPP -#define ESP_OPEN_RTOS_CPLUSPLUS_HPP - -#include - -/****************************************************************************************************************** - * C++ new and delete operators - * - */ - -/** - * - * @param size - * @return - */ -inline void *operator new(size_t size) -{ - return malloc(size); -} -/** - * - * @param size - * @return - */ -inline void *operator new[](size_t size) -{ - return malloc(size); -} -/** - * - * @param ptr - */ -inline void operator delete(void * ptr) -{ - free(ptr); -} -/** - * - * @param ptr - */ -inline void operator delete[](void * ptr) -{ - free(ptr); -} - -#endif /* ESP_OPEN_RTOS_CPLUSPLUS_HPP */ - From 6c06e5e91ea956b198f2c0f839cd9382ba095ef3 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 26 Aug 2015 11:11:31 +1000 Subject: [PATCH 36/56] common_macros: Include sys/cdefs.h, defines _Static_assert among others --- core/include/common_macros.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/include/common_macros.h b/core/include/common_macros.h index b0d89e1..355248b 100644 --- a/core/include/common_macros.h +++ b/core/include/common_macros.h @@ -10,6 +10,8 @@ #ifndef _COMMON_MACROS_H #define _COMMON_MACROS_H +#include + #define UNUSED __attributed((unused)) #ifndef BIT From 8a29e46319ca012daf0a7b5c071cf6aee80156b2 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 26 Aug 2015 11:14:34 +1000 Subject: [PATCH 37/56] examples/Makefile: Use MAKE to properly invoke make recursively --- examples/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index 0436a13..2f816e5 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -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: From a5ba05b5f9ea4141371a22ec9ec3cb633fd48916 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 26 Aug 2015 11:16:58 +1000 Subject: [PATCH 38/56] Remove stray extras/cplusplus --- extras/cplusplus/component.mk | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 extras/cplusplus/component.mk diff --git a/extras/cplusplus/component.mk b/extras/cplusplus/component.mk deleted file mode 100644 index 3f5673d..0000000 --- a/extras/cplusplus/component.mk +++ /dev/null @@ -1,3 +0,0 @@ -# Component makefile for extras/cplusplus - -INC_DIRS += $(ROOT)extras From f31daa7f9ac46df798df33503b14f6faf790b876 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Sat, 12 Sep 2015 15:23:42 +1000 Subject: [PATCH 39/56] iomux: Fix setting of invalid bits when masking in iomux fields Fixes regression from 2a939e97 Part of issue #45 --- core/include/esp/iomux_regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/include/esp/iomux_regs.h b/core/include/esp/iomux_regs.h index 4ea3be2..2600da9 100644 --- a/core/include/esp/iomux_regs.h +++ b/core/include/esp/iomux_regs.h @@ -45,7 +45,7 @@ _Static_assert(sizeof(struct IOMUX_REGS) == 0x44, "IOMUX_REGS is the wrong size" #define IOMUX_PIN_FUNC_MASK 0x00001030 /* WARNING: Macro evaluates argument twice */ -#define IOMUX_FUNC(val) (VAL2FIELD(IOMUX_PIN_FUNC_LOW, val) | VAL2FIELD(IOMUX_PIN_FUNC_HIGH, val)) +#define IOMUX_FUNC(val) (VAL2FIELD_M(IOMUX_PIN_FUNC_LOW, val) | VAL2FIELD_M(IOMUX_PIN_FUNC_HIGH, val)) /* WARNING: Macro evaluates argument twice */ #define IOMUX_FUNC_VALUE(regbits) (FIELD2VAL(IOMUX_PIN_FUNC_LOW, regbits) | FIELD2VAL(IOMUX_PIN_FUNC_HIGH, regbits)) From 3aff91c85c1c5bc9d2f783aa62826edb85ac908e Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Sat, 12 Sep 2015 16:20:05 +1000 Subject: [PATCH 40/56] Rename GPIO_CONF_PUSH_PULL to GPIO_CONF_OPEN_DRAIN Seems I got the functionality of this bit inverted when initially testing. In testing it also seems open drain mode is ignored on some pins, which still source current. Needs more investigation though (may be pullups internal to the ESP modules or set by default in software.) Relates to #45 --- core/include/esp/gpio.h | 10 ++++------ core/include/esp/gpio_regs.h | 15 ++++++++++----- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/core/include/esp/gpio.h b/core/include/esp/gpio.h index 679fff2..4f431f2 100644 --- a/core/include/esp/gpio.h +++ b/core/include/esp/gpio.h @@ -27,28 +27,26 @@ typedef enum { INLINED void gpio_enable(const uint8_t gpio_num, const gpio_direction_t direction) { uint32_t iomux_flags; - uint32_t ctrl_val; switch(direction) { case GPIO_INPUT: iomux_flags = 0; - ctrl_val = 0; break; case GPIO_OUTPUT: iomux_flags = IOMUX_PIN_OUTPUT_ENABLE; - ctrl_val = GPIO_CONF_PUSH_PULL; break; case GPIO_OUT_OPEN_DRAIN: iomux_flags = IOMUX_PIN_OUTPUT_ENABLE; - ctrl_val = 0; break; case GPIO_INPUT_PULLUP: iomux_flags = IOMUX_PIN_PULLUP; - ctrl_val = 0; break; } iomux_set_gpio_function(gpio_num, iomux_flags); - GPIO.CONF[gpio_num] = (GPIO.CONF[gpio_num] & FIELD_MASK(GPIO_CONF_INTTYPE)) | ctrl_val; + if(direction == GPIO_OUT_OPEN_DRAIN) + GPIO.CONF[gpio_num] |= GPIO_CONF_OPEN_DRAIN; + else + GPIO.CONF[gpio_num] &= ~GPIO_CONF_OPEN_DRAIN; if (iomux_flags & IOMUX_PIN_OUTPUT_ENABLE) GPIO.ENABLE_OUT_SET = BIT(gpio_num); else diff --git a/core/include/esp/gpio_regs.h b/core/include/esp/gpio_regs.h index 3d91efb..815e7c1 100644 --- a/core/include/esp/gpio_regs.h +++ b/core/include/esp/gpio_regs.h @@ -76,10 +76,15 @@ _Static_assert(sizeof(struct GPIO_REGS) == 0x74, "GPIO_REGS is the wrong size"); * Under what conditions this GPIO input should generate an interrupt. * (see gpio_inttype_t enum below for values) * - * GPIO_CONF_PUSH_PULL (boolean) - * When set, a high output state will pull the pin up to +Vcc (3.3V). When - * cleared, output functions in "open drain" mode (low state will pull down - * to ground, but high state allows output to "float"). + * GPIO_CONF_OPEN_DRAIN (boolean) + * If this bit is set, the pin is in "open drain" mode - a high output state + * will leave the pin floating but not source any current. If bit is cleared, + * the pin is in push/pull mode so a high output state will drive the pin up + * to +Vcc (3.3V). In either case, a low output state will pull the pin down + * to ground. + * + * GPIO_CONF_OPEN_DRAIN does not appear to work on all pins. + * * * GPIO_CONF_SOURCE_PWM (boolean) * When set, GPIO pin output will be connected to the sigma-delta PWM @@ -93,7 +98,7 @@ _Static_assert(sizeof(struct GPIO_REGS) == 0x74, "GPIO_REGS is the wrong size"); #define GPIO_CONF_WAKEUP_ENABLE BIT(10) #define GPIO_CONF_INTTYPE_M 0x00000007 #define GPIO_CONF_INTTYPE_S 7 -#define GPIO_CONF_PUSH_PULL BIT(2) +#define GPIO_CONF_OPEN_DRAIN BIT(2) #define GPIO_CONF_SOURCE_PWM BIT(0) /* Valid values for the GPIO_CONF_INTTYPE field */ From 0da6c97a9d320dff6a01818accd6cd2c84ff876f Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Sat, 12 Sep 2015 16:28:11 +1000 Subject: [PATCH 41/56] Rename main.cpp in tasks example --- examples/cpp_01_tasks/{main.cpp => cpp_tasks.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/cpp_01_tasks/{main.cpp => cpp_tasks.cpp} (100%) diff --git a/examples/cpp_01_tasks/main.cpp b/examples/cpp_01_tasks/cpp_tasks.cpp similarity index 100% rename from examples/cpp_01_tasks/main.cpp rename to examples/cpp_01_tasks/cpp_tasks.cpp From 1c9e106db84766a1ecc35cb1476514932d4a3e29 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 27 Aug 2015 16:47:38 +1000 Subject: [PATCH 42/56] Compile with -ffunction-sectons -fdata-sections, link with -gc-sections This seems to shrink code size by abou 3.5%. Not sure if there are any downsides. --- common.mk | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/common.mk b/common.mk index e6e6c84..83c4f1f 100644 --- a/common.mk +++ b/common.mk @@ -94,14 +94,25 @@ OWN_LIBC ?= 1 # Note: you will need a recent esp ENTRY_SYMBOL ?= call_user_start +# Set this to zero if you don't want individual function & data sections +# (some code may be slightly slower, linking will be slighty slower, +# but compiled code size will come down a small amount.) +SPLIT_SECTIONS ?= 1 + # Common flags for both C & C++_ C_CXX_FLAGS = -Wall -Werror -Wl,-EL -nostdlib -mlongcalls -mtext-section-literals $(CPPFLAGS) # Flags for C only CFLAGS = $(C_CXX_FLAGS) -std=gnu99 # Flags for C++ only CXXFLAGS = $(C_CXX_FLAGS) -fno-exceptions -fno-rtti + LDFLAGS = -nostdlib -Wl,--no-check-sections -Wl,-L$(BUILD_DIR)sdklib -Wl,-L$(ROOT)lib -u $(ENTRY_SYMBOL) -Wl,-static -Wl,-Map=build/${PROGRAM}.map $(EXTRA_LDFLAGS) +ifeq ($(SPLIT_SECTIONS),1) + C_CXX_FLAGS += -ffunction-sections -fdata-sections + LDFLAGS += -Wl,-gc-sections +endif + ifeq ($(FLAVOR),debug) C_CXX_FLAGS += -g -O0 LDFLAGS += -g -O0 From f230fbcd65df45854baab39d0c066ac605443dfc Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 18 Sep 2015 13:45:44 +1000 Subject: [PATCH 43/56] Move start of IROM0 to 0x40220000, save 128kB of flash Old starting point left 256kB for RAM sections, but I think they shouldn't ever possibly exceed 128kB. --- common.mk | 2 +- ld/eagle.app.v6.ld | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common.mk b/common.mk index 83c4f1f..f67e814 100644 --- a/common.mk +++ b/common.mk @@ -163,7 +163,7 @@ ifeq ($(OTA),0) # for non-OTA, we create two different files for uploading into the flash # these are the names and options to generate them FW_ADDR_1 = 0x00000 -FW_ADDR_2 = 0x40000 +FW_ADDR_2 = 0x20000 FW_FILE_1 = $(addprefix $(FW_BASE),$(FW_ADDR_1).bin) FW_FILE_2 = $(addprefix $(FW_BASE),$(FW_ADDR_2).bin) else diff --git a/ld/eagle.app.v6.ld b/ld/eagle.app.v6.ld index 566ad67..f1d11cc 100644 --- a/ld/eagle.app.v6.ld +++ b/ld/eagle.app.v6.ld @@ -32,7 +32,7 @@ ets_printf = printf; */ #ifndef OTA -#define IROM0_START 0x40240000 +#define IROM0_START 0x40220000 /* Non-OTA sizes */ #if FLASH_SIZE == 2 /* 256kB */ From 1b22cc088eadf8e0b907592356c07766f2a0fbf7 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 17 Sep 2015 20:35:39 +1000 Subject: [PATCH 44/56] Add initial mbedTLS and HTTPS example project (using howsmyssl.com JSON API) mbedTLS version 2.1.0 (current stable) Has some known issues/hacks: * Entropy source not hooked in at all * Linker script has a messy hack in it to store some (not all) data in irom --- .gitmodules | 3 + examples/http_get_mbedtls/Makefile | 4 + examples/http_get_mbedtls/http_get_mbedtls.c | 347 +++ .../http_get_mbedtls/include/mbedtls/config.h | 27 + extras/mbedtls/component.mk | 56 + extras/mbedtls/include/mbedtls/config.h | 2444 +++++++++++++++++ extras/mbedtls/mbedtls | 1 + extras/mbedtls/net_lwip.c | 510 ++++ ld/eagle.app.v6.ld | 119 +- lwip/component.mk | 2 +- 10 files changed, 3455 insertions(+), 58 deletions(-) create mode 100644 examples/http_get_mbedtls/Makefile create mode 100644 examples/http_get_mbedtls/http_get_mbedtls.c create mode 100644 examples/http_get_mbedtls/include/mbedtls/config.h create mode 100644 extras/mbedtls/component.mk create mode 100644 extras/mbedtls/include/mbedtls/config.h create mode 160000 extras/mbedtls/mbedtls create mode 100644 extras/mbedtls/net_lwip.c diff --git a/.gitmodules b/.gitmodules index 6a00a93..74c2102 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,6 @@ path = axtls/axtls url = https://github.com/SuperHouse/axtls.git +[submodule "extras/mbedtls/mbedtls"] + path = extras/mbedtls/mbedtls + url = https://github.com/ARMmbed/mbedtls.git diff --git a/examples/http_get_mbedtls/Makefile b/examples/http_get_mbedtls/Makefile new file mode 100644 index 0000000..fc9a4fa --- /dev/null +++ b/examples/http_get_mbedtls/Makefile @@ -0,0 +1,4 @@ +PROGRAM=http_get_mbedtls +COMPONENTS = FreeRTOS lwip core extras/mbedtls + +include ../../common.mk diff --git a/examples/http_get_mbedtls/http_get_mbedtls.c b/examples/http_get_mbedtls/http_get_mbedtls.c new file mode 100644 index 0000000..d1fbf0d --- /dev/null +++ b/examples/http_get_mbedtls/http_get_mbedtls.c @@ -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 + +#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); +} diff --git a/examples/http_get_mbedtls/include/mbedtls/config.h b/examples/http_get_mbedtls/include/mbedtls/config.h new file mode 100644 index 0000000..2674292 --- /dev/null +++ b/examples/http_get_mbedtls/include/mbedtls/config.h @@ -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 + +#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 diff --git a/extras/mbedtls/component.mk b/extras/mbedtls/component.mk new file mode 100644 index 0000000..c392471 --- /dev/null +++ b/extras/mbedtls/component.mk @@ -0,0 +1,56 @@ +# Component makefile for mbedtls + +# mbedtls by default builds into 3 libraries not one. We just use one for now (doesn't make a huge difference when static linking) + +# Config: +# We supply our own hand tweaked mbedtls/config.h in our 'include' dir, the rest of upstream mbedtls is not changed. + +MBEDTLS_DIR = $(mbedtls_ROOT)mbedtls/ +INC_DIRS += $(mbedtls_ROOT)include $(MBEDTLS_DIR)include + +# these OBJS_xxx variables are copied directly from mbedtls/mbedtls/Makefile, +# minus a few values (noted in comments) +# +# If updating to a future mbedtls version you can just copy these in. +OBJS_CRYPTO= aes.o aesni.o arc4.o \ + asn1parse.o asn1write.o base64.o \ + bignum.o blowfish.o camellia.o \ + ccm.o cipher.o cipher_wrap.o \ + ctr_drbg.o des.o dhm.o \ + ecdh.o ecdsa.o ecp.o \ + ecp_curves.o entropy.o entropy_poll.o \ + error.o gcm.o havege.o \ + hmac_drbg.o md.o md2.o \ + md4.o md5.o md_wrap.o \ + memory_buffer_alloc.o oid.o \ + padlock.o pem.o pk.o \ + pk_wrap.o pkcs12.o pkcs5.o \ + pkparse.o pkwrite.o platform.o \ + ripemd160.o rsa.o sha1.o \ + sha256.o sha512.o threading.o \ + timing.o version.o \ + version_features.o xtea.o +# minus net.o + +OBJS_X509= certs.o pkcs11.o x509.o \ + x509_create.o x509_crl.o x509_crt.o \ + x509_csr.o x509write_crt.o x509write_csr.o + +OBJS_TLS= debug.o ssl_cache.o \ + ssl_ciphersuites.o ssl_cli.o \ + ssl_cookie.o ssl_srv.o ssl_ticket.o \ + ssl_tls.o + +# args for passing into compile rule generation +mbedtls_INC_DIR = +mbedtls_SRC_DIR = $(mbedtls_ROOT) +mbedtls_EXTRA_SRC_FILES = $(patsubst %.o,$(MBEDTLS_DIR)library/%.c,$(OBJS_CRYPTO) $(OBJS_X509) $(OBJS_TLS)) + +# depending on cipher configuration, some mbedTLS variables are unused +mbedtls_CFLAGS = -Wno-error=unused-but-set-variable -Wno-error=unused-variable $(CFLAGS) + +$(eval $(call component_compile_rules,mbedtls)) + +# Helpful error if git submodule not initialised +$(MBEDTLS_DIR): + $(error "mbedtls git submodule not installed. Please run 'git submodule update --init'") diff --git a/extras/mbedtls/include/mbedtls/config.h b/extras/mbedtls/include/mbedtls/config.h new file mode 100644 index 0000000..903006d --- /dev/null +++ b/extras/mbedtls/include/mbedtls/config.h @@ -0,0 +1,2444 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/timing.c + * library/padlock.c + * include/mbedtls/bn_mul.h + * + * Comment to disable the use of assembly code. + */ +#define MBEDTLS_HAVE_ASM + +/** + * \def MBEDTLS_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define MBEDTLS_HAVE_SSE2 + +/** + * \def MBEDTLS_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with MBEDTLS_HAVE_TIME_DATE + * + * Comment if your system does not support time functions + */ +//#define MBEDTLS_HAVE_TIME + +/** + * \def MBEDTLS_HAVE_TIME_DATE + * + * System has time.h and time(), gmtime() and the clock is correct. + * The time needs to be correct (not necesarily very accurate, but at least + * the date should be correct). This is used to verify the validity period of + * X.509 certificates. + * + * Comment if your system does not have a correct clock. + */ +//#define MBEDTLS_HAVE_TIME_DATE + +/** + * \def MBEDTLS_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided calloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling MBEDTLS_PLATFORM_MEMORY without the + * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide + * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and + * free() function pointer at runtime. + * + * Enabling MBEDTLS_PLATFORM_MEMORY and specifying + * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +//#define MBEDTLS_PLATFORM_MEMORY + +/** + * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. calloc() to + * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a + * MBEDTLS_PLATFORM_XXX_MACRO. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def MBEDTLS_PLATFORM_XXX_ALT + * + * Uncomment a macro to let mbed TLS support the function in the platform + * abstraction layer. + * + * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will + * provide a function "mbedtls_platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require MBEDTLS_PLATFORM_C to be defined! + * + * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; + * it will be enabled automatically by check_config.h + * + * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as + * MBEDTLS_PLATFORM_XXX_MACRO! + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define MBEDTLS_PLATFORM_EXIT_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT + +/** + * \def MBEDTLS_DEPRECATED_WARNING + * + * Mark deprecated functions so that they generate a warning if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * This only works with GCC and Clang. With other compilers, you may want to + * use MBEDTLS_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions. + */ +#define MBEDTLS_DEPRECATED_WARNING + +/** + * \def MBEDTLS_DEPRECATED_REMOVED + * + * Remove deprecated functions so that they generate an error if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * Uncomment to get errors on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_REMOVED + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def MBEDTLS_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(), + * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() + * + * Only works if you have MBEDTLS_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define MBEDTLS_TIMING_ALT + +/** + * \def MBEDTLS__MODULE_NAME__ALT + * + * Uncomment a macro to let mbed TLS use your alternate core implementation of + * a symmetric crypto or hash module (e.g. platform specific assembly + * optimized implementations). Keep in mind that the function prototypes + * should remain the same. + * + * This replaces the whole module. If you only want to replace one of the + * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer + * provide the "struct mbedtls_aes_context" definition and omit the base function + * declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * module. + */ +//#define MBEDTLS_AES_ALT +//#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_BLOWFISH_ALT +//#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_DES_ALT +//#define MBEDTLS_XTEA_ALT +//#define MBEDTLS_MD2_ALT +//#define MBEDTLS_MD4_ALT +//#define MBEDTLS_MD5_ALT +//#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_SHA1_ALT +//#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_SHA512_ALT + +/** + * \def MBEDTLS__FUNCTION_NAME__ALT + * + * Uncomment a macro to let mbed TLS use you alternate core implementation of + * symmetric crypto or hash function. Keep in mind that function prototypes + * should remain the same. + * + * This replaces only one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will + * no longer provide the mbedtls_sha1_process() function, but it will still provide + * the other function (using your mbedtls_sha1_process() function) and the definition + * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible + * with this definition. + * + * Note: if you use the AES_xxx_ALT macros, then is is recommended to also set + * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES + * tables. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ +//#define MBEDTLS_MD2_PROCESS_ALT +//#define MBEDTLS_MD4_PROCESS_ALT +//#define MBEDTLS_MD5_PROCESS_ALT +//#define MBEDTLS_RIPEMD160_PROCESS_ALT +//#define MBEDTLS_SHA1_PROCESS_ALT +//#define MBEDTLS_SHA256_PROCESS_ALT +//#define MBEDTLS_SHA512_PROCESS_ALT +//#define MBEDTLS_DES_SETKEY_ALT +//#define MBEDTLS_DES_CRYPT_ECB_ALT +//#define MBEDTLS_DES3_CRYPT_ECB_ALT +//#define MBEDTLS_AES_SETKEY_ENC_ALT +//#define MBEDTLS_AES_SETKEY_DEC_ALT +//#define MBEDTLS_AES_ENCRYPT_ALT +//#define MBEDTLS_AES_DECRYPT_ALT + +/** + * \def MBEDTLS_ENTROPY_HARDWARE_ALT + * + * Uncomment this macro to let mbed TLS use your own implementation of a + * hardware entropy collector. + * + * Your function must be called \c mbedtls_hardware_poll(), have the same + * prototype as declared in entropy_poll.h, and accept NULL as first argument. + * + * Uncomment to use your own hardware entropy collector. + */ +//#define MBEDTLS_ENTROPY_HARDWARE_ALT + +/** + * \def MBEDTLS_AES_ROM_TABLES + * + * Store the AES tables in ROM. + * + * Uncomment this macro to store the AES tables in ROM. + */ +#define MBEDTLS_AES_ROM_TABLES + +/** + * \def MBEDTLS_CAMELLIA_SMALL_MEMORY + * + * Use less ROM for the Camellia implementation (saves about 768 bytes). + * + * Uncomment this macro to use less memory for Camellia. + */ +//#define MBEDTLS_CAMELLIA_SMALL_MEMORY + +/** + * \def MBEDTLS_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CBC + +/** + * \def MBEDTLS_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CFB + +/** + * \def MBEDTLS_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CTR + +/** + * \def MBEDTLS_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define MBEDTLS_CIPHER_NULL_CIPHER + +/** + * \def MBEDTLS_CIPHER_PADDING_XXX + * + * Uncomment or comment macros to add support for specific padding modes + * in the cipher layer with cipher modes that support padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define MBEDTLS_CIPHER_PADDING_ZEROS + +/** + * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites + */ +//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES + * + * Remove RC4 ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on RC4 from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to + * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them + * explicitly. + * + * Uncomment this macro to remove RC4 ciphersuites by default. + */ +#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES + +/** + * \def MBEDTLS_ECP_XXXX_ENABLED + * + * Enables specific curves within the Elliptic Curve module. + * By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED + +/** + * \def MBEDTLS_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#define MBEDTLS_ECP_NIST_OPTIM + +/** + * \def MBEDTLS_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: MBEDTLS_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ +#define MBEDTLS_ECDSA_DETERMINISTIC + +/** + * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + */ +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + +/** + * \def MBEDTLS_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ +#define MBEDTLS_PK_PARSE_EC_EXTENDED + +/** + * \def MBEDTLS_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of mbedtls_strerror() in + * third party libraries easier when MBEDTLS_ERROR_C is disabled + * (no effect when MBEDTLS_ERROR_C is enabled). + * + * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're + * not using mbedtls_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * mbedtls_strerror() + */ +#define MBEDTLS_ERROR_STRERROR_DUMMY + +/** + * \def MBEDTLS_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: MBEDTLS_BIGNUM_C + */ +#define MBEDTLS_GENPRIME + +/** + * \def MBEDTLS_FS_IO + * + * Enable functions that use the filesystem. + */ +//#define MBEDTLS_FS_IO + +/** + * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * mbedtls_timing_hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def MBEDTLS_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +#define MBEDTLS_NO_PLATFORM_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_FORCE_SHA256 + * + * Force the entropy accumulator to use a SHA-256 accumulator instead of the + * default SHA-512 based one (if both are available). + * + * Requires: MBEDTLS_SHA256_C + * + * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option + * if you have performance concerns. + * + * This option is only useful if both MBEDTLS_SHA256_C and + * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. + */ +//#define MBEDTLS_ENTROPY_FORCE_SHA256 + +/** + * \def MBEDTLS_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define MBEDTLS_MEMORY_DEBUG + +/** + * \def MBEDTLS_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define MBEDTLS_MEMORY_BACKTRACE + +/** + * \def MBEDTLS_PK_RSA_ALT_SUPPORT + * + * Support external private RSA keys (eg from a HSM) in the PK layer. + * + * Comment this macro to disable support for external private RSA keys. + */ +#define MBEDTLS_PK_RSA_ALT_SUPPORT + +/** + * \def MBEDTLS_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: MBEDTLS_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define MBEDTLS_PKCS1_V15 + +/** + * \def MBEDTLS_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +#define MBEDTLS_PKCS1_V21 + +/** + * \def MBEDTLS_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define MBEDTLS_RSA_NO_CRT + +/** + * \def MBEDTLS_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +#define MBEDTLS_SELF_TEST + +/** + * \def MBEDTLS_SHA256_SMALLER + * + * Enable an implementation of SHA-256 that has lower ROM footprint but also + * lower performance. + * + * The default implementation is meant to be a reasonnable compromise between + * performance and size. This version optimizes more aggressively for size at + * the expense of performance. Eg on Cortex-M4 it reduces the size of + * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about + * 30%. + * + * Uncomment to enable the smaller implementation of SHA256. + */ +#define MBEDTLS_SHA256_SMALLER + +/** + * \def MBEDTLS_SSL_AEAD_RANDOM_IV + * + * Generate a random IV rather than using the record sequence number as a + * nonce for ciphersuites using and AEAD algorithm (GCM or CCM). + * + * Using the sequence number is generally recommended. + * + * Uncomment this macro to always use random IVs with AEAD ciphersuites. + */ +//#define MBEDTLS_SSL_AEAD_RANDOM_IV + +/** + * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, mbed TLS can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define MBEDTLS_SSL_ALL_ALERT_MESSAGES + +/** + * \def MBEDTLS_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +//#define MBEDTLS_SSL_DEBUG_ALL + +/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC + * + * Enable support for Encrypt-then-MAC, RFC 7366. + * + * This allows peers that both support it to use a more robust protection for + * ciphersuites using CBC, providing deep resistance against timing attacks + * on the padding or underlying cipher. + * + * This only affects CBC ciphersuites, and is useless if none is defined. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Encrypt-then-MAC + */ +#define MBEDTLS_SSL_ENCRYPT_THEN_MAC + +/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET + * + * Enable support for Extended Master Secret, aka Session Hash + * (draft-ietf-tls-session-hash-02). + * + * This was introduced as "the proper fix" to the Triple Handshake familiy of + * attacks, but it is recommended to always use it (even if you disable + * renegotiation), since it actually fixes a more fundamental issue in the + * original SSL/TLS design, and has implications beyond Triple Handshake. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Extended Master Secret. + */ +#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET + +/** + * \def MBEDTLS_SSL_FALLBACK_SCSV + * + * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00). + * + * For servers, it is recommended to always enable this, unless you support + * only one version of TLS, or know for sure that none of your clients + * implements a fallback strategy. + * + * For clients, you only need this if you're using a fallback strategy, which + * is not recommended in the first place, unless you absolutely need it to + * interoperate with buggy (version-intolerant) servers. + * + * Comment this macro to disable support for FALLBACK_SCSV + */ +#define MBEDTLS_SSL_FALLBACK_SCSV + +/** + * \def MBEDTLS_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ +//#define MBEDTLS_SSL_HW_RECORD_ACCEL + +/** + * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING + * + * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0. + * + * This is a countermeasure to the BEAST attack, which also minimizes the risk + * of interoperability issues compared to sending 0-length records. + * + * Comment this macro to disable 1/n-1 record splitting. + */ +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING + +/** + * \def MBEDTLS_SSL_RENEGOTIATION + * + * Disable support for TLS renegotiation. + * + * The two main uses of renegotiation are (1) refresh keys on long-lived + * connections and (2) client authentication after the initial handshake. + * If you don't need renegotiation, it's probably better to disable it, since + * it has been associated with security issues in the past and is easy to + * misuse/misunderstand. + * + * Comment this to disable support for renegotiation. + */ +#define MBEDTLS_SSL_RENEGOTIATION + +/** + * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to enable support for SSLv2 Client Hello messages. + */ +//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * + * Pick the ciphersuite according to the client's preferences rather than ours + * in the SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to respect client's ciphersuite order + */ +//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + +/** + * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def MBEDTLS_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ +#define MBEDTLS_SSL_PROTO_SSL3 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +#define MBEDTLS_SSL_PROTO_TLS1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled). + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 / DTLS 1.0 + */ +#define MBEDTLS_SSL_PROTO_TLS1_1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * + * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 + */ +#define MBEDTLS_SSL_PROTO_TLS1_2 + +/** + * \def MBEDTLS_SSL_PROTO_DTLS + * + * Enable support for DTLS (all available versions). + * + * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0, + * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_1 + * or MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for DTLS + */ +#define MBEDTLS_SSL_PROTO_DTLS + +/** + * \def MBEDTLS_SSL_ALPN + * + * Enable support for RFC 7301 Application Layer Protocol Negotiation. + * + * Comment this macro to disable support for ALPN. + */ +#define MBEDTLS_SSL_ALPN + +/** + * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY + * + * Enable support for the anti-replay mechanism in DTLS. + * + * Requires: MBEDTLS_SSL_TLS_C + * MBEDTLS_SSL_PROTO_DTLS + * + * \warning Disabling this is often a security risk! + * See mbedtls_ssl_conf_dtls_anti_replay() for details. + * + * Comment this to disable anti-replay in DTLS. + */ +#define MBEDTLS_SSL_DTLS_ANTI_REPLAY + +/** + * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Enable support for HelloVerifyRequest on DTLS servers. + * + * This feature is highly recommended to prevent DTLS servers being used as + * amplifiers in DoS attacks against other hosts. It should always be enabled + * unless you know for sure amplification cannot be a problem in the + * environment in which your server operates. + * + * \warning Disabling this can ba a security risk! (see above) + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Comment this to disable support for HelloVerifyRequest. + */ +#define MBEDTLS_SSL_DTLS_HELLO_VERIFY + +/** + * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT + * + * Enable support for a limit of records with bad MAC. + * + * See mbedtls_ssl_conf_dtls_badmac_limit(). + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + */ +#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT + +/** + * \def MBEDTLS_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * Client-side, provides full support for session tickets (maintainance of a + * session store remains the responsibility of the application, though). + * Server-side, you also need to provide callbacks for writing and parsing + * tickets, including authenticated encryption and key management. Example + * callbacks are provided by MBEDTLS_SSL_TICKET_C. + * + * Comment this macro to disable support for SSL session tickets + */ +#define MBEDTLS_SSL_SESSION_TICKETS + +/** + * \def MBEDTLS_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Requires: MBEDTLS_X509_CRT_PARSE_C + * + * Comment this macro to disable support for server name indication in SSL + */ +#define MBEDTLS_SSL_SERVER_NAME_INDICATION + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +#define MBEDTLS_SSL_TRUNCATED_HMAC + +/** + * \def MBEDTLS_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define MBEDTLS_THREADING_ALT + +/** + * \def MBEDTLS_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define MBEDTLS_THREADING_PTHREAD + +/** + * \def MBEDTLS_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via mbedtls_version_check_feature(). + * + * Requires: MBEDTLS_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +#define MBEDTLS_VERSION_FEATURES + +/** + * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + +/** + * \def MBEDTLS_X509_CHECK_KEY_USAGE + * + * Enable verification of the keyUsage extension (CA and leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused + * (intermediate) CA and leaf certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip keyUsage checking for both CA and leaf certificates. + */ +#define MBEDTLS_X509_CHECK_KEY_USAGE + +/** + * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + * + * Enable verification of the extendedKeyUsage extension (leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip extendedKeyUsage checking for certificates. + */ +#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + +/** + * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT + * + * Enable parsing and verification of X.509 certificates, CRLs and CSRS + * signed with RSASSA-PSS (aka PKCS#1 v2.1). + * + * Comment this macro to disallow using RSASSA-PSS in certificates. + */ +#define MBEDTLS_X509_RSASSA_PSS_SUPPORT + +/** + * \def MBEDTLS_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * \warning TLS-level compression MAY REDUCE SECURITY! See for example the + * CRIME attack. Before enabling this option, you should examine with care if + * CRIME or similar exploits may be a applicable to your use case. + * + * \note Currently compression can't be used with DTLS. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define MBEDTLS_ZLIB_SUPPORT +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def MBEDTLS_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +#define MBEDTLS_AESNI_C + +/** + * \def MBEDTLS_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/ssl_tls.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define MBEDTLS_AES_C + +/** + * \def MBEDTLS_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_ARC4_C + +/** + * \def MBEDTLS_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define MBEDTLS_ASN1_PARSE_C + +/** + * \def MBEDTLS_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/mbedtls_x509write_csr.c + */ +#define MBEDTLS_ASN1_WRITE_C + +/** + * \def MBEDTLS_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define MBEDTLS_BASE64_C + +/** + * \def MBEDTLS_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#define MBEDTLS_BIGNUM_C + +/** + * \def MBEDTLS_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +#define MBEDTLS_BLOWFISH_C + +/** + * \def MBEDTLS_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +#define MBEDTLS_CAMELLIA_C + +/** + * \def MBEDTLS_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +#define MBEDTLS_CCM_C + +/** + * \def MBEDTLS_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +#define MBEDTLS_CERTS_C + +/** + * \def MBEDTLS_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define MBEDTLS_CIPHER_C + +/** + * \def MBEDTLS_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-256-based random generator. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: MBEDTLS_AES_C + * + * This module provides the CTR_DRBG AES-256 random number generator. + */ +#define MBEDTLS_CTR_DRBG_C + +/** + * \def MBEDTLS_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +//#define MBEDTLS_DEBUG_C + +/** + * \def MBEDTLS_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + */ +#define MBEDTLS_DES_C + +/** + * \def MBEDTLS_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + */ +#define MBEDTLS_DHM_C + +/** + * \def MBEDTLS_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: MBEDTLS_ECP_C + */ +#define MBEDTLS_ECDH_C + +/** + * \def MBEDTLS_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C + */ +#define MBEDTLS_ECDSA_C + +/** + * \def MBEDTLS_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * + * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED + */ +#define MBEDTLS_ECP_C + +/** + * \def MBEDTLS_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C + * + * This module provides a generic entropy pool + */ +#define MBEDTLS_ENTROPY_C + +/** + * \def MBEDTLS_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables mbedtls_strerror(). + */ +#define MBEDTLS_ERROR_C + +/** + * \def MBEDTLS_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +#define MBEDTLS_GCM_C + +/** + * \def MBEDTLS_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: MBEDTLS_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define MBEDTLS_HAVEGE_C + +/** + * \def MBEDTLS_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +#define MBEDTLS_HMAC_DRBG_C + +/** + * \def MBEDTLS_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/mbedtls_md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define MBEDTLS_MD_C + +/** + * \def MBEDTLS_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/mbedtls_md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + */ +//#define MBEDTLS_MD2_C + +/** + * \def MBEDTLS_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/mbedtls_md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + */ +//#define MBEDTLS_MD4_C + +/** + * \def MBEDTLS_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/mbedtls_md5.c + * Caller: library/mbedtls_md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS and X.509. + * PEM_PARSE uses MD5 for decrypting encrypted keys. + */ +#define MBEDTLS_MD5_C + +/** + * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: MBEDTLS_PLATFORM_C + * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C + +/** + * \def MBEDTLS_NET_C + * + * Enable the TCP/IP networking routines. + * + * Module: library/net.c + * + * This module provides TCP/IP networking routines. + */ +#define MBEDTLS_NET_C + +/** + * \def MBEDTLS_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/mbedtls_x509_crl.c + * library/mbedtls_x509_crt.c + * library/mbedtls_x509_csr.c + * library/x509write_crt.c + * library/mbedtls_x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define MBEDTLS_OID_C + +/** + * \def MBEDTLS_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +#define MBEDTLS_PADLOCK_C + +/** + * \def MBEDTLS_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/mbedtls_x509_crl.c + * library/mbedtls_x509_crt.c + * library/mbedtls_x509_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +#define MBEDTLS_PEM_PARSE_C + +/** + * \def MBEDTLS_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/mbedtls_x509write_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +#define MBEDTLS_PEM_WRITE_C + +/** + * \def MBEDTLS_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define MBEDTLS_PK_C + +/** + * \def MBEDTLS_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/mbedtls_x509_crt.c + * library/mbedtls_x509_csr.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define MBEDTLS_PK_PARSE_C + +/** + * \def MBEDTLS_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key write functions. + */ +#define MBEDTLS_PK_WRITE_C + +/** + * \def MBEDTLS_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +#define MBEDTLS_PKCS5_C + +/** + * \def MBEDTLS_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: MBEDTLS_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define MBEDTLS_PKCS11_C + +/** + * \def MBEDTLS_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * Can use: MBEDTLS_ARC4_C + * + * This module enables PKCS#12 functions. + */ +#define MBEDTLS_PKCS12_C + +/** + * \def MBEDTLS_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT + * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * \note This abstraction layer must be enabled on Windows (including MSYS2) + * as other module rely on it for a fixed snprintf implementation. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define MBEDTLS_PLATFORM_C + +/** + * \def MBEDTLS_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/mbedtls_ripemd160.c + * Caller: library/mbedtls_md.c + * + */ +#define MBEDTLS_RIPEMD160_C + +/** + * \def MBEDTLS_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C + */ +#define MBEDTLS_RSA_C + +/** + * \def MBEDTLS_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/mbedtls_sha1.c + * Caller: library/mbedtls_md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS and SHA1-signed certificates. + */ +#define MBEDTLS_SHA1_C + +/** + * \def MBEDTLS_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/mbedtls_sha256.c + * Caller: library/entropy.c + * library/mbedtls_md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define MBEDTLS_SHA256_C + +/** + * \def MBEDTLS_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/mbedtls_sha512.c + * Caller: library/entropy.c + * library/mbedtls_md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define MBEDTLS_SHA512_C + +/** + * \def MBEDTLS_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: MBEDTLS_SSL_CACHE_C + */ +#define MBEDTLS_SSL_CACHE_C + +/** + * \def MBEDTLS_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +#define MBEDTLS_SSL_COOKIE_C + +/** + * \def MBEDTLS_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: MBEDTLS_CIPHER_C + */ +#define MBEDTLS_SSL_TICKET_C + +/** + * \def MBEDTLS_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define MBEDTLS_SSL_CLI_C + +/** + * \def MBEDTLS_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +#define MBEDTLS_SSL_SRV_C + +/** + * \def MBEDTLS_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * and at least one of the MBEDTLS_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +#define MBEDTLS_SSL_TLS_C + +/** + * \def MBEDTLS_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either MBEDTLS_THREADING_ALT or + * MBEDTLS_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +//#define MBEDTLS_THREADING_C + +/** + * \def MBEDTLS_TIMING_C + * + * Enable the portable timing interface. + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +//#define MBEDTLS_TIMING_C + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define MBEDTLS_VERSION_C + +/** + * \def MBEDTLS_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/mbedtls_x509_crl.c + * library/mbedtls_x509_crt.c + * library/mbedtls_x509_csr.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, + * MBEDTLS_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +#define MBEDTLS_X509_USE_C + +/** + * \def MBEDTLS_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/mbedtls_x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#define MBEDTLS_X509_CRT_PARSE_C + +/** + * \def MBEDTLS_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/mbedtls_x509_crl.c + * Caller: library/mbedtls_x509_crt.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +#define MBEDTLS_X509_CRL_PARSE_C + +/** + * \def MBEDTLS_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/mbedtls_x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +#define MBEDTLS_X509_CSR_PARSE_C + +/** + * \def MBEDTLS_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +#define MBEDTLS_X509_CREATE_C + +/** + * \def MBEDTLS_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +#define MBEDTLS_X509_CRT_WRITE_C + +/** + * \def MBEDTLS_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +#define MBEDTLS_X509_CSR_WRITE_C + +/** + * \def MBEDTLS_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +#define MBEDTLS_XTEA_C + +/* \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ +#define MBEDTLS_MPI_WINDOW_SIZE 1 /**< Maximum windows size used. */ +#define MBEDTLS_MPI_MAX_SIZE 512 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* HMAC_DRBG options */ +//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +#define MBEDTLS_ECP_WINDOW_SIZE 2 /**< Maximum window size used */ +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ + +/* Memory buffer allocator options */ +//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +/* Note: your snprintf must correclty zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ + +/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ +/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ +//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ +/* Note: your snprintf must correclty zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ + +/* SSL Cache options */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* SSL options */ +#define MBEDTLS_SSL_MAX_CONTENT_LEN 4096 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */ +//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ +//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +//#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* X509 options */ +//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ + +/* \} name SECTION: Module configuration options */ + +#if defined(TARGET_LIKE_MBED) +#include "mbedtls/target_config.h" +#endif + +/* + * Allow user to override any previous default. + * + * Use two macro names for that, as: + * - with yotta the prefix YOTTA_CFG_ is forced + * - without yotta is looks weird to have a YOTTA prefix. + */ +#if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE) +#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE +#elif defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/extras/mbedtls/mbedtls b/extras/mbedtls/mbedtls new file mode 160000 index 0000000..0a0c22e --- /dev/null +++ b/extras/mbedtls/mbedtls @@ -0,0 +1 @@ +Subproject commit 0a0c22e0efcf2f8f71d7e16712f80b8f77326f72 diff --git a/extras/mbedtls/net_lwip.c b/extras/mbedtls/net_lwip.c new file mode 100644 index 0000000..10dba89 --- /dev/null +++ b/extras/mbedtls/net_lwip.c @@ -0,0 +1,510 @@ +/* + * TCP/IP or UDP/IP networking functions + * modified for LWIP support on ESP8266 + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Additions Copyright (C) 2015 Angus Gratton + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_NET_C) + +#include "mbedtls/net.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +/* + * Prepare for using the sockets interface + */ +static int net_prepare( void ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + WSADATA wsaData; + + if( wsa_init_done == 0 ) + { + if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 ) + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + + wsa_init_done = 1; + } +#else +#endif + return( 0 ); +} + +/* + * Initialize a context + */ +void mbedtls_net_init( mbedtls_net_context *ctx ) +{ + ctx->fd = -1; +} + +/* + * Initiate a TCP connection with host:port and the given protocol + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto ) +{ + int ret; + struct addrinfo hints, *addr_list, *cur; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* Do name resolution with both IPv6 and IPv4 */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + + if( getaddrinfo( host, port, &hints, &addr_list ) != 0 ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a connection succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( ctx->fd < 0 ) + { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( connect( ctx->fd, cur->ai_addr, cur->ai_addrlen ) == 0 ) + { + ret = 0; + break; + } + + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_CONNECT_FAILED; + } + + freeaddrinfo( addr_list ); + + return( ret ); +} + +/* + * Create a listening socket on bind_ip:port + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ) +{ + int n, ret; + struct addrinfo hints, *addr_list, *cur; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + + if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a binding succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( ctx->fd < 0 ) + { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + n = 1; + if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &n, sizeof( n ) ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( bind( ctx->fd, cur->ai_addr, cur->ai_addrlen ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_BIND_FAILED; + continue; + } + + /* Listen only makes sense for TCP */ + if( proto == MBEDTLS_NET_PROTO_TCP ) + { + if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_LISTEN_FAILED; + continue; + } + } + + /* I we ever get there, it's a success */ + ret = 0; + break; + } + + freeaddrinfo( addr_list ); + + return( ret ); + +} + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + ((void) ctx); + return( WSAGetLastError() == WSAEWOULDBLOCK ); +} +#else +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + * + * Note: on a blocking socket this function always returns 0! + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + /* + * Never return 'WOULD BLOCK' on a non-blocking socket + */ + if( ( fcntl( ctx->fd, F_GETFL, 0) & O_NONBLOCK ) != O_NONBLOCK ) + return( 0 ); + + switch( errno ) + { +#if defined EAGAIN + case EAGAIN: +#endif +#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif + return( 1 ); + } + return( 0 ); +} +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +/* + * Accept a connection from a remote client + */ +int mbedtls_net_accept( mbedtls_net_context *bind_ctx, + mbedtls_net_context *client_ctx, + void *client_ip, size_t buf_size, size_t *ip_len ) +{ + int ret; + int type; + + struct sockaddr_in client_addr; + + socklen_t n = (socklen_t) sizeof( client_addr ); + socklen_t type_len = (socklen_t) sizeof( type ); + + /* Is this a TCP or UDP socket? */ + if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE, + (void *) &type, (socklen_t *) &type_len ) != 0 || + ( type != SOCK_STREAM && type != SOCK_DGRAM ) ) + { + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + if( type == SOCK_STREAM ) + { + /* TCP: actual accept() */ + ret = client_ctx->fd = (int) accept( bind_ctx->fd, + (struct sockaddr *) &client_addr, &n ); + } + else + { + /* UDP: wait for a message, but keep it in the queue */ + char buf[1] = { 0 }; + + ret = recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, + (struct sockaddr *) &client_addr, &n ); + +#if defined(_WIN32) + if( ret == SOCKET_ERROR && + WSAGetLastError() == WSAEMSGSIZE ) + { + /* We know buf is too small, thanks, just peeking here */ + ret = 0; + } +#endif + } + + if( ret < 0 ) + { + if( net_would_block( bind_ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + /* UDP: hijack the listening socket to communicate with the client, + * then bind a new socket to accept new connections */ + if( type != SOCK_STREAM ) + { + struct sockaddr_in local_addr; + int one = 1; + + if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + + client_ctx->fd = bind_ctx->fd; + bind_ctx->fd = -1; /* In case we exit early */ + + n = sizeof( struct sockaddr_in ); + if( getsockname( client_ctx->fd, + (struct sockaddr *) &local_addr, &n ) != 0 || + ( bind_ctx->fd = (int) socket( AF_INET, + SOCK_DGRAM, IPPROTO_UDP ) ) < 0 || + setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &one, sizeof( one ) ) != 0 ) + { + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + } + + if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 ) + { + return( MBEDTLS_ERR_NET_BIND_FAILED ); + } + } + + if( client_ip != NULL ) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; + *ip_len = sizeof( addr4->sin_addr.s_addr ); + + if( buf_size < *ip_len ) + return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + + memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len ); + } + + return( 0 ); +} + +/* + * Set the socket blocking or non-blocking + */ +int mbedtls_net_set_block( mbedtls_net_context *ctx ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + u_long n = 0; + return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); +#else + return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL, 0 ) & ~O_NONBLOCK ) ); +#endif +} + +int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + u_long n = 1; + return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); +#else + return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL, 0 ) | O_NONBLOCK ) ); +#endif +} + +/* + * Portable usleep helper + */ +void mbedtls_net_usleep( unsigned long usec ) +{ +#if defined(_WIN32) + Sleep( ( usec + 999 ) / 1000 ); +#else + struct timeval tv; + tv.tv_sec = usec / 1000000; +#if defined(__unix__) || defined(__unix) || \ + ( defined(__APPLE__) && defined(__MACH__) ) + tv.tv_usec = (suseconds_t) usec % 1000000; +#else + tv.tv_usec = usec % 1000000; +#endif + select( 0, NULL, NULL, NULL, &tv ); +#endif +} + +/* + * Read at most 'len' characters + */ +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) +{ + int ret; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + ret = (int) read( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + + return( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + return( ret ); +} + +/* + * Read at most 'len' characters, blocking for at most 'timeout' ms + */ +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, + uint32_t timeout ) +{ + int ret; + struct timeval tv; + fd_set read_fds; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + FD_ZERO( &read_fds ); + FD_SET( fd, &read_fds ); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv ); + + /* Zero fds ready means we timed out */ + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_TIMEOUT ); + + if( ret < 0 ) + { +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAEINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#else + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + + return( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + /* This call will not block */ + return( mbedtls_net_recv( ctx, buf, len ) ); +} + +/* + * Write at most 'len' characters + */ +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ) +{ + int ret; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + ret = (int) write( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_WRITE ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_WRITE ); +#endif + + return( MBEDTLS_ERR_NET_SEND_FAILED ); + } + + return( ret ); +} + +/* + * Gracefully close the connection + */ +void mbedtls_net_free( mbedtls_net_context *ctx ) +{ + if( ctx->fd == -1 ) + return; + + shutdown( ctx->fd, 2 ); + close( ctx->fd ); + + ctx->fd = -1; +} + +#endif /* MBEDTLS_NET_C */ diff --git a/ld/eagle.app.v6.ld b/ld/eagle.app.v6.ld index f1d11cc..3a52fed 100644 --- a/ld/eagle.app.v6.ld +++ b/ld/eagle.app.v6.ld @@ -136,6 +136,68 @@ SECTIONS _dport0_data_end = ABSOLUTE(.); } >dport0_0_seg :dport0_0_phdr + .text : ALIGN(4) /* IRAM */ + { + _stext = .; + _text_start = ABSOLUTE(.); + . = ALIGN (16); + *(.vecbase.text) + *(.entry.text) + *(.init.literal) + *(.init) + /* esp-open-rtos compiled source files use the .iram1.* section names for IRAM + functions, etc. */ + *(.iram1.*) + /* SDK libraries expect their .text sections to link to iram, not irom */ + *sdklib*:*(.literal .text .literal.* .text.*) + /* libgcc integer functions also need to be in .text, as some are called before + flash is mapped (also performance) + */ + *libgcc.a:*i3.o(.literal .text .literal.* .text.*) + + /* libc also in IRAM */ + *libc.a:*malloc.o(.literal .text .literal.* .text.*) + *libc.a:*mallocr.o(.literal .text .literal.* .text.*) + *libc.a:*freer.o(.literal .text .literal.* .text.*) + *libc.a:*memcpy.o(.literal .text .literal.* .text.*) + *libc.a:*memset.o(.literal .text .literal.* .text.*) + *libc.a:*memcmp.o(.literal .text .literal.* .text.*) + *libc.a:*memmove.o(.literal .text .literal.* .text.*) + *libc.a:*rand.o(.literal .text .literal.* .text.*) + *libc.a:*bzero.o(.literal .text .literal.* .text.*) + *libc.a:*lock.o(.literal .text .literal.* .text.*) + + *libc.a:*printf.o(.literal .text .literal.* .text.*) + *libc.a:*findfp.o(.literal .text .literal.* .text.*) + *libc.a:*fputwc.o(.literal .text .literal.* .text.*) + + /* xthal_set_intset() called from PendSV in NMI context */ + *libhal.a:*set_intset.o(.literal .text .literal.* .text.*) + + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + } >iram1_0_seg :iram1_0_phdr + + .irom0.text : ALIGN(4) + { + _irom0_text_start = ABSOLUTE(.); + /* esp-open-rtos compiled code goes into IROM by default + (except for libgcc which is matched above.) + */ + *(.literal .text .literal.* .text.*) + /* mbedtls rodata */ + *mbedtls.a:*.o(.rodata.* .rodata) + /* actual certificate in example (TEMPORARY HACK) */ + *:cert.o(.rodata.* .rodata) + /* Anything explicitly marked as "irom" or "irom0" should go here */ + *(.irom.* .irom.*.* .irom0.*) + _irom0_text_end = ABSOLUTE(.); + } >irom0_0_seg :irom0_0_phdr + .data : ALIGN(4) { _data_start = ABSOLUTE(.); @@ -218,63 +280,6 @@ SECTIONS } >dram0_0_seg :dram0_0_bss_phdr /* __stack = 0x3ffc8000; */ - .text : ALIGN(4) /* IRAM */ - { - _stext = .; - _text_start = ABSOLUTE(.); - . = ALIGN (16); - *(.vecbase.text) - *(.entry.text) - *(.init.literal) - *(.init) - /* esp-open-rtos compiled source files use the .iram1.* section names for IRAM - functions, etc. */ - *(.iram1.*) - /* SDK libraries expect their .text sections to link to iram, not irom */ - *sdklib*:*(.literal .text .literal.* .text.*) - /* libgcc integer functions also need to be in .text, as some are called before - flash is mapped (also performance) - */ - *libgcc.a:*i3.o(.literal .text .literal.* .text.*) - - /* libc also in IRAM */ - *libc.a:*malloc.o(.literal .text .literal.* .text.*) - *libc.a:*mallocr.o(.literal .text .literal.* .text.*) - *libc.a:*freer.o(.literal .text .literal.* .text.*) - *libc.a:*memcpy.o(.literal .text .literal.* .text.*) - *libc.a:*memset.o(.literal .text .literal.* .text.*) - *libc.a:*memcmp.o(.literal .text .literal.* .text.*) - *libc.a:*memmove.o(.literal .text .literal.* .text.*) - *libc.a:*rand.o(.literal .text .literal.* .text.*) - *libc.a:*bzero.o(.literal .text .literal.* .text.*) - *libc.a:*lock.o(.literal .text .literal.* .text.*) - - *libc.a:*printf.o(.literal .text .literal.* .text.*) - *libc.a:*findfp.o(.literal .text .literal.* .text.*) - *libc.a:*fputwc.o(.literal .text .literal.* .text.*) - - /* xthal_set_intset() called from PendSV in NMI context */ - *libhal.a:*set_intset.o(.literal .text .literal.* .text.*) - - *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) - *(.fini.literal) - *(.fini) - *(.gnu.version) - _text_end = ABSOLUTE(.); - _etext = .; - } >iram1_0_seg :iram1_0_phdr - - .irom0.text : ALIGN(4) - { - _irom0_text_start = ABSOLUTE(.); - /* esp-open-rtos compiled code goes into IROM by default - (except for libgcc which is matched above.) - */ - *(.literal .text .literal.* .text.*) - /* Anything explicitly marked as "irom" or "irom0" should go here */ - *(.irom.* .irom.*.* .irom0.*) - _irom0_text_end = ABSOLUTE(.); - } >irom0_0_seg :irom0_0_phdr .lit4 : ALIGN(4) { diff --git a/lwip/component.mk b/lwip/component.mk index e16baa0..1bbe21c 100644 --- a/lwip/component.mk +++ b/lwip/component.mk @@ -1,7 +1,7 @@ # Component makefile for LWIP LWIP_DIR = $(lwip_ROOT)lwip/src/ -INC_DIRS += $(LWIP_DIR)include $(ROOT)lwip/include $(lwip_ROOT)include $(LWIP_DIR)include/ipv4 $(LWIP_DIR)include/ipv4/lwip $(LWIP_DIR)include/lwip +INC_DIRS += $(LWIP_DIR)include $(ROOT)lwip/include $(lwip_ROOT)include $(LWIP_DIR)include/posix $(LWIP_DIR)include/ipv4 $(LWIP_DIR)include/ipv4/lwip $(LWIP_DIR)include/lwip # args for passing into compile rule generation lwip_INC_DIR = # all in INC_DIRS, needed for normal operation From b03f279f747197c5ab1621b0852f0bd949e68109 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 18 Sep 2015 15:12:09 +1000 Subject: [PATCH 45/56] mbedTLS: Add ESP8266 hardware entropy source discovered by @foogod Addresses #3, provided turns out to be an effective HWRNG. --- core/include/esp/wdev_regs.h | 44 +++++++++++++++++++++++++ extras/mbedtls/hardware_entropy.c | 27 +++++++++++++++ extras/mbedtls/include/mbedtls/config.h | 8 +++-- 3 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 core/include/esp/wdev_regs.h create mode 100644 extras/mbedtls/hardware_entropy.c diff --git a/core/include/esp/wdev_regs.h b/core/include/esp/wdev_regs.h new file mode 100644 index 0000000..bc7d54b --- /dev/null +++ b/core/include/esp/wdev_regs.h @@ -0,0 +1,44 @@ +/* esp/dport_regs.h + * + * ESP8266 WDEV register definitions + * + * In the DPORT memory space, alongside DPORT regs. However mostly + * concerned with the WiFi hardware interface. + * + * Not well understood at all, 100% figured out via reverse engineering. + */ + +#ifndef _ESP_WDEV__REGS_H +#define _ESP_WDEV__REGS_H + +#include "esp/types.h" +#include "common_macros.h" + +#define WDEV_BASE 0x3ff20e00 +#define WDEV (*(struct WDEV_REGS *)(WDEV_BASE)) + +/* WDEV registers +*/ + +struct WDEV_REGS { + uint32_t volatile _unknown00; // 0x00 + uint32_t volatile _unknown04; // 0x04 + uint32_t volatile _unknown08; // 0x08 + uint32_t volatile _unknown0c; // 0x0c + uint32_t volatile _unknown10; // 0x10 + uint32_t volatile _unknown14; // 0x14 + uint32_t volatile _unknown18; // 0x18 + uint32_t volatile _unknown1c; // 0x1c + uint32_t volatile _unknown20; // 0x20 + uint32_t volatile _unknown24; // 0x24 + uint32_t volatile _unknown28; // 0x28 + uint32_t volatile _unknown2c; // 0x2c + uint32_t volatile _unknown30; // 0x30 + uint32_t volatile _unknown34; // 0x34 + uint32_t volatile _unknown38; // 0x38 + uint32_t volatile _unknown3c; // 0x3c + uint32_t volatile _unknown40; // 0x40 + uint32_t volatile HWRNG; // 0x44 Appears to be HW RNG, see https://github.com/SuperHouse/esp-open-rtos/issues/3#issuecomment-139453094 +}; + +#endif diff --git a/extras/mbedtls/hardware_entropy.c b/extras/mbedtls/hardware_entropy.c new file mode 100644 index 0000000..85dd00d --- /dev/null +++ b/extras/mbedtls/hardware_entropy.c @@ -0,0 +1,27 @@ +/* ESP8266 "Hardware RNG" (validity still being confirmed) support for ESP8266 + * + * Based on research done by @foogod. + * + * Please don't rely on this too much as an entropy source, quite yet... + * + * Part of esp-open-rtos + * Copyright (C) 2015 Angus Gratton + * BSD Licensed as described in the file LICENSE + */ +#include +#include +#include + +int mbedtls_hardware_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + (void)(data); + for(int i = 0; i < len; i+=4) { + uint32_t random = WDEV.HWRNG; + /* using memcpy here in case output is unaligned */ + memcpy(output + i, &random, (i+4 <= len) ? 4 : (len % 4)); + } + if(olen) + *olen = len; + return 0; +} diff --git a/extras/mbedtls/include/mbedtls/config.h b/extras/mbedtls/include/mbedtls/config.h index 903006d..54ce5be 100644 --- a/extras/mbedtls/include/mbedtls/config.h +++ b/extras/mbedtls/include/mbedtls/config.h @@ -289,7 +289,8 @@ * * Uncomment to use your own hardware entropy collector. */ -//#define MBEDTLS_ENTROPY_HARDWARE_ALT +/* hardware RNG interface provided in hardware_entropy.c */ +#define MBEDTLS_ENTROPY_HARDWARE_ALT /** * \def MBEDTLS_AES_ROM_TABLES @@ -777,7 +778,7 @@ * This option is only useful if both MBEDTLS_SHA256_C and * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. */ -//#define MBEDTLS_ENTROPY_FORCE_SHA256 +#define MBEDTLS_ENTROPY_FORCE_SHA256 /** * \def MBEDTLS_MEMORY_DEBUG @@ -2350,7 +2351,8 @@ /* CTR_DRBG options */ //#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ -//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +/* this is normally 10x higher, but reseeding seems quite inexpensive on esp8266 */ +#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 1000 /**< Interval before reseed is performed by default */ //#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ //#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ //#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ From 59a0a6f86e1a1a987f2b89537d3acac0070e3568 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Sun, 20 Sep 2015 21:41:39 +1000 Subject: [PATCH 46/56] http_get_mbedtls: Add root cert used by howmyssl.com --- examples/http_get_mbedtls/cert.c | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 examples/http_get_mbedtls/cert.c diff --git a/examples/http_get_mbedtls/cert.c b/examples/http_get_mbedtls/cert.c new file mode 100644 index 0000000..a0050a6 --- /dev/null +++ b/examples/http_get_mbedtls/cert.c @@ -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 +#include +#include + +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"; + + From f1bff97103c56748ef672b62330e05341911937b Mon Sep 17 00:00:00 2001 From: Alex Stewart Date: Mon, 21 Sep 2015 22:13:14 -0700 Subject: [PATCH 47/56] Further optimizations for LoadStoreErrorHandler --- core/exception_unaligned_load.S.inc | 190 ------------------- core/exception_vectors.S | 278 +++++++++++++++++++++++++++- 2 files changed, 268 insertions(+), 200 deletions(-) delete mode 100644 core/exception_unaligned_load.S.inc diff --git a/core/exception_unaligned_load.S.inc b/core/exception_unaligned_load.S.inc deleted file mode 100644 index 03c9830..0000000 --- a/core/exception_unaligned_load.S.inc +++ /dev/null @@ -1,190 +0,0 @@ -/* Xtensa Exception unaligned load handler - - Completes l8/l16 load instructions from Instruction address space, - that the architecture require to be 4 byte aligned word reads. - - Called from either UserExceptionVector or DoubleExceptionVector - depending on where the exception happened. - - Fast path (no branches) is for l8ui. - - Part of esp-open-rtos - Copyright (C) Angus Gratton - BSD Licensed as described in the file LICENSE -*/ - .text - .section .vecbase.text, "x" - .literal_position - -/* "Fix" LoadStoreException exceptions that are l8/l16 from an Instruction region, - normal exception variant. */ -UserExceptionLoadStoreHandler: - addi sp, sp, -0x18 - s32i a2, sp, 0x08 - rsr.epc1 a2 -/* Inner UserLoadStoreExceptionHandler handlers. Works for both level1 & level 2 interrupt level. - * - * Called from level-specific handler above which sets up stack and loads epcX into a2. - */ -InnerLoadStoreExceptionHandler: - s32i a3, sp, 0x0c - s32i a4, sp, 0x10 - s32i a5, sp, 0x14 - rsr.sar a0 // save sar in a0 - - /* Examine the instruction we failed to execute (in a2) */ - ssa8l a2 // sar is now correct shift for aligned read - movi a3, ~3 - and a2, a2, a3 // a2 now 4-byte aligned address of instruction - l32i a3, a2, 0 - l32i a4, a2, 4 - src a2, a4, a3 // a2 now instruction that failed - - /* check for l8ui opcode 0x000002, or branch to check l16 */ - movi a3, 0x00700F /* opcode mask for l8ui/l16si/l16ui */ - and a3, a2, a3 - bnei a3, 0x000002, .Lcheck_fix_16bit - movi a5, 0xFF - -.Lcan_fix: - /* verified an 8- or 16-bit read - a2 holds instruction, a5 holds mask to apply to read value - */ - rsr.excvaddr a3 // read faulting address - ssa8l a3 /* sar is now shift to extract a3's byte */ - movi a4, ~3 - and a3, a3, a4 /* a3 now word aligned read address */ - - l32i a3, a3, 0 /* perform the actual read */ - srl a3, a3 /* shift right correct distance */ - and a4, a3, a5 /* mask off bits we need for an l8/l16 */ - - bbsi a5, 14, .Lmaybe_extend_sign -.Lafter_extend_sign: - /* a2 holds instruction, a4 holds the correctly read value */ - extui a2, a2, 4, 4 /* a2 now destination register 0-15 */ - - /* test if a4 needs to be written directly to a register (ie not a working register) */ - bgei a2, 6, .Lwrite_value_direct_reg - /* test if a4 needs to be written to a0 */ - beqz a2, .Lwrite_value_a0_reg - - /* otherwise, a4 can be written to a saved working register 'slot' on the stack */ - addx4 a5, a2, sp - s32i a4, a5, 0 - -.Lafter_write_value: - /* test PS.INTLEVEL (1=User, 2=Double) to see which interrupt level we restore from - */ - rsr.ps a2 - bbsi a2, 1, .Lincrement_PC_intlevel2 -.Lincrement_PC_intlevel1: - rsr.epc1 a2 - addi a3, a2, 0x3 - wsr.epc1 a3 - wsr.sar a0 // restore saved sar - rsr.excsave1 a0 // restore a0 saved in exception vector -.Lafter_increment_PC: - // Restore registers - l32i a2, sp, 0x08 - l32i a3, sp, 0x0c - l32i a4, sp, 0x10 - l32i a5, sp, 0x14 - addi sp, sp, 0x18 - rfe - - -/* Check the load instruction a2 for an l16si/16ui instruction - - First test for a signed vs unsigned load. - - a2 is the instruction, need to load a5 with the mask to use */ -.Lcheck_fix_16bit: - movi a4, 0x001002 /* l16si or l16ui opcode after masking */ - bne a3, a4, .Lcant_fix - - bbsi a2, 15, .Lcan_fix_16bit_signed - movi a5, 0xFFFF - j .Lcan_fix -.Lcan_fix_16bit_signed: - movi a5, 0x7FFF - j .Lcan_fix - -/* not an opcode we can try to fix, so bomb out - TODO: the exception dump will have some wrong values in it */ -.Lcant_fix: - call0 sdk_user_fatal_exception_handler - -/* increment PC for a DoubleException */ -.Lincrement_PC_intlevel2: - rsr.epc2 a2 - addi a3, a2, 0x3 - wsr.epc2 a3 - wsr.sar a0 // restore saved sar - rsr.excsave2 a0 // restore a0 saved in exception vector - j .Lafter_increment_PC - -.Lmaybe_extend_sign: /* apply 16-bit sign extension if necessary - a3 holds raw value, a4 holds masked */ - bbsi a5, 15, .Lafter_extend_sign /* 16-bit unsigned, no sign extension */ - bbci a3, 15, .Lafter_extend_sign /* sign bit not set, no sign extension */ - movi a3, 0xFFFF8000 - or a4, a3, a4 /* set 32-bit sign bits */ - j .Lafter_extend_sign - -.Lwrite_value_direct_reg: - /* Directly update register index a2, in range 6-15, using value in a4 */ - addi a2, a2, -6 - slli a2, a2, 3 /* offset from a6, x8 */ - movi a3, .Ldirect_reg_jumptable - add a2, a2, a3 - jx a2 - .align 8 -.Ldirect_reg_jumptable: - mov a6, a4 - j .Lafter_write_value - .align 8 - mov a7, a4 - j .Lafter_write_value - .align 8 - mov a8, a4 - j .Lafter_write_value - .align 8 - mov a9, a4 - j .Lafter_write_value - .align 8 - mov a10, a4 - j .Lafter_write_value - .align 8 - mov a11, a4 - j .Lafter_write_value - .align 8 - mov a12, a4 - j .Lafter_write_value - .align 8 - mov a13, a4 - j .Lafter_write_value - .align 8 - mov a14, a4 - j .Lafter_write_value - .align 8 - mov a15, a4 - j .Lafter_write_value - -.Lwrite_value_a0_reg: - /* a0 is saved in excsave1,so just update this with value - TODO: This won't work with interrupt level 2 - */ - wsr.excsave1 a4 - j .Lafter_write_value - - .literal_position -/* "Fix" LoadStoreException exceptions that are l8/l16 from an Instruction region, - DoubleException exception variant (ie load happened in a level1 exception handler). */ -DoubleExceptionLoadStoreHandler: - addi sp, sp, -0x18 - s32i a2, sp, 0x08 - rsr.epc2 a2 - j InnerLoadStoreExceptionHandler - -/* End of InnerUserLoadStoreExceptionHandler */ diff --git a/core/exception_vectors.S b/core/exception_vectors.S index 270b711..a577034 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -26,7 +26,6 @@ .text .section .vecbase.text, "x" .global VecBase - .type VecBase, @function /* it's not really a function, but treat it like one */ .org 0 VecBase: /* IMPORTANT: exception vector literals will go here, but we @@ -36,35 +35,38 @@ VecBase: */ .literal_position .org 0x10 + .type DebugExceptionVector, @function DebugExceptionVector: wsr.excsave2 a0 call0 sdk_user_fatal_exception_handler rfi 2 .org 0x20 + .type NMIExceptionVector, @function NMIExceptionVector: wsr.excsave3 a0 call0 CallNMIExceptionHandler rfi 3 /* CallNMIExceptionHandler should call rfi itself */ .org 0x30 + .type KernelExceptionVector, @function KernelExceptionVector: break 1, 0 call0 sdk_user_fatal_exception_handler rfe .org 0x50 + .type UserExceptionVector, @function UserExceptionVector: wsr.excsave1 a0 rsr.exccause a0 - beqi a0, CAUSE_LOADSTORE, UserExceptionLoadStoreHandler + beqi a0, CAUSE_LOADSTORE, LoadStoreErrorHandler j UserExceptionHandler .org 0x70 + .type DoubleExceptionVector, @function DoubleExceptionVector: break 1, 4 - rsr.exccause a0 - beqi a0, CAUSE_LOADSTORE, DoubleExceptionLoadStoreHandler call0 sdk_user_fatal_exception_handler /* Reset vector would go here at offset 0x80 but should be unused, @@ -72,10 +74,260 @@ DoubleExceptionVector: /***** end of exception vectors *****/ -/* We include this here so UserExceptionLoadStoreHandler is within - the range of a 'beq' instruction jump. +/* Xtensa Exception unaligned load handler + + Completes l8/l16 load instructions from Instruction address space, + for which the architecture only supports 32-bit reads. + + Called from UserExceptionVector if EXCCAUSE is LoadStoreErrorCause + + Fast path (no branches) is for l8ui. */ -#include "exception_unaligned_load.S.inc" + .literal_position + + .type LoadStoreErrorHandler, @function +LoadStoreErrorHandler: + # Note: we use a0 as our "stack pointer" here because it's already been + # saved in UserExceptionVector, and we never call out to other routines + # so we don't have to worry about it being clobbered. It would be + # preferable to use a1 instead, but this would require changes to other + # parts of UserExceptionHandler code which we haven't gotten around to + # yet. + # TODO: Eventually, switch everything over to saving a1 instead of a0 + # in UserExceptionVector so we can use the more mnemonic SP for this. + + # Note: registers are saved in the (regnum * 4) address so calculation + # is easier later on. This means we don't use the first two entries + # (since we don't save a0 or a1 here), so we just adjust the pointer in + # a0 to pretend we have two extra slots at the beginning. + movi a0, LoadStoreErrorHandlerStack - 8 + s32i a2, a0, 0x08 + s32i a3, a0, 0x0c + s32i a4, a0, 0x10 + s32i a5, a0, 0x14 + rsr.sar a5 # Save SAR in a5 to restore later + + # Examine the opcode which generated the exception + # Note: Instructions are in this order to avoid pipeline stalls. + rsr.epc1 a2 + movi a3, ~3 + ssa8l a2 // sar is now correct shift for aligned read + and a2, a2, a3 // a2 now 4-byte aligned address of instruction + l32i a4, a2, 0 + l32i a2, a2, 4 + movi a3, 0x00700F // opcode mask for l8ui/l16si/l16ui + src a2, a2, a4 // a2 now instruction that failed + and a3, a2, a3 + bnei a3, 0x000002, .LSE_check_l16 + + # Note: At this point, opcode could technically be one of two things: + # xx0xx2 (L8UI) + # xx8xx2 (Reserved (invalid) opcode) + # It is assumed that we'll never get to this point from an illegal + # opcode, so we don't bother to check for that case and presume this is + # always an L8UI. + + /* a2 holds instruction */ + movi a4, ~3 + rsr.excvaddr a3 // read faulting address + and a4, a3, a4 /* a4 now word aligned read address */ + + l32i a4, a4, 0 /* perform the actual read */ + ssa8l a3 /* sar is now shift to extract a3's byte */ + srl a3, a4 /* shift right correct distance */ + extui a4, a3, 0, 8 /* mask off bits we need for an l8 */ + +.LSE_post_fetch: + # We jump back here after either the L8UI or the L16*I routines do the + # necessary work to read the value from memory. + # At this point, a2 holds the faulting instruction and a4 holds the + # correctly read value. + + # Restore original SAR value (saved in a5) and update EPC so we'll + # return back to the instruction following the one we just emulated + # Note: Instructions are in this order to avoid pipeline stalls + rsr.epc1 a3 + wsr.sar a5 + addi a3, a3, 0x3 + wsr.epc1 a3 + + # Stupid opcode tricks: The jumptable we use later on needs 16 bytes + # per entry (so we can avoid a second jump by just doing a RFE inside + # each entry). Unfortunately, however, Xtensa doesn't have an addx16 + # operation to make that easy for us. Luckily, all of the faulting + # opcodes we're processing are guaranteed to have bit 3 be zero, which + # means if we just shift the register bits of the opcode down by 3 + # instead of 4, we will get the register number multiplied by 2. This + # combined with an addx8 will give us an effective addx16 without + # needing any extra shift operations. + extui a2, a2, 3, 5 /* a2 now destination register 0-15 times 2 */ + + bgei a2, 12, .LSE_assign_reg # a6..a15 use jumptable + blti a2, 4, .LSE_assign_reg # a0..a1 use jumptable + + # We're storing into a2..a5, which are all saved in our "stack" area. + # Calculate the correct address and stick the value in there, then just + # do our normal restore and RFE (no jumps required, which actually + # makes a2..a5 substantially faster). + addx2 a2, a2, a0 + s32i a4, a2, 0 + + # Restore all regs and return + l32i a2, a0, 0x08 + l32i a3, a0, 0x0c + l32i a4, a0, 0x10 + l32i a5, a0, 0x14 + rsr.excsave1 a0 # restore a0 saved by UserExceptionVector + rfe + +.LSE_assign_reg: + # At this point, a2 contains the register number times 2, a4 is the + # read value. + + movi a3, .LSE_assign_jumptable + addx8 a2, a2, a3 # a2 is now the address to jump to + + # Restore everything except a2 and a4 + l32i a3, a0, 0x0c + l32i a5, a0, 0x14 + + jx a2 + +/* Check the load instruction a2 for an l16si/16ui instruction + + a2 is the instruction, a3 is masked instruction */ + .balign 4 +.LSE_check_l16: + movi a4, 0x001002 /* l16si or l16ui opcode after masking */ + bne a3, a4, .LSE_wrong_opcode + + # Note: At this point, the opcode could be one of two things: + # xx1xx2 (L16UI) + # xx9xx2 (L16SI) + # Both of these we can handle. + + movi a4, ~3 + rsr.excvaddr a3 // read faulting address + and a4, a3, a4 /* a4 now word aligned read address */ + + l32i a4, a4, 0 /* perform the actual read */ + ssa8l a3 /* sar is now shift to extract a3's byte */ + srl a3, a4 /* shift right correct distance */ + extui a4, a3, 0, 16 /* mask off bits we need for an l16 */ + + bbci a2, 15, .LSE_post_fetch # Not a signed op + bbci a4, 15, .LSE_post_fetch # Value does not require sign-extension + + movi a3, 0xFFFF0000 + or a4, a3, a4 /* set 32-bit sign bits */ + j .LSE_post_fetch + +/* If we got here it's not an opcode we can try to fix, so bomb out */ +.LSE_wrong_opcode: + # Restore registers so any dump the fatal exception routine produces + # will have correct values + wsr.sar a5 # Restore SAR saved in a5 + l32i a2, a0, 0x08 + l32i a3, a0, 0x0c + l32i a4, a0, 0x10 + l32i a5, a0, 0x14 + call0 sdk_user_fatal_exception_handler + + .balign 4 +.LSE_assign_jumptable: + .org .LSE_assign_jumptable + (16 * 0) + # a0 is saved in excsave1, so just update that with the value + wsr.excsave1 a4 + l32i a2, a0, 0x08 + l32i a4, a0, 0x10 + rsr.excsave1 a0 + rfe + + .org .LSE_assign_jumptable + (16 * 1) + mov a1, a4 + l32i a2, a0, 0x08 + l32i a4, a0, 0x10 + rsr.excsave1 a0 + rfe + + # NOTE: Opcodes a2 .. a5 are not handled by the jumptable routines + # (they're taken care of directly in .LSE_post_fetch above) + # This leaves 64 bytes of wasted space here. We could fill it with + # other things, but that would just make it harder to understand what's + # going on, and that's bad enough with this routine already. Even on + # the ESP8266, 64 bytes of IRAM wasted aren't the end of the world.. + + .org .LSE_assign_jumptable + (16 * 6) + mov a6, a4 + l32i a2, a0, 0x08 + l32i a4, a0, 0x10 + rsr.excsave1 a0 + rfe + + .org .LSE_assign_jumptable + (16 * 7) + mov a7, a4 + l32i a2, a0, 0x08 + l32i a4, a0, 0x10 + rsr.excsave1 a0 + rfe + + .org .LSE_assign_jumptable + (16 * 8) + mov a8, a4 + l32i a2, a0, 0x08 + l32i a4, a0, 0x10 + rsr.excsave1 a0 + rfe + + .org .LSE_assign_jumptable + (16 * 9) + mov a9, a4 + l32i a2, a0, 0x08 + l32i a4, a0, 0x10 + rsr.excsave1 a0 + rfe + + .org .LSE_assign_jumptable + (16 * 10) + mov a10, a4 + l32i a2, a0, 0x08 + l32i a4, a0, 0x10 + rsr.excsave1 a0 + rfe + + .org .LSE_assign_jumptable + (16 * 11) + mov a11, a4 + l32i a2, a0, 0x08 + l32i a4, a0, 0x10 + rsr.excsave1 a0 + rfe + + .org .LSE_assign_jumptable + (16 * 12) + mov a12, a4 + l32i a2, a0, 0x08 + l32i a4, a0, 0x10 + rsr.excsave1 a0 + rfe + + .org .LSE_assign_jumptable + (16 * 13) + mov a13, a4 + l32i a2, a0, 0x08 + l32i a4, a0, 0x10 + rsr.excsave1 a0 + rfe + + .org .LSE_assign_jumptable + (16 * 14) + mov a14, a4 + l32i a2, a0, 0x08 + l32i a4, a0, 0x10 + rsr.excsave1 a0 + rfe + + .org .LSE_assign_jumptable + (16 * 15) + mov a15, a4 + l32i a2, a0, 0x08 + l32i a4, a0, 0x10 + rsr.excsave1 a0 + rfe + +/* End of LoadStoreErrorHandler */ .section .bss NMIHandlerStack: /* stack space for NMI handler */ @@ -84,6 +336,12 @@ NMIHandlerStack: /* stack space for NMI handler */ NMIRegisterSaved: /* register space for saving NMI registers */ .skip 4*(16 + 6) +LoadStoreErrorHandlerStack: + .word 0 # a2 + .word 0 # a3 + .word 0 # a4 + .word 0 # a5 + /* Save register relative to a0 */ .macro SAVE_REG register, regnum s32i \register, a0, (0x20 + 4 * \regnum) @@ -181,7 +439,7 @@ CallNMIExceptionHandler: .type UserExceptionHandler, @function UserExceptionHandler: - mov a0, sp /* a0 was saved in UserExceptionVector */ + mov a0, sp /* a0 was saved by UserExceptionVector */ addi sp, sp, -0x50 s32i a0, sp, 0x10 rsr.ps a0 @@ -214,7 +472,7 @@ UserHandleTimer: and a3, a2, a3 /* a3 = a2 & 0xFFBF, ie remove 0x40 from a2 if set */ bnez a3, UserTimerDone /* bits other than 0x40 are set */ movi a3, 0x40 - sub a12, a2, a3 /* a12 - a2 - 0x40 - I think a12 _must_ be zero here? */ + sub a12, a2, a3 /* a12 = a2 - 0x40 -- Will be zero if bit 6 set */ call0 sdk__xt_timer_int /* tick timer interrupt */ mov a2, a12 /* restore a2 from a12, ie zero */ beqz a2, UserIntDone @@ -226,7 +484,7 @@ UserIntDone: break 1, 1 /* non-zero remnant in a2 means fail */ call0 sdk_user_fatal_exception_handler UserIntExit: - call0 sdk__xt_int_exit /* calls rfi */ + call0 sdk__xt_int_exit /* jumps to _xt_user_exit. Never returns here */ /* _xt_user_exit is used to exit interrupt context. TODO: Find a better place for this to live. From b15d149b09ef7066e8fd946604c9d6c28e23ff20 Mon Sep 17 00:00:00 2001 From: Alex Stewart Date: Wed, 23 Sep 2015 08:51:36 -0700 Subject: [PATCH 48/56] More LoadStoreErrorHandler performance improvements --- core/exception_vectors.S | 207 +++++++++++++++++++-------------------- 1 file changed, 102 insertions(+), 105 deletions(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index a577034..a8d513a 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -58,9 +58,9 @@ KernelExceptionVector: .org 0x50 .type UserExceptionVector, @function UserExceptionVector: - wsr.excsave1 a0 - rsr.exccause a0 - beqi a0, CAUSE_LOADSTORE, LoadStoreErrorHandler + wsr.excsave1 a1 + rsr.exccause a1 + beqi a1, CAUSE_LOADSTORE, LoadStoreErrorHandler j UserExceptionHandler .org 0x70 @@ -87,25 +87,15 @@ DoubleExceptionVector: .type LoadStoreErrorHandler, @function LoadStoreErrorHandler: - # Note: we use a0 as our "stack pointer" here because it's already been - # saved in UserExceptionVector, and we never call out to other routines - # so we don't have to worry about it being clobbered. It would be - # preferable to use a1 instead, but this would require changes to other - # parts of UserExceptionHandler code which we haven't gotten around to - # yet. - # TODO: Eventually, switch everything over to saving a1 instead of a0 - # in UserExceptionVector so we can use the more mnemonic SP for this. - - # Note: registers are saved in the (regnum * 4) address so calculation - # is easier later on. This means we don't use the first two entries - # (since we don't save a0 or a1 here), so we just adjust the pointer in - # a0 to pretend we have two extra slots at the beginning. - movi a0, LoadStoreErrorHandlerStack - 8 - s32i a2, a0, 0x08 - s32i a3, a0, 0x0c - s32i a4, a0, 0x10 - s32i a5, a0, 0x14 - rsr.sar a5 # Save SAR in a5 to restore later + # Note: registers are saved in the address corresponding to their + # register number times 4. This allows a quick and easy mapping later + # on when needing to store the value to a particular register number. + movi sp, LoadStoreErrorHandlerStack + s32i a0, sp, 0 + s32i a2, sp, 0x08 + s32i a3, sp, 0x0c + s32i a4, sp, 0x10 + rsr.sar a0 # Save SAR in a0 to restore later # Examine the opcode which generated the exception # Note: Instructions are in this order to avoid pipeline stalls. @@ -143,11 +133,11 @@ LoadStoreErrorHandler: # At this point, a2 holds the faulting instruction and a4 holds the # correctly read value. - # Restore original SAR value (saved in a5) and update EPC so we'll + # Restore original SAR value (saved in a0) and update EPC so we'll # return back to the instruction following the one we just emulated # Note: Instructions are in this order to avoid pipeline stalls rsr.epc1 a3 - wsr.sar a5 + wsr.sar a0 addi a3, a3, 0x3 wsr.epc1 a3 @@ -162,34 +152,35 @@ LoadStoreErrorHandler: # needing any extra shift operations. extui a2, a2, 3, 5 /* a2 now destination register 0-15 times 2 */ - bgei a2, 12, .LSE_assign_reg # a6..a15 use jumptable - blti a2, 4, .LSE_assign_reg # a0..a1 use jumptable + bgei a2, 10, .LSE_assign_reg # a5..a15 use jumptable + beqi a2, 2, .LSE_assign_a1 # a1 uses a special routine - # We're storing into a2..a5, which are all saved in our "stack" area. + # We're storing into a0 or a2..a4, which are all saved in our "stack" area. # Calculate the correct address and stick the value in there, then just # do our normal restore and RFE (no jumps required, which actually - # makes a2..a5 substantially faster). - addx2 a2, a2, a0 + # makes a0..a4 substantially faster). + addx2 a2, a2, sp s32i a4, a2, 0 # Restore all regs and return - l32i a2, a0, 0x08 - l32i a3, a0, 0x0c - l32i a4, a0, 0x10 - l32i a5, a0, 0x14 - rsr.excsave1 a0 # restore a0 saved by UserExceptionVector + l32i a0, sp, 0 + l32i a2, sp, 0x08 + l32i a3, sp, 0x0c + l32i a4, sp, 0x10 + rsr.excsave1 a1 # restore a1 saved by UserExceptionVector rfe .LSE_assign_reg: # At this point, a2 contains the register number times 2, a4 is the # read value. - movi a3, .LSE_assign_jumptable - addx8 a2, a2, a3 # a2 is now the address to jump to - - # Restore everything except a2 and a4 - l32i a3, a0, 0x0c - l32i a5, a0, 0x14 + # Calculate the jumptable address, and restore regs except a2 and a4 + # so we have less to do after jumping. + # Note: Instructions are in this order to avoid pipeline stalls. + movi a3, .LSE_jumptable_base + l32i a0, sp, 0 + addx8 a2, a2, a3 # a2 is now the address to jump to + l32i a3, sp, 0x0c jx a2 @@ -226,105 +217,109 @@ LoadStoreErrorHandler: .LSE_wrong_opcode: # Restore registers so any dump the fatal exception routine produces # will have correct values - wsr.sar a5 # Restore SAR saved in a5 - l32i a2, a0, 0x08 - l32i a3, a0, 0x0c - l32i a4, a0, 0x10 - l32i a5, a0, 0x14 + wsr.sar a0 # Restore SAR saved in a0 + l32i a0, sp, 0 + l32i a2, sp, 0x08 + l32i a3, sp, 0x0c + l32i a4, sp, 0x10 + rsr.excsave1 a1 call0 sdk_user_fatal_exception_handler .balign 4 -.LSE_assign_jumptable: - .org .LSE_assign_jumptable + (16 * 0) - # a0 is saved in excsave1, so just update that with the value +.LSE_assign_a1: + # a1 is saved in excsave1, so just update that with the value wsr.excsave1 a4 - l32i a2, a0, 0x08 - l32i a4, a0, 0x10 - rsr.excsave1 a0 + # Restore all regs and return + l32i a0, sp, 0 + l32i a2, sp, 0x08 + l32i a3, sp, 0x0c + l32i a4, sp, 0x10 + rsr.excsave1 a1 # restore a1 saved by UserExceptionVector rfe - .org .LSE_assign_jumptable + (16 * 1) - mov a1, a4 - l32i a2, a0, 0x08 - l32i a4, a0, 0x10 - rsr.excsave1 a0 + .balign 4 +.LSE_jumptable: + # The first 5 entries (80 bytes) of this table are unused (registers + # a0..a4 are handled separately above). Rather than have a whole bunch + # of wasted space, we just pretend that the table starts 80 bytes + # earlier in memory. + .set .LSE_jumptable_base, .LSE_jumptable - (16 * 5) + + .org .LSE_jumptable_base + (16 * 5) + mov a5, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr.excsave1 a1 rfe - # NOTE: Opcodes a2 .. a5 are not handled by the jumptable routines - # (they're taken care of directly in .LSE_post_fetch above) - # This leaves 64 bytes of wasted space here. We could fill it with - # other things, but that would just make it harder to understand what's - # going on, and that's bad enough with this routine already. Even on - # the ESP8266, 64 bytes of IRAM wasted aren't the end of the world.. - - .org .LSE_assign_jumptable + (16 * 6) + .org .LSE_jumptable_base + (16 * 6) mov a6, a4 - l32i a2, a0, 0x08 - l32i a4, a0, 0x10 - rsr.excsave1 a0 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr.excsave1 a1 rfe - .org .LSE_assign_jumptable + (16 * 7) + .org .LSE_jumptable_base + (16 * 7) mov a7, a4 - l32i a2, a0, 0x08 - l32i a4, a0, 0x10 - rsr.excsave1 a0 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr.excsave1 a1 rfe - .org .LSE_assign_jumptable + (16 * 8) + .org .LSE_jumptable_base + (16 * 8) mov a8, a4 - l32i a2, a0, 0x08 - l32i a4, a0, 0x10 - rsr.excsave1 a0 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr.excsave1 a1 rfe - .org .LSE_assign_jumptable + (16 * 9) + .org .LSE_jumptable_base + (16 * 9) mov a9, a4 - l32i a2, a0, 0x08 - l32i a4, a0, 0x10 - rsr.excsave1 a0 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr.excsave1 a1 rfe - .org .LSE_assign_jumptable + (16 * 10) + .org .LSE_jumptable_base + (16 * 10) mov a10, a4 - l32i a2, a0, 0x08 - l32i a4, a0, 0x10 - rsr.excsave1 a0 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr.excsave1 a1 rfe - .org .LSE_assign_jumptable + (16 * 11) + .org .LSE_jumptable_base + (16 * 11) mov a11, a4 - l32i a2, a0, 0x08 - l32i a4, a0, 0x10 - rsr.excsave1 a0 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr.excsave1 a1 rfe - .org .LSE_assign_jumptable + (16 * 12) + .org .LSE_jumptable_base + (16 * 12) mov a12, a4 - l32i a2, a0, 0x08 - l32i a4, a0, 0x10 - rsr.excsave1 a0 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr.excsave1 a1 rfe - .org .LSE_assign_jumptable + (16 * 13) + .org .LSE_jumptable_base + (16 * 13) mov a13, a4 - l32i a2, a0, 0x08 - l32i a4, a0, 0x10 - rsr.excsave1 a0 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr.excsave1 a1 rfe - .org .LSE_assign_jumptable + (16 * 14) + .org .LSE_jumptable_base + (16 * 14) mov a14, a4 - l32i a2, a0, 0x08 - l32i a4, a0, 0x10 - rsr.excsave1 a0 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr.excsave1 a1 rfe - .org .LSE_assign_jumptable + (16 * 15) + .org .LSE_jumptable_base + (16 * 15) mov a15, a4 - l32i a2, a0, 0x08 - l32i a4, a0, 0x10 - rsr.excsave1 a0 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr.excsave1 a1 rfe /* End of LoadStoreErrorHandler */ @@ -337,10 +332,11 @@ NMIRegisterSaved: /* register space for saving NMI registers */ .skip 4*(16 + 6) LoadStoreErrorHandlerStack: + .word 0 # a0 + .word 0 # (unused) .word 0 # a2 .word 0 # a3 .word 0 # a4 - .word 0 # a5 /* Save register relative to a0 */ .macro SAVE_REG register, regnum @@ -439,7 +435,8 @@ CallNMIExceptionHandler: .type UserExceptionHandler, @function UserExceptionHandler: - mov a0, sp /* a0 was saved by UserExceptionVector */ + xsr.excsave1 a0 # a0 now contains sp + mov sp, a0 addi sp, sp, -0x50 s32i a0, sp, 0x10 rsr.ps a0 From 87f77b10217aec7317caf99ff47b233d6bfc51c9 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 24 Sep 2015 20:48:16 +1000 Subject: [PATCH 49/56] Refactor Hardware RNG functions to esp/hwrand.h As suggested by @foogod, thanks! --- core/esp_hwrand.c | 27 +++++++++++++++++++++++++++ core/include/esp/hwrand.h | 22 ++++++++++++++++++++++ extras/mbedtls/hardware_entropy.c | 9 ++------- 3 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 core/esp_hwrand.c create mode 100644 core/include/esp/hwrand.h diff --git a/core/esp_hwrand.c b/core/esp_hwrand.c new file mode 100644 index 0000000..7a591eb --- /dev/null +++ b/core/esp_hwrand.c @@ -0,0 +1,27 @@ +/* Hardware Random Number Generator Functions + * + * For documentation, see http://esp8266-re.foogod.com/wiki/Random_Number_Generator + * + * Part of esp-open-rtos + * Copyright (C) 2015 Angus Gratton + * BSD Licensed as described in the file LICENSE + */ +#include +#include +#include + +/* Return a random 32-bit number */ +uint32_t hwrand(void) +{ + return WDEV.HWRNG; +} + +/* Fill a variable size buffer with data from the Hardware RNG */ +void hwrand_fill(uint8_t *buf, size_t len) +{ + for(size_t i = 0; i < len; i+=4) { + uint32_t random = WDEV.HWRNG; + /* using memcpy here in case 'buf' is unaligned */ + memcpy(buf + i, &random, (i+4 <= len) ? 4 : (len % 4)); + } +} diff --git a/core/include/esp/hwrand.h b/core/include/esp/hwrand.h new file mode 100644 index 0000000..8ec75e1 --- /dev/null +++ b/core/include/esp/hwrand.h @@ -0,0 +1,22 @@ +/** esp/hwrand.h + * + * Hardware Random Number Generator functions. + * + * For documentation, see http://esp8266-re.foogod.com/wiki/Random_Number_Generator + * + * Part of esp-open-rtos + * Copyright (C) 2015 Angus Gratton + * BSD Licensed as described in the file LICENSE + */ +#ifndef _ESP_RNG_H +#define _ESP_RNG_H +#include +#include + +/* Return a random 32-bit number */ +uint32_t hwrand(void); + +/* Fill a variable size buffer with data from the Hardware RNG */ +void hwrand_fill(uint8_t *buf, size_t len); + +#endif diff --git a/extras/mbedtls/hardware_entropy.c b/extras/mbedtls/hardware_entropy.c index 85dd00d..0d197cd 100644 --- a/extras/mbedtls/hardware_entropy.c +++ b/extras/mbedtls/hardware_entropy.c @@ -9,18 +9,13 @@ * BSD Licensed as described in the file LICENSE */ #include -#include -#include +#include int mbedtls_hardware_poll( void *data, unsigned char *output, size_t len, size_t *olen ) { (void)(data); - for(int i = 0; i < len; i+=4) { - uint32_t random = WDEV.HWRNG; - /* using memcpy here in case output is unaligned */ - memcpy(output + i, &random, (i+4 <= len) ? 4 : (len % 4)); - } + hwrand_fill(output, len); if(olen) *olen = len; return 0; From edbfd3a66ecd32e6f8daaa199d38d98e1ba85e65 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 25 Sep 2015 09:22:06 +1000 Subject: [PATCH 50/56] unaligned_load tests: Remove incorrect references to DoubleException --- examples/experiments/unaligned_load/unaligned_load.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/experiments/unaligned_load/unaligned_load.c b/examples/experiments/unaligned_load/unaligned_load.c index d2d132f..d7f7203 100644 --- a/examples/experiments/unaligned_load/unaligned_load.c +++ b/examples/experiments/unaligned_load/unaligned_load.c @@ -207,7 +207,7 @@ void test_string(const char *string, char *label, bool evict_cache) run_test(string, test_l16si, "load as l16si", nullvalue, evict_cache); } -static void test_doubleexception(); +static void test_isr(); static void test_sign_extension(); void sanity_tests(void); @@ -225,7 +225,7 @@ void user_init(void) test_string(iromtest, "Cached flash", 0); test_string(iromtest, "'Uncached' flash", 1); - test_doubleexception(); + test_isr(); test_sign_extension(); } @@ -241,9 +241,9 @@ static void frc1_interrupt_handler(void) frc1_finished = true; } -static void test_doubleexception() +static void test_isr() { - printf("Testing DoubleException behaviour...\r\n"); + 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); From 4dd87125268eb86ff58ea2f45b205b2d22861f88 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 25 Sep 2015 09:41:51 +1000 Subject: [PATCH 51/56] unaligned_load: Run some tests after scheduler/network/wifi all up and running As written this doesn't expose any new bugs. --- .../unaligned_load/unaligned_load.c | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/examples/experiments/unaligned_load/unaligned_load.c b/examples/experiments/unaligned_load/unaligned_load.c index d7f7203..1574172 100644 --- a/examples/experiments/unaligned_load/unaligned_load.c +++ b/examples/experiments/unaligned_load/unaligned_load.c @@ -209,6 +209,7 @@ void test_string(const char *string, char *label, bool evict_cache) static void test_isr(); static void test_sign_extension(); +static void test_system_interaction(); void sanity_tests(void); void user_init(void) @@ -227,6 +228,9 @@ void user_init(void) test_isr(); test_sign_extension(); + + xTaskHandle taskHandle; + xTaskCreate(test_system_interaction, (signed char *)"interactionTask", 256, &taskHandle, 2, NULL); } static volatile bool frc1_ran; @@ -270,12 +274,40 @@ static void test_sign_extension() 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 worked as expected.\r\n"); + printf("l16si sign extension PASSED.\r\n"); } else { - printf("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]); + 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 */ From b6c2e4df597d17b13ceb154012a5efec153893e3 Mon Sep 17 00:00:00 2001 From: Alex Stewart Date: Thu, 24 Sep 2015 18:32:32 -0700 Subject: [PATCH 52/56] Fix bad memory access in NMI handler CallNMIExceptionHandler was saving/restoring registers to the wrong offsets, causing it to potentially corrupt the first two slots of the LoadStoreErrorHandler's save area. --- core/exception_vectors.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index a8d513a..26e542f 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -340,12 +340,12 @@ LoadStoreErrorHandlerStack: /* Save register relative to a0 */ .macro SAVE_REG register, regnum - s32i \register, a0, (0x20 + 4 * \regnum) + s32i \register, a0, (4 * (\regnum + 6)) .endm /* Load register relative to sp */ .macro LOAD_REG register, regnum - l32i \register, sp, (0x20 + 4 * \regnum) + l32i \register, sp, (4 * (\regnum + 6)) .endm .text From b8134895243a7f8d803cf9f3da60895603e59e1d Mon Sep 17 00:00:00 2001 From: Alex Stewart Date: Thu, 24 Sep 2015 22:43:29 -0700 Subject: [PATCH 53/56] Code reformat/cleanup of exception_vectors.S --- core/exception_vectors.S | 973 ++++++++++++++++++++------------------- 1 file changed, 506 insertions(+), 467 deletions(-) diff --git a/core/exception_vectors.S b/core/exception_vectors.S index 26e542f..5e7f20e 100644 --- a/core/exception_vectors.S +++ b/core/exception_vectors.S @@ -1,502 +1,541 @@ /* Xtensa Exception (ie interrupt) Vectors & low-level handler code - - Core exception handler code is placed in the .vecbase section, - which gets picked up specially in the linker script and placed - at beginning of IRAM. - - The actual VecBase symbol should be the first thing in .vecbase - (this is not strictly important as it gets set by symbol lookup not - by hardcoded address, but having it at 0x40100000 means that the - exception vectors have memorable offsets, which match the default - Boot ROM vector offsets. So convenient for human understanding. - - Part of esp-open-rtos - Original vector contents Copyright (C) 2014-2015 Espressif Systems - Additions Copyright (C) Superhouse Automation Pty Ltd and Angus Gratton - BSD Licensed as described in the file LICENSE -*/ + * + * Core exception handler code is placed in the .vecbase section, which gets + * picked up specially in the linker script and placed at beginning of IRAM. + * + * The actual VecBase symbol should be the first thing in .vecbase (this is not + * strictly important as it gets set by symbol lookup not by hardcoded address, + * but having it at 0x40100000 means that the exception vectors have memorable + * offsets, which match the default Boot ROM vector offsets. So convenient for + * human understanding. + * + * Part of esp-open-rtos + * Original vector contents Copyright (C) 2014-2015 Espressif Systems + * Additions Copyright (C) Superhouse Automation Pty Ltd and Angus Gratton + * BSD Licensed as described in the file LICENSE + */ #include "led_debug.s" /* Some UserException causes, see table Table 4–64 in ISA reference */ + #define CAUSE_SYSCALL 1 #define CAUSE_LOADSTORE 3 #define CAUSE_LVL1INT 4 - .text - .section .vecbase.text, "x" - .global VecBase - .org 0 -VecBase: - /* IMPORTANT: exception vector literals will go here, but we - can't have more than 4 otherwise we push DebugExceptionVector past - offset 0x10 relative to VecBase. There should be ways to avoid this, - and also keep the VecBase offsets easy to read, but this works for now. - */ - .literal_position - .org 0x10 - .type DebugExceptionVector, @function -DebugExceptionVector: - wsr.excsave2 a0 - call0 sdk_user_fatal_exception_handler - rfi 2 + .section .bss - .org 0x20 - .type NMIExceptionVector, @function -NMIExceptionVector: - wsr.excsave3 a0 - call0 CallNMIExceptionHandler - rfi 3 /* CallNMIExceptionHandler should call rfi itself */ - - .org 0x30 - .type KernelExceptionVector, @function -KernelExceptionVector: - break 1, 0 - call0 sdk_user_fatal_exception_handler - rfe - - .org 0x50 - .type UserExceptionVector, @function -UserExceptionVector: - wsr.excsave1 a1 - rsr.exccause a1 - beqi a1, CAUSE_LOADSTORE, LoadStoreErrorHandler - j UserExceptionHandler - - .org 0x70 - .type DoubleExceptionVector, @function -DoubleExceptionVector: - break 1, 4 - call0 sdk_user_fatal_exception_handler - -/* Reset vector would go here at offset 0x80 but should be unused, - as vecbase goes back to mask ROM vectors on reset */ - -/***** end of exception vectors *****/ - -/* Xtensa Exception unaligned load handler - - Completes l8/l16 load instructions from Instruction address space, - for which the architecture only supports 32-bit reads. - - Called from UserExceptionVector if EXCCAUSE is LoadStoreErrorCause - - Fast path (no branches) is for l8ui. -*/ - .literal_position - - .type LoadStoreErrorHandler, @function -LoadStoreErrorHandler: - # Note: registers are saved in the address corresponding to their - # register number times 4. This allows a quick and easy mapping later - # on when needing to store the value to a particular register number. - movi sp, LoadStoreErrorHandlerStack - s32i a0, sp, 0 - s32i a2, sp, 0x08 - s32i a3, sp, 0x0c - s32i a4, sp, 0x10 - rsr.sar a0 # Save SAR in a0 to restore later - - # Examine the opcode which generated the exception - # Note: Instructions are in this order to avoid pipeline stalls. - rsr.epc1 a2 - movi a3, ~3 - ssa8l a2 // sar is now correct shift for aligned read - and a2, a2, a3 // a2 now 4-byte aligned address of instruction - l32i a4, a2, 0 - l32i a2, a2, 4 - movi a3, 0x00700F // opcode mask for l8ui/l16si/l16ui - src a2, a2, a4 // a2 now instruction that failed - and a3, a2, a3 - bnei a3, 0x000002, .LSE_check_l16 - - # Note: At this point, opcode could technically be one of two things: - # xx0xx2 (L8UI) - # xx8xx2 (Reserved (invalid) opcode) - # It is assumed that we'll never get to this point from an illegal - # opcode, so we don't bother to check for that case and presume this is - # always an L8UI. - - /* a2 holds instruction */ - movi a4, ~3 - rsr.excvaddr a3 // read faulting address - and a4, a3, a4 /* a4 now word aligned read address */ - - l32i a4, a4, 0 /* perform the actual read */ - ssa8l a3 /* sar is now shift to extract a3's byte */ - srl a3, a4 /* shift right correct distance */ - extui a4, a3, 0, 8 /* mask off bits we need for an l8 */ - -.LSE_post_fetch: - # We jump back here after either the L8UI or the L16*I routines do the - # necessary work to read the value from memory. - # At this point, a2 holds the faulting instruction and a4 holds the - # correctly read value. - - # Restore original SAR value (saved in a0) and update EPC so we'll - # return back to the instruction following the one we just emulated - # Note: Instructions are in this order to avoid pipeline stalls - rsr.epc1 a3 - wsr.sar a0 - addi a3, a3, 0x3 - wsr.epc1 a3 - - # Stupid opcode tricks: The jumptable we use later on needs 16 bytes - # per entry (so we can avoid a second jump by just doing a RFE inside - # each entry). Unfortunately, however, Xtensa doesn't have an addx16 - # operation to make that easy for us. Luckily, all of the faulting - # opcodes we're processing are guaranteed to have bit 3 be zero, which - # means if we just shift the register bits of the opcode down by 3 - # instead of 4, we will get the register number multiplied by 2. This - # combined with an addx8 will give us an effective addx16 without - # needing any extra shift operations. - extui a2, a2, 3, 5 /* a2 now destination register 0-15 times 2 */ - - bgei a2, 10, .LSE_assign_reg # a5..a15 use jumptable - beqi a2, 2, .LSE_assign_a1 # a1 uses a special routine - - # We're storing into a0 or a2..a4, which are all saved in our "stack" area. - # Calculate the correct address and stick the value in there, then just - # do our normal restore and RFE (no jumps required, which actually - # makes a0..a4 substantially faster). - addx2 a2, a2, sp - s32i a4, a2, 0 - - # Restore all regs and return - l32i a0, sp, 0 - l32i a2, sp, 0x08 - l32i a3, sp, 0x0c - l32i a4, sp, 0x10 - rsr.excsave1 a1 # restore a1 saved by UserExceptionVector - rfe - -.LSE_assign_reg: - # At this point, a2 contains the register number times 2, a4 is the - # read value. - - # Calculate the jumptable address, and restore regs except a2 and a4 - # so we have less to do after jumping. - # Note: Instructions are in this order to avoid pipeline stalls. - movi a3, .LSE_jumptable_base - l32i a0, sp, 0 - addx8 a2, a2, a3 # a2 is now the address to jump to - l32i a3, sp, 0x0c - - jx a2 - -/* Check the load instruction a2 for an l16si/16ui instruction - - a2 is the instruction, a3 is masked instruction */ - .balign 4 -.LSE_check_l16: - movi a4, 0x001002 /* l16si or l16ui opcode after masking */ - bne a3, a4, .LSE_wrong_opcode - - # Note: At this point, the opcode could be one of two things: - # xx1xx2 (L16UI) - # xx9xx2 (L16SI) - # Both of these we can handle. - - movi a4, ~3 - rsr.excvaddr a3 // read faulting address - and a4, a3, a4 /* a4 now word aligned read address */ - - l32i a4, a4, 0 /* perform the actual read */ - ssa8l a3 /* sar is now shift to extract a3's byte */ - srl a3, a4 /* shift right correct distance */ - extui a4, a3, 0, 16 /* mask off bits we need for an l16 */ - - bbci a2, 15, .LSE_post_fetch # Not a signed op - bbci a4, 15, .LSE_post_fetch # Value does not require sign-extension - - movi a3, 0xFFFF0000 - or a4, a3, a4 /* set 32-bit sign bits */ - j .LSE_post_fetch - -/* If we got here it's not an opcode we can try to fix, so bomb out */ -.LSE_wrong_opcode: - # Restore registers so any dump the fatal exception routine produces - # will have correct values - wsr.sar a0 # Restore SAR saved in a0 - l32i a0, sp, 0 - l32i a2, sp, 0x08 - l32i a3, sp, 0x0c - l32i a4, sp, 0x10 - rsr.excsave1 a1 - call0 sdk_user_fatal_exception_handler - - .balign 4 -.LSE_assign_a1: - # a1 is saved in excsave1, so just update that with the value - wsr.excsave1 a4 - # Restore all regs and return - l32i a0, sp, 0 - l32i a2, sp, 0x08 - l32i a3, sp, 0x0c - l32i a4, sp, 0x10 - rsr.excsave1 a1 # restore a1 saved by UserExceptionVector - rfe - - .balign 4 -.LSE_jumptable: - # The first 5 entries (80 bytes) of this table are unused (registers - # a0..a4 are handled separately above). Rather than have a whole bunch - # of wasted space, we just pretend that the table starts 80 bytes - # earlier in memory. - .set .LSE_jumptable_base, .LSE_jumptable - (16 * 5) - - .org .LSE_jumptable_base + (16 * 5) - mov a5, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr.excsave1 a1 - rfe - - .org .LSE_jumptable_base + (16 * 6) - mov a6, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr.excsave1 a1 - rfe - - .org .LSE_jumptable_base + (16 * 7) - mov a7, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr.excsave1 a1 - rfe - - .org .LSE_jumptable_base + (16 * 8) - mov a8, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr.excsave1 a1 - rfe - - .org .LSE_jumptable_base + (16 * 9) - mov a9, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr.excsave1 a1 - rfe - - .org .LSE_jumptable_base + (16 * 10) - mov a10, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr.excsave1 a1 - rfe - - .org .LSE_jumptable_base + (16 * 11) - mov a11, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr.excsave1 a1 - rfe - - .org .LSE_jumptable_base + (16 * 12) - mov a12, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr.excsave1 a1 - rfe - - .org .LSE_jumptable_base + (16 * 13) - mov a13, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr.excsave1 a1 - rfe - - .org .LSE_jumptable_base + (16 * 14) - mov a14, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr.excsave1 a1 - rfe - - .org .LSE_jumptable_base + (16 * 15) - mov a15, a4 - l32i a2, sp, 0x08 - l32i a4, sp, 0x10 - rsr.excsave1 a1 - rfe - -/* End of LoadStoreErrorHandler */ - - .section .bss -NMIHandlerStack: /* stack space for NMI handler */ - .skip 4*0x100 +NMIHandlerStack: # stack space for NMI handler + .skip 4*0x100 .LNMIHandlerStackTop: -NMIRegisterSaved: /* register space for saving NMI registers */ - .skip 4*(16 + 6) +NMIRegisterSaved: # register space for saving NMI registers + .skip 4*(16 + 6) LoadStoreErrorHandlerStack: - .word 0 # a0 - .word 0 # (unused) - .word 0 # a2 - .word 0 # a3 - .word 0 # a4 + .word 0 # a0 + .word 0 # (unused) + .word 0 # a2 + .word 0 # a3 + .word 0 # a4 + +/***************************** Exception Vectors *****************************/ + + .section .vecbase.text, "x" + +/* Note: Exception vectors must be aligned on a 256-byte (0x100) boundary or + * they will not function properly. (This is taken care of in the linker + * script by ensuring .vecbase.text is aligned properly, and putting VecBase + * right at the beginning of .vecbase.text) */ + .org 0 +VecBase: + .global VecBase + /* IMPORTANT: exception vector literals will go here, but we + * can't have more than 4 otherwise we push DebugExceptionVector past + * offset 0x10 relative to VecBase. There should be ways to avoid this, + * and also keep the VecBase offsets easy to read, but this works for + * now. */ + .literal_position + + .org VecBase + 0x10 +DebugExceptionVector: + .type DebugExceptionVector, @function + + wsr a0, excsave2 + call0 sdk_user_fatal_exception_handler + rfi 2 + + .org VecBase + 0x20 +NMIExceptionVector: + .type NMIExceptionVector, @function + + wsr a0, excsave3 + call0 CallNMIExceptionHandler + rfi 3 # Should never be reached + + .org VecBase + 0x30 +KernelExceptionVector: + .type KernelExceptionVector, @function + + break 1, 0 + call0 sdk_user_fatal_exception_handler + rfe + + .org VecBase + 0x50 +UserExceptionVector: + .type UserExceptionVector, @function + + wsr a1, excsave1 + rsr a1, exccause + beqi a1, CAUSE_LOADSTORE, LoadStoreErrorHandler + j UserExceptionHandler + + .org VecBase + 0x70 +DoubleExceptionVector: + .type DoubleExceptionVector, @function + + break 1, 4 + call0 sdk_user_fatal_exception_handler + +/* Reset vector at offset 0x80 is unused, as vecbase gets reset to mask ROM + * vectors on chip reset. */ + +/*************************** LoadStoreError Handler **************************/ + + .section .vecbase.text, "x" + +/* Xtensa "Load/Store Exception" handler: + * Completes L8/L16 load instructions from Instruction address space, for which + * the architecture only supports 32-bit reads. + * + * Called from UserExceptionVector if EXCCAUSE is LoadStoreErrorCause + * + * (Fast path (no branches) is for L8UI) + */ + .literal_position + + .balign 4 +LoadStoreErrorHandler: + .type LoadStoreErrorHandler, @function + + /* Registers are saved in the address corresponding to their register + * number times 4. This allows a quick and easy mapping later on when + * needing to store the value to a particular register number. */ + movi sp, LoadStoreErrorHandlerStack + s32i a0, sp, 0 + s32i a2, sp, 0x08 + s32i a3, sp, 0x0c + s32i a4, sp, 0x10 + rsr a0, sar # Save SAR in a0 to restore later + + /* Examine the opcode which generated the exception */ + /* Note: Instructions are in this order to avoid pipeline stalls. */ + rsr a2, epc1 + movi a3, ~3 + ssa8l a2 # sar is now correct shift for aligned read + and a2, a2, a3 # a2 now 4-byte aligned address of instruction + l32i a4, a2, 0 + l32i a2, a2, 4 + movi a3, 0x00700F # opcode mask for l8ui/l16si/l16ui + src a2, a2, a4 # a2 now instruction that failed + and a3, a2, a3 # a3 is masked instruction + bnei a3, 0x000002, .LSE_check_l16 + + /* Note: At this point, opcode could technically be one of two things: + * xx0xx2 (L8UI) + * xx8xx2 (Reserved (invalid) opcode) + * It is assumed that we'll never get to this point from an illegal + * opcode, so we don't bother to check for that case and presume this + * is always an L8UI. */ + + movi a4, ~3 + rsr a3, excvaddr # read faulting address + and a4, a3, a4 # a4 now word aligned read address + + l32i a4, a4, 0 # perform the actual read + ssa8l a3 # sar is now shift to extract a3's byte + srl a3, a4 # shift right correct distance + extui a4, a3, 0, 8 # mask off bits we need for an l8 + +.LSE_post_fetch: + /* We jump back here after either the L8UI or the L16*I routines do the + * necessary work to read the value from memory. + * At this point, a2 holds the faulting instruction and a4 holds the + * correctly read value. + + * Restore original SAR value (saved in a0) and update EPC so we'll + * return back to the instruction following the one we just emulated */ + + /* Note: Instructions are in this order to avoid pipeline stalls */ + rsr a3, epc1 + wsr a0, sar + addi a3, a3, 0x3 + wsr a3, epc1 + + /* Stupid opcode tricks: The jumptable we use later on needs 16 bytes + * per entry (so we can avoid a second jump by just doing a RFE inside + * each entry). Unfortunately, however, Xtensa doesn't have an addx16 + * operation to make that easy for us. Luckily, all of the faulting + * opcodes we're processing are guaranteed to have bit 3 be zero, which + * means if we just shift the register bits of the opcode down by 3 + * instead of 4, we will get the register number multiplied by 2. This + * combined with an addx8 will give us an effective addx16 without + * needing any extra shift operations. */ + extui a2, a2, 3, 5 # a2 is now destination register 0-15 times 2 + + bgei a2, 10, .LSE_assign_reg # a5..a15 use jumptable + beqi a2, 2, .LSE_assign_a1 # a1 uses a special routine + + /* We're storing into a0 or a2..a4, which are all saved in our "stack" + * area. Calculate the correct address and stick the value in there, + * then just do our normal restore and RFE (no jumps required, which + * actually makes a0..a4 substantially faster). */ + addx2 a2, a2, sp + s32i a4, a2, 0 + + /* Restore all regs and return */ + l32i a0, sp, 0 + l32i a2, sp, 0x08 + l32i a3, sp, 0x0c + l32i a4, sp, 0x10 + rsr a1, excsave1 # restore a1 saved by UserExceptionVector + rfe + +.LSE_assign_reg: + /* At this point, a2 contains the register number times 2, a4 is the + * read value. */ + + /* Calculate the jumptable address, and restore all regs except a2 and + * a4 so we have less to do after jumping. */ + /* Note: Instructions are in this order to avoid pipeline stalls. */ + movi a3, .LSE_jumptable_base + l32i a0, sp, 0 + addx8 a2, a2, a3 # a2 is now the address to jump to + l32i a3, sp, 0x0c + + jx a2 + + .balign 4 +.LSE_check_l16: + /* At this point, a2 contains the opcode, a3 is masked opcode */ + movi a4, 0x001002 # l16si or l16ui opcode after masking + bne a3, a4, .LSE_wrong_opcode + + /* Note: At this point, the opcode could be one of two things: + * xx1xx2 (L16UI) + * xx9xx2 (L16SI) + * Both of these we can handle. */ + + movi a4, ~3 + rsr a3, excvaddr # read faulting address + and a4, a3, a4 # a4 now word aligned read address + + l32i a4, a4, 0 # perform the actual read + ssa8l a3 # sar is now shift to extract a3's bytes + srl a3, a4 # shift right correct distance + extui a4, a3, 0, 16 # mask off bits we need for an l16 + + bbci a2, 15, .LSE_post_fetch # Not a signed op + bbci a4, 15, .LSE_post_fetch # Value does not need sign-extension + + movi a3, 0xFFFF0000 + or a4, a3, a4 # set 32-bit sign bits + j .LSE_post_fetch + +.LSE_wrong_opcode: + /* If we got here it's not an opcode we can try to fix, so bomb out. + * Restore registers so any dump the fatal exception routine produces + * will have correct values */ + wsr a0, sar + l32i a0, sp, 0 + l32i a2, sp, 0x08 + l32i a3, sp, 0x0c + l32i a4, sp, 0x10 + rsr a1, excsave1 + call0 sdk_user_fatal_exception_handler + + .balign 4 +.LSE_assign_a1: + /* a1 is saved in excsave1, so just update that with the value, */ + wsr a4, excsave1 + /* Then restore all regs and return */ + l32i a0, sp, 0 + l32i a2, sp, 0x08 + l32i a3, sp, 0x0c + l32i a4, sp, 0x10 + rsr a1, excsave1 + rfe + + .balign 4 +.LSE_jumptable: + /* The first 5 entries (80 bytes) of this table are unused (registers + * a0..a4 are handled separately above). Rather than have a whole bunch + * of wasted space, we just pretend that the table starts 80 bytes + * earlier in memory. */ + .set .LSE_jumptable_base, .LSE_jumptable - (16 * 5) + + .org .LSE_jumptable_base + (16 * 5) + mov a5, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 + rfe + + .org .LSE_jumptable_base + (16 * 6) + mov a6, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 + rfe + + .org .LSE_jumptable_base + (16 * 7) + mov a7, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 + rfe + + .org .LSE_jumptable_base + (16 * 8) + mov a8, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 + rfe + + .org .LSE_jumptable_base + (16 * 9) + mov a9, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 + rfe + + .org .LSE_jumptable_base + (16 * 10) + mov a10, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 + rfe + + .org .LSE_jumptable_base + (16 * 11) + mov a11, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 + rfe + + .org .LSE_jumptable_base + (16 * 12) + mov a12, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 + rfe + + .org .LSE_jumptable_base + (16 * 13) + mov a13, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 + rfe + + .org .LSE_jumptable_base + (16 * 14) + mov a14, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 + rfe + + .org .LSE_jumptable_base + (16 * 15) + mov a15, a4 + l32i a2, sp, 0x08 + l32i a4, sp, 0x10 + rsr a1, excsave1 + rfe + +/****************************** call_user_start ******************************/ + + .section .vecbase.text, "x" + +/* This is the first entrypoint called from the ROM after loading the image + * into IRAM. It just sets up the VECBASE register to point at our own + * exception vectors and then calls sdk_user_start() */ + + .literal_position + + .balign 4 +call_user_start: + .global call_user_start + .type call_user_start, @function + + movi a2, VecBase + wsr a2, vecbase + call0 sdk_user_start + +/*************************** NMI Exception Handler ***************************/ + + .section .vecbase.text, "x" /* Save register relative to a0 */ .macro SAVE_REG register, regnum - s32i \register, a0, (4 * (\regnum + 6)) + s32i \register, a0, (4 * (\regnum + 6)) .endm /* Load register relative to sp */ .macro LOAD_REG register, regnum - l32i \register, sp, (4 * (\regnum + 6)) + l32i \register, sp, (4 * (\regnum + 6)) .endm - .text - .section .vecbase.text - .literal_position - .align 4 - .global call_user_start - .type call_user_start, @function -call_user_start: - movi a2, VecBase - wsr.vecbase a2 - call0 sdk_user_start + .literal_position - .literal_position - .align 16 - .type CallNMIExceptionHandler, @function + .balign 16 CallNMIExceptionHandler: - movi a0, NMIRegisterSaved - SAVE_REG a2, 2 - SAVE_REG sp, 1 - SAVE_REG a3, 3 - rsr.excsave3 a2 /* a2 is now former a0 */ - SAVE_REG a4, 4 - SAVE_REG a2, 0 - rsr.epc1 a3 - rsr.exccause a4 - SAVE_REG a3, -5 - SAVE_REG a4, -4 - rsr.excvaddr a3 - SAVE_REG a3, -3 - rsr.excsave1 a3 - SAVE_REG a3, -2 - SAVE_REG a5, 5 - SAVE_REG a6, 6 - SAVE_REG a7, 7 - SAVE_REG a8, 8 - SAVE_REG a9, 9 - SAVE_REG a10, 10 - SAVE_REG a11, 11 - SAVE_REG a12, 12 - SAVE_REG a13, 13 - SAVE_REG a14, 14 - SAVE_REG a15, 15 - movi sp, .LNMIHandlerStackTop - movi a0, 0 - movi a2, 0x23 /* argument for handler */ - wsr.ps a2 - rsync - rsr.sar a14 - s32i a14, sp, 0 /* this is also NMIRegisterSaved+0 */ - call0 sdk_wDev_ProcessFiq - l32i a15, sp, 0 - wsr.sar a15 - movi a2, 0x33 - wsr.ps a2 - rsync - LOAD_REG a4, 4 - LOAD_REG a5, 5 - LOAD_REG a6, 6 - LOAD_REG a7, 7 - LOAD_REG a8, 8 - LOAD_REG a9, 9 - LOAD_REG a10, 10 - LOAD_REG a11, 11 - LOAD_REG a12, 12 - LOAD_REG a13, 13 - LOAD_REG a14, 14 - LOAD_REG a15, 15 - LOAD_REG a2, -5 - LOAD_REG a3, -4 - wsr.epc1 a2 - wsr.exccause a3 - LOAD_REG a2, -3 - LOAD_REG a3, -2 - wsr.excvaddr a2 - wsr.excsave1 a3 - LOAD_REG a0, 0 - /* set dport nmi status bit 0 (wDev_ProcessFiq clears & verifies this bit stays cleared, - see http://esp8266-re.foogod.com/wiki/WDev_ProcessFiq_%28IoT_RTOS_SDK_0.9.9%29) */ - movi a2, 0x3ff00000 - movi a3, 0x1 - s32i a3, a2, 0 - LOAD_REG a2, 2 - LOAD_REG a3, 3 - LOAD_REG a1, 1 - rfi 0x3 + .type CallNMIExceptionHandler, @function - .type UserExceptionHandler, @function + movi a0, NMIRegisterSaved + SAVE_REG a2, 2 + SAVE_REG sp, 1 + SAVE_REG a3, 3 + rsr a2, excsave3 # a2 is now former a0 + SAVE_REG a4, 4 + SAVE_REG a2, 0 + rsr a3, epc1 + rsr a4, exccause + SAVE_REG a3, -5 + SAVE_REG a4, -4 + rsr a3, excvaddr + SAVE_REG a3, -3 + rsr a3, excsave1 + SAVE_REG a3, -2 + SAVE_REG a5, 5 + SAVE_REG a6, 6 + SAVE_REG a7, 7 + SAVE_REG a8, 8 + SAVE_REG a9, 9 + SAVE_REG a10, 10 + SAVE_REG a11, 11 + SAVE_REG a12, 12 + SAVE_REG a13, 13 + SAVE_REG a14, 14 + SAVE_REG a15, 15 + movi sp, .LNMIHandlerStackTop + movi a0, 0 + movi a2, 0x23 # argument for handler + wsr a2, ps + rsync + rsr a14, sar + s32i a14, sp, 0 # this is also NMIRegisterSaved+0 + call0 sdk_wDev_ProcessFiq + l32i a15, sp, 0 + wsr a15, sar + movi a2, 0x33 + wsr a2, ps + rsync + LOAD_REG a4, 4 + LOAD_REG a5, 5 + LOAD_REG a6, 6 + LOAD_REG a7, 7 + LOAD_REG a8, 8 + LOAD_REG a9, 9 + LOAD_REG a10, 10 + LOAD_REG a11, 11 + LOAD_REG a12, 12 + LOAD_REG a13, 13 + LOAD_REG a14, 14 + LOAD_REG a15, 15 + LOAD_REG a2, -5 + LOAD_REG a3, -4 + wsr a2, epc1 + wsr a3, exccause + LOAD_REG a2, -3 + LOAD_REG a3, -2 + wsr a2, excvaddr + wsr a3, excsave1 + LOAD_REG a0, 0 + /* set dport nmi status bit 0 (wDev_ProcessFiq clears & verifies this + * bit stays cleared, see + * http://esp8266-re.foogod.com/wiki/WDev_ProcessFiq_%28IoT_RTOS_SDK_0.9.9%29) + */ + movi a2, 0x3ff00000 + movi a3, 0x1 + s32i a3, a2, 0 + LOAD_REG a2, 2 + LOAD_REG a3, 3 + LOAD_REG a1, 1 + rfi 3 + +/*********************** General UserException Handler ***********************/ + + .section .vecbase.text, "x" + +/* Called by UserExceptionVector if EXCCAUSE is anything other than + * LoadStoreCause. */ + + .literal_position + + .balign 4 UserExceptionHandler: - xsr.excsave1 a0 # a0 now contains sp - mov sp, a0 - addi sp, sp, -0x50 - s32i a0, sp, 0x10 - rsr.ps a0 - s32i a0, sp, 0x08 - rsr.epc1 a0 - s32i a0, sp, 0x04 - rsr.excsave1 a0 - s32i a0, sp, 0x0c - movi a0, _xt_user_exit - s32i a0, sp, 0x0 - call0 sdk__xt_int_enter - movi a0, 0x23 - wsr.ps a0 - rsync - rsr.exccause a2 - beqi a2, CAUSE_LVL1INT, UserHandleInterrupt - /* Any UserException cause other than level 1 interrupt triggers a panic */ + .type UserExceptionHandler, @function + xsr a0, excsave1 # a0 now contains sp + mov sp, a0 + addi sp, sp, -0x50 + s32i a0, sp, 0x10 + rsr a0, ps + s32i a0, sp, 0x08 + rsr a0, epc1 + s32i a0, sp, 0x04 + rsr a0, excsave1 + s32i a0, sp, 0x0c + movi a0, _xt_user_exit + s32i a0, sp, 0x0 + call0 sdk__xt_int_enter + movi a0, 0x23 + wsr a0, ps + rsync + rsr a2, exccause + beqi a2, CAUSE_LVL1INT, UserHandleInterrupt + /* Any UserException cause other than level 1 interrupt should panic */ UserFailOtherExceptionCause: - break 1, 1 - call0 sdk_user_fatal_exception_handler + break 1, 1 + call0 sdk_user_fatal_exception_handler UserHandleInterrupt: - rsil a0, 1 - rsr.intenable a2 - rsr.interrupt a3 - movi a4, 0x3fff - and a2, a2, a3 - and a2, a2, a4 /* a2 = 0x3FFF & INTENABLE & INTERRUPT */ + rsil a0, 1 + rsr a2, intenable + rsr a3, interrupt + movi a4, 0x3fff + and a2, a2, a3 + and a2, a2, a4 # a2 = 0x3FFF & INTENABLE & INTERRUPT UserHandleTimer: - movi a3, 0xffbf - and a3, a2, a3 /* a3 = a2 & 0xFFBF, ie remove 0x40 from a2 if set */ - bnez a3, UserTimerDone /* bits other than 0x40 are set */ - movi a3, 0x40 - sub a12, a2, a3 /* a12 = a2 - 0x40 -- Will be zero if bit 6 set */ - call0 sdk__xt_timer_int /* tick timer interrupt */ - mov a2, a12 /* restore a2 from a12, ie zero */ - beqz a2, UserIntDone + movi a3, 0xffbf + and a3, a2, a3 # a3 = a2 with bit 6 cleared + bnez a3, UserTimerDone # If any non-timer interrupt bits set + movi a3, 0x40 + sub a12, a2, a3 # a12 = a2 - 0x40 -- Will be zero if bit 6 set + call0 sdk__xt_timer_int # tick timer interrupt + mov a2, a12 # restore a2 from a12, ie zero + beqz a2, UserIntDone UserTimerDone: - call0 _xt_isr_handler - bnez a2, UserHandleTimer + call0 _xt_isr_handler + bnez a2, UserHandleTimer UserIntDone: - beqz a2, UserIntExit - break 1, 1 /* non-zero remnant in a2 means fail */ - call0 sdk_user_fatal_exception_handler + beqz a2, UserIntExit + /* FIXME: this code will never be reached */ + break 1, 1 + call0 sdk_user_fatal_exception_handler UserIntExit: - call0 sdk__xt_int_exit /* jumps to _xt_user_exit. Never returns here */ + call0 sdk__xt_int_exit # jumps to _xt_user_exit. Never returns here -/* _xt_user_exit is used to exit interrupt context. - TODO: Find a better place for this to live. -*/ - .text - .section .text - .global _xt_user_exit - .type _xt_user_exit, @function + .section .text + +/* _xt_user_exit is used to exit interrupt context. */ +/* TODO: Find a better place for this to live. */ _xt_user_exit: - l32i a0, sp, 0x8 - wsr.ps a0 - l32i a0, sp, 0x4 - wsr.epc1 a0 - l32i a0, sp, 0xc - l32i sp, sp, 0x10 - rsync - rfe + .global _xt_user_exit + .type _xt_user_exit, @function + + l32i a0, sp, 0x8 + wsr a0, ps + l32i a0, sp, 0x4 + wsr a0, epc1 + l32i a0, sp, 0xc + l32i sp, sp, 0x10 + rsync + rfe From 99facb808e72171ae2807a3969fbd8474dd50f38 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 28 Sep 2015 13:01:13 +1000 Subject: [PATCH 54/56] hmac_test_vectors test: Replace axTLS with mbedTLS --- examples/tests/hmac_test_vectors/Makefile | 1 + .../hmac_test_vectors/hmac_test_vectors.c | 27 ++++++++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/examples/tests/hmac_test_vectors/Makefile b/examples/tests/hmac_test_vectors/Makefile index ea2761a..f314ff7 100644 --- a/examples/tests/hmac_test_vectors/Makefile +++ b/examples/tests/hmac_test_vectors/Makefile @@ -1,2 +1,3 @@ PROGRAM=hmac_test +EXTRA_COMPONENTS=extras/mbedtls include ../../../common.mk diff --git a/examples/tests/hmac_test_vectors/hmac_test_vectors.c b/examples/tests/hmac_test_vectors/hmac_test_vectors.c index 426f217..a6a20f9 100644 --- a/examples/tests/hmac_test_vectors/hmac_test_vectors.c +++ b/examples/tests/hmac_test_vectors/hmac_test_vectors.c @@ -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 @@ -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]) { From 233e5f377a1193b803a32ed5e8a0c3c76f5cc0fd Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 28 Sep 2015 13:00:56 +1000 Subject: [PATCH 55/56] Remove axTLS --- .gitmodules | 4 - README.md | 5 +- axtls/axtls | 1 - axtls/axtls_esp_stubs.c | 33 ---- axtls/component.mk | 22 --- axtls/include/config.h | 128 --------------- axtls/include/os_int.h | 6 - axtls/include/os_port.h | 95 ------------ axtls/include/version.h | 10 -- common.mk | 2 +- examples/http_get_ssl/Makefile | 2 - examples/http_get_ssl/http_get_ssl.c | 223 --------------------------- 12 files changed, 3 insertions(+), 528 deletions(-) delete mode 160000 axtls/axtls delete mode 100644 axtls/axtls_esp_stubs.c delete mode 100644 axtls/component.mk delete mode 100644 axtls/include/config.h delete mode 100644 axtls/include/os_int.h delete mode 100644 axtls/include/os_port.h delete mode 100644 axtls/include/version.h delete mode 100644 examples/http_get_ssl/Makefile delete mode 100644 examples/http_get_ssl/http_get_ssl.c diff --git a/.gitmodules b/.gitmodules index 74c2102..8dc737e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,10 +1,6 @@ [submodule "lwip/lwip"] path = lwip/lwip url = https://github.com/SuperHouse/esp-lwip.git -[submodule "axtls/axtls"] - path = axtls/axtls - url = https://github.com/SuperHouse/axtls.git - [submodule "extras/mbedtls/mbedtls"] path = extras/mbedtls/mbedtls url = https://github.com/ARMmbed/mbedtls.git diff --git a/README.md b/README.md index d91cd05..5b8f64f 100644 --- a/README.md +++ b/README.md @@ -71,14 +71,13 @@ Current status is alpha quality, actively developed. AP STATION mode (ie wifi cl - rboot-ota - OTA support (over-the-air updates) including a TFTP server for receiving updates ([for rboot by @raburton](http://richard.burtons.org/2015/05/18/rboot-a-new-boot-loader-for-esp8266/)) - bmp180 driver for digital pressure sensor ([upstream project](https://github.com/Angus71/esp-open-rtos-driver-bmp180)) * `FreeRTOS` contains FreeRTOS implementation, subdirectory structure is the standard FreeRTOS structure. `FreeRTOS/source/portable/esp8266/` contains the ESP8266 port. -* `lwip` and `axtls` contain the lwIP TCP/IP library and the axTLS TLS library ('libssl' in the esp8266 SDKs), respectively. See [Third Party Libraries](https://github.com/SuperHouse/esp-open-rtos/wiki/Third-Party-Libraries) wiki page for details. +* `lwip` contains the lwIP TCP/IP library. See [Third Party Libraries](https://github.com/SuperHouse/esp-open-rtos/wiki/Third-Party-Libraries) wiki page for details. * `libc` contains the newlib libc. [Libc details here](https://github.com/SuperHouse/esp-open-rtos/wiki/libc-configuration). ## Open Source Components * [FreeRTOS](http://freertos.org) V7.5.2 * [lwIP](http://lwip.wikia.com/wiki/LwIP_Wiki) v1.4.1, modified via the [esp-lwip project](https://github.com/kadamski/esp-lwip) by @kadamski. -* [axTLS](http://axtls.sourceforge.net/) compiled from development version v1.5.3, plus modifications for low memory devices. * [newlib](https://github.com/projectgus/newlib-xtensa) v2.2.0, with patches for xtensa support and locking stubs for thread-safe operation on FreeRTOS. For details of how third party libraries are integrated, [see the wiki page](https://github.com/SuperHouse/esp-open-rtos/wiki/Third-Party-Libraries). @@ -96,7 +95,7 @@ Some binary libraries appear to contain unattributed open source code: ## Licensing -* BSD license (as described in LICENSE) applies to original source files, [lwIP](http://lwip.wikia.com/wiki/LwIP_Wiki), and [axTLS](http://axtls.sourceforge.net/). lwIP is Copyright (C) Swedish Institute of Computer Science. axTLS is Copyright (C) Cameron Rich. +* BSD license (as described in LICENSE) applies to original source files, [lwIP](http://lwip.wikia.com/wiki/LwIP_Wiki). lwIP is Copyright (C) Swedish Institute of Computer Science. * FreeRTOS is provided under the GPL with the FreeRTOS linking exception, allowing non-GPL firmwares to be produced using FreeRTOS as the RTOS core. License details in files under FreeRTOS dir. FreeRTOS is Copyright (C) Real Time Engineers Ltd. diff --git a/axtls/axtls b/axtls/axtls deleted file mode 160000 index a4860ef..0000000 --- a/axtls/axtls +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a4860ef68d7f5d98a8731f99787d51cc44c433c9 diff --git a/axtls/axtls_esp_stubs.c b/axtls/axtls_esp_stubs.c deleted file mode 100644 index 3182594..0000000 --- a/axtls/axtls_esp_stubs.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Stub time-related functions for TLS time-related operations - * - * ESPTODO: Revisit these ASAP as gettimeofday() is used for entropy - * - * Part of esp-open-rtos - * Copyright (C) 2015 Superhouse Automation Pty Ltd - * BSD Licensed as described in the file LICENSE - */ -#include -#include -#include - -time_t time(time_t *t) -{ - return 0; -} - -time_t mktime(struct tm *tm) -{ - return 0; -} - -int gettimeofday(struct timeval *tv, void *tz) -{ - return 0; -} - -void abort(void) -{ - printf("abort() was called.\r\n"); - while(1) {} -} diff --git a/axtls/component.mk b/axtls/component.mk deleted file mode 100644 index 73859a2..0000000 --- a/axtls/component.mk +++ /dev/null @@ -1,22 +0,0 @@ -# Component makefile for axTLS - -# axTLS has its own configure and build system, but it's not particularly -# designed for embedded systems. For now we're just imposing the ESP Open RTOS -# build system over the top. - -# We supply our own hand tweaked config.h in the external 'include' dir. - -AXTLS_DIR = $(axtls_ROOT)axtls/ -INC_DIRS += $(axtls_ROOT)include $(AXTLS_DIR)ssl $(AXTLS_DIR)crypto - -# args for passing into compile rule generation -axtls_INC_DIR = $(AXTLS_DIR)include $(AXTLS_DIR) -axtls_SRC_DIR = $(AXTLS_DIR)crypto $(AXTLS_DIR)ssl $(axtls_ROOT) - -#axtls_CFLAGS = $(CFLAGS) -Wno-address - -$(eval $(call component_compile_rules,axtls)) - -# Helpful error if git submodule not initialised -$(axtls_SRC_DIR): - $(error "axtls git submodule not installed. Please run 'git submodule init' then 'git submodule update'") diff --git a/axtls/include/config.h b/axtls/include/config.h deleted file mode 100644 index 175d083..0000000 --- a/axtls/include/config.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Automatically generated header file: don't edit - */ -#define HAVE_DOT_CONFIG 0 -#undef CONFIG_PLATFORM_LINUX -#undef CONFIG_PLATFORM_CYGWIN -#undef CONFIG_PLATFORM_WIN32 - -/* - * General Configuration - */ -#define PREFIX "/usr/local" -#define CROSS "xtensa-lx106-elf-" -#undef CONFIG_DEBUG -#define CONFIG_STRIP_UNWANTED_SECTIONS 1 -#undef CONFIG_VISUAL_STUDIO_7_0 -#undef CONFIG_VISUAL_STUDIO_8_0 -#undef CONFIG_VISUAL_STUDIO_10_0 -#define CONFIG_VISUAL_STUDIO_7_0_BASE "" -#define CONFIG_VISUAL_STUDIO_8_0_BASE "" -#define CONFIG_VISUAL_STUDIO_10_0_BASE "" -#define CONFIG_EXTRA_CFLAGS_OPTIONS "" -#define CONFIG_EXTRA_LDFLAGS_OPTIONS "" - -/* - * Embedded System Options (added for ESP RTOS SDK, don't have config entries yetr) - */ -#define CONFIG_NO_FILESYSTEM 1 -#define CONFIG_USE_RAND 1 -#define CONFIG_MAX_PLAIN_LENGTH 1024 -#define CONFIG_MAX_KEY_BYTE_SIZE 256 /* for max 2048 bit keys (untested with >1024 bit keys) */ - -/* - * SSL Library - */ -#undef CONFIG_SSL_SERVER_ONLY -#undef CONFIG_SSL_CERT_VERIFICATION -#define CONFIG_SSL_ENABLE_CLIENT 1 -#undef CONFIG_SSL_FULL_MODE -#undef CONFIG_SSL_SKELETON_MODE -#undef CONFIG_SSL_PROT_LOW -#define CONFIG_SSL_PROT_MEDIUM 1 -#undef CONFIG_SSL_PROT_HIGH -#undef CONFIG_SSL_USE_DEFAULT_KEY -#define CONFIG_SSL_PRIVATE_KEY_LOCATION "" -#define CONFIG_SSL_PRIVATE_KEY_PASSWORD "" -#define CONFIG_SSL_X509_CERT_LOCATION "" -#undef CONFIG_SSL_GENERATE_X509_CERT -#define CONFIG_SSL_X509_COMMON_NAME "" -#define CONFIG_SSL_X509_ORGANIZATION_NAME "" -#define CONFIG_SSL_X509_ORGANIZATION_UNIT_NAME "" -#undef CONFIG_SSL_ENABLE_V23_HANDSHAKE -#undef CONFIG_SSL_HAS_PEM -#undef CONFIG_SSL_USE_PKCS12 -#define CONFIG_SSL_EXPIRY_TIME 24 -#define CONFIG_X509_MAX_CA_CERTS 1 -#define CONFIG_SSL_MAX_CERTS 3 -#undef CONFIG_SSL_CTX_MUTEXING -#undef CONFIG_USE_DEV_URANDOM -#undef CONFIG_WIN32_USE_CRYPTO_LIB -#undef CONFIG_OPENSSL_COMPATIBLE -#undef CONFIG_PERFORMANCE_TESTING -#undef CONFIG_SSL_TEST -#undef CONFIG_AXTLSWRAP -#undef CONFIG_AXHTTPD -#undef CONFIG_HTTP_STATIC_BUILD -#define CONFIG_HTTP_PORT -#define CONFIG_HTTP_HTTPS_PORT -#define CONFIG_HTTP_SESSION_CACHE_SIZE -#define CONFIG_HTTP_WEBROOT "" -#define CONFIG_HTTP_TIMEOUT -#undef CONFIG_HTTP_HAS_CGI -#define CONFIG_HTTP_CGI_EXTENSIONS "" -#undef CONFIG_HTTP_ENABLE_LUA -#define CONFIG_HTTP_LUA_PREFIX "" -#undef CONFIG_HTTP_BUILD_LUA -#define CONFIG_HTTP_CGI_LAUNCHER "" -#undef CONFIG_HTTP_DIRECTORIES -#undef CONFIG_HTTP_HAS_AUTHORIZATION -#undef CONFIG_HTTP_HAS_IPV6 -#undef CONFIG_HTTP_ENABLE_DIFFERENT_USER -#define CONFIG_HTTP_USER "" -#undef CONFIG_HTTP_VERBOSE -#undef CONFIG_HTTP_IS_DAEMON - -/* - * Language Bindings - */ -#undef CONFIG_BINDINGS -#undef CONFIG_CSHARP_BINDINGS -#undef CONFIG_VBNET_BINDINGS -#define CONFIG_DOT_NET_FRAMEWORK_BASE "" -#undef CONFIG_JAVA_BINDINGS -#define CONFIG_JAVA_HOME "" -#undef CONFIG_PERL_BINDINGS -#define CONFIG_PERL_CORE "" -#define CONFIG_PERL_LIB "" -#undef CONFIG_LUA_BINDINGS -#define CONFIG_LUA_CORE "" - -/* - * Samples - */ -#undef CONFIG_SAMPLES -#undef CONFIG_C_SAMPLES -#undef CONFIG_CSHARP_SAMPLES -#undef CONFIG_VBNET_SAMPLES -#undef CONFIG_JAVA_SAMPLES -#undef CONFIG_PERL_SAMPLES -#undef CONFIG_LUA_SAMPLES - -/* - * BigInt Options - */ -#undef CONFIG_BIGINT_CLASSICAL -#undef CONFIG_BIGINT_MONTGOMERY -#define CONFIG_BIGINT_BARRETT 1 -#define CONFIG_BIGINT_CRT 1 -#undef CONFIG_BIGINT_KARATSUBA -#define MUL_KARATSUBA_THRESH -#define SQU_KARATSUBA_THRESH -#define CONFIG_BIGINT_SLIDING_WINDOW 1 -#define CONFIG_BIGINT_SQUARE 1 -#define CONFIG_BIGINT_CHECK_ON 1 -#define CONFIG_INTEGER_32BIT 1 -#undef CONFIG_INTEGER_16BIT -#undef CONFIG_INTEGER_8BIT - diff --git a/axtls/include/os_int.h b/axtls/include/os_int.h deleted file mode 100644 index 3fc09cd..0000000 --- a/axtls/include/os_int.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _OS_INT_H -#define _OS_INT_H - -#include - -#endif diff --git a/axtls/include/os_port.h b/axtls/include/os_port.h deleted file mode 100644 index 67fc3db..0000000 --- a/axtls/include/os_port.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2007-2015, Cameron Rich - * Modifications Copyright (c) 2015 Superhouse Automation Pty Ltd - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * * Neither the name of the axTLS project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file os_port.h - * - * Some stuff to minimise the differences between windows and linux/unix - */ - -#ifndef _HEADER_OS_PORT_H -#define _HEADER_OS_PORT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "FreeRTOS.h" -#include "os_int.h" -#include "config.h" -#include -#include -#include -//#include -#include -#include -#include -#include -#include -#include -#if defined(CONFIG_SSL_CTX_MUTEXING) -#include "semphr.h" -#endif - -#define SOCKET_READ(A,B,C) read(A,B,C) -#define SOCKET_WRITE(A,B,C) write(A,B,C) -#define SOCKET_CLOSE(A) if (A >= 0) close(A) -#define TTY_FLUSH() - -static inline uint64_t be64toh(uint64_t x) { - return ntohl(x>>32) | ((uint64_t)(ntohl(x)) << 32); -} - -void exit_now(const char *format, ...) __attribute((noreturn)); - -#define EXP_FUNC -#define STDCALL - -/* Mutex definitions */ -#if defined(CONFIG_SSL_CTX_MUTEXING) -#define SSL_CTX_MUTEX_TYPE xSemaphoreHandle -#define SSL_CTX_MUTEX_INIT(A) vSemaphoreCreateBinaryCreateMutex(A) -#define SSL_CTX_MUTEX_DESTROY(A) vSemaphoreDelete(A) -#define SSL_CTX_LOCK(A) xSemaphoreTakeRecursive(A, portMAX_DELAY) -#define SSL_CTX_UNLOCK(A) xSemaphoreGiveRecursive(A) -#else -#define SSL_CTX_MUTEX_TYPE -#define SSL_CTX_MUTEX_INIT(A) -#define SSL_CTX_MUTEX_DESTROY(A) -#define SSL_CTX_LOCK(A) -#define SSL_CTX_UNLOCK(A) -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/axtls/include/version.h b/axtls/include/version.h deleted file mode 100644 index 8fee21b..0000000 --- a/axtls/include/version.h +++ /dev/null @@ -1,10 +0,0 @@ -/* axTLS version header - - We need this because we're using axTLS from source repo, not from a release. -*/ - -#ifndef _VERSION_H - -#define AXTLS_VERSION "esp-open-rtos axTLS " GITSHORTREV - -#endif diff --git a/common.mk b/common.mk index 0f07811..7b236fb 100644 --- a/common.mk +++ b/common.mk @@ -80,7 +80,7 @@ OBJDUMP = $(CROSS)objdump # Source components to compile and link. Each of these are subdirectories # of the root, with a 'component.mk' file. -COMPONENTS ?= $(EXTRA_COMPONENTS) FreeRTOS lwip axtls core +COMPONENTS ?= $(EXTRA_COMPONENTS) FreeRTOS lwip core # binary esp-iot-rtos SDK libraries to link. These are pre-processed prior to linking. SDK_LIBS ?= main net80211 phy pp wpa diff --git a/examples/http_get_ssl/Makefile b/examples/http_get_ssl/Makefile deleted file mode 100644 index fe64c2c..0000000 --- a/examples/http_get_ssl/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -PROGRAM=http_get_ssl -include ../../common.mk diff --git a/examples/http_get_ssl/http_get_ssl.c b/examples/http_get_ssl/http_get_ssl.c deleted file mode 100644 index 22351b9..0000000 --- a/examples/http_get_ssl/http_get_ssl.c +++ /dev/null @@ -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 - -#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"); -} From 0f960f0b2c8b20cdf097f5c366241dc696b937ee Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 28 Sep 2015 13:09:07 +1000 Subject: [PATCH 56/56] Update README regarding mbedTLS --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 5b8f64f..a202dbd 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ Current status is alpha quality, actively developed. AP STATION mode (ie wifi cl * `include` contains header files from Espressif RTOS SDK, relating to the binary libraries & Xtensa core. * `core` contains source & headers for low-level ESP8266 functions & peripherals. `core/include/esp` contains useful headers for peripheral access, etc. Minimal to no FreeRTOS dependencies. * `extras` is a directory that contains optional components that can be added to your project. Most 'extras' components will have a corresponding example in the `examples` directory. Extras include: + - mbedtls - [mbedTLS](https://tls.mbed.org/) is a TLS/SSL library providing up to date secure connectivity and encryption support. - i2c - software i2c driver ([upstream project](https://github.com/kanflo/esp-open-rtos-driver-i2c)) - rboot-ota - OTA support (over-the-air updates) including a TFTP server for receiving updates ([for rboot by @raburton](http://richard.burtons.org/2015/05/18/rboot-a-new-boot-loader-for-esp8266/)) - bmp180 driver for digital pressure sensor ([upstream project](https://github.com/Angus71/esp-open-rtos-driver-bmp180)) @@ -88,6 +89,8 @@ Binary libraries (inside the `lib` dir) are all supplied by Espressif as part of As part of the esp-open-rtos build process, all binary SDK symbols are prefixed with `sdk_`. This makes it easier to differentiate binary & open source code, and also prevents namespace conflicts. +Espressif's RTOS SDK provided a "libssl" based on axTLS. This has been replaced with the more up to date mbedTLS library (see below). + Some binary libraries appear to contain unattributed open source code: * libnet80211.a & libwpa.a appear to be based on FreeBSD net80211/wpa, or forks of them. ([See this issue](https://github.com/SuperHouse/esp-open-rtos/issues/4)). @@ -103,6 +106,8 @@ Some binary libraries appear to contain unattributed open source code: * Newlib is covered by several copyrights and licenses, as per the files in the `libc` directory. +* [mbedTLS](https://tls.mbed.org/) is provided under the Apache 2.0 license as described in the file extras/mbedtls/mbedtls/apache-2.0.txt. mbedTLS is Copyright (C) ARM Limited. + Components under `extras/` may contain different licenses, please see those directories for details. ## Contributions