1.1.AHB介绍

高级高性能总线简单点理解就是一条架在处理器CPU与内存与外设之间的通信渠道,大家相互之间需要遵循此总线的约束协议,然后就能在高频时钟的驱动下进行数据交互,交互是总线的核心要义。我开始理解与接触总线是先搜索的 RCC->AHB1ENR|=1<<5;这条语句是如何调用AHB总线的,芯片是如何解析这条指令的,结果在百度与谷歌引擎下都没有搜到相关的内容。(难道是太简单了,没有人来讲解与问这种问题,好吧,懂的都懂。。。)

1.2.AHB交互过程

机缘巧合之下(朋友搜到的)得到了一本神书——《ARM Cortex-M0 全可编程SoC原理及实现》不得不说这本书的作者太懂底层的人了,讲解的很细致,哪怕一个小知识点都给你说明一遍,从Cortex的寄存器,汇编指令,中断与异常开始讲解,将Cortex M3内核的内容都进行了浓缩,学习arm内核的神书,建议大家支持正版。
首先从通信双方数据交互的层面说一下总线是如何通信的,CPU根据用户编译生成的二进制文件(还是理解为汇编吧,好理解些),比如一些寄存器操作指令 MOV、MOVS、STR、LDR指令等,就涉及到读取与写入地址,而这些地址与数据就写在了AHB总线的不同总线中;
RCC->AHB1ENR|=1<<5; --假定地址转换后为(uint32_t volatile *) 0x40000000 = 0x20;
M0 的AHB总线有三个信号:32位数据总线(分为写数据总线与读数据总线)-0x20就在写数据总线中;32位地址总线-0x40000000就在地址总线中;控制信号-用于同步与识别,比如此处用于写入地址,那么控制信号 HWRITE就是高电平,还有几条控制信号,一会儿再讲。
有点尴尬,书上是用的读取数据来举例,道理类似,先看图。

(1)处理器先将需要读取的地址写到地址总线上,译码器会根据地址,译码分路出该地址区域的一个片选信号HSEL为高电平,并且读操作时写控制信号HWRITE就是低电平表示是读取操作。
(2)而对应要被读的外设就应该要在自己的模块中做出响应(准确来说是随时都在将数据放在自己的读数据总线上),多路复用器就根据HSEL信号,被选中模块外设生成的准备信号YOUT,将该模块总线的数据总线数据映射到AHB的RWATA(读)数据总线上,这样处理器读取RWATA数据总线的数据并保存就是一次完整的数据读取流程。也就是说你拿到了你想要拿的地址的数据值。

1.3.AHB的内部构成

前面提到了地址译码器与多路复用器,这都是AHB总线里面的分模块,正是这两个负责选择的模块才能让总线有选择的操作哪个外设地址。
1.3.1.地址译码器

作用一目了然,就是输入32位地址,然后根据地址选通S0 S1 …中的哪一个,被选通的那个信号就很重要,在模块实现与复用器里面都要用到这个信号作为核心的判断依据。输出MUL_HSL是将所有片选的HSEL信号聚合为一个四位数据,与HSEL信号是同步产生的。
实现就类似于这种

一目了然,Verilog case就是C语言里的switch语句,分路选择的功能。
1.3.2.数据复用器

多路复用器功能也一目了然,输出就两个:一个是 RWATA数据总线,也就是AHB的读取数据总线,专用于外设到处理器的数据传输通道,内部实现是将S0 S1…等的数据总线数据根据译码器输出的多路组合MUL_HSL[3:0]的数据位来选通是哪个外设的数据总线映射到RWATA上;HREADY输出信号则是直接等于选通外设产生的HREADYOUT_Sx。
1.3.3.控制线

如图中模块是实现中,输入中除了HCLK(时钟) HREST(复位) HSEL (译码片选)HADDR(地址总线) HWDATA (写数据总线)这些是上面提到的,当然key是用户设定的按键输入口,跟总线没关系,其余的就是控制信号。
书上要清楚全面些

