diff options
-rw-r--r-- | libraries/libcli/Makefile | 3 | ||||
-rw-r--r-- | libraries/libprof/Makefile | 6 | ||||
-rw-r--r-- | libraries/libprof/gmon.c | 427 | ||||
-rw-r--r-- | libraries/libprof/gmon.h | 57 | ||||
-rw-r--r-- | libraries/libprof/memfunc.c (renamed from memfunc.c) | 52 | ||||
-rw-r--r-- | libraries/libprof/profil.c | 96 | ||||
-rw-r--r-- | libraries/libprof/profil.h | 60 | ||||
-rw-r--r-- | libraries/libtfm/Makefile | 2 | ||||
-rw-r--r-- | libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_it.c | 7 | ||||
-rw-r--r-- | projects/cli-test/cli-test.c | 6 | ||||
-rw-r--r-- | projects/hsm/Makefile | 1 | ||||
-rw-r--r-- | projects/hsm/hsm.c | 97 | ||||
-rw-r--r-- | projects/hsm/mgmt-keystore.c | 51 | ||||
-rw-r--r-- | projects/hsm/mgmt-masterkey.c | 90 | ||||
-rw-r--r-- | projects/libhal-test/main.c | 1 | ||||
-rw-r--r-- | spiflash_n25q128.c | 2 | ||||
-rw-r--r-- | task.c | 22 | ||||
-rw-r--r-- | task.h | 1 |
18 files changed, 454 insertions, 527 deletions
diff --git a/libraries/libcli/Makefile b/libraries/libcli/Makefile index cd1d3b6..6bc805a 100644 --- a/libraries/libcli/Makefile +++ b/libraries/libcli/Makefile @@ -11,7 +11,8 @@ CFLAGS += \ -DDO_REGULAR=0 \ -DDO_SOCKET=0 \ -DDO_TAB_COMPLETION=1 \ - -DDO_TELNET=0 + -DDO_TELNET=0 \ + -DCLI_MAX_LINE_WORDS=36 CFLAGS += -Wno-unused-parameter all: libcli.a diff --git a/libraries/libprof/Makefile b/libraries/libprof/Makefile index 4fe5fb4..28bedea 100644 --- a/libraries/libprof/Makefile +++ b/libraries/libprof/Makefile @@ -1,12 +1,16 @@ LIB = libprof.a -OBJS = gmon.o profil.o profiler.o +OBJS = gmon.o profiler.o memfunc.o # Don't profile the profiling code, because that way lies madness (and recursion). CFLAGS := $(subst -pg,,$(CFLAGS)) all: $(LIB) +# But do profile the mem functions +memfunc.o: memfunc.c + $(CC) $(CFLAGS) -pg -c -o $@ $< + %.o : %.c $(CC) $(CFLAGS) -c -o $@ $< diff --git a/libraries/libprof/gmon.c b/libraries/libprof/gmon.c index 317a173..a34f1a2 100644 --- a/libraries/libprof/gmon.c +++ b/libraries/libprof/gmon.c @@ -36,289 +36,226 @@ #include <stdlib.h> #include <stdio.h> #include <unistd.h> -#include <stdint.h> -#include "gmon.h" -#include "profil.h" #include <string.h> +#include "gmon.h" #define bzero(ptr,size) memset (ptr, 0, size); #define ERR(s) write(2, s, sizeof(s)) -struct gmonparam _gmonparam = { GMON_PROF_OFF, NULL, 0, NULL, 0, NULL, 0, 0L, 0, 0, 0}; -static char already_setup = 0; /* flag to indicate if we need to init */ -static int s_scale; -/* see profil(2) where this is described (incorrectly) */ -#define SCALE_1_TO_1 0x10000L +/* profiling frequency. (No larger than 1000) */ +/* Note this doesn't set the frequency, but merely describes it. */ +#define PROF_HZ 1000 -static void moncontrol(int mode); +struct gmonparam _gmonparam = { off, NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, 0}; -void monstartup (size_t lowpc, size_t highpc) { - register size_t o; - char *cp; - struct gmonparam *p = &_gmonparam; +void monstartup(size_t lowpc, size_t highpc) +{ + static char already_setup = 0; + struct gmonparam *p = &_gmonparam; - if (already_setup) { - /* zero out cp as value will be added there */ - bzero(p->tos, p->kcountsize + p->fromssize + p->tossize); - moncontrol(1); /* start */ - return; - } - already_setup = 1; + if (already_setup) { + /* reinitialize counters and arcs */ + bzero(p->kcount, p->kcountsize); + bzero(p->froms, p->fromssize); + bzero(p->tos, p->tossize); + p->state = on; + return; + } + already_setup = 1; - /* enable semihosting, for eventual output */ - extern void initialise_monitor_handles(void); - initialise_monitor_handles(); + /* enable semihosting, for eventual output */ + extern void initialise_monitor_handles(void); + initialise_monitor_handles(); - /* - * round lowpc and highpc to multiples of the density we're using - * so the rest of the scaling (here and in gprof) stays in ints. - */ - p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER)); - p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER)); - p->textsize = p->highpc - p->lowpc + 0x20; - p->kcountsize = p->textsize / HISTFRACTION; - p->fromssize = p->textsize / HASHFRACTION; - p->tolimit = p->textsize * ARCDENSITY / 100; - if (p->tolimit < MINARCS) { - p->tolimit = MINARCS; - } else if (p->tolimit > MAXARCS) { - p->tolimit = MAXARCS; - } - p->tossize = p->tolimit * sizeof(struct tostruct); + /* + * round lowpc and highpc to multiples of the density we're using + * so the rest of the scaling (here and in gprof) stays in ints. + */ + p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER)); + p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER)); + p->textsize = p->highpc - p->lowpc; + p->kcountsize = p->textsize / HISTFRACTION; + p->fromssize = p->textsize / HASHFRACTION; + p->tolimit = p->textsize * ARCDENSITY / 100; + if (p->tolimit < MINARCS) { + p->tolimit = MINARCS; + } else if (p->tolimit > MAXARCS) { + p->tolimit = MAXARCS; + } + p->tossize = p->tolimit * sizeof(struct tostruct); - extern void *hal_allocate_static_memory(const size_t size); - cp = hal_allocate_static_memory(p->kcountsize + p->fromssize + p->tossize); - if (cp == NULL) { - ERR("monstartup: out of memory\n"); - return; - } + extern void *hal_allocate_static_memory(const size_t size); + void *cp = hal_allocate_static_memory(p->kcountsize + p->fromssize + p->tossize); + if (cp == NULL) { + ERR("monstartup: out of memory\n"); + return; + } - /* zero out cp as value will be added there */ - bzero(cp, p->kcountsize + p->fromssize + p->tossize); + bzero(cp, p->kcountsize + p->fromssize + p->tossize); + p->kcount = (unsigned short *)cp; cp += p->kcountsize; + p->froms = (unsigned short *)cp; cp += p->fromssize; + p->tos = (struct tostruct *)cp; - p->tos = (struct tostruct *)cp; - cp += p->tossize; - p->kcount = (unsigned short *)cp; - cp += p->kcountsize; - p->froms = (unsigned short *)cp; + p->state = on; +} - p->tos[0].link = 0; +void _mcleanup(void) +{ + static const char gmon_out[] = "gmon.out"; + int fd; + struct gmonparam *p = &_gmonparam; - o = p->highpc - p->lowpc; - if (p->kcountsize < o) { -#ifndef notdef - s_scale = ((float)p->kcountsize / o ) * SCALE_1_TO_1; -#else /* avoid floating point */ - int quot = o / p->kcountsize; + if (p->state == err) { + ERR("_mcleanup: tos overflow\n"); + } - if (quot >= 0x10000) - s_scale = 1; - else if (quot >= 0x100) - s_scale = 0x10000 / quot; - else if (o >= 0x800000) - s_scale = 0x1000000 / (o / (p->kcountsize >> 8)); - else - s_scale = 0x1000000 / ((o << 8) / p->kcountsize); -#endif - } else { - s_scale = SCALE_1_TO_1; - } - moncontrol(1); /* start */ -} + fd = open(gmon_out , O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0666); + if (fd < 0) { + perror( gmon_out ); + return; + } -void _mcleanup(void) { - static const char gmon_out[] = "gmon.out"; - int fd; - int fromindex; - int endfrom; - size_t frompc; - int toindex; - struct rawarc rawarc; - struct gmonparam *p = &_gmonparam; - struct gmonhdr gmonhdr = {0}, *hdr; - const char *proffile; -#ifdef DEBUG - int log, len; - char dbuf[200]; -#endif + struct gmonhdr hdr = { + .lpc = p->lowpc, + .hpc = p->highpc, + .ncnt = p->kcountsize + sizeof(struct gmonhdr), + .version = GMONVERSION, + .profrate = PROF_HZ + }; + write(fd, &hdr, sizeof(hdr)); - if (p->state == GMON_PROF_ERROR) { - ERR("_mcleanup: tos overflow\n"); - } - moncontrol(0); /* stop */ - proffile = gmon_out; - fd = open(proffile , O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0666); - if (fd < 0) { - perror( proffile ); - return; - } -#ifdef DEBUG - log = open("gmon.log", O_CREAT|O_TRUNC|O_WRONLY, 0664); - if (log < 0) { - perror("mcount: gmon.log"); - return; - } - len = sprintf(dbuf, "[mcleanup1] kcount 0x%x ssiz %d\n", - (unsigned int)p->kcount, p->kcountsize); - write(log, dbuf, len); -#endif - hdr = (struct gmonhdr *)&gmonhdr; - hdr->lpc = p->lowpc; - hdr->hpc = p->highpc; - hdr->ncnt = p->kcountsize + sizeof(gmonhdr); - hdr->version = GMONVERSION; - hdr->profrate = PROF_HZ; - hdr->spare[0] = hdr->spare[1] = hdr->spare[2] = 0; - write(fd, (char *)hdr, sizeof *hdr); - write(fd, p->kcount, p->kcountsize); - endfrom = p->fromssize / sizeof(*p->froms); - for (fromindex = 0; fromindex < endfrom; fromindex++) { - if (p->froms[fromindex] == 0) { - continue; - } - frompc = p->lowpc; - frompc += fromindex * HASHFRACTION * sizeof(*p->froms); - for (toindex = p->froms[fromindex]; toindex != 0; toindex = p->tos[toindex].link) { -#ifdef DEBUG - len = sprintf(dbuf, - "[mcleanup2] frompc 0x%x selfpc 0x%x count %ld\n" , - frompc, p->tos[toindex].selfpc, - p->tos[toindex].count); - write(log, dbuf, len); -#endif - rawarc.raw_frompc = frompc; - rawarc.raw_selfpc = p->tos[toindex].selfpc; - rawarc.raw_count = p->tos[toindex].count; - write(fd, &rawarc, sizeof rawarc); - } - } - close(fd); -} + write(fd, p->kcount, p->kcountsize); -/* - * Control profiling - * profiling is what mcount checks to see if - * all the data structures are ready. - */ -static void moncontrol(int mode) { - struct gmonparam *p = &_gmonparam; + for (size_t fromindex = 0; fromindex < p->fromssize / sizeof(*p->froms); fromindex++) { + size_t frompc = p->lowpc + fromindex * HASHFRACTION * sizeof(*p->froms); + for (size_t toindex = p->froms[fromindex]; toindex != 0; toindex = p->tos[toindex].next) { + struct rawarc arc = { + .frompc = frompc, + .selfpc = p->tos[toindex].selfpc, + .count = p->tos[toindex].count + }; + write(fd, &arc, sizeof(arc)); + } + } - if (mode) { - /* start */ - profil((char *)p->kcount, p->kcountsize, p->lowpc, s_scale); - p->state = GMON_PROF_ON; - } else { - /* stop */ - profil((char *)0, 0, 0, 0); - p->state = GMON_PROF_OFF; - } + close(fd); } -void _mcount_internal(uint32_t *frompcindex, uint32_t *selfpc) { - register struct tostruct *top; - register struct tostruct *prevtop; - register long toindex; +void _mcount_internal(size_t frompc, size_t selfpc) +{ + register unsigned short *fromptr; + register struct tostruct *top; + register unsigned short toindex; struct gmonparam *p = &_gmonparam; /* - * check that we are profiling - * and that we aren't recursively invoked. - */ - if (p->state!=GMON_PROF_ON) { - goto out; - } - p->state++; - /* - * check that frompcindex is a reasonable pc value. - * for example: signal catchers get called from the stack, - * not from text space. too bad. + * check that we are profiling and that we aren't recursively invoked. + * check that frompc is a reasonable pc value. */ - frompcindex = (uint32_t*)((long)frompcindex - (long)p->lowpc); - if ((unsigned long)frompcindex > p->textsize) { - goto done; + if (p->state != on || (frompc -= p->lowpc) > p->textsize) { + return; } - frompcindex = (uint32_t*)&p->froms[((long)frompcindex) / (HASHFRACTION * sizeof(*p->froms))]; - toindex = *((unsigned short*)frompcindex); /* get froms[] value */ - if (toindex == 0) { - /* - * first time traversing this arc - */ - toindex = ++p->tos[0].link; /* the link of tos[0] points to the last used record in the array */ + + fromptr = &p->froms[frompc / (HASHFRACTION * sizeof(*p->froms))]; + toindex = *fromptr; /* get froms[] value */ + + if (toindex == 0) { /* we haven't seen this caller before */ + toindex = ++p->tos[0].next; /* index of the last used record in the array */ if (toindex >= p->tolimit) { /* more tos[] entries than we can handle! */ - goto overflow; - } - *((unsigned short*)frompcindex) = (unsigned short)toindex; /* store new 'to' value into froms[] */ + overflow: + p->state = err; /* halt further profiling */ +#define TOLIMIT "mcount: tos overflow\n" + write (2, TOLIMIT, sizeof(TOLIMIT)); + return; + } + *fromptr = toindex; /* store new 'to' value into froms[] */ top = &p->tos[toindex]; - top->selfpc = (size_t)selfpc; + top->selfpc = selfpc; top->count = 1; - top->link = 0; - goto done; - } - top = &p->tos[toindex]; - if (top->selfpc == (size_t)selfpc) { - /* - * arc at front of chain; usual case. - */ - top->count++; - goto done; + top->next = 0; } - /* - * have to go looking down chain for it. - * top points to what we are looking at, - * prevtop points to previous top. - * we know it is not at the head of the chain. - */ - for (; /* goto done */; ) { - if (top->link == 0) { + + else { /* we've seen this caller before */ + top = &p->tos[toindex]; + if (top->selfpc == selfpc) { /* - * top is end of the chain and none of the chain - * had top->selfpc == selfpc. - * so we allocate a new tostruct - * and link it to the head of the chain. + * arc at front of chain; usual case. */ - toindex = ++p->tos[0].link; - if (toindex >= p->tolimit) { - goto overflow; - } - top = &p->tos[toindex]; - top->selfpc = (size_t)selfpc; - top->count = 1; - top->link = *((unsigned short*)frompcindex); - *(unsigned short*)frompcindex = (unsigned short)toindex; - goto done; + top->count++; } - /* - * otherwise, check the next arc on the chain. - */ - prevtop = top; - top = &p->tos[top->link]; - if (top->selfpc == (size_t)selfpc) { + + else { /* - * there it is. - * increment its count - * move it to the head of the chain. + * have to go looking down chain for it. + * top points to what we are looking at, + * prevtop points to previous top. + * we know it is not at the head of the chain. */ - top->count++; - toindex = prevtop->link; - prevtop->link = top->link; - top->link = *((unsigned short*)frompcindex); - *((unsigned short*)frompcindex) = (unsigned short)toindex; - goto done; + while (1) { + if (top->next == 0) { + /* + * top is end of the chain and none of the chain + * had top->selfpc == selfpc. + * so we allocate a new tostruct + * and put it at the head of the chain. + */ + toindex = ++p->tos[0].next; + if (toindex >= p->tolimit) { + goto overflow; + } + top = &p->tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->next = *fromptr; + *fromptr = toindex; + break; + } + + else { + /* + * otherwise, check the next arc on the chain. + */ + register struct tostruct *prevtop = top; + top = &p->tos[top->next]; + if (top->selfpc == selfpc) { + /* + * there it is. + * increment its count + * move it to the head of the chain. + */ + top->count++; + toindex = prevtop->next; + prevtop->next = top->next; + top->next = *fromptr; + *fromptr = toindex; + break; + } + } + } } } - done: - p->state--; - /* and fall through */ - out: - return; /* normal return restores saved registers */ - overflow: - p->state++; /* halt further profiling */ - #define TOLIMIT "mcount: tos overflow\n" - write (2, TOLIMIT, sizeof(TOLIMIT)); - goto out; + + return; /* normal return restores saved registers */ } -void _monInit(void) { - _gmonparam.state = GMON_PROF_OFF; - already_setup = 0; +#include <stdint.h> +#include "stm32f4xx_hal.h" /* __get_MSP */ + +/* called from the SysTick handler */ +void profil_callback(void) +{ + struct gmonparam *p = &_gmonparam; + + if (p->state == on) { + /* The interrupt mechanism pushes xPSR, PC, LR, R12, and R3-R0 onto the + * stack, so PC is the 6th word from the top at that point. However, the + * normal function entry code pushes registers as well, so the stack + * offset right now depends on the call tree that got us here. + */ + size_t pc = (size_t)((uint32_t *)__get_MSP())[6 + 6]; + if ((pc -= p->lowpc) < p->textsize) { + size_t idx = pc / (HISTFRACTION * sizeof(*p->kcount)); + p->kcount[idx]++; + } + } } diff --git a/libraries/libprof/gmon.h b/libraries/libprof/gmon.h index 8b5ecf0..9016502 100644 --- a/libraries/libprof/gmon.h +++ b/libraries/libprof/gmon.h @@ -40,28 +40,6 @@ #ifndef _SYS_GMON_H_ #define _SYS_GMON_H_ -#ifndef __P -#define __P(x) x -#endif - -/* On POSIX systems, profile.h is a KRB5 header. To avoid collisions, just - pull in profile.h's content here. The profile.h header won't be provided - by Mingw-w64 anymore at one point. */ -#if 0 -#include <profile.h> -#else -#ifndef _WIN64 -#define _MCOUNT_CALL __attribute__ ((regparm (2))) -extern void _mcount(void); -#else -#define _MCOUNT_CALL -extern void mcount(void); -#endif -#define _MCOUNT_DECL __attribute__((gnu_inline)) __inline__ \ - void _MCOUNT_CALL _mcount_private -#define MCOUNT -#endif - /* * Structure prepended to gmon.out profiling data file. */ @@ -83,7 +61,8 @@ struct gmonhdr { /* * fraction of text space to allocate for histogram counters here, 1/2 */ -#define HISTFRACTION 2 +//#define HISTFRACTION 2 +#define HISTFRACTION 1 /* * Fraction of text space to allocate for from hash buckets. @@ -113,7 +92,8 @@ struct gmonhdr { * profiling data structures without (in practice) sacrificing * any granularity. */ -#define HASHFRACTION 2 +//#define HASHFRACTION 2 +#define HASHFRACTION 1 /* * percent of text space to allocate for tostructs with a minimum. @@ -123,10 +103,10 @@ struct gmonhdr { #define MAXARCS ((1 << (8 * sizeof(HISTCOUNTER))) - 2) struct tostruct { - size_t selfpc; /* callee address/program counter. The caller address is in froms[] array which points to tos[] array */ - long count; /* how many times it has been called */ - unsigned short link; /* link to next entry in hash table. For tos[0] this points to the last used entry */ - unsigned short pad; /* additional padding bytes, to have entries 4byte aligned */ + size_t selfpc; /* callee address. The caller address is in froms[] array which points to tos[] array */ + unsigned long count; /* how many times it has been called */ + unsigned short next; /* next entry in hash table. For tos[0] this is the index of the last used entry */ + unsigned short pad; /* additional padding bytes, to have entries 4byte aligned */ }; /* @@ -134,9 +114,9 @@ struct tostruct { * the called site and a count. */ struct rawarc { - size_t raw_frompc; - size_t raw_selfpc; - long raw_count; + size_t frompc; + size_t selfpc; + long count; }; /* @@ -149,29 +129,20 @@ struct rawarc { * The profiling data structures are housed in this structure. */ struct gmonparam { - int state; + enum { off, on, err } state; unsigned short *kcount; /* histogram PC sample array */ size_t kcountsize; /* size of kcount[] array in bytes */ unsigned short *froms; /* array of hashed 'from' addresses. The 16bit value is an index into the tos[] array */ size_t fromssize; /* size of froms[] array in bytes */ - struct tostruct *tos; /* to struct, contains histogram counter */ + struct tostruct *tos; /* to struct, contains arc counters */ size_t tossize; /* size of tos[] array in bytes */ - long tolimit; + size_t tolimit; size_t lowpc; /* low program counter of area */ size_t highpc; /* high program counter */ size_t textsize; /* code size */ }; extern struct gmonparam _gmonparam; -/* - * Possible states of profiling. - */ -#define GMON_PROF_ON 0 -#define GMON_PROF_BUSY 1 -#define GMON_PROF_ERROR 2 -#define GMON_PROF_OFF 3 - void _mcleanup(void); /* routine to be called to write gmon.out file */ -void _monInit(void); /* initialization routine */ #endif /* !_SYS_GMONH_ */ diff --git a/memfunc.c b/libraries/libprof/memfunc.c index fd94b28..fc908e1 100644 --- a/memfunc.c +++ b/libraries/libprof/memfunc.c @@ -4,9 +4,15 @@ /* * Profilable substitutes for mem*(), lacking libc_p.a * - * This code was written with reference to newlib, but does not copy every - * quirk and loop-unrolling optimization from newlib. Its only purpose is - * to let us figure out who is calling memcpy 2 million times. + * This code was written with reference to newlib, and was recently + * brought closer into line with newlib, to make profiling more accurate. + * + * Newlib is maintained by Cygwin, which is Red Hat. There is no copyright + * statement in the corresponding newlib source files, nor is there a + * COPYING file in newlib/libc/string or newlib/libc. Consider this file + * to be covered under one or more of the 50 copyright notices in + * newlib/COPYING, most of which are BSD. In any case, this file is only + * used for profiling, and is not used in production builds. */ #define is_word_aligned(x) (((size_t)(x) & 3) == 0) @@ -16,12 +22,19 @@ void *memcpy(void *dst, const void *src, size_t n) uint8_t *d8 = (uint8_t *)dst; uint8_t *s8 = (uint8_t *)src; - if (n >= 4 && is_word_aligned(src) && is_word_aligned(dst)) { + if (n >= sizeof(uint32_t) && is_word_aligned(src) && is_word_aligned(dst)) { uint32_t *d32 = (uint32_t *)dst; uint32_t *s32 = (uint32_t *)src; - while (n >= 4) { + while (n >= 4 * sizeof(uint32_t)) { + *d32++ = *s32++; + *d32++ = *s32++; + *d32++ = *s32++; *d32++ = *s32++; - n -= 4; + n -= 4 * sizeof(uint32_t); + } + while (n >= sizeof(uint32_t)) { + *d32++ = *s32++; + n -= sizeof(uint32_t); } d8 = (uint8_t *)d32; s8 = (uint8_t *)s32; @@ -38,12 +51,25 @@ void *memset(void *dst, int c, size_t n) uint8_t *d8 = (uint8_t *)dst; uint8_t c8 = (uint8_t)c; - if (n >= 4 && is_word_aligned(dst)) { - uint32_t *d32 = (uint32_t *)dst; + while (!is_word_aligned(d8)) { + if (n--) + *d8++ = c8; + else + return dst; + } + if (n >= sizeof(uint32_t)) { + uint32_t *d32 = (uint32_t *)d8; uint32_t c32 = (c8 << 24) | (c8 << 16) | (c8 << 8) | (c8); - while (n >= 4) { + while (n >= 4 * sizeof(uint32_t)) { + *d32++ = c32; + *d32++ = c32; + *d32++ = c32; + *d32++ = c32; + n -= 4 * sizeof(uint32_t); + } + while (n >= sizeof(uint32_t)) { *d32++ = c32; - n -= 4; + n -= sizeof(uint32_t); } d8 = (uint8_t *)d32; } @@ -59,15 +85,15 @@ int memcmp(const void *dst, const void *src, size_t n) uint8_t *d8 = (uint8_t *)dst; uint8_t *s8 = (uint8_t *)src; - if (n >= 4 && is_word_aligned(src) && is_word_aligned(dst)) { + if (n >= sizeof(uint32_t) && is_word_aligned(src) && is_word_aligned(dst)) { uint32_t *d32 = (uint32_t *)dst; uint32_t *s32 = (uint32_t *)src; - while (n >= 4) { + while (n >= sizeof(uint32_t)) { if (*d32 != *s32) break; d32++; s32++; - n -= 4; + n -= sizeof(uint32_t); } d8 = (uint8_t *)d32; s8 = (uint8_t *)s32; diff --git a/libraries/libprof/profil.c b/libraries/libprof/profil.c deleted file mode 100644 index b0d8d55..0000000 --- a/libraries/libprof/profil.c +++ /dev/null @@ -1,96 +0,0 @@ -/* profil.c -- win32 profil.c equivalent - - Copyright 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. - - This file is part of Cygwin. - - This software is a copyrighted work licensed under the terms of the - Cygwin license. Please consult the file "CYGWIN_LICENSE" for - details. */ - -/* - * This file is taken from Cygwin distribution, adapted to be used for bare embedded targets. - */ -#include <stdio.h> -#include <sys/types.h> -#include <errno.h> -#include <math.h> -#include "profil.h" -#include <string.h> - -#include "stm32f4xx_hal.h" /* __get_MSP */ - -/* global profinfo for profil() call */ -static struct profinfo prof = { - PROFILE_NOT_INIT, 0, 0, 0, 0 -}; - -/* sample the current program counter */ -void profil_callback(void) { - if (prof.state == PROFILE_ON) { - /* The interrupt mechanism pushes xPSR, PC, LR, R12, and R3-R0 onto the - * stack, so PC is the 6th word from the top at that point. However, the - * normal function entry code pushes registers as well, so the stack - * offset right now depends on the call tree that got us here. - */ - size_t pc = (size_t)((uint32_t *)__get_MSP())[6 + 6]; - if (pc >= prof.lowpc && pc < prof.highpc) { - size_t idx = PROFIDX (pc, prof.lowpc, prof.scale); - prof.counter[idx]++; - } - } -} - -/* Stop profiling to the profiling buffer pointed to by p. */ -static int profile_off (struct profinfo *p) { - p->state = PROFILE_OFF; - return 0; -} - -/* Create a timer thread and pass it a pointer P to the profiling buffer. */ -static int profile_on (struct profinfo *p) { - p->state = PROFILE_ON; - return 0; /* ok */ -} - -/* - * start or stop profiling - * - * profiling goes into the SAMPLES buffer of size SIZE (which is treated - * as an array of unsigned shorts of size size/2) - * - * each bin represents a range of pc addresses from OFFSET. The number - * of pc addresses in a bin depends on SCALE. (A scale of 65536 maps - * each bin to two addresses, A scale of 32768 maps each bin to 4 addresses, - * a scale of 1 maps each bin to 128k address). Scale may be 1 - 65536, - * or zero to turn off profiling - */ -int profile_ctl (struct profinfo *p, char *samples, size_t size, size_t offset, unsigned int scale) { - size_t maxbin; - - if (scale > 65536) { - errno = EINVAL; - return -1; - } - profile_off(p); - if (scale) { - memset(samples, 0, size); - memset(p, 0, sizeof *p); - maxbin = size >> 1; - prof.counter = (unsigned short*)samples; - prof.lowpc = offset; - prof.highpc = PROFADDR(maxbin, offset, scale); - prof.scale = scale; - return profile_on(p); - } - return 0; -} - -/* Equivalent to unix profil() - Every SLEEPTIME interval, the user's program counter (PC) is examined: - offset is subtracted and the result is multiplied by scale. - The word pointed to by this address is incremented. */ -int profil (char *samples, size_t size, size_t offset, unsigned int scale) { - return profile_ctl (&prof, samples, size, offset, scale); -} - diff --git a/libraries/libprof/profil.h b/libraries/libprof/profil.h deleted file mode 100644 index c72dc00..0000000 --- a/libraries/libprof/profil.h +++ /dev/null @@ -1,60 +0,0 @@ -/* profil.h: gprof profiling header file - - Copyright 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -/* - * This file is taken from Cygwin distribution. Please keep it in sync. - * The differences should be within __MINGW32__ guard. - */ - -#ifndef __PROFIL_H__ -#define __PROFIL_H__ - -/* profiling frequency. (No larger than 1000) */ -#define PROF_HZ 1000 - -/* convert an addr to an index */ -#define PROFIDX(pc, base, scale) \ - ({ \ - size_t i = (pc - base) / 2; \ - if (sizeof (unsigned long long int) > sizeof (size_t)) \ - i = (unsigned long long int) i * scale / 65536; \ - else \ - i = i / 65536 * scale + i % 65536 * scale / 65536; \ - i; \ - }) - -/* convert an index into an address */ -#define PROFADDR(idx, base, scale) \ - ((base) \ - + ((((unsigned long long)(idx) << 16) \ - / (unsigned long long)(scale)) << 1)) - -/* convert a bin size into a scale */ -#define PROFSCALE(range, bins) (((bins) << 16) / ((range) >> 1)) - -typedef void *_WINHANDLE; - -typedef enum { - PROFILE_NOT_INIT = 0, - PROFILE_ON, - PROFILE_OFF -} PROFILE_State; - -struct profinfo { - PROFILE_State state; /* profiling state */ - unsigned short *counter; /* profiling counters */ - size_t lowpc, highpc; /* range to be profiled */ - unsigned int scale; /* scale value of bins */ -}; - -int profile_ctl(struct profinfo *, char *, size_t, size_t, unsigned int); -int profil(char *, size_t, size_t, unsigned int); - -#endif /* __PROFIL_H__ */ diff --git a/libraries/libtfm/Makefile b/libraries/libtfm/Makefile index b50421c..359729b 100644 --- a/libraries/libtfm/Makefile +++ b/libraries/libtfm/Makefile @@ -38,7 +38,7 @@ STM32_LIBTFM_CFLAGS_OPTIMIZATION := -O3 -funroll-loops -fomit-frame-pointer endif CFLAGS := $(subst ${STM32_CFLAGS_OPTIMIZATION},${STM32_LIBTFM_CFLAGS_OPTIMIZATION},${CFLAGS}) -CFLAGS += -DTFM_ARM -Dasm=__asm__ -Wa,-mimplicit-it=thumb +CFLAGS += -DTFM_ARM -DENDIAN_LITTLE -Dasm=__asm__ -Wa,-mimplicit-it=thumb CFLAGS += -I${LIBTFM_SRC}/tomsfastmath/src/headers CFLAGS += -DFP_MAX_SIZE="(${BITS}*2+(8*DIGIT_BIT))" CFLAGS += -Wall -W -Wshadow -Wno-uninitialized diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_it.c b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_it.c index 81b27cb..d3bafb2 100644 --- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_it.c +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_it.c @@ -64,13 +64,6 @@ void HardFault_Handler(void) while (1) { ; } } -static void default_SysTick_hook(void) { }; -static void (*SysTick_hook)(void) = default_SysTick_hook; -void set_SysTick_hook(void (*hook)(void)) -{ - SysTick_hook = (hook == NULL) ? default_SysTick_hook : hook; -} - /** * @brief This function handles SysTick Handler. * @param None diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c index 82946fa..c0fe57e 100644 --- a/projects/cli-test/cli-test.c +++ b/projects/cli-test/cli-test.c @@ -88,3 +88,9 @@ void *hal_allocate_static_memory(const size_t size) { return NULL; } + +int hal_free_static_memory(const void * const ptr) +{ + return 0; +} + diff --git a/projects/hsm/Makefile b/projects/hsm/Makefile index 3430e14..37c552d 100644 --- a/projects/hsm/Makefile +++ b/projects/hsm/Makefile @@ -25,7 +25,6 @@ LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 LDFLAGS += -Wl,--gc-sections ifdef DO_PROFILING -OBJS += $(TOPLEVEL)/memfunc.o LDFLAGS += --specs=rdimon.specs -lc -lrdimon endif diff --git a/projects/hsm/hsm.c b/projects/hsm/hsm.c index 64529f6..a34b1f7 100644 --- a/projects/hsm/hsm.c +++ b/projects/hsm/hsm.c @@ -86,27 +86,19 @@ static uint8_t busy_stack[BUSY_STACK_SIZE]; * 4096-byte block of an FPGA or bootloader image upload. */ #ifndef CLI_STACK_SIZE -#define CLI_STACK_SIZE 8*1024 -#endif -static uint8_t cli_stack[CLI_STACK_SIZE]; - -#ifndef MAX_PKT_SIZE -/* An arbitrary number, more or less driven by the 4096-bit RSA - * keygen test. - */ -#define MAX_PKT_SIZE 4096 +#define CLI_STACK_SIZE 16*1024 #endif /* RPC buffers. For each active request, there will be two - input and output. */ typedef struct rpc_buffer_s { size_t len; - uint8_t buf[MAX_PKT_SIZE]; + uint8_t buf[HAL_RPC_MAX_PKT_SIZE]; struct rpc_buffer_s *next; /* for ibuf queue linking */ } rpc_buffer_t; /* RPC input (requst) buffers */ -static rpc_buffer_t ibufs[NUM_RPC_TASK]; +static rpc_buffer_t *ibufs; /* ibuf queue structure */ typedef struct { @@ -348,36 +340,73 @@ static void busy_task(void) } } -/* Allocate memory from SDRAM1. There is only malloc, no free, so we don't - * worry about fragmentation. */ -static uint8_t *sdram_malloc(size_t size) +#include "stm-fpgacfg.h" +#include "hashsig.h" + +static void hashsig_restart_task(void) { - /* end of variables declared with __attribute__((section(".sdram1"))) */ - extern uint8_t _esdram1 __asm ("_esdram1"); - /* end of SDRAM1 section */ - extern uint8_t __end_sdram1 __asm ("__end_sdram1"); + /* wait for the fpga to configure itself on cold-boot */ + while (fpgacfg_check_done() != CMSIS_HAL_OK) + task_yield(); + + /* reinitialize the hashsig key structures after a device restart */ + hal_hashsig_ks_init(); + + /* done, convert this task to an RPC handler */ + task_mod((char *)task_get_cookie(NULL), dispatch_task, NULL); +} - static uint8_t *sdram_heap = &_esdram1; +/* end of variables declared with __attribute__((section(".sdram1"))) */ +extern uint8_t _esdram1 __asm ("_esdram1"); +/* end of SDRAM1 section */ +extern uint8_t __end_sdram1 __asm ("__end_sdram1"); +static uint8_t *sdram_heap = &_esdram1; + +/* Allocate memory from SDRAM1. */ +static uint8_t *sdram_malloc(size_t size) +{ uint8_t *p = sdram_heap; #define pad(n) (((n) + 3) & ~3) size = pad(size); - if (p + size > &__end_sdram1) + if (p + size + sizeof(uint32_t) > &__end_sdram1) return NULL; - sdram_heap += size; + *(uint32_t *)p = (uint32_t)size; + p += sizeof(uint32_t); + + sdram_heap += size + sizeof(uint32_t); return p; } -/* Implement static memory allocation for libhal over sdram_malloc(). - * Once again, there's only alloc, not free. */ +/* A very limited form of free(), which only frees memory if it's at the + * top of the heap. + */ +static hal_error_t sdram_free(uint8_t *ptr) +{ + uint8_t *p = ptr - sizeof(uint32_t); + uint32_t size = *(uint32_t *)p; + if (ptr + size == sdram_heap) { + sdram_heap = p; + return LIBHAL_OK; + } + else + return HAL_ERROR_FORBIDDEN; +} +/* Implement static memory allocation for libhal over sdram_malloc(). + */ void *hal_allocate_static_memory(const size_t size) { return sdram_malloc(size); } +hal_error_t hal_free_static_memory(const void * const ptr) +{ + return sdram_free((uint8_t *)ptr); +} + /* Critical section start/end - temporarily disable interrupts. */ void hal_critical_section_start(void) @@ -431,9 +460,13 @@ int main(void) Error_Handler(); /* Initialize the ibuf queues. */ + ibufs = (rpc_buffer_t *)sdram_malloc(NUM_RPC_TASK * sizeof(rpc_buffer_t)); + if (ibufs == NULL) + Error_Handler(); + memset(ibufs, 0, NUM_RPC_TASK * sizeof(rpc_buffer_t)); memset(&ibuf_waiting, 0, sizeof(ibuf_waiting)); memset(&ibuf_ready, 0, sizeof(ibuf_ready)); - for (size_t i = 0; i < sizeof(ibufs)/sizeof(ibufs[0]); ++i) + for (size_t i = 0; i < NUM_RPC_TASK; ++i) ibuf_put(&ibuf_waiting, &ibufs[i]); /* Create the rpc dispatch worker tasks. */ @@ -443,8 +476,14 @@ int main(void) void *stack = (void *)sdram_malloc(TASK_STACK_SIZE); if (stack == NULL) Error_Handler(); - if (task_add(label[i], dispatch_task, &ibufs[i], stack, TASK_STACK_SIZE) == NULL) - Error_Handler(); + if (i == NUM_RPC_TASK - 1) { + if (task_add("hashsig_restart", hashsig_restart_task, label[i], stack, TASK_STACK_SIZE) == NULL) + Error_Handler(); + } + else { + if (task_add(label[i], dispatch_task, NULL, stack, TASK_STACK_SIZE) == NULL) + Error_Handler(); + } } /* Create the busy task. */ @@ -461,9 +500,13 @@ int main(void) */ /* Create the CLI task. */ - if (task_add("cli", (funcp_t)cli_main, NULL, cli_stack, sizeof(cli_stack)) == NULL) + void *cli_stack = (void *)sdram_malloc(CLI_STACK_SIZE); + if (task_add("cli", (funcp_t)cli_main, NULL, cli_stack, CLI_STACK_SIZE) == NULL) Error_Handler(); /* Start the tasker */ task_yield(); + + /*NOTREACHED*/ + return 0; } diff --git a/projects/hsm/mgmt-keystore.c b/projects/hsm/mgmt-keystore.c index b79a5fe..9eb42da 100644 --- a/projects/hsm/mgmt-keystore.c +++ b/projects/hsm/mgmt-keystore.c @@ -50,6 +50,7 @@ #include <stdlib.h> #include <string.h> +#include <strings.h> #include <ctype.h> @@ -180,6 +181,8 @@ static int cmd_keystore_delete_key(struct cli_def *cli, const char *command, cha return CLI_OK; } +#include "ks.h" + static int show_keys(struct cli_def *cli, const char *title) { const hal_client_handle_t client = { -1 }; @@ -198,6 +201,16 @@ static int show_keys(struct cli_def *cli, const char *title) cli_print(cli, title); + size_t avail; + if ((status = hal_ks_available(hal_ks_token, &avail)) == HAL_OK) + cli_print(cli, "Token keystore: %d available", avail); + else + cli_print(cli, "Error reading token keystore: %s", hal_error_string(status)); + if ((status = hal_ks_available(hal_ks_volatile, &avail)) == HAL_OK) + cli_print(cli, "Volatile keystore: %d available", avail); + else + cli_print(cli, "Error reading volatile keystore: %s", hal_error_string(status)); + while (!done) { if ((status = hal_rpc_pkey_match(client, session, HAL_KEY_TYPE_NONE, HAL_CURVE_NONE, @@ -248,6 +261,10 @@ static int show_keys(struct cli_def *cli, const char *title) case HAL_KEY_TYPE_RSA_PUBLIC: type_name = "RSA public"; break; case HAL_KEY_TYPE_EC_PRIVATE: type_name = "EC private"; break; case HAL_KEY_TYPE_EC_PUBLIC: type_name = "EC public"; break; + case HAL_KEY_TYPE_HASHSIG_PRIVATE: type_name = "hashsig private"; break; + case HAL_KEY_TYPE_HASHSIG_PUBLIC: type_name = "hashsig public"; break; + case HAL_KEY_TYPE_HASHSIG_LMS: type_name = "hashsig lms"; break; + case HAL_KEY_TYPE_HASHSIG_LMOTS: type_name = "hashsig lmots"; break; } const char *curve_name = "unknown"; @@ -304,13 +321,34 @@ static int cmd_keystore_erase(struct cli_def *cli, const char *command, char *ar { hal_error_t err; HAL_StatusTypeDef status; + int preserve_PINs = 0; command = command; - if (argc != 1 || strcmp(argv[0], "YesIAmSure") != 0) { - cli_print(cli, "Syntax: keystore erase YesIAmSure"); + if (argc < 1 || argc > 2 || strcmp(argv[0], "YesIAmSure") != 0) { + usage: + cli_print(cli, "Syntax: keystore erase YesIAmSure [preservePINs]"); return CLI_ERROR; } + if (argc == 2) { + if (strcasecmp(argv[1], "preservePINs") != 0) + goto usage; + else + preserve_PINs = 1; + } + + hal_user_t users[3] = { HAL_USER_NORMAL, HAL_USER_SO, HAL_USER_WHEEL }; + hal_ks_pin_t pins[3]; + if (preserve_PINs) { + for (size_t i = 0; i < 3; ++i) { + const hal_ks_pin_t *pin; + if (hal_get_pin(users[i], &pin) != HAL_OK) { + cli_print(cli, "Failed to get the PINs"); + return CLI_ERROR; + } + memcpy(&pins[i], pin, sizeof(*pin)); + } + } cli_print(cli, "OK, erasing keystore, this will take about 45 seconds..."); if ((status = keystore_erase_bulk()) != CMSIS_HAL_OK) { @@ -328,6 +366,15 @@ static int cmd_keystore_erase(struct cli_def *cli, const char *command, char *ar return CLI_ERROR; } + if (preserve_PINs) { + for (size_t i = 0; i < 3; ++i) { + if (hal_set_pin(users[i], &pins[i]) != HAL_OK) { + cli_print(cli, "Failed to restore the PINs"); + return CLI_ERROR; + } + } + } + cli_print(cli, "Keystore erased"); return CLI_OK; } diff --git a/projects/hsm/mgmt-masterkey.c b/projects/hsm/mgmt-masterkey.c index 765cb10..e63e0e0 100644 --- a/projects/hsm/mgmt-masterkey.c +++ b/projects/hsm/mgmt-masterkey.c @@ -60,24 +60,6 @@ static char * _status2str(const hal_error_t status) } } -static int _parse_hex_groups(uint8_t *buf, size_t len, char *argv[], int argc) -{ - int i; - uint32_t *dst = (uint32_t *) buf; - uint32_t *end = (uint32_t *) buf + len - 1; - char *err_ptr = NULL; - - if (! argc) return 0; - - for (i = 0; i < argc; i++) { - if (dst >= end) return -1; - *dst++ = strtoul(argv[i], &err_ptr, 16); - if (*err_ptr) return -2; - } - - return 1; -} - static int cmd_masterkey_status(struct cli_def *cli, const char *command, char *argv[], int argc) { hal_error_t status; @@ -97,12 +79,54 @@ static int cmd_masterkey_status(struct cli_def *cli, const char *command, char * return CLI_OK; } +static int str_to_hex_digit(char c) +{ + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'a' && c <= 'f') + c = c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + c = c - 'A' + 10; + else + return -1; + + return c; +} + +static inline char hex_to_str_digit(const uint8_t c) +{ + return (c < 10) ? ((char)c + '0') : ((char)c + 'A' - 10); +} + +static char *hexdump_kek(const uint8_t * const kek) +{ + /* This is only for dumping masterkey values, so has no length checks. + * Do not use it for anything else. + * + * For convenience of possibly hand-copying and hand-retyping, the key + * is divided into 8 4-byte (8-character) groups. + */ + + static char buf[2 * KEK_LENGTH + 8]; + char *dst = buf; + + for (size_t i = 0; i < KEK_LENGTH; ++i) { + uint8_t b = kek[i]; + *dst++ = hex_to_str_digit(b >> 4); + *dst++ = hex_to_str_digit(b & 0xf); + if ((i & 3) == 3) + *dst++ = ' '; + } + buf[sizeof(buf) - 1] = '\0'; + + return buf; +} + static int _masterkey_set(struct cli_def *cli, char *argv[], int argc, char *label, hal_error_t (*writer)(const uint8_t * const, const size_t)) { uint8_t buf[KEK_LENGTH] = {0}; hal_error_t err; - int i; if (argc == 0) { /* fill master key with yummy randomness */ @@ -110,20 +134,32 @@ static int _masterkey_set(struct cli_def *cli, char *argv[], int argc, cli_print(cli, "Error getting random key: %s", hal_error_string(err)); return CLI_ERROR; } - cli_print(cli, "Random key:\n"); - uart_send_hexdump(buf, 0, sizeof(buf) - 1); - cli_print(cli, "\n"); + cli_print(cli, "Random key:\n%s", hexdump_kek(buf)); } else { - if ((i = _parse_hex_groups(&buf[0], sizeof(buf), argv, argc)) != 1) { - cli_print(cli, "Failed parsing master key, expected up to 8 groups of 32-bit hex chars (%i)", i); + /* input is 32 hex bytes, arranged however the user wants */ + size_t len = 0; + for (int i = 0; i < argc; ++i) { + for (char *cp = argv[i]; *cp != '\0'; ) { + int c; + if ((c = str_to_hex_digit(*cp++)) < 0) + goto errout; + buf[len] = c << 4; + if ((c = str_to_hex_digit(*cp++)) < 0) + goto errout; + buf[len] |= c & 0xf; + if (++len > KEK_LENGTH) + goto errout; + } + } + if (len < KEK_LENGTH) { + errout: + cli_print(cli, "Failed parsing master key, expected exactly %d hex bytes", KEK_LENGTH); return CLI_ERROR; } - cli_print(cli, "Parsed key:\n"); - uart_send_hexdump(buf, 0, sizeof(buf) - 1); - cli_print(cli, "\n"); + cli_print(cli, "Parsed key:\n%s", hexdump_kek(buf)); } if ((err = writer(buf, sizeof(buf))) == LIBHAL_OK) { diff --git a/projects/libhal-test/main.c b/projects/libhal-test/main.c index fff8c38..c0d9330 100644 --- a/projects/libhal-test/main.c +++ b/projects/libhal-test/main.c @@ -43,6 +43,7 @@ extern void __main(void); int main(void) { stm_init(); + HAL_Delay(500); led_on(LED_GREEN); __main(); diff --git a/spiflash_n25q128.c b/spiflash_n25q128.c index 5e10185..df53f19 100644 --- a/spiflash_n25q128.c +++ b/spiflash_n25q128.c @@ -197,7 +197,7 @@ HAL_StatusTypeDef n25q128_write_page(struct spiflash_ctx *ctx, uint32_t page_off } -static int n25q128_erase_something(struct spiflash_ctx *ctx, uint8_t command, uint32_t byte_offset) +static HAL_StatusTypeDef n25q128_erase_something(struct spiflash_ctx *ctx, uint8_t command, uint32_t byte_offset) { // check offset if (byte_offset >= N25Q128_NUM_BYTES) return HAL_ERROR; @@ -131,6 +131,24 @@ tcb_t *task_add(char *name, funcp_t func, void *cookie, void *stack, size_t stac return t; } +/* Reinitalize the current task. + * NOTE: This will destroy any state in the running task. + * DO NOT CALL THIS UNLESS YOU ARE REALLY SURE THAT'S WHAT YOU WANT TO DO. + */ +void task_mod(char *name, funcp_t func, void *cookie) +{ + tcb_t *t = cur_task; + t->name = name; + t->func = func; + t->cookie = cookie; + t->state = TASK_INIT; + t->stack_ptr = t->stack_base + t->stack_len; + for (uint32_t *p = (uint32_t *)t->stack_base; p < (uint32_t *)t->stack_ptr; ++p) + *p = STACK_GUARD_WORD; + __set_MSP((uint32_t)cur_task->stack_ptr); + task_yield(); +} + /* Set the idle hook function pointer. * * This function is called repeatedly when the system is idle (there are @@ -232,11 +250,11 @@ void task_yield(void) /* If there are no other runnable tasks (and cur_task is runnable), * we don't need to context-switch. */ - if (next == cur_task) + if (next == cur_task && cur_task->state != TASK_INIT) return; /* Save current context, if there is one. */ - if (cur_task != NULL) { + if (cur_task != NULL && cur_task->state != TASK_INIT) { __asm("push {r0-r12, lr}"); cur_task->stack_ptr = (void *)__get_MSP(); @@ -51,6 +51,7 @@ typedef struct { unsigned locked; } task_mutex_t; typedef void (*funcp_t)(void); extern tcb_t *task_add(char *name, funcp_t func, void *cookie, void *stack, size_t stack_len); +extern void task_mod(char *name, funcp_t func, void *cookie); extern void task_set_idle_hook(funcp_t func); |