GCC and IAR

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

你可能感兴趣的:(System,System)