HSIZE;由处理器指向从设备的表示传输的数据宽度是字,字节,半字。(汇编指令中有对应的操作指令如STRH)
HTRANS;由处理器指向从设备的表示处理器当前的传输状态,在繁忙态时是不希望有任何读写操作。[1:0]可以有四种状态 IDEL,BUSY,NONSEQUENTIAL,SEQUENTIAL。
HWRITE;由处理器产生用来表示当前是写还是读操作,STR就是写,HWRITE就是高电平,LDR就是读,HWRITE是低电平。
HPORT与HBURST是一些内核的高级功能需要使用的地方,我们就不深究了,书上有讲解什么意思我没用,就不瞎讲。

1.4.实现过程与理解

比如说你在地址译码器先划分了不同地址区域的片选信号,然后你要往某一个地址写一个数据或读取数据,(uint32_t volatile *)0x51000008 假设这就是你要操作的地址,如果你代码是用在的左值,那就是写操作,0x51000008 = 1;对应的汇编可以看看,也就是分别向51000008与51000004写数据1;

地址译码HSEL对应的区域就会被拉高,对芯片内核来说呢,编译后识别到汇编的代码是STR指令,就像51芯片一样,你使用mov指令时,芯片的/R引脚就会自动输出低电平一样,控制线的HWRITE就会输出高电平,HADDR[31:0] 就是你要写的地址值,WDATE[31:0]就是你的数据1,的对应的接收模块里面就要设置接收判断,接收并保存这个数据就可以了,仿真图如图

因为FPGA是时钟对齐的,写入数据要先判断HSEL因此数据就会在下一个时钟。
又比如接收芯片发过来的数据;你代码是用在的右值,那就是读操作 i = (uint32_t volatile *)0x51000008; 对应的汇编可以看看是啥,

地址译码HSEL对应的区域就会被拉高,控制线的HWRITE就会输出低电平表示读,HADDR[31:0] 就是你要读的地址值,此时是RDATA[31:0] 与数据复用器在起作用,数据复用器会根据生成的HSEL芯片选择对应的RDATA到复用器的输出总线上,这样芯片读总线的数据那就是模块返回的数据了。如仿真图。

附上启动代码与对应的C代码。


总结:

以上呢就是我对Cortex内核总线AHB的一些实现过程的了解,虽然是最简单的读写操作,但是在整个AHB总线中也就只有读写,具有复杂功能的外设只是在外设实现中有复杂的逻辑判断,因此在设计c代码的时候就要配置这样寄存器那样寄存器,核心就是在于数据的传送。当然,如果你也对RCC->AHB1ENR|=1<<5;这条寄存器指令比较费解如何实现的,那么我希望你看完了我的理解之后能对别人说的明白你的理解,那样就变成了你的知识了。
最后,启动代码与结构体只是为了让对理解有一点点帮助,使用宏定义将地址转换为结构体地址从而方便访问连续的地址值是嵌入式封装的核心,我觉得这点有必要对理解总线的朋友提出来。

