1 GCC
1.1 内建函数
int __builtin_constant_p( exp )
GCC的内建函数 __builtin_constant_p 用于判断一个值是否为编译时常数,如果参数exp的值是常数,函数返回 1,否则返回 0。
弱函数
__attribute__((weak)) var_type function(var_type)
{
}
或者:
extern var_type function(var_type) __attribute__((weak));
var_type function(var_type)
{
}
1.2 FreeRTOS自定义GCC section
@flash.ld
SECTIONS
{
[…]
.text :
{
[…]
. = ALIGN(4);
PROVIDE (__core_initcall = .);
KEEP(*(.core.initcall))
PROVIDE (__core_initcall_end = .);
. = ALIGN(4);
PROVIDE (__module_initcall = .);
KEEP(*(.module.initcall))
PROVIDE (__module_initcall_end = .);
. = ALIGN(4);
PROVIDE (__late_initcall = .);
KEEP(*(.late.initcall))
PROVIDE (__late_initcall_end = .);
. = ALIGN(4);
PROVIDE (__atcmds_section = .);
KEEP(*(.oem_atcmds))
PROVIDE (__atcmds_section_end = .);
[…]
}
[…]
}
@cutils.h
typedef void (*initcall_t)(void);
extern initcall_t __core_initcall[];
extern initcall_t __core_initcall_end[];
extern initcall_t __module_initcall[];
extern initcall_t __module_initcall_end[];
extern initcall_t __late_initcall[];
extern initcall_t __late_initcall_end[];
#if 1
#define core_initcall(fn) \
static initcall_t __initcall_##fn \
__attribute__((used,section(".core.initcall"))) = fn
#define module_init(fn) \
static initcall_t __initcall_##fn \
__attribute__((used,section(".module.initcall"))) = fn
#define late_initcall(fn) \
static initcall_t __initcall_##fn \
__attribute__((used,section(".late.initcall"))) = fn
#else
#define core_initcall(fn) \
void fn(void) __attribute__((unused))
#define module_init(fn) \
void fn(void) __attribute__((unused))
#define late_initcall(fn) \
void fn(void) __attribute__((unused))
#endif
extern const atci_cmd_hdlr_item_t __atcmds_section[];
extern const atci_cmd_hdlr_item_t __atcmds_section_end[];
#if 1
#define DECLARE_AT_COMMAND(NAME, ROUTINE) \
static const char __atcmd_label_##NAME[] = "AT+"#NAME; \
static const atci_cmd_hdlr_item_t __atcmd_##NAME \
__attribute__((used,section(".oem_atcmds"))) = \
{ \
.command_head = __atcmd_label_##NAME, \
.command_hdlr = ROUTINE, \
}
#else
#define DECLARE_AT_COMMAND(NAME, ROUTINE) \
atci_status_t (ROUTINE)(atci_parse_cmd_param_t *parse_cmd) __attribute__((unused))
#endif
@main.c
static void section_core_init(void)
{
initcall_t *initcall;
for (initcall = __core_initcall;
initcall < __core_initcall_end;
initcall++) {
(*initcall)();
}
}
static void section_module_init(void)
{
initcall_t *initcall;
for (initcall = __module_initcall;
initcall < __module_initcall_end;
initcall++) {
(*initcall)();
}
}
static void section_late_init(void)
{
initcall_t *initcall;
for (initcall = __late_initcall;
initcall < __late_initcall_end;
initcall++) {
(*initcall)();
}
}
static bool atcmds_section_cb(atci_parse_cmd_param_ex_t *parse_cmd)
{
atci_cmd_hdlr_item_t *handler;
for (handler = __atcmds_section;
handler < __atcmds_section_end;
handler++) {
LOGE("command_head: %s; "
"parse_cmd->string_ptr: %s, parse_cmd->hash_value1: 0x%08x, "
"parse_cmd->hash_value2: 0x%08x\r\n",
handler->command_head,
parse_cmd->string_ptr, parse_cmd->hash_value1, parse_cmd->hash_value2);
if (!strncmp((char *)parse_cmd->string_ptr,
handler->command_head,
strlen(handler->command_head))) {
handler->command_hdlr((atci_parse_cmd_param_t*)parse_cmd);
return true;
}
}
return false;
}
2 IAR
2.1 URLs
IAR程序中获取堆指针与栈指针
http://blog.csdn.net/sunheshan/article/details/48548103
3 MCU链表操作头文件-porting from Linux
@ utils.h
#if !defined(__UTILS_H)
#define __UTILS_H
#ifdef __cplusplus
extern "C" {
#endif
#include
#include
#include
#include
#include
#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD(name) \
struct list_head name = { \
.next = &(name), \
.prev = &(name), \
}
#define LEGACY_LIST_HEAD(type, name) \
type name = { \
.next = &(name), \
.prev = &(name), \
}
#define list_empty(head) ((head) == (head)->next)
#define list_for_each(node, head) \
for (node = (head)->next; node != (head); node = node->next)
#define list_for_each_safe(node, n, head) \
for (node = (head)->next, n = node->next; \
node != (head); \
node = n, n = node->next)
#define list_init(head) do { \
(head)->next = (head); \
(head)->prev = (head); \
} while (0)
#define list_add_head(node, head) do { \
(node)->next = (head)->next; \
(node)->prev = (head); \
(head)->next->prev = (node); \
(head)->next = (node); \
} while (0)
#define list_add_tail(node, head) do { \
(node)->next = (head); \
(node)->prev = (head)->prev; \
(head)->prev->next = (node); \
(head)->prev = (node); \
} while (0)
#define list_del(node) do { \
(node)->next->prev = (node)->prev; \
(node)->prev->next = (node)->next; \
(node)->next = NULL; \
(node)->prev = NULL; \
} while (0)
#ifdef __cplusplus
}
#endif
#endif
4 AT Command Parser
#include
#include
#include
typedef int int32;
static char *at_tok_next_int(char *str, int32 *tok)
{
char *p, *end;
if (!str || !tok) {
return NULL;
}
p = str;
while (*p != '\0' && *p != '\r' && *p != '\n' && isspace(*p)) p++;
if (*p == '\0') {
goto err;
}
if (strchr(p, ',')) {
end = strchr(p, ',');
*end = '\0';
end++;
} else {
end = p + strlen(p);
}
*tok = strtoul(p, NULL, 0);
return end;
err:
return NULL;
}
static char *at_tok_next_str(char *str, char *tok)
{
char *p, *end;
unsigned int i;
if (!str || !tok) {
return NULL;
}
p = str;
while (*p != '\0' && *p != '\r' && *p != '\n' && isspace(*p)) p++;
if (*p == '\0') {
goto err;
}
if (strchr(p, ',')) {
end = strchr(p, ',');
*end = '\0';
end++;
} else {
end = p + strlen(p);
}
strcpy(tok, p);
for (i = strlen(tok); i >= 0; i--) {
if (isalpha(tok[i]) || isdigit(tok[i])) {
break;
} else if (isspace(tok[i]) || tok[i] == '\r' || tok[i] == '\n') {
tok[i] = '\0';
}
}
return end;
err:
return NULL;
}
int main(int argc, char **argv)
{
char at[] = {"AT+TEST=5,1,HELLO\r\n"};
int prx_len = strlen("AT+TEST=");
char *p = at + prx_len;
int v1;
int v2;
char v3[16];
p = at_tok_next_int(p, &v1);
if (p) {
p = at_tok_next_int(p, &v2);
}
if (p) {
p = at_tok_next_str(p, v3);
}
fprintf(stdout, "%d %d %s\n", v1, v2, v3);
return 0;
}
5 JSON
#define __api
#define ACTION_SZ 64
#define AUTH_SZ 32
#define UUID_SZ 32
#define PARAMS_SZ 256
#define MSG_SZ 64
#define STATUS_SZ 32
#define RESULT_SZ 256
typedef unsigned int u32;
typedef struct req_arg {
char action[ACTION_SZ];
char auth[AUTH_SZ];
char uuid[UUID_SZ];
char params[PARAMS_SZ];
} req_arg_t;
typedef struct rsp_arg {
char msg[MSG_SZ];
char uuid[UUID_SZ];
char status[STATUS_SZ];
char result[RESULT_SZ];
} rsp_arg_t;
void __api u_json_clr_qm(char *json)
{
int i;
for (i = 0; i < strlen(json); i++) {
if (json[i] == '\"') {
json[i] = ' ';
}
}
}
int __api u_json_get_value(const char *json, int json_len, const char *key,
char *value, int value_len)
{
char *p, *p2, *end;
unsigned int nleft = 0, nright = 0;
unsigned int i, len;
if (!json || !key || !value) {
goto err;
}
p = strstr(json, key);
if (!p) {
printf("Oops\n");
goto err;
}
p += strlen(key);
while (*p != '\0' && *p != ':') p++;
if (*p != ':') {
printf("err1, invalid json string: %s\n", json);
goto err;
}
p++;
while (*p != '\0' && isspace(*p)) p++;
//printf("DEBUG:%s-\n", p);
if (*p == '{') {
p++;
end = p;
while (*end != '\0' && *end != '}') end++;
if (*end != '}') {
printf("err2, invalid json string: %s\n", json);
goto err;
}
p2 = p;
// In 64bit machine, this will show a warning message,
// because of sizeof(char *) = 8, but sizeof(u32) = 4
//while ((u32)p2 != (u32)end) {
while ((u32)p2 < (u32)end) {
if (*p2 == '{') {
nleft++;
}
p2++;
}
if (nleft > 0) {
end++;
while (*end != '\0') {
if (*end == '}') {
nright++;
}
if (nleft == nright) {
break;
}
end++;
}
}
} else {
end = p;
while (*end != '\0' && *end != ',' && *end != '}') end++;
// TODO: Need check error?
}
len = (u32)(end - p);
value_len = len < (value_len - 1) ? len : (value_len - 1);
memcpy(value, p, value_len);
value[value_len] = '\0';
for (i = value_len; i >= 0; i--) {
if (isalpha(value[i]) || isdigit(value[i])) {
break;
} else if (isspace(value[i])) {
value[i] = '\0';
}
}
return 0;
err:
return -1;
}
6 Customized Print Function
#include
static int format_xxx_data(unsigned char *buf, unsigned int buf_len, const char *fmt,...)
{
va_list ap;
int n;
if (NULL == buf) {
return -1;
}
va_start(ap, fmt);
n = vsnprintf(buf, buf_len, fmt, ap);
va_end(ap);
return n;
}
7 ringbuf(num_of_msgs是2的N次方,siz_of_msg > 0)
typedef struct {
uint8_t *buf;
uint16_t num_of_msgs;
uint16_t siz_of_msg;
uint32_t write_seq;
uint32_t read_seq;
#define AVAIL_BIT 0x01
EventGroupHandle_t event_group;
SemaphoreHandle_t sem;
} ringbuf_t;
static bool ringbuf_popback(ringbuf_t *handle, void *msg)
{
uint32_t offset;
if (!handle || !msg) {
return false;
}
if (NULL != handle->sem) {
xSemaphoreTake(handle->sem, portMAX_DELAY);
}
if (handle->read_seq == handle->write_seq) {
goto out;
}
offset = (handle->read_seq & (handle->num_of_msgs - 1)) * handle->siz_of_msg;
memcpy(msg, &(handle->buf[offset]), handle->siz_of_msg);
handle->read_seq++;
if (NULL != handle->sem) {
xSemaphoreGive(handle->sem);
}
return true;
out:
if (NULL != handle->sem) {
xSemaphoreGive(handle->sem);
}
return false;
}
static void ringbuf_push(ringbuf_t *handle, void *msg)
{
uint32_t offset;
if (!handle || !msg) {
return;
}
if (NULL != handle->sem) {
xSemaphoreTake(handle->sem, portMAX_DELAY);
}
offset = (handle->write_seq & (handle->num_of_msgs - 1)) * handle->siz_of_msg;
memcpy(&(handle->buf[offset]), msg, handle->siz_of_msg);
handle->write_seq++;
if ((handle->write_seq - handle->read_seq) > handle->num_of_msgs) {
handle->read_seq = handle->write_seq - handle->num_of_msgs;
}
if (NULL != handle->sem) {
xSemaphoreGive(handle->sem);
}
xEventGroupSetBits(handle->event_group, AVAIL_BIT);
}
static bool ringbuf_empty(ringbuf_t *handle)
{
bool ret = false;
if (!handle) {
return true;
}
if (NULL != handle->sem) {
xSemaphoreTake(handle->sem, portMAX_DELAY);
}
if (handle->read_seq == handle->write_seq) {
ret = true;
}
if (NULL != handle->sem) {
xSemaphoreGive(handle->sem);
}
return ret;
}
static ringbuf_t *ringbuf_create(uint16_t num_of_msgs, uint16_t siz_of_msg)
{
ringbuf_t *rb;
rb = pvPortMalloc(sizeof(ringbuf_t));
if (!rb) {
goto out;
}
rb->num_of_msgs = num_of_msgs;
rb->siz_of_msg = siz_of_msg;
rb->buf = pvPortMalloc(num_of_msgs * siz_of_msg);
if (!rb->buf) {
goto free_rb;
}
rb->sem = xSemaphoreCreateBinary();
if(!rb->sem) {
goto free_buf;
}
xSemaphoreGive(rb->sem);
rb->event_group = xEventGroupCreate();
if (!rb->event_group) {
goto del_sem;
}
return rb;
del_sem:
vSemaphoreDelete(rb->sem);
rb->sem = NULL;
free_buf:
if (rb->buf) {
vPortFree(rb->buf);
rb->buf = NULL;
}
free_rb:
if (rb) {
vPortFree(rb);
rb = NULL;
}
out:
return NULL;
}
static void ringbuf_delete(ringbuf_t *handle)
{
if (!handle) {
return;
}
vEventGroupDelete(handle->event_group);
vSemaphoreDelete(handle->sem);
vPortFree(handle->buf);
vPortFree(handle);
}
static void ringbuf_reset(ringbuf_t *handle)
{
if (!handle) {
return;
}
if (NULL != handle->sem) {
xSemaphoreTake(handle->sem, portMAX_DELAY);
}
handle->read_seq = 0;
handle->write_seq = 0;
if (NULL != handle->sem) {
xSemaphoreGive(handle->sem);
}
}
static void ringbuf_wait(ringbuf_t *handle)
{
if (!handle) {
return;
}
xEventGroupWaitBits(handle->event_group,
AVAIL_BIT,
pdTRUE,
pdFALSE,
portMAX_DELAY);
}
8 用sscanf解析文本
/*
* #FLAG LENGTH PAYLOAD
* 12 04 11 22 33 44
* 21 04 44 33 22 11
* 55 06 44 33 22 11 00 71
* 66 05 44 33 22 11 81
* 33 00
* 44
*/
#define UT_FILE "./config.txt"
int main(int argc, char **argv)
{
FILE *fp;
char buf[128];
char trash_buf[128];
char *ptr;
int flag, length, val;
int i, buf_len;
fp = fopen(UT_FILE, "r");
if (fp != NULL) {
while (fgets(buf, 127, fp)) {
ptr = (char *)buf;
if (strchr(ptr, '#')) {
continue;
}
while (ptr && (*ptr != '\0') && isspace(*ptr)) ptr++;
if (!ptr) {
continue;
}
buf_len = strlen(ptr);
if (buf_len <= 6) {
/* "xx xx\n" */
if ((buf_len == 6) && 2 == sscanf(ptr, "%02x %02x\n", &flag, &length)) {
printf("%02x %02x\n", flag, length);
}
continue;
}
if (3 == sscanf(ptr, "%02x %02x %s\n", &flag, &length, trash_buf)) {
printf("%02x %02x", flag, length);
ptr += 6;
for (i = length; i--; i >= 0) {
if (i == 0) {
if (1 == sscanf(ptr, "%02x\n", &val)) {
printf(" %02x", val);
}
} else if (2 == sscanf(ptr, "%02x %s\n", &val, trash_buf)) {
printf(" %02x", val);
}
if (0 != i) {
ptr += 3;
}
}
printf("\n");
}
}
fclose(fp);
}
return 0;
}
9 Abbreviation
IAR:后两个字母取之于创始人名字Anders Rundgren的首字母,瑞典语Ingenjörsfirman Anders Rundgren,意为Anders Rundgren工程公司
Linux ffs:find first bit set
Linux fls:find last (most-significant) set bit