基于此问题的答案: How does cpu communicate with peripherals?
我已经知道现代CPU通常使用类似于DMA的机制与外围设备,IO设备等进行通信。
最近,我买了一块FRDM-K66F板。正如其用户指南所述,该板载CPU基于ARM,并且已经安装了Mbed OS 5。
关于“数字输入/输出”功能,我只知道:
C ++程序-> mbed库-> GPIO API-> ...? ->硬件
我想澄清一下 cpu如何在低级范围内与外围设备一起使用? (从GPIO API到硬件,尤其是在mbed情况下)
在mbed-os库中是否声明了一些与mbed-board cpu中的特定寄存器相对应的特殊变量?以便arm编译器可以将此类语句转换为特定的访问指令?
我不知道如何在Google中搜索此问题,因此,如果有任何有用的参考或用户指南,请为我粘贴。
答案 0 :(得分:0)
没有区别,也没有魔力,也没有使mbed变得特别的东西。
答案在有问题的零件和电路板的文档中。您通过google或转到NXP并查找有问题的MCU:MK66FN2M0VMD18当然是来自您的链接。在那里,它将告诉您它是专门基于ARM的cortex-m4,因此您需要前往军备现场并获取埋在NXP芯片中的处理器内核的处理器详细信息。您可以从所链接的站点获取有关委员会的文档,或者搜索委员会的名称。
例如,该板的用户指南显示了SDA和SDL的陀螺仪连接,您可以使用微控制器的文档来查找有关该部件的I2C接口以及这些引脚上的接口,和/或只需稍微敲一下即可。 gpio。通常最好先咬一下,然后再根据需要尝试使mcu i2c外设工作。
应该在BOARD文档中描述BOARD上其余的外围设备,最好是那里有原理图。对于电路板上的每个芯片(包括NXP MCU),您都可以访问各个供应商站点以获取有关每个芯片的信息,其中包括如何对其进行编程,因此,例如,在这种情况下,陀螺仪将转到NXP,因为它也是NXP芯片并获取该文档,了解如何对其进行编程等。
现在,该信息和“ mbed os”之间是一堆驱动程序和os层,其概念与主板上操作系统的计算机上的浏览器上的此网页之间的层没有什么不同。板上的某些芯片是通过板或电缆连接的,还有通过电缆或连接器连接到其他板的其他物品(硬盘驱动器等)。
就像您的计算机一样,有一些接口和关于这些接口的文档以及使用这些接口,总线和协议的文档编写的软件。
NXP可能具有用于I2C之类的MCU芯片外围设备的裸机库,希望我也可以为陀螺仪提供某种形式的示例代码,因为我一直在该芯片上进行选择,但有时没有,有时您必须编写你自己,那就是微控制器世界的本质。
与此mbed类似,NXP可能以符合mbed os的方式编写代码(请注意mbed裸机和mbed os可能是不同的接口)基本上为该产品编写了芯片和板驱动程序。可能发布在NXP的站点上而不是ARM mbed站点上,但是谁知道我对mbed和CMSIS都没有用,所以很少去看它。恩智浦的利益是为该板提供源代码,因为他们希望您使用该板来制造产品并购买大量芯片,如果他们阻碍了他们所做的一切只是向您出售一个或几个板,并且被淘汰出局。这是单片机世界的本质,与主板世界不同,在主板世界中,他们想向您出售一块芯片和一块单板并每天给您打电话。微控制器供应商只有在我们每个人中的第N个购买成千上万个零件的芯片时才能生存。为了使第N个人做到这一点,他们需要带有原理图和源代码的参考/评估平台,否则第N个人将使用ST或ti或其他提供原理图和源代码的供应商产品。
因此,您要询问的所有内容都在不同地方记录了下来,这是一个基于ARM的芯片(不是arm芯片),因此arm核心本身由arm记录。这是一个NXP芯片,因此该芯片的其余部分最好由NXP进行记录,但是您可能还需要购买其他购买的IP到该供应商站点进行记录,在极少数情况下,MCU会出现这种情况,但对于操作系统级别的芯片(例如橙色pi上的allwinner芯片或树莓pi上的Broadcom芯片)拥有一些已购买的ip,但NDA指示他们无法对其进行记录,并且ip供应商不会给您提供没有NDA的文档(您可能无法获得)(通常是USB,DDR ,以及其他一些倾向于包含这些秘密的IP)。您不应该在这些MCU上看到它,极少数情况下,他们可能会说这是16550兼容的uart或这是ARM blahnumber uart,因此您必须对其进行Google搜索。
如果在OS上运行,则包括RTOS,至少一般而言存在例外。应用程序与api通信,而api与操作系统驱动程序进行通信,而api驱动程序与芯片上的外围设备(gpio,i2c,spi,uart,usb,计时器等)通信,其中一些正在使用芯片外部接口连接到板上的其他项目。或连接到板上。只要软件设计正确且没有漏洞,应用程序,api和驱动程序的组合就会使外围设备执行您要求的任何操作。这与在计算机上编写程序没有什么不同。这里没有魔术。
关于ARM与计算机上使用的ARM或x86或其他处理器没什么特别的。在通用处理器(例如ARM和X86)上有加载/存储(读/写)指令,确切的语法是特定于汇编程序的,机器代码是特定于处理器的。正如您在其他链接中提到的那样,x86的I / O指令与内存指令的概念不同,后者在当时仅是内存接口上的单个引脚(I / O与内存信号/引脚以及读取与写入信号/别针等)。 ARM都是内存映射的I / O,x86也是大多数,它具有反向兼容性,您可以从intel的x86文档中阅读以了解当今如何在芯片外部总线上实现它。
与x86不同,ARM是购买IP并埋在供应商芯片中的,因此在这种情况下,ARM总线在NXP芯片内部,在NXP中,您具有地址解码器,而MCU几乎没有地址空间直接映射到芯片外部。因此,在NXP文档中可以找到NXP芯片的特定地址空间,例如,该特定NXP芯片uart可能特定于该NXP芯片,没有理由假设它与另一个NXP芯片相同,并且肯定不是相同的地址或地址可以工作或将接口/注册为使用相同ARM内核的非NXP芯片。片上外设都可以通过在芯片内的ARM总线上加载和存储指令来访问。恩智浦在ARM规则中定义了哪些地址与内容,闪存,内存和特定外设相关。内核与片上外设之间也存在中断,以完善其接口。
使用(RT)OS时,通常是OS中的驱动程序与OS中的api进行对话,而api最终成为加载和存储指令的一种,从而导致向基于nxp芯片的存储控制器进行ARM总线事务on地址将交易传递到芯片中的处理程序(闪存,内存,特定的外设)中。
该芯片的地址空间可在NXP文档中找到,一些芯片供应商在一个文档中有地址空间,如数据表,而在另一文档中有寄存器偏移的半通用外设的详细信息。但是每个供应商都在做他们自己的事情,通常那里的信息比其他信息差(NXP很好,微芯片很差,ST和TI很好)。从历史上看,恩智浦会在寄存器说明中尽量保留寄存器的完整地址,在大多数情况下,大多数供应商的基本地址都记录在该文档或其他文档的其他地方,而外围文档仅显示基址的偏移量。
API只是有人将它们设计为好,坏或其他方面的API(不要假定供应商代码是好的,您可以从它的视线中看出来,它很少由“ A”团队编写,通常由被困的人编写)有时候做的还好/有时候做的不好)。操作系统驱动程序也是如此。
为恩智浦最大的利益就是为这些板卡提供交钥匙应用,以展示其功能。但是对于那些产品的大多数消费者而言,与计算机主板不同,MCU消费者是开发芯片+软件级产品以及这种软件+板级产品的理想开发商。因此,虽然交钥匙应用程序很有趣,但我们并不是在购买用于运行该软件的开发板,因此理想情况下可以在任何地方使用api文档,源代码等。 mbed是一件容易的事,因此您可能必须从arm而非nxp获得一些该软件。这取决于恩智浦选择打包的方式和方式。
答案 1 :(得分:0)
简单的答案是多个抽象级别。 MBED是一个旨在移植到许多不同供应商的许多设备上的操作系统:
由于它是通用代码,因此对于任何特定用途而言,代码都不总是最佳的。它甚至可能不提供硬件提供的所有功能。目的是很容易添加对新设备的支持。
为了显示一些示例,我将引用Cortex-M3 DesignStart Eval目标中的片段。该外围设备的数量有限,如果需要,您也可以在verilog中下载该平台的源代码。这只是操作系统的一部分,这些片段并没有完全结合在一起。
PinNames既包含50引脚接口的EXPnn号,也包含GPIO备用功能引脚多路复用定义:
typedef enum {
ALTERNATE_FUNC = 0, /* The pin is used for alternative function */
GPIO_FUNC = 1 /* The pin is used for GPIO function */
} PinFunction;
gpio_api.c实现了标准API与内部逻辑之间的映射(有时很丑)。例如,要初始化特定的引脚,请在编号和外设之间进行查找(基于每个GPIO 16个引脚):
void gpio_init(gpio_t *obj, PinName pin)
{
struct arm_gpio_dev_t *gpio_dev;
if (pin >= EXP0 && pin <= EXP51) {
/* GPIO pins */
switch (GPIO_DEV_NUMBER(pin)) {
case GPIO0_NUMBER:
gpio_dev = &ARM_GPIO0_DEV;
break;
}
arm_gpio_init(gpio_dev);
obj->gpio_dev = gpio_dev;
obj->mps2_io_dev = NULL;
obj->arm_mps2_io_write = NULL;
obj->pin_number = GPIO_PIN_NUMBER(pin);
/* GPIO is input by default */
obj->direction = PIN_INPUT;
return;
}
该设备的实际内存映射在CM3DS.h
中捕获#define CMSDK_GPIO0_BASE 0x40010000UL
#define CMSDK_GPIO1_BASE 0x40011000UL
#define CMSDK_GPIO2_BASE 0x40012000UL
#define CMSDK_GPIO3_BASE 0x40013000UL