开发指南
本文档提供 XSTAR 开发的详细指南,包括代码规范、驱动开发、命令开发、测试等内容。快速上手见快速开始,架构背景见架构设计。
目录
代码规范
文件命名
- 源文件:
kebab-case.c(如clk-fixed.c、i2c-gpio.c) - 头文件:
kebab-case.h(与源文件同名)
文件头注释
每个源文件必须包含 MIT 许可证头:
/*
* driver/clk/clk-fixed.c
*
* Copyright(c) Jianjun Jiang <8192542@qq.com>
*
* 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.
*/
代码格式
- 缩进:使用 Tab(不使用空格)
- 行宽:约 120 字符(不严格强制,但保持合理)
- 大括号:函数和控制结构使用 Allman 风格(左大括号在下一行);struct/enum 定义和初始化列表使用 K&R 风格(左大括号在同一行)
- 注释:尽量减少注释,不主动添加代码注释(除非明确要求);现有代码中的设备树文档注释和结构体字段注释仅供参考
命名规范
- 函数:
snake_case(如clk_fixed_probe、register_driver) - 变量:
snake_case(如pdat、rate、kobj) - 类型:
snake_case_t后缀(如struct driver_t、enum device_type_t) - 常量:
ALL_CAPS_WITH_UNDERSCORES(如DEVICE_TYPE_MAX_COUNT、TRUE、FALSE) - 宏:
ALL_CAPS(如ARRAY_SIZE、container_of、offsetof)
头文件保护
格式:__PATH_TO_FILE_H__,示例:
#ifndef __XSTAR_DRIVER_CLK_H__
#define __XSTAR_DRIVER_CLK_H__
/* 头文件内容 */
#endif /* __XSTAR_DRIVER_CLK_H__ */
包含顺序
#include <xstar.h>
#include <xos/xos.h>
#include <driver/clk/clk.h>
- 本地项目头文件(
#include <xstar.h>或#include <xos/xos.h>) - 驱动/内核头文件(如
#include <driver/clk/clk.h>) - 标准/外部头文件(如果有)
错误处理
- 布尔函数:成功返回
TRUE,失败返回FALSE - 指针函数:成功返回指针,失败返回
NULL - 始终检查返回值
- 错误路径中清理分配的资源
static struct device_t * my_probe(struct driver_t * drv, struct dtnode_t * n)
{
struct xxx_pdata_t *pdat;
struct xxx_t *xxx;
pdat = xos_mem_malloc(sizeof(struct xxx_pdata_t));
if(!pdat)
return NULL;
xxx = xos_mem_malloc(sizeof(struct xxx_t));
if(!xxx)
{
xos_mem_free(pdat);
return NULL;
}
/* 初始化和注册 */
return dev;
}
类型使用
使用标准类型(通过 <xos/xos.h> 经 <xstarcfg.h> 提供):
uint8_t、uint16_t、uint32_t、uint64_tint8_t、int16_t、int32_t、int64_tsize_t、ssize_tio_addr_tNULL、TRUE、FALSE(从libx/xdef.h)
驱动开发
驱动模板
#include <xstar.h>
#include <driver/xxx/xxx.h>
struct xxx_pdata_t {
/* 私有数据 */
};
static struct device_t * xxx_probe(struct driver_t * drv, struct dtnode_t * n)
{
struct xxx_pdata_t *pdat;
/* 解析设备树属性 */
const char *name = dt_read_string(n, "name", NULL);
int value = dt_read_int(n, "value", 0);
/* 分配私有数据 */
pdat = xos_mem_malloc(sizeof(struct xxx_pdata_t));
if(!pdat)
return NULL;
/* 初始化硬件 */
/* 创建并注册设备 */
return register_xxx(drv, pdat);
}
static void xxx_remove(struct device_t * dev)
{
struct xxx_pdata_t *pdat = (struct xxx_pdata_t *)dev->priv;
/* 释放资 源 */
xos_mem_free(pdat);
}
static void xxx_suspend(struct device_t * dev)
{
}
static void xxx_resume(struct device_t * dev)
{
}
static struct driver_t xxx_driver = {
.name = "xxx-driver",
.probe = xxx_probe,
.remove = xxx_remove,
.suspend = xxx_suspend,
.resume = xxx_resume,
};
static void xxx_driver_init(void)
{
register_driver(&xxx_driver);
}
static void xxx_driver_exit(void)
{
unregister_driver(&xxx_driver);
}
driver_initcall(xxx_driver_init);
driver_exitcall(xxx_driver_exit);
设备树配置
在 romdisk/dtree/default.json 中添加设备配置:
{
"xxx-driver:0": {
"name": "my-device",
"value": 42
}
}
设备树键名格式为 "driver-name:id@address":
driver-name:驱动名称,必须与driver_t.name匹配id:设备实例编号(可选)address:物理地址(可选)
设置 "status": "disabled" 可跳过设备探测。
设备属性读取
| 函数 | 返回类型 | 说明 |
|---|---|---|
dt_read_string(n, name, def) | char * | 读取字符串 |
dt_read_int(n, name, def) | int | 读取整数 |
dt_read_long(n, name, def) | long long | 读取长整数 |
dt_read_bool(n, name, def) | int | 读取布尔值 |
dt_read_double(n, name, def) | double | 读取双精度浮点 |
dt_read_object(n, name) | struct dtnode_t | 读取子对象 |