初始版本
20
external/cJSON/LICENSE
vendored
Normal 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
416
external/cifra_AES128-EAX/cifra_eax_aes.c
vendored
Normal 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
|
||||
};
|
||||
|
||||
152
external/cifra_AES128-EAX/cifra_eax_aes.h
vendored
Normal 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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:"MS 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", "MS ゴシック", 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", "MS ゴシック", 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", "MS ゴシック", 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", "MS ゴシック", monospace; letter-spacing: 0; }
|
||||
hr {border-width: 1px; margin: 1em;}
|
||||
div.abst {font-family: "MS Pゴシック",sans-serif;}
|
||||
div.para {clear: both; font-family: "MS 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: "MS Pゴシック",sans-serif; background-color: #d8d8FF; padding: 0.5em 0.5em; margin: 0 0 0.5em;}
|
||||
h3 {font-size: 1.5em; font-family: "MS 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: "MS Pゴシック",sans-serif; margin: 2em 0 0.2em;}
|
||||
h5 {font-size: 1em; font-family: "MS 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
@@ -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
@@ -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
@@ -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
@@ -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
|
After Width: | Height: | Size: 1.4 KiB |
BIN
external/fatfs/doc/res/f2.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
external/fatfs/doc/res/f3.png
vendored
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
external/fatfs/doc/res/f4.png
vendored
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
external/fatfs/doc/res/f5.png
vendored
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
external/fatfs/doc/res/f6.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
external/fatfs/doc/res/f7.png
vendored
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
external/fatfs/doc/res/fd.mp4
vendored
Normal file
BIN
external/fatfs/doc/res/funcs.png
vendored
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
external/fatfs/doc/res/layers.png
vendored
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
external/fatfs/doc/res/layers1.png
vendored
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
external/fatfs/doc/res/layers2.png
vendored
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
external/fatfs/doc/res/layers3.png
vendored
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
external/fatfs/doc/res/mkfatimg.zip
vendored
Normal file
BIN
external/fatfs/doc/res/mkfs.xls
vendored
Normal file
BIN
external/fatfs/doc/res/modules.png
vendored
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
external/fatfs/doc/res/rwtest1.png
vendored
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
external/fatfs/doc/res/rwtest2.png
vendored
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
external/fatfs/doc/res/rwtest3.png
vendored
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
189
external/fatfs/doc/updates.txt
vendored
Normal 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
366
external/fatfs/src/ff.h
vendored
Normal 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
@@ -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
@@ -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
11045
external/fatfs/src/option/cc936.c
vendored
Normal file
8674
external/fatfs/src/option/cc949.c
vendored
Normal file
6900
external/fatfs/src/option/cc950.c
vendored
Normal file
388
external/fatfs/src/option/ccsbcs.c
vendored
Normal 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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__ */
|
||||
|
||||
207
external/freertos/config/FreeRTOSConfig.h
vendored
Normal 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
@@ -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.
|
||||
|
||||
128
external/freertos/portable/ARM/nrf51/port.c
vendored
Normal 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
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
34
external/freertos/portable/ARM/nrf51/portmacro.h
vendored
Normal 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 */
|
||||
153
external/freertos/portable/ARM/nrf52/port.c
vendored
Normal 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
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
34
external/freertos/portable/ARM/nrf52/portmacro.h
vendored
Normal 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 */
|
||||
243
external/freertos/portable/CMSIS/nrf51/port_cmsis.c
vendored
Normal 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);
|
||||
}
|
||||
233
external/freertos/portable/CMSIS/nrf51/port_cmsis_systick.c
vendored
Normal 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
|
||||
216
external/freertos/portable/CMSIS/nrf51/portmacro_cmsis.h
vendored
Normal 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 */
|
||||
|
||||
357
external/freertos/portable/CMSIS/nrf52/port_cmsis.c
vendored
Normal 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 */
|
||||
297
external/freertos/portable/CMSIS/nrf52/port_cmsis_systick.c
vendored
Normal 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
|
||||
187
external/freertos/portable/CMSIS/nrf52/portmacro_cmsis.h
vendored
Normal 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 */
|
||||
|
||||
134
external/freertos/portable/GCC/nrf51/port.c
vendored
Normal 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"
|
||||
);
|
||||
}
|
||||
36
external/freertos/portable/GCC/nrf51/portmacro.h
vendored
Normal 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 */
|
||||
|
||||
148
external/freertos/portable/GCC/nrf52/port.c
vendored
Normal 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))
|
||||
);
|
||||
}
|
||||
36
external/freertos/portable/GCC/nrf52/portmacro.h
vendored
Normal 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 */
|
||||
|
||||
148
external/freertos/portable/IAR/nrf51/port.c
vendored
Normal 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)
|
||||
);
|
||||
}
|
||||
40
external/freertos/portable/IAR/nrf51/portmacro.h
vendored
Normal 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 */
|
||||
|
||||
168
external/freertos/portable/IAR/nrf52/port.c
vendored
Normal 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)
|
||||
);
|
||||
}
|
||||
41
external/freertos/portable/IAR/nrf52/portmacro.h
vendored
Normal 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
@@ -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
@@ -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
@@ -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 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
1169
external/freertos/source/include/FreeRTOS.h
vendored
Normal file
134
external/freertos/source/include/StackMacros.h
vendored
Normal 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 */
|
||||
|
||||
721
external/freertos/source/include/croutine.h
vendored
Normal 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 */
|
||||
280
external/freertos/source/include/deprecated_definitions.h
vendored
Normal 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 */
|
||||
|
||||
757
external/freertos/source/include/event_groups.h
vendored
Normal 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 */
|
||||
|
||||
|
||||