对于许多TI的芯片来说,引脚复用的配置是在Control Module(配置模块)的寄存器里配置的,(这个和三星的CPU有点不同,三星的一般在GPIO的寄存器中配置)。所以当你需要配置这些寄存器的时候,请到数据手册的Control Module的Pad Control Registers查找。

TI的CPU芯片手册有两种:

一种是datasheet(DS:数据手册),较小,只是大概介绍下芯片的结构;

另一种是Technical Reference Manual(TRM:技术参考手册),较大,详细介绍芯片的各部分功能原理和寄存器定义。

在开发过程中,这两个手册都需要参考,是互补的。

对于AM335X,关于引脚复用的列表及模式号与功能的对应可以在数据手册中找到:

2 Terminal Description:

2.2 Ball Characteristics

关于引脚复用寄存器定义及各引脚相应寄存器的偏移可以在TRM中找到:

9 Control Module

9.1 Control Module

9.1.3 Functional Description

9.1.3.2 Pad Control Registers (包含引脚复用寄存器定义)

9.1.5 Registers

9.1.5.1 CONTROL_MODULE Registers (包含引脚相应寄存器的偏移)

二、软件

由于TI的芯片构架类似,对于Linux内核来说,早就已经为这个做好了一个软件上的框架,无论是在启动的初始化阶段还是在系统运行时,都可以通过这个框架提供的接口函数配置芯片的MUX。下面就来简要的分析一下。

以AM335X为例,相关代码位置:arch/arm/mach-omap2

mux.h

mux.c

mux33xx.h

mux33xx.c

board-am335xevm.c

(还有一些用到了:arch/arm/plat-omap/include/plat/omap_hwmod.h)

其中他们的层次关系是:

(1)重要的数据结构

/**

* struct mux_partition - 包含分区相关信息

* @name: 当前分区名

* @flags: 本分区的特定标志

* @phys: 物理地址

* @size: 分区大小

* @base: ioremap 映射过的虚拟地址

* @muxmodes: 本分区mux节点链表头

* @node: 分区链表头

*/

struct omap_mux_partition {

const char        *name;

u32            flags;

u32            phys;

u32            size;

void __iomem        *base;

struct list_head    muxmodes;

struct list_head    node;

};

这个数据结构中包含了芯片中几乎所有定义好的mux的数据,它在mux数据初始化函数omap_mux_init中初始化,并添加到全局

mux_partitions链表中(通过node成员)。而其中的muxmodes是所有mux信息节点的链表头,用来链接以下数据结构:

/**

* struct omap_mux_entry - mux信息节点

* @mux: omap_mux结构体

* @node: 链表节点

*/

struct omap_mux_entry {

struct omap_mux        mux;

struct list_head    node;

};

而在以上数据结构中,struct omap_mux是记录单个mux节点数据的结构体:

/**

* struct omap_mux - omap mux 寄存器偏移和值的数据

* @reg_offset:    从Control Module寄存器基地址算起的mux寄存器偏移

* @gpio:    GPIO 编号

* @muxnames:    引脚可用的信号模式字符串指针数组

* @balls:    封装中可用的引脚

*/

struct omap_mux {

u16    reg_offset;

u16    gpio;

#ifdef CONFIG_OMAP_MUX

char    *muxnames[OMAP_MUX_NR_MODES];

#ifdef CONFIG_DEBUG_FS

char    *balls[OMAP_MUX_NR_SIDES];

#endif

#endif

};

而struct

mux_partition中muxmodes链表及其节点数据的初始化都是在omap_mux_init初始化函数中

(omap_mux_init_list(partition, superset);),而struct

omap_mux节点数据中信息是由mux33xx.h和mux33xx.c中提供的。你可以在mux33xx.c中看到一个巨大的struct

omap_mux结构体数组初始化代码,这个代码一看就明了。不同的芯片只需要根据芯片资料修改这个结构体就好了,但是am33xx的这个结构体(当前)

还不完善,gpio的数据还都是0。值得一提的是其中用到了一个宏:

#define _AM33XX_MUXENTRY(M0, g, m0, m1, m2, m3, m4, m5, m6, m7)        \

