gcc编译器 __attribute__ ((section(".")))

提到section,就得说RO RI ZI了,在ARM编译器编译之后,代码被划分为不同的段,RO Section(ReadOnly)中存放代码段和常量,RW Section(ReadWrite)中存放可读写静态变量和全局变量,ZI Section(ZeroInit)是存放在RW段中初始化为0的变量。默认情况下,编译器将其生成的目标代码存放在.data 和.bss 段中。section 属性允许指定变量(或函数存放到特定的段中。) 在内核中我们经常遇到"section"类似的字眼.把相关的CPU或设备信息存放在某个section里面.然后对这个section进行遍历,判断这个section里面是否有我们自己想要的信息。

section_test.h

#ifndef __SECTION_TEST_H__
#define __SECTION_TEST_H__

struct section_frame_t {
    uint8_t dest;
    uint8_t source;
    uint8_t resv;
    uint8_t length;
    uint8_t data[32];
};

struct section_iframe_t {
    uint8_t dest_addr;
    uint8_t dest_lun: 2;
    uint8_t dest_net_fn: 6;
    uint8_t sum;

    uint8_t source_addr;
    uint8_t source_lun: 2;
    uint8_t sequence: 6;

    uint8_t cmd;
    uint8_t data[26];
};

#pragma pack(4)

/*
 * 如果要使用下面的宏,必须修改你的连接文件${BOARD}.lds,在适当的地方加入:
 * . = ALIGN(4);
 * __section_test_table_start = .;
 * KEEP (*(SORT(.section_test_table)))
 * __section_test_table_end = .;
 *
 */
struct section_cmd_t {
    int8_t *name;
    uint8_t net_fn;
    uint8_t cmd;
    uint32_t (*callback)(struct section_frame_t *section_b);
};

extern uint32_t __section_test_table_start;
extern uint32_t __section_test_table_end;

#define SECTION_TEST(_name, _net_fn, _cmd, _callback)       \
    __attribute__ ((section(".section_test_table")))        \
    struct section_cmd_t _section_test_item_##_name##_cmd = {  \
        .name = (int8_t *)#_name,                                     \
        .net_fn = _net_fn,                                  \
        .cmd = _cmd,                                        \
        .callback = _callback }

#endif

section_test.c
#include "board.h"
#include "os.h"
#include "section_test.h"

static int32_t section_item_handler(struct section_frame_t *sectionb,
                                    uint32_t *table_start, uint32_t *table_end)
{
    struct section_cmd_t *start = (struct section_cmd_t *)table_start;
    struct section_cmd_t *end = (struct section_cmd_t *)table_end;
    struct section_iframe_t *setioni = (struct section_iframe_t *)sectionb->data;

    for (; start < end; start++)
        if ((start->cmd == setioni->cmd) &&
            (start->net_fn == setioni->dest_net_fn))
            return start->callback(sectionb);

    return false;
}

int32_t section_test_handler(struct section_frame_t *sectionb)
{
    int32_t table_len = __section_test_table_end - __section_test_table_start;

    parser_print("table length = %d\n", table_len);
    return section_item_handler(sectionb, &__section_test_table_start,
                                &__section_test_table_end);
}

static uint32_t section_test1(struct section_frame_t *sectionb)
{
    struct section_iframe_t *sectioni = (struct section_iframe_t *)sectionb->data;

    parser_print("section_test 1!\n");

}
SECTION_TEST(SECTION_TEST1, 0x18, 0x01, section_test1);

static uint32_t section_test2(struct section_frame_t *sectionb)
{
    struct section_iframe_t *sectioni = (struct section_iframe_t *)sectionb->data;

    parser_print("section_test 2!\n");

}
SECTION_TEST(SECTION_TEST2, 0x18, 0x02, section_test2);

static uint32_t section_test3(struct section_frame_t *sectionb)
{
    struct section_iframe_t *sectioni = (struct section_iframe_t *)sectionb->data;

    parser_print("section_test 3!\n");

}
SECTION_TEST(SECTION_TEST1, 0x18, 0x03, section_test3);


int32_t do_section_test(void)
{
    struct section_frame_t _sectionb = {0};
    struct section_iframe_t _sectioni = {0};
    parser_print("section test begin:\ns");

    _sectioni.dest_net_fn = 0x18;
    _sectioni.cmd = 0x01;
    memcpy(&_sectionb.data, &_sectioni, sizeof(struct section_iframe_t));
    section_test_handler(&_sectionb);

    _sectioni.cmd = 0x02;
    memcpy(&_sectionb.data, &_sectioni, sizeof(struct section_iframe_t));
    section_test_handler(&_sectionb);

    _sectioni.cmd = 0x03;
    memcpy(&_sectionb.data, &_sectioni, sizeof(struct section_iframe_t));
    section_test_handler(&_sectionb);

    _sectioni.cmd = 0x01;
    memcpy(&_sectionb.data, &_sectioni, sizeof(struct section_iframe_t));
    section_test_handler(&_sectionb);

    return 0;
}


PARSE_CMD(section, "section test", 0, do_section_test);


SECTION_TEST()定义数目不同,table 的length也不同。


你可能感兴趣的:(编程,C语言)