IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 一、【k210】FPIOA分析 -> 正文阅读

[嵌入式]一、【k210】FPIOA分析

零、K210概述

1.为什么有这一篇文章?

在入手的K210开发板中,了解相关模块内容,我是先看如何点亮LED,这样基础的操作GPIO的方法就理解了。在看官方给的示例代码时,看到了如下操作:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AgJHfEPJ-1648393343293)(…/pic/image-20220326210947746.png)]

将硬件引脚映射成软件GPIO功能。so what ???

于是,在对FPIOA的内容进行了大致的了解后,输出此篇文章。

2.FPIOA概念

概念摘自 勘智的k210 datasheet

FPIOA为现场可编程IO阵列。此功能允许用户将255个内部功能(GPIO/I2C/UART/SPI等)映射到芯片外围的48个自由IO上:

  • 支持IO的可编程功能选择
  • 支持IO输出的8种驱动能力选择
  • 支持IO的内部上拉电阻选择
  • 支持IO的内部下拉电阻选择
  • 支持IO输入的内部施密特触发器设置
  • 支持IO输出的斜率控制
  • 支持内部输入逻辑的电平设置7

本人理解,正常的MCU都是特定的引脚有特定的功能,比如说STM32串口功能都是在固定的引脚上。而这个FPIOA功能则让K210每个引脚的功能由我们自己定义

3.FPIOA实现

  1. fpioa_set_function()函数解析
  2. fpioa_set_function_raw()函数解析
  3. fpioa_t结构体及相关内容

我们实际LED点亮例程中,进行了GPIO功能配置,代码如下:

void hardware_init(void)
{
    fpioa_set_function(PIN_LED_0, FUNC_LED0); //将PIN_LED_0引脚设置为GPIO0功能
    fpioa_set_function(PIN_LED_1, FUNC_LED1); //将PIN_LED_1引脚设置为GPIO1功能
}

3.1fpioa_set_function()

从上述代码中可以看出,通过调用勘智K210的裸机版SDK中的fpioa_set_function()函数进行了硬件引脚和软件功能的映射。沿着fpioa_set_function()的内容对FPIOA的功能实现进行深入分析。fpioa_set_function()中的逻辑顺序如下:

  1. 检查引脚编号和功能编号是否超出限制
  2. 如果指定引脚number要绑定的功能为FUNC_RESV0,则调用fpioa_set_function_raw(number, FUNC_RESV0)
  3. 如果指定引脚number要绑定的是其他功能,则会遍历所有引脚的功能配置,如果有其他引脚绑定着这个功能,则会将其他引脚的功能设置为FUNC_RESV0。
  4. 调用fpioa_set_function_raw(number, function)配置引脚number为指定功能
int fpioa_set_function(int number, fpioa_function_t function)
{
    uint8_t index = 0;
    /* Check parameters FPIOA_NUM_IO为引脚数量48, FUNC_MAX为支持的功能数256*/
    if(number < 0 || number >= FPIOA_NUM_IO || function < 0 || function >= FUNC_MAX)
        return -1;
    if(function == FUNC_RESV0) 
    {
        fpioa_set_function_raw(number, FUNC_RESV0);
        return 0;
    }
    /* Compare all IO */
    for(index = 0; index < FPIOA_NUM_IO; index++)
    {
        if((fpioa->io[index].ch_sel == function) && (index != number))
            fpioa_set_function_raw(index, FUNC_RESV0);
    }
    fpioa_set_function_raw(number, function);
    return 0;
}

3.2fpioa_set_function_raw()

从上述fpioa_set_function()定义中可以看出,该函数最终都是调用fpioa_set_function_raw()来实现的。查看函数定义,可以确认逻辑顺序如下:

  1. 检测传入参数
  2. 给fpioa结构体的成员变量io[number]赋值。所赋值来自于function_config中。
int fpioa_set_function_raw(int number, fpioa_function_t function)
{
    /* Check parameters */
    if(number < 0 || number >= FPIOA_NUM_IO || function < 0 || function >= FUNC_MAX)
        return -1;
    /* Atomic write register */
    fpioa->io[number] = (const fpioa_io_config_t){
        .ch_sel = function_config[function].ch_sel,
        .ds = function_config[function].ds,
        .oe_en = function_config[function].oe_en,
        .oe_inv = function_config[function].oe_inv,
        .do_sel = function_config[function].do_sel,
        .do_inv = function_config[function].do_inv,
        .pu = function_config[function].pu,
        .pd = function_config[function].pd,
        .sl = function_config[function].sl,
        .ie_en = function_config[function].ie_en,
        .ie_inv = function_config[function].ie_inv,
        .di_inv = function_config[function].di_inv,
        .st = function_config[function].st,
        /* resv and pad_di do not need initialization */
    };
    return 0;
}

fpioa作为一个结构体变量,赋值如下:

volatile fpioa_t *const fpioa = (volatile fpioa_t *)FPIOA_BASE_ADDR;

fpioa指针变量被const修饰,表明fpioa所存的地址不能修改,而地址指向的值可以改动