白话讲懂Cortex 内核中的AHB总线相关推荐

  1. 你真的懂Linux内核中的阻塞和异步通知机制吗?(花了五天整理,墙裂推荐!)

    工科生一枚,热衷于底层技术开发,有强烈的好奇心,感兴趣内容包括单片机,嵌入式Linux,Uboot等,欢迎学习交流! 爱好跑步,打篮球,睡觉. 欢迎加我QQ1500836631(备注CSDN),一起学 ...

  2. 白话讲懂wait notify 和park unpark的使用示例和区别

    wait 和notify wait 和notify使用的时候有很多的限制: 例如必须用在schronized的同步块里面,因为他们依赖于schronized里面的锁. wait和notify不能指定唤 ...

  3. linux内核中的SPI

    0.说明 介绍spi基本协议,以及在linux内核中spi驱动程序框架. SPI驱动基于标准了总线设备驱动模型,因此本文仅示意分析SPI框架,驱动实现细节按照总线设备驱动模型来实现,不做过多分析. 1 ...

  4. 【systemverilog项目】AHB-SRAMC(AHB总线)个人学习笔记

    AHB-SRAMC项目中,应用的总线正是AMBA总线中的AHB总线. 1.AMBA总线的简要概述(关于AMBA总线的详细内容参见<AMBA总线>pdf): AMBA总线中,有三种总线:AH ...

  5. 内核开发知识第二讲,编写Kerner 程序中注意的问题.

    一丶函数多线程的安全问题 什么是函数多线程安全. 简单来说就是 ,一个函数在调用过程中.还没有返回的时候.再次被其他线程调用了.但是函数执行的结果是可靠的.就可以了说这个函数是安全的. 比如我们在用户 ...

  6. 深度:一文看懂Linux内核,Linux内核架构和工作原理详解

    简介 作用是将应用层序的请求传递给硬件,并充当底层驱动程序,对系统中的各种设备和组件进行寻址.目前支持模块的动态装卸(裁剪).Linux内核就是基于这个策略实现的.Linux进程1.采用层次结构,每个 ...

  7. java 协程线程的区别_用大白话讲进程和线程、协程的区别

    什么是进程和线程 有一定基础的小伙伴们肯定都知道进程和线程. 进程是什么呢? 直白地讲,进程就是应用程序的启动实例.比如我们运行一个游戏,打开一个软件,就是开启了一个进程. 进程拥有代码和打开的文件资 ...

  8. 一文看懂Linux内核!Linux内核架构和工作原理详解

    linux内核相关视频解析: 5个方面分析linux内核架构,让你对内核不再陌生 90分钟了解Linux内存架构,numa的优势,slab的实现,vmalloc的原理 手把手带你实现一个Linux内核 ...

  9. 深度:一文看懂Linux内核!Linux内核架构和工作原理详解

    简介 作用是将应用层序的请求传递给硬件,并充当底层驱动程序,对系统中的各种设备和组件进行寻址.目前支持模块的动态装卸(裁剪).Linux内核就是基于这个策略实现的.Linux进程1.采用层次结构,每个 ...

最新文章

  1. 十年学术生涯新开端:港中文助理教授周博磊宣布加入UCLA
  2. R语言数据结构之数据框
  3. python官网下载步骤2019-Python IDE开发工具下载
  4. docker安装nginx容器小记
  5. 不大于数的2整数幂的数
  6. 世界上5种顶级思维,你一定要知道
  7. python100内的质数_python输出100以内的质数与合数实例代码
  8. 商业创业计划书ppt你的绝佳选择
  9. MATLAB虚数矩阵不可随意转置
  10. 前端--开发“抽屉新热榜”
  11. 《知识产权知识产权信用管理规定》解读问答
  12. 云计算是什么意思?3张图看懂云计算架构
  13. 计算机考研复试_C++重点知识笔记面试题
  14. MySQL基础练习题
  15. Hinton独立发布44页论文火爆社区,没有实验:给你们个idea,自己去试吧
  16. 使用Aplayer制作视频播放器
  17. 谢伏瞻:当前宏观经济形势与发展趋势
  18. 王道计算机网络课代表 - 考研计算机 第四章 网络层 究极精华总结笔记
  19. 关于idea设置打开页面的默认浏览器
  20. 鸿蒙 保存图片到相册

热门文章

  1. PAT乙级-1015 德才论-C语言实现(40行AC)
  2. 【零信任落地案例】山石网科南京市中医院云数据中心〃零 信任”建设项目成功案例
  3. PHP输出缓存控制详解及flush、ob_flush的区别
  4. 转: 如何写好一篇文章
  5. VSCode rust-analyzer failed to load workspace: can‘t find Cargo.toml 或could not find Cargo.toml
  6. 将 RGB 图像转换为索引图像
  7. 标准的身份证验证(第18位校验码)
  8. 使用css修改input框中checkbox的样式
  9. 网络地址转换的类型及特点
  10. 记一次诡异的事件——fd有事件,poll不返回