当前位置: 首页 > news >正文

linker list

linker list是利用lds 描述符实现同类型数据连续排布的一种机制。
下面是uboot里面的应用说明

lds文件里面需要增加section描述:

. = ALIGN(4);.u_boot_list : {KEEP(*(SORT(.u_boot_list*)));}

linker_list.h:

/* SPDX-License-Identifier: GPL-2.0+ */
/** include/linker_lists.h** Implementation of linker-generated arrays** Copyright (C) 2012 Marek Vasut <marex@denx.de>*/#ifndef __LINKER_LISTS_H__
#define __LINKER_LISTS_H__#include <linux/compiler.h>/** There is no use in including this from ASM files.* So just don't define anything when included from ASM.*/#if !defined(__ASSEMBLY__)/*** llsym() - Access a linker-generated array entry* @_type:	Data type of the entry* @_name:	Name of the entry* @_list:	name of the list. Should contain only characters allowed*		in a C variable name!*/
#define llsym(_type, _name, _list) \((_type *)&_u_boot_list_2_##_list##_2_##_name)/*** ll_entry_declare() - Declare linker-generated array entry* @_type:	Data type of the entry* @_name:	Name of the entry* @_list:	name of the list. Should contain only characters allowed*		in a C variable name!** This macro declares a variable that is placed into a linker-generated* array. This is a basic building block for more advanced use of linker-* generated arrays. The user is expected to build their own macro wrapper* around this one.** A variable declared using this macro must be compile-time initialized.** Special precaution must be made when using this macro:** 1) The _type must not contain the "static" keyword, otherwise the*    entry is generated and can be iterated but is listed in the map*    file and cannot be retrieved by name.** 2) In case a section is declared that contains some array elements AND*    a subsection of this section is declared and contains some elements,*    it is imperative that the elements are of the same type.** 3) In case an outer section is declared that contains some array elements*    AND an inner subsection of this section is declared and contains some*    elements, then when traversing the outer section, even the elements of*    the inner sections are present in the array.** Example:** ::**   ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {*           .x = 3,*           .y = 4,*   };*/
#define ll_entry_declare(_type, _name, _list)				\_type _u_boot_list_2_##_list##_2_##_name __aligned(4)		\__attribute__((unused,				\section(".u_boot_list_2_"#_list"_2_"#_name)))/*** ll_entry_declare_list() - Declare a list of link-generated array entries* @_type:	Data type of each entry* @_name:	Name of the entry* @_list:	name of the list. Should contain only characters allowed*		in a C variable name!** This is like ll_entry_declare() but creates multiple entries. It should* be assigned to an array.** ::**   ll_entry_declare_list(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {*        { .x = 3, .y = 4 },*        { .x = 8, .y = 2 },*        { .x = 1, .y = 7 }*   };*/
#define ll_entry_declare_list(_type, _name, _list)			\_type _u_boot_list_2_##_list##_2_##_name[] __aligned(4)		\__attribute__((unused,				\section(".u_boot_list_2_"#_list"_2_"#_name)))/** We need a 0-byte-size type for iterator symbols, and the compiler* does not allow defining objects of C type 'void'. Using an empty* struct is allowed by the compiler, but causes gcc versions 4.4 and* below to complain about aliasing. Therefore we use the next best* thing: zero-sized arrays, which are both 0-byte-size and exempt from* aliasing warnings.*//*** ll_entry_start() - Point to first entry of linker-generated array* @_type:	Data type of the entry* @_list:	Name of the list in which this entry is placed** This function returns ``(_type *)`` pointer to the very first entry of a* linker-generated array placed into subsection of .u_boot_list section* specified by _list argument.** Since this macro defines an array start symbol, its leftmost index* must be 2 and its rightmost index must be 1.** Example:** ::**   struct my_sub_cmd *msc = ll_entry_start(struct my_sub_cmd, cmd_sub);*/
#define ll_entry_start(_type, _list)					\
({									\static char start[0] __aligned(4) __attribute__((unused,	\section(".u_boot_list_2_"#_list"_1")));			\(_type *)&start;						\
})/*** ll_entry_end() - Point after last entry of linker-generated array* @_type:	Data type of the entry* @_list:	Name of the list in which this entry is placed*		(with underscores instead of dots)** This function returns ``(_type *)`` pointer after the very last entry of* a linker-generated array placed into subsection of .u_boot_list* section specified by _list argument.** Since this macro defines an array end symbol, its leftmost index* must be 2 and its rightmost index must be 3.** Example:** ::**   struct my_sub_cmd *msc = ll_entry_end(struct my_sub_cmd, cmd_sub);*/
#define ll_entry_end(_type, _list)					\
({									\static char end[0] __aligned(4) __attribute__((unused,		\section(".u_boot_list_2_"#_list"_3")));			\(_type *)&end;							\
})
/*** ll_entry_count() - Return the number of elements in linker-generated array* @_type:	Data type of the entry* @_list:	Name of the list of which the number of elements is computed** This function returns the number of elements of a linker-generated array* placed into subsection of .u_boot_list section specified by _list* argument. The result is of an unsigned int type.** Example:** ::**   int i;*   const unsigned int count = ll_entry_count(struct my_sub_cmd, cmd_sub);*   struct my_sub_cmd *msc = ll_entry_start(struct my_sub_cmd, cmd_sub);*   for (i = 0; i < count; i++, msc++)*           printf("Entry %i, x=%i y=%i\n", i, msc->x, msc->y);*/
#define ll_entry_count(_type, _list)					\({								\_type *start = ll_entry_start(_type, _list);		\_type *end = ll_entry_end(_type, _list);		\unsigned int _ll_result = end - start;			\_ll_result;						\})/*** ll_entry_get() - Retrieve entry from linker-generated array by name* @_type:	Data type of the entry* @_name:	Name of the entry* @_list:	Name of the list in which this entry is placed** This function returns a pointer to a particular entry in linker-generated* array identified by the subsection of u_boot_list where the entry resides* and it's name.** Example:** ::**   ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {*           .x = 3,*           .y = 4,*   };*   ...*   struct my_sub_cmd *c = ll_entry_get(struct my_sub_cmd, my_sub_cmd, cmd_sub);*/
#define ll_entry_get(_type, _name, _list)				\({								\extern _type _u_boot_list_2_##_list##_2_##_name;	\_type *_ll_result =					\&_u_boot_list_2_##_list##_2_##_name;		\_ll_result;						\})/*** ll_start() - Point to first entry of first linker-generated array* @_type:	Data type of the entry** This function returns ``(_type *)`` pointer to the very first entry of* the very first linker-generated array.** Since this macro defines the start of the linker-generated arrays,* its leftmost index must be 1.** Example:** ::**   struct my_sub_cmd *msc = ll_start(struct my_sub_cmd);*/
#define ll_start(_type)							\
({									\static char start[0] __aligned(4) __attribute__((unused,	\section(".u_boot_list_1")));				\(_type *)&start;						\
})/*** ll_end() - Point after last entry of last linker-generated array* @_type:	Data type of the entry** This function returns ``(_type *)`` pointer after the very last entry of* the very last linker-generated array.** Since this macro defines the end of the linker-generated arrays,* its leftmost index must be 3.** Example:** ::**   struct my_sub_cmd *msc = ll_end(struct my_sub_cmd);*/
#define ll_end(_type)							\
({									\static char end[0] __aligned(4) __attribute__((unused,		\section(".u_boot_list_3")));				\(_type *)&end;							\
})#endif /* __ASSEMBLY__ */#endif	/* __LINKER_LISTS_H__ */

ll_entry_declare_list 和ll_entry_declare差别是前者是数组声明,一次可以声明多个条目,后者只声明(定义)一个条目。

ll_entry_start(_type, _list) 获取该类型列表首个条目地址

ll_entry_get(_type, _name, _list) 根据名字 返回条目地址

ll_entry_count(_type, _list) 返回该类型条目数

使用实例

参考driver的定义:

struct driver {char *name;enum uclass_id id;const struct udevice_id *of_match;int (*bind)(struct udevice *dev);int (*probe)(struct udevice *dev);int (*remove)(struct udevice *dev);int (*unbind)(struct udevice *dev);int (*ofdata_to_platdata)(struct udevice *dev);int (*child_post_bind)(struct udevice *dev);int (*child_pre_probe)(struct udevice *dev);int (*child_post_remove)(struct udevice *dev);int priv_auto_alloc_size;int platdata_auto_alloc_size;int per_child_auto_alloc_size;int per_child_platdata_auto_alloc_size;const void *ops;	/* driver-specific operations */uint32_t flags;
};/* Declare a new U-Boot driver */
#define U_BOOT_DRIVER(__name)						\ll_entry_declare(struct driver, __name, driver)

usb hub driver

U_BOOT_DRIVER(usb_generic_hub) = {
.name = “usb_hub”,
.id = UCLASS_USB_HUB,
.of_match = usb_hub_ids,
.flags = DM_FLAG_ALLOC_PRIV_DMA,
};

相关文章:

linker list

linker list是利用lds 描述符实现同类型数据连续排布的一种机制。 下面是uboot里面的应用说明 lds文件里面需要增加section描述&#xff1a; . ALIGN(4);.u_boot_list : {KEEP(*(SORT(.u_boot_list*)));}linker_list.h: /* SPDX-License-Identifier: GPL-2.0 */ /** include…...

[CUDA手搓]从零开始用C++ CUDA搭建一个卷积神经网络(LeNet),了解神经网络各个层背后算法原理

文章目录 前言一、所需环境二、实现思路2.1. 定义了LeNet网络模型结构&#xff0c;并训练了20次2.2 以txt格式导出训练结果(模型的各个层权重偏置等参数)2.3 (可选)以pth格式导出训练结果&#xff0c;以方便后期调试2.4 C CUDA要做的事 三、C CUDA具体实现3.1 新建.cu文件并填好…...

【开源】基于JAVA+Vue+SpringBoot的数据可视化的智慧河南大屏

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 数据模块 A4.2 数据模块 B4.3 数据模块 C4.4 数据模块 D4.5 数据模块 E 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的数据可视化的智慧河南大屏&#xff0c;包含了GDP、…...

页面单跳转换率统计案例分析

需求说明 页面单跳转化率 计算页面单跳转化率&#xff0c;什么是页面单跳转换率&#xff0c;比如一个用户在一次 Session 过程中访问的页面路径 3,5,7,9,10,21&#xff0c;那么页面 3 跳到页面 5 叫一次单跳&#xff0c;7-9 也叫一次单跳&#xff0c; 那么单跳转化率就是要统计…...

眸思MouSi:“听见世界” — 用多模态大模型点亮盲人生活

文章目录 1. Introduction1.1 APP细节展示2. Demo2.1 论文链接2.2 联系方式3. Experiment3.1 多专家的结合是否有效?3.2 如何更好的将多专家整合在一起?Reference让盲人听见世界,复旦眸思大模型打破视觉界限,用科技点亮新生活 1. Introduction 在这个世界上,视力是探索万…...

电商小程序05用户注册

目录 1 搭建页面2 设置默认跳转总结 我们上一篇拆解了登录功能&#xff0c;如果用户没有账号就需要注册了。本篇我们介绍一下注册功能的实现。 1 搭建页面 打开应用&#xff0c;点击左上角的新建页面 输入页面的名称&#xff0c;用户注册 删掉网格布局&#xff0c;添加表单容…...

什么是UI设计?

用户界面&#xff08;UI&#xff09;它是人与机器互动的载体&#xff0c;也是用户体验&#xff08;UX&#xff09;一个组成部分。用户界面由视觉设计 (即传达产品的外观和感觉) 和交互设计 (即元素的功能和逻辑组织) 两部分组成。用户界面设计的目标是创建一个用户界面&#xf…...

React 实现表单组件

表单是html的基础元素&#xff0c;接下来我会用React实现一个表单组件。支持包括输入状态管理&#xff0c;表单验证&#xff0c;错误信息展示&#xff0c;表单提交&#xff0c;动态表单元素等功能。 数据状态 表单元素的输入状态管理&#xff0c;可以基于react state 实现。 …...

PlantUML绘制UML图教程

UML&#xff08;Unified Modeling Language&#xff09;是一种通用的建模语言&#xff0c;广泛用于软件开发中对系统进行可视化建模。PlantUML是一款强大的工具&#xff0c;通过简单的文本描述&#xff0c;能够生成UML图&#xff0c;包括类图、时序图、用例图等。PlantUML是一款…...

自学Python第二十二天- Django框架(六) django的实用插件:cron、APScheduler

django-crontab 和 django-cron 有时候需要django在后台不断的执行一个任务&#xff0c;简单的可以通过中间件来实现&#xff0c;但是中间件是根据请求触发的。如果需要定时执行任务&#xff0c;则需要使用到一些插件。 django-crontab 和 django-cron 是常用的用于处理定时任…...

医院挂号预约|医院挂号预约小程序|基于微信小程序的医院挂号预约系统设计与实现(源码+数据库+文档)

医院挂号预约小程序目录 目录 基于微信小程序的医院挂号预约系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、小程序用户端 2、系统服务端 &#xff08;1&#xff09; 用户管理 &#xff08;2&#xff09;医院管理 &#xff08;3&#xff09;医生管理 &…...

网络选择流程分析(首选网络类型切换流程)

首先是界面,我在此平台的界面如下: 对应的入口源码位置在Settings的UniEnabledNetworkModePreferenceController中,当然其他平台可能在PreferredNetworkModePreferenceController中,流程上都是大同小异 然后点击切换按钮会调用到UniEnabledNetworkModePreferenceControlle…...

AutoSAR(基础入门篇)6.1-Vector的汽车电子开发工具链简介

目录 前言 一、PREEvision 二、vVIRTUALtarget 三、DaVinci 四、CANoe 五、CANape 其他 前言 因为国内用...

TI的电量计驱动在卸载时导致Linux卡死

背景 最近移植TI电量计芯片bq40z50的驱动&#xff0c;移植完毕后&#xff0c;能正常读取电池信息了&#xff0c;但是无意中发现驱动卸载会导致Linux卡死&#xff0c;死前终端闪过大量打印&#xff0c;将putty的缓冲区都耗尽了&#xff0c;必须启用syslog转发并用visual syslog…...

使用yolo训练自己的模型

YOLO&#xff08;You Only Look Once&#xff09;是一种用于目标检测的深度学习模型&#xff0c;旨在实时检测图像或视频中的多个对象。与传统的目标检测方法不同&#xff0c;YOLO一次性处理整个图像&#xff0c;而不是通过滑动窗口或区域提议进行多次检测。这种方法使得YOLO在…...

堆的概念实现

前言 本文将详细讲解堆。堆是一种二叉树&#xff08;一般是完全二叉树&#xff09;使用顺序结构的数组来存储。 tip&#xff1a;这里我们需要注意区分堆在不同地方的含义&#xff0c;这里的堆是一个数据结构&#xff0c;操作系统虚拟进程地址空间的堆是操作系统中管理内存的一块…...

Redis(三)主从架构、Redis哨兵架构、Redis集群方案对比、Redis高可用集群搭建、Redis高可用集群之水平扩展

转自 极客时间 Redis主从架构 redis主从架构搭建&#xff0c;配置从节点步骤&#xff1a; 1、复制一份redis.conf文件2、将相关配置修改为如下值&#xff1a; port 6380 pidfile /var/run/redis_6380.pid # 把pid进程号写入pidfile配置的文件 logfile "6380.log" …...

pnpm + vite 从外网迁移到内网环境开发

离线安装pnpm 在有外网的机器上执行以下命令&#xff0c;下载pnpm的tgz压缩包至桌面&#xff0c;注意下载版本和当前使用版本保持一致 npm pack -g pnpm7.4.0 --pack-destination ~/Desktop将tgz压缩包拷贝至离线机器在离线机器中执行命令 npm -g i /home/user/offline/pnpm…...

寒假作业7

sql语句 创建表格 create table 表名 &#xff08;字段名 数据类型&#xff0c;字段名 数据类型&#xff09; create table if not exists 表名 &#xff08;字段名 数据类型&#xff0c; 字段名 数据类型&#xff09; 删除表格 drop table 表名&#xff1b; 插入记录 全字…...

【0257】关于pg内核shared cache invalidation messages (概念篇)

文章目录 1. inval messages2. 可配置参数(Configurable parameters)1. inval messages 所谓“共享缓存无效消息(shared cache invalidation messages)”,从概念上讲,共享缓存无效消息存储在一个无限数组中,其中maxMsgNum是存储提交消息的下一个数组下标, minMsgNum是…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...