3.3fpioa_t结构体及相关内容

typedef struct _fpioa
{
    fpioa_io_config_t io[FPIOA_NUM_IO];
    /*!< FPIOA GPIO multiplexer io array */
    fpioa_tie_t tie;
    /*!< FPIOA GPIO multiplexer tie */
} __attribute__((packed, aligned(4))) fpioa_t;

该结构体由两部分组成:

  1. 记录每个引脚寄存器配置的io数组,数据类型为 fpioa_io_config_t结构体
  2. 记录多路复用器联系的tie结构体,数据类型为fpio_tie_t结构体

3.3.1 fpioa_io_config_t结构体

本人理解这个结构体就是记录引脚的寄存器配置的。根据代码注释和结构体的内容。寄存器每个位的功能如下

typedef struct _fpioa_io_config
{
    uint32_t ch_sel : 8;
    /*!< Channel select from 256 input. */
    uint32_t ds : 4;
    /*!< Driving selector. */
    uint32_t oe_en : 1;
    /*!< Static output enable, will AND with OE_INV. */
    uint32_t oe_inv : 1;
    /*!< Invert output enable. */
    uint32_t do_sel : 1;
    /*!< Data output select: 0 for DO, 1 for OE. */
    uint32_t do_inv : 1;
    /*!< Invert the result of data output select (DO_SEL). */
    uint32_t pu : 1;
    /*!< Pull up enable. 0 for nothing, 1 for pull up. */
    uint32_t pd : 1;
    /*!< Pull down enable. 0 for nothing, 1 for pull down. */
    uint32_t resv0 : 1;
    /*!< Reserved bits. */
    uint32_t sl : 1;
    /*!< Slew rate control enable. */
    uint32_t ie_en : 1;
    /*!< Static input enable, will AND with IE_INV. */
    uint32_t ie_inv : 1;
    /*!< Invert input enable. */
    uint32_t di_inv : 1;
    /*!< Invert Data input. */
    uint32_t st : 1;
    /*!< Schmitt trigger. */
    uint32_t resv1 : 7;
    /*!< Reserved bits. */
    uint32_t pad_di : 1;
    /*!< Read current IO's data input. */
} __attribute__((packed, aligned(4))) fpioa_io_config_t;
  • bit[31], PAD_DI: Read current IO’s data input.
  • bit[30:24], NA: Reserved bits.
  • bit[22], DI_INV: Invert Data input.
  • bit[21], IE_INV: Invert the input enable signal
  • bit[20], IE_EN: Input enable. It can disable or enable IO input.
  • bit[19], SL: Slew rate control enable.
  • bit[18], SPU: Strong pull up.
  • bit[17], PD: Pull select: 0 for pull down, 1 for pull up.
  • bit[16], PU: Pull enable.
  • bit[15], DO_INV: Invert the result of data output select (DO_SEL).
  • bit[14], DO_SEL: Data output select: 0 for DO, 1 for OE.
  • bit[13], OE_INV: Invert the output enable signal.
  • bit[12], OE_EN: Output enable.It can disable or enable IO output.
  • bit[11:8], DS: Driving selector.
  • bit[7:0], CH_SEL: Channel select from 256 input.

3.3.2 fpio_tie_t结构体

此结构体用于配置每个function的使能状态和默认值。

typedef struct _fpioa_tie
{
    uint32_t en[FUNC_MAX / 32];
    /*!< FPIOA GPIO multiplexer tie enable array */
    uint32_t val[FUNC_MAX / 32];
    /*!< FPIOA GPIO multiplexer tie value array */
} __attribute__((packed, aligned(4))) fpioa_tie_t;

3.3.3 function_config

fpioa_set_function_raw()函数中给fpioa->io[number]赋值时,是从function_config[]数组中获取的值。查看该数组的内容,大致如下:

/* Function list */
static const fpioa_assign_t function_config[FUNC_MAX] =
{
        {.ch_sel = FUNC_JTAG_TCLK,
         .ds = 0x0,
         .oe_en = 0,
         .oe_inv = 0,
         .do_sel = 0,
         .do_inv = 0,
         .pu = 0,
         .pd = 0,
         .resv1 = 0,
         .sl = 0,
         .ie_en = 1,
         .ie_inv = 0,
         .di_inv = 0,
         .st = 1,
         .tie_en = 0,
         .tie_val = 0,
         .resv0 = 0,
         .pad_di = 0},
        {.ch_sel = FUNC_JTAG_TDI,
         ...},
    	{.ch_sel = FUNC_JTAG_TMS,
         ...},
    	...
};  	

此数组为结构体数组,数组大小与function数量一致,这样在将软件功能映射到硬件引脚上时,就可以直接给对应的引脚io寄存器进行赋值,寄存器的具体配置则来自function_config[]数组中根据function配置好的值。

4.总结

通过FPIOA功能,可以对任意引脚配置不同的功能,相对于我知道的STM32,完全不用再去查原理图看哪个引脚是什么功能,自己想定义成啥就是啥。真是高呀!!!!!

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 18:41:35  更:2022-03-30 18:44:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:42:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码