提到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也不同。