{                                    \

.reg_offset    = (AM33XX_CONTROL_PADCONF_##M0##_OFFSET),    \

.gpio        = (g),                        \

.muxnames    = { m0, m1, m2, m3, m4, m5, m6, m7 },        \

}

这个宏使得这个结构体数组的初始化变得清晰明了。

上的数据结构是在系统初始化的时候使用的,在struct

omap_mux_partition完成初始化后,omap_mux_init初始化函数最后会根据不同的板子初始化部分mux寄存器

(omap_mux_init_signals(partition, board_mux);),其中牵涉到了以下结构体:

/**

* struct omap_board_mux - 初始化mux寄存器的数据

* @reg_offset:    从Control Module寄存器基地址算起的mux寄存器偏移

* @mux_value:    希望设置的mux寄存器值

*/

struct omap_board_mux {

u16    reg_offset;

u16    value;

};

在最上层的板级初始化文件(board-am335xevm.c)中会定义一个这样的结构体数组,确定所要初始化的引脚复用寄存器,交由omap_mux_init_signals(partition, board_mux);使用。例如:

#ifdef CONFIG_OMAP_MUX

static struct omap_board_mux board_mux[] __initdata = {

AM33XX_MUX(I2C0_SDA, OMAP_MUX_MODE0 | AM33XX_SLEWCTRL_SLOW |

AM33XX_INPUT_EN | AM33XX_PIN_OUTPUT),

AM33XX_MUX(I2C0_SCL, OMAP_MUX_MODE0 | AM33XX_SLEWCTRL_SLOW |

AM33XX_INPUT_EN | AM33XX_PIN_OUTPUT),

{ .reg_offset = OMAP_MUX_TERMINATOR },

};

#else

#define    board_mux    NULL

#endif

其中用到了一个宏:

/* 如果引脚没有定义为输入,拉动电阻将会被禁用

* 如果定义为输入,所提供的标志位将确定拉动电阻的配置

*/

#define AM33XX_MUX(mode0, mux_value)                    \

{                                    \

.reg_offset    = (AM33XX_CONTROL_PADCONF_##mode0##_OFFSET),    \

.value        = (((mux_value) & AM33XX_INPUT_EN) ? (mux_value)\

: ((mux_value) | AM33XX_PULL_DISA)),    \

}

注意_AM33XX_MUXENTRY和AM33XX_MUX这两个宏,前者是用于struct omap_mux的;后者是用于struct omap_board_mux的。

(2)重要的接口函数

/**

* omap_mux_init - MUX初始化的私有函数,请勿使用

* 由各板级特定的MUX初始化函数调用

*/

int omap_mux_init(const char *name, u32 flags,

u32 mux_pbase, u32 mux_size,

struct omap_mux *superset,

struct omap_mux *package_subset,

struct omap_board_mux *board_mux,

struct omap_ball *package_balls);

这个函数是内部用于初始化struct mux_partition的最总要的函数,但是这个函数并不作为接口函数使用,而是供各芯片初始化函数“*_mux_init”所使用的。比如AM33XX芯片:

/**

* am33xx_mux_init() - 用板级特定的设置来初始化MUX系统

* @board_mux:        板级特定的MUX配置表

*/

int __init am33xx_mux_init(struct omap_board_mux *board_subset)

{

return omap_mux_init("core", 0, AM33XX_CONTROL_PADCONF_MUX_PBASE,

AM33XX_CONTROL_PADCONF_MUX_SIZE, am33xx_muxmodes,

NULL, board_subset, NULL);

}

有了已经初始化好的struct mux_partition结构体,我们可以利用mux.h提供的许多函数方便的初始化各mux寄存器:

/**

* omap_mux_init_signal - 根据信号名字符串初始化一个引脚的mux

* @muxname:        mode0_name.signal_name的格式的Mux名称

* @val:        mux寄存器值

*/

int omap_mux_init_signal(const char *muxname, int val);

/**

* omap_mux_get() - 通过名字返回一个mux分区

* @name:        mux分区名

*

*/

struct omap_mux_partition *omap_mux_get(const char *name);

/**

* omap_mux_read() - 读取mux寄存器(通过分区结构体指针和寄存器偏移值)

* @partition:        Mux分区

* @mux_offset:        mux寄存器偏移

*

*/

u16 omap_mux_read(struct omap_mux_partition *p, u16 mux_offset);

/**

* omap_mux_write() - 写mux寄存器(通过分区结构体指针和寄存器偏移值)

* @partition:        Mux分区

* @val:        新的mux寄存器值

* @mux_offset:        mux寄存器偏移

*

* 这个函数仅有在非GPIO信号的动态复用需要

*/

void omap_mux_write(struct omap_mux_partition *p, u16 val, u16 mux_offset);

/**

* omap_mux_write_array() - 写mux寄存器阵列

* @partition:        Mux分区

* @board_mux:        mux寄存器阵列 (用MAP_MUX_TERMINATOR结尾)

*

* 这个函数仅有在非GPIO信号的动态复用需要

*/

void omap_mux_write_array(struct omap_mux_partition *p,

struct omap_board_mux *board_mux);

在代码比较完备的芯片中,struct omap_mux中的gpio成员有被初始化过,这样就可以使用以下接口函数:

/**

* omap_mux_init_gpio - 根据GPIO编号初始化一个信号引脚

* @gpio:        GPIO编号

* @val:        mux寄存器值

*/

int omap_mux_init_gpio(int gpio, int val);

/**

* omap_mux_get_gpio() - 根据GPIO编号获取一个mux寄存器值

* @gpio:        GPIO编号

*

*/

u16 omap_mux_get_gpio(int gpio);

/**

* omap_mux_set_gpio() - 根据GPIO编号设定一个mux寄存器值

* @val:        新的mux寄存器值

* @gpio:        GPIO编号

*

*/

void omap_mux_set_gpio(u16 val, int gpio);

但是am33xx的gpio成员(当前)还都是0,所有这些函数没法使用。

此外,在mux.h中还导出了其他的软件接口和数据结构,这些在am33xx中没有使用,有需要的时候再看。

在板级初始化代码(比如board-am335xevm.c)运行完芯片特定的MUX初始化函数

(am33xx_mux_init(board_mux);)之后,也可以在各子系统初始化时通过上面的接口函数修改配置MUX,比如在am33xx中使

用了自己封装的一个函数和结构体:

/* 模块引脚复用结构体 */

struct pinmux_config {

const char *string_name; /* 信号名格式化字符串,“模式0字符串.目标模式字符串“ */

int val; /* 其他mux寄存器可选配置值 */

};

/*

* @pin_mux - 单个模块引脚复用结构体

*            其中定义了本模块所有引脚复用细节.

*/

static void setup_pin_mux(struct pinmux_config *pin_mux)

{

int i;

for (i = 0; pin_mux->string_name != NULL; pin_mux++)

omap_mux_init_signal(pin_mux->string_name, pin_mux->val);

}

你可以在board-am335xevm.c中看到如下的代码:

static struct pinmux_config d_can_ia_pin_mux[] = {

{"uart0_rxd.d_can0_tx", OMAP_MUX_MODE2 | AM33XX_PULL_ENBL},

{"uart0_txd.d_can0_rx", OMAP_MUX_MODE2 | AM33XX_PIN_INPUT_PULLUP},

{NULL, 0},

};

......

static void d_can_init(int evm_id, int profile)

{

switch (evm_id) {

case IND_AUT_MTR_EVM:

if ((profile == PROFILE_0) || (profile == PROFILE_1)) {

setup_pin_mux(d_can_ia_pin_mux);

/* Instance Zero */

am33xx_d_can_init(0);

}

break;

case GEN_PURP_EVM:

if (profile == PROFILE_1) {

setup_pin_mux(d_can_gp_pin_mux);

/* Instance One */

am33xx_d_can_init(1);

}

break;

default:

break;

}

}

三、使用注意

上面初始化过的结构体和接口函数的定义都是带有"__init"和“__initdata”的,所以这些都只能在内核初始化代码中使用,一旦系统初始化结束并进入了文件系统,这些定义都会被free。所有它们不能在内核模块(.ok)中被调用,否则你就等着Oops吧。因为一个芯片的引脚复用一般是硬件设计的时候定死的,一般不可能在启动后更改。如果你是在要在模块中改变引脚复用配置,你只能通过自己ioremap相关寄存器再修改它们来实现。

安卓 体验linux mux,Linux下TI omap芯片 MUX 配置分析(以AM335X芯片为例)相关推荐

  1. Linux(Ubuntu 16) 下Java开发环境的配置(二)------Tomcat的配置及常见问题

    前言 相比于java JDK的配置,Tomcat的配置简单的多,简直就相当于直接运行了,本文以Tomcat8.0为例进行配置 1.Tomcat的下载 地址:https://tomcat.apache. ...

  2. Linux下TI omap芯片 MUX 配置分析(以AM335X芯片为例)

    在移植内核的时候,通常会遇到引脚复用(MUX)的配置问题.在现在的Linux内核中,对于TI的ARM芯片,早已经有了比较通用的MUX配置框架.这对于许多TI的芯片都是通用的,这次看AM335X的代码顺 ...

  3. Linux和window下tomcat虚拟路径的配置方式

    配置Linux下tomcat虚拟路径: 找到linux下的server.xml文件,在<Host>标签内进行如下配置 <Host name="localhost" ...

  4. realvnc 6 教程 linux,CentOS 6下VNC的安装与配置

    一.下载安装 可到http://www.realvnc.com/下载最新版的vnc 包括linux下的vnc server 和windows下的vnc view [root@ linux ~]# cd ...

  5. linux重装eclipse_linux下安装eclipse时如何配置.

    linux下安装eclipse时如何配置. linux下安装eclipse时如何配置. 方法一: 只要设置的java的环境变量剩下的就和windows一样了 设置环境变量如下: vi ~/.bash_ ...

  6. Linux(Ubuntu 16) 下Java开发环境的配置(一)------JDK的配置

    前言: 本文介绍的是通用的安装方法,一般linux系统均可使用该方法安装.本文以Java8环境为例进行配置. 1.JDK的下载 进入java下载页(http://www.oracle.com/tech ...

  7. Linux终端模式下查看电脑的硬件配置信息小技巧

    原文地址:http://os.51cto.com/art/200803/67281.htm 在图形模式下我们可以很方便的利用Linux的图形工具,点击几下就可以查看到Linux系统的的硬件信息.但是大 ...

  8. linux(CentOS6)下的wifi热点安装配置------hostapd-2.0

    linux下wifi软热点---hostapd-2.0 有兴趣的朋友可以参看下面网站: http://w1.fi/hostapd/ http://www.ibm.com/developerworks/ ...

  9. Linux 6.x 下Oracle 11g R2 安装配置

    Oracle 11g R2 数据库安装硬件配置要求: 最小内存 1 GB of RAM 虚拟内存容量,这个oracle也有要求,不用担心此时的swap分区不够oracle的要求 .虚拟内存swap如何 ...

最新文章

  1. chrome 技巧篇-如何查看web元素绑定的监听事件
  2. 开发者福利:史上最全Android 开发和安全系列工具
  3. OpenGL fragmentlist片段列表的实例
  4. java上传png_java上传png图片出现红色背景
  5. C语言内存动态分配与释放
  6. win11正式版iso镜像如何安装 windows11正式版iso镜像安装方法
  7. python聊天室详细教程_Python基础教程书籍案例:在线聊天室(虚拟茶话会)【下】...
  8. jdbc map获取keys_小前端读源码 - React(浅析Keys原理)
  9. java即时通讯源码 IM即时通讯源码 IM源码 安卓苹果原生APP源码 带音视频无标题】
  10. opencv下载百度网盘链接及安装
  11. MySQL多实例管理(mysqld_multi)
  12. java列名无效_Java:列名无效
  13. html中将字体设置成透明的,解决css设置背景透明,文字不透明_html/css_WEB-ITnose
  14. 通用能力-判断推理题
  15. 第一届安洵杯writeup
  16. oracle远程导入数据库
  17. 【6GHz矩形贴片天线设计与分析】
  18. 红米Note9Pro和红米Note9ProMax哪个好-区别是什么
  19. 【新知实验室】实时音视频(TRTC)之初体验
  20. 场景拆解六步设计法,手把手教你细化场景

热门文章

  1. Placement Rules 使用文档
  2. 一个小游戏的代码(猜数字)
  3. 长沙哪个服务器网速最快,5G网络湖南长沙首秀?网速是4G的60倍,快的让人无法想象...
  4. 3.28~~3.29
  5. 【转】美剧字幕长讲述她如何练听力的
  6. su联合推拉使用方法_紫天学习星球教学:联合推拉插件完全功能使用详解(中文)...
  7. tcl/tk参考——tcl内建命令
  8. unity基础(3)——从Unity Asset store获取资源
  9. 通过U盘安装系统时,提示无法在驱动器分区上安装windows的解决办法
  10. t分布, 卡方x分布,F分布