初始版本

This commit is contained in:
xiaozhengsheng
2025-08-19 09:49:41 +08:00
parent 10f1ddf1c1
commit 6df0f7d96e
2974 changed files with 1712873 additions and 54 deletions

20
external/cJSON/LICENSE vendored Normal file
View File

@@ -0,0 +1,20 @@
Copyright (c) 2009 Dave Gamble
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.

247
external/cJSON/README vendored Normal file
View File

@@ -0,0 +1,247 @@
/*
Copyright (c) 2009 Dave Gamble
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.
*/
Welcome to cJSON.
cJSON aims to be the dumbest possible parser that you can get your job done with.
It's a single file of C, and a single header file.
JSON is described best here: http://www.json.org/
It's like XML, but fat-free. You use it to move data around, store things, or just
generally represent your program's state.
First up, how do I build?
Add cJSON.c to your project, and put cJSON.h somewhere in the header search path.
For example, to build the test app:
gcc cJSON.c test.c -o test -lm
./test
As a library, cJSON exists to take away as much legwork as it can, but not get in your way.
As a point of pragmatism (i.e. ignoring the truth), I'm going to say that you can use it
in one of two modes: Auto and Manual. Let's have a quick run-through.
I lifted some JSON from this page: http://www.json.org/fatfree.html
That page inspired me to write cJSON, which is a parser that tries to share the same
philosophy as JSON itself. Simple, dumb, out of the way.
Some JSON:
{
"name": "Jack (\"Bee\") Nimble",
"format": {
"type": "rect",
"width": 1920,
"height": 1080,
"interlace": false,
"frame rate": 24
}
}
Assume that you got this from a file, a webserver, or magic JSON elves, whatever,
you have a char * to it. Everything is a cJSON struct.
Get it parsed:
cJSON *root = cJSON_Parse(my_json_string);
This is an object. We're in C. We don't have objects. But we do have structs.
What's the framerate?
cJSON *format = cJSON_GetObjectItem(root,"format");
int framerate = cJSON_GetObjectItem(format,"frame rate")->valueint;
Want to change the framerate?
cJSON_GetObjectItem(format,"frame rate")->valueint=25;
Back to disk?
char *rendered=cJSON_Print(root);
Finished? Delete the root (this takes care of everything else).
cJSON_Delete(root);
That's AUTO mode. If you're going to use Auto mode, you really ought to check pointers
before you dereference them. If you want to see how you'd build this struct in code?
cJSON *root,*fmt;
root=cJSON_CreateObject();
cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
cJSON_AddItemToObject(root, "format", fmt=cJSON_CreateObject());
cJSON_AddStringToObject(fmt,"type", "rect");
cJSON_AddNumberToObject(fmt,"width", 1920);
cJSON_AddNumberToObject(fmt,"height", 1080);
cJSON_AddFalseToObject (fmt,"interlace");
cJSON_AddNumberToObject(fmt,"frame rate", 24);
Hopefully we can agree that's not a lot of code? There's no overhead, no unnecessary setup.
Look at test.c for a bunch of nice examples, mostly all ripped off the json.org site, and
a few from elsewhere.
What about manual mode? First up you need some detail.
Let's cover how the cJSON objects represent the JSON data.
cJSON doesn't distinguish arrays from objects in handling; just type.
Each cJSON has, potentially, a child, siblings, value, a name.
The root object has: Object Type and a Child
The Child has name "name", with value "Jack ("Bee") Nimble", and a sibling:
Sibling has type Object, name "format", and a child.
That child has type String, name "type", value "rect", and a sibling:
Sibling has type Number, name "width", value 1920, and a sibling:
Sibling has type Number, name "height", value 1080, and a sibling:
Sibling hs type False, name "interlace", and a sibling:
Sibling has type Number, name "frame rate", value 24
Here's the structure:
typedef struct cJSON {
struct cJSON *next,*prev;
struct cJSON *child;
int type;
char *valuestring;
int valueint;
double valuedouble;
char *string;
} cJSON;
By default all values are 0 unless set by virtue of being meaningful.
next/prev is a doubly linked list of siblings. next takes you to your sibling,
prev takes you back from your sibling to you.
Only objects and arrays have a "child", and it's the head of the doubly linked list.
A "child" entry will have prev==0, but next potentially points on. The last sibling has next=0.
The type expresses Null/True/False/Number/String/Array/Object, all of which are #defined in
cJSON.h
A Number has valueint and valuedouble. If you're expecting an int, read valueint, if not read
valuedouble.
Any entry which is in the linked list which is the child of an object will have a "string"
which is the "name" of the entry. When I said "name" in the above example, that's "string".
"string" is the JSON name for the 'variable name' if you will.
Now you can trivially walk the lists, recursively, and parse as you please.
You can invoke cJSON_Parse to get cJSON to parse for you, and then you can take
the root object, and traverse the structure (which is, formally, an N-tree),
and tokenise as you please. If you wanted to build a callback style parser, this is how
you'd do it (just an example, since these things are very specific):
void parse_and_callback(cJSON *item,const char *prefix)
{
while (item)
{
char *newprefix=malloc(strlen(prefix)+strlen(item->name)+2);
sprintf(newprefix,"%s/%s",prefix,item->name);
int dorecurse=callback(newprefix, item->type, item);
if (item->child && dorecurse) parse_and_callback(item->child,newprefix);
item=item->next;
free(newprefix);
}
}
The prefix process will build you a separated list, to simplify your callback handling.
The 'dorecurse' flag would let the callback decide to handle sub-arrays on it's own, or
let you invoke it per-item. For the item above, your callback might look like this:
int callback(const char *name,int type,cJSON *item)
{
if (!strcmp(name,"name")) { /* populate name */ }
else if (!strcmp(name,"format/type") { /* handle "rect" */ }
else if (!strcmp(name,"format/width") { /* 800 */ }
else if (!strcmp(name,"format/height") { /* 600 */ }
else if (!strcmp(name,"format/interlace") { /* false */ }
else if (!strcmp(name,"format/frame rate") { /* 24 */ }
return 1;
}
Alternatively, you might like to parse iteratively.
You'd use:
void parse_object(cJSON *item)
{
int i; for (i=0;i<cJSON_GetArraySize(item);i++)
{
cJSON *subitem=cJSON_GetArrayItem(item,i);
// handle subitem.
}
}
Or, for PROPER manual mode:
void parse_object(cJSON *item)
{
cJSON *subitem=item->child;
while (subitem)
{
// handle subitem
if (subitem->child) parse_object(subitem->child);
subitem=subitem->next;
}
}
Of course, this should look familiar, since this is just a stripped-down version
of the callback-parser.
This should cover most uses you'll find for parsing. The rest should be possible
to infer.. and if in doubt, read the source! There's not a lot of it! ;)
In terms of constructing JSON data, the example code above is the right way to do it.
You can, of course, hand your sub-objects to other functions to populate.
Also, if you find a use for it, you can manually build the objects.
For instance, suppose you wanted to build an array of objects?
cJSON *objects[24];
cJSON *Create_array_of_anything(cJSON **items,int num)
{
int i;cJSON *prev, *root=cJSON_CreateArray();
for (i=0;i<24;i++)
{
if (!i) root->child=objects[i];
else prev->next=objects[i], objects[i]->prev=prev;
prev=objects[i];
}
return root;
}
and simply: Create_array_of_anything(objects,24);
cJSON doesn't make any assumptions about what order you create things in.
You can attach the objects, as above, and later add children to each
of those objects.
As soon as you call cJSON_Print, it renders the structure to text.
The test.c code shows how to handle a bunch of typical cases. If you uncomment
the code, it'll load, parse and print a bunch of test files, also from json.org,
which are more complex than I'd care to try and stash into a const char array[].
Enjoy cJSON!
- Dave Gamble, Aug 2009

784
external/cJSON/cJSON.c vendored Normal file
View File

@@ -0,0 +1,784 @@
/*
Copyright (c) 2009 Dave Gamble
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.
*/
/* cJSON */
/* JSON parser in C. */
/* Suppress Lint warnings for third-party library. */
/*lint -save -e534 -e547 -e616 -e687 -e689 */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include "cJSON.h"
#include <ctype.h>
#include "math.h"
static const char *ep;
const char *cJSON_GetErrorPtr(void) {return ep;}
static int cJSON_strcasecmp(const char *s1,const char *s2)
{
if (!s1) {return (s1==s2)?0:1;};if (!s2) {return 1;};
for(; tolower(*(const unsigned char *)s1) == tolower(*(const unsigned char *)s2); ++s1, ++s2) if(*s1 == 0) {return 0;};
return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
}
static void *(*cJSON_malloc)(size_t sz) = malloc;
static void (*cJSON_free)(void *ptr) = free;
static char* cJSON_strdup(const char* str)
{
size_t len;
char* copy;
len = strlen(str) + 1;
copy = (char*)cJSON_malloc(len);
if (!copy) return 0;
memcpy(copy,str,len);
return copy;
}
void cJSON_InitHooks(cJSON_Hooks* hooks)
{
if (!hooks) { /* Reset hooks */
cJSON_malloc = malloc;
cJSON_free = free;
return;
}
cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
}
/* Internal constructor. */
static cJSON *cJSON_New_Item(void)
{
cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
if (node) memset(node,0,sizeof(cJSON));
return node;
}
/* Delete a cJSON structure. */
void cJSON_Delete(cJSON *c)
{
cJSON *next;
while (c)
{
next=c->next;
if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string);
cJSON_free(c);
c=next;
}
}
#ifdef CJSON_DOUBLE_SUPPORT
/* Parse the input text to generate a number, and populate the result into item. */
static const char *parse_number(cJSON *item,const char *num)
{
double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
if (*num=='-') sign=-1,num++; /* Has sign? */
if (*num=='0') num++; /* is zero */
if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */
if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */
if (*num=='e' || *num=='E') /* Exponent? */
{ num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */
while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */
}
n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
item->valuedouble=n;
item->valueint=(int)n;
item->type=cJSON_Number;
return num;
}
#else
/* Parse the input text to generate a number, and populate the result into item. */
static const char *parse_number(cJSON *item, const char *num)
{
int n=0,sign=1;
if (*num=='-') sign=-1,num++; /* Has sign? */
if (*num=='0') num++; /* is zero */
if (*num>='1' && *num<='9') do n=(n*10)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */
n=sign*n;
item->valueint=(int)n;
item->type=cJSON_Number;
return num;
}
#endif
static int pow2gt (int x) { --x; x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x+1; }
typedef struct {char *buffer; int length; int offset; } printbuffer;
static char* ensure(printbuffer *p,int needed)
{
char *newbuffer;int newsize;
if (!p || !p->buffer) return 0;
needed+=p->offset;
if (needed<=p->length) return p->buffer+p->offset;
newsize=pow2gt(needed);
newbuffer=(char*)cJSON_malloc(newsize);
if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;}
if (newbuffer) memcpy(newbuffer,p->buffer,p->length);
cJSON_free(p->buffer);
p->length=newsize;
p->buffer=newbuffer;
return newbuffer+p->offset;
}
static int update(printbuffer *p)
{
char *str;
if (!p || !p->buffer) return 0;
str=p->buffer+p->offset;
return p->offset+strlen(str);
}
/* Render the number nicely from the given item into a string. */
static char *print_number(cJSON *item,printbuffer *p)
{
char *str=0;
double d=item->valuedouble;
if (d==0)
{
if (p) str=ensure(p,2);
else str=(char*)cJSON_malloc(2); /* special case for 0. */
if (str) strcpy(str,"0");
}
else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
{
if (p) str=ensure(p,21);
else str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
if (str) sprintf(str,"%d",item->valueint);
}
else
{
if (p) str=ensure(p,64);
else str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
if (str)
{
if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);
else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
else sprintf(str,"%f",d);
}
}
return str;
}
static unsigned parse_hex4(const char *str)
{
unsigned h=0;
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
h=h<<4;str++;
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
h=h<<4;str++;
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
h=h<<4;str++;
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
return h;
}
/* Parse the input text into an unescaped cstring, and populate item. */
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static const char *parse_string(cJSON *item,const char *str)
{
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
if (*str!='\"') {ep=str;return 0;} /* not a string! */
while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
if (!out) return 0;
ptr=str+1;ptr2=out;
while (*ptr!='\"' && *ptr)
{
if (*ptr!='\\') *ptr2++=*ptr++;
else
{
ptr++;
switch (*ptr)
{
case 'b': *ptr2++='\b'; break;
case 'f': *ptr2++='\f'; break;
case 'n': *ptr2++='\n'; break;
case 'r': *ptr2++='\r'; break;
case 't': *ptr2++='\t'; break;
case 'u': /* transcode utf16 to utf8. */
uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */
if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */
if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */
{
if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */
uc2=parse_hex4(ptr+3);ptr+=6;
if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */
uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
}
len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
switch (len) {
case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 1: *--ptr2 =(uc | firstByteMark[len]);
}
ptr2+=len;
break;
default: *ptr2++=*ptr; break;
}
ptr++;
}
}
*ptr2=0;
if (*ptr=='\"') ptr++;
item->valuestring=out;
item->type=cJSON_String;
return ptr;
}
/* Render the cstring provided to an escaped version that can be printed. */
static char *print_string_ptr(const char *str,printbuffer *p)
{
const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token;
for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\'))?1:0;
if (!flag)
{
len=ptr-str;
if (p) out=ensure(p,len+3);
else out=(char*)cJSON_malloc(len+3);
if (!out) return 0;
ptr2=out;*ptr2++='\"';
strcpy(ptr2,str);
ptr2[len]='\"';
ptr2[len+1]=0;
return out;
}
if (!str)
{
if (p) out=ensure(p,3);
else out=(char*)cJSON_malloc(3);
if (!out) return 0;
strcpy(out,"\"\"");
return out;
}
ptr=str;
token=*ptr;
while ((token) && ++len)
{
if (strchr("\"\\\b\f\n\r\t",token))
len++;
else
if (token<32) len+=5;
ptr++;
token=*ptr;
}
if (p) out=ensure(p,len+3);
else out=(char*)cJSON_malloc(len+3);
if (!out) return 0;
ptr2=out;ptr=str;
*ptr2++='\"';
while (*ptr)
{
if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
else
{
*ptr2++='\\';
switch (token=*ptr++)
{
case '\\': *ptr2++='\\'; break;
case '\"': *ptr2++='\"'; break;
case '\b': *ptr2++='b'; break;
case '\f': *ptr2++='f'; break;
case '\n': *ptr2++='n'; break;
case '\r': *ptr2++='r'; break;
case '\t': *ptr2++='t'; break;
default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
}
}
}
*ptr2++='\"';*ptr2++=0;
return out;
}
/* Invote print_string_ptr (which is useful) on an item. */
static char *print_string(cJSON *item,printbuffer *p) {return print_string_ptr(item->valuestring,p);}
/* Predeclare these prototypes. */
static const char *parse_value(cJSON *item,const char *value);
static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p);
static const char *parse_array(cJSON *item,const char *value);
static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p);
static const char *parse_object(cJSON *item,const char *value);
static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p);
/* Utility to jump whitespace and cr/lf */
static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
/* Parse an object - create a new root, and populate. */
cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
{
const char *end=0;
cJSON *c=cJSON_New_Item();
ep=0;
if (!c) return 0; /* memory fail */
end=parse_value(c,skip(value));
if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */
/* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
if (return_parse_end) *return_parse_end=end;
return c;
}
/* Default options for cJSON_Parse */
cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
/* Render a cJSON item/entity/structure to text. */
char *cJSON_Print(cJSON *item) {return print_value(item,0,1,0);}
char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0,0);}
char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt)
{
printbuffer p;
p.buffer=(char*)cJSON_malloc(prebuffer);
p.length=prebuffer;
p.offset=0;
return print_value(item,0,fmt,&p);
}
/* Parser core - when encountering text, process appropriately. */
static const char *parse_value(cJSON *item,const char *value)
{
if (!value) return 0; /* Fail on null. */
if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
if (*value=='\"') { return parse_string(item,value); }
if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
if (*value=='[') { return parse_array(item,value); }
if (*value=='{') { return parse_object(item,value); }
ep=value;return 0; /* failure. */
}
/* Render a value to text. */
static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p)
{
char *out=0;
if (!item) return 0;
if (p)
{
switch ((item->type)&255)
{
case cJSON_NULL: {out=ensure(p,5); if (out) strcpy(out,"null"); break;}
case cJSON_False: {out=ensure(p,6); if (out) strcpy(out,"false"); break;}
case cJSON_True: {out=ensure(p,5); if (out) strcpy(out,"true"); break;}
case cJSON_Number: out=print_number(item,p);break;
case cJSON_String: out=print_string(item,p);break;
case cJSON_Array: out=print_array(item,depth,fmt,p);break;
case cJSON_Object: out=print_object(item,depth,fmt,p);break;
}
}
else
{
switch ((item->type)&255)
{
case cJSON_NULL: out=cJSON_strdup("null"); break;
case cJSON_False: out=cJSON_strdup("false");break;
case cJSON_True: out=cJSON_strdup("true"); break;
case cJSON_Number: out=print_number(item,0);break;
case cJSON_String: out=print_string(item,0);break;
case cJSON_Array: out=print_array(item,depth,fmt,0);break;
case cJSON_Object: out=print_object(item,depth,fmt,0);break;
}
}
return out;
}
/* Build an array from input text. */
static const char *parse_array(cJSON *item,const char *value)
{
cJSON *child;
if (*value!='[') {ep=value;return 0;} /* not an array! */
item->type=cJSON_Array;
value=skip(value+1);
if (*value==']') return value+1; /* empty array. */
item->child=child=cJSON_New_Item();
if (!item->child) return 0; /* memory fail */
value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
if (!value) return 0;
while (*value==',')
{
cJSON *new_item;
new_item=cJSON_New_Item();
if (!new_item) return 0; /* memory fail */
child->next=new_item;new_item->prev=child;child=new_item;
value=skip(parse_value(child,skip(value+1)));
if (!value) return 0; /* memory fail */
}
if (*value==']') return value+1; /* end of array */
ep=value;return 0; /* malformed. */
}
/* Render an array to text */
static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p)
{
char **entries;
char *out=0,*ptr,*ret;int len=5;
cJSON *child=item->child;
int numentries=0,i=0,fail=0;
size_t tmplen=0;
/* How many entries in the array? */
while (child) numentries++,child=child->next;
/* Explicitly handle numentries==0 */
if (!numentries)
{
if (p) out=ensure(p,3);
else out=(char*)cJSON_malloc(3);
if (out) strcpy(out,"[]");
return out;
}
if (p)
{
/* Compose the output array. */
i=p->offset;
ptr=ensure(p,1);if (!ptr) return 0; *ptr='['; p->offset++;
child=item->child;
while (child && !fail)
{
print_value(child,depth+1,fmt,p);
p->offset=update(p);
if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;}
child=child->next;
}
ptr=ensure(p,2);if (!ptr) return 0; *ptr++=']';*ptr=0;
out=(p->buffer)+i;
}
else
{
/* Allocate an array to hold the values for each */
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!entries) return 0;
memset(entries,0,numentries*sizeof(char*));
/* Retrieve all the results: */
child=item->child;
while (child && !fail)
{
ret=print_value(child,depth+1,fmt,0);
entries[i++]=ret;
if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
child=child->next;
}
/* If we didn't fail, try to malloc the output string */
if (!fail) out=(char*)cJSON_malloc(len);
/* If that fails, we fail. */
if (!out) fail=1;
/* Handle failure. */
if (fail)
{
for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
cJSON_free(entries);
return 0;
}
/* Compose the output array. */
*out='[';
ptr=out+1;*ptr=0;
for (i=0;i<numentries;i++)
{
tmplen=strlen(entries[i]);memcpy(ptr,entries[i],tmplen);ptr+=tmplen;
if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
cJSON_free(entries[i]);
}
cJSON_free(entries);
*ptr++=']';*ptr++=0;
}
return out;
}
/* Build an object from the text. */
static const char *parse_object(cJSON *item,const char *value)
{
cJSON *child;
if (*value!='{') {ep=value;return 0;} /* not an object! */
item->type=cJSON_Object;
value=skip(value+1);
if (*value=='}') return value+1; /* empty array. */
item->child=child=cJSON_New_Item();
if (!item->child) return 0;
value=skip(parse_string(child,skip(value)));
if (!value) return 0;
child->string=child->valuestring;child->valuestring=0;
if (*value!=':') {ep=value;return 0;} /* fail! */
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
if (!value) return 0;
while (*value==',')
{
cJSON *new_item;
new_item=cJSON_New_Item();
if (!(new_item)) return 0; /* memory fail */
child->next=new_item;new_item->prev=child;child=new_item;
value=skip(parse_string(child,skip(value+1)));
if (!value) return 0;
child->string=child->valuestring;child->valuestring=0;
if (*value!=':') {ep=value;return 0;} /* fail! */
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
if (!value) return 0;
}
if (*value=='}') return value+1; /* end of array */
ep=value;return 0; /* malformed. */
}
/* Render an object to text. */
static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p)
{
char **entries=0,**names=0;
char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
cJSON *child=item->child;
int numentries=0,fail=0;
size_t tmplen=0;
/* Count the number of entries. */
while (child) numentries++,child=child->next;
/* Explicitly handle empty object case */
if (!numentries)
{
if (p) out=ensure(p,fmt?depth+4:3);
else out=(char*)cJSON_malloc(fmt?depth+4:3);
if (!out) return 0;
ptr=out;*ptr++='{';
if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
*ptr++='}';*ptr++=0;
return out;
}
if (p)
{
/* Compose the output: */
i=p->offset;
len=fmt?2:1; ptr=ensure(p,len+1); if (!ptr) return 0;
*ptr++='{'; if (fmt) *ptr++='\n'; *ptr=0; p->offset+=len;
child=item->child;depth++;
while (child)
{
if (fmt)
{
ptr=ensure(p,depth); if (!ptr) return 0;
for (j=0;j<depth;j++) *ptr++='\t';
p->offset+=depth;
}
print_string_ptr(child->string,p);
p->offset=update(p);
len=fmt?2:1;
ptr=ensure(p,len); if (!ptr) return 0;
*ptr++=':';if (fmt) *ptr++='\t';
p->offset+=len;
print_value(child,depth,fmt,p);
p->offset=update(p);
len=(fmt?1:0)+(child->next?1:0);
ptr=ensure(p,len+1); if (!ptr) return 0;
if (child->next) *ptr++=',';
if (fmt) {*ptr++='\n';};*ptr=0;
p->offset+=len;
child=child->next;
}
ptr=ensure(p,fmt?(depth+1):2); if (!ptr) return 0;
if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
*ptr++='}';*ptr=0;
out=(p->buffer)+i;
}
else
{
/* Allocate space for the names and the objects */
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!entries) return 0;
names=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!names) {cJSON_free(entries);return 0;}
memset(entries,0,sizeof(char*)*numentries);
memset(names,0,sizeof(char*)*numentries);
/* Collect all the results into our arrays: */
child=item->child;depth++;if (fmt) len+=depth;
while (child)
{
names[i]=str=print_string_ptr(child->string,0);
entries[i++]=ret=print_value(child,depth,fmt,0);
if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
child=child->next;
}
/* Try to allocate the output string */
if (!fail) out=(char*)cJSON_malloc(len);
if (!out) fail=1;
/* Handle failure */
if (fail)
{
for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
cJSON_free(names);cJSON_free(entries);
return 0;
}
/* Compose the output: */
*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
for (i=0;i<numentries;i++)
{
if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
tmplen=strlen(names[i]);memcpy(ptr,names[i],tmplen);ptr+=tmplen;
*ptr++=':';if (fmt) *ptr++='\t';
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
if (i!=numentries-1) *ptr++=',';
if (fmt) {*ptr++='\n';};*ptr=0;
cJSON_free(names[i]);cJSON_free(entries[i]);
}
cJSON_free(names);cJSON_free(entries);
if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
*ptr++='}';*ptr++=0;
}
return out;
}
/* Get Array size/item / object item. */
int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
/* Utility for array list handling. */
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
/* Utility for handling references. */
static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
/* Add item to array/object. */
void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);}
void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
if (c->prev) {c->prev->next=c->next;};if (c->next) {c->next->prev=c->prev;};if (c==array->child) {array->child=c->next;};c->prev=c->next=0;return c;}
void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
/* Replace array/object items with new ones. */
void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) {cJSON_AddItemToArray(array,newitem);return;}
newitem->next=c;newitem->prev=c->prev;c->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;}
void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
/* Create basic types: */
cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
/* Create Arrays: */
cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
/* Duplication */
cJSON *cJSON_Duplicate(cJSON *item,int recurse)
{
cJSON *newitem,*cptr,*nptr=0,*newchild;
/* Bail on bad ptr */
if (!item) return 0;
/* Create new item */
newitem=cJSON_New_Item();
if (!newitem) return 0;
/* Copy over all vars */
newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}}
if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}}
/* If non-recursive, then we're done! */
if (!recurse) return newitem;
/* Walk the ->next chain for the child. */
cptr=item->child;
while (cptr)
{
newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */
if (!newchild) {cJSON_Delete(newitem);return 0;}
if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */
else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */
cptr=cptr->next;
}
return newitem;
}
void cJSON_Minify(char *json)
{
char *into=json;
while (*json)
{
if (*json==' ') json++;
else if (*json=='\t') json++; /* Whitespace characters. */
else if (*json=='\r') json++;
else if (*json=='\n') json++;
else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; /* double-slash comments, to end of line. */
else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} /* multiline comments. */
else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */
else *into++=*json++; /* All other characters. */
}
*into=0; /* and null-terminate. */
}
/*lint -restore */

149
external/cJSON/cJSON.h vendored Normal file
View File

@@ -0,0 +1,149 @@
/*
Copyright (c) 2009 Dave Gamble
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.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
/* cJSON Types: */
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON {
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
int type; /* The type of the item, as above. */
char *valuestring; /* The item's string, if type==cJSON_String */
int valueint; /* The item's number, if type==cJSON_Number */
double valuedouble; /* The item's number, if type==cJSON_Number */
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;
typedef struct cJSON_Hooks {
void *(*malloc_fn)(size_t sz);
void (*free_fn)(void *ptr);
} cJSON_Hooks;
/* Supply malloc, realloc and free functions to cJSON */
extern void cJSON_InitHooks(cJSON_Hooks* hooks);
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
extern cJSON *cJSON_Parse(const char *value);
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
extern char *cJSON_Print(cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
extern char *cJSON_PrintUnformatted(cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt);
/* Delete a cJSON entity and all subentities. */
extern void cJSON_Delete(cJSON *c);
/* Returns the number of items in an array (or object). */
extern int cJSON_GetArraySize(cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
/* Get item "string" from object. Case insensitive. */
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
extern const char *cJSON_GetErrorPtr(void);
/* These calls create a cJSON item of the appropriate type. */
extern cJSON *cJSON_CreateNull(void);
extern cJSON *cJSON_CreateTrue(void);
extern cJSON *cJSON_CreateFalse(void);
extern cJSON *cJSON_CreateBool(int b);
extern cJSON *cJSON_CreateNumber(double num);
extern cJSON *cJSON_CreateString(const char *string);
extern cJSON *cJSON_CreateArray(void);
extern cJSON *cJSON_CreateObject(void);
/* These utilities create an Array of count items. */
extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
/* Append item to the specified array/object. */
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
extern void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
/* Remove/Detatch items from Arrays/Objects. */
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
/* Update array items. */
extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* Shifts pre-existing items to the right. */
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
need to be released. With recurse!=0, it will duplicate any children connected to the item.
The item->next and ->prev pointers are always zero on return from Duplicate. */
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
extern void cJSON_Minify(char *json);
/* Macros for creating things quickly. */
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
#define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
#ifdef __cplusplus
}
#endif
#endif

68
external/cJSON/cJSON_iot_hooks.c vendored Normal file
View File

@@ -0,0 +1,68 @@
/**
* Copyright (c) 2015 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, 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.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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.
*
*/
#include <stdlib.h>
#include "cJSON.h"
#include "cJSON_iot_hooks.h"
#include "sdk_config.h"
#include "mem_manager.h"
static cJSON_Hooks m_iot_hooks;
/**@brief malloc() function definition. */
static void * malloc_fn_hook(size_t sz)
{
return nrf_malloc(sz);
}
/**@brief free() function definition. */
static void free_fn_hook(void * p_ptr)
{
nrf_free((uint8_t * ) p_ptr);
}
/**@brief Initialize cJSON by assigning function hooks. */
void cJSON_Init(void)
{
m_iot_hooks.malloc_fn = malloc_fn_hook;
m_iot_hooks.free_fn = free_fn_hook;
cJSON_InitHooks(&m_iot_hooks);
}

67
external/cJSON/cJSON_iot_hooks.h vendored Normal file
View File

@@ -0,0 +1,67 @@
/**
* Copyright (c) 2015 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, 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.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 cJSON_iot_hooks.h
*
* @defgroup cjson cJSON parsing library - IoT hooks.
* @{
*
* @brief Memory allocation hooks using mem_manager.
*/
#ifndef IOT_HOOKS_H__
#define IOT_HOOKS_H__
#include <stdint.h>
/**
* @brief Initialize cJSON with nRF's hooks.
*
* @param None.
*
* @retval None.
*
*/
void cJSON_Init(void);
#endif // IOT_HOOKS_H__
/** @} */

162
external/cJSON/test.c vendored Normal file
View File

@@ -0,0 +1,162 @@
/*
Copyright (c) 2009 Dave Gamble
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.
*/
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
/* Parse text to JSON, then render back to text, and print! */
void doit(char *text)
{
char *out;cJSON *json;
json=cJSON_Parse(text);
if (!json) {printf("Error before: [%s]\n",cJSON_GetErrorPtr());}
else
{
out=cJSON_Print(json);
cJSON_Delete(json);
printf("%s\n",out);
free(out);
}
}
/* Read a file, parse, render back, etc. */
void dofile(char *filename)
{
FILE *f;long len;char *data;
f=fopen(filename,"rb");fseek(f,0,SEEK_END);len=ftell(f);fseek(f,0,SEEK_SET);
data=(char*)malloc(len+1);fread(data,1,len,f);fclose(f);
doit(data);
free(data);
}
/* Used by some code below as an example datatype. */
struct record {const char *precision;double lat,lon;const char *address,*city,*state,*zip,*country; };
/* Create a bunch of objects as demonstration. */
void create_objects()
{
cJSON *root,*fmt,*img,*thm,*fld;char *out;int i; /* declare a few. */
/* Our "days of the week" array: */
const char *strings[7]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
/* Our matrix: */
int numbers[3][3]={{0,-1,0},{1,0,0},{0,0,1}};
/* Our "gallery" item: */
int ids[4]={116,943,234,38793};
/* Our array of "records": */
struct record fields[2]={
{"zip",37.7668,-1.223959e+2,"","SAN FRANCISCO","CA","94107","US"},
{"zip",37.371991,-1.22026e+2,"","SUNNYVALE","CA","94085","US"}};
/* Here we construct some JSON standards, from the JSON site. */
/* Our "Video" datatype: */
root=cJSON_CreateObject();
cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
cJSON_AddItemToObject(root, "format", fmt=cJSON_CreateObject());
cJSON_AddStringToObject(fmt,"type", "rect");
cJSON_AddNumberToObject(fmt,"width", 1920);
cJSON_AddNumberToObject(fmt,"height", 1080);
cJSON_AddFalseToObject (fmt,"interlace");
cJSON_AddNumberToObject(fmt,"frame rate", 24);
out=cJSON_Print(root); cJSON_Delete(root); printf("%s\n",out); free(out); /* Print to text, Delete the cJSON, print it, release the string. */
/* Our "days of the week" array: */
root=cJSON_CreateStringArray(strings,7);
out=cJSON_Print(root); cJSON_Delete(root); printf("%s\n",out); free(out);
/* Our matrix: */
root=cJSON_CreateArray();
for (i=0;i<3;i++) cJSON_AddItemToArray(root,cJSON_CreateIntArray(numbers[i],3));
/* cJSON_ReplaceItemInArray(root,1,cJSON_CreateString("Replacement")); */
out=cJSON_Print(root); cJSON_Delete(root); printf("%s\n",out); free(out);
/* Our "gallery" item: */
root=cJSON_CreateObject();
cJSON_AddItemToObject(root, "Image", img=cJSON_CreateObject());
cJSON_AddNumberToObject(img,"Width",800);
cJSON_AddNumberToObject(img,"Height",600);
cJSON_AddStringToObject(img,"Title","View from 15th Floor");
cJSON_AddItemToObject(img, "Thumbnail", thm=cJSON_CreateObject());
cJSON_AddStringToObject(thm, "Url", "http:/*www.example.com/image/481989943");
cJSON_AddNumberToObject(thm,"Height",125);
cJSON_AddStringToObject(thm,"Width","100");
cJSON_AddItemToObject(img,"IDs", cJSON_CreateIntArray(ids,4));
out=cJSON_Print(root); cJSON_Delete(root); printf("%s\n",out); free(out);
/* Our array of "records": */
root=cJSON_CreateArray();
for (i=0;i<2;i++)
{
cJSON_AddItemToArray(root,fld=cJSON_CreateObject());
cJSON_AddStringToObject(fld, "precision", fields[i].precision);
cJSON_AddNumberToObject(fld, "Latitude", fields[i].lat);
cJSON_AddNumberToObject(fld, "Longitude", fields[i].lon);
cJSON_AddStringToObject(fld, "Address", fields[i].address);
cJSON_AddStringToObject(fld, "City", fields[i].city);
cJSON_AddStringToObject(fld, "State", fields[i].state);
cJSON_AddStringToObject(fld, "Zip", fields[i].zip);
cJSON_AddStringToObject(fld, "Country", fields[i].country);
}
/* cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root,1),"City",cJSON_CreateIntArray(ids,4)); */
out=cJSON_Print(root); cJSON_Delete(root); printf("%s\n",out); free(out);
}
int main (int argc, const char * argv[]) {
/* a bunch of json: */
char text1[]="{\n\"name\": \"Jack (\\\"Bee\\\") Nimble\", \n\"format\": {\"type\": \"rect\", \n\"width\": 1920, \n\"height\": 1080, \n\"interlace\": false,\"frame rate\": 24\n}\n}";
char text2[]="[\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]";
char text3[]="[\n [0, -1, 0],\n [1, 0, 0],\n [0, 0, 1]\n ]\n";
char text4[]="{\n \"Image\": {\n \"Width\": 800,\n \"Height\": 600,\n \"Title\": \"View from 15th Floor\",\n \"Thumbnail\": {\n \"Url\": \"http:/*www.example.com/image/481989943\",\n \"Height\": 125,\n \"Width\": \"100\"\n },\n \"IDs\": [116, 943, 234, 38793]\n }\n }";
char text5[]="[\n {\n \"precision\": \"zip\",\n \"Latitude\": 37.7668,\n \"Longitude\": -122.3959,\n \"Address\": \"\",\n \"City\": \"SAN FRANCISCO\",\n \"State\": \"CA\",\n \"Zip\": \"94107\",\n \"Country\": \"US\"\n },\n {\n \"precision\": \"zip\",\n \"Latitude\": 37.371991,\n \"Longitude\": -122.026020,\n \"Address\": \"\",\n \"City\": \"SUNNYVALE\",\n \"State\": \"CA\",\n \"Zip\": \"94085\",\n \"Country\": \"US\"\n }\n ]";
/* Process each json textblock by parsing, then rebuilding: */
doit(text1);
doit(text2);
doit(text3);
doit(text4);
doit(text5);
/* Parse standard testfiles: */
/* dofile("../../tests/test1"); */
/* dofile("../../tests/test2"); */
/* dofile("../../tests/test3"); */
/* dofile("../../tests/test4"); */
/* dofile("../../tests/test5"); */
/* Now some samplecode for building objects concisely: */
create_objects();
return 0;
}

290
external/cifra_AES128-EAX/bitops.h vendored Normal file
View File

@@ -0,0 +1,290 @@
/*
* cifra - embedded cryptography library
* Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#ifndef BITOPS_H
#define BITOPS_H
#include <stdint.h>
#include <stddef.h>
/* Assorted bitwise and common operations used in ciphers. */
/** Circularly rotate right x by n bits.
* 0 > n > 32. */
static inline uint32_t rotr32(uint32_t x, unsigned n)
{
return (x >> n) | (x << (32 - n));
}
/** Circularly rotate left x by n bits.
* 0 > n > 32. */
static inline uint32_t rotl32(uint32_t x, unsigned n)
{
return (x << n) | (x >> (32 - n));
}
/** Circularly rotate right x by n bits.
* 0 > n > 64. */
static inline uint64_t rotr64(uint64_t x, unsigned n)
{
return (x >> n) | (x << (64 - n));
}
/** Circularly rotate left x by n bits.
* 0 > n > 64. */
static inline uint64_t rotl64(uint64_t x, unsigned n)
{
return (x << n) | (x >> (64 - n));
}
/** Read 4 bytes from buf, as a 32-bit big endian quantity. */
static inline uint32_t read32_be(const uint8_t buf[4])
{
return (buf[0] << 24) |
(buf[1] << 16) |
(buf[2] << 8) |
(buf[3]);
}
/** Read 4 bytes from buf, as a 32-bit little endian quantity. */
static inline uint32_t read32_le(const uint8_t buf[4])
{
return (buf[3] << 24) |
(buf[2] << 16) |
(buf[1] << 8) |
(buf[0]);
}
/** Read 8 bytes from buf, as a 64-bit big endian quantity. */
static inline uint64_t read64_be(const uint8_t buf[8])
{
uint32_t hi = read32_be(buf),
lo = read32_be(buf + 4);
return ((uint64_t)hi) << 32 |
lo;
}
/** Read 8 bytes from buf, as a 64-bit little endian quantity. */
static inline uint64_t read64_le(const uint8_t buf[8])
{
uint32_t hi = read32_le(buf + 4),
lo = read32_le(buf);
return ((uint64_t)hi) << 32 |
lo;
}
/** Encode v as a 32-bit big endian quantity into buf. */
static inline void write32_be(uint32_t v, uint8_t buf[4])
{
*buf++ = (v >> 24) & 0xff;
*buf++ = (v >> 16) & 0xff;
*buf++ = (v >> 8) & 0xff;
*buf = v & 0xff;
}
/** Encode v as a 32-bit little endian quantity into buf. */
static inline void write32_le(uint32_t v, uint8_t buf[4])
{
*buf++ = v & 0xff;
*buf++ = (v >> 8) & 0xff;
*buf++ = (v >> 16) & 0xff;
*buf = (v >> 24) & 0xff;
}
/** Encode v as a 64-bit big endian quantity into buf. */
static inline void write64_be(uint64_t v, uint8_t buf[8])
{
*buf++ = (v >> 56) & 0xff;
*buf++ = (v >> 48) & 0xff;
*buf++ = (v >> 40) & 0xff;
*buf++ = (v >> 32) & 0xff;
*buf++ = (v >> 24) & 0xff;
*buf++ = (v >> 16) & 0xff;
*buf++ = (v >> 8) & 0xff;
*buf = v & 0xff;
}
/** Encode v as a 64-bit little endian quantity into buf. */
static inline void write64_le(uint64_t v, uint8_t buf[8])
{
*buf++ = v & 0xff;
*buf++ = (v >> 8) & 0xff;
*buf++ = (v >> 16) & 0xff;
*buf++ = (v >> 24) & 0xff;
*buf++ = (v >> 32) & 0xff;
*buf++ = (v >> 40) & 0xff;
*buf++ = (v >> 48) & 0xff;
*buf = (v >> 56) & 0xff;
}
/** out = in ^ b8.
* out and in may alias. */
static inline void xor_b8(uint8_t *out, const uint8_t *in, uint8_t b8, size_t len)
{
for (size_t i = 0; i < len; i++)
out[i] = in[i] ^ b8;
}
/** out = x ^ y.
* out, x and y may alias. */
static inline void xor_bb(uint8_t *out, const uint8_t *x, const uint8_t *y, size_t len)
{
for (size_t i = 0; i < len; i++)
out[i] = x[i] ^ y[i];
}
/* out ^= x
* out and x may alias. */
static inline void xor_words(uint32_t *out, const uint32_t *x, size_t nwords)
{
for (size_t i = 0; i < nwords; i++)
out[i] ^= x[i];
}
/** Produce 0xffffffff if x == y, zero otherwise, without branching. */
static inline uint32_t mask_u32(uint32_t x, uint32_t y)
{
uint32_t diff = x ^ y;
uint32_t diff_is_zero = ~diff & (diff - 1);
return - (diff_is_zero >> 31);
}
/** Product 0xff if x == y, zero otherwise, without branching. */
static inline uint8_t mask_u8(uint32_t x, uint32_t y)
{
uint32_t diff = x ^ y;
uint8_t diff_is_zero = ~diff & (diff - 1);
return - (diff_is_zero >> 7);
}
/** Select the ith entry from the given table of n values, in a side channel-silent
* way. */
static inline uint32_t select_u32(uint32_t i, volatile const uint32_t *tab, uint32_t n)
{
uint32_t r = 0;
for (uint32_t ii = 0; ii < n; ii++)
{
uint32_t mask = mask_u32(i, ii);
r = (r & ~mask) | (tab[ii] & mask);
}
return r;
}
/** Select the ith entry from the given table of n values, in a side channel-silent
* way. */
static inline uint8_t select_u8(uint32_t i, volatile const uint8_t *tab, uint32_t n)
{
uint8_t r = 0;
for (uint32_t ii = 0; ii < n; ii++)
{
uint8_t mask = mask_u8(i, ii);
r = (r & ~mask) | (tab[ii] & mask);
}
return r;
}
/** Select the ath, bth, cth and dth entries from the given table of n values,
* placing the results into a, b, c and d. */
static inline void select_u8x4(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d,
volatile const uint8_t *tab, uint32_t n)
{
uint8_t ra = 0,
rb = 0,
rc = 0,
rd = 0;
uint8_t mask;
for (uint32_t i = 0; i < n; i++)
{
uint8_t item = tab[i];
mask = mask_u8(*a, i); ra = (ra & ~mask) | (item & mask);
mask = mask_u8(*b, i); rb = (rb & ~mask) | (item & mask);
mask = mask_u8(*c, i); rc = (rc & ~mask) | (item & mask);
mask = mask_u8(*d, i); rd = (rd & ~mask) | (item & mask);
}
*a = ra;
*b = rb;
*c = rc;
*d = rd;
}
/** out ^= if0 or if1, depending on the value of bit. */
static inline void select_xor128(uint32_t out[4],
const uint32_t if0[4],
const uint32_t if1[4],
uint8_t bit)
{
uint32_t mask1 = mask_u32(bit, 1);
uint32_t mask0 = ~mask1;
out[0] ^= (if0[0] & mask0) | (if1[0] & mask1);
out[1] ^= (if0[1] & mask0) | (if1[1] & mask1);
out[2] ^= (if0[2] & mask0) | (if1[2] & mask1);
out[3] ^= (if0[3] & mask0) | (if1[3] & mask1);
}
/** Increments the integer stored at v (of non-zero length len)
* with the least significant byte first. */
static inline void incr_le(uint8_t *v, size_t len)
{
size_t i = 0;
while (1)
{
if (++v[i] != 0)
return;
i++;
if (i == len)
return;
}
}
/** Increments the integer stored at v (of non-zero length len)
* with the most significant byte last. */
static inline void incr_be(uint8_t *v, size_t len)
{
len--;
while (1)
{
if (++v[len] != 0)
return;
if (len == 0)
return;
len--;
}
}
/** Copies len bytes from in to out, with in shifted left by offset bits
* to the right. */
static inline void copy_bytes_unaligned(uint8_t *out, const uint8_t *in, size_t len, uint8_t offset)
{
uint8_t byte_off = offset / 8;
uint8_t bit_off = offset & 7;
uint8_t rmask = (1 << bit_off) - 1;
uint8_t lmask = ~rmask;
for (size_t i = 0; i < len; i++)
{
out[i] = (in[i + byte_off] << bit_off) & lmask;
out[i] |= (in[i + byte_off + 1] >> (8 - bit_off)) & rmask;
}
}
#endif

197
external/cifra_AES128-EAX/blockwise.c vendored Normal file
View File

@@ -0,0 +1,197 @@
/*
* cifra - embedded cryptography library
* Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include "blockwise.h"
#include "bitops.h"
#include "tassert.h"
#include <string.h>
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
void cf_blockwise_accumulate(uint8_t *partial, size_t *npartial, size_t nblock,
const void *inp, size_t nbytes,
cf_blockwise_in_fn process,
void *ctx)
{
cf_blockwise_accumulate_final(partial, npartial, nblock,
inp, nbytes,
process, process, ctx);
}
void cf_blockwise_accumulate_final(uint8_t *partial, size_t *npartial, size_t nblock,
const void *inp, size_t nbytes,
cf_blockwise_in_fn process,
cf_blockwise_in_fn process_final,
void *ctx)
{
const uint8_t *bufin = inp;
assert(partial && *npartial < nblock);
assert(inp || !nbytes);
assert(process && ctx);
/* If we have partial data, copy in to buffer. */
if (*npartial && nbytes)
{
size_t space = nblock - *npartial;
size_t taken = MIN(space, nbytes);
memcpy(partial + *npartial, bufin, taken);
bufin += taken;
nbytes -= taken;
*npartial += taken;
/* If that gives us a full block, process it. */
if (*npartial == nblock)
{
if (nbytes == 0)
process_final(ctx, partial);
else
process(ctx, partial);
*npartial = 0;
}
}
/* now nbytes < nblock or *npartial == 0. */
/* If we have a full block of data, process it directly. */
while (nbytes >= nblock)
{
/* Partial buffer must be empty, or we're ignoring extant data */
assert(*npartial == 0);
if (nbytes == nblock)
process_final(ctx, bufin);
else
process(ctx, bufin);
bufin += nblock;
nbytes -= nblock;
}
/* Finally, if we have remaining data, buffer it. */
while (nbytes)
{
size_t space = nblock - *npartial;
size_t taken = MIN(space, nbytes);
memcpy(partial + *npartial, bufin, taken);
bufin += taken;
nbytes -= taken;
*npartial += taken;
/* If we started with *npartial, we must have copied it
* in first. */
assert(*npartial < nblock);
}
}
void cf_blockwise_xor(uint8_t *partial, size_t *npartial, size_t nblock,
const void *inp, void *outp, size_t nbytes,
cf_blockwise_out_fn process, void *ctx)
{
const uint8_t *inb = inp;
uint8_t *outb = outp;
assert(partial && *npartial < nblock);
assert(inp || !nbytes);
assert(process && ctx);
while (nbytes)
{
/* If we're out of material, and need more, produce a block. */
if (*npartial == 0)
{
process(ctx, partial);
*npartial = nblock;
}
size_t offset = nblock - *npartial;
size_t taken = MIN(*npartial, nbytes);
xor_bb(outb, inb, partial + offset, taken);
*npartial -= taken;
nbytes -= taken;
outb += taken;
inb += taken;
}
}
void cf_blockwise_acc_byte(uint8_t *partial, size_t *npartial,
size_t nblock,
uint8_t byte, size_t nbytes,
cf_blockwise_in_fn process,
void *ctx)
{
/* only memset the whole of the block once */
int filled = 0;
while (nbytes)
{
size_t start = *npartial;
size_t count = MIN(nbytes, nblock - start);
if (!filled)
memset(partial + start, byte, count);
if (start == 0 && count == nblock)
filled = 1;
if (start + count == nblock)
{
process(ctx, partial);
*npartial = 0;
} else {
*npartial += count;
}
nbytes -= count;
}
}
void cf_blockwise_acc_pad(uint8_t *partial, size_t *npartial,
size_t nblock,
uint8_t fbyte, uint8_t mbyte, uint8_t lbyte,
size_t nbytes,
cf_blockwise_in_fn process,
void *ctx)
{
switch (nbytes)
{
case 0: break;
case 1: fbyte ^= lbyte;
cf_blockwise_accumulate(partial, npartial, nblock, &fbyte, 1, process, ctx);
break;
case 2:
cf_blockwise_accumulate(partial, npartial, nblock, &fbyte, 1, process, ctx);
cf_blockwise_accumulate(partial, npartial, nblock, &lbyte, 1, process, ctx);
break;
default:
cf_blockwise_accumulate(partial, npartial, nblock, &fbyte, 1, process, ctx);
/* If the middle and last bytes differ, then process the last byte separately.
* Otherwise, just extend the middle block size. */
if (lbyte != mbyte)
{
cf_blockwise_acc_byte(partial, npartial, nblock, mbyte, nbytes - 2, process, ctx);
cf_blockwise_accumulate(partial, npartial, nblock, &lbyte, 1, process, ctx);
} else {
cf_blockwise_acc_byte(partial, npartial, nblock, mbyte, nbytes - 1, process, ctx);
}
break;
}
}

147
external/cifra_AES128-EAX/blockwise.h vendored Normal file
View File

@@ -0,0 +1,147 @@
/*
* cifra - embedded cryptography library
* Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#ifndef BLOCKWISE_H
#define BLOCKWISE_H
#include <stdint.h>
#include <stddef.h>
/* Processing function for cf_blockwise_accumulate. */
typedef void (*cf_blockwise_in_fn)(void *ctx, const uint8_t *data);
/* Processing function for cf_blockwise_xor. */
typedef void (*cf_blockwise_out_fn)(void *ctx, uint8_t *data);
/* This function manages the common abstraction of accumulating input in
* a buffer, and processing it when a full block is available.
*
* partial is the buffer (maintained by the caller)
* on entry, npartial is the currently valid count of used bytes on
* the front of partial.
* on exit, npartial is updated to reflect the status of partial.
* nblock is the blocksize to accumulate -- partial must be at least
* this long!
* input is the new data to process, of length nbytes.
* process is the processing function, passed ctx and a pointer
* to the data to process (always exactly nblock bytes long!)
* which may not neccessarily be the same as partial.
*/
void cf_blockwise_accumulate(uint8_t *partial, size_t *npartial,
size_t nblock,
const void *input, size_t nbytes,
cf_blockwise_in_fn process,
void *ctx);
/* This function manages the common abstraction of accumulating input in
* a buffer, and processing it when a full block is available.
* This version supports calling a different processing function for
* the last block.
*
* partial is the buffer (maintained by the caller)
* on entry, npartial is the currently valid count of used bytes on
* the front of partial.
* on exit, npartial is updated to reflect the status of partial.
* nblock is the blocksize to accumulate -- partial must be at least
* this long!
* input is the new data to process, of length nbytes.
* process is the processing function, passed ctx and a pointer
* to the data to process (always exactly nblock bytes long!)
* which may not neccessarily be the same as partial.
* process_final is called last (but may not be called at all if
* all input is buffered).
*/
void cf_blockwise_accumulate_final(uint8_t *partial, size_t *npartial,
size_t nblock,
const void *input, size_t nbytes,
cf_blockwise_in_fn process,
cf_blockwise_in_fn process_final,
void *ctx);
/* This function manages XORing an input stream with a keystream
* to produce an output stream. The keystream is produced in blocks
* (ala a block cipher in counter mode).
*
* partial is the keystream buffer (maintained by the caller)
* on entry, *npartial is the currently valid count of bytes in partial:
* unused bytes are at the *end*. So *npartial = 4 means the last four
* bytes of partial are usable as keystream.
* on exit, npartial is updated to reflect the new state of partial.
* nblock is the blocksize to accumulate -- partial must be at least
* this long!
* input is the new data to process, of length nbytes.
* output is where to write input xored with the keystream -- also length
* nbytes.
* process is the processing function, passed ctx and partial which it
* should fill with fresh key stream.
*/
void cf_blockwise_xor(uint8_t *partial, size_t *npartial,
size_t nblock,
const void *input, void *output, size_t nbytes,
cf_blockwise_out_fn newblock,
void *ctx);
/* This function processes a single byte a number of times. It's useful
* for padding, and more efficient than calling cf_blockwise_accumulate
* a bunch of times.
*
* partial is the buffer (maintained by the caller)
* on entry, npartial is the currently valid count of used bytes on
* the front of partial.
* on exit, npartial is updated to reflect the status of partial.
* nblock is the blocksize to accumulate -- partial must be at least
* this long!
* process is the processing function, passed ctx and a pointer
* to the data to process (always exactly nblock bytes long!)
* which may not neccessarily be the same as partial.
* byte is the byte to process, nbytes times.
*/
void cf_blockwise_acc_byte(uint8_t *partial, size_t *npartial,
size_t nblock,
uint8_t byte, size_t nbytes,
cf_blockwise_in_fn process,
void *ctx);
/* This function attempts to process patterns of bytes common in
* block cipher padding.
*
* This takes three bytes:
* - a first byte, fbyte,
* - a middle byte, mbyte,
* - a last byte, lbyte.
*
* If nbytes is zero, nothing happens.
* If nbytes is one, the byte fbyte ^ lbyte is processed.
* If nbytes is two, the fbyte then lbyte are processed.
* If nbytes is three or more, fbyte, then one or more mbytes, then fbyte
* is processed.
*
* partial is the buffer (maintained by the caller)
* on entry, npartial is the currently valid count of used bytes on
* the front of partial.
* on exit, npartial is updated to reflect the status of partial.
* nblock is the blocksize to accumulate -- partial must be at least
* this long!
* process is the processing function, passed ctx and a pointer
* to the data to process (always exactly nblock bytes long!)
* which may not neccessarily be the same as partial.
*/
void cf_blockwise_acc_pad(uint8_t *partial, size_t *npartial,
size_t nblock,
uint8_t fbyte, uint8_t mbyte, uint8_t lbyte,
size_t nbytes,
cf_blockwise_in_fn process,
void *ctx);
#endif

59
external/cifra_AES128-EAX/cf_config.h vendored Normal file
View File

@@ -0,0 +1,59 @@
/*
* cifra - embedded cryptography library
* Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#ifndef CF_CONFIG_H
#define CF_CONFIG_H
/**
* Library configuration
* =====================
*/
/* .. c:macro:: CF_SIDE_CHANNEL_PROTECTION
* Define this as 1 if you need all available side channel protections.
* **This option may alter the ABI**.
*
* This has a non-trivial performance penalty. Where a
* side-channel free option is cheap or free (like checking
* a MAC) this is always done in a side-channel free way.
*
* The default is **on** for all available protections.
*/
#ifndef CF_SIDE_CHANNEL_PROTECTION
# define CF_SIDE_CHANNEL_PROTECTION 1
#endif
/* .. c:macro:: CF_TIME_SIDE_CHANNEL_PROTECTION
* Define this as 1 if you need timing/branch prediction side channel
* protection.
*
* You probably want this. The default is on. */
#ifndef CF_TIME_SIDE_CHANNEL_PROTECTION
# define CF_TIME_SIDE_CHANNEL_PROTECTION CF_SIDE_CHANNEL_PROTECTION
#endif
/* .. c:macro:: CF_CACHE_SIDE_CHANNEL_PROTECTION
* Define this as 1 if you need cache side channel protection.
*
* If you have a microcontroller with no cache, you can turn this off
* without negative effects.
*
* The default is on. This will have some performance impact,
* especially on AES.
*/
#ifndef CF_CACHE_SIDE_CHANNEL_PROTECTION
# define CF_CACHE_SIDE_CHANNEL_PROTECTION CF_SIDE_CHANNEL_PROTECTION
#endif
#endif

150
external/cifra_AES128-EAX/cifra_cmac.c vendored Normal file
View File

@@ -0,0 +1,150 @@
/*
* cifra - embedded cryptography library
* Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include "handy.h"
#include "prp.h"
#include "modes.h"
#include "bitops.h"
#include "blockwise.h"
#include "gf128.h"
#include "tassert.h"
#include <string.h>
void cf_cmac_init(cf_cmac *ctx, const cf_prp *prp, void *prpctx)
{
uint8_t L[CF_MAXBLOCK];
assert(prp->blocksz == 16);
mem_clean(ctx, sizeof *ctx);
/* L = E_K(0^n) */
mem_clean(L, prp->blocksz);
prp->encrypt(prpctx, L, L);
/* B = 2L */
cf_gf128 gf;
cf_gf128_frombytes_be(L, gf);
cf_gf128_double(gf, gf);
cf_gf128_tobytes_be(gf, ctx->B);
/* P = 4L */
cf_gf128_double(gf, gf);
cf_gf128_tobytes_be(gf, ctx->P);
ctx->prp = prp;
ctx->prpctx = prpctx;
}
void cf_cmac_sign(cf_cmac *ctx, const uint8_t *data, size_t len, uint8_t out[CF_MAXBLOCK])
{
cf_cmac_stream stream;
stream.cmac = *ctx;
cf_cmac_stream_reset(&stream);
cf_cmac_stream_update(&stream, data, len, 1);
cf_cmac_stream_final(&stream, out);
}
void cf_cmac_stream_init(cf_cmac_stream *ctx, const cf_prp *prp, void *prpctx)
{
cf_cmac_init(&ctx->cmac, prp, prpctx);
cf_cmac_stream_reset(ctx);
}
void cf_cmac_stream_reset(cf_cmac_stream *ctx)
{
uint8_t iv_zero[CF_MAXBLOCK] = { 0 };
cf_cbc_init(&ctx->cbc, ctx->cmac.prp, ctx->cmac.prpctx, iv_zero);
mem_clean(ctx->buffer, sizeof ctx->buffer);
ctx->used = 0;
ctx->processed = 0;
ctx->finalised = 0;
}
static void cmac_process(void *vctx, const uint8_t *block)
{
cf_cmac_stream *ctx = vctx;
uint8_t output[CF_MAXBLOCK];
cf_cbc_encrypt(&ctx->cbc, block, output, 1);
ctx->processed += ctx->cmac.prp->blocksz;
}
static void cmac_process_final(cf_cmac_stream *ctx, const uint8_t *block,
const uint8_t *xor)
{
uint8_t input[CF_MAXBLOCK];
uint8_t output[CF_MAXBLOCK];
xor_bb(input, block, xor, ctx->cmac.prp->blocksz);
cf_cbc_encrypt(&ctx->cbc, input, output, 1);
ctx->processed += ctx->cmac.prp->blocksz;
/* signature is in ctx->cbc.block. */
}
static void cmac_process_final_nopad(void *vctx, const uint8_t *block)
{
cf_cmac_stream *ctx = vctx;
cmac_process_final(ctx, block, ctx->cmac.B);
ctx->finalised = 1;
}
static void cmac_process_final_pad(void *vctx, const uint8_t *block)
{
cf_cmac_stream *ctx = vctx;
cmac_process_final(ctx, block, ctx->cmac.P);
ctx->finalised = 1;
}
void cf_cmac_stream_update(cf_cmac_stream *ctx, const uint8_t *data, size_t len, int isfinal)
{
size_t blocksz = ctx->cmac.prp->blocksz;
cf_blockwise_in_fn final_fn = cmac_process;
int needpad = 0;
if (isfinal)
{
int whole_number_of_blocks = ((len + ctx->used) & 0xf) == 0;
int empty_message = len == 0 && ctx->used == 0 && ctx->processed == 0;
assert(!ctx->finalised); /* finalised before? */
assert(len != 0 || empty_message); /* we can't be told we're done after the fact. */
/* If we have a whole number of blocks, and at least 1 block, we XOR in B.
* Otherwise, we need to pad and XOR in P. */
if (whole_number_of_blocks && !empty_message)
final_fn = cmac_process_final_nopad;
else
needpad = 1;
}
/* Input data */
cf_blockwise_accumulate_final(ctx->buffer, &ctx->used, blocksz,
data, len,
cmac_process,
final_fn, ctx);
/* Input padding */
if (needpad)
{
cf_blockwise_acc_pad(ctx->buffer, &ctx->used, blocksz,
0x80, 0x00, 0x00, blocksz - ctx->used,
cmac_process_final_pad, ctx);
}
}
void cf_cmac_stream_final(cf_cmac_stream *ctx, uint8_t out[CF_MAXBLOCK])
{
assert(ctx->finalised);
memcpy(out, ctx->cbc.block, ctx->cmac.prp->blocksz);
}

View File

@@ -0,0 +1,416 @@
/*
* cifra - embedded cryptography library
* Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <string.h>
#include <stdlib.h>
#include "handy.h"
#include "cf_config.h"
#include "cifra_eax_aes.h"
#include "bitops.h"
#include "tassert.h"
static const uint8_t S[256] =
{
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe,
0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4,
0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7,
0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3,
0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09,
0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3,
0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe,
0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92,
0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c,
0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19,
0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2,
0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5,
0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25,
0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86,
0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e,
0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42,
0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};
static const uint8_t Rcon[11] =
{
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
};
#ifdef INLINE_FUNCS
static inline uint32_t word4(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3)
{
return b0 << 24 | b1 << 16 | b2 << 8 | b3;
}
static inline uint8_t byte(uint32_t w, unsigned x)
{
/* nb. bytes are numbered 0 (leftmost, top)
* to 3 (rightmost). */
x = 3 - x;
return (w >> (x * 8)) & 0xff;
}
static uint32_t round_constant(uint32_t i)
{
return Rcon[i] << 24;
}
static uint32_t rot_word(uint32_t w)
{
/* Takes
* word [a0,a1,a2,a3]
* returns
* word [a1,a2,a3,a0]
*
*/
return rotl32(w, 8);
}
#endif
#define word4(a, b, c, d) (((uint32_t)(a) << 24) | ((uint32_t)(b) << 16) | ((uint32_t)(c) << 8) | (d))
#define byte(w, x) ((w >> ((3 - (x)) << 3)) & 0xff)
#define round_constant(i) ((uint32_t)(Rcon[i]) << 24)
#define rot_word(w) rotl32((w), 8)
static uint32_t sub_word(uint32_t w, const uint8_t *sbox)
{
uint8_t a = byte(w, 0),
b = byte(w, 1),
c = byte(w, 2),
d = byte(w, 3);
#if CF_CACHE_SIDE_CHANNEL_PROTECTION
select_u8x4(&a, &b, &c, &d, sbox, 256);
#else
a = sbox[a];
b = sbox[b];
c = sbox[c];
d = sbox[d];
#endif
return word4(a, b, c, d);
}
static void aes_schedule(cf_aes_context *ctx, const uint8_t *key, size_t nkey)
{
size_t i,
nb = AES_BLOCKSZ / 4,
nk = nkey / 4,
n = nb * (ctx->rounds + 1);
uint32_t *w = ctx->ks;
/* First words are just the key. */
for (i = 0; i < nk; i++)
{
w[i] = read32_be(key + i * 4);
}
uint32_t i_div_nk = 1;
uint32_t i_mod_nk = 0;
for (; i < n; i++, i_mod_nk++)
{
uint32_t temp = w[i - 1];
if (i_mod_nk == nk)
{
i_div_nk++;
i_mod_nk = 0;
}
if (i_mod_nk == 0)
temp = sub_word(rot_word(temp), S) ^ round_constant(i_div_nk);
else if (nk > 6 && i_mod_nk == 4)
temp = sub_word(temp, S);
w[i] = w[i - nk] ^ temp;
}
}
void cf_aes_init(cf_aes_context *ctx, const uint8_t *key, size_t nkey)
{
memset(ctx, 0, sizeof *ctx);
switch (nkey)
{
#if CF_AES_MAXROUNDS >= AES128_ROUNDS
case 16:
ctx->rounds = AES128_ROUNDS;
aes_schedule(ctx, key, nkey);
break;
#endif
#if CF_AES_MAXROUNDS >= AES192_ROUNDS
case 24:
ctx->rounds = AES192_ROUNDS;
aes_schedule(ctx, key, nkey);
break;
#endif
#if CF_AES_MAXROUNDS >= AES256_ROUNDS
case 32:
ctx->rounds = AES256_ROUNDS;
aes_schedule(ctx, key, nkey);
break;
#endif
default:
abort();
}
}
static void add_round_key(uint32_t state[4], const uint32_t rk[4])
{
state[0] ^= rk[0];
state[1] ^= rk[1];
state[2] ^= rk[2];
state[3] ^= rk[3];
}
static void sub_block(uint32_t state[4])
{
state[0] = sub_word(state[0], S);
state[1] = sub_word(state[1], S);
state[2] = sub_word(state[2], S);
state[3] = sub_word(state[3], S);
}
static void shift_rows(uint32_t state[4])
{
uint32_t u, v, x, y;
u = word4(byte(state[0], 0),
byte(state[1], 1),
byte(state[2], 2),
byte(state[3], 3));
v = word4(byte(state[1], 0),
byte(state[2], 1),
byte(state[3], 2),
byte(state[0], 3));
x = word4(byte(state[2], 0),
byte(state[3], 1),
byte(state[0], 2),
byte(state[1], 3));
y = word4(byte(state[3], 0),
byte(state[0], 1),
byte(state[1], 2),
byte(state[2], 3));
state[0] = u;
state[1] = v;
state[2] = x;
state[3] = y;
}
static uint32_t gf_poly_mul2(uint32_t x)
{
return
((x & 0x7f7f7f7f) << 1) ^
(((x & 0x80808080) >> 7) * 0x1b);
}
static uint32_t mix_column(uint32_t x)
{
uint32_t x2 = gf_poly_mul2(x);
return x2 ^ rotr32(x ^ x2, 24) ^ rotr32(x, 16) ^ rotr32(x, 8);
}
static void mix_columns(uint32_t state[4])
{
state[0] = mix_column(state[0]);
state[1] = mix_column(state[1]);
state[2] = mix_column(state[2]);
state[3] = mix_column(state[3]);
}
void cf_aes_encrypt(const cf_aes_context *ctx,
const uint8_t in[AES_BLOCKSZ],
uint8_t out[AES_BLOCKSZ])
{
assert(ctx->rounds == AES128_ROUNDS ||
ctx->rounds == AES192_ROUNDS ||
ctx->rounds == AES256_ROUNDS);
uint32_t state[4] = {
read32_be(in + 0),
read32_be(in + 4),
read32_be(in + 8),
read32_be(in + 12)
};
const uint32_t *round_keys = ctx->ks;
add_round_key(state, round_keys);
round_keys += 4;
for (uint32_t round = 1; round < ctx->rounds; round++)
{
sub_block(state);
shift_rows(state);
mix_columns(state);
add_round_key(state, round_keys);
round_keys += 4;
}
sub_block(state);
shift_rows(state);
add_round_key(state, round_keys);
write32_be(state[0], out + 0);
write32_be(state[1], out + 4);
write32_be(state[2], out + 8);
write32_be(state[3], out + 12);
}
#if CF_AES_ENCRYPT_ONLY == 0
static const uint8_t S_inv[256] =
{
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81,
0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e,
0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23,
0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66,
0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72,
0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65,
0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46,
0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca,
0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91,
0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6,
0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f,
0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2,
0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8,
0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93,
0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb,
0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6,
0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};
static void inv_sub_block(uint32_t state[4])
{
state[0] = sub_word(state[0], S_inv);
state[1] = sub_word(state[1], S_inv);
state[2] = sub_word(state[2], S_inv);
state[3] = sub_word(state[3], S_inv);
}
static void inv_shift_rows(uint32_t state[4])
{
uint32_t u, v, x, y;
u = word4(byte(state[0], 0),
byte(state[3], 1),
byte(state[2], 2),
byte(state[1], 3));
v = word4(byte(state[1], 0),
byte(state[0], 1),
byte(state[3], 2),
byte(state[2], 3));
x = word4(byte(state[2], 0),
byte(state[1], 1),
byte(state[0], 2),
byte(state[3], 3));
y = word4(byte(state[3], 0),
byte(state[2], 1),
byte(state[1], 2),
byte(state[0], 3));
state[0] = u;
state[1] = v;
state[2] = x;
state[3] = y;
}
static uint32_t inv_mix_column(uint32_t x)
{
uint32_t x2 = gf_poly_mul2(x),
x4 = gf_poly_mul2(x2),
x9 = x ^ gf_poly_mul2(x4),
x11 = x2 ^ x9,
x13 = x4 ^ x9;
return x ^ x2 ^ x13 ^ rotr32(x11, 24) ^ rotr32(x13, 16) ^ rotr32(x9, 8);
}
static void inv_mix_columns(uint32_t state[4])
{
state[0] = inv_mix_column(state[0]);
state[1] = inv_mix_column(state[1]);
state[2] = inv_mix_column(state[2]);
state[3] = inv_mix_column(state[3]);
}
void cf_aes_decrypt(const cf_aes_context *ctx,
const uint8_t in[AES_BLOCKSZ],
uint8_t out[AES_BLOCKSZ])
{
assert(ctx->rounds == AES128_ROUNDS ||
ctx->rounds == AES192_ROUNDS ||
ctx->rounds == AES256_ROUNDS);
uint32_t state[4] = {
read32_be(in + 0),
read32_be(in + 4),
read32_be(in + 8),
read32_be(in + 12)
};
const uint32_t *round_keys = &ctx->ks[ctx->rounds << 2];
add_round_key(state, round_keys);
round_keys -= 4;
for (uint32_t round = ctx->rounds - 1; round != 0; round--)
{
inv_shift_rows(state);
inv_sub_block(state);
add_round_key(state, round_keys);
inv_mix_columns(state);
round_keys -= 4;
}
inv_shift_rows(state);
inv_sub_block(state);
add_round_key(state, round_keys);
write32_be(state[0], out + 0);
write32_be(state[1], out + 4);
write32_be(state[2], out + 8);
write32_be(state[3], out + 12);
}
#else
void cf_aes_decrypt(const cf_aes_context *ctx,
const uint8_t in[AES_BLOCKSZ],
uint8_t out[AES_BLOCKSZ])
{
abort();
}
#endif
void cf_aes_finish(cf_aes_context *ctx)
{
mem_clean(ctx, sizeof *ctx);
}
const cf_prp cf_aes = {
.blocksz = AES_BLOCKSZ,
.encrypt = (cf_prp_block) cf_aes_encrypt,
.decrypt = (cf_prp_block) cf_aes_decrypt
};

View File

@@ -0,0 +1,152 @@
/*
* cifra - embedded cryptography library
* Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
/**
* The AES block cipher
* ====================
*
* This is a small, simple implementation of AES. Key expansion is done
* first, filling in a :c:type:`cf_aes_context`. Then encryption and
* decryption can be performed as desired.
*
* Usually you don't want to use AES directly; you should use it via
* a :doc:`block cipher mode <modes>`.
*/
#ifndef AES_H
#define AES_H
#include <stddef.h>
#include <stdint.h>
#include "prp.h"
/* .. c:macro:: AES_BLOCKSZ
* AES has a 128-bit block size. This quantity is in bytes.
*/
#define AES_BLOCKSZ 16
/* --- Size configuration --- */
/* .. c:macro:: AES128_ROUNDS
* .. c:macro:: AES192_ROUNDS
* .. c:macro:: AES256_ROUNDS
*
* Round counts for different key sizes.
*/
#define AES128_ROUNDS 10
#define AES192_ROUNDS 12
#define AES256_ROUNDS 14
/* .. c:macro:: CF_AES_MAXROUNDS
*
* You can reduce the maximum number of rounds this implementation
* supports. This reduces the storage needed by :c:type:`cf_aes_context`.
*
* The default is :c:macro:`AES256_ROUNDS` and is good for all key
* sizes.
*/
#ifndef CF_AES_MAXROUNDS
# define CF_AES_MAXROUNDS AES256_ROUNDS
#endif
/* .. c:macro:: CF_AES_ENCRYPT_ONLY
*
* Define this to 1 if you don't need to decrypt anything.
* This saves space. :c:func:`cf_aes_decrypt` calls `abort(3)`.
*/
#ifndef CF_AES_ENCRYPT_ONLY
# define CF_AES_ENCRYPT_ONLY 0
#endif
/* .. c:type:: cf_aes_context
* This type represents an expanded AES key. Create one
* using :c:func:`cf_aes_init`, make use of one using
* :c:func:`cf_aes_encrypt` or :c:func:`cf_aes_decrypt`.
*
* The contents of this structure are equivalent to the
* original key material. You should clean the
* contents of this structure with :c:func:`cf_aes_finish`
* when you're done.
*
* .. c:member:: cf_aes_context.rounds
*
* Number of rounds to use, set by :c:func:`cf_aes_init`.
*
* This depends on the original key size, and will be
* :c:macro:`AES128_ROUNDS`, :c:macro:`AES192_ROUNDS` or
* :c:macro:`AES256_ROUNDS`.
*
* .. c:member:: cf_aes_context.ks
*
* Expanded key material. Filled in by :c:func:`cf_aes_init`.
*/
typedef struct
{
uint32_t rounds;
uint32_t ks[AES_BLOCKSZ / 4 * (CF_AES_MAXROUNDS + 1)];
} cf_aes_context;
/* .. c:function:: $DECL
* This function does AES key expansion. It destroys
* existing contents of :c:data:`ctx`.
*
* :param ctx: expanded key context, filled in by this function.
* :param key: pointer to key material, of :c:data:`nkey` bytes.
* :param nkey: length of key material. Must be `16`, `24` or `32`.
*/
extern void cf_aes_init(cf_aes_context *ctx,
const uint8_t *key,
size_t nkey);
/* .. c:function:: $DECL
* Encrypts the given block, from :c:data:`in` to :c:data:`out`.
* These may alias.
*
* Fails at runtime if :c:data:`ctx` is invalid.
*
* :param ctx: expanded key context
* :param in: input block (read)
* :param out: output block (written)
*/
extern void cf_aes_encrypt(const cf_aes_context *ctx,
const uint8_t in[AES_BLOCKSZ],
uint8_t out[AES_BLOCKSZ]);
/* .. c:function:: $DECL
* Decrypts the given block, from :c:data:`in` to :c:data:`out`.
* These may alias.
*
* Fails at runtime if :c:data:`ctx` is invalid.
*
* :param ctx: expanded key context
* :param in: input block (read)
* :param out: output block (written)
*/
extern void cf_aes_decrypt(const cf_aes_context *ctx,
const uint8_t in[AES_BLOCKSZ],
uint8_t out[AES_BLOCKSZ]);
/* .. c:function:: $DECL
* Erase scheduled key material.
*
* Call this when you're done to erase the round keys. */
extern void cf_aes_finish(cf_aes_context *ctx);
/* .. c:var:: const cf_prp cf_aes
* Abstract interface to AES. See :c:type:`cf_prp` for
* more information. */
extern const cf_prp cf_aes;
#endif

115
external/cifra_AES128-EAX/eax.c vendored Normal file
View File

@@ -0,0 +1,115 @@
/*
* cifra - embedded cryptography library
* Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include "prp.h"
#include "modes.h"
#include "tassert.h"
#include "handy.h"
#include <string.h>
static void cmac_compute_n(cf_cmac_stream *ctx,
uint8_t t,
const uint8_t *input, size_t ninput,
uint8_t out[CF_MAXBLOCK])
{
size_t blocksz = ctx->cmac.prp->blocksz;
assert(blocksz > 0);
uint8_t firstblock[CF_MAXBLOCK];
memset(firstblock, 0, blocksz);
firstblock[blocksz - 1] = t;
cf_cmac_stream_reset(ctx);
if (ninput)
{
cf_cmac_stream_update(ctx, firstblock, blocksz, 0);
cf_cmac_stream_update(ctx, input, ninput, 1);
} else {
cf_cmac_stream_update(ctx, firstblock, blocksz, 1);
}
cf_cmac_stream_final(ctx, out);
}
void cf_eax_encrypt(const cf_prp *prp, void *prpctx,
const uint8_t *plain, size_t nplain,
const uint8_t *header, size_t nheader,
const uint8_t *nonce, size_t nnonce,
uint8_t *cipher, /* the same size as nplain */
uint8_t *tag, size_t ntag)
{
uint8_t NN[CF_MAXBLOCK],
HH[CF_MAXBLOCK],
CC[CF_MAXBLOCK];
cf_cmac_stream cmac;
cf_cmac_stream_init(&cmac, prp, prpctx);
/* NN = OMAC_K^0(N) */
cmac_compute_n(&cmac, 0, nonce, nnonce, NN);
/* HH = OMAC_K^1(H) */
cmac_compute_n(&cmac, 1, header, nheader, HH);
/* C = CTR_K^NN(M) */
cf_ctr ctr;
cf_ctr_init(&ctr, prp, prpctx, NN);
cf_ctr_cipher(&ctr, plain, cipher, nplain);
/* CC = OMAC_K^2(C) */
cmac_compute_n(&cmac, 2, cipher, nplain, CC);
/* Tag = NN ^ CC ^ HH
* T = Tag [ first tau bits ] */
assert(ntag <= prp->blocksz);
for (size_t i = 0; i < ntag; i++)
tag[i] = NN[i] ^ CC[i] ^ HH[i];
}
int cf_eax_decrypt(const cf_prp *prp, void *prpctx,
const uint8_t *cipher, size_t ncipher,
const uint8_t *header, size_t nheader,
const uint8_t *nonce, size_t nnonce,
const uint8_t *tag, size_t ntag,
uint8_t *plain) /* the same size as ncipher */
{
uint8_t NN[CF_MAXBLOCK],
HH[CF_MAXBLOCK],
CC[CF_MAXBLOCK];
cf_cmac_stream cmac;
cf_cmac_stream_init(&cmac, prp, prpctx);
/* NN = OMAC_K^0(N) */
cmac_compute_n(&cmac, 0, nonce, nnonce, NN);
/* HH = OMAC_K^1(H) */
cmac_compute_n(&cmac, 1, header, nheader, HH);
/* CC = OMAC_K^2(C) */
cmac_compute_n(&cmac, 2, cipher, ncipher, CC);
uint8_t tt[CF_MAXBLOCK];
assert(ntag && ntag <= prp->blocksz);
for (size_t i = 0; i < ntag; i++)
tt[i] = NN[i] ^ CC[i] ^ HH[i];
if (!mem_eq(tt, tag, ntag))
return 1;
cf_ctr ctr;
cf_ctr_init(&ctr, prp, prpctx, NN);
cf_ctr_cipher(&ctr, cipher, plain, ncipher);
return 0;
}

113
external/cifra_AES128-EAX/gf128.c vendored Normal file
View File

@@ -0,0 +1,113 @@
/*
* cifra - embedded cryptography library
* Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include "cf_config.h"
#include "gf128.h"
#include "bitops.h"
#include <string.h>
void cf_gf128_tobytes_be(const cf_gf128 in, uint8_t out[16])
{
write32_be(in[0], out + 0);
write32_be(in[1], out + 4);
write32_be(in[2], out + 8);
write32_be(in[3], out + 12);
}
void cf_gf128_frombytes_be(const uint8_t in[16], cf_gf128 out)
{
out[0] = read32_be(in + 0);
out[1] = read32_be(in + 4);
out[2] = read32_be(in + 8);
out[3] = read32_be(in + 12);
}
/* out = 2 * in. Arguments may alias. */
void cf_gf128_double(const cf_gf128 in, cf_gf128 out)
{
uint8_t table[2] = { 0x00, 0x87 };
uint32_t borrow = 0;
uint32_t inword;
inword = in[3]; out[3] = (inword << 1) | borrow; borrow = inword >> 31;
inword = in[2]; out[2] = (inword << 1) | borrow; borrow = inword >> 31;
inword = in[1]; out[1] = (inword << 1) | borrow; borrow = inword >> 31;
inword = in[0]; out[0] = (inword << 1) | borrow; borrow = inword >> 31;
#if CF_CACHE_SIDE_CHANNEL_PROTECTION
out[3] ^= select_u8(borrow, table, 2);
#else
out[3] ^= table[borrow];
#endif
}
/* out = 2 * in. Arguments may alias. */
void cf_gf128_double_le(const cf_gf128 in, cf_gf128 out)
{
uint8_t table[2] = { 0x00, 0xe1 };
uint32_t borrow = 0;
uint32_t inword;
inword = in[0]; out[0] = (inword >> 1) | (borrow << 31); borrow = inword & 1;
inword = in[1]; out[1] = (inword >> 1) | (borrow << 31); borrow = inword & 1;
inword = in[2]; out[2] = (inword >> 1) | (borrow << 31); borrow = inword & 1;
inword = in[3]; out[3] = (inword >> 1) | (borrow << 31); borrow = inword & 1;
#if CF_CACHE_SIDE_CHANNEL_PROTECTION
out[0] ^= select_u8(borrow, table, 2) << 24;
#else
out[0] ^= table[borrow] << 24;
#endif
}
/* out = x + y. Arguments may alias. */
void cf_gf128_add(const cf_gf128 x, const cf_gf128 y, cf_gf128 out)
{
out[0] = x[0] ^ y[0];
out[1] = x[1] ^ y[1];
out[2] = x[2] ^ y[2];
out[3] = x[3] ^ y[3];
}
/* out = xy. Arguments may alias. */
void cf_gf128_mul(const cf_gf128 x, const cf_gf128 y, cf_gf128 out)
{
#if CF_TIME_SIDE_CHANNEL_PROTECTION
cf_gf128 zero = { 0 };
#endif
/* Z_0 = 0^128
* V_0 = Y */
cf_gf128 Z, V;
memset(Z, 0, sizeof Z);
memcpy(V, y, sizeof V);
for (int i = 0; i < 128; i++)
{
uint32_t word = x[i >> 5];
uint8_t bit = (word >> (31 - (i & 31))) & 1;
#if CF_TIME_SIDE_CHANNEL_PROTECTION
select_xor128(Z, zero, V, bit);
#else
if (bit)
xor_words(Z, V, 4);
#endif
cf_gf128_double_le(V, V);
}
memcpy(out, Z, sizeof Z);
}

55
external/cifra_AES128-EAX/gf128.h vendored Normal file
View File

@@ -0,0 +1,55 @@
/*
* cifra - embedded cryptography library
* Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#ifndef GF128_H
#define GF128_H
#include <stddef.h>
#include <stdint.h>
/**
* @brief Operations in GF(2^128).
*
* These implementations are constant time, but relatively slow.
*/
typedef uint32_t cf_gf128[4];
/* Unpack from big-endian bytes into out. */
void cf_gf128_frombytes_be(const uint8_t in[16], cf_gf128 out);
/* Pack in big-endian order into out. */
void cf_gf128_tobytes_be(const cf_gf128 in, uint8_t out[16]);
/* out = 2 * in. Arguments may not alias. */
void cf_gf128_double(const cf_gf128 in, cf_gf128 out);
/* out = 2 * in. Arguments may not alias.
* This differs from cf_gf128_double because it interprets the
* block in little endian: the lsb is the msb of the
* first element, the msb is the lsb of the last element.
*
* GCM uses this convention. */
void cf_gf128_double_le(const cf_gf128 in, cf_gf128 out);
/* out = x + y. Arguments may alias. */
void cf_gf128_add(const cf_gf128 x, const cf_gf128 y, cf_gf128 out);
/* out = xy. Arguments may alias.
*
* This uses cf_gf128_double_le internally, and is suitable for
* GCM. */
void cf_gf128_mul(const cf_gf128 x, const cf_gf128 y, cf_gf128 out);
#endif

88
external/cifra_AES128-EAX/handy.h vendored Normal file
View File

@@ -0,0 +1,88 @@
#ifndef HANDY_H
#define HANDY_H
#include <stddef.h>
#include <stdint.h>
#include <string.h>
/*
* Handy CPP defines and C inline functions.
*/
/* Evaluates to the number of items in array-type variable arr. */
#define ARRAYCOUNT(arr) (sizeof arr / sizeof arr[0])
/* Normal MIN/MAX macros. Evaluate argument expressions only once. */
#ifndef MIN
#define MIN(x, y) \
({ typeof (x) __x = (x); \
typeof (y) __y = (y); \
__x < __y ? __x : __y; })
#endif
#ifndef MAX
#define MAX(x, y) \
({ typeof (x) __x = (x); \
typeof (y) __y = (y); \
__x > __y ? __x : __y; })
#endif
/* Swap two values. Uses GCC type inference magic. */
#ifndef SWAP
#define SWAP(x, y) \
do { \
typeof (x) __tmp = (x); \
(x) = (y); \
(y) = __tmp; \
} while (0)
#endif
/** Stringify its argument. */
#define STRINGIFY(x) STRINGIFY_(x)
#define STRINGIFY_(x) #x
/* Error handling macros.
*
* These expect a zero = success, non-zero = error convention.
*/
/** Error: return.
*
* If the expression fails, return the error from this function. */
#define ER(expr) do { typeof (expr) err_ = (expr); if (err_) return err_; } while (0)
/** Error: goto.
*
* If the expression fails, goto x_err. Assumes defn of label
* x_err and 'error_type err'. */
#define EG(expr) do { err = (expr); if (err) goto x_err; } while (0)
/** Like memset(ptr, 0, len), but not allowed to be removed by
* compilers. */
static inline void mem_clean(volatile void *v, size_t len)
{
if (len)
{
memset((void *) v, 0, len);
(void) *((volatile uint8_t *) v);
}
}
/** Returns 1 if len bytes at va equal len bytes at vb, 0 if they do not.
* Does not leak length of common prefix through timing. */
static inline unsigned mem_eq(const void *va, const void *vb, size_t len)
{
const volatile uint8_t *a = va;
const volatile uint8_t *b = vb;
uint8_t tmp;
uint8_t diff = 0;
while (len--)
{
tmp = *b++;
diff |= *a++ ^ tmp;
}
return !diff;
}
#endif

121
external/cifra_AES128-EAX/license.txt vendored Normal file
View File

@@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

99
external/cifra_AES128-EAX/modes.c vendored Normal file
View File

@@ -0,0 +1,99 @@
/*
* cifra - embedded cryptography library
* Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include "prp.h"
#include "modes.h"
#include "bitops.h"
#include "blockwise.h"
#include <string.h>
#include "tassert.h"
/* CBC */
void cf_cbc_init(cf_cbc *ctx, const cf_prp *prp, void *prpctx, const uint8_t iv[CF_MAXBLOCK])
{
ctx->prp = prp;
ctx->prpctx = prpctx;
memcpy(ctx->block, iv, prp->blocksz);
}
void cf_cbc_encrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks)
{
uint8_t buf[CF_MAXBLOCK];
size_t nblk = ctx->prp->blocksz;
while (blocks--)
{
xor_bb(buf, input, ctx->block, nblk);
ctx->prp->encrypt(ctx->prpctx, buf, ctx->block);
memcpy(output, ctx->block, nblk);
input += nblk;
output += nblk;
}
}
void cf_cbc_decrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks)
{
uint8_t buf[CF_MAXBLOCK];
size_t nblk = ctx->prp->blocksz;
while (blocks--)
{
ctx->prp->decrypt(ctx->prpctx, input, buf);
xor_bb(output, buf, ctx->block, nblk);
memcpy(ctx->block, input, nblk);
input += nblk;
output += nblk;
}
}
/* CTR */
void cf_ctr_init(cf_ctr *ctx, const cf_prp *prp, void *prpctx, const uint8_t nonce[CF_MAXBLOCK])
{
memset(ctx, 0, sizeof *ctx);
ctx->counter_offset = 0;
ctx->counter_width = prp->blocksz;
ctx->prp = prp;
ctx->prpctx = prpctx;
ctx->nkeymat = 0;
memcpy(ctx->nonce, nonce, prp->blocksz);
}
void cf_ctr_custom_counter(cf_ctr *ctx, size_t offset, size_t width)
{
assert(ctx->prp->blocksz <= offset + width);
ctx->counter_offset = offset;
ctx->counter_width = width;
}
static void ctr_next_block(void *vctx, uint8_t *out)
{
cf_ctr *ctx = vctx;
ctx->prp->encrypt(ctx->prpctx, ctx->nonce, out);
incr_be(ctx->nonce + ctx->counter_offset, ctx->counter_width);
}
void cf_ctr_cipher(cf_ctr *ctx, const uint8_t *input, uint8_t *output, size_t bytes)
{
cf_blockwise_xor(ctx->keymat, &ctx->nkeymat,
ctx->prp->blocksz,
input, output, bytes,
ctr_next_block,
ctx);
}
void cf_ctr_discard_block(cf_ctr *ctx)
{
ctx->nkeymat = 0;
}

560
external/cifra_AES128-EAX/modes.h vendored Normal file
View File

@@ -0,0 +1,560 @@
/*
* cifra - embedded cryptography library
* Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#ifndef MODES_H
#define MODES_H
#include <stddef.h>
#include <stdint.h>
#include "prp.h"
/**
* Block cipher modes
* ==================
*/
/**
* CBC mode
* --------
* This implementation allows encryption or decryption of whole
* blocks in CBC mode. It does not offer a byte-wise incremental
* interface, or do any padding.
*
* This mode provides no useful integrity and should not be used
* directly.
*/
/* .. c:type:: cf_cbc
* This structure binds together the things needed to encrypt/decrypt whole
* blocks in CBC mode.
*
* .. c:member:: cf_cbc.prp
* How to encrypt or decrypt blocks. This could be, for example, :c:data:`cf_aes`.
*
* .. c:member:: cf_cbc.prpctx
* Private data for prp functions. For a `prp` of `cf_aes`, this would be a
* pointer to a :c:type:`cf_aes_context` instance.
*
* .. c:member:: cf_cbc.block
* The IV or last ciphertext block.
*/
typedef struct
{
const cf_prp *prp;
void *prpctx;
uint8_t block[CF_MAXBLOCK];
} cf_cbc;
/* .. c:function:: $DECL
* Initialise CBC encryption/decryption context using selected prp, prp context and IV. */
void cf_cbc_init(cf_cbc *ctx, const cf_prp *prp, void *prpctx, const uint8_t iv[CF_MAXBLOCK]);
/* .. c:function:: $DECL
* Encrypt blocks in CBC mode. input and output
* must point to blocks * ctx->prp->blocksz bytes of storage (and may alias). */
void cf_cbc_encrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks);
/* .. c:function:: $DECL
* Decrypt blocks in CBC mode. input and output
* must point to blocks * ctx->prp->blocksz bytes of storage (and may alias). */
void cf_cbc_decrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks);
/**
* Counter mode
* ------------
* This implementation allows incremental encryption/decryption of
* messages. Encryption and decryption are the same operation.
*
* The counter is always big-endian, but has configurable location
* and size within the nonce block. The counter wraps, so you
* should make sure the length of a message with a given nonce
* doesn't cause nonce reuse.
*
* This mode provides no integrity and should not be used directly.
*/
/* .. c:type:: cf_ctr
*
* .. c:member:: cf_ctr.prp
* How to encrypt or decrypt blocks. This could be, for example, :c:data:`cf_aes`.
*
* .. c:member:: cf_ctr.prpctx
* Private data for prp functions. For a `prp` of `cf_aes`, this would be a
* pointer to a :c:type:`cf_aes_context` instance.
*
* .. c:member:: cf_ctr.nonce
* The next block to encrypt to get another block of key stream.
*
* .. c:member:: cf_ctr.keymat
* The current block of key stream.
*
* .. c:member:: cf_ctr.nkeymat
* The number of bytes at the end of :c:member:`keymat` that are so-far unused.
* If this is zero, all the bytes are used up and/or of undefined value.
*
* .. c:member:: cf_ctr.counter_offset
* The offset (in bytes) of the counter block within the nonce.
*
* .. c:member:: cf_ctr.counter_width
* The width (in bytes) of the counter block in the nonce.
*/
typedef struct
{
const cf_prp *prp;
void *prpctx;
uint8_t nonce[CF_MAXBLOCK];
uint8_t keymat[CF_MAXBLOCK];
size_t nkeymat;
size_t counter_offset;
size_t counter_width;
} cf_ctr;
/* .. c:function:: $DECL
* Initialise CTR encryption/decryption context using selected prp and nonce.
* (nb, this only increments the whole nonce as a big endian block) */
void cf_ctr_init(cf_ctr *ctx, const cf_prp *prp, void *prpctx, const uint8_t nonce[CF_MAXBLOCK]);
/* .. c:function:: $DECL
* Set the location and width of the nonce counter.
*
* eg. offset = 12, width = 4 means the counter is mod 2^32 and placed
* at the end of the nonce. */
void cf_ctr_custom_counter(cf_ctr *ctx, size_t offset, size_t width);
/* .. c:function:: $DECL
* Encrypt or decrypt bytes in CTR mode.
* input and output may alias and must point to specified number of bytes. */
void cf_ctr_cipher(cf_ctr *ctx, const uint8_t *input, uint8_t *output, size_t bytes);
/* .. c:function:: $DECL
* Discards the rest of this block of key stream. */
void cf_ctr_discard_block(cf_ctr *ctx);
/**
* CBC-MAC
* -------
* This is a incremental interface to computing a CBC-MAC tag over a message.
*
* It optionally pads the message with PKCS#5/PKCS#7 padding -- if you don't
* do this, messages must be an exact number of blocks long.
*
* You shouldn't use this directly because it isn't secure for variable-length
* messages. Use CMAC instead.
*/
/* .. c:type:: cf_cbcmac_stream
* Stream interface to CBC-MAC signing.
*
* .. c:member:: cf_cbcmac.prp
* How to encrypt or decrypt blocks. This could be, for example, :c:data:`cf_aes`.
*
* .. c:member:: cf_cbcmac.prpctx
* Private data for prp functions. For a `prp` of `cf_aes`, this would be a
* pointer to a :c:type:`cf_aes_context` instance.
*
* .. c:member:: cf_cbcmac.cbc
* CBC data.
*
* .. c:member:: cf_cbcmac.buffer
* Buffer for data which can't be processed until we have a full block.
*
* .. c:member:: cf_cbcmac.used
* How many bytes at the front of :c:member:`buffer` are valid.
*/
typedef struct
{
const cf_prp *prp;
void *prpctx;
cf_cbc cbc;
uint8_t buffer[CF_MAXBLOCK];
size_t used;
} cf_cbcmac_stream;
/* .. c:function:: $DECL
* Initialise CBC-MAC signing context using selected prp. */
void cf_cbcmac_stream_init(cf_cbcmac_stream *ctx, const cf_prp *prp, void *prpctx);
/* .. c:function:: $DECL
* Reset the streaming signing context, to sign a new message. */
void cf_cbcmac_stream_reset(cf_cbcmac_stream *ctx);
/* .. c:function:: $DECL
* Process ndata bytes at data. */
void cf_cbcmac_stream_update(cf_cbcmac_stream *ctx, const uint8_t *data, size_t ndata);
/* .. c:function:: $DECL
* Finish the current block of data by adding zeroes. Does nothing if there
* are no bytes awaiting processing. */
void cf_cbcmac_stream_finish_block_zero(cf_cbcmac_stream *ctx);
/* .. c:function:: $DECL
* Output the MAC to ctx->prp->blocksz bytes at out.
* ctx->used must be zero: the inputed message must be an exact number of
* blocks. */
void cf_cbcmac_stream_nopad_final(cf_cbcmac_stream *ctx, uint8_t out[CF_MAXBLOCK]);
/* .. c:function:: $DECL
* Output the MAC to ctx->prp->blocksz bytes at out.
*
* The message is padded with PKCS#5 padding. */
void cf_cbcmac_stream_pad_final(cf_cbcmac_stream *ctx, uint8_t out[CF_MAXBLOCK]);
/**
* CMAC
* ----
* This is both a one-shot and incremental interface to
* computing a CMAC tag over a message.
*
* The one-shot interface separates out the per-key computation,
* so if you need to compute lots of MACs with one key you don't
* pay that cost more than once.
*
* CMAC is a good choice for a symmetric MAC.
*/
/* .. c:type:: cf_cmac
* One-shot interface to CMAC signing.
*
* .. c:member:: cf_cmac.prp
* How to encrypt or decrypt blocks. This could be, for example, :c:data:`cf_aes`.
*
* .. c:member:: cf_cmac.prpctx
* Private data for prp functions. For a `prp` of `cf_aes`, this would be a
* pointer to a :c:type:`cf_aes_context` instance.
*
* .. c:member:: cf_cmac.B
* The XOR offset for the last message block if it is a complete block
* (also known as K\ :sub:`1`).
*
* .. c:member:: cf_cmac.P
* The XOR offset for the last message block if it is a partial block
* (also known as K\ :sub:`2`).
*/
typedef struct
{
const cf_prp *prp;
void *prpctx;
uint8_t B[CF_MAXBLOCK];
uint8_t P[CF_MAXBLOCK];
} cf_cmac;
/* .. c:function:: $DECL
* Initialise CMAC signing context using selected prp. */
void cf_cmac_init(cf_cmac *ctx, const cf_prp *prp, void *prpctx);
/* .. c:function:: $DECL
* CMAC sign the given data. The MAC is written to ctx->prp->blocksz
* bytes at out. This is a one-shot function. */
void cf_cmac_sign(cf_cmac *ctx, const uint8_t *data, size_t bytes,
uint8_t out[CF_MAXBLOCK]);
/* .. c:type:: cf_cmac_stream
* Stream interface to CMAC signing.
*
* Input data in arbitrary chunks using :c:func:`cf_cmac_stream_update`.
* The last bit of data must be signalled with the `isfinal` flag to
* that function, and the data cannot be zero length unless the whole
* message is empty.
*
* .. c:member:: cf_cmac_stream.cmac
* CMAC one-shot data.
*
* .. c:member:: cf_cmac_stream.cbc
* CBC block encryption data.
*
* .. c:member:: cf_cmac_stream.buffer
* Buffer for data which can't be processed until we have a full block.
*
* .. c:member:: cf_cmac_stream.used
* How many bytes at the front of :c:member:`buffer` are valid.
*
* .. c:member:: cf_cmac_stream.processed
* How many bytes in total we've processed. This is used to correctly
* process empty messages.
*
* .. c:member:: cf_cmac_stream.finalised
* A flag set when the final chunk of the message has been processed.
* Only when this flag is set can you get the MAC out.
*/
typedef struct
{
cf_cmac cmac;
cf_cbc cbc;
uint8_t buffer[CF_MAXBLOCK];
size_t used;
size_t processed;
int finalised;
} cf_cmac_stream;
/* .. c:function:: $DECL
* Initialise CMAC streaming signing context using selected prp. */
void cf_cmac_stream_init(cf_cmac_stream *ctx, const cf_prp *prp, void *prpctx);
/* .. c:function:: $DECL
* Reset the streaming signing context, to sign a new message. */
void cf_cmac_stream_reset(cf_cmac_stream *ctx);
/* .. c:function:: $DECL
* Process ndata bytes at data. isfinal is non-zero if this is the last piece
* of data. */
void cf_cmac_stream_update(cf_cmac_stream *ctx, const uint8_t *data, size_t ndata,
int isfinal);
/* .. c:function:: $DECL
* Output the MAC to ctx->cmac->prp->blocksz bytes at out.
* cf_cmac_stream_update with isfinal non-zero must have been called
* since the last _init/_reset. */
void cf_cmac_stream_final(cf_cmac_stream *ctx, uint8_t out[CF_MAXBLOCK]);
/**
* EAX
* ---
*
* The EAX authenticated encryption mode. This is a one-shot
* interface.
*
* EAX is a pretty respectable and fast AEAD mode.
*/
/* .. c:function:: $DECL
* EAX authenticated encryption.
*
* This function does not fail.
*
* :param prp/prpctx: describe the block cipher to use.
* :param plain: message plaintext.
* :param nplain: length of message. May be zero.
* :param header: additionally authenticated data (AAD).
* :param nheader: length of AAD. May be zero.
* :param nonce: nonce. This must not repeat for a given key.
* :param nnonce: length of nonce. The nonce can be any length.
* :param cipher: ciphertext output. `nplain` bytes are written here.
* :param tag: authentication tag. `ntag` bytes are written here.
* :param ntag: authentication tag length. This must be non-zero and no greater than `prp->blocksz`.
*/
void cf_eax_encrypt(const cf_prp *prp, void *prpctx,
const uint8_t *plain, size_t nplain,
const uint8_t *header, size_t nheader,
const uint8_t *nonce, size_t nnonce,
uint8_t *cipher,
uint8_t *tag, size_t ntag);
/* .. c:function:: $DECL
* EAX authenticated decryption.
*
* :return: 0 on success, non-zero on error. Nothing is written to plain on error.
*
* :param prp/prpctx: describe the block cipher to use.
* :param cipher: message ciphertext.
* :param ncipher: message length.
* :param header: additionally authenticated data (AAD).
* :param nheader: length of AAD.
* :param nonce: nonce.
* :param nnonce: length of nonce.
* :param tag: authentication tag. `ntag` bytes are read from here.
* :param ntag: authentication tag length.
* :param plain: plaintext output. `ncipher` bytes are written here.
*/
int cf_eax_decrypt(const cf_prp *prp, void *prpctx,
const uint8_t *cipher, size_t ncipher,
const uint8_t *header, size_t nheader,
const uint8_t *nonce, size_t nnonce,
const uint8_t *tag, size_t ntag,
uint8_t *plain);
/**
* GCM
* ---
* The GCM ('Galois counter mode') authenticated encryption mode.
* This is a one-shot interface.
*
* GCM is a reasonably respectable AEAD mode. It's somewhat more
* complex than EAX, and side channel-free implementations can
* be quite slow.
*/
/* .. c:function:: $DECL
* GCM authenticated encryption.
*
* This function does not fail.
*
* :param prp/prpctx: describe the block cipher to use.
* :param plain: message plaintext.
* :param nplain: length of message. May be zero.
* :param header: additionally authenticated data (AAD).
* :param nheader: length of AAD. May be zero.
* :param nonce: nonce. This must not repeat for a given key.
* :param nnonce: length of nonce. The nonce can be any length, but 12 bytes is strongly recommended.
* :param cipher: ciphertext output. `nplain` bytes are written here.
* :param tag: authentication tag. `ntag` bytes are written here.
* :param ntag: authentication tag length. This must be non-zero and no greater than `prp->blocksz`.
*
* This function does not fail.
*/
void cf_gcm_encrypt(const cf_prp *prp, void *prpctx,
const uint8_t *plain, size_t nplain,
const uint8_t *header, size_t nheader,
const uint8_t *nonce, size_t nnonce,
uint8_t *cipher,
uint8_t *tag, size_t ntag);
/* .. c:function:: $DECL
* GCM authenticated decryption.
*
* :return: 0 on success, non-zero on error. Nothing is written to plain on error.
*
* :param prp: describe the block cipher to use.
* :param prpctx: describe the block cipher to use.
* :param cipher: message ciphertext.
* :param ncipher: message length.
* :param header: additionally authenticated data (AAD).
* :param nheader: length of AAD.
* :param nonce: nonce.
* :param nnonce: length of nonce.
* :param tag: authentication tag. `ntag` bytes are read from here.
* :param ntag: authentication tag length.
* :param plain: plaintext output. `ncipher` bytes are written here.
*/
int cf_gcm_decrypt(const cf_prp *prp, void *prpctx,
const uint8_t *cipher, size_t ncipher,
const uint8_t *header, size_t nheader,
const uint8_t *nonce, size_t nnonce,
const uint8_t *tag, size_t ntag,
uint8_t *plain);
/**
* CCM
* ---
*
* The CCM ('Counter with CBC-MAC') authenticated encryption mode.
* CCM is a widely used AEAD mode (in IPSec, WPA2, Bluetooth, etc.)
*
* It works (at a high level) by just gluing together CTR and CBC-MAC
* modes (in MAC-then-encrypt mode) and then fixing the problems inherent
* with CBC-MAC in over-complicated ways.
*
* This is a one-shot interface, which is good because the underlying
* mechanism isn't actually online: you need to know the message length
* before you start, or do everything in two passes.
*/
/* .. c:function:: $DECL
* CCM authenticated encryption.
*
* This function does not fail.
*
* :param prp/prpctx: describe the block cipher to use.
* :param plain: message plaintext.
* :param nplain: length of message. May be zero. Must meet the constraints placed on it by `L`.
* :param L: length of the message length encoding. This must be in the interval `[2,8]` and gives a maximum message size of 2\ :sup:`8L` bytes.
* :param header: additionally authenticated data (AAD).
* :param nheader: length of AAD. May be zero.
* :param nonce: nonce. This must not repeat for a given key.
* :param nnonce: length of nonce. Must be exactly `15 - L` bytes for a 128-bit block cipher.
* :param cipher: ciphertext output. `nplain` bytes are written here.
* :param tag: authentication tag. `ntag` bytes are written here.
* :param ntag: authentication tag length. This must be 4, 6, 8, 10, 12, 14 or 16.
*/
void cf_ccm_encrypt(const cf_prp *prp, void *prpctx,
const uint8_t *plain, size_t nplain, size_t L,
const uint8_t *header, size_t nheader,
const uint8_t *nonce, size_t nnonce,
uint8_t *cipher,
uint8_t *tag, size_t ntag);
/* .. c:function:: $DECL
* CCM authenticated decryption.
*
* :return: 0 on success, non-zero on error. Plain is cleared on error.
*
* :param prp: describe the block cipher to use.
* :param prpctx: describe the block cipher to use.
* :param cipher: message ciphertext.
* :param ncipher: length of message.
* :param L: length of the message length encoding. See :c:func:`cf_ccm_encrypt`.
* :param header: additionally authenticated data (AAD).
* :param nheader: length of AAD.
* :param nonce: nonce.
* :param nnonce: length of nonce.
* :param tag: authentication tag. `ntag` bytes are read from here.
* :param ntag: authentication tag length. This must be 4, 6, 8, 10, 12, 14 or 16.
* :param plain: plaintext output. `ncipher` bytes are written here.
*/
int cf_ccm_decrypt(const cf_prp *prp, void *prpctx,
const uint8_t *cipher, size_t ncipher, size_t L,
const uint8_t *header, size_t nheader,
const uint8_t *nonce, size_t nnonce,
const uint8_t *tag, size_t ntag,
uint8_t *plain);
/**
* OCB
* ---
*
* OCB is an authenticated encryption mode by Phil Rogaway.
*
* This is version 3, as standardised in RFC7253. It's defined
* only for block ciphers with a 128-bit block size.
*
* This is a one-shot interface.
*/
/* .. c:function:: $DECL
* OCB authenticated encryption.
*
* This function does not fail.
*
* :param prp/prpctx: describe the block cipher to use.
* :param plain: message plaintext.
* :param nplain: length of message. May be zero.
* :param header: additionally authenticated data (AAD).
* :param nheader: length of AAD. May be zero.
* :param nonce: nonce. This must not repeat for a given key.
* :param nnonce: length of nonce. Must be 15 or fewer bytes.
* :param cipher: ciphertext output. `nplain` bytes are written here.
* :param tag: authentication tag. `ntag` bytes are written here.
* :param ntag: authentication tag length. Must be 16 or fewer bytes.
*/
void cf_ocb_encrypt(const cf_prp *prp, void *prpctx,
const uint8_t *plain, size_t nplain,
const uint8_t *header, size_t nheader,
const uint8_t *nonce, size_t nnonce,
uint8_t *cipher,
uint8_t *tag, size_t ntag);
/* .. c:function:: $DECL
* OCB authenticated decryption.
*
* :return: 0 on success, non-zero on error. `plain` is cleared on error.
*
* :param prp: describe the block cipher to use.
* :param prpctx: describe the block cipher to use.
* :param cipher: message ciphertext.
* :param ncipher: length of message.
* :param header: additionally authenticated data (AAD).
* :param nheader: length of AAD.
* :param nonce: nonce.
* :param nnonce: length of nonce.
* :param tag: authentication tag. `ntag` bytes are read from here.
* :param ntag: authentication tag length.
* :param plain: plaintext output. `ncipher` bytes are written here.
*/
int cf_ocb_decrypt(const cf_prp *prp, void *prpctx,
const uint8_t *cipher, size_t ncipher,
const uint8_t *header, size_t nheader,
const uint8_t *nonce, size_t nnonce,
const uint8_t *tag, size_t ntag,
uint8_t *plain);
#endif

64
external/cifra_AES128-EAX/prp.h vendored Normal file
View File

@@ -0,0 +1,64 @@
/*
* cifra - embedded cryptography library
* Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#ifndef PRP_H
#define PRP_H
#include <stddef.h>
#include <stdint.h>
/**
* General block cipher description
* ================================
* This allows us to implement block cipher modes which can work
* with different block ciphers.
*/
/* .. c:type:: cf_prp_block
* Block processing function type.
*
* The `in` and `out` blocks may alias.
*
* :rtype: void
* :param ctx: block cipher-specific context object.
* :param in: input block.
* :param out: output block.
*/
typedef void (*cf_prp_block)(void *ctx, const uint8_t *in, uint8_t *out);
/* .. c:type:: cf_prp
* Describes an PRP in a general way.
*
* .. c:member:: cf_prp.blocksz
* Block size in bytes. Must be no more than :c:macro:`CF_MAXBLOCK`.
*
* .. c:member:: cf_prp.encrypt
* Block encryption function.
*
* .. c:member:: cf_prp.decrypt
* Block decryption function.
*/
typedef struct
{
size_t blocksz;
cf_prp_block encrypt;
cf_prp_block decrypt;
} cf_prp;
/* .. c:macro:: CF_MAXBLOCK
* The maximum block cipher blocksize we support, in bytes.
*/
#define CF_MAXBLOCK 16
#endif

32
external/cifra_AES128-EAX/tassert.h vendored Normal file
View File

@@ -0,0 +1,32 @@
/*
* cifra - embedded cryptography library
* Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#ifndef TASSERT_H
#define TASSERT_H
/* Tiny assert
* -----------
*
* This is an assert(3) definition which doesn't include any
* strings, but just branches to abort(3) on failure.
*/
#ifndef FULL_FAT_ASSERT
# include <stdlib.h>
# define assert(expr) do { if (!(expr)) abort(); } while (0)
#else
# include <assert.h>
#endif
#endif

67
external/fatfs/doc/css_e.css vendored Normal file
View File

@@ -0,0 +1,67 @@
* {margin: 0; padding: 0; border-width: 0;}
body {margin: 8px; background-color: #e0ffff; font-color: black; font-family: serif; line-height: 133%; max-width: 1024px;}
a:link {color: blue;}
a:visited {color: darkmagenta;}
a:hover {background-color: #a0ffff;}
a:active {color: darkmagenta; overflow: hidden; outline:none; position: relative; top: 1px; left: 1px;}
abbr {border-width: 1px;}
p {margin: 0 0 0.3em 1em;}
i {margin: 0 0.3em 0 0;}
b {margin: 0 0.1em;}
em {font-style: normal; font-weight: bold; margin: 0 0.1em;}
strong {}
pre {border: 1px dashed gray; margin: 0.5em 1em; padding: 0.5em; line-height: 1.2em; font-size: 85%; font-family: "Consolas", "Courier New", monospace; background-color: white;}
pre span.c {color: green;}
pre span.k {color: blue;}
pre span.arg {font-style: italic;}
tt {margin: 0 0.2em; font-size: 0.85em; font-family: "Consolas", "Courier New", monospace; }
tt.arg {font-style: italic;}
ol {margin: 0.5em 2.5em;}
ul {margin: 0.5em 2em;}
ul ul {margin: 0 2em 0.5em 1em;}
dl {margin: 0.5em 1em;}
dd {margin: 0 2em;}
dt {font-size: 0.85em; font-family: "Consolas", "Courier New", monospace;}
dl.par dt {margin: 0.5em 0 0 0 ; font-style: italic; }
dl.ret dt {margin: 0.5em 0 0 0 ; font-size: 0.85em; font-family: "Consolas", "Courier New", monospace;}
hr {border-width: 1px; margin: 1em;}
div.abst {font-family: sans-serif;}
div.para {clear: both; font-family: serif;}
div.ret a {font-size: 0.85em; font-family: "Consolas", "Courier New", monospace; }
.equ {text-indent: 0; margin: 1em 2em 1em;}
.indent {margin-left: 2em;}
.rset {float: right; margin: 0.3em 0 0.5em 0.5em;}
.lset {float: left; margin: 0.3em 0.5em 0.5em 0.5em;}
ul.flat li {list-style-type: none; margin: 0;}
a.imglnk img {border: 1px solid;}
.iequ {white-space: nowrap; font-weight: bold;}
.clr {clear: both;}
.it {font-style: italic;}
.mfd {font-size: 0.7em; padding: 0 1px; border: 1px solid; white-space : nowrap}
.ral {text-align: right; }
.lal {text-align: left; }
.cal {text-align: center; }
h1 {line-height: 1em; font-size: 2em; font-family: sans-serif; padding: 0.3em 0 0.3em;}
h2 {font-size: 2em; font-family: sans-serif; background-color: #d8d8FF; padding: 0.5em 0.5em; margin: 0 0 0.5em;}
h3 {font-size: 1.5em; font-family: sans-serif; margin: 1.5em 0 0.5em;}
div.doc h3 {border-color: #b0d8d8; border-style: solid; border-width: 0px 0px 4px 12px; padding: 4px; margin-top: 3em;}
h4 {font-size: 1.2em; font-family: sans-serif; margin: 2em 0 0.2em;}
h5 {font-size: 1em; font-family: sans-serif; margin: 1em 0 0em;}
p.hdd {float: right; text-align: right; margin-top: 0.5em;}
hr.hds {clear: both; margin-bottom: 1em;}
kbd {letter-spacing: 0;}
small {font-size: 80%;}
.indent {margin-left: 2em;}
/* Tables */
table {margin: 0.5em 1em; border-collapse: collapse; border: 2px solid black; }
th {background-color: white; border-style: solid; border-width: 1px 1px 2px; border-color: black; padding: 0 3px; vertical-align: top; white-space: nowrap;}
td {background-color: white; border: 1px solid black; padding: 0 3px; vertical-align: top; line-height: 1.3em;}
table.lst td:first-child {font-size: 0.85em; font-family: "Consolas", "Courier New", monospace;}
table.lst2 td {font-size: 0.85em; font-family: "Consolas", "Courier New", monospace;}
table caption {font-family: sans-serif; font-weight: bold;}
tr.lst3 td { border-width: 2px 1px 1px; }
p.foot {clear: both; text-indent: 0; margin: 1em 0.5em 1em;}

70
external/fatfs/doc/css_j.css vendored Normal file
View File

@@ -0,0 +1,70 @@
@charset "Shift_JIS";
/* Common style sheet for Tech Notes */
* {margin: 0; padding: 0; border-width: 0;}
body {margin: 8px; background-color: #e0ffff; font-color: black; font-family:" P明朝", serif; line-height: 150%; letter-spacing: 1px; max-width: 1024px;}
a:link {color: blue;}
a:visited {color: darkmagenta;}
a:hover {background-color: #a0ffff;}
a:active {color: darkmagenta; overflow: hidden; outline:none; position: relative; top: 1px; left: 1px;}
abbr {border-width: 1px;}
p {text-indent: 0.8em; margin: 0 0 0.3em 0.5em;}
i {margin: 0 0.3em 0 0;}
b {margin: 0 0.1em;}
em {font-style: normal; font-weight: bold; margin: 0 0.1em;}
strong {}
pre {border: 1px dashed gray; margin: 0.5em 1em; padding: 0.5em; line-height: 1.2em; letter-spacing: 0; font-size: 0.85em; font-family: "Consolas", "Courier New", " ゴシック", monospace; background-color: white;}
pre span.c {color: green;}
pre span.k {color: blue;}
pre span.arg {font-style: italic;}
tt {margin: 0 0.2em; letter-spacing: 0; font-size: 0.85em; font-family: "Consolas", "Courier New", " ゴシック", monospace;}
tt.arg {font-style: italic;}
ol {margin: 0.5em 2.5em;}
ul {margin: 0.5em 2em;}
ul ul {margin: 0 2em 0.5em 1em;}
dl {margin: 0.5em 1em;}
dd {margin: 0em 2em;}
dt {font-size: 0.85em; font-family: "Consolas", "Courier New", " ゴシック", monospace;}
dl.par dt {margin: 0.5em 0 0 0 ; font-style: italic; letter-spacing: 0;}
dl.ret dt {margin: 0.5em 0 0 0 ; font-size: 0.85em; font-family: "Consolas", "Courier New", " ゴシック", monospace; letter-spacing: 0; }
hr {border-width: 1px; margin: 1em;}
div.abst {font-family: " Pゴシック",sans-serif;}
div.para {clear: both; font-family: " P明朝",serif;}
div.ret a {font-size: 0.85em; font-family: "Consolas", "Courier New", monospace; }
.equ {text-indent: 0; margin: 1em 2em 1em;}
.indent {margin-left: 2em;}
.rset {float: right; margin: 0.3em 0 0.5em 0.5em;}
.lset {float: left; margin: 0.3em 0.5em 0.5em 0.5em;}
ul.flat li {list-style-type: none; margin: 0;}
a.imglnk img {border: 1px solid;}
.iequ {white-space: nowrap; font-weight: bold;}
.clr {clear: both;}
.it {font-style: italic;}
.mfd {font-size: 0.7em; padding: 0 1px; border: 1px solid; white-space : nowrap}
.ral {text-align: right; }
.lal {text-align: left; }
.cal {text-align: center; }
h1 {line-height: 1em; font-size: 2em; font-family: sans-serif; padding: 0.3em 0 0.3em;}
h2 {font-size: 2em; font-family: " Pゴシック",sans-serif; background-color: #d8d8FF; padding: 0.5em 0.5em; margin: 0 0 0.5em;}
h3 {font-size: 1.5em; font-family: " Pゴシック",sans-serif; margin: 1.5em 0 0.5em;}
div.doc h3 {border-color: #b0d8d8; border-style: solid; border-width: 0px 0px 4px 12px; padding: 4px; margin-top: 3em;}
h4 {font-size: 1.2em; font-family: " Pゴシック",sans-serif; margin: 2em 0 0.2em;}
h5 {font-size: 1em; font-family: " Pゴシック",sans-serif; margin: 1em 0 0em;}
p.hdd {float: right; text-align: right; margin-top: 0.5em;}
hr.hds {clear: both; margin-bottom: 1em;}
kbd {letter-spacing: 0;}
small {font-size: 80%;}
.indent {margin-left: 2em;}
/* Tables */
table {margin: 0.5em 1em; border-collapse: collapse; border: 2px solid black; letter-spacing: 0;}
th {background-color: white; border-style: solid; border-width: 1px 1px 2px; border-color: black; padding: 0 3px; vertical-align: top;}
td {background-color: white; border: 1px solid black; padding: 0 3px; vertical-align: top; line-height: 1.3em;}
table.lst td:first-child {font-size: 0.85em; font-family: "Consolas", "Courier New", monospace; white-space: nowrap;}
table.lst2 td {font-size: 0.85em; font-family: "Consolas", "Courier New", monospace; white-space: nowrap;}
table caption {font-family: sans-serif; font-weight: bold;}
tr.lst3 td {border-width: 2px 1px 1px; }
p.foot {clear: both; text-indent: 0; margin: 1em 0.5em 1em;}

44
external/fatfs/doc/res/app1.c vendored Normal file
View File

@@ -0,0 +1,44 @@
/*------------------------------------------------------------/
/ Open or create a file in append mode
/ (This function was sperseded by FA_OPEN_APPEND at FatFs R0.12a)
/------------------------------------------------------------*/
FRESULT open_append (
FIL* fp, /* [OUT] File object to create */
const char* path /* [IN] File name to be opened */
)
{
FRESULT fr;
/* Opens an existing file. If not exist, creates a new file. */
fr = f_open(fp, path, FA_WRITE | FA_OPEN_ALWAYS);
if (fr == FR_OK) {
/* Seek to end of the file to append data */
fr = f_lseek(fp, f_size(fp));
if (fr != FR_OK)
f_close(fp);
}
return fr;
}
int main (void)
{
FRESULT fr;
FATFS fs;
FIL fil;
/* Open or create a log file and ready to append */
f_mount(&fs, "", 0);
fr = open_append(&fil, "logfile.txt");
if (fr != FR_OK) return 1;
/* Append a line */
f_printf(&fil, "%02u/%02u/%u, %2u:%02u\n", Mday, Mon, Year, Hour, Min);
/* Close the file */
f_close(&fil);
return 0;
}

70
external/fatfs/doc/res/app2.c vendored Normal file
View File

@@ -0,0 +1,70 @@
/*------------------------------------------------------------/
/ Remove all contents of a directory
/ This function works regardless of _FS_RPATH.
/------------------------------------------------------------*/
FRESULT empty_directory (
char* path /* Working buffer filled with start directory */
)
{
UINT i, j;
FRESULT fr;
DIR dir;
FILINFO fno;
#if _USE_LFN
fno.lfname = 0; /* Disable LFN output */
#endif
fr = f_opendir(&dir, path);
if (fr == FR_OK) {
for (i = 0; path[i]; i++) ;
path[i++] = '/';
for (;;) {
fr = f_readdir(&dir, &fno);
if (fr != FR_OK || !fno.fname[0]) break;
if (_FS_RPATH && fno.fname[0] == '.') continue;
j = 0;
do
path[i+j] = fno.fname[j];
while (fno.fname[j++]);
if (fno.fattrib & AM_DIR) {
fr = empty_directory(path);
if (fr != FR_OK) break;
}
fr = f_unlink(path);
if (fr != FR_OK) break;
}
path[--i] = '\0';
closedir(&dir);
}
return fr;
}
int main (void)
{
FRESULT fr;
FATFS fs;
char buff[64]; /* Working buffer */
f_mount(&fs, "", 0);
strcpy(buff, "/"); /* Directory to be emptied */
fr = empty_directory(buff);
if (fr) {
printf("Function failed. (%u)\n", fr);
return fr;
} else {
printf("All contents in the %s are successfully removed.\n", buff);
return 0;
}
}

109
external/fatfs/doc/res/app3.c vendored Normal file
View File

@@ -0,0 +1,109 @@
/*----------------------------------------------------------------------/
/ Allocate a contiguous area to the file
/-----------------------------------------------------------------------/
/ This function checks if the file is contiguous with desired size.
/ If not, a block of contiguous sectors is allocated to the file.
/ If the file has been opened without FA_WRITE flag, it only checks if
/ the file is contiguous and returns the resulut.
/-----------------------------------------------------------------------/
/ This function can work with FatFs R0.09 - R0.11a.
/ It is incompatible with R0.12+. Use f_expand function instead.
/----------------------------------------------------------------------*/
/* Declarations of FatFs internal functions accessible from applications.
/ This is intended to be used for disk checking/fixing or dirty hacks :-) */
DWORD clust2sect (FATFS* fs, DWORD clst);
DWORD get_fat (FATFS* fs, DWORD clst);
FRESULT put_fat (FATFS* fs, DWORD clst, DWORD val);
DWORD allocate_contiguous_clusters ( /* Returns the first sector in LBA (0:error or not contiguous) */
FIL* fp, /* Pointer to the open file object */
DWORD len /* Number of bytes to allocate */
)
{
DWORD csz, tcl, ncl, ccl, cl;
if (f_lseek(fp, 0) || !len) /* Check if the given parameters are valid */
return 0;
csz = 512UL * fp->fs->csize; /* Cluster size in unit of byte (assuming 512 bytes/sector) */
tcl = (len + csz - 1) / csz; /* Total number of clusters required */
len = tcl * csz; /* Round-up file size to the cluster boundary */
/* Check if the existing cluster chain is contiguous */
if (len == fp->fsize) {
ncl = 0; ccl = fp->sclust;
do {
cl = get_fat(fp->fs, ccl); /* Get the cluster status */
if (cl + 1 < 3) return 0; /* Hard error? */
if (cl != ccl + 1 && cl < fp->fs->n_fatent) break; /* Not contiguous? */
ccl = cl;
} while (++ncl < tcl);
if (ncl == tcl) /* Is the file contiguous? */
return clust2sect(fp->fs, fp->sclust); /* File is contiguous. Return the start sector */
}
/* File is not contiguous */
#if _FS_READONLY
return 0; /* Exit if in read-only cfg. */
#else
if (!(fp->flag & FA_WRITE)) return 0; /* Exit if the file object is for read-only */
if (f_truncate(fp)) return 0; /* Remove the non-contiguous chain */
/* Find a free contiguous area */
ccl = cl = 2; ncl = 0;
do {
if (cl >= fp->fs->n_fatent) return 0; /* No contiguous area is found. */
if (get_fat(fp->fs, cl)) { /* Encounterd a cluster in use */
do { /* Skip the block of used clusters */
cl++;
if (cl >= fp->fs->n_fatent) return 0; /* No contiguous area is found. */
} while (get_fat(fp->fs, cl));
ccl = cl; ncl = 0;
}
cl++; ncl++;
} while (ncl < tcl);
/* Create a contiguous cluster chain */
fp->fs->last_clust = ccl - 1;
if (f_lseek(fp, len)) return 0;
return clust2sect(fp->fs, fp->sclust); /* Return file start sector */
#endif
}
int main (void)
{
FRESULT fr;
DRESULT dr;
FATFS fs;
FIL fil;
DWORD org;
/* Open or create a file to write */
f_mount(&fs, "", 0);
fr = f_open(&fil, "fastrec.log", FA_READ | FA_WRITE | FA_OPEN_ALWAYS);
if (fr) return 1;
/* Check if the file is 256MB in size and occupies a contiguous area.
/ If not, a contiguous area will be re-allocated to the file. */
org = allocate_contiguous_clusters(&fil, 0x10000000);
if (!org) {
printf("Function failed due to any error or insufficient contiguous area.\n");
f_close(&fil);
return 1;
}
/* Now you can read/write the file without file system layer. */
...
dr = disk_write(fil.fs->drv, Buff, org, 1024); /* Write 512KiB from top of the file */
...
f_close(&fil);
return 0;
}

317
external/fatfs/doc/res/app4.c vendored Normal file
View File

@@ -0,0 +1,317 @@
/*----------------------------------------------------------------------/
/ Low level disk I/O module function checker
/-----------------------------------------------------------------------/
/ WARNING: The data on the target drive will be lost!
*/
#include <stdio.h>
#include <string.h>
#include "ff.h"
#include "diskio.h"
static
DWORD pn (
DWORD pns
)
{
static DWORD lfsr;
UINT n;
if (pns) {
lfsr = pns;
for (n = 0; n < 32; n++) pn(0);
}
if (lfsr & 1) {
lfsr >>= 1;
lfsr ^= 0x80200003;
} else {
lfsr >>= 1;
}
return lfsr;
}
int test_diskio (
BYTE pdrv, /* Physical drive number to be checked (all data on the drive will be lost) */
UINT ncyc, /* Number of test cycles */
DWORD* buff, /* Pointer to the working buffer */
UINT sz_buff /* Size of the working buffer in unit of byte */
)
{
UINT n, cc, ns;
DWORD sz_drv, lba, lba2, pns = 1;
WORD sz_sect, sz_eblk;
BYTE *pbuff = (BYTE*)buff;
DSTATUS ds;
DRESULT dr;
printf("test_diskio(%u, %u, 0x%08X, 0x%08X)\n", pdrv, ncyc, (UINT)buff, sz_buff);
if (sz_buff < _MAX_SS + 4) {
printf("Insufficient work area to test.\n");
return 1;
}
for (cc = 1; cc <= ncyc; cc++) {
printf("**** Test cycle %u of %u start ****\n", cc, ncyc);
/* Initialization */
printf(" disk_initalize(%u)", pdrv);
ds = disk_initialize(pdrv);
if (ds & STA_NOINIT) {
printf(" - failed.\n");
return 2;
} else {
printf(" - ok.\n");
}
/* Get drive size */
printf("**** Get drive size ****\n");
printf(" disk_ioctl(%u, GET_SECTOR_COUNT, 0x%08X)", pdrv, (UINT)&sz_drv);
sz_drv = 0;
dr = disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_drv);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
return 3;
}
if (sz_drv < 128) {
printf("Failed: Insufficient drive size to test.\n");
return 4;
}
printf(" Number of sectors on the drive %u is %lu.\n", pdrv, sz_drv);
#if _MAX_SS != _MIN_SS
/* Get sector size */
printf("**** Get sector size ****\n");
printf(" disk_ioctl(%u, GET_SECTOR_SIZE, 0x%X)", pdrv, (UINT)&sz_sect);
sz_sect = 0;
dr = disk_ioctl(pdrv, GET_SECTOR_SIZE, &sz_sect);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
return 5;
}
printf(" Size of sector is %u bytes.\n", sz_sect);
#else
sz_sect = _MAX_SS;
#endif
/* Get erase block size */
printf("**** Get block size ****\n");
printf(" disk_ioctl(%u, GET_BLOCK_SIZE, 0x%X)", pdrv, (UINT)&sz_eblk);
sz_eblk = 0;
dr = disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_eblk);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
}
if (dr == RES_OK || sz_eblk >= 2) {
printf(" Size of the erase block is %u sectors.\n", sz_eblk);
} else {
printf(" Size of the erase block is unknown.\n");
}
/* Single sector write test */
printf("**** Single sector write test 1 ****\n");
lba = 0;
for (n = 0, pn(pns); n < sz_sect; n++) pbuff[n] = (BYTE)pn(0);
printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba);
dr = disk_write(pdrv, pbuff, lba, 1);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
return 6;
}
printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv);
dr = disk_ioctl(pdrv, CTRL_SYNC, 0);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
return 7;
}
memset(pbuff, 0, sz_sect);
printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba);
dr = disk_read(pdrv, pbuff, lba, 1);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
return 8;
}
for (n = 0, pn(pns); n < sz_sect && pbuff[n] == (BYTE)pn(0); n++) ;
if (n == sz_sect) {
printf(" Data matched.\n");
} else {
printf("Failed: Read data differs from the data written.\n");
return 10;
}
pns++;
/* Multiple sector write test */
printf("**** Multiple sector write test ****\n");
lba = 1; ns = sz_buff / sz_sect;
if (ns > 4) ns = 4;
for (n = 0, pn(pns); n < (UINT)(sz_sect * ns); n++) pbuff[n] = (BYTE)pn(0);
printf(" disk_write(%u, 0x%X, %lu, %u)", pdrv, (UINT)pbuff, lba, ns);
dr = disk_write(pdrv, pbuff, lba, ns);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
return 11;
}
printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv);
dr = disk_ioctl(pdrv, CTRL_SYNC, 0);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
return 12;
}
memset(pbuff, 0, sz_sect * ns);
printf(" disk_read(%u, 0x%X, %lu, %u)", pdrv, (UINT)pbuff, lba, ns);
dr = disk_read(pdrv, pbuff, lba, ns);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
return 13;
}
for (n = 0, pn(pns); n < (UINT)(sz_sect * ns) && pbuff[n] == (BYTE)pn(0); n++) ;
if (n == (UINT)(sz_sect * ns)) {
printf(" Data matched.\n");
} else {
printf("Failed: Read data differs from the data written.\n");
return 14;
}
pns++;
/* Single sector write test (misaligned memory address) */
printf("**** Single sector write test 2 ****\n");
lba = 5;
for (n = 0, pn(pns); n < sz_sect; n++) pbuff[n+3] = (BYTE)pn(0);
printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+3), lba);
dr = disk_write(pdrv, pbuff+3, lba, 1);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
return 15;
}
printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv);
dr = disk_ioctl(pdrv, CTRL_SYNC, 0);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
return 16;
}
memset(pbuff+5, 0, sz_sect);
printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+5), lba);
dr = disk_read(pdrv, pbuff+5, lba, 1);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
return 17;
}
for (n = 0, pn(pns); n < sz_sect && pbuff[n+5] == (BYTE)pn(0); n++) ;
if (n == sz_sect) {
printf(" Data matched.\n");
} else {
printf("Failed: Read data differs from the data written.\n");
return 18;
}
pns++;
/* 4GB barrier test */
printf("**** 4GB barrier test ****\n");
if (sz_drv >= 128 + 0x80000000 / (sz_sect / 2)) {
lba = 6; lba2 = lba + 0x80000000 / (sz_sect / 2);
for (n = 0, pn(pns); n < (UINT)(sz_sect * 2); n++) pbuff[n] = (BYTE)pn(0);
printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba);
dr = disk_write(pdrv, pbuff, lba, 1);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
return 19;
}
printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+sz_sect), lba2);
dr = disk_write(pdrv, pbuff+sz_sect, lba2, 1);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
return 20;
}
printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv);
dr = disk_ioctl(pdrv, CTRL_SYNC, 0);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
return 21;
}
memset(pbuff, 0, sz_sect * 2);
printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba);
dr = disk_read(pdrv, pbuff, lba, 1);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
return 22;
}
printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+sz_sect), lba2);
dr = disk_read(pdrv, pbuff+sz_sect, lba2, 1);
if (dr == RES_OK) {
printf(" - ok.\n");
} else {
printf(" - failed.\n");
return 23;
}
for (n = 0, pn(pns); pbuff[n] == (BYTE)pn(0) && n < (UINT)(sz_sect * 2); n++) ;
if (n == (UINT)(sz_sect * 2)) {
printf(" Data matched.\n");
} else {
printf("Failed: Read data differs from the data written.\n");
return 24;
}
} else {
printf(" Test skipped.\n");
}
pns++;
printf("**** Test cycle %u of %u completed ****\n\n", cc, ncyc);
}
return 0;
}
int main (int argc, char* argv[])
{
int rc;
DWORD buff[512]; /* 2048 byte working buffer */
/* Check function/compatibility of the physical drive #0 */
rc = test_diskio(0, 3, buff, sizeof buff);
if (rc) {
printf("Sorry the function/compatibility test failed. (rc=%d)\nFatFs will not work on this disk driver.\n", rc);
} else {
printf("Congratulations! The disk driver works well.\n");
}
return rc;
}

BIN
external/fatfs/doc/res/f1.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
external/fatfs/doc/res/f2.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
external/fatfs/doc/res/f3.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
external/fatfs/doc/res/f4.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
external/fatfs/doc/res/f5.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
external/fatfs/doc/res/f6.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
external/fatfs/doc/res/f7.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
external/fatfs/doc/res/fd.mp4 vendored Normal file

Binary file not shown.

BIN
external/fatfs/doc/res/funcs.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
external/fatfs/doc/res/layers.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
external/fatfs/doc/res/layers1.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
external/fatfs/doc/res/layers2.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
external/fatfs/doc/res/layers3.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
external/fatfs/doc/res/mkfatimg.zip vendored Normal file

Binary file not shown.

BIN
external/fatfs/doc/res/mkfs.xls vendored Normal file

Binary file not shown.

BIN
external/fatfs/doc/res/modules.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
external/fatfs/doc/res/rwtest1.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
external/fatfs/doc/res/rwtest2.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
external/fatfs/doc/res/rwtest3.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

189
external/fatfs/doc/updates.txt vendored Normal file
View File

@@ -0,0 +1,189 @@
R0.12b (September 4, 2016)
Improved f_rename() to be able to rename objects with the same name but case.
Fixed an error in the case conversion teble of code page 866. (ff.c)
Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12)
Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12)
Fixed f_mkfs() creating exFAT volume with too small cluster size can collapse unallocated memory. (appeared at R0.12)
Fixed wrong object name can be returned when read directory at Unicode cfg. (appeared at R0.12)
Fixed large file allocation/removing on the exFAT volume collapses allocation bitmap. (appeared at R0.12)
Fixed some internal errors in f_expand() and f_lseek(). (appeared at R0.12)
R0.12a (July 10, 2016)
Added support for creating exFAT volume with some changes of f_mkfs().
Added a file open method FA_OPEN_APPEND. An f_lseek() following f_open() is no longer needed.
f_forward() is available regardless of _FS_TINY.
Fixed f_mkfs() creates wrong volume. (appeared at R0.12)
Fixed wrong memory read in create_name(). (appeared at R0.12)
Fixed compilation fails at some configurations, _USE_FASTSEEK and _USE_FORWARD.
R0.12 (April 12, 2016)
Added support for exFAT file system. (_FS_EXFAT)
Added f_expand(). (_USE_EXPAND)
Changed some members in FINFO structure and behavior of f_readdir().
Added an option _USE_CHMOD and removed an option _WORD_ACCESS.
Fixed errors in the case conversion teble of Unicode (cc*.c).
R0.11a (September 5, 2015)
Fixed wrong media change can lead a deadlock at thread-safe configuration.
Added code page 771, 860, 861, 863, 864, 865 and 869. (_CODE_PAGE)
Removed some code pages actually not exist on the standard systems. (_CODE_PAGE)
Fixed errors in the case conversion teble of code page 437 and 850 (ff.c).
Fixed errors in the case conversion teble of Unicode (cc*.c).
R0.11 (February 9, 2015)
Added f_findfirst() and f_findnext(). (_USE_FIND)
Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c)
Fixed _FS_NORTC option does not work properly. (appeared at R0.10c)
R0.10c (November 9, 2014)
Added a configuration option for the platforms without RTC. (_FS_NORTC)
Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b)
Fixed a potential problem of FAT access that can appear on disk error.
Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08)
R0.10b (May 19, 2014)
Fixed a hard error in the disk I/O layer can collapse the directory entry.
Fixed LFN entry is not deleted on delete/rename an object with its lossy converted SFN. (appeared at R0.07)
R0.10a (January 15, 2014)
Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID)
Added an option for minimum sector size. (_MIN_SS)
2nd argument of f_rename() can have a drive number and it will be ignored.
Fixed f_mount() with forced mount fails when drive number is larger than 0. (appeared at R0.10)
Fixed f_close() invalidates the file object without volume lock.
Fixed volume lock is left acquired after return from f_closedir(). (appeared at R0.10)
Fixed creation of a directory entry with LFN fails on too many SFN collisions. (appeared at R0.07)
R0.10 (October 2, 2013)
Added an option for character encoding on the file. (_STRF_ENCODE)
Added f_closedir().
Added forced full FAT scan option for f_getfree(). (_FS_NOFSINFO)
Added forced mount option with changes of f_mount().
Improved behavior of volume auto detection.
Improved write throughput of f_puts() and f_printf().
Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write().
Fixed f_write() can be truncated when the file size is close to 4GB.
Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect result code on error.
R0.09b (January 24, 2013)
Added f_getlabel() and f_setlabel(). (_USE_LABEL = 1)
R0.09a (August 27, 2012)
Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
Changed file functions reject null object pointer to avoid crash.
Changed option name _FS_SHARE to _FS_LOCK.
R0.09 (September 6, 2011)
f_mkfs() supports multiple partition on a physical drive.
Added f_fdisk(). (_MULTI_PARTITION = 2)
R0.08b (January 15, 2011)
Fast seek function is also applied to f_read() and f_write().
f_lseek() reports required table size on creating CLMP.
Extended format syntax of f_printf().
Ignores duplicated directory separators in given path names.
R0.08a (August 16, 2010)
Added f_getcwd(). (_FS_RPATH = 2)
Added sector erase function. (_USE_ERASE)
Moved file lock semaphore table from fs object to the bss.
Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'.
Fixed f_mkfs() creates wrong FAT32 volume.
R0.08 (May 15, 2010)
Added a memory configuration option. (_USE_LFN)
Added support of file lock. (_FS_SHARE)
Added fast seek function. (_USE_FASTSEEK)
Changed some types on the API, XCHAR->TCHAR.
Changed fname member in the FILINFO structure on Unicode cfg.
String functions support UTF-8 encoding files on Unicode cfg.
R0.07e (November 3, 2009)
Separated out configuration options from ff.h to ffconf.h.
Added a configuration option, _LFN_UNICODE.
Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH.
Fixed name matching error on the 13 char boundary.
Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
R0.07c (Junuary 21, 2009)
Fixed f_unlink() may return FR_OK on error.
Fixed wrong cache control in f_lseek().
Added support of relative path.
Added f_chdir().
Added f_chdrive().
Added proper case conversion to extended characters.
R0.07a (April 14, 2009)
Separated out OS dependent code on re-entrant configuration.
Added multiple sector size support.
R0.07 (April 1, 2009)
Merged Tiny-FatFs into FatFs as a buffer configuration option.
Added long file name support.
Added multiple code page support.
Added re-entrancy for multitask operation.
Added auto cluster size selection to f_mkfs().
Added rewind option to f_readdir().
Changed result code of critical errors.
Renamed string functions to avoid name collision.
R0.06 (April 1, 2008)
Added f_forward. (Tiny-FatFs)
Added string functions: fgets, fputc, fputs and fprintf.
Improved performance of f_lseek on moving to the same or following cluster.
R0.05a (February 3, 2008)
Added f_truncate.
Added f_utime.
Fixed off by one error at FAT sub-type determination.
Fixed btr in f_read can be mistruncated.
Fixed cached sector is left not flushed when create and close without write.
R0.05 (August 26, 2007)
Changed arguments of f_read, f_write.
Changed arguments of f_mkfs. (FatFs)
Fixed f_mkfs on FAT32 creates incorrect FSInfo. (FatFs)
Fixed f_mkdir on FAT32 creates incorrect directory. (FatFs)
R0.04b (May 5, 2007)
Added _USE_NTFLAG option.
Added FSInfo support.
Fixed some problems corresponds to FAT32. (Tiny-FatFs)
Fixed DBCS name can result FR_INVALID_NAME.
Fixed short seek (<= csize) collapses the file object.
R0.04a (April 1, 2007)
Supported multiple partitions on a plysical drive. (FatFs)
Added minimization level 3.
Added a capability of extending file size to f_lseek.
Fixed an endian sensitive code in f_mkfs. (FatFs)
Fixed a problem corresponds to FAT32 support. (Tiny-FatFs)
R0.04 (February 4, 2007)
Supported multiple drive system. (FatFs)
Changed some APIs for multiple drive system.
Added f_mkfs. (FatFs)
Added _USE_FAT32 option. (Tiny-FatFs)
R0.03a (December 11, 2006)
Improved cluster scan algolithm to write files fast.
Fixed f_mkdir creates incorrect directory on FAT32.
R0.03 (September 22, 2006)
Added f_rename.
Changed option _FS_MINIMUM to _FS_MINIMIZE.
R0.02a (June 10, 2006)
Added a configuration option _FS_MINIMUM.
R0.02 (Jun 01, 2006)
Added FAT12.
Removed unbuffered mode.
Fixed a problem on small (<32M) patition.
R0.01 (April 29, 2006)
First release
R0.00 (February 26, 2006)
Prototype (not released)

333
external/fatfs/port/diskio_blkdev.c vendored Normal file
View File

@@ -0,0 +1,333 @@
/**
* Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, 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.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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.
*
*/
#include "diskio_blkdev.h"
/**
* @brief Registered drives array.
* */
static diskio_blkdev_t * m_drives;
/**
* @brief Number of registered drives.
* */
static BYTE m_drives_count;
/**
* @brief Block device handler.
*
* @ref nrf_block_dev_ev_handler
* */
static void block_dev_handler(struct nrf_block_dev_s const * p_blk_dev,
nrf_block_dev_event_t const * p_event)
{
uint8_t drv = (uint8_t)(uint32_t) p_event->p_context;
ASSERT(drv < m_drives_count);
switch (p_event->ev_type)
{
case NRF_BLOCK_DEV_EVT_INIT:
case NRF_BLOCK_DEV_EVT_UNINIT:
case NRF_BLOCK_DEV_EVT_BLK_WRITE_DONE:
case NRF_BLOCK_DEV_EVT_BLK_READ_DONE:
m_drives[drv].last_result = p_event->result;
m_drives[drv].busy = false;
break;
default:
break;
}
}
/**
* @brief Default IO operation wait function.
* */
static void default_wait_func(void)
{
__WFE();
}
DSTATUS disk_initialize(BYTE drv)
{
ASSERT(m_drives);
if (drv >= m_drives_count)
{
return (STA_NODISK | STA_NOINIT);
}
if (!m_drives[drv].config.p_block_device)
{
return (STA_NODISK | STA_NOINIT);
}
if (!(m_drives[drv].state & STA_NOINIT))
{
// Disk already initialized.
return m_drives[drv].state;
}
if (m_drives[drv].config.wait_func == NULL)
{
m_drives[drv].config.wait_func = default_wait_func;
}
m_drives[drv].busy = true;
ret_code_t err_code = nrf_blk_dev_init(m_drives[drv].config.p_block_device,
block_dev_handler,
(void *) (uint32_t) drv);
if (err_code == NRF_SUCCESS)
{
while (m_drives[drv].busy)
{
m_drives[drv].config.wait_func();
}
if (m_drives[drv].last_result == NRF_BLOCK_DEV_RESULT_SUCCESS)
{
m_drives[drv].state &= ~STA_NOINIT;
}
}
return m_drives[drv].state;
}
DSTATUS disk_uninitialize(BYTE drv)
{
ASSERT(m_drives);
if (drv >= m_drives_count)
{
return (STA_NODISK | STA_NOINIT);
}
if (!m_drives[drv].config.p_block_device)
{
return (STA_NODISK | STA_NOINIT);
}
if (m_drives[drv].state & STA_NOINIT)
{
// Disk already uninitialized.
return m_drives[drv].state;
}
(void)nrf_blk_dev_ioctl(m_drives[drv].config.p_block_device,
NRF_BLOCK_DEV_IOCTL_REQ_CACHE_FLUSH,
NULL);
ret_code_t ret;
do
{
/*Perform synchronous uninit.*/
ret = nrf_blk_dev_uninit(m_drives[drv].config.p_block_device);
} while (ret == NRF_ERROR_BUSY);
if (ret == NRF_SUCCESS)
{
while (m_drives[drv].busy)
{
m_drives[drv].config.wait_func();
}
}
if (m_drives[drv].last_result == NRF_BLOCK_DEV_RESULT_SUCCESS)
{
m_drives[drv].state |= STA_NOINIT;
}
return m_drives[drv].state;
}
DSTATUS disk_status(BYTE drv)
{
ASSERT(m_drives);
if (drv >= m_drives_count)
{
return STA_NOINIT;
}
return m_drives[drv].state;
}
DRESULT disk_read(BYTE drv, BYTE *buff, DWORD sector, UINT count)
{
ASSERT(m_drives);
if ((drv >= m_drives_count) || (!count))
{
return RES_PARERR; // Invalid parameter(s).
}
if ((m_drives[drv].config.p_block_device == NULL)
|| (m_drives[drv].state & STA_NOINIT))
{
return RES_NOTRDY; // Disk not initialized.
}
const nrf_block_req_t req = {
.p_buff = buff,
.blk_id = sector,
.blk_count = count
};
m_drives[drv].busy = true;
ret_code_t err_code = nrf_blk_dev_read_req(m_drives[drv].config.p_block_device, &req);
if (err_code == NRF_SUCCESS)
{
while (m_drives[drv].busy)
{
m_drives[drv].config.wait_func();
}
if (m_drives[drv].last_result == NRF_BLOCK_DEV_RESULT_SUCCESS)
{
return RES_OK;
}
}
return RES_ERROR;
}
DRESULT disk_write(BYTE drv, const BYTE *buff, DWORD sector, UINT count)
{
ASSERT(m_drives);
if ((drv >= m_drives_count) || (!count))
{
return RES_PARERR; // Invalid parameter(s).
}
if ((m_drives[drv].config.p_block_device == NULL)
|| (m_drives[drv].state & STA_NOINIT))
{
return RES_NOTRDY; // Disk not initialized.
}
if (m_drives[drv].state & STA_PROTECT)
{
return RES_WRPRT; // Disk protection is enabled.
}
const nrf_block_req_t req = {
.p_buff = (void *)buff,
.blk_id = sector,
.blk_count = count
};
m_drives[drv].busy = true;
ret_code_t err_code = nrf_blk_dev_write_req(m_drives[drv].config.p_block_device, &req);
if (err_code == NRF_SUCCESS)
{
while (m_drives[drv].busy)
{
m_drives[drv].config.wait_func();
}
if (m_drives[drv].last_result == NRF_BLOCK_DEV_RESULT_SUCCESS)
{
return RES_OK;
}
}
return RES_ERROR;
}
DRESULT disk_ioctl(BYTE drv, BYTE cmd, void *buff)
{
ASSERT(m_drives);
if (drv >= m_drives_count)
{
return RES_PARERR;
}
switch (cmd)
{
case CTRL_SYNC:
{
bool flush_in_progress = true;
do {
/*Perform synchronous FLUSH operation on block device*/
ret_code_t ret = nrf_blk_dev_ioctl(m_drives[drv].config.p_block_device,
NRF_BLOCK_DEV_IOCTL_REQ_CACHE_FLUSH,
&flush_in_progress);
if (ret != NRF_SUCCESS && ret != NRF_ERROR_BUSY)
{
break;
}
} while (flush_in_progress);
return RES_OK;
}
case GET_SECTOR_COUNT:
{
if (m_drives[drv].config.p_block_device == NULL)
{
return RES_NOTRDY;
}
DWORD * val = buff;
*val = nrf_blk_dev_geometry(m_drives[drv].config.p_block_device)->blk_count;
return RES_OK;
}
case GET_SECTOR_SIZE:
{
if (m_drives[drv].config.p_block_device == NULL)
{
return RES_NOTRDY;
}
WORD * val = buff;
*val = nrf_blk_dev_geometry(m_drives[drv].config.p_block_device)->blk_size;
return RES_OK;
}
default:
break;
}
return RES_ERROR;
}
void diskio_blockdev_register(diskio_blkdev_t * diskio_blkdevs, size_t count)
{
ASSERT(diskio_blkdevs);
m_drives = diskio_blkdevs;
m_drives_count = count;
}

186
external/fatfs/port/diskio_blkdev.h vendored Normal file
View File

@@ -0,0 +1,186 @@
/**
* Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, 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.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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.
*
*/
#ifndef DISKIO_SDCARD_H_
#define DISKIO_SDCARD_H_
#include "diskio.h"
#include "nrf_block_dev.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@file
*
* @defgroup diskio_blockdev FatFS disk I/O interface based on block device.
* @{
*
* @brief This module implements the FatFs disk API. Internals of this module are based on block device.
*
*/
/**
* @brief FatFs disk I/O block device configuration structure.
* */
typedef struct
{
const nrf_block_dev_t * p_block_device; ///< Block device associated with a FatFs drive.
/**
* @brief FatFs disk interface synchronous wait function.
*
* The function to be called repeatedly until the disk I/O operation is completed.
*/
void (*wait_func)(void);
} diskio_blkdev_config_t;
/**
* @brief Disk I/O block device.
* */
typedef struct
{
diskio_blkdev_config_t config; ///< Disk I/O configuration.
nrf_block_dev_result_t last_result; ///< Result of the last I/O operation.
volatile DSTATUS state; ///< Current disk state.
volatile bool busy; ///< Disk busy flag.
} diskio_blkdev_t;
/**
* @brief Initializer of @ref diskio_blkdev_t.
*
* @param blk_device Block device handle.
* @param wait_funcion User wait function (NULL is allowed).
* */
#define DISKIO_BLOCKDEV_CONFIG(blk_device, wait_funcion) { \
.config = { \
.p_block_device = (blk_device), \
.wait_func = (wait_funcion), \
}, \
.last_result = NRF_BLOCK_DEV_RESULT_SUCCESS, \
.state = STA_NOINIT, \
.busy = false \
}
/**
* @brief FatFs disk initialization.
*
* Initializes a block device assigned to a drive number.
*
* @param[in] drv Drive number.
*
* @return Disk status code.
* */
DSTATUS disk_initialize(BYTE drv);
/**
* @brief FatFs disk uninitialization.
*
* Uninitializes a block device assigned to a drive number.
*
* @param[in] drv Drive index.
*
* @return Disk status code.
* */
DSTATUS disk_uninitialize(BYTE drv);
/**
* @brief FatFs disk status get.
*
* @param[in] drv Drive index.
*
* @return Disk status code.
* */
DSTATUS disk_status(BYTE drv);
/**
* @brief FatFs disk sector read.
*
* @param[in] drv Drive number.
* @param[out] buff Output buffer.
* @param[in] sector Sector start number.
* @param[in] count Sector count.
*
* @return FatFs standard error code.
* */
DRESULT disk_read(BYTE drv, BYTE* buff, DWORD sector, UINT count);
/**
* @brief FatFs disk sector write.
*
* @param[in] drv Drive number.
* @param[in] buff Input buffer.
* @param[in] sector Sector start number.
* @param[in] count Sector count.
*
* @return FatFs standard error code.
* */
DRESULT disk_write(BYTE drv, const BYTE* buff, DWORD sector, UINT count);
/**
* @brief FatFs disk I/O control operation.
*
* @param[in] drv Drive number.
* @param[in] cmd I/O control command.
* @param buff I/O control parameter (optional).
*
* @return FatFs standard error code.
* */
DRESULT disk_ioctl(BYTE drv, BYTE cmd, void* buff);
/**
* @brief Registers a block device array.
*
* @warning This function must be called before any other function from this header.
*
* @param[in] diskio_blkdevs Disk I/O block device array.
* @param[in] count Number of elements in a block device array.
* */
void diskio_blockdev_register(diskio_blkdev_t * diskio_blkdevs, size_t count);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /*DISKIO_SDCARD_H_*/

279
external/fatfs/src/00history.txt vendored Normal file
View File

@@ -0,0 +1,279 @@
----------------------------------------------------------------------------
Revision history of FatFs module
----------------------------------------------------------------------------
R0.00 (February 26, 2006)
Prototype.
R0.01 (April 29, 2006)
The first release.
R0.02 (June 01, 2006)
Added FAT12 support.
Removed unbuffered mode.
Fixed a problem on small (<32M) partition.
R0.02a (June 10, 2006)
Added a configuration option (_FS_MINIMUM).
R0.03 (September 22, 2006)
Added f_rename().
Changed option _FS_MINIMUM to _FS_MINIMIZE.
R0.03a (December 11, 2006)
Improved cluster scan algorithm to write files fast.
Fixed f_mkdir() creates incorrect directory on FAT32.
R0.04 (February 04, 2007)
Added f_mkfs().
Supported multiple drive system.
Changed some interfaces for multiple drive system.
Changed f_mountdrv() to f_mount().
R0.04a (April 01, 2007)
Supported multiple partitions on a physical drive.
Added a capability of extending file size to f_lseek().
Added minimization level 3.
Fixed an endian sensitive code in f_mkfs().
R0.04b (May 05, 2007)
Added a configuration option _USE_NTFLAG.
Added FSINFO support.
Fixed DBCS name can result FR_INVALID_NAME.
Fixed short seek (<= csize) collapses the file object.
R0.05 (August 25, 2007)
Changed arguments of f_read(), f_write() and f_mkfs().
Fixed f_mkfs() on FAT32 creates incorrect FSINFO.
Fixed f_mkdir() on FAT32 creates incorrect directory.
R0.05a (February 03, 2008)
Added f_truncate() and f_utime().
Fixed off by one error at FAT sub-type determination.
Fixed btr in f_read() can be mistruncated.
Fixed cached sector is not flushed when create and close without write.
R0.06 (April 01, 2008)
Added fputc(), fputs(), fprintf() and fgets().
Improved performance of f_lseek() on moving to the same or following cluster.
R0.07 (April 01, 2009)
Merged Tiny-FatFs as a configuration option. (_FS_TINY)
Added long file name feature. (_USE_LFN)
Added multiple code page feature. (_CODE_PAGE)
Added re-entrancy for multitask operation. (_FS_REENTRANT)
Added auto cluster size selection to f_mkfs().
Added rewind option to f_readdir().
Changed result code of critical errors.
Renamed string functions to avoid name collision.
R0.07a (April 14, 2009)
Septemberarated out OS dependent code on reentrant cfg.
Added multiple sector size feature.
R0.07c (June 21, 2009)
Fixed f_unlink() can return FR_OK on error.
Fixed wrong cache control in f_lseek().
Added relative path feature.
Added f_chdir() and f_chdrive().
Added proper case conversion to extended character.
R0.07e (November 03, 2009)
Septemberarated out configuration options from ff.h to ffconf.h.
Fixed f_unlink() fails to remove a sub-directory on _FS_RPATH.
Fixed name matching error on the 13 character boundary.
Added a configuration option, _LFN_UNICODE.
Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
R0.08 (May 15, 2010)
Added a memory configuration option. (_USE_LFN = 3)
Added file lock feature. (_FS_SHARE)
Added fast seek feature. (_USE_FASTSEEK)
Changed some types on the API, XCHAR->TCHAR.
Changed .fname in the FILINFO structure on Unicode cfg.
String functions support UTF-8 encoding files on Unicode cfg.
R0.08a (August 16, 2010)
Added f_getcwd(). (_FS_RPATH = 2)
Added sector erase feature. (_USE_ERASE)
Moved file lock semaphore table from fs object to the bss.
Fixed f_mkfs() creates wrong FAT32 volume.
R0.08b (January 15, 2011)
Fast seek feature is also applied to f_read() and f_write().
f_lseek() reports required table size on creating CLMP.
Extended format syntax of f_printf().
Ignores duplicated directory separators in given path name.
R0.09 (September 06, 2011)
f_mkfs() supports multiple partition to complete the multiple partition feature.
Added f_fdisk().
R0.09a (August 27, 2012)
Changed f_open() and f_opendir() reject null object pointer to avoid crash.
Changed option name _FS_SHARE to _FS_LOCK.
Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
R0.09b (January 24, 2013)
Added f_setlabel() and f_getlabel().
R0.10 (October 02, 2013)
Added selection of character encoding on the file. (_STRF_ENCODE)
Added f_closedir().
Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO)
Added forced mount feature with changes of f_mount().
Improved behavior of volume auto detection.
Improved write throughput of f_puts() and f_printf().
Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write().
Fixed f_write() can be truncated when the file size is close to 4GB.
Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect value on error.
R0.10a (January 15, 2014)
Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID)
Added a configuration option of minimum sector size. (_MIN_SS)
2nd argument of f_rename() can have a drive number and it will be ignored.
Fixed f_mount() with forced mount fails when drive number is >= 1. (appeared at R0.10)
Fixed f_close() invalidates the file object without volume lock.
Fixed f_closedir() returns but the volume lock is left acquired. (appeared at R0.10)
Fixed creation of an entry with LFN fails on too many SFN collisions. (appeared at R0.07)
R0.10b (May 19, 2014)
Fixed a hard error in the disk I/O layer can collapse the directory entry.
Fixed LFN entry is not deleted on delete/rename an object with lossy converted SFN. (appeared at R0.07)
R0.10c (November 09, 2014)
Added a configuration option for the platforms without RTC. (_FS_NORTC)
Changed option name _USE_ERASE to _USE_TRIM.
Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b)
Fixed a potential problem of FAT access that can appear on disk error.
Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08)
R0.11 (February 09, 2015)
Added f_findfirst(), f_findnext() and f_findclose(). (_USE_FIND)
Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c)
Fixed _FS_NORTC option does not work properly. (appeared at R0.10c)
R0.11a (September 05, 2015)
Fixed wrong media change can lead a deadlock at thread-safe configuration.
Added code page 771, 860, 861, 863, 864, 865 and 869. (_CODE_PAGE)
Removed some code pages actually not exist on the standard systems. (_CODE_PAGE)
Fixed errors in the case conversion teble of code page 437 and 850 (ff.c).
Fixed errors in the case conversion teble of Unicode (cc*.c).
R0.12 (April 12, 2016)
Added support for exFAT file system. (_FS_EXFAT)
Added f_expand(). (_USE_EXPAND)
Changed some members in FINFO structure and behavior of f_readdir().
Added an option _USE_CHMOD.
Removed an option _WORD_ACCESS.
Fixed errors in the case conversion table of Unicode (cc*.c).
R0.12a (July 10, 2016)
Added support for creating exFAT volume with some changes of f_mkfs().
Added a file open method FA_OPEN_APPEND. An f_lseek() following f_open() is no longer needed.
f_forward() is available regardless of _FS_TINY.
Fixed f_mkfs() creates wrong volume. (appeared at R0.12)
Fixed wrong memory read in create_name(). (appeared at R0.12)
Fixed compilation fails at some configurations, _USE_FASTSEEK and _USE_FORWARD.
R0.12b (September 04, 2016)
Improved f_rename() to be able to rename objects with the same name but case.
Fixed an error in the case conversion teble of code page 866. (ff.c)
Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12)
Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12)
Fixed f_mkfs() creating exFAT volume with too small cluster size can collapse unallocated memory. (appeared at R0.12)
Fixed wrong object name can be returned when read directory at Unicode cfg. (appeared at R0.12)
Fixed large file allocation/removing on the exFAT volume collapses allocation bitmap. (appeared at R0.12)
Fixed some internal errors in f_expand() and f_lseek(). (appeared at R0.12)

21
external/fatfs/src/00readme.txt vendored Normal file
View File

@@ -0,0 +1,21 @@
FatFs Module Source Files R0.12a
FILES
00readme.txt This file.
history.txt Revision history.
ffconf.h Configuration file for FatFs module.
ff.h Common include file for FatFs and application module.
ff.c FatFs module.
diskio.h Common include file for FatFs and disk I/O module.
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
integer.h Integer type definitions for FatFs.
option Optional external functions.
Low level disk I/O module is not included in this archive because the FatFs
module is only a generic file system layer and not depend on any specific
storage device. You have to provide a low level disk I/O module that written
to control the target storage device.

225
external/fatfs/src/diskio.c vendored Normal file
View File

@@ -0,0 +1,225 @@
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2016 */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be */
/* attached to the FatFs via a glue function rather than modifying it. */
/* This is an example of glue functions to attach various exsisting */
/* storage control modules to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/
#include "diskio.h" /* FatFs lower layer API */
/* Definitions of physical drive number for each drive */
#define DEV_RAM 0 /* Example: Map Ramdisk to physical drive 0 */
#define DEV_MMC 1 /* Example: Map MMC/SD card to physical drive 1 */
#define DEV_USB 2 /* Example: Map USB MSD to physical drive 2 */
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case DEV_RAM :
result = RAM_disk_status();
// translate the reslut code here
return stat;
case DEV_MMC :
result = MMC_disk_status();
// translate the reslut code here
return stat;
case DEV_USB :
result = USB_disk_status();
// translate the reslut code here
return stat;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case DEV_RAM :
result = RAM_disk_initialize();
// translate the reslut code here
return stat;
case DEV_MMC :
result = MMC_disk_initialize();
// translate the reslut code here
return stat;
case DEV_USB :
result = USB_disk_initialize();
// translate the reslut code here
return stat;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_RAM :
// translate the arguments here
result = RAM_disk_read(buff, sector, count);
// translate the reslut code here
return res;
case DEV_MMC :
// translate the arguments here
result = MMC_disk_read(buff, sector, count);
// translate the reslut code here
return res;
case DEV_USB :
// translate the arguments here
result = USB_disk_read(buff, sector, count);
// translate the reslut code here
return res;
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_RAM :
// translate the arguments here
result = RAM_disk_write(buff, sector, count);
// translate the reslut code here
return res;
case DEV_MMC :
// translate the arguments here
result = MMC_disk_write(buff, sector, count);
// translate the reslut code here
return res;
case DEV_USB :
// translate the arguments here
result = USB_disk_write(buff, sector, count);
// translate the reslut code here
return res;
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_RAM :
// Process of the command for the RAM drive
return res;
case DEV_MMC :
// Process of the command for the MMC/SD card
return res;
case DEV_USB :
// Process of the command the USB drive
return res;
}
return RES_PARERR;
}

80
external/fatfs/src/diskio.h vendored Normal file
View File

@@ -0,0 +1,80 @@
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2014 /
/-----------------------------------------------------------------------*/
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h"
/* Status of Disk Functions */
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
/*---------------------------------------*/
/* Prototypes for disk control functions */
DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus
}
#endif
#endif

6041
external/fatfs/src/ff.c vendored Normal file

File diff suppressed because it is too large Load Diff

366
external/fatfs/src/ff.h vendored Normal file
View File

@@ -0,0 +1,366 @@
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT file system module R0.12b /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2016, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/----------------------------------------------------------------------------*/
#ifndef _FATFS
#define _FATFS 68020 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h" /* Basic integer types */
#include "ffconf.h" /* FatFs configuration options */
#if _FATFS != _FFCONF
#error Wrong configuration file (ffconf.h).
#endif
/* Definitions of volume management */
#if _MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
#else /* Single partition configuration */
#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */
#define LD2PT(vol) 0 /* Find first valid partition or in SFD */
#endif
/* Type of path name strings on FatFs API */
#if _LFN_UNICODE /* Unicode (UTF-16) string */
#if _USE_LFN == 0
#error _LFN_UNICODE must be 0 at non-LFN cfg.
#endif
#ifndef _INC_TCHAR
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#endif
#else /* ANSI/OEM string */
#ifndef _INC_TCHAR
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* Type of file size variables */
#if _FS_EXFAT
#if _USE_LFN == 0
#error LFN must be enabled when enable exFAT
#endif
typedef QWORD FSIZE_t;
#else
typedef DWORD FSIZE_t;
#endif
/* File system object structure (FATFS) */
typedef struct {
BYTE fs_type; /* File system type (0:N/A) */
BYTE drv; /* Physical drive number */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
WORD id; /* File system mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
WORD csize; /* Cluster size [sectors] */
#if _MAX_SS != _MIN_SS
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
#endif
#if _USE_LFN != 0
WCHAR* lfnbuf; /* LFN working buffer */
#endif
#if _FS_EXFAT
BYTE* dirbuf; /* Directory entry block scratchpad buffer */
#endif
#if _FS_REENTRANT
_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !_FS_READONLY
DWORD last_clst; /* Last allocated cluster */
DWORD free_clst; /* Number of free clusters */
#endif
#if _FS_RPATH != 0
DWORD cdir; /* Current directory start cluster (0:root) */
#if _FS_EXFAT
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */
DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */
#endif
#endif
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
DWORD fsize; /* Size of an FAT [sectors] */
DWORD volbase; /* Volume base sector */
DWORD fatbase; /* FAT base sector */
DWORD dirbase; /* Root directory base sector/cluster */
DWORD database; /* Data base sector */
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFS;
/* Object ID and allocation information (_FDID) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
BYTE attr; /* Object attribute */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous (no data on FAT), =3:got flagmented, b2:sub-directory stretched) */
DWORD sclust; /* Object start cluster (0:no cluster or root directory) */
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
#if _FS_EXFAT
DWORD n_cont; /* Size of coutiguous part, clusters - 1 (valid when stat == 3) */
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
DWORD c_ofs; /* Offset in the containing directory (valid when sclust != 0) */
#endif
#if _FS_LOCK != 0
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif
} _FDID;
/* File object structure (FIL) */
typedef struct {
_FDID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
DWORD clust; /* Current cluster of fpter (invalid when fprt is 0) */
DWORD sect; /* Sector number appearing in buf[] (0:invalid) */
#if !_FS_READONLY
DWORD dir_sect; /* Sector number containing the directory entry */
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
#endif
#if _USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS]; /* File private data read/write window */
#endif
} FIL;
/* Directory object structure (DIR) */
typedef struct {
_FDID obj; /* Object identifier */
DWORD dptr; /* Current read/write offset */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector */
BYTE* dir; /* Pointer to the directory item in the win[] */
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */
#if _USE_LFN != 0
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
#endif
#if _USE_FIND
const TCHAR* pat; /* Pointer to the name matching pattern */
#endif
} DIR;
/* File information structure (FILINFO) */
typedef struct {
FSIZE_t fsize; /* File size */
WORD fdate; /* Modified date */
WORD ftime; /* Modified time */
BYTE fattrib; /* File attribute */
#if _USE_LFN != 0
TCHAR altname[13]; /* Altenative file name */
TCHAR fname[_MAX_LFN + 1]; /* Primary file name */
#else
TCHAR fname[13]; /* File name */
#endif
} FILINFO;
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_LOCK */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
FRESULT f_close (FIL* fp); /* Close an open file object */
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */
FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */
FRESULT f_truncate (FIL* fp); /* Truncate the file */
FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
FRESULT f_closedir (DIR* dp); /* Close an open directory */
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */
FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->obj.objsize)
#define f_rewind(fp) f_lseek((fp), 0)
#define f_rewinddir(dp) f_readdir((dp), 0)
#ifndef EOF
#define EOF (-1)
#endif
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* RTC function */
#if !_FS_READONLY && !_FS_NORTC
DWORD get_fattime (void);
#endif
/* Unicode support functions */
#if _USE_LFN != 0 /* Unicode - OEM code conversion */
WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */
WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */
#if _USE_LFN == 3 /* Memory functions */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
#endif
#endif
/* Sync functions */
#if _FS_REENTRANT
int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */
int ff_req_grant (_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* File access mode and open method flags (3rd argument of f_open) */
#define FA_READ 0x01
#define FA_WRITE 0x02
#define FA_OPEN_EXISTING 0x00
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA_OPEN_APPEND 0x30
/* Fast seek controls (2nd argument of f_lseek) */
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
/* Format options (2nd argument of f_mkfs) */
#define FM_FAT 0x01
#define FM_FAT32 0x02
#define FM_EXFAT 0x04
#define FM_ANY 0x07
#define FM_SFD 0x08
/* Filesystem type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
#define FS_EXFAT 4
/* File attribute bits for directory entry (FILINFO.fattrib) */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
#ifdef __cplusplus
}
#endif
#endif /* _FATFS */

267
external/fatfs/src/ffconf.h vendored Normal file
View File

@@ -0,0 +1,267 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module configuration file
/---------------------------------------------------------------------------*/
#define _FFCONF 68020 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function Configurations
/---------------------------------------------------------------------------*/
#define _FS_READONLY 0
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/ and optional writing functions as well. */
#define _FS_MINIMIZE 0
/* This option defines minimization level to remove some basic API functions.
/
/ 0: All basic functions are enabled.
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
/ are removed.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
#define _USE_STRFUNC 0
/* This option switches string functions, f_gets(), f_putc(), f_puts() and
/ f_printf().
/
/ 0: Disable string functions.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
#define _USE_FIND 0
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
#define _USE_MKFS 1
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#define _USE_FASTSEEK 0
/* This option switches fast seek function. (0:Disable or 1:Enable) */
#define _USE_EXPAND 0
/* This option switches f_expand function. (0:Disable or 1:Enable) */
#define _USE_CHMOD 0
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
/ (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */
#define _USE_LABEL 0
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */
#define _USE_FORWARD 0
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
#define _CODE_PAGE 932
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
/ 1 - ASCII (No extended character. Non-LFN cfg. only)
/ 437 - U.S.
/ 720 - Arabic
/ 737 - Greek
/ 771 - KBL
/ 775 - Baltic
/ 850 - Latin 1
/ 852 - Latin 2
/ 855 - Cyrillic
/ 857 - Turkish
/ 860 - Portuguese
/ 861 - Icelandic
/ 862 - Hebrew
/ 863 - Canadian French
/ 864 - Arabic
/ 865 - Nordic
/ 866 - Russian
/ 869 - Greek 2
/ 932 - Japanese (DBCS)
/ 936 - Simplified Chinese (DBCS)
/ 949 - Korean (DBCS)
/ 950 - Traditional Chinese (DBCS)
*/
#define _USE_LFN 0
#define _MAX_LFN 255
/* The _USE_LFN switches the support of long file name (LFN).
/
/ 0: Disable support of LFN. _MAX_LFN has no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added
/ to the project. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and
/ additional 608 bytes at exFAT enabled. _MAX_LFN can be in range from 12 to 255.
/ It should be set 255 to support full featured LFN operations.
/ When use stack for the working buffer, take care on stack overflow. When use heap
/ memory for the working buffer, memory management functions, ff_memalloc() and
/ ff_memfree(), must be added to the project. */
#define _LFN_UNICODE 0
/* This option switches character encoding on the API. (0:ANSI/OEM or 1:UTF-16)
/ To use Unicode string for the path name, enable LFN and set _LFN_UNICODE = 1.
/ This option also affects behavior of string I/O functions. */
#define _STRF_ENCODE 3
/* When _LFN_UNICODE == 1, this option selects the character encoding ON THE FILE to
/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
/
/ 0: ANSI/OEM
/ 1: UTF-16LE
/ 2: UTF-16BE
/ 3: UTF-8
/
/ This option has no effect when _LFN_UNICODE == 0. */
#define _FS_RPATH 0
/* This option configures support of relative path.
/
/ 0: Disable relative path and remove related functions.
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
/ 2: f_getcwd() function is available in addition to 1.
*/
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
#define _VOLUMES 1
/* Number of volumes (logical drives) to be used. */
#define _STR_VOLUME_ID 0
#define _VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
/* _STR_VOLUME_ID switches string support of volume ID.
/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
/ the drive ID strings are: A-Z and 0-9. */
#define _MULTI_PARTITION 0
/* This option switches support of multi-partition on a physical drive.
/ By default (0), each logical drive number is bound to the same physical drive
/ number and only an FAT volume found on the physical drive will be mounted.
/ When multi-partition is enabled (1), each logical drive number can be bound to
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
/ funciton will be available. */
#define _MIN_SS 512
#define _MAX_SS 512
/* These options configure the range of sector size to be supported. (512, 1024,
/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
/ disk_ioctl() function. */
#define _USE_TRIM 0
/* This option switches support of ATA-TRIM. (0:Disable or 1:Enable)
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
/ disk_ioctl() function. */
#define _FS_NOFSINFO 0
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
/ bit0=1: Do not trust free cluster count in the FSINFO.
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
*/
/*---------------------------------------------------------------------------/
/ System Configurations
/---------------------------------------------------------------------------*/
#define _FS_TINY 0
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of file object (FIL) is reduced _MAX_SS bytes.
/ Instead of private sector buffer eliminated from the file object, common sector
/ buffer in the file system object (FATFS) is used for the file data transfer. */
#define _FS_EXFAT 0
/* This option switches support of exFAT file system. (0:Disable or 1:Enable)
/ When enable exFAT, also LFN needs to be enabled. (_USE_LFN >= 1)
/ Note that enabling exFAT discards C89 compatibility. */
#define _FS_NORTC 1
#define _NORTC_MON 1
#define _NORTC_MDAY 1
#define _NORTC_YEAR 2016
/* The option _FS_NORTC switches timestamp functiton. If the system does not have
/ any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable
/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time.
/ To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be
/ added to the project to get current time form real-time clock. _NORTC_MON,
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
/ These options have no effect at read-only configuration (_FS_READONLY = 1). */
#define _FS_LOCK 0
/* The option _FS_LOCK switches file lock function to control duplicated file open
/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
/ is 1.
/
/ 0: Disable file lock function. To avoid volume corruption, application program
/ should avoid illegal open, remove and rename to the open objects.
/ >0: Enable file lock function. The value defines how many files/sub-directories
/ can be opened simultaneously under file lock control. Note that the file
/ lock control is independent of re-entrancy. */
#define _FS_REENTRANT 0
#define _FS_TIMEOUT 1000
#define _SYNC_t HANDLE
/* The option _FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
/ module itself. Note that regardless of this option, file access to different
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
/ to the same volume is under control of this function.
/
/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
/ function, must be added to the project. Samples are available in
/ option/syscall.c.
/
/ The _FS_TIMEOUT defines timeout period in unit of time tick.
/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.h. */
/* #include <windows.h> // O/S definitions */
/*--- End of configuration options ---*/

38
external/fatfs/src/integer.h vendored Normal file
View File

@@ -0,0 +1,38 @@
/*-------------------------------------------*/
/* Integer type definitions for FatFs module */
/*-------------------------------------------*/
#ifndef _FF_INTEGER
#define _FF_INTEGER
#ifdef _WIN32 /* FatFs development platform */
#include <windows.h>
#include <tchar.h>
typedef unsigned __int64 QWORD;
#else /* Embedded platform */
/* These types MUST be 16-bit or 32-bit */
typedef int INT;
typedef unsigned int UINT;
/* This type MUST be 8-bit */
typedef unsigned char BYTE;
/* These types MUST be 16-bit */
typedef short SHORT;
typedef unsigned short WORD;
typedef unsigned short WCHAR;
/* These types MUST be 32-bit */
typedef long LONG;
typedef unsigned long DWORD;
/* This type MUST be 64-bit (Remove this for C89 compatibility) */
typedef unsigned long long QWORD;
#endif
#endif

3870
external/fatfs/src/option/cc932.c vendored Normal file

File diff suppressed because it is too large Load Diff

11045
external/fatfs/src/option/cc936.c vendored Normal file

File diff suppressed because it is too large Load Diff

8674
external/fatfs/src/option/cc949.c vendored Normal file

File diff suppressed because it is too large Load Diff

6900
external/fatfs/src/option/cc950.c vendored Normal file

File diff suppressed because it is too large Load Diff

388
external/fatfs/src/option/ccsbcs.c vendored Normal file
View File

@@ -0,0 +1,388 @@
/*------------------------------------------------------------------------*/
/* Unicode - Local code bidirectional converter (C)ChaN, 2015 */
/* (SBCS code pages) */
/*------------------------------------------------------------------------*/
/* 437 U.S.
/ 720 Arabic
/ 737 Greek
/ 771 KBL
/ 775 Baltic
/ 850 Latin 1
/ 852 Latin 2
/ 855 Cyrillic
/ 857 Turkish
/ 860 Portuguese
/ 861 Icelandic
/ 862 Hebrew
/ 863 Canadian French
/ 864 Arabic
/ 865 Nordic
/ 866 Russian
/ 869 Greek 2
*/
#include "../ff.h"
#if _CODE_PAGE == 437
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 720
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */
0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627,
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A,
0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 737
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */
0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E,
0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 771
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP771(0x80-0xFF) to Unicode conversion table */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x0104, 0x0105, 0x010C, 0x010D,
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
0x0118, 0x0119, 0x0116, 0x0117, 0x012E, 0x012F, 0x0160, 0x0161, 0x0172, 0x0173, 0x016A, 0x016B, 0x017D, 0x017E, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 775
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */
0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4,
0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D,
0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019,
0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 850
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 852
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4,
0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 855
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A,
0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580,
0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116,
0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 857
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4,
0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 860
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP860(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2,
0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 861
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP861(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 862
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 863
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP863(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0,
0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192,
0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2219,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 864
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP864(0x80-0xFF) to Unicode conversion table */
0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518,
0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000,
0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5,
0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, 0xFED1, 0x061B, 0xFEB1, 0xFEB5, 0xFEB9, 0x061F,
0x00A2, 0xFE80, 0xFE81, 0xFE83, 0xFE85, 0xFECA, 0xFE8B, 0xFE8D, 0xFE91, 0xFE93, 0xFE97, 0xFE9B, 0xFE9F, 0xFEA3, 0xFEA7, 0xFEA9,
0xFEAB, 0xFEAD, 0xFEAF, 0xFEB3, 0xFEB7, 0xFEBB, 0xFEBF, 0xFEC1, 0xFEC5, 0xFECB, 0xFECF, 0x00A6, 0x00AC, 0x00F7, 0x00D7, 0xFEC9,
0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFEBD, 0xFECC, 0xFECE, 0xFECD, 0xFEE1,
0xFE7D, 0x0651, 0xFEE5, 0xFEE9, 0xFEEC, 0xFEF0, 0xFEF2, 0xFED0, 0xFED5, 0xFEF5, 0xFEF6, 0xFEDD, 0xFED9, 0xFEF1, 0x25A0, 0x0000
};
#elif _CODE_PAGE == 865
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP865(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 866
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 869
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP869(0x80-0xFF) to Unicode conversion table */
0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389,
0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF,
0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x039A, 0x039B, 0x039C, 0x039D, 0x2563, 0x2551, 0x2557, 0x255D, 0x039E, 0x039F, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0A30, 0x03A1, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x03A3,
0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x2518, 0x250C, 0x2588, 0x2584, 0x03B4, 0x03B5, 0x2580,
0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x0384,
0x00AD, 0x00B1, 0x03C5, 0x03C6, 0x03C7, 0x00A7, 0x03C8, 0x0385, 0x00B0, 0x00A8, 0x03C9, 0x03CB, 0x03B0, 0x03CE, 0x25A0, 0x00A0
};
#endif
#if !_TBLDEF || !_USE_LFN
#error This file is not needed at current configuration. Remove from the project.
#endif
WCHAR ff_convert ( /* Converted character, Returns zero on error */
WCHAR chr, /* Character code to be converted */
UINT dir /* 0: Unicode to OEM code, 1: OEM code to Unicode */
)
{
WCHAR c;
if (chr < 0x80) { /* ASCII */
c = chr;
} else {
if (dir) { /* OEM code to Unicode */
c = (chr >= 0x100) ? 0 : Tbl[chr - 0x80];
} else { /* Unicode to OEM code */
for (c = 0; c < 0x80; c++) {
if (chr == Tbl[c]) break;
}
c = (c + 0x80) & 0xFF;
}
}
return c;
}
WCHAR ff_wtoupper ( /* Returns upper converted character */
WCHAR chr /* Unicode character to be upper converted (BMP only) */
)
{
/* Compressed upper conversion table */
static const WCHAR cvt1[] = { /* U+0000 - U+0FFF */
/* Basic Latin */
0x0061,0x031A,
/* Latin-1 Supplement */
0x00E0,0x0317, 0x00F8,0x0307, 0x00FF,0x0001,0x0178,
/* Latin Extended-A */
0x0100,0x0130, 0x0132,0x0106, 0x0139,0x0110, 0x014A,0x012E, 0x0179,0x0106,
/* Latin Extended-B */
0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA,
0x01CD,0x0110, 0x01DD,0x0001,0x018E, 0x01DE,0x0112, 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, 0x01F8,0x0128,
0x0222,0x0112, 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, 0x0246,0x010A,
/* IPA Extensions */
0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7,
/* Greek, Coptic */
0x037B,0x0003,0x03FD,0x03FE,0x03FF, 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, 0x03B1,0x0311,
0x03C2,0x0002,0x03A3,0x03A3, 0x03C4,0x0308, 0x03CC,0x0003,0x038C,0x038E,0x038F, 0x03D8,0x0118,
0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA,
/* Cyrillic */
0x0430,0x0320, 0x0450,0x0710, 0x0460,0x0122, 0x048A,0x0136, 0x04C1,0x010E, 0x04CF,0x0001,0x04C0, 0x04D0,0x0144,
/* Armenian */
0x0561,0x0426,
0x0000
};
static const WCHAR cvt2[] = { /* U+1000 - U+FFFF */
/* Phonetic Extensions */
0x1D7D,0x0001,0x2C63,
/* Latin Extended Additional */
0x1E00,0x0196, 0x1EA0,0x015A,
/* Greek Extended */
0x1F00,0x0608, 0x1F10,0x0606, 0x1F20,0x0608, 0x1F30,0x0608, 0x1F40,0x0606,
0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, 0x1F60,0x0608,
0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB,
0x1F80,0x0608, 0x1F90,0x0608, 0x1FA0,0x0608, 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC,
0x1FCC,0x0001,0x1FC3, 0x1FD0,0x0602, 0x1FE0,0x0602, 0x1FE5,0x0001,0x1FEC, 0x1FF2,0x0001,0x1FFC,
/* Letterlike Symbols */
0x214E,0x0001,0x2132,
/* Number forms */
0x2170,0x0210, 0x2184,0x0001,0x2183,
/* Enclosed Alphanumerics */
0x24D0,0x051A, 0x2C30,0x042F,
/* Latin Extended-C */
0x2C60,0x0102, 0x2C67,0x0106, 0x2C75,0x0102,
/* Coptic */
0x2C80,0x0164,
/* Georgian Supplement */
0x2D00,0x0826,
/* Full-width */
0xFF41,0x031A,
0x0000
};
const WCHAR *p;
WCHAR bc, nc, cmd;
p = chr < 0x1000 ? cvt1 : cvt2;
for (;;) {
bc = *p++; /* Get block base */
if (!bc || chr < bc) break;
nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */
if (chr < bc + nc) { /* In the block? */
switch (cmd) {
case 0: chr = p[chr - bc]; break; /* Table conversion */
case 1: chr -= (chr - bc) & 1; break; /* Case pairs */
case 2: chr -= 16; break; /* Shift -16 */
case 3: chr -= 32; break; /* Shift -32 */
case 4: chr -= 48; break; /* Shift -48 */
case 5: chr -= 26; break; /* Shift -26 */
case 6: chr += 8; break; /* Shift +8 */
case 7: chr -= 80; break; /* Shift -80 */
case 8: chr -= 0x1C60; break; /* Shift -0x1C60 */
}
break;
}
if (!cmd) p += nc;
}
return chr;
}

151
external/fatfs/src/option/syscall.c vendored Normal file
View File

@@ -0,0 +1,151 @@
/*------------------------------------------------------------------------*/
/* Sample code of OS dependent controls for FatFs */
/* (C)ChaN, 2014 */
/*------------------------------------------------------------------------*/
#include "../ff.h"
#if _FS_REENTRANT
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to create a new
/ synchronization object, such as semaphore and mutex. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
BYTE vol, /* Corresponding volume (logical drive number) */
_SYNC_t *sobj /* Pointer to return the created sync object */
)
{
int ret;
*sobj = CreateMutex(NULL, FALSE, NULL); /* Win32 */
ret = (int)(*sobj != INVALID_HANDLE_VALUE);
// *sobj = SyncObjects[vol]; /* uITRON (give a static sync object) */
// ret = 1; /* The initial value of the semaphore must be 1. */
// *sobj = OSMutexCreate(0, &err); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// *sobj = xSemaphoreCreateMutex(); /* FreeRTOS */
// ret = (int)(*sobj != NULL);
return ret;
}
/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to delete a synchronization
/ object that created with ff_cre_syncobj() function. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to any error */
_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
)
{
int ret;
ret = CloseHandle(sobj); /* Win32 */
// ret = 1; /* uITRON (nothing to do) */
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// vSemaphoreDelete(sobj); /* FreeRTOS */
// ret = 1;
return ret;
}
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
_SYNC_t sobj /* Sync object to wait */
)
{
int ret;
ret = (int)(WaitForSingleObject(sobj, _FS_TIMEOUT) == WAIT_OBJECT_0); /* Win32 */
// ret = (int)(wai_sem(sobj) == E_OK); /* uITRON */
// OSMutexPend(sobj, _FS_TIMEOUT, &err)); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// ret = (int)(xSemaphoreTake(sobj, _FS_TIMEOUT) == pdTRUE); /* FreeRTOS */
return ret;
}
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/
void ff_rel_grant (
_SYNC_t sobj /* Sync object to be signaled */
)
{
ReleaseMutex(sobj); /* Win32 */
// sig_sem(sobj); /* uITRON */
// OSMutexPost(sobj); /* uC/OS-II */
// xSemaphoreGive(sobj); /* FreeRTOS */
}
#endif
#if _USE_LFN == 3 /* LFN with a working buffer on the heap */
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/*------------------------------------------------------------------------*/
/* If a NULL is returned, the file function fails with FR_NOT_ENOUGH_CORE.
*/
void* ff_memalloc ( /* Returns pointer to the allocated memory block */
UINT msize /* Number of bytes to allocate */
)
{
return malloc(msize); /* Allocate a new memory block with POSIX API */
}
/*------------------------------------------------------------------------*/
/* Free a memory block */
/*------------------------------------------------------------------------*/
void ff_memfree (
void* mblock /* Pointer to the memory block to free */
)
{
free(mblock); /* Discard the memory block with POSIX API */
}
#endif

17
external/fatfs/src/option/unicode.c vendored Normal file
View File

@@ -0,0 +1,17 @@
#include "../ff.h"
#if _USE_LFN != 0
#if _CODE_PAGE == 932 /* Japanese Shift_JIS */
#include "cc932.c"
#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */
#include "cc936.c"
#elif _CODE_PAGE == 949 /* Korean */
#include "cc949.c"
#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */
#include "cc950.c"
#else /* Single Byte Character-Set */
#include "ccsbcs.c"
#endif
#endif

208
external/fnmatch/fnmatch.c vendored Normal file
View File

@@ -0,0 +1,208 @@
/* $NetBSD: fnmatch.c,v 1.26 2014/10/12 22:32:33 christos Exp $ */
/*
* Copyright (c) 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Guido van Rossum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*/
/*
* Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
* Compares a filename or pathname to a pattern.
*/
#include <ctype.h>
#include "fnmatch.h"
#include <string.h>
#define EOS '\0'
static inline int foldcase(int ch, int flags)
{
if ((flags & FNM_CASEFOLD) != 0 && isupper(ch))
return tolower(ch);
return ch;
}
#define FOLDCASE(ch, flags) foldcase((unsigned char)(ch), (flags))
static const char * rangematch(const char *pattern, int test, int flags)
{
int negate, ok, need;
char c, c2;
if (pattern == NULL)
{
return NULL;
}
/*
* A bracket expression starting with an unquoted circumflex
* character produces unspecified results (IEEE 1003.2-1992,
* 3.13.2). This implementation treats it like '!', for
* consistency with the regular expression syntax.
* J.T. Conklin (conklin@ngai.kaleida.com)
*/
if ((negate = (*pattern == '!' || *pattern == '^')) != 0)
++pattern;
need = 1;
for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']' || need;) {
need = 0;
if (c == '/')
return (void *)-1;
if (c == '\\' && !(flags & FNM_NOESCAPE))
c = FOLDCASE(*pattern++, flags);
if (c == EOS)
return NULL;
if (*pattern == '-'
&& (c2 = FOLDCASE(*(pattern + 1), flags)) != EOS &&
c2 != ']') {
pattern += 2;
if (c2 == '\\' && !(flags & FNM_NOESCAPE))
c2 = FOLDCASE(*pattern++, flags);
if (c2 == EOS)
return NULL;
if (c <= test && test <= c2)
ok = 1;
} else if (c == test)
ok = 1;
}
return ok == negate ? NULL : pattern;
}
static int fnmatchx(const char *pattern, const char *string, int flags, size_t recursion)
{
const char *stringstart, *r;
char c, test;
if ((pattern == NULL) || (string == NULL))
{
return FNM_NOMATCH;
}
if (recursion-- == 0)
return FNM_NORES;
for (stringstart = string;;) {
switch (c = FOLDCASE(*pattern++, flags)) {
case EOS:
if ((flags & FNM_LEADING_DIR) && *string == '/')
return 0;
return *string == EOS ? 0 : FNM_NOMATCH;
case '?':
if (*string == EOS)
return FNM_NOMATCH;
if (*string == '/' && (flags & FNM_PATHNAME))
return FNM_NOMATCH;
if (*string == '.' && (flags & FNM_PERIOD) &&
(string == stringstart ||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
return FNM_NOMATCH;
++string;
break;
case '*':
c = FOLDCASE(*pattern, flags);
/* Collapse multiple stars. */
while (c == '*')
c = FOLDCASE(*++pattern, flags);
if (*string == '.' && (flags & FNM_PERIOD) &&
(string == stringstart ||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
return FNM_NOMATCH;
/* Optimize for pattern with * at end or before /. */
if (c == EOS) {
if (flags & FNM_PATHNAME)
return (flags & FNM_LEADING_DIR) ||
strchr(string, '/') == NULL ?
0 : FNM_NOMATCH;
else
return 0;
} else if (c == '/' && flags & FNM_PATHNAME) {
if ((string = strchr(string, '/')) == NULL)
return FNM_NOMATCH;
break;
}
/* General case, use recursion. */
while ((test = FOLDCASE(*string, flags)) != EOS) {
int e;
switch ((e = fnmatchx(pattern, string,
flags & ~FNM_PERIOD, recursion))) {
case FNM_NOMATCH:
break;
default:
return e;
}
if (test == '/' && flags & FNM_PATHNAME)
break;
++string;
}
return FNM_NOMATCH;
case '[':
if (*string == EOS)
return FNM_NOMATCH;
if (*string == '/' && flags & FNM_PATHNAME)
return FNM_NOMATCH;
if ((r = rangematch(pattern,
FOLDCASE(*string, flags), flags)) == NULL)
return FNM_NOMATCH;
if (r == (void *)-1) {
if (*string != '[')
return FNM_NOMATCH;
} else
pattern = r;
++string;
break;
case '\\':
if (!(flags & FNM_NOESCAPE)) {
if ((c = FOLDCASE(*pattern++, flags)) == EOS) {
c = '\0';
--pattern;
}
}
/* FALLTHROUGH */
default:
if (c != FOLDCASE(*string++, flags))
return FNM_NOMATCH;
break;
}
}
/* NOTREACHED */
}
int fnmatch(const char *pattern, const char *string, int flags)
{
return fnmatchx(pattern, string, flags, 64);
}

50
external/fnmatch/fnmatch.h vendored Normal file
View File

@@ -0,0 +1,50 @@
/* $NetBSD: fnmatch.h,v 1.12.50.1 2011/02/08 16:18:55 bouyer Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)fnmatch.h 8.1 (Berkeley) 6/2/93
*/
#ifndef _FNMATCH_H_
#define _FNMATCH_H_
#define FNM_NOMATCH 1 /* Match failed. */
#define FNM_NOSYS 2 /* Function not implemented. */
#define FNM_NORES 3 /* Out of resources */
#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
#define FNM_PERIOD 0x04 /* Period must be matched by period. */
#define FNM_CASEFOLD 0x08 /* Pattern is matched case-insensitive */
#define FNM_LEADING_DIR 0x10 /* Ignore /<tail> after Imatch. */
int fnmatch(const char *, const char *, int);
#endif /* !_FNMATCH_H_ */

85
external/fprintf/nrf_fprintf.c vendored Normal file
View File

@@ -0,0 +1,85 @@
/**
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, 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.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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.
*
*/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_FPRINTF)
#include <stdarg.h>
#include "nrf_assert.h"
#include "nrf_fprintf_format.h"
void nrf_fprintf_buffer_flush(nrf_fprintf_ctx_t * const p_ctx)
{
ASSERT(p_ctx != NULL);
if (p_ctx->io_buffer_cnt == 0)
{
return;
}
p_ctx->fwrite(p_ctx->p_user_ctx,
p_ctx->p_io_buffer,
p_ctx->io_buffer_cnt);
p_ctx->io_buffer_cnt = 0;
}
void nrf_fprintf(nrf_fprintf_ctx_t * const p_ctx,
char const * p_fmt,
...)
{
ASSERT(p_ctx != NULL);
ASSERT(p_ctx->fwrite != NULL);
ASSERT(p_ctx->p_io_buffer != NULL);
ASSERT(p_ctx->io_buffer_size > 0);
if (p_fmt == NULL)
{
return;
}
va_list args = {0};
va_start(args, p_fmt);
nrf_fprintf_fmt(p_ctx, p_fmt, &args);
va_end(args);
}
#endif // NRF_MODULE_ENABLED(NRF_FPRINTF)

114
external/fprintf/nrf_fprintf.h vendored Normal file
View File

@@ -0,0 +1,114 @@
/**
* Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, 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.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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.
*
*/
#ifndef NRF_FPRINTF_H__
#define NRF_FPRINTF_H__
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef void (* nrf_fprintf_fwrite)(void const * p_user_ctx, char const * p_str, size_t length);
/**
* @brief fprintf context
*/
typedef struct nrf_fprintf_ctx
{
char * const p_io_buffer; ///< Pointer to IO buffer.
size_t const io_buffer_size; ///< IO buffer size.
size_t io_buffer_cnt; ///< IO buffer usage.
bool auto_flush; ///< Auto flush configurator.
void const * const p_user_ctx; ///< Pointer to user data to be passed to the fwrite funciton.
nrf_fprintf_fwrite fwrite; ///< Pointer to function sending data stream.
} nrf_fprintf_ctx_t;
/**
* @brief Macro for defining nrf_fprintf instance.
*
* @param name Instance name.
* @param _p_user_ctx Pointer to user data.
* @param _p_io_buffer Pointer to IO buffer
* @param _io_buffer_size Size of IO buffer.
* @param _auto_flush Indicator if IO buffer shall be automatically flush.
* @param _fwrite Pointer to function sending data stream.
* */
#define NRF_FPRINTF_DEF(name, _p_user_ctx, _p_io_buffer, _io_buffer_size, _auto_flush, _fwrite) \
static nrf_fprintf_ctx_t name = \
{ \
.p_io_buffer = _p_io_buffer, \
.io_buffer_size = _io_buffer_size, \
.io_buffer_cnt = 0, \
.auto_flush = _auto_flush, \
.p_user_ctx = _p_user_ctx, \
.fwrite = _fwrite \
}
/**
* @brief fprintf like function which send formated data stream to output specified by user
* @ref nrf_fprintf_ctx_t
*
* @param p_ctx fprintf context.
* @param p_fmt Format string.
* @param ... List of parameters to print.
* */
void nrf_fprintf(nrf_fprintf_ctx_t * const p_ctx,
char const * p_fmt,
...);
/**
* @brief function flushing data stored in io_buffer @ref nrf_fprintf_ctx_t
*
* @param p_ctx fprintf context
*/
void nrf_fprintf_buffer_flush(nrf_fprintf_ctx_t * const p_ctx);
#ifdef __cplusplus
}
#endif
#endif /* NRF_FPRINTF_H__ */

810
external/fprintf/nrf_fprintf_format.c vendored Normal file
View File

@@ -0,0 +1,810 @@
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 2014 - 2017 SEGGER Microcontroller GmbH & Co. KG *
* *
* www.segger.com Support: support@segger.com *
* *
**********************************************************************
* *
* SEGGER RTT * Real Time Transfer for embedded targets *
* *
**********************************************************************
* *
* All rights reserved. *
* *
* SEGGER strongly recommends to not make any changes *
* to or modify the source code of this software in order to stay *
* compatible with the RTT protocol and J-Link. *
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* conditions are met: *
* *
* o Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* o 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. *
* *
* o Neither the name of SEGGER Microcontroller GmbH & Co. KG *
* 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 SEGGER Microcontroller 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. *
* *
**********************************************************************
* *
* RTT version: 6.14d *
* *
*********************************************************************/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_FPRINTF)
#include <stdarg.h>
#include "nrf_assert.h"
#include "nrf_fprintf.h"
#include "nrf_fprintf_format.h"
#define NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY (1u << 0)
#define NRF_CLI_FORMAT_FLAG_PAD_ZERO (1u << 1)
#define NRF_CLI_FORMAT_FLAG_PRINT_SIGN (1u << 2)
#define NRF_CLI_FORMAT_DOUBLE_DEF_PRECISION 6
#define NRF_CLI_FORMAT_DOUBLE_SIGN_POSITION 63U
#define NRF_CLI_FORMAT_DOUBLE_SIGN_MASK 1ULL
#define NRF_CLI_FORMAT_DOUBLE_SIGN (NRF_CLI_FORMAT_DOUBLE_SIGN_MASK << NRF_CLI_FORMAT_DOUBLE_SIGN_POSITION)
#define NRF_CLI_FORMAT_DOUBLE_EXP_POSITION 52U
#define NRF_CLI_FORMAT_DOUBLE_EXP_MASK 0x7FFULL
#define NRF_CLI_FORMAT_DOUBLE_EXP (NRF_CLI_FORMAT_DOUBLE_EXP_MASK << NRF_CLI_FORMAT_DOUBLE_EXP_POSITION)
#define NRF_CLI_FORMAT_DOUBLE_MANT_POSITION 0U
#define NRF_CLI_FORMAT_DOUBLE_MANT_MASK 0xFFFFFFFFFFFFF
#define NRF_CLI_FORMAT_DOUBLE_MANT (NRF_CLI_FORMAT_DOUBLE_MANT_MASK << NRF_CLI_FORMAT_DOUBLE_MANT_POSITION)
#define NRF_CLI_FORMAT_DOUBLE_SIGN_GET(v) (!!((v) & NRF_CLI_FORMAT_DOUBLE_SIGN))
#define NRF_CLI_FORMAT_DOUBLE_EXP_GET(v) (((v) & NRF_CLI_FORMAT_DOUBLE_EXP) >> NRF_CLI_FORMAT_DOUBLE_EXP_POSITION)
#define NRF_CLI_FORMAT_DOUBLE_MANT_GET(v) (((v) & NRF_CLI_FORMAT_DOUBLE_MANT) >> NRF_CLI_FORMAT_DOUBLE_MANT_POSITION)
#define NRF_CLI_FORMAT_REQ_SIGN_SPACE(s, f) ((s) | (!!((f) & NRF_CLI_FORMAT_FLAG_PRINT_SIGN)))
#define HIGH_32(v) ((v) >> 32)
#define LOW_32(v) (((1ULL << 32) - 1) & v)
static void buffer_add(nrf_fprintf_ctx_t * const p_ctx, char c)
{
#if NRF_MODULE_ENABLED(NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF)
if (c == '\n')
{
buffer_add(p_ctx, '\r');
}
#endif
p_ctx->p_io_buffer[p_ctx->io_buffer_cnt++] = c;
if (p_ctx->io_buffer_cnt >= p_ctx->io_buffer_size)
{
nrf_fprintf_buffer_flush(p_ctx);
}
}
static void string_print(nrf_fprintf_ctx_t * const p_ctx,
char const * p_str,
uint32_t FieldWidth,
uint32_t FormatFlags)
{
uint32_t Width = 0;
char c;
if ((FormatFlags & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) == NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY)
{
while ((c = *p_str) != '\0')
{
p_str++;
Width++;
buffer_add(p_ctx, c);
}
while ((FieldWidth > Width) && (FieldWidth > 0))
{
FieldWidth--;
buffer_add(p_ctx, ' ');
}
}
else
{
if (p_str != 0)
{
Width = strlen(p_str);
}
while ((FieldWidth > Width) && (FieldWidth > 0))
{
FieldWidth--;
buffer_add(p_ctx, ' ');
}
while ((c = *p_str) != '\0')
{
p_str++;
Width++;
buffer_add(p_ctx, c);
}
}
}
static void unsigned_print(nrf_fprintf_ctx_t * const p_ctx,
uint32_t v,
uint32_t Base,
uint32_t NumDigits,
uint32_t FieldWidth,
uint32_t FormatFlags)
{
static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F' };
uint32_t Div;
uint32_t Value;
uint32_t Width;
char c;
Value = v;
//
// Get actual field width
//
Width = 1u;
while (Value >= Base)
{
Value = (Value / Base);
Width++;
}
if (NumDigits > Width)
{
Width = NumDigits;
}
//
// Print leading chars if necessary
//
if ((FormatFlags & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) == 0u)
{
if (FieldWidth != 0u)
{
if (((FormatFlags & NRF_CLI_FORMAT_FLAG_PAD_ZERO) == NRF_CLI_FORMAT_FLAG_PAD_ZERO) &&
(NumDigits == 0u))
{
c = '0';
}
else
{
c = ' ';
}
while ((FieldWidth != 0u) && (Width < FieldWidth))
{
FieldWidth--;
buffer_add(p_ctx, c);
}
}
}
Value = 1;
/*
* Compute Digit.
* Loop until Digit has the value of the highest digit required.
* Example: If the output is 345 (Base 10), loop 2 times until Digit is 100.
*/
while (1)
{
/* User specified a min number of digits to print? => Make sure we loop at least that
* often, before checking anything else (> 1 check avoids problems with NumDigits
* being signed / unsigned)
*/
if (NumDigits > 1u)
{
NumDigits--;
}
else
{
Div = v / Value;
// Is our divider big enough to extract the highest digit from value? => Done
if (Div < Base)
{
break;
}
}
Value *= Base;
}
//
// Output digits
//
do
{
Div = v / Value;
v -= Div * Value;
buffer_add(p_ctx, _aV2C[Div]);
Value /= Base;
} while (Value);
//
// Print trailing spaces if necessary
//
if ((FormatFlags & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) == NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY)
{
if (FieldWidth != 0u)
{
while ((FieldWidth != 0u) && (Width < FieldWidth))
{
FieldWidth--;
buffer_add(p_ctx, ' ');
}
}
}
}
static void int_print(nrf_fprintf_ctx_t * const p_ctx,
int32_t v,
uint32_t Base,
uint32_t NumDigits,
uint32_t FieldWidth,
uint32_t FormatFlags)
{
uint32_t Width;
int32_t Number;
Number = (v < 0) ? -v : v;
//
// Get actual field width
//
Width = 1u;
while (Number >= (int32_t)Base)
{
Number = (Number / (int32_t)Base);
Width++;
}
if (NumDigits > Width)
{
Width = NumDigits;
}
if ((FieldWidth > 0u) && ((v < 0) ||
((FormatFlags & NRF_CLI_FORMAT_FLAG_PRINT_SIGN) == NRF_CLI_FORMAT_FLAG_PRINT_SIGN)))
{
FieldWidth--;
}
//
// Print leading spaces if necessary
//
if ((((FormatFlags & NRF_CLI_FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) &&
((FormatFlags & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) == 0u))
{
if (FieldWidth != 0u)
{
while ((FieldWidth != 0u) && (Width < FieldWidth))
{
FieldWidth--;
buffer_add(p_ctx, ' ');
}
}
}
//
// Print sign if necessary
//
if (v < 0)
{
v = -v;
buffer_add(p_ctx, '-');
}
else if ((FormatFlags & NRF_CLI_FORMAT_FLAG_PRINT_SIGN) == NRF_CLI_FORMAT_FLAG_PRINT_SIGN)
{
buffer_add(p_ctx, '+');
}
else
{
/* do nothing */
}
//
// Print leading zeros if necessary
//
if (((FormatFlags & NRF_CLI_FORMAT_FLAG_PAD_ZERO) == NRF_CLI_FORMAT_FLAG_PAD_ZERO) &&
((FormatFlags & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u))
{
if (FieldWidth != 0u)
{
while ((FieldWidth != 0u) && (Width < FieldWidth))
{
FieldWidth--;
buffer_add(p_ctx, '0');
}
}
}
//
// Print number without sign
//
unsigned_print(p_ctx, (uint32_t)v, Base, NumDigits, FieldWidth, FormatFlags);
}
#if NRF_MODULE_ENABLED(NRF_FPRINTF_DOUBLE)
static void fill_space(nrf_fprintf_ctx_t * const p_ctx,
uint8_t len,
bool zeros)
{
for (; len > 0; len--)
{
if (zeros)
{
buffer_add(p_ctx, '0');
}
else
{
buffer_add(p_ctx, ' ');
}
}
}
static void float_print(nrf_fprintf_ctx_t * const p_ctx,
double v,
uint32_t digits,
uint32_t width,
uint32_t format,
bool uppercase)
{
bool sign, transform = false;
uint64_t num, mant, lead, low, base, res, carry, x, s0, s1, s2, s3, fr;
int32_t exp;
uint8_t highest, offset, lead_len = 0, skipped = 0;
uint8_t precision = digits ? digits + 1 : NRF_CLI_FORMAT_DOUBLE_DEF_PRECISION + 1;
/* Default digits should be -1, because 0 could be a requirement, not the default.
* This should be changed for the whole library.
*/
if ((v > 0.0) && (v < 1.0))
{
v += 1.0;
transform = true;
}
else if ((v > -1.0) && (v < 0.0))
{
v -= 1.0;
transform = true;
}
memcpy(&num, &v, sizeof(num));
sign = NRF_CLI_FORMAT_DOUBLE_SIGN_GET(num);
exp = NRF_CLI_FORMAT_DOUBLE_EXP_GET(num);
mant = NRF_CLI_FORMAT_DOUBLE_MANT_GET(num);
/* Special cases */
if (exp == NRF_CLI_FORMAT_DOUBLE_EXP_MASK)
{
if (width && (!(format & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY)))
{
fill_space(p_ctx, width - 3 - NRF_CLI_FORMAT_REQ_SIGN_SPACE(sign, format), false);
}
if (sign)
{
buffer_add(p_ctx, '-');
}
else if (format & NRF_CLI_FORMAT_FLAG_PRINT_SIGN)
{
buffer_add(p_ctx, '+');
}
if (mant != 0)
{
if(uppercase)
{
buffer_add(p_ctx, 'N');
buffer_add(p_ctx, 'A');
buffer_add(p_ctx, 'N');
}
else
{
buffer_add(p_ctx, 'n');
buffer_add(p_ctx, 'a');
buffer_add(p_ctx, 'n');
}
}
else
{
if(uppercase)
{
buffer_add(p_ctx, 'I');
buffer_add(p_ctx, 'N');
buffer_add(p_ctx, 'F');
}
else
{
buffer_add(p_ctx, 'i');
buffer_add(p_ctx, 'n');
buffer_add(p_ctx, 'f');
}
}
return;
}
/* Add leading 1 to mantissa (except 0.0) */
if ((mant != 0) || (exp != 0))
{
mant |= (1ULL << 52);
}
/* Convert the exponent */
exp = exp - 1023;
/* Whole numbers */
offset = 52 - exp;
if (offset > 64)
{
/* Float fraction offset overflow */
return;
}
lead = (mant >> (offset));
/* Fraction */
low = mant & (~(lead << offset));
while (((low & 0x1) == 0) && low > 0)
{
low = low >> 1U;
skipped++;
}
highest = (offset - skipped);
base = 1;
for(uint8_t i = 0; i < precision; i++)
{
base *= 10;
}
/* Handle multiplication with possible overflow */
x = LOW_32(low) * LOW_32(base);
s0 = LOW_32(x);
x = HIGH_32(low) * LOW_32(base) + HIGH_32(x);
s1 = LOW_32(x);
s2 = HIGH_32(x);
x = s1 + LOW_32(low) * HIGH_32(base);
s1 = LOW_32(x);
x = s2 + HIGH_32(low) * HIGH_32(base) + HIGH_32(x);
s2 = LOW_32(x);
s3 = HIGH_32(x);
res = s1 << 32 | s0;
carry = s3 << 32 | s2;
/* Divide and combine */
carry = carry << (64 - highest);
res = res >> highest;
fr = res | carry;
/* Roundup */
if (fr%10 >= 5)
{
fr /= 10;
fr++;
}
else
{
fr /= 10;
}
precision--;
if (transform && (lead == 1))
{
lead = 0;
}
/* Maximum precision handled by int_print() is 10 */
if (precision > 10)
{
for (uint8_t delta = precision - 10; delta > 0; delta--)
{
fr /= 10;
}
precision = 10;
}
res = lead;
while (res > 0)
{
res /= 10;
lead_len++;
}
if ((lead == 0) && (fr == 0))
{
lead_len = 1;
}
if(lead_len == 0)
{
lead_len = 1;
}
if (width && (!(format & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY)))
{
int32_t space = width - lead_len - precision - NRF_CLI_FORMAT_REQ_SIGN_SPACE(sign, format) - 1;
if (space > 0)
{
fill_space(p_ctx, space, format & NRF_CLI_FORMAT_FLAG_PAD_ZERO);
}
}
if (sign)
{
buffer_add(p_ctx, '-');
}
else if (format & NRF_CLI_FORMAT_FLAG_PRINT_SIGN)
{
buffer_add(p_ctx, '+');
}
int_print(p_ctx,
lead,
10u,
0,
0,
0);
buffer_add(p_ctx, '.');
int_print(p_ctx,
fr,
10u,
precision,
0,
0);
if (width && (format & NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY))
{
int32_t space = width - lead_len - precision - NRF_CLI_FORMAT_REQ_SIGN_SPACE(sign, format) - 1;
if (space > 0)
{
fill_space(p_ctx, space, false);
}
}
}
#endif
void nrf_fprintf_fmt(nrf_fprintf_ctx_t * const p_ctx,
char const * p_fmt,
va_list * p_args)
{
ASSERT(p_ctx != NULL);
ASSERT(p_ctx->fwrite != NULL);
ASSERT(p_ctx->p_io_buffer != NULL);
ASSERT(p_ctx->io_buffer_size > 0);
if (p_fmt == NULL)
{
return;
}
char c;
int32_t v;
uint32_t NumDigits;
uint32_t FormatFlags;
uint32_t FieldWidth;
do
{
c = *p_fmt;
p_fmt++;
if (c == 0u)
{
break;
}
if (c == '%')
{
//
// Filter out flags
//
FormatFlags = 0u;
v = 1;
do
{
c = *p_fmt;
switch (c)
{
case '-':
FormatFlags |= NRF_CLI_FORMAT_FLAG_LEFT_JUSTIFY;
p_fmt++;
break;
case '0':
FormatFlags |= NRF_CLI_FORMAT_FLAG_PAD_ZERO;
p_fmt++;
break;
case '+':
FormatFlags |= NRF_CLI_FORMAT_FLAG_PRINT_SIGN;
p_fmt++;
break;
default:
v = 0;
break;
}
} while (v);
//
// filter out field width
//
FieldWidth = 0u;
do
{
if (c == '*')
{
/*lint -save -e64 -e56*/
FieldWidth += va_arg(*p_args, unsigned);
/*lint -restore*/
p_fmt++;
break;
}
c = *p_fmt;
if ((c < '0') || (c > '9'))
{
break;
}
p_fmt++;
FieldWidth = (FieldWidth * 10u) + (c - '0');
} while (1);
//
// Filter out precision (number of digits to display)
//
NumDigits = 0u;
c = *p_fmt;
if (c == '.')
{
p_fmt++;
do
{
c = *p_fmt;
if ((c < '0') || (c > '9'))
{
break;
}
p_fmt++;
NumDigits = NumDigits * 10u + (c - '0');
} while (1);
}
//
// Filter out length modifier
//
c = *p_fmt;
do
{
if ((c == 'l') || (c == 'h'))
{
p_fmt++;
c = *p_fmt;
}
else
{
break;
}
} while (1);
//
// Handle specifiers
//
/*lint -save -e64*/
switch (c)
{
case 'c':
{
char c0;
v = va_arg(*p_args, int32_t);
c0 = (char)v;
buffer_add(p_ctx, c0);
break;
}
case 'd':
case 'i':
v = va_arg(*p_args, int32_t);
int_print(p_ctx,
v,
10u,
NumDigits,
FieldWidth,
FormatFlags);
break;
case 'u':
v = va_arg(*p_args, int32_t);
unsigned_print(p_ctx,
(uint32_t)v,
10u,
NumDigits,
FieldWidth,
FormatFlags);
break;
case 'x':
case 'X':
v = va_arg(*p_args, int32_t);
unsigned_print(p_ctx,
(uint32_t)v,
16u,
NumDigits,
FieldWidth,
FormatFlags);
break;
case 's':
{
char const * p_s = va_arg(*p_args, const char *);
string_print(p_ctx, p_s, FieldWidth, FormatFlags);
break;
}
case 'p':
v = va_arg(*p_args, int32_t);
buffer_add(p_ctx, '0');
buffer_add(p_ctx, 'x');
unsigned_print(p_ctx, (uint32_t)v, 16u, 8u, 8u, 0);
break;
case '%':
buffer_add(p_ctx, '%');
break;
#if NRF_MODULE_ENABLED(NRF_FPRINTF_DOUBLE)
case 'f':
{
double dbl = va_arg(*p_args, double);
float_print(p_ctx,
dbl,
NumDigits,
FieldWidth,
FormatFlags,
false);
break;
}
case 'F':
{
double dbl = va_arg(*p_args, double);
float_print(p_ctx,
dbl,
NumDigits,
FieldWidth,
FormatFlags,
true);
break;
}
#endif
default:
break;
}
/*lint -restore*/
p_fmt++;
}
else
{
buffer_add(p_ctx, c);
}
} while (*p_fmt != '\0');
if (p_ctx->auto_flush)
{
nrf_fprintf_buffer_flush(p_ctx);
}
}
#endif // NRF_MODULE_ENABLED(NRF_FPRINTF)

86
external/fprintf/nrf_fprintf_format.h vendored Normal file
View File

@@ -0,0 +1,86 @@
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 2014 - 2017 SEGGER Microcontroller GmbH & Co. KG *
* *
* www.segger.com Support: support@segger.com *
* *
**********************************************************************
* *
* SEGGER RTT * Real Time Transfer for embedded targets *
* *
**********************************************************************
* *
* All rights reserved. *
* *
* SEGGER strongly recommends to not make any changes *
* to or modify the source code of this software in order to stay *
* compatible with the RTT protocol and J-Link. *
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* conditions are met: *
* *
* o Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* o 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. *
* *
* o Neither the name of SEGGER Microcontroller GmbH & Co. KG *
* 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 SEGGER Microcontroller 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. *
* *
**********************************************************************
* *
* RTT version: 6.14d *
* *
*********************************************************************/
#ifndef NRF_FPRINTF_FORMAT_H__
#define NRF_FPRINTF_FORMAT_H__
#include <stdarg.h>
#include "nrf_fprintf.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Printf like function which sends formated data stream to output.
*
* @param nrf_fprintf_ctx_t Print context.
* @param p_fmt Format string.
* @param p_args List of parameters to print.
* */
void nrf_fprintf_fmt(nrf_fprintf_ctx_t * const p_ctx,
char const * p_fmt,
va_list * p_args);
#ifdef __cplusplus
}
#endif
#endif /* NRF_FPRINTF_FORMAT_H__ */

View File

@@ -0,0 +1,207 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#ifdef SOFTDEVICE_PRESENT
#include "nrf_soc.h"
#endif
#include "app_util_platform.h"
/*-----------------------------------------------------------
* Possible configurations for system timer
*/
#define FREERTOS_USE_RTC 0 /**< Use real time clock for the system */
#define FREERTOS_USE_SYSTICK 1 /**< Use SysTick timer for system */
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
#define configTICK_SOURCE FREERTOS_USE_RTC
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configUSE_TICKLESS_IDLE 0
#define configUSE_TICKLESS_IDLE_SIMPLE_DEBUG 1 /* See into vPortSuppressTicksAndSleep source code for explanation */
#define configCPU_CLOCK_HZ ( SystemCoreClock )
#define configTICK_RATE_HZ 1024
#define configMAX_PRIORITIES ( 3 )
#define configMINIMAL_STACK_SIZE ( 60 )
#define configTOTAL_HEAP_SIZE ( 4096 )
#define configMAX_TASK_NAME_LEN ( 4 )
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_ALTERNATIVE_API 0 /* Deprecated! */
#define configQUEUE_REGISTRY_SIZE 2
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 1
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_MALLOC_FAILED_HOOK 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 0
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Software timer definitions. */
#define configUSE_TIMERS 0
#define configTIMER_TASK_PRIORITY ( 2 )
#define configTIMER_QUEUE_LENGTH 32
#define configTIMER_TASK_STACK_DEPTH ( 80 )
/* Tickless Idle configuration. */
#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2
/* Tickless idle/low power functionality. */
/* Define to trap errors during development. */
#if defined(DEBUG_NRF) || defined(DEBUG_NRF_USER)
#define configASSERT( x ) ASSERT(x)
#endif
/* FreeRTOS MPU specific definitions. */
#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 1
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_xResumeFromISR 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_xTaskGetIdleTaskHandle 1
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1
#define INCLUDE_pcTaskGetTaskName 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xEventGroupSetBitFromISR 1
#define INCLUDE_xTimerPendFunctionCall 1
/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY _PRIO_APP_HIGH
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY configLIBRARY_LOWEST_INTERRUPT_PRIORITY
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names - or at least those used in the unmodified vector table. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
/*-----------------------------------------------------------
* Settings that are generated automatically
* basing on the settings above
*/
#if (configTICK_SOURCE == FREERTOS_USE_SYSTICK)
// do not define configSYSTICK_CLOCK_HZ for SysTick to be configured automatically
// to CPU clock source
#define xPortSysTickHandler SysTick_Handler
#elif (configTICK_SOURCE == FREERTOS_USE_RTC)
#define configSYSTICK_CLOCK_HZ ( 32768UL )
#define xPortSysTickHandler RTC1_IRQHandler
#else
#error Unsupported configTICK_SOURCE value
#endif
/* Code below should be only used by the compiler, and not the assembler. */
#if !(defined(__ASSEMBLY__) || defined(__ASSEMBLER__))
#include "nrf.h"
#include "nrf_assert.h"
/* This part of definitions may be problematic in assembly - it uses definitions from files that are not assembly compatible. */
/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#error "This port requires __NVIC_PRIO_BITS to be defined"
#endif
/* Access to current system core clock is required only if we are ticking the system by systimer */
#if (configTICK_SOURCE == FREERTOS_USE_SYSTICK)
#include <stdint.h>
extern uint32_t SystemCoreClock;
#endif
#endif /* !assembler */
/** Implementation note: Use this with caution and set this to 1 ONLY for debugging
* ----------------------------------------------------------
* Set the value of configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG to below for enabling or disabling RTOS tick auto correction:
* 0. This is default. If the RTC tick interrupt is masked for more than 1 tick by higher priority interrupts, then most likely
* one or more RTC ticks are lost. The tick interrupt inside RTOS will detect this and make a correction needed. This is needed
* for the RTOS internal timers to be more accurate.
* 1. The auto correction for RTOS tick is disabled even though few RTC tick interrupts were lost. This feature is desirable when debugging
* the RTOS application and stepping though the code. After stepping when the application is continued in debug mode, the auto-corrections of
* RTOS tick might cause asserts. Setting configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG to 1 will make RTC and RTOS go out of sync but could be
* convenient for debugging.
*/
#define configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG 0
#endif /* FREERTOS_CONFIG_H */

38
external/freertos/license/license.txt vendored Normal file
View File

@@ -0,0 +1,38 @@
The FreeRTOS kernel is released under the MIT open source license, the text of
which is provided below.
This license covers the FreeRTOS kernel source files, which are located in the
/FreeRTOS/Source directory of the official FreeRTOS kernel download. It also
covers most of the source files in the demo application projects, which are
located in the /FreeRTOS/Demo directory of the official FreeRTOS download. The
demo projects may also include third party software that is not part of FreeRTOS
and is licensed separately to FreeRTOS. Examples of third party software
includes header files provided by chip or tools vendors, linker scripts,
peripheral drivers, etc. All the software in subdirectories of the /FreeRTOS
directory is either open source or distributed with permission, and is free for
use. For the avoidance of doubt, refer to the comments at the top of each
source file.
License text:
-------------
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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. If you wish to use our Amazon
FreeRTOS name, please do so in a fair use way that does not cause confusion.
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.

View File

@@ -0,0 +1,128 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM CM0 port.
*----------------------------------------------------------*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
/*
* Start first task is a separate function so it can be tested in isolation.
*/
void vPortStartFirstTask( void );
/*
* Exception handlers.
*/
void xPortPendSVHandler( void );
void vPortSVCHandler( void );
/*-----------------------------------------------------------*/
__asm void vPortSVCHandler( void )
{
/* This function is no longer used, but retained for backward
compatibility. */
}
/*-----------------------------------------------------------*/
__asm void vPortStartFirstTask( void )
{
PRESERVE8
EXTERN __Vectors
/* Use the NVIC offset register to locate the stack. */
ldr r0, =__Vectors
ldr r0, [r0]
/* Set the msp back to the start of the stack. */
msr msp, r0
ldr r3, =pxCurrentTCB /* Obtain location of pxCurrentTCB. */
ldr r1, [r3]
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
adds r0, #32 /* Discard everything up to r0. */
msr psp, r0 /* This is now the new top of stack to use in the task. */
movs r0, #2 /* Switch to the psp stack. */
msr CONTROL, r0
pop {r0-r5} /* Pop the registers that are saved automatically. */
mov lr, r5 /* lr is now in r5. */
cpsie i /* The first task has its context and interrupts can be enabled. */
pop {pc} /* Finally, pop the PC to jump to the user defined task code. */
ALIGN
}
/*-----------------------------------------------------------*/
__asm void xPortPendSVHandler( void )
{
extern vPortSafeTaskSwitchContext
extern pxCurrentTCB
PRESERVE8
mrs r0, psp
ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */
ldr r2, [r3]
subs r0, #32 /* Make space for the remaining low registers. */
str r0, [r2] /* Save the new top of stack. */
stmia r0!, {r4-r7} /* Store the low registers that are not saved automatically. */
mov r4, r8 /* Store the high registers. */
mov r5, r9
mov r6, r10
mov r7, r11
stmia r0!, {r4-r7}
push {r3, r14}
bl vPortSafeTaskSwitchContext
pop {r2, r3} /* lr goes in r3. r2 now holds tcb pointer. */
ldr r1, [r2]
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
adds r0, #16 /* Move to the high registers. */
ldmia r0!, {r4-r7} /* Pop the high registers. */
mov r8, r4
mov r9, r5
mov r10, r6
mov r11, r7
msr psp, r0 /* Remember the new top of stack for the task. */
subs r0, #32 /* Go back for the low registers that are not automatically restored. */
ldmia r0!, {r4-r7} /* Pop low registers. */
bx r3
ALIGN
}
/*-----------------------------------------------------------*/

View File

@@ -0,0 +1,34 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#include "portmacro_cmsis.h"
#endif /* PORTMACRO_H */

View File

@@ -0,0 +1,153 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM CM4F port.
*----------------------------------------------------------*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
/*
* Start first task is a separate function so it can be tested in isolation.
*/
void vPortStartFirstTask( void );
/*
* Exception handlers.
*/
void xPortPendSVHandler( void );
void vPortSVCHandler( void );
/*-----------------------------------------------------------*/
__asm void vPortSVCHandler( void )
{
PRESERVE8
/* Get the location of the current TCB. */
ldr r3, =pxCurrentTCB
ldr r1, [r3]
ldr r0, [r1]
/* Pop the core registers. */
ldmia r0!, {r4-r11, r14}
msr psp, r0
isb
mov r0, #0
msr basepri, r0
bx r14
}
/*-----------------------------------------------------------*/
__asm void vPortStartFirstTask( void )
{
PRESERVE8
EXTERN __Vectors
/* Use the NVIC offset register to locate the stack. */
ldr r0, =__Vectors
ldr r0, [r0]
/* Set the msp back to the start of the stack. */
msr msp, r0
/* Globally enable interrupts. */
cpsie i
cpsie f
dsb
isb
#ifdef SOFTDEVICE_PRESENT
/* Block kernel interrupts only (PendSV) before calling SVC */
mov r0, #(configKERNEL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
msr basepri, r0
#endif
/* Call SVC to start the first task. */
svc 0
ALIGN
}
/*-----------------------------------------------------------*/
__asm void xPortPendSVHandler( void )
{
extern uxCriticalNesting;
extern pxCurrentTCB;
extern vTaskSwitchContext;
PRESERVE8
mrs r0, psp
isb
/* Get the location of the current TCB. */
ldr r3, =pxCurrentTCB
ldr r2, [r3]
/* Is the task using the FPU context? If so, push high vfp registers. */
tst r14, #0x10
it eq
vstmdbeq r0!, {s16-s31}
/* Save the core registers. */
stmdb r0!, {r4-r11, r14}
/* Save the new top of stack into the first member of the TCB. */
str r0, [r2]
stmdb sp!, {r3}
mov r0, #(configMAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
msr basepri, r0
dsb
isb
bl vTaskSwitchContext
mov r0, #0
msr basepri, r0
ldmia sp!, {r3}
/* The first item in pxCurrentTCB is the task top of stack. */
ldr r1, [r3]
ldr r0, [r1]
/* Pop the core registers. */
ldmia r0!, {r4-r11, r14}
/* Is the task using the FPU context? If so, pop the high vfp registers
too. */
tst r14, #0x10
it eq
vldmiaeq r0!, {s16-s31}
msr psp, r0
isb
bx r14
ALIGN
}
/*-----------------------------------------------------------*/

View File

@@ -0,0 +1,34 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#include "portmacro_cmsis.h"
#endif /* PORTMACRO_H */

View File

@@ -0,0 +1,243 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM CM0 port.
*----------------------------------------------------------*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#ifdef SOFTDEVICE_PRESENT
#include "nrf_soc.h"
#endif
/* Make sure that all elements in isr state fits in uint32_t element*/
#include "portmacro_cmsis.h"
STATIC_ASSERT(sizeof(portISRState_t) == sizeof(uint32_t));
/* Constants used for assertion check of the selected CPU */
#define portCORTEX_M0_r0p0_ID ( 0x410CC200UL )
/* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
/* Constants required to set up the initial stack. */
#define portINITIAL_XPSR (((xPSR_Type){.b.T = 1}).w)
#define portINITIAL_EXEC_RETURN ( 0xfffffffd )
/* Let the user override the pre-loading of the initial LR with the address of
prvTaskExitError() in case is messes up unwinding of the stack in the
debugger. */
#ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else
#define portTASK_RETURN_ADDRESS prvTaskExitError
#endif
/* Each task maintains its own interrupt status in the critical nesting
variable. */
static UBaseType_t uxCriticalNesting = 0;
#ifdef SOFTDEVICE_PRESENT
/* Flag that is set when yielding should be done after critical section exiting */
static UBaseType_t uxYieldFlag = 0;
#endif
/*
* Setup the timer to generate the tick interrupts. The implementation in this
* file is weak to allow application writers to change the timer used to
* generate the tick interrupt.
*/
extern void vPortSetupTimerInterrupt( void );
/*
* Exception handlers.
*/
void xPortSysTickHandler( void );
/*
* Start first task is a separate function so it can be tested in isolation.
*/
extern void vPortStartFirstTask( void );
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{
/* Simulate the stack frame as it would be created by a context switch
interrupt. */
/* Offset added to account for the way the MCU uses the stack on entry/exit
of interrupts, and to ensure alignment. */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
/* Save code space by skipping register initialisation. */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
static void prvTaskExitError( void )
{
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS();
for ( ;; );
}
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
BaseType_t xPortStartScheduler( void )
{
/* This port can be used only on Cortex-M0 processor */
configASSERT( SCB->CPUID == portCORTEX_M0_r0p0_ID );
/* Make PendSV the lowest priority interrupts. */
NVIC_SetPriority(PendSV_IRQn, configKERNEL_INTERRUPT_PRIORITY);
/* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */
vPortSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0;
/* Finally this port requires SEVONPEND to be active */
SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
/* Start the first task. */
vPortStartFirstTask();
/* Should never get here as the tasks will now be executing! Call the task
exit error function to prevent compiler warnings about a static function
not being called in the case that the application writer overrides this
functionality by defining configTASK_RETURN_ADDRESS. */
prvTaskExitError();
/* Should not get here! */
return 0;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL );
}
/*-----------------------------------------------------------*/
void vPortTaskYield( void )
{
#ifdef SOFTDEVICE_PRESENT
if (uxCriticalNesting > 0)
{
uxYieldFlag = 1;
}
else
{
portPendSVSchedule();
}
#else
portPendSVSchedule();
#endif
}
/*-----------------------------------------------------------*/
void vPortEnterCritical( void )
{
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */
if ( uxCriticalNesting == 1 )
{
configASSERT( ( SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk ) == 0 );
}
}
/*-----------------------------------------------------------*/
void vPortExitCritical( void )
{
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if ( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
#ifdef SOFTDEVICE_PRESENT
if (uxYieldFlag)
{
uxYieldFlag = 0;
portPendSVSchedule();
}
#endif
}
}
/*-----------------------------------------------------------*/
void vPortSafeTaskSwitchContext( void )
{
uint32_t isrstate = portSET_INTERRUPT_MASK_FROM_ISR();
vTaskSwitchContext();
portCLEAR_INTERRUPT_MASK_FROM_ISR(isrstate);
}

View File

@@ -0,0 +1,233 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM CM0 port.
* CMSIS compatible layer to menage SysTick ticking source.
*----------------------------------------------------------*/
#if configTICK_SOURCE == FREERTOS_USE_SYSTICK
#error NRF51 does not support SysTick module
/*-----------------------------------------------------------*/
#elif configTICK_SOURCE == FREERTOS_USE_RTC
#if configUSE_16_BIT_TICKS == 1
#error This port does not support 16 bit ticks.
#endif
#include "nrf_rtc.h"
#include "nrf_drv_clock.h"
/*-----------------------------------------------------------*/
void xPortSysTickHandler( void )
{
#if configUSE_TICKLESS_IDLE == 1
nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
#endif
BaseType_t switch_req = pdFALSE;
uint32_t isrstate = portSET_INTERRUPT_MASK_FROM_ISR();
uint32_t systick_counter = nrf_rtc_counter_get(portNRF_RTC_REG);
nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_TICK);
if (configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG == 0)
{
/* check FreeRTOSConfig.h file for more details on configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG */
TickType_t diff;
diff = (systick_counter - xTaskGetTickCount()) & portNRF_RTC_MAXTICKS;
/* At most 1 step if scheduler is suspended - the xTaskIncrementTick
* would return the tick state from the moment when suspend function was called. */
if ((diff > 1) && (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING))
{
diff = 1;
}
while ((diff--) > 0)
{
switch_req |= xTaskIncrementTick();
}
}
else
{
switch_req = xTaskIncrementTick();
}
/* Increment the RTOS tick as usual which checks if there is a need for rescheduling */
if ( switch_req != pdFALSE )
{
/* A context switch is required. Context switching is performed in
the PendSV interrupt. Pend the PendSV interrupt. */
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
__SEV();
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( isrstate );
}
/*
* Setup the RTC time to generate the tick interrupts at the required
* frequency.
*/
void vPortSetupTimerInterrupt( void )
{
/* Request LF clock */
nrf_drv_clock_lfclk_request(NULL);
/* Configure SysTick to interrupt at the requested rate. */
nrf_rtc_prescaler_set(portNRF_RTC_REG, portNRF_RTC_PRESCALER);
nrf_rtc_int_enable (portNRF_RTC_REG, RTC_INTENSET_TICK_Msk);
nrf_rtc_task_trigger (portNRF_RTC_REG, NRF_RTC_TASK_CLEAR);
nrf_rtc_task_trigger (portNRF_RTC_REG, NRF_RTC_TASK_START);
nrf_rtc_event_enable(portNRF_RTC_REG, RTC_EVTEN_OVRFLW_Msk);
NVIC_SetPriority(portNRF_RTC_IRQn, configKERNEL_INTERRUPT_PRIORITY);
NVIC_EnableIRQ(portNRF_RTC_IRQn);
}
#if configUSE_TICKLESS_IDLE == 1
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
/*
* Implementation note:
*
* To help debugging the option configUSE_TICKLESS_IDLE_SIMPLE_DEBUG was presented.
* This option would make sure that even if program execution was stopped inside
* this function no more than expected number of ticks would be skipped.
*
* Normally RTC works all the time even if firmware execution was stopped
* and that may lead to skipping too much of ticks.
*/
TickType_t enterTime;
/* Make sure the SysTick reload value does not overflow the counter. */
if ( xExpectedIdleTime > portNRF_RTC_MAXTICKS - configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
{
xExpectedIdleTime = portNRF_RTC_MAXTICKS - configEXPECTED_IDLE_TIME_BEFORE_SLEEP;
}
/* Block all the interrupts globally */
#ifdef SOFTDEVICE_PRESENT
do{
uint8_t dummy = 0;
uint32_t err_code = sd_nvic_critical_region_enter(&dummy);
APP_ERROR_CHECK(err_code);
}while (0);
#else
__disable_irq();
#endif
/* Configure CTC interrupt */
enterTime = nrf_rtc_counter_get(portNRF_RTC_REG);
if ( eTaskConfirmSleepModeStatus() != eAbortSleep )
{
TickType_t xModifiableIdleTime;
TickType_t wakeupTime = (enterTime + xExpectedIdleTime) & portNRF_RTC_MAXTICKS;
/* Stop tick events */
nrf_rtc_int_disable(portNRF_RTC_REG, NRF_RTC_INT_TICK_MASK);
/* Configure CTC interrupt */
nrf_rtc_cc_set(portNRF_RTC_REG, 0, wakeupTime);
nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
nrf_rtc_int_enable(portNRF_RTC_REG, NRF_RTC_INT_COMPARE0_MASK);
__DSB();
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
* set its parameter to 0 to indicate that its implementation contains
* its own wait for interrupt or wait for event instruction, and so wfi
* should not be executed again. However, the original expected idle
* time variable must remain unmodified, so a copy is taken. */
xModifiableIdleTime = xExpectedIdleTime;
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
if ( xModifiableIdleTime > 0 )
{
#ifdef SOFTDEVICE_PRESENT
uint32_t err_code = sd_app_evt_wait();
APP_ERROR_CHECK(err_code);
#else
/* No SD - we would just block interrupts globally.
* BASEPRI cannot be used for that because it would prevent WFE from wake up.
*/
do{
__WFE();
} while (0 == (NVIC->ISPR[0]));
#endif
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
nrf_rtc_int_disable(portNRF_RTC_REG, NRF_RTC_INT_COMPARE0_MASK);
nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
/* Correct the system ticks */
{
TickType_t diff;
TickType_t exitTime;
nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_TICK);
nrf_rtc_int_enable (portNRF_RTC_REG, NRF_RTC_INT_TICK_MASK);
exitTime = nrf_rtc_counter_get(portNRF_RTC_REG);
diff = (exitTime - enterTime) & portNRF_RTC_MAXTICKS;
/* It is important that we clear pending here so that our corrections are latest and in sync with tick_interrupt handler */
NVIC_ClearPendingIRQ(portNRF_RTC_IRQn);
if ((configUSE_TICKLESS_IDLE_SIMPLE_DEBUG) && (diff > xExpectedIdleTime))
{
diff = xExpectedIdleTime;
}
if (diff > 0)
{
vTaskStepTick(diff);
}
}
}
#ifdef SOFTDEVICE_PRESENT
uint32_t err_code = sd_nvic_critical_region_exit(0);
APP_ERROR_CHECK(err_code);
#else
__enable_irq();
#endif
}
#endif // configUSE_TICKLESS_IDLE
#else // configTICK_SOURCE
#error Unsupported configTICK_SOURCE value
#endif // configTICK_SOURCE == FREERTOS_USE_SYSTICK

View File

@@ -0,0 +1,216 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef PORTMACRO_CMSIS_H
#define PORTMACRO_CMSIS_H
#include "app_util.h"
#include "nordic_common.h"
#ifdef SOFTDEVICE_PRESENT
#include "nrf_soc.h"
#include "softdevice_handler.h"
#include "app_error.h"
#include "app_util_platform.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the
* given hardware and compiler.
*
* These settings should not be altered.
*-----------------------------------------------------------
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef uint32_t UBaseType_t; /* to provide compatibility with CMSIS */
#if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1
#endif
/*-----------------------------------------------------------*/
/* Architecture specifics. */
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8
/* RTC register */
#define portNRF_RTC_REG NRF_RTC1
/* IRQn used by the selected RTC */
#define portNRF_RTC_IRQn RTC1_IRQn
/* Constants required to manipulate the NVIC. */
#define portNRF_RTC_PRESCALER ( (uint32_t) (ROUNDED_DIV(configSYSTICK_CLOCK_HZ, configTICK_RATE_HZ) - 1) )
/* Maximum RTC ticks */
#define portNRF_RTC_MAXTICKS ((1U<<24)-1U)
/*-----------------------------------------------------------*/
/* Internal auxiliary macro */
#define portPendSVSchedule() do \
{ \
/* Set a PendSV to request a context switch. */ \
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; \
__SEV(); \
/* Barriers are normally not required but do ensure the code is completely \
within the specified behaviour for the architecture. */ \
__DSB(); \
__ISB(); \
}while (0)
/* Scheduler utilities. */
#define portYIELD() vPortTaskYield()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if ( (xSwitchRequired) != pdFALSE ) { portPendSVSchedule(); }
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/
/* Critical section management. */
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
extern void vPortTaskYield( void );
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortDisableISR()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortRestoreISR(x)
#define portDISABLE_INTERRUPTS() vPortDisableISR()
#define portENABLE_INTERRUPTS() vPortEnableISR()
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are
not necessary for to use this port. They are defined so the common demo files
(which build with all the ports) will build. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/*-----------------------------------------------------------*/
/* Tickless idle/low power functionality. */
#ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif
/*-----------------------------------------------------------*/
__STATIC_INLINE void vPortDisableISR(void)
{
#ifdef SOFTDEVICE_PRESENT
uint8_t dummy = 0;
uint32_t err_code = sd_nvic_critical_region_enter(&dummy);
APP_ERROR_CHECK(err_code);
#else
__disable_irq();
#endif
}
__STATIC_INLINE void vPortEnableISR(void)
{
#ifdef SOFTDEVICE_PRESENT
uint32_t err_code = sd_nvic_critical_region_exit(0);
APP_ERROR_CHECK(err_code);
#else
__enable_irq();
#endif
}
/* Union used to remember current ISR state.
* It concentrates information about ISR state and internal SD state into 32 bit variable. */
typedef union
{
uint32_t u32; //< 32 bit access to the variable
uint8_t sd_nested; //< Soft device nested element
bool irq_nested; //< Global was disabled
}portISRState_t;
__STATIC_INLINE uint32_t ulPortDisableISR(void)
{
portISRState_t isrs = {0};
#ifdef SOFTDEVICE_PRESENT
uint32_t err_code = sd_nvic_critical_region_enter(&isrs.sd_nested);
APP_ERROR_CHECK(err_code);
#else
uint32_t primask = __get_PRIMASK();
if(primask == 0)
{
__disable_irq();
}
else
{
isrs.irq_nested = true;
}
#endif
return isrs.u32;
}
__STATIC_INLINE void vPortRestoreISR(uint32_t state)
{
portISRState_t isrs = {state};
#ifdef SOFTDEVICE_PRESENT
uint32_t err_code = sd_nvic_critical_region_exit(isrs.sd_nested);
APP_ERROR_CHECK(err_code);
#else
if(!isrs.irq_nested)
{
__enable_irq();
}
#endif
}
/*-----------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_CMSIS_H */

View File

@@ -0,0 +1,357 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM CM4F port.
*----------------------------------------------------------*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#ifdef SOFTDEVICE_PRESENT
#include "nrf_soc.h"
#include "app_util.h"
#include "app_util_platform.h"
#endif
#if !(__FPU_USED) && !(__LINT__)
#error This port can only be used when the project options are configured to enable hardware floating point support.
#endif
#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
#endif
/* Constants used to detect a Cortex-M7 r0p1 core, which should use the ARM_CM7
r0p1 port. */
#define portCORTEX_M4_r0p1_ID ( 0x410FC241UL )
/* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
/* Constants required to set up the initial stack. */
#define portINITIAL_XPSR (((xPSR_Type){.b.T = 1}).w)
#define portINITIAL_EXEC_RETURN ( 0xfffffffd )
/* Let the user override the pre-loading of the initial LR with the address of
prvTaskExitError() in case is messes up unwinding of the stack in the
debugger. */
#ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else
#define portTASK_RETURN_ADDRESS prvTaskExitError
#endif
/* Each task maintains its own interrupt status in the critical nesting
variable. */
static UBaseType_t uxCriticalNesting = 0;
/*
* Setup the timer to generate the tick interrupts. The implementation in this
* file is weak to allow application writers to change the timer used to
* generate the tick interrupt.
*/
extern void vPortSetupTimerInterrupt( void );
/*
* Exception handlers.
*/
void xPortSysTickHandler( void );
/*
* Start first task is a separate function so it can be tested in isolation.
*/
extern void vPortStartFirstTask( void );
/*
* Function to enable the VFP.
*/
static void vPortEnableVFP( void );
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
/*
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
* FreeRTOS API functions are not called from interrupts that have been assigned
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
*/
#if ( configASSERT_DEFINED == 1 )
static uint8_t ucMaxSysCallPriority = 0;
static uint32_t ulMaxPRIGROUPValue = 0;
#endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{
/* Simulate the stack frame as it would be created by a context switch
interrupt. */
/* Offset added to account for the way the MCU uses the stack on entry/exit
of interrupts, and to ensure alignment. */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
/* Save code space by skipping register initialisation. */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
/* A save method is being used that requires each task to maintain its
own exec return value. */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_EXEC_RETURN;
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
static void prvTaskExitError( void )
{
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS();
for ( ;; );
}
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
BaseType_t xPortStartScheduler( void )
{
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
/* This port is designed for nRF52, this is Cortex-M4 r0p1. */
configASSERT( SCB->CPUID == portCORTEX_M4_r0p1_ID );
#if ( configASSERT_DEFINED == 1 )
{
volatile uint32_t ulOriginalPriority;
volatile uint8_t * const pucFirstUserPriorityRegister = &NVIC->IP[0];
volatile uint8_t ucMaxPriorityValue;
/* Determine the maximum priority from which ISR safe FreeRTOS API
functions can be called. ISR safe functions are those that end in
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
ensure interrupt entry is as fast and simple as possible.
Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to all
possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
/* Use the same mask on the maximum system call priority. */
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
/* Calculate the maximum acceptable priority group value for the number
of bits read back. */
ulMaxPRIGROUPValue = SCB_AIRCR_PRIGROUP_Msk >> SCB_AIRCR_PRIGROUP_Pos;
while ( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{
ulMaxPRIGROUPValue--;
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
}
/* Remove any bits that are more than actually existing. */
ulMaxPRIGROUPValue &= SCB_AIRCR_PRIGROUP_Msk >> SCB_AIRCR_PRIGROUP_Pos;
/* Restore the clobbered interrupt priority register to its original
value. */
*pucFirstUserPriorityRegister = ulOriginalPriority;
}
#endif /* conifgASSERT_DEFINED */
/* Make PendSV the lowest priority interrupts. */
NVIC_SetPriority(PendSV_IRQn, configKERNEL_INTERRUPT_PRIORITY);
/* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */
vPortSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0;
/* Ensure the VFP is enabled - it should be anyway. */
vPortEnableVFP();
/* Lazy save always. */
FPU->FPCCR |= FPU_FPCCR_ASPEN_Msk | FPU_FPCCR_LSPEN_Msk;
/* Finally this port requires SEVONPEND to be active */
SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
/* Start the first task. */
vPortStartFirstTask();
/* Should never get here as the tasks will now be executing! Call the task
exit error function to prevent compiler warnings about a static function
not being called in the case that the application writer overrides this
functionality by defining configTASK_RETURN_ADDRESS. */
prvTaskExitError();
/* Should not get here! */
return 0;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL );
}
/*-----------------------------------------------------------*/
void vPortEnterCritical( void )
{
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */
if ( uxCriticalNesting == 1 )
{
configASSERT( ( SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk ) == 0 );
}
}
/*-----------------------------------------------------------*/
void vPortExitCritical( void )
{
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if ( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
}
}
/*-----------------------------------------------------------*/
/* This is a naked function. */
static void vPortEnableVFP( void )
{
SCB->CPACR |= 0xf << 20;
}
/*-----------------------------------------------------------*/
#if ( configASSERT_DEFINED == 1 )
void vPortValidateInterruptPriority( void )
{
uint32_t ulCurrentInterrupt;
uint8_t ucCurrentPriority;
IPSR_Type ipsr;
/* Obtain the number of the currently executing interrupt. */
ipsr.w = __get_IPSR();
ulCurrentInterrupt = ipsr.b.ISR;
/* Is the interrupt number a user defined interrupt? */
if ( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
{
/* Look up the interrupt's priority. */
ucCurrentPriority = NVIC->IP[ ulCurrentInterrupt - portFIRST_USER_INTERRUPT_NUMBER ];
/* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY.
Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than
configMAX_SYSCALL_INTERRUPT_PRIORITY.
Interrupts that use the FreeRTOS API must not be left at their
default priority of zero as that is the highest possible priority,
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
and therefore also guaranteed to be invalid.
FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible.
The following links provide detailed information:
http://www.freertos.org/RTOS-Cortex-M3-M4.html
http://www.freertos.org/FAQHelp.html */
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
}
/* Priority grouping: The interrupt controller (NVIC) allows the bits
that define each interrupt's priority to be split between bits that
define the interrupt's pre-emption priority bits and bits that define
the interrupt's sub-priority. For simplicity all bits must be defined
to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority).
If the application only uses CMSIS libraries for interrupt
configuration then the correct setting can be achieved on all Cortex-M
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredicable behaviour. */
configASSERT( NVIC_GetPriorityGrouping() <= ulMaxPRIGROUPValue );
}
#endif /* configASSERT_DEFINED */

View File

@@ -0,0 +1,297 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "app_util.h"
#ifdef SOFTDEVICE_PRESENT
#include "nrf_soc.h"
#include "nrf_sdh.h"
#include "app_error.h"
#include "app_util_platform.h"
#endif
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM CM4F port.
* CMSIS compatible layer to menage SysTick ticking source.
*----------------------------------------------------------*/
#if configTICK_SOURCE == FREERTOS_USE_SYSTICK
#ifndef configSYSTICK_CLOCK_HZ
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
/* Ensure the SysTick is clocked at the same frequency as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( SysTick_CTRL_CLKSOURCE_Msk )
#else
/* The way the SysTick is clocked is not modified in case it is not the same
as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
#endif
#if configUSE_TICKLESS_IDLE == 1
#error SysTick port for RF52 does not support tickless idle. Use RTC mode instead.
#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
void xPortSysTickHandler( void )
{
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
executes all interrupts must be unmasked. There is therefore no need to
save and then restore the interrupt mask value as its value is already
known. */
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
{
/* Increment the RTOS tick. */
if ( xTaskIncrementTick() != pdFALSE )
{
/* A context switch is required. Context switching is performed in
the PendSV interrupt. Pend the PendSV interrupt. */
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
__SEV();
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
}
/*-----------------------------------------------------------*/
/*
* Setup the systick timer to generate the tick interrupts at the required
* frequency.
*/
void vPortSetupTimerInterrupt( void )
{
/* Set interrupt priority */
NVIC_SetPriority(SysTick_IRQn, configKERNEL_INTERRUPT_PRIORITY);
/* Configure SysTick to interrupt at the requested rate. */
SysTick->LOAD = ROUNDED_DIV(configSYSTICK_CLOCK_HZ, configTICK_RATE_HZ) - 1UL;
SysTick->CTRL = ( portNVIC_SYSTICK_CLK_BIT | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk );
}
/*-----------------------------------------------------------*/
#elif configTICK_SOURCE == FREERTOS_USE_RTC
#if configUSE_16_BIT_TICKS == 1
#error This port does not support 16 bit ticks.
#endif
#include "nrf_rtc.h"
#include "nrf_drv_clock.h"
/*-----------------------------------------------------------*/
void xPortSysTickHandler( void )
{
#if configUSE_TICKLESS_IDLE == 1
nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
#endif
BaseType_t switch_req = pdFALSE;
uint32_t isrstate = portSET_INTERRUPT_MASK_FROM_ISR();
uint32_t systick_counter = nrf_rtc_counter_get(portNRF_RTC_REG);
nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_TICK);
if (configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG == 0)
{
/* check FreeRTOSConfig.h file for more details on configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG */
TickType_t diff;
diff = (systick_counter - xTaskGetTickCount()) & portNRF_RTC_MAXTICKS;
/* At most 1 step if scheduler is suspended - the xTaskIncrementTick
* would return the tick state from the moment when suspend function was called. */
if ((diff > 1) && (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING))
{
diff = 1;
}
while ((diff--) > 0)
{
switch_req |= xTaskIncrementTick();
}
}
else
{
switch_req = xTaskIncrementTick();
}
/* Increment the RTOS tick as usual which checks if there is a need for rescheduling */
if ( switch_req != pdFALSE )
{
/* A context switch is required. Context switching is performed in
the PendSV interrupt. Pend the PendSV interrupt. */
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
__SEV();
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( isrstate );
}
/*
* Setup the RTC time to generate the tick interrupts at the required
* frequency.
*/
void vPortSetupTimerInterrupt( void )
{
/* Request LF clock */
nrf_drv_clock_lfclk_request(NULL);
/* Configure SysTick to interrupt at the requested rate. */
nrf_rtc_prescaler_set(portNRF_RTC_REG, portNRF_RTC_PRESCALER);
nrf_rtc_int_enable (portNRF_RTC_REG, RTC_INTENSET_TICK_Msk);
nrf_rtc_task_trigger (portNRF_RTC_REG, NRF_RTC_TASK_CLEAR);
nrf_rtc_task_trigger (portNRF_RTC_REG, NRF_RTC_TASK_START);
nrf_rtc_event_enable(portNRF_RTC_REG, RTC_EVTEN_OVRFLW_Msk);
NVIC_SetPriority(portNRF_RTC_IRQn, configKERNEL_INTERRUPT_PRIORITY);
NVIC_EnableIRQ(portNRF_RTC_IRQn);
}
#if configUSE_TICKLESS_IDLE == 1
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
/*
* Implementation note:
*
* To help debugging the option configUSE_TICKLESS_IDLE_SIMPLE_DEBUG was presented.
* This option would make sure that even if program execution was stopped inside
* this function no more than expected number of ticks would be skipped.
*
* Normally RTC works all the time even if firmware execution was stopped
* and that may lead to skipping too much of ticks.
*/
TickType_t enterTime;
/* Make sure the SysTick reload value does not overflow the counter. */
if ( xExpectedIdleTime > portNRF_RTC_MAXTICKS - configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
{
xExpectedIdleTime = portNRF_RTC_MAXTICKS - configEXPECTED_IDLE_TIME_BEFORE_SLEEP;
}
/* Block all the interrupts globally */
#ifdef SOFTDEVICE_PRESENT
do{
uint8_t dummy = 0;
uint32_t err_code = sd_nvic_critical_region_enter(&dummy);
APP_ERROR_CHECK(err_code);
}while (0);
#else
__disable_irq();
#endif
enterTime = nrf_rtc_counter_get(portNRF_RTC_REG);
if ( eTaskConfirmSleepModeStatus() != eAbortSleep )
{
TickType_t xModifiableIdleTime;
TickType_t wakeupTime = (enterTime + xExpectedIdleTime) & portNRF_RTC_MAXTICKS;
/* Stop tick events */
nrf_rtc_int_disable(portNRF_RTC_REG, NRF_RTC_INT_TICK_MASK);
/* Configure CTC interrupt */
nrf_rtc_cc_set(portNRF_RTC_REG, 0, wakeupTime);
nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
nrf_rtc_int_enable(portNRF_RTC_REG, NRF_RTC_INT_COMPARE0_MASK);
__DSB();
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
* set its parameter to 0 to indicate that its implementation contains
* its own wait for interrupt or wait for event instruction, and so wfi
* should not be executed again. However, the original expected idle
* time variable must remain unmodified, so a copy is taken. */
xModifiableIdleTime = xExpectedIdleTime;
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
if ( xModifiableIdleTime > 0 )
{
#ifdef SOFTDEVICE_PRESENT
if (nrf_sdh_is_enabled())
{
uint32_t err_code = sd_app_evt_wait();
APP_ERROR_CHECK(err_code);
}
else
#endif
{
/* No SD - we would just block interrupts globally.
* BASEPRI cannot be used for that because it would prevent WFE from wake up.
*/
do{
__WFE();
} while (0 == (NVIC->ISPR[0] | NVIC->ISPR[1]));
}
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
nrf_rtc_int_disable(portNRF_RTC_REG, NRF_RTC_INT_COMPARE0_MASK);
nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
/* Correct the system ticks */
{
TickType_t diff;
TickType_t exitTime;
nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_TICK);
nrf_rtc_int_enable (portNRF_RTC_REG, NRF_RTC_INT_TICK_MASK);
exitTime = nrf_rtc_counter_get(portNRF_RTC_REG);
diff = (exitTime - enterTime) & portNRF_RTC_MAXTICKS;
/* It is important that we clear pending here so that our corrections are latest and in sync with tick_interrupt handler */
NVIC_ClearPendingIRQ(portNRF_RTC_IRQn);
if ((configUSE_TICKLESS_IDLE_SIMPLE_DEBUG) && (diff > xExpectedIdleTime))
{
diff = xExpectedIdleTime;
}
if (diff > 0)
{
vTaskStepTick(diff);
}
}
}
#ifdef SOFTDEVICE_PRESENT
uint32_t err_code = sd_nvic_critical_region_exit(0);
APP_ERROR_CHECK(err_code);
#else
__enable_irq();
#endif
}
#endif // configUSE_TICKLESS_IDLE
#else // configTICK_SOURCE
#error Unsupported configTICK_SOURCE value
#endif // configTICK_SOURCE == FREERTOS_USE_SYSTICK

View File

@@ -0,0 +1,187 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef PORTMACRO_CMSIS_H
#define PORTMACRO_CMSIS_H
#include "app_util.h"
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the
* given hardware and compiler.
*
* These settings should not be altered.
*-----------------------------------------------------------
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef uint32_t UBaseType_t; /* to provide compatibility with CMSIS */
#if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1
#endif
/*-----------------------------------------------------------*/
/* Architecture specifics. */
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8
/* RTC register */
#define portNRF_RTC_REG NRF_RTC1
/* IRQn used by the selected RTC */
#define portNRF_RTC_IRQn RTC1_IRQn
/* Constants required to manipulate the NVIC. */
#define portNRF_RTC_PRESCALER ( (uint32_t) (ROUNDED_DIV(configSYSTICK_CLOCK_HZ, configTICK_RATE_HZ) - 1) )
/* Maximum RTC ticks */
#define portNRF_RTC_MAXTICKS ((1U<<24)-1U)
/*-----------------------------------------------------------*/
/* Scheduler utilities. */
#define portYIELD() do \
{ \
/* Set a PendSV to request a context switch. */ \
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; \
__SEV(); \
/* Barriers are normally not required but do ensure the code is completely \
within the specified behaviour for the architecture. */ \
__DSB(); \
__ISB(); \
}while (0)
#define portEND_SWITCHING_ISR( xSwitchRequired ) if ( (xSwitchRequired) != pdFALSE ) portYIELD()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/
/* Critical section management. */
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are
not necessary for to use this port. They are defined so the common demo files
(which build with all the ports) will build. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/*-----------------------------------------------------------*/
/* Tickless idle/low power functionality. */
#ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif
/*-----------------------------------------------------------*/
/* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Count leading zeros helper. */
#define ucPortCountLeadingZeros( bits ) __CLZ( bits )
/* Check the configuration. */
#if ( configMAX_PRIORITIES > 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif
/* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/*-----------------------------------------------------------*/
#ifdef configASSERT
void vPortValidateInterruptPriority( void );
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
#endif
/*-----------------------------------------------------------*/
#define vPortSetBASEPRI( ulNewMaskValue ) __set_BASEPRI(ulNewMaskValue)
/*-----------------------------------------------------------*/
#define vPortRaiseBASEPRI( ) vPortSetBASEPRI(configMAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
/*-----------------------------------------------------------*/
__STATIC_INLINE uint32_t ulPortRaiseBASEPRI( void )
{
uint32_t ulOriginalBASEPRI = __get_BASEPRI();
vPortRaiseBASEPRI();
return ulOriginalBASEPRI;
}
/*-----------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_CMSIS_H */

View File

@@ -0,0 +1,134 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM CM0 port.
*----------------------------------------------------------*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
/*
* Start first task is a separate function so it can be tested in isolation.
*/
void vPortStartFirstTask( void ) __attribute__ (( naked ));
/*
* Exception handlers.
*/
void vPortSVCHandler( void );
void xPortPendSVHandler( void ) __attribute__ (( naked ));
/*-----------------------------------------------------------*/
void vPortStartFirstTask( void )
{
__asm volatile(
" .syntax unified \n"
" \n"
#if defined(__SES_ARM)
" ldr r0, =_vectors \n" /* Locate the stack using _vectors table. */
#else
" ldr r0, =__isr_vector \n" /* Locate the stack using __isr_vector table. */
#endif
" ldr r0, [r0] \n"
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
" \n"
" ldr r3, =pxCurrentTCB \n" /* Obtain location of pxCurrentTCB. */
" ldr r1, [r3] \n"
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" adds r0, #32 \n" /* Discard everything up to r0 */
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
" movs r0, #2 \n" /* Switch to the psp stack. */
" msr CONTROL, r0 \n"
" pop {r0-r5} \n" /* Pop the registers that are saved automatically. */
" mov lr, r5 \n" /* lr is now in r5. */
" cpsie i \n" /* The first task has its context and interrupts can be enabled. */
" pop {pc} \n" /* Finally, pop the PC to jump to the user defined task code. */
" \n"
" .align 2 \n"
);
}
/*-----------------------------------------------------------*/
void vPortSVCHandler( void )
{
/* This function is no longer used, but retained for backward
compatibility. */
}
/*-----------------------------------------------------------*/
void xPortPendSVHandler( void )
{
/* This is a naked function. */
__asm volatile
(
" .syntax unified \n"
" \n"
" mrs r0, psp \n"
" \n"
" ldr r3, =pxCurrentTCB \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n"
" \n"
" subs r0, #32 \n" /* Make space for the remaining low registers. */
" str r0, [r2] \n" /* Save the new top of stack. */
" stmia r0!, {r4-r7} \n" /* Store the low registers that are not saved automatically. */
" mov r4, r8 \n" /* Store the high registers. */
" mov r5, r9 \n"
" mov r6, r10 \n"
" mov r7, r11 \n"
" stmia r0!, {r4-r7} \n"
" \n"
" push {r3, r14} \n"
" bl vPortSafeTaskSwitchContext \n"
" pop {r2, r3} \n" /* lr goes in r3. r2 now holds tcb pointer. */
" \n"
" ldr r1, [r2] \n"
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" adds r0, #16 \n" /* Move to the high registers. */
" ldmia r0!, {r4-r7} \n" /* Pop the high registers. */
" mov r8, r4 \n"
" mov r9, r5 \n"
" mov r10, r6 \n"
" mov r11, r7 \n"
" \n"
" msr psp, r0 \n" /* Remember the new top of stack for the task. */
" \n"
" subs r0, #32 \n" /* Go back for the low registers that are not automatically restored. */
" ldmia r0!, {r4-r7} \n" /* Pop low registers. */
" \n"
" bx r3 \n"
" \n"
" .align 2 \n"
);
}

View File

@@ -0,0 +1,36 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#include "portmacro_cmsis.h"
#endif /* PORTMACRO_H */

View File

@@ -0,0 +1,148 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM CM4F port.
*----------------------------------------------------------*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
/*
* Start first task is a separate function so it can be tested in isolation.
*/
void vPortStartFirstTask( void ) __attribute__ (( naked ));
/*
* Exception handlers.
*/
void vPortSVCHandler( void ) __attribute__ (( naked ));
void xPortPendSVHandler( void ) __attribute__ (( naked ));
/*-----------------------------------------------------------*/
void vPortStartFirstTask( void )
{
__asm volatile(
#if defined(__SES_ARM)
" ldr r0, =_vectors \n" /* Locate the stack using _vectors table. */
#else
" ldr r0, =__isr_vector \n" /* Locate the stack using __isr_vector table. */
#endif
" ldr r0, [r0] \n"
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
" cpsie i \n" /* Globally enable interrupts. */
" cpsie f \n"
" dsb \n"
" isb \n"
#ifdef SOFTDEVICE_PRESENT
/* Block kernel interrupts only (PendSV) before calling SVC */
" mov r0, %0 \n"
" msr basepri, r0 \n"
#endif
" svc 0 \n" /* System call to start first task. */
" \n"
" .align 2 \n"
#ifdef SOFTDEVICE_PRESENT
::"i"(configKERNEL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
#endif
);
}
/*-----------------------------------------------------------*/
void vPortSVCHandler( void )
{
__asm volatile (
" ldr r3, =pxCurrentTCB \n" /* Restore the context. */
" ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
" msr psp, r0 \n" /* Restore the task stack pointer. */
" isb \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
" bx r14 \n"
" \n"
" .align 2 \n"
);
}
/*-----------------------------------------------------------*/
void xPortPendSVHandler( void )
{
/* This is a naked function. */
__asm volatile
(
" mrs r0, psp \n"
" isb \n"
" \n"
" ldr r3, =pxCurrentTCB \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n"
" \n"
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */
" it eq \n"
" vstmdbeq r0!, {s16-s31} \n"
" \n"
" stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */
" \n"
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
" \n"
" stmdb sp!, {r3} \n"
" mov r0, %0 \n"
" msr basepri, r0 \n"
" dsb \n"
" isb \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
" ldmia sp!, {r3} \n"
" \n"
" ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldr r0, [r1] \n"
" \n"
" ldmia r0!, {r4-r11, r14} \n" /* Pop the core registers. */
" \n"
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */
" it eq \n"
" vldmiaeq r0!, {s16-s31} \n"
" \n"
" msr psp, r0 \n"
" isb \n"
" \n"
" \n"
" bx r14 \n"
" \n"
" .align 2 \n"
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
);
}

View File

@@ -0,0 +1,36 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#include "portmacro_cmsis.h"
#endif /* PORTMACRO_H */

View File

@@ -0,0 +1,148 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM CM0 port.
*----------------------------------------------------------*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
/*
* Start first task is a separate function so it can be tested in isolation.
*/
__stackless void vPortStartFirstTask( void );
/*
* Exception handlers.
*/
void vPortSVCHandler( void );
__stackless void xPortPendSVHandler( void );
/*
* The real object type has no meaning here - we would just use its addresses inside assembly
*/
extern uint32_t __Vectors;
extern uint32_t pxCurrentTCB;
/*-----------------------------------------------------------*/
__stackless void vPortStartFirstTask( void )
{
__asm volatile(
" ldr r0, 1f \n" /* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
" \n"
" ldr r3, 2f \n" /* Obtain location of pxCurrentTCB. */
" ldr r1, [r3] \n"
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" adds r0, #32 \n" /* Discard everything up to r0 */
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
" movs r0, #2 \n" /* Switch to the psp stack. */
" msr CONTROL, r0 \n"
" pop {r0-r5} \n" /* Pop the registers that are saved automatically. */
" mov lr, r5 \n" /* lr is now in r5. */
" cpsie i \n" /* The first task has its context and interrupts can be enabled. */
" pop {pc} \n" /* Finally, pop the PC to jump to the user defined task code. */
" \n"
" nop \n" /* Manual alignment of the label below */
"DATA \n"
"1: \n"
" DC32 %c0 \n"
"2: \n"
" DC32 %c1 \n"
: /* Outputs */
: /* Inputs */
"i"(&__Vectors),
"i"(&pxCurrentTCB)
);
}
/*-----------------------------------------------------------*/
void vPortSVCHandler( void )
{
/* This function is no longer used, but retained for backward
compatibility. */
}
/*-----------------------------------------------------------*/
__stackless void xPortPendSVHandler( void )
{
/* This is a naked function. */
__asm volatile
(
" mrs r0, psp \n"
" \n"
" ldr r3, 1f \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n"
" \n"
" subs r0, #32 \n" /* Make space for the remaining low registers. */
" str r0, [r2] \n" /* Save the new top of stack. */
" stmia r0!, {r4-r7} \n" /* Store the low registers that are not saved automatically. */
" mov r4, r8 \n" /* Store the high registers. */
" mov r5, r9 \n"
" mov r6, r10 \n"
" mov r7, r11 \n"
" stmia r0!, {r4-r7} \n"
" \n"
" push {r3, r14} \n"
" bl %c1 \n"
" pop {r2, r3} \n" /* lr goes in r3. r2 now holds tcb pointer. */
" \n"
" ldr r1, [r2] \n"
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" adds r0, #16 \n" /* Move to the high registers. */
" ldmia r0!, {r4-r7} \n" /* Pop the high registers. */
" mov r8, r4 \n"
" mov r9, r5 \n"
" mov r10, r6 \n"
" mov r11, r7 \n"
" \n"
" msr psp, r0 \n" /* Remember the new top of stack for the task. */
" \n"
" subs r0, #32 \n" /* Go back for the low registers that are not automatically restored. */
" ldmia r0!, {r4-r7} \n" /* Pop low registers. */
" \n"
" bx r3 \n"
" \n"
" nop \n" /* Manual alignment of the label below */
"DATA \n"
"1: \n"
" DC32 %c0 \n"
: /* Outputs */
: /* Inputs */
"i"(&pxCurrentTCB),
"i"(&vTaskSwitchContext)
);
}

View File

@@ -0,0 +1,40 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#include "portmacro_cmsis.h"
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
the source code because to do so would cause other compilers to generate
warnings. */
#pragma diag_suppress=Pe191
#pragma diag_suppress=Pa082
#endif /* PORTMACRO_H */

View File

@@ -0,0 +1,168 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM CM4F port.
*----------------------------------------------------------*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
/*
* Start first task is a separate function so it can be tested in isolation.
*/
__stackless void vPortStartFirstTask( void );
/*
* Exception handlers.
*/
__stackless void vPortSVCHandler( void );
__stackless void xPortPendSVHandler( void );
extern uint32_t __Vectors;
extern uint32_t pxCurrentTCB;
/*-----------------------------------------------------------*/
__stackless void vPortStartFirstTask( void )
{
__asm volatile(
" ldr.n r0, 1f \n" /* Locate the stack using __Vectors table. */
" ldr r0, [r0] \n"
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
" cpsie i \n" /* Globally enable interrupts. */
" cpsie f \n"
" dsb \n"
" isb \n"
#ifdef SOFTDEVICE_PRESENT
/* Block kernel interrupts only (PendSV) before calling SVC */
" mov r0, %1 \n"
" msr basepri, r0 \n"
#endif
" svc 0 \n" /* System call to start first task. */
" \n"
" nop \n" /* Manual alignment of the label below */
"DATA \n"
"1: \n"
" DC32 %c0 \n"
: /* Outputs */
: /* Inputs */
"i"(&__Vectors)
#ifdef SOFTDEVICE_PRESENT
,
"i"(configKERNEL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
#endif
);
}
/*-----------------------------------------------------------*/
__stackless void vPortSVCHandler( void )
{
__asm volatile (
" ldr.n r3, 1f \n" /* Restore the context. */
" ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
" msr psp, r0 \n" /* Restore the task stack pointer. */
" isb \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
" bx r14 \n"
" \n"
" \n" /* Manual alignment of the label below */
"DATA \n"
"1: \n"
" DC32 %c0 \n"
: /* Outputs */
: /* Inputs */
"i"(&pxCurrentTCB)
);
}
/*-----------------------------------------------------------*/
__stackless void xPortPendSVHandler( void )
{
/* This is a naked function. */
__asm volatile
(
" mrs r0, psp \n"
" isb \n"
" \n"
" ldr.n r3, 1f \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n"
" \n"
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */
" it eq \n"
" vstmdbeq r0!, {s16-s31} \n"
" \n"
" stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */
" \n"
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
" \n"
" stmdb sp!, {r3} \n"
" mov r0, %0 \n"
" msr basepri, r0 \n"
" dsb \n"
" isb \n"
" bl %c2 \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
" ldmia sp!, {r3} \n"
" \n"
" ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldr r0, [r1] \n"
" \n"
" ldmia r0!, {r4-r11, r14} \n" /* Pop the core registers. */
" \n"
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */
" it eq \n"
" vldmiaeq r0!, {s16-s31} \n"
" \n"
" msr psp, r0 \n"
" isb \n"
" \n"
" \n"
" bx r14 \n"
" \n"
" \n" /* Manual alignment of the label below */
"DATA \n"
"1: \n"
" DC32 %c1 \n"
: /* Outputs */
: /* Inputs */
"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)),
"i"(&pxCurrentTCB),
"i"(&vTaskSwitchContext)
);
}

View File

@@ -0,0 +1,41 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#include "portmacro_cmsis.h"
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
the source code because to do so would cause other compilers to generate
warnings. */
#pragma diag_suppress=Pe191
#pragma diag_suppress=Pa082
#endif /* PORTMACRO_H */

12
external/freertos/readme.txt vendored Normal file
View File

@@ -0,0 +1,12 @@
Implementations detail.
No changes to original FreeRTOS code was made.
Directories was reorganized to move all changed or optional items outside the original, copied code.
That way just copying new version of FreeRTOS should give functional code.
Folders:
- source: Original Source directory from FreeRTOS. Deleted all port files from portable subdirectory.
In portable subdirectory only MemMang was left.
- license: Original License directory from FreeRTOS.
- config: Base (clean) FreeRTOS configuration file.
- portable: Port files created for nrf5x microcontroller.

354
external/freertos/source/croutine.c vendored Normal file
View File

@@ -0,0 +1,354 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#include "FreeRTOS.h"
#include "task.h"
#include "croutine.h"
/* Remove the whole file is co-routines are not being used. */
#if( configUSE_CO_ROUTINES != 0 )
/*
* Some kernel aware debuggers require data to be viewed to be global, rather
* than file scope.
*/
#ifdef portREMOVE_STATIC_QUALIFIER
#define static
#endif
/* Lists for ready and blocked co-routines. --------------------*/
static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */
static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */
static List_t xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */
static List_t * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */
static List_t * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
static List_t xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */
/* Other file private variables. --------------------------------*/
CRCB_t * pxCurrentCoRoutine = NULL;
static UBaseType_t uxTopCoRoutineReadyPriority = 0;
static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0;
/* The initial state of the co-routine when it is created. */
#define corINITIAL_STATE ( 0 )
/*
* Place the co-routine represented by pxCRCB into the appropriate ready queue
* for the priority. It is inserted at the end of the list.
*
* This macro accesses the co-routine ready lists and therefore must not be
* used from within an ISR.
*/
#define prvAddCoRoutineToReadyQueue( pxCRCB ) \
{ \
if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \
{ \
uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \
} \
vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \
}
/*
* Utility to ready all the lists used by the scheduler. This is called
* automatically upon the creation of the first co-routine.
*/
static void prvInitialiseCoRoutineLists( void );
/*
* Co-routines that are readied by an interrupt cannot be placed directly into
* the ready lists (there is no mutual exclusion). Instead they are placed in
* in the pending ready list in order that they can later be moved to the ready
* list by the co-routine scheduler.
*/
static void prvCheckPendingReadyList( void );
/*
* Macro that looks at the list of co-routines that are currently delayed to
* see if any require waking.
*
* Co-routines are stored in the queue in the order of their wake time -
* meaning once one co-routine has been found whose timer has not expired
* we need not look any further down the list.
*/
static void prvCheckDelayedList( void );
/*-----------------------------------------------------------*/
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex )
{
BaseType_t xReturn;
CRCB_t *pxCoRoutine;
/* Allocate the memory that will store the co-routine control block. */
pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );
if( pxCoRoutine )
{
/* If pxCurrentCoRoutine is NULL then this is the first co-routine to
be created and the co-routine data structures need initialising. */
if( pxCurrentCoRoutine == NULL )
{
pxCurrentCoRoutine = pxCoRoutine;
prvInitialiseCoRoutineLists();
}
/* Check the priority is within limits. */
if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES )
{
uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1;
}
/* Fill out the co-routine control block from the function parameters. */
pxCoRoutine->uxState = corINITIAL_STATE;
pxCoRoutine->uxPriority = uxPriority;
pxCoRoutine->uxIndex = uxIndex;
pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode;
/* Initialise all the other co-routine control block parameters. */
vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) );
vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
/* Set the co-routine control block as a link back from the ListItem_t.
This is so we can get back to the containing CRCB from a generic item
in a list. */
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
/* Event lists are always in priority order. */
listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) );
/* Now the co-routine has been initialised it can be added to the ready
list at the correct priority. */
prvAddCoRoutineToReadyQueue( pxCoRoutine );
xReturn = pdPASS;
}
else
{
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
}
return xReturn;
}
/*-----------------------------------------------------------*/
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList )
{
TickType_t xTimeToWake;
/* Calculate the time to wake - this may overflow but this is
not a problem. */
xTimeToWake = xCoRoutineTickCount + xTicksToDelay;
/* We must remove ourselves from the ready list before adding
ourselves to the blocked list as the same list item is used for
both lists. */
( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
/* The list item will be inserted in wake time order. */
listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake );
if( xTimeToWake < xCoRoutineTickCount )
{
/* Wake time has overflowed. Place this item in the
overflow list. */
vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
}
else
{
/* The wake time has not overflowed, so we can use the
current block list. */
vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
}
if( pxEventList )
{
/* Also add the co-routine to an event list. If this is done then the
function must be called with interrupts disabled. */
vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) );
}
}
/*-----------------------------------------------------------*/
static void prvCheckPendingReadyList( void )
{
/* Are there any co-routines waiting to get moved to the ready list? These
are co-routines that have been readied by an ISR. The ISR cannot access
the ready lists itself. */
while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
{
CRCB_t *pxUnblockedCRCB;
/* The pending ready list can be accessed by an ISR. */
portDISABLE_INTERRUPTS();
{
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) );
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
}
portENABLE_INTERRUPTS();
( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) );
prvAddCoRoutineToReadyQueue( pxUnblockedCRCB );
}
}
/*-----------------------------------------------------------*/
static void prvCheckDelayedList( void )
{
CRCB_t *pxCRCB;
xPassedTicks = xTaskGetTickCount() - xLastTickCount;
while( xPassedTicks )
{
xCoRoutineTickCount++;
xPassedTicks--;
/* If the tick count has overflowed we need to swap the ready lists. */
if( xCoRoutineTickCount == 0 )
{
List_t * pxTemp;
/* Tick count has overflowed so we need to swap the delay lists. If there are
any items in pxDelayedCoRoutineList here then there is an error! */
pxTemp = pxDelayedCoRoutineList;
pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList;
pxOverflowDelayedCoRoutineList = pxTemp;
}
/* See if this tick has made a timeout expire. */
while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE )
{
pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList );
if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) )
{
/* Timeout not yet expired. */
break;
}
portDISABLE_INTERRUPTS();
{
/* The event could have occurred just before this critical
section. If this is the case then the generic list item will
have been moved to the pending ready list and the following
line is still valid. Also the pvContainer parameter will have
been set to NULL so the following lines are also valid. */
( void ) uxListRemove( &( pxCRCB->xGenericListItem ) );
/* Is the co-routine waiting on an event also? */
if( pxCRCB->xEventListItem.pvContainer )
{
( void ) uxListRemove( &( pxCRCB->xEventListItem ) );
}
}
portENABLE_INTERRUPTS();
prvAddCoRoutineToReadyQueue( pxCRCB );
}
}
xLastTickCount = xCoRoutineTickCount;
}
/*-----------------------------------------------------------*/
void vCoRoutineSchedule( void )
{
/* See if any co-routines readied by events need moving to the ready lists. */
prvCheckPendingReadyList();
/* See if any delayed co-routines have timed out. */
prvCheckDelayedList();
/* Find the highest priority queue that contains ready co-routines. */
while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) )
{
if( uxTopCoRoutineReadyPriority == 0 )
{
/* No more co-routines to check. */
return;
}
--uxTopCoRoutineReadyPriority;
}
/* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines
of the same priority get an equal share of the processor time. */
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) );
/* Call the co-routine. */
( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex );
return;
}
/*-----------------------------------------------------------*/
static void prvInitialiseCoRoutineLists( void )
{
UBaseType_t uxPriority;
for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ )
{
vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) );
}
vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 );
vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 );
vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList );
/* Start with pxDelayedCoRoutineList using list1 and the
pxOverflowDelayedCoRoutineList using list2. */
pxDelayedCoRoutineList = &xDelayedCoRoutineList1;
pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2;
}
/*-----------------------------------------------------------*/
BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList )
{
CRCB_t *pxUnblockedCRCB;
BaseType_t xReturn;
/* This function is called from within an interrupt. It can only access
event lists and the pending ready list. This function assumes that a
check has already been made to ensure pxEventList is not empty. */
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority )
{
xReturn = pdTRUE;
}
else
{
xReturn = pdFALSE;
}
return xReturn;
}
#endif /* configUSE_CO_ROUTINES == 0 */

739
external/freertos/source/event_groups.c vendored Normal file
View File

@@ -0,0 +1,739 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/* Standard includes. */
#include <stdlib.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
all the API functions to use the MPU wrappers. That should only be done when
task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "event_groups.h"
/* Lint e961 and e750 are suppressed as a MISRA exception justified because the
MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
header files above, but not in this file, in order to generate the correct
privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
/* The following bit fields convey control information in a task's event list
item value. It is important they don't clash with the
taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
#if configUSE_16_BIT_TICKS == 1
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
#define eventWAIT_FOR_ALL_BITS 0x0400U
#define eventEVENT_BITS_CONTROL_BYTES 0xff00U
#else
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL
#define eventWAIT_FOR_ALL_BITS 0x04000000UL
#define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
#endif
typedef struct xEventGroupDefinition
{
EventBits_t uxEventBits;
List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
#if( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxEventGroupNumber;
#endif
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
#endif
} EventGroup_t;
/*-----------------------------------------------------------*/
/*
* Test the bits set in uxCurrentEventBits to see if the wait condition is met.
* The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is
* pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
* are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the
* wait condition is met if any of the bits set in uxBitsToWait for are also set
* in uxCurrentEventBits.
*/
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
/*-----------------------------------------------------------*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer )
{
EventGroup_t *pxEventBits;
/* A StaticEventGroup_t object must be provided. */
configASSERT( pxEventGroupBuffer );
#if( configASSERT_DEFINED == 1 )
{
/* Sanity check that the size of the structure used to declare a
variable of type StaticEventGroup_t equals the size of the real
event group structure. */
volatile size_t xSize = sizeof( StaticEventGroup_t );
configASSERT( xSize == sizeof( EventGroup_t ) );
}
#endif /* configASSERT_DEFINED */
/* The user has provided a statically allocated event group - use it. */
pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 EventGroup_t and StaticEventGroup_t are guaranteed to have the same size and alignment requirement - checked by configASSERT(). */
if( pxEventBits != NULL )
{
pxEventBits->uxEventBits = 0;
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
{
/* Both static and dynamic allocation can be used, so note that
this event group was created statically in case the event group
is later deleted. */
pxEventBits->ucStaticallyAllocated = pdTRUE;
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
traceEVENT_GROUP_CREATE( pxEventBits );
}
else
{
traceEVENT_GROUP_CREATE_FAILED();
}
return ( EventGroupHandle_t ) pxEventBits;
}
#endif /* configSUPPORT_STATIC_ALLOCATION */
/*-----------------------------------------------------------*/
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
EventGroupHandle_t xEventGroupCreate( void )
{
EventGroup_t *pxEventBits;
/* Allocate the event group. */
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
if( pxEventBits != NULL )
{
pxEventBits->uxEventBits = 0;
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
{
/* Both static and dynamic allocation can be used, so note this
event group was allocated statically in case the event group is
later deleted. */
pxEventBits->ucStaticallyAllocated = pdFALSE;
}
#endif /* configSUPPORT_STATIC_ALLOCATION */
traceEVENT_GROUP_CREATE( pxEventBits );
}
else
{
traceEVENT_GROUP_CREATE_FAILED();
}
return ( EventGroupHandle_t ) pxEventBits;
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait )
{
EventBits_t uxOriginalBitValue, uxReturn;
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
BaseType_t xAlreadyYielded;
BaseType_t xTimeoutOccurred = pdFALSE;
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
configASSERT( uxBitsToWaitFor != 0 );
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
{
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
}
#endif
vTaskSuspendAll();
{
uxOriginalBitValue = pxEventBits->uxEventBits;
( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
{
/* All the rendezvous bits are now set - no need to block. */
uxReturn = ( uxOriginalBitValue | uxBitsToSet );
/* Rendezvous always clear the bits. They will have been cleared
already unless this is the only task in the rendezvous. */
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
xTicksToWait = 0;
}
else
{
if( xTicksToWait != ( TickType_t ) 0 )
{
traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
/* Store the bits that the calling task is waiting for in the
task's event list item so the kernel knows when a match is
found. Then enter the blocked state. */
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
/* This assignment is obsolete as uxReturn will get set after
the task unblocks, but some compilers mistakenly generate a
warning about uxReturn being returned without being set if the
assignment is omitted. */
uxReturn = 0;
}
else
{
/* The rendezvous bits were not set, but no block time was
specified - just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits;
xTimeoutOccurred = pdTRUE;
}
}
}
xAlreadyYielded = xTaskResumeAll();
if( xTicksToWait != ( TickType_t ) 0 )
{
if( xAlreadyYielded == pdFALSE )
{
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* The task blocked to wait for its required bits to be set - at this
point either the required bits were set or the block time expired. If
the required bits were set they will have been stored in the task's
event list item, and they should now be retrieved then cleared. */
uxReturn = uxTaskResetEventItemValue();
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
{
/* The task timed out, just return the current event bit value. */
taskENTER_CRITICAL();
{
uxReturn = pxEventBits->uxEventBits;
/* Although the task got here because it timed out before the
bits it was waiting for were set, it is possible that since it
unblocked another task has set the bits. If this is the case
then it needs to clear the bits before exiting. */
if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
{
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL();
xTimeoutOccurred = pdTRUE;
}
else
{
/* The task unblocked because the bits were set. */
}
/* Control bits might be set as the task had blocked should not be
returned. */
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
}
traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
/* Prevent compiler warnings when trace macros are not used. */
( void ) xTimeoutOccurred;
return uxReturn;
}
/*-----------------------------------------------------------*/
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
{
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
EventBits_t uxReturn, uxControlBits = 0;
BaseType_t xWaitConditionMet, xAlreadyYielded;
BaseType_t xTimeoutOccurred = pdFALSE;
/* Check the user is not attempting to wait on the bits used by the kernel
itself, and that at least one bit is being requested. */
configASSERT( xEventGroup );
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
configASSERT( uxBitsToWaitFor != 0 );
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
{
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
}
#endif
vTaskSuspendAll();
{
const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
/* Check to see if the wait condition is already met or not. */
xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
if( xWaitConditionMet != pdFALSE )
{
/* The wait condition has already been met so there is no need to
block. */
uxReturn = uxCurrentEventBits;
xTicksToWait = ( TickType_t ) 0;
/* Clear the wait bits if requested to do so. */
if( xClearOnExit != pdFALSE )
{
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else if( xTicksToWait == ( TickType_t ) 0 )
{
/* The wait condition has not been met, but no block time was
specified, so just return the current value. */
uxReturn = uxCurrentEventBits;
xTimeoutOccurred = pdTRUE;
}
else
{
/* The task is going to block to wait for its required bits to be
set. uxControlBits are used to remember the specified behaviour of
this call to xEventGroupWaitBits() - for use when the event bits
unblock the task. */
if( xClearOnExit != pdFALSE )
{
uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
if( xWaitForAllBits != pdFALSE )
{
uxControlBits |= eventWAIT_FOR_ALL_BITS;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Store the bits that the calling task is waiting for in the
task's event list item so the kernel knows when a match is
found. Then enter the blocked state. */
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
/* This is obsolete as it will get set after the task unblocks, but
some compilers mistakenly generate a warning about the variable
being returned without being set if it is not done. */
uxReturn = 0;
traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
}
}
xAlreadyYielded = xTaskResumeAll();
if( xTicksToWait != ( TickType_t ) 0 )
{
if( xAlreadyYielded == pdFALSE )
{
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* The task blocked to wait for its required bits to be set - at this
point either the required bits were set or the block time expired. If
the required bits were set they will have been stored in the task's
event list item, and they should now be retrieved then cleared. */
uxReturn = uxTaskResetEventItemValue();
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
{
taskENTER_CRITICAL();
{
/* The task timed out, just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits;
/* It is possible that the event bits were updated between this
task leaving the Blocked state and running again. */
if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
{
if( xClearOnExit != pdFALSE )
{
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
xTimeoutOccurred = pdTRUE;
}
taskEXIT_CRITICAL();
}
else
{
/* The task unblocked because the bits were set. */
}
/* The task blocked so control bits may have been set. */
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
}
traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
/* Prevent compiler warnings when trace macros are not used. */
( void ) xTimeoutOccurred;
return uxReturn;
}
/*-----------------------------------------------------------*/
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
{
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
EventBits_t uxReturn;
/* Check the user is not attempting to clear the bits used by the kernel
itself. */
configASSERT( xEventGroup );
configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
taskENTER_CRITICAL();
{
traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
/* The value returned is the event group value prior to the bits being
cleared. */
uxReturn = pxEventBits->uxEventBits;
/* Clear the bits. */
pxEventBits->uxEventBits &= ~uxBitsToClear;
}
taskEXIT_CRITICAL();
return uxReturn;
}
/*-----------------------------------------------------------*/
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
{
BaseType_t xReturn;
traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
{
UBaseType_t uxSavedInterruptStatus;
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
EventBits_t uxReturn;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
uxReturn = pxEventBits->uxEventBits;
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
return uxReturn;
}
/*-----------------------------------------------------------*/
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
{
ListItem_t *pxListItem, *pxNext;
ListItem_t const *pxListEnd;
List_t *pxList;
EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
BaseType_t xMatchFound = pdFALSE;
/* Check the user is not attempting to set the bits used by the kernel
itself. */
configASSERT( xEventGroup );
configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
pxList = &( pxEventBits->xTasksWaitingForBits );
pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
vTaskSuspendAll();
{
traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
pxListItem = listGET_HEAD_ENTRY( pxList );
/* Set the bits. */
pxEventBits->uxEventBits |= uxBitsToSet;
/* See if the new bit value should unblock any tasks. */
while( pxListItem != pxListEnd )
{
pxNext = listGET_NEXT( pxListItem );
uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
xMatchFound = pdFALSE;
/* Split the bits waited for from the control bits. */
uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
{
/* Just looking for single bit being set. */
if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
{
xMatchFound = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
{
/* All bits are set. */
xMatchFound = pdTRUE;
}
else
{
/* Need all bits to be set, but not all the bits were set. */
}
if( xMatchFound != pdFALSE )
{
/* The bits match. Should the bits be cleared on exit? */
if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
{
uxBitsToClear |= uxBitsWaitedFor;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Store the actual event flag value in the task's event list
item before removing the task from the event list. The
eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
that is was unblocked due to its required bits matching, rather
than because it timed out. */
vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
}
/* Move onto the next list item. Note pxListItem->pxNext is not
used here as the list item may have been removed from the event list
and inserted into the ready/pending reading list. */
pxListItem = pxNext;
}
/* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
bit was set in the control word. */
pxEventBits->uxEventBits &= ~uxBitsToClear;
}
( void ) xTaskResumeAll();
return pxEventBits->uxEventBits;
}
/*-----------------------------------------------------------*/
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
{
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
vTaskSuspendAll();
{
traceEVENT_GROUP_DELETE( xEventGroup );
while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
{
/* Unblock the task, returning 0 as the event list is being deleted
and cannot therefore have any bits set. */
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
}
#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
{
/* The event group can only have been allocated dynamically - free
it again. */
vPortFree( pxEventBits );
}
#elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
{
/* The event group could have been allocated statically or
dynamically, so check before attempting to free the memory. */
if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
{
vPortFree( pxEventBits );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
}
( void ) xTaskResumeAll();
}
/*-----------------------------------------------------------*/
/* For internal use only - execute a 'set bits' command that was pended from
an interrupt. */
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet )
{
( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet );
}
/*-----------------------------------------------------------*/
/* For internal use only - execute a 'clear bits' command that was pended from
an interrupt. */
void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear )
{
( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear );
}
/*-----------------------------------------------------------*/
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits )
{
BaseType_t xWaitConditionMet = pdFALSE;
if( xWaitForAllBits == pdFALSE )
{
/* Task only has to wait for one bit within uxBitsToWaitFor to be
set. Is one already set? */
if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
{
xWaitConditionMet = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
/* Task has to wait for all the bits in uxBitsToWaitFor to be set.
Are they set already? */
if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
{
xWaitConditionMet = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
return xWaitConditionMet;
}
/*-----------------------------------------------------------*/
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken )
{
BaseType_t xReturn;
traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if (configUSE_TRACE_FACILITY == 1)
UBaseType_t uxEventGroupGetNumber( void* xEventGroup )
{
UBaseType_t xReturn;
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
if( xEventGroup == NULL )
{
xReturn = 0;
}
else
{
xReturn = pxEventBits->uxEventGroupNumber;
}
return xReturn;
}
#endif /* configUSE_TRACE_FACILITY */
/*-----------------------------------------------------------*/
#if ( configUSE_TRACE_FACILITY == 1 )
void vEventGroupSetNumber( void * xEventGroup, UBaseType_t uxEventGroupNumber )
{
( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber;
}
#endif /* configUSE_TRACE_FACILITY */
/*-----------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,134 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef STACK_MACROS_H
#define STACK_MACROS_H
#ifndef _MSC_VER /* Visual Studio doesn't support #warning. */
#warning The name of this file has changed to stack_macros.h. Please update your code accordingly. This source file (which has the original name) will be removed in future released.
#endif
/*
* Call the stack overflow hook function if the stack of the task being swapped
* out is currently overflowed, or looks like it might have overflowed in the
* past.
*
* Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check
* the current stack state only - comparing the current top of stack value to
* the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1
* will also cause the last few stack bytes to be checked to ensure the value
* to which the bytes were set when the task was created have not been
* overwritten. Note this second test does not guarantee that an overflowed
* stack will always be recognised.
*/
/*-----------------------------------------------------------*/
#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) )
/* Only the current stack state is to be checked. */
#define taskCHECK_FOR_STACK_OVERFLOW() \
{ \
/* Is the currently saved stack pointer within the stack limit? */ \
if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \
{ \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
} \
}
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
/*-----------------------------------------------------------*/
#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) )
/* Only the current stack state is to be checked. */
#define taskCHECK_FOR_STACK_OVERFLOW() \
{ \
\
/* Is the currently saved stack pointer within the stack limit? */ \
if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \
{ \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
} \
}
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
/*-----------------------------------------------------------*/
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
#define taskCHECK_FOR_STACK_OVERFLOW() \
{ \
const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \
const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; \
\
if( ( pulStack[ 0 ] != ulCheckValue ) || \
( pulStack[ 1 ] != ulCheckValue ) || \
( pulStack[ 2 ] != ulCheckValue ) || \
( pulStack[ 3 ] != ulCheckValue ) ) \
{ \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
} \
}
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
/*-----------------------------------------------------------*/
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
#define taskCHECK_FOR_STACK_OVERFLOW() \
{ \
int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \
static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \
\
\
pcEndOfStack -= sizeof( ucExpectedStackBytes ); \
\
/* Has the extremity of the task stack ever been written over? */ \
if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \
{ \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
} \
}
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
/*-----------------------------------------------------------*/
/* Remove stack overflow macro if not being used. */
#ifndef taskCHECK_FOR_STACK_OVERFLOW
#define taskCHECK_FOR_STACK_OVERFLOW()
#endif
#endif /* STACK_MACROS_H */

View File

@@ -0,0 +1,721 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef CO_ROUTINE_H
#define CO_ROUTINE_H
#ifndef INC_FREERTOS_H
#error "include FreeRTOS.h must appear in source files before include croutine.h"
#endif
#include "list.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Used to hide the implementation of the co-routine control block. The
control block structure however has to be included in the header due to
the macro implementation of the co-routine functionality. */
typedef void * CoRoutineHandle_t;
/* Defines the prototype to which co-routine functions must conform. */
typedef void (*crCOROUTINE_CODE)( CoRoutineHandle_t, UBaseType_t );
typedef struct corCoRoutineControlBlock
{
crCOROUTINE_CODE pxCoRoutineFunction;
ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */
ListItem_t xEventListItem; /*< List item used to place the CRCB in event lists. */
UBaseType_t uxPriority; /*< The priority of the co-routine in relation to other co-routines. */
UBaseType_t uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */
uint16_t uxState; /*< Used internally by the co-routine implementation. */
} CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */
/**
* croutine. h
*<pre>
BaseType_t xCoRoutineCreate(
crCOROUTINE_CODE pxCoRoutineCode,
UBaseType_t uxPriority,
UBaseType_t uxIndex
);</pre>
*
* Create a new co-routine and add it to the list of co-routines that are
* ready to run.
*
* @param pxCoRoutineCode Pointer to the co-routine function. Co-routine
* functions require special syntax - see the co-routine section of the WEB
* documentation for more information.
*
* @param uxPriority The priority with respect to other co-routines at which
* the co-routine will run.
*
* @param uxIndex Used to distinguish between different co-routines that
* execute the same function. See the example below and the co-routine section
* of the WEB documentation for further information.
*
* @return pdPASS if the co-routine was successfully created and added to a ready
* list, otherwise an error code defined with ProjDefs.h.
*
* Example usage:
<pre>
// Co-routine to be created.
void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
// This may not be necessary for const variables.
static const char cLedToFlash[ 2 ] = { 5, 6 };
static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
// Must start every co-routine with a call to crSTART();
crSTART( xHandle );
for( ;; )
{
// This co-routine just delays for a fixed period, then toggles
// an LED. Two co-routines are created using this function, so
// the uxIndex parameter is used to tell the co-routine which
// LED to flash and how int32_t to delay. This assumes xQueue has
// already been created.
vParTestToggleLED( cLedToFlash[ uxIndex ] );
crDELAY( xHandle, uxFlashRates[ uxIndex ] );
}
// Must end every co-routine with a call to crEND();
crEND();
}
// Function that creates two co-routines.
void vOtherFunction( void )
{
uint8_t ucParameterToPass;
TaskHandle_t xHandle;
// Create two co-routines at priority 0. The first is given index 0
// so (from the code above) toggles LED 5 every 200 ticks. The second
// is given index 1 so toggles LED 6 every 400 ticks.
for( uxIndex = 0; uxIndex < 2; uxIndex++ )
{
xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
}
}
</pre>
* \defgroup xCoRoutineCreate xCoRoutineCreate
* \ingroup Tasks
*/
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex );
/**
* croutine. h
*<pre>
void vCoRoutineSchedule( void );</pre>
*
* Run a co-routine.
*
* vCoRoutineSchedule() executes the highest priority co-routine that is able
* to run. The co-routine will execute until it either blocks, yields or is
* preempted by a task. Co-routines execute cooperatively so one
* co-routine cannot be preempted by another, but can be preempted by a task.
*
* If an application comprises of both tasks and co-routines then
* vCoRoutineSchedule should be called from the idle task (in an idle task
* hook).
*
* Example usage:
<pre>
// This idle task hook will schedule a co-routine each time it is called.
// The rest of the idle task will execute between co-routine calls.
void vApplicationIdleHook( void )
{
vCoRoutineSchedule();
}
// Alternatively, if you do not require any other part of the idle task to
// execute, the idle task hook can call vCoRoutineScheduler() within an
// infinite loop.
void vApplicationIdleHook( void )
{
for( ;; )
{
vCoRoutineSchedule();
}
}
</pre>
* \defgroup vCoRoutineSchedule vCoRoutineSchedule
* \ingroup Tasks
*/
void vCoRoutineSchedule( void );
/**
* croutine. h
* <pre>
crSTART( CoRoutineHandle_t xHandle );</pre>
*
* This macro MUST always be called at the start of a co-routine function.
*
* Example usage:
<pre>
// Co-routine to be created.
void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
static int32_t ulAVariable;
// Must start every co-routine with a call to crSTART();
crSTART( xHandle );
for( ;; )
{
// Co-routine functionality goes here.
}
// Must end every co-routine with a call to crEND();
crEND();
}</pre>
* \defgroup crSTART crSTART
* \ingroup Tasks
*/
#define crSTART( pxCRCB ) switch( ( ( CRCB_t * )( pxCRCB ) )->uxState ) { case 0:
/**
* croutine. h
* <pre>
crEND();</pre>
*
* This macro MUST always be called at the end of a co-routine function.
*
* Example usage:
<pre>
// Co-routine to be created.
void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
static int32_t ulAVariable;
// Must start every co-routine with a call to crSTART();
crSTART( xHandle );
for( ;; )
{
// Co-routine functionality goes here.
}
// Must end every co-routine with a call to crEND();
crEND();
}</pre>
* \defgroup crSTART crSTART
* \ingroup Tasks
*/
#define crEND() }
/*
* These macros are intended for internal use by the co-routine implementation
* only. The macros should not be used directly by application writers.
*/
#define crSET_STATE0( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2):
#define crSET_STATE1( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1):
/**
* croutine. h
*<pre>
crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );</pre>
*
* Delay a co-routine for a fixed period of time.
*
* crDELAY can only be called from the co-routine function itself - not
* from within a function called by the co-routine function. This is because
* co-routines do not maintain their own stack.
*
* @param xHandle The handle of the co-routine to delay. This is the xHandle
* parameter of the co-routine function.
*
* @param xTickToDelay The number of ticks that the co-routine should delay
* for. The actual amount of time this equates to is defined by
* configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_PERIOD_MS
* can be used to convert ticks to milliseconds.
*
* Example usage:
<pre>
// Co-routine to be created.
void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
// This may not be necessary for const variables.
// We are to delay for 200ms.
static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
// Must start every co-routine with a call to crSTART();
crSTART( xHandle );
for( ;; )
{
// Delay for 200ms.
crDELAY( xHandle, xDelayTime );
// Do something here.
}
// Must end every co-routine with a call to crEND();
crEND();
}</pre>
* \defgroup crDELAY crDELAY
* \ingroup Tasks
*/
#define crDELAY( xHandle, xTicksToDelay ) \
if( ( xTicksToDelay ) > 0 ) \
{ \
vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \
} \
crSET_STATE0( ( xHandle ) );
/**
* <pre>
crQUEUE_SEND(
CoRoutineHandle_t xHandle,
QueueHandle_t pxQueue,
void *pvItemToQueue,
TickType_t xTicksToWait,
BaseType_t *pxResult
)</pre>
*
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
*
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
* xQueueSend() and xQueueReceive() can only be used from tasks.
*
* crQUEUE_SEND can only be called from the co-routine function itself - not
* from within a function called by the co-routine function. This is because
* co-routines do not maintain their own stack.
*
* See the co-routine section of the WEB documentation for information on
* passing data between tasks and co-routines and between ISR's and
* co-routines.
*
* @param xHandle The handle of the calling co-routine. This is the xHandle
* parameter of the co-routine function.
*
* @param pxQueue The handle of the queue on which the data will be posted.
* The handle is obtained as the return value when the queue is created using
* the xQueueCreate() API function.
*
* @param pvItemToQueue A pointer to the data being posted onto the queue.
* The number of bytes of each queued item is specified when the queue is
* created. This number of bytes is copied from pvItemToQueue into the queue
* itself.
*
* @param xTickToDelay The number of ticks that the co-routine should block
* to wait for space to become available on the queue, should space not be
* available immediately. The actual amount of time this equates to is defined
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
* portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example
* below).
*
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if
* data was successfully posted onto the queue, otherwise it will be set to an
* error defined within ProjDefs.h.
*
* Example usage:
<pre>
// Co-routine function that blocks for a fixed period then posts a number onto
// a queue.
static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
static BaseType_t xNumberToPost = 0;
static BaseType_t xResult;
// Co-routines must begin with a call to crSTART().
crSTART( xHandle );
for( ;; )
{
// This assumes the queue has already been created.
crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
if( xResult != pdPASS )
{
// The message was not posted!
}
// Increment the number to be posted onto the queue.
xNumberToPost++;
// Delay for 100 ticks.
crDELAY( xHandle, 100 );
}
// Co-routines must end with a call to crEND().
crEND();
}</pre>
* \defgroup crQUEUE_SEND crQUEUE_SEND
* \ingroup Tasks
*/
#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \
{ \
*( pxResult ) = xQueueCRSend( ( pxQueue) , ( pvItemToQueue) , ( xTicksToWait ) ); \
if( *( pxResult ) == errQUEUE_BLOCKED ) \
{ \
crSET_STATE0( ( xHandle ) ); \
*pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \
} \
if( *pxResult == errQUEUE_YIELD ) \
{ \
crSET_STATE1( ( xHandle ) ); \
*pxResult = pdPASS; \
} \
}
/**
* croutine. h
* <pre>
crQUEUE_RECEIVE(
CoRoutineHandle_t xHandle,
QueueHandle_t pxQueue,
void *pvBuffer,
TickType_t xTicksToWait,
BaseType_t *pxResult
)</pre>
*
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
*
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
* xQueueSend() and xQueueReceive() can only be used from tasks.
*
* crQUEUE_RECEIVE can only be called from the co-routine function itself - not
* from within a function called by the co-routine function. This is because
* co-routines do not maintain their own stack.
*
* See the co-routine section of the WEB documentation for information on
* passing data between tasks and co-routines and between ISR's and
* co-routines.
*
* @param xHandle The handle of the calling co-routine. This is the xHandle
* parameter of the co-routine function.
*
* @param pxQueue The handle of the queue from which the data will be received.
* The handle is obtained as the return value when the queue is created using
* the xQueueCreate() API function.
*
* @param pvBuffer The buffer into which the received item is to be copied.
* The number of bytes of each queued item is specified when the queue is
* created. This number of bytes is copied into pvBuffer.
*
* @param xTickToDelay The number of ticks that the co-routine should block
* to wait for data to become available from the queue, should data not be
* available immediately. The actual amount of time this equates to is defined
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
* portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the
* crQUEUE_SEND example).
*
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if
* data was successfully retrieved from the queue, otherwise it will be set to
* an error code as defined within ProjDefs.h.
*
* Example usage:
<pre>
// A co-routine receives the number of an LED to flash from a queue. It
// blocks on the queue until the number is received.
static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
static BaseType_t xResult;
static UBaseType_t uxLEDToFlash;
// All co-routines must start with a call to crSTART().
crSTART( xHandle );
for( ;; )
{
// Wait for data to become available on the queue.
crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
if( xResult == pdPASS )
{
// We received the LED to flash - flash it!
vParTestToggleLED( uxLEDToFlash );
}
}
crEND();
}</pre>
* \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE
* \ingroup Tasks
*/
#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \
{ \
*( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), ( xTicksToWait ) ); \
if( *( pxResult ) == errQUEUE_BLOCKED ) \
{ \
crSET_STATE0( ( xHandle ) ); \
*( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), 0 ); \
} \
if( *( pxResult ) == errQUEUE_YIELD ) \
{ \
crSET_STATE1( ( xHandle ) ); \
*( pxResult ) = pdPASS; \
} \
}
/**
* croutine. h
* <pre>
crQUEUE_SEND_FROM_ISR(
QueueHandle_t pxQueue,
void *pvItemToQueue,
BaseType_t xCoRoutinePreviouslyWoken
)</pre>
*
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
* functions used by tasks.
*
* crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
* pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
* xQueueReceiveFromISR() can only be used to pass data between a task and and
* ISR.
*
* crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue
* that is being used from within a co-routine.
*
* See the co-routine section of the WEB documentation for information on
* passing data between tasks and co-routines and between ISR's and
* co-routines.
*
* @param xQueue The handle to the queue on which the item is to be posted.
*
* @param pvItemToQueue A pointer to the item that is to be placed on the
* queue. The size of the items the queue will hold was defined when the
* queue was created, so this many bytes will be copied from pvItemToQueue
* into the queue storage area.
*
* @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto
* the same queue multiple times from a single interrupt. The first call
* should always pass in pdFALSE. Subsequent calls should pass in
* the value returned from the previous call.
*
* @return pdTRUE if a co-routine was woken by posting onto the queue. This is
* used by the ISR to determine if a context switch may be required following
* the ISR.
*
* Example usage:
<pre>
// A co-routine that blocks on a queue waiting for characters to be received.
static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{
char cRxedChar;
BaseType_t xResult;
// All co-routines must start with a call to crSTART().
crSTART( xHandle );
for( ;; )
{
// Wait for data to become available on the queue. This assumes the
// queue xCommsRxQueue has already been created!
crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
// Was a character received?
if( xResult == pdPASS )
{
// Process the character here.
}
}
// All co-routines must end with a call to crEND().
crEND();
}
// An ISR that uses a queue to send characters received on a serial port to
// a co-routine.
void vUART_ISR( void )
{
char cRxedChar;
BaseType_t xCRWokenByPost = pdFALSE;
// We loop around reading characters until there are none left in the UART.
while( UART_RX_REG_NOT_EMPTY() )
{
// Obtain the character from the UART.
cRxedChar = UART_RX_REG;
// Post the character onto a queue. xCRWokenByPost will be pdFALSE
// the first time around the loop. If the post causes a co-routine
// to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
// In this manner we can ensure that if more than one co-routine is
// blocked on the queue only one is woken by this ISR no matter how
// many characters are posted to the queue.
xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
}
}</pre>
* \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR
* \ingroup Tasks
*/
#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) )
/**
* croutine. h
* <pre>
crQUEUE_SEND_FROM_ISR(
QueueHandle_t pxQueue,
void *pvBuffer,
BaseType_t * pxCoRoutineWoken
)</pre>
*
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
* functions used by tasks.
*
* crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
* pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
* xQueueReceiveFromISR() can only be used to pass data between a task and and
* ISR.
*
* crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data
* from a queue that is being used from within a co-routine (a co-routine
* posted to the queue).
*
* See the co-routine section of the WEB documentation for information on
* passing data between tasks and co-routines and between ISR's and
* co-routines.
*
* @param xQueue The handle to the queue on which the item is to be posted.
*
* @param pvBuffer A pointer to a buffer into which the received item will be
* placed. The size of the items the queue will hold was defined when the
* queue was created, so this many bytes will be copied from the queue into
* pvBuffer.
*
* @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become
* available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a
* co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise
* *pxCoRoutineWoken will remain unchanged.
*
* @return pdTRUE an item was successfully received from the queue, otherwise
* pdFALSE.
*
* Example usage:
<pre>
// A co-routine that posts a character to a queue then blocks for a fixed
// period. The character is incremented each time.
static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{
// cChar holds its value while this co-routine is blocked and must therefore
// be declared static.
static char cCharToTx = 'a';
BaseType_t xResult;
// All co-routines must start with a call to crSTART().
crSTART( xHandle );
for( ;; )
{
// Send the next character to the queue.
crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
if( xResult == pdPASS )
{
// The character was successfully posted to the queue.
}
else
{
// Could not post the character to the queue.
}
// Enable the UART Tx interrupt to cause an interrupt in this
// hypothetical UART. The interrupt will obtain the character
// from the queue and send it.
ENABLE_RX_INTERRUPT();
// Increment to the next character then block for a fixed period.
// cCharToTx will maintain its value across the delay as it is
// declared static.
cCharToTx++;
if( cCharToTx > 'x' )
{
cCharToTx = 'a';
}
crDELAY( 100 );
}
// All co-routines must end with a call to crEND().
crEND();
}
// An ISR that uses a queue to receive characters to send on a UART.
void vUART_ISR( void )
{
char cCharToTx;
BaseType_t xCRWokenByPost = pdFALSE;
while( UART_TX_REG_EMPTY() )
{
// Are there any characters in the queue waiting to be sent?
// xCRWokenByPost will automatically be set to pdTRUE if a co-routine
// is woken by the post - ensuring that only a single co-routine is
// woken no matter how many times we go around this loop.
if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
{
SEND_CHARACTER( cCharToTx );
}
}
}</pre>
* \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR
* \ingroup Tasks
*/
#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) )
/*
* This function is intended for internal use by the co-routine macros only.
* The macro nature of the co-routine implementation requires that the
* prototype appears here. The function should not be used by application
* writers.
*
* Removes the current co-routine from its ready list and places it in the
* appropriate delayed list.
*/
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList );
/*
* This function is intended for internal use by the queue implementation only.
* The function should not be used by application writers.
*
* Removes the highest priority co-routine from the event list and places it in
* the pending ready list.
*/
BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList );
#ifdef __cplusplus
}
#endif
#endif /* CO_ROUTINE_H */

View File

@@ -0,0 +1,280 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef DEPRECATED_DEFINITIONS_H
#define DEPRECATED_DEFINITIONS_H
/* Each FreeRTOS port has a unique portmacro.h header file. Originally a
pre-processor definition was used to ensure the pre-processor found the correct
portmacro.h file for the port being used. That scheme was deprecated in favour
of setting the compiler's include path such that it found the correct
portmacro.h file - removing the need for the constant and allowing the
portmacro.h file to be located anywhere in relation to the port being used. The
definitions below remain in the code for backward compatibility only. New
projects should not use them. */
#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT
#include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h"
typedef void ( __interrupt __far *pxISR )();
#endif
#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT
#include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h"
typedef void ( __interrupt __far *pxISR )();
#endif
#ifdef GCC_MEGA_AVR
#include "../portable/GCC/ATMega323/portmacro.h"
#endif
#ifdef IAR_MEGA_AVR
#include "../portable/IAR/ATMega323/portmacro.h"
#endif
#ifdef MPLAB_PIC24_PORT
#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
#endif
#ifdef MPLAB_DSPIC_PORT
#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
#endif
#ifdef MPLAB_PIC18F_PORT
#include "../../Source/portable/MPLAB/PIC18F/portmacro.h"
#endif
#ifdef MPLAB_PIC32MX_PORT
#include "../../Source/portable/MPLAB/PIC32MX/portmacro.h"
#endif
#ifdef _FEDPICC
#include "libFreeRTOS/Include/portmacro.h"
#endif
#ifdef SDCC_CYGNAL
#include "../../Source/portable/SDCC/Cygnal/portmacro.h"
#endif
#ifdef GCC_ARM7
#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
#endif
#ifdef GCC_ARM7_ECLIPSE
#include "portmacro.h"
#endif
#ifdef ROWLEY_LPC23xx
#include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
#endif
#ifdef IAR_MSP430
#include "..\..\Source\portable\IAR\MSP430\portmacro.h"
#endif
#ifdef GCC_MSP430
#include "../../Source/portable/GCC/MSP430F449/portmacro.h"
#endif
#ifdef ROWLEY_MSP430
#include "../../Source/portable/Rowley/MSP430F449/portmacro.h"
#endif
#ifdef ARM7_LPC21xx_KEIL_RVDS
#include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h"
#endif
#ifdef SAM7_GCC
#include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h"
#endif
#ifdef SAM7_IAR
#include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h"
#endif
#ifdef SAM9XE_IAR
#include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h"
#endif
#ifdef LPC2000_IAR
#include "..\..\Source\portable\IAR\LPC2000\portmacro.h"
#endif
#ifdef STR71X_IAR
#include "..\..\Source\portable\IAR\STR71x\portmacro.h"
#endif
#ifdef STR75X_IAR
#include "..\..\Source\portable\IAR\STR75x\portmacro.h"
#endif
#ifdef STR75X_GCC
#include "..\..\Source\portable\GCC\STR75x\portmacro.h"
#endif
#ifdef STR91X_IAR
#include "..\..\Source\portable\IAR\STR91x\portmacro.h"
#endif
#ifdef GCC_H8S
#include "../../Source/portable/GCC/H8S2329/portmacro.h"
#endif
#ifdef GCC_AT91FR40008
#include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h"
#endif
#ifdef RVDS_ARMCM3_LM3S102
#include "../../Source/portable/RVDS/ARM_CM3/portmacro.h"
#endif
#ifdef GCC_ARMCM3_LM3S102
#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
#endif
#ifdef GCC_ARMCM3
#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
#endif
#ifdef IAR_ARM_CM3
#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
#endif
#ifdef IAR_ARMCM3_LM
#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
#endif
#ifdef HCS12_CODE_WARRIOR
#include "../../Source/portable/CodeWarrior/HCS12/portmacro.h"
#endif
#ifdef MICROBLAZE_GCC
#include "../../Source/portable/GCC/MicroBlaze/portmacro.h"
#endif
#ifdef TERN_EE
#include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h"
#endif
#ifdef GCC_HCS12
#include "../../Source/portable/GCC/HCS12/portmacro.h"
#endif
#ifdef GCC_MCF5235
#include "../../Source/portable/GCC/MCF5235/portmacro.h"
#endif
#ifdef COLDFIRE_V2_GCC
#include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h"
#endif
#ifdef COLDFIRE_V2_CODEWARRIOR
#include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h"
#endif
#ifdef GCC_PPC405
#include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h"
#endif
#ifdef GCC_PPC440
#include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h"
#endif
#ifdef _16FX_SOFTUNE
#include "..\..\Source\portable\Softune\MB96340\portmacro.h"
#endif
#ifdef BCC_INDUSTRIAL_PC_PORT
/* A short file name has to be used in place of the normal
FreeRTOSConfig.h when using the Borland compiler. */
#include "frconfig.h"
#include "..\portable\BCC\16BitDOS\PC\prtmacro.h"
typedef void ( __interrupt __far *pxISR )();
#endif
#ifdef BCC_FLASH_LITE_186_PORT
/* A short file name has to be used in place of the normal
FreeRTOSConfig.h when using the Borland compiler. */
#include "frconfig.h"
#include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h"
typedef void ( __interrupt __far *pxISR )();
#endif
#ifdef __GNUC__
#ifdef __AVR32_AVR32A__
#include "portmacro.h"
#endif
#endif
#ifdef __ICCAVR32__
#ifdef __CORE__
#if __CORE__ == __AVR32A__
#include "portmacro.h"
#endif
#endif
#endif
#ifdef __91467D
#include "portmacro.h"
#endif
#ifdef __96340
#include "portmacro.h"
#endif
#ifdef __IAR_V850ES_Fx3__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_V850ES_Jx3__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_V850ES_Jx3_L__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_V850ES_Jx2__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_V850ES_Hx2__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_78K0R_Kx3__
#include "../../Source/portable/IAR/78K0R/portmacro.h"
#endif
#ifdef __IAR_78K0R_Kx3L__
#include "../../Source/portable/IAR/78K0R/portmacro.h"
#endif
#endif /* DEPRECATED_DEFINITIONS_H */

View File

@@ -0,0 +1,757 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef EVENT_GROUPS_H
#define EVENT_GROUPS_H
#ifndef INC_FREERTOS_H
#error "include FreeRTOS.h" must appear in source files before "include event_groups.h"
#endif
/* FreeRTOS includes. */
#include "timers.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* An event group is a collection of bits to which an application can assign a
* meaning. For example, an application may create an event group to convey
* the status of various CAN bus related events in which bit 0 might mean "A CAN
* message has been received and is ready for processing", bit 1 might mean "The
* application has queued a message that is ready for sending onto the CAN
* network", and bit 2 might mean "It is time to send a SYNC message onto the
* CAN network" etc. A task can then test the bit values to see which events
* are active, and optionally enter the Blocked state to wait for a specified
* bit or a group of specified bits to be active. To continue the CAN bus
* example, a CAN controlling task can enter the Blocked state (and therefore
* not consume any processing time) until either bit 0, bit 1 or bit 2 are
* active, at which time the bit that was actually active would inform the task
* which action it had to take (process a received message, send a message, or
* send a SYNC).
*
* The event groups implementation contains intelligence to avoid race
* conditions that would otherwise occur were an application to use a simple
* variable for the same purpose. This is particularly important with respect
* to when a bit within an event group is to be cleared, and when bits have to
* be set and then tested atomically - as is the case where event groups are
* used to create a synchronisation point between multiple tasks (a
* 'rendezvous').
*
* \defgroup EventGroup
*/
/**
* event_groups.h
*
* Type by which event groups are referenced. For example, a call to
* xEventGroupCreate() returns an EventGroupHandle_t variable that can then
* be used as a parameter to other event group functions.
*
* \defgroup EventGroupHandle_t EventGroupHandle_t
* \ingroup EventGroup
*/
typedef void * EventGroupHandle_t;
/*
* The type that holds event bits always matches TickType_t - therefore the
* number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1,
* 32 bits if set to 0.
*
* \defgroup EventBits_t EventBits_t
* \ingroup EventGroup
*/
typedef TickType_t EventBits_t;
/**
* event_groups.h
*<pre>
EventGroupHandle_t xEventGroupCreate( void );
</pre>
*
* Create a new event group.
*
* Internally, within the FreeRTOS implementation, event groups use a [small]
* block of memory, in which the event group's structure is stored. If an event
* groups is created using xEventGropuCreate() then the required memory is
* automatically dynamically allocated inside the xEventGroupCreate() function.
* (see http://www.freertos.org/a00111.html). If an event group is created
* using xEventGropuCreateStatic() then the application writer must instead
* provide the memory that will get used by the event group.
* xEventGroupCreateStatic() therefore allows an event group to be created
* without using any dynamic memory allocation.
*
* Although event groups are not related to ticks, for internal implementation
* reasons the number of bits available for use in an event group is dependent
* on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If
* configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit
* 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has
* 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store
* event bits within an event group.
*
* @return If the event group was created then a handle to the event group is
* returned. If there was insufficient FreeRTOS heap available to create the
* event group then NULL is returned. See http://www.freertos.org/a00111.html
*
* Example usage:
<pre>
// Declare a variable to hold the created event group.
EventGroupHandle_t xCreatedEventGroup;
// Attempt to create the event group.
xCreatedEventGroup = xEventGroupCreate();
// Was the event group created successfully?
if( xCreatedEventGroup == NULL )
{
// The event group was not created because there was insufficient
// FreeRTOS heap available.
}
else
{
// The event group was created.
}
</pre>
* \defgroup xEventGroupCreate xEventGroupCreate
* \ingroup EventGroup
*/
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
#endif
/**
* event_groups.h
*<pre>
EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer );
</pre>
*
* Create a new event group.
*
* Internally, within the FreeRTOS implementation, event groups use a [small]
* block of memory, in which the event group's structure is stored. If an event
* groups is created using xEventGropuCreate() then the required memory is
* automatically dynamically allocated inside the xEventGroupCreate() function.
* (see http://www.freertos.org/a00111.html). If an event group is created
* using xEventGropuCreateStatic() then the application writer must instead
* provide the memory that will get used by the event group.
* xEventGroupCreateStatic() therefore allows an event group to be created
* without using any dynamic memory allocation.
*
* Although event groups are not related to ticks, for internal implementation
* reasons the number of bits available for use in an event group is dependent
* on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If
* configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit
* 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has
* 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store
* event bits within an event group.
*
* @param pxEventGroupBuffer pxEventGroupBuffer must point to a variable of type
* StaticEventGroup_t, which will be then be used to hold the event group's data
* structures, removing the need for the memory to be allocated dynamically.
*
* @return If the event group was created then a handle to the event group is
* returned. If pxEventGroupBuffer was NULL then NULL is returned.
*
* Example usage:
<pre>
// StaticEventGroup_t is a publicly accessible structure that has the same
// size and alignment requirements as the real event group structure. It is
// provided as a mechanism for applications to know the size of the event
// group (which is dependent on the architecture and configuration file
// settings) without breaking the strict data hiding policy by exposing the
// real event group internals. This StaticEventGroup_t variable is passed
// into the xSemaphoreCreateEventGroupStatic() function and is used to store
// the event group's data structures
StaticEventGroup_t xEventGroupBuffer;
// Create the event group without dynamically allocating any memory.
xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
</pre>
*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) PRIVILEGED_FUNCTION;
#endif
/**
* event_groups.h
*<pre>
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
const TickType_t xTicksToWait );
</pre>
*
* [Potentially] block to wait for one or more bits to be set within a
* previously created event group.
*
* This function cannot be called from an interrupt.
*
* @param xEventGroup The event group in which the bits are being tested. The
* event group must have previously been created using a call to
* xEventGroupCreate().
*
* @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
* inside the event group. For example, to wait for bit 0 and/or bit 2 set
* uxBitsToWaitFor to 0x05. To wait for bits 0 and/or bit 1 and/or bit 2 set
* uxBitsToWaitFor to 0x07. Etc.
*
* @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within
* uxBitsToWaitFor that are set within the event group will be cleared before
* xEventGroupWaitBits() returns if the wait condition was met (if the function
* returns for a reason other than a timeout). If xClearOnExit is set to
* pdFALSE then the bits set in the event group are not altered when the call to
* xEventGroupWaitBits() returns.
*
* @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then
* xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor
* are set or the specified block time expires. If xWaitForAllBits is set to
* pdFALSE then xEventGroupWaitBits() will return when any one of the bits set
* in uxBitsToWaitFor is set or the specified block time expires. The block
* time is specified by the xTicksToWait parameter.
*
* @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
* for one/all (depending on the xWaitForAllBits value) of the bits specified by
* uxBitsToWaitFor to become set.
*
* @return The value of the event group at the time either the bits being waited
* for became set, or the block time expired. Test the return value to know
* which bits were set. If xEventGroupWaitBits() returned because its timeout
* expired then not all the bits being waited for will be set. If
* xEventGroupWaitBits() returned because the bits it was waiting for were set
* then the returned value is the event group value before any bits were
* automatically cleared in the case that xClearOnExit parameter was set to
* pdTRUE.
*
* Example usage:
<pre>
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
void aFunction( EventGroupHandle_t xEventGroup )
{
EventBits_t uxBits;
const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
// Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
// the event group. Clear the bits before exiting.
uxBits = xEventGroupWaitBits(
xEventGroup, // The event group being tested.
BIT_0 | BIT_4, // The bits within the event group to wait for.
pdTRUE, // BIT_0 and BIT_4 should be cleared before returning.
pdFALSE, // Don't wait for both bits, either bit will do.
xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
{
// xEventGroupWaitBits() returned because both bits were set.
}
else if( ( uxBits & BIT_0 ) != 0 )
{
// xEventGroupWaitBits() returned because just BIT_0 was set.
}
else if( ( uxBits & BIT_4 ) != 0 )
{
// xEventGroupWaitBits() returned because just BIT_4 was set.
}
else
{
// xEventGroupWaitBits() returned because xTicksToWait ticks passed
// without either BIT_0 or BIT_4 becoming set.
}
}
</pre>
* \defgroup xEventGroupWaitBits xEventGroupWaitBits
* \ingroup EventGroup
*/
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
*<pre>
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
</pre>
*
* Clear bits within an event group. This function cannot be called from an
* interrupt.
*
* @param xEventGroup The event group in which the bits are to be cleared.
*
* @param uxBitsToClear A bitwise value that indicates the bit or bits to clear
* in the event group. For example, to clear bit 3 only, set uxBitsToClear to
* 0x08. To clear bit 3 and bit 0 set uxBitsToClear to 0x09.
*
* @return The value of the event group before the specified bits were cleared.
*
* Example usage:
<pre>
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
void aFunction( EventGroupHandle_t xEventGroup )
{
EventBits_t uxBits;
// Clear bit 0 and bit 4 in xEventGroup.
uxBits = xEventGroupClearBits(
xEventGroup, // The event group being updated.
BIT_0 | BIT_4 );// The bits being cleared.
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
{
// Both bit 0 and bit 4 were set before xEventGroupClearBits() was
// called. Both will now be clear (not set).
}
else if( ( uxBits & BIT_0 ) != 0 )
{
// Bit 0 was set before xEventGroupClearBits() was called. It will
// now be clear.
}
else if( ( uxBits & BIT_4 ) != 0 )
{
// Bit 4 was set before xEventGroupClearBits() was called. It will
// now be clear.
}
else
{
// Neither bit 0 nor bit 4 were set in the first place.
}
}
</pre>
* \defgroup xEventGroupClearBits xEventGroupClearBits
* \ingroup EventGroup
*/
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
*<pre>
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
</pre>
*
* A version of xEventGroupClearBits() that can be called from an interrupt.
*
* Setting bits in an event group is not a deterministic operation because there
* are an unknown number of tasks that may be waiting for the bit or bits being
* set. FreeRTOS does not allow nondeterministic operations to be performed
* while interrupts are disabled, so protects event groups that are accessed
* from tasks by suspending the scheduler rather than disabling interrupts. As
* a result event groups cannot be accessed directly from an interrupt service
* routine. Therefore xEventGroupClearBitsFromISR() sends a message to the
* timer task to have the clear operation performed in the context of the timer
* task.
*
* @param xEventGroup The event group in which the bits are to be cleared.
*
* @param uxBitsToClear A bitwise value that indicates the bit or bits to clear.
* For example, to clear bit 3 only, set uxBitsToClear to 0x08. To clear bit 3
* and bit 0 set uxBitsToClear to 0x09.
*
* @return If the request to execute the function was posted successfully then
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
* if the timer service queue was full.
*
* Example usage:
<pre>
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
// An event group which it is assumed has already been created by a call to
// xEventGroupCreate().
EventGroupHandle_t xEventGroup;
void anInterruptHandler( void )
{
// Clear bit 0 and bit 4 in xEventGroup.
xResult = xEventGroupClearBitsFromISR(
xEventGroup, // The event group being updated.
BIT_0 | BIT_4 ); // The bits being set.
if( xResult == pdPASS )
{
// The message was posted successfully.
}
}
</pre>
* \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR
* \ingroup EventGroup
*/
#if( configUSE_TRACE_FACILITY == 1 )
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;
#else
#define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL )
#endif
/**
* event_groups.h
*<pre>
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
</pre>
*
* Set bits within an event group.
* This function cannot be called from an interrupt. xEventGroupSetBitsFromISR()
* is a version that can be called from an interrupt.
*
* Setting bits in an event group will automatically unblock tasks that are
* blocked waiting for the bits.
*
* @param xEventGroup The event group in which the bits are to be set.
*
* @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
* For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
* and bit 0 set uxBitsToSet to 0x09.
*
* @return The value of the event group at the time the call to
* xEventGroupSetBits() returns. There are two reasons why the returned value
* might have the bits specified by the uxBitsToSet parameter cleared. First,
* if setting a bit results in a task that was waiting for the bit leaving the
* blocked state then it is possible the bit will be cleared automatically
* (see the xClearBitOnExit parameter of xEventGroupWaitBits()). Second, any
* unblocked (or otherwise Ready state) task that has a priority above that of
* the task that called xEventGroupSetBits() will execute and may change the
* event group value before the call to xEventGroupSetBits() returns.
*
* Example usage:
<pre>
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
void aFunction( EventGroupHandle_t xEventGroup )
{
EventBits_t uxBits;
// Set bit 0 and bit 4 in xEventGroup.
uxBits = xEventGroupSetBits(
xEventGroup, // The event group being updated.
BIT_0 | BIT_4 );// The bits being set.
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
{
// Both bit 0 and bit 4 remained set when the function returned.
}
else if( ( uxBits & BIT_0 ) != 0 )
{
// Bit 0 remained set when the function returned, but bit 4 was
// cleared. It might be that bit 4 was cleared automatically as a
// task that was waiting for bit 4 was removed from the Blocked
// state.
}
else if( ( uxBits & BIT_4 ) != 0 )
{
// Bit 4 remained set when the function returned, but bit 0 was
// cleared. It might be that bit 0 was cleared automatically as a
// task that was waiting for bit 0 was removed from the Blocked
// state.
}
else
{
// Neither bit 0 nor bit 4 remained set. It might be that a task
// was waiting for both of the bits to be set, and the bits were
// cleared as the task left the Blocked state.
}
}
</pre>
* \defgroup xEventGroupSetBits xEventGroupSetBits
* \ingroup EventGroup
*/
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
*<pre>
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
</pre>
*
* A version of xEventGroupSetBits() that can be called from an interrupt.
*
* Setting bits in an event group is not a deterministic operation because there
* are an unknown number of tasks that may be waiting for the bit or bits being
* set. FreeRTOS does not allow nondeterministic operations to be performed in
* interrupts or from critical sections. Therefore xEventGroupSetBitsFromISR()
* sends a message to the timer task to have the set operation performed in the
* context of the timer task - where a scheduler lock is used in place of a
* critical section.
*
* @param xEventGroup The event group in which the bits are to be set.
*
* @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
* For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
* and bit 0 set uxBitsToSet to 0x09.
*
* @param pxHigherPriorityTaskWoken As mentioned above, calling this function
* will result in a message being sent to the timer daemon task. If the
* priority of the timer daemon task is higher than the priority of the
* currently running task (the task the interrupt interrupted) then
* *pxHigherPriorityTaskWoken will be set to pdTRUE by
* xEventGroupSetBitsFromISR(), indicating that a context switch should be
* requested before the interrupt exits. For that reason
* *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the
* example code below.
*
* @return If the request to execute the function was posted successfully then
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
* if the timer service queue was full.
*
* Example usage:
<pre>
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
// An event group which it is assumed has already been created by a call to
// xEventGroupCreate().
EventGroupHandle_t xEventGroup;
void anInterruptHandler( void )
{
BaseType_t xHigherPriorityTaskWoken, xResult;
// xHigherPriorityTaskWoken must be initialised to pdFALSE.
xHigherPriorityTaskWoken = pdFALSE;
// Set bit 0 and bit 4 in xEventGroup.
xResult = xEventGroupSetBitsFromISR(
xEventGroup, // The event group being updated.
BIT_0 | BIT_4 // The bits being set.
&xHigherPriorityTaskWoken );
// Was the message posted successfully?
if( xResult == pdPASS )
{
// If xHigherPriorityTaskWoken is now set to pdTRUE then a context
// switch should be requested. The macro used is port specific and
// will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
// refer to the documentation page for the port being used.
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
}
</pre>
* \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
* \ingroup EventGroup
*/
#if( configUSE_TRACE_FACILITY == 1 )
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
#else
#define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken )
#endif
/**
* event_groups.h
*<pre>
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
const EventBits_t uxBitsToWaitFor,
TickType_t xTicksToWait );
</pre>
*
* Atomically set bits within an event group, then wait for a combination of
* bits to be set within the same event group. This functionality is typically
* used to synchronise multiple tasks, where each task has to wait for the other
* tasks to reach a synchronisation point before proceeding.
*
* This function cannot be used from an interrupt.
*
* The function will return before its block time expires if the bits specified
* by the uxBitsToWait parameter are set, or become set within that time. In
* this case all the bits specified by uxBitsToWait will be automatically
* cleared before the function returns.
*
* @param xEventGroup The event group in which the bits are being tested. The
* event group must have previously been created using a call to
* xEventGroupCreate().
*
* @param uxBitsToSet The bits to set in the event group before determining
* if, and possibly waiting for, all the bits specified by the uxBitsToWait
* parameter are set.
*
* @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
* inside the event group. For example, to wait for bit 0 and bit 2 set
* uxBitsToWaitFor to 0x05. To wait for bits 0 and bit 1 and bit 2 set
* uxBitsToWaitFor to 0x07. Etc.
*
* @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
* for all of the bits specified by uxBitsToWaitFor to become set.
*
* @return The value of the event group at the time either the bits being waited
* for became set, or the block time expired. Test the return value to know
* which bits were set. If xEventGroupSync() returned because its timeout
* expired then not all the bits being waited for will be set. If
* xEventGroupSync() returned because all the bits it was waiting for were
* set then the returned value is the event group value before any bits were
* automatically cleared.
*
* Example usage:
<pre>
// Bits used by the three tasks.
#define TASK_0_BIT ( 1 << 0 )
#define TASK_1_BIT ( 1 << 1 )
#define TASK_2_BIT ( 1 << 2 )
#define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
// Use an event group to synchronise three tasks. It is assumed this event
// group has already been created elsewhere.
EventGroupHandle_t xEventBits;
void vTask0( void *pvParameters )
{
EventBits_t uxReturn;
TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
for( ;; )
{
// Perform task functionality here.
// Set bit 0 in the event flag to note this task has reached the
// sync point. The other two tasks will set the other two bits defined
// by ALL_SYNC_BITS. All three tasks have reached the synchronisation
// point when all the ALL_SYNC_BITS are set. Wait a maximum of 100ms
// for this to happen.
uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );
if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
{
// All three tasks reached the synchronisation point before the call
// to xEventGroupSync() timed out.
}
}
}
void vTask1( void *pvParameters )
{
for( ;; )
{
// Perform task functionality here.
// Set bit 1 in the event flag to note this task has reached the
// synchronisation point. The other two tasks will set the other two
// bits defined by ALL_SYNC_BITS. All three tasks have reached the
// synchronisation point when all the ALL_SYNC_BITS are set. Wait
// indefinitely for this to happen.
xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
// xEventGroupSync() was called with an indefinite block time, so
// this task will only reach here if the syncrhonisation was made by all
// three tasks, so there is no need to test the return value.
}
}
void vTask2( void *pvParameters )
{
for( ;; )
{
// Perform task functionality here.
// Set bit 2 in the event flag to note this task has reached the
// synchronisation point. The other two tasks will set the other two
// bits defined by ALL_SYNC_BITS. All three tasks have reached the
// synchronisation point when all the ALL_SYNC_BITS are set. Wait
// indefinitely for this to happen.
xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
// xEventGroupSync() was called with an indefinite block time, so
// this task will only reach here if the syncrhonisation was made by all
// three tasks, so there is no need to test the return value.
}
}
</pre>
* \defgroup xEventGroupSync xEventGroupSync
* \ingroup EventGroup
*/
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
*<pre>
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
</pre>
*
* Returns the current value of the bits in an event group. This function
* cannot be used from an interrupt.
*
* @param xEventGroup The event group being queried.
*
* @return The event group bits at the time xEventGroupGetBits() was called.
*
* \defgroup xEventGroupGetBits xEventGroupGetBits
* \ingroup EventGroup
*/
#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 )
/**
* event_groups.h
*<pre>
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
</pre>
*
* A version of xEventGroupGetBits() that can be called from an ISR.
*
* @param xEventGroup The event group being queried.
*
* @return The event group bits at the time xEventGroupGetBitsFromISR() was called.
*
* \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR
* \ingroup EventGroup
*/
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
/**
* event_groups.h
*<pre>
void xEventGroupDelete( EventGroupHandle_t xEventGroup );
</pre>
*
* Delete an event group that was previously created by a call to
* xEventGroupCreate(). Tasks that are blocked on the event group will be
* unblocked and obtain 0 as the event group's value.
*
* @param xEventGroup The event group being deleted.
*/
void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
/* For internal use only. */
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION;
void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
#if (configUSE_TRACE_FACILITY == 1)
UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) PRIVILEGED_FUNCTION;
void vEventGroupSetNumber( void* xEventGroup, UBaseType_t uxEventGroupNumber ) PRIVILEGED_FUNCTION;
#endif
#ifdef __cplusplus
}
#endif
#endif /* EVENT_GROUPS_H */

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