博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【龙芯1c库】封装引脚复用接口和使用示例
阅读量:2360 次
发布时间:2019-05-10

本文共 8073 字,大约阅读时间需要 26 分钟。

龙芯1c库是把龙芯1c的常用外设的常用功能封装为一个库,类似于STM32库。Git地址:https://gitee.com/caogos/OpenLoongsonLib1c

引脚复用不是一个单独的功能,但在很多地方都需要用到。我想还是有必要单独讨论一下的,所以就有了此文。

龙芯1c库中引脚复用接口使用示例

引脚复用接口简介

提供两个接口,分别是

/* * 把指定pin设置为指定用途(普通gpio,非gpio) * @gpio gpio引脚编号 * @purpose 用途 */void pin_set_purpose(unsigned int gpio, pin_purpose_t purpose);/* * 设置指定pin为第n复用 * @gpio gpio编号 * @remap 第n复用 */void pin_set_remap(unsigned int gpio, pin_remap_t remap);
再来看看第二个参数分别是啥

// 引脚用途typedef enum{    PIN_PURPOSE_GPIO = 0,               // 引脚用作普通gpio    PIN_PURPOSE_OTHER,                  // 引脚用作其它功能(非gpio)}pin_purpose_t;// 引脚复用typedef enum{    PIN_REMAP_FIRST = 0,                // 第一复用    PIN_REMAP_SECOND,                   // 第二复用    PIN_REMAP_THIRD,                    // 第三复用    PIN_REMAP_FOURTH,                   // 第四复用    PIN_REMAP_FIFTH,                    // 第五复用}pin_remap_t;
这里讨论的是引脚复用,为何会涉及gpio呢,请看下图

这是《龙芯1c300处理器用户手册》v1.4中的截图,其中有提到GPIO复用,我想这里的GPIO复用应该就是指引脚用作GPIO,其优先级仅高于默认功能。

再来看看《龙芯1c300处理器数据手册》v1.3中关于引脚复用的表格,如下

按道理上讲,引脚复用的接口应该有引脚编号,并且应该以引脚编号作为索引,可前面提到的接口怎么没有引脚编号,而是以gpio编号作为索引呢?

龙芯1c处理器上有些引脚是固定的,只能用作某个固定功能,不能用作其它功能,否则cpu不能正常工作,比如晶振,内存占用的引脚,flash占用的引脚等。一般可以复用的引脚也可以作为普通GPIO使用,如果这个理由还不够充分,那么再给你个理由

上图中的寄存器是用于配置引脚复用功能的,虽然手册中说的是PAD[31:0],但经过实际测试,应该是GPIO[31:0],也就是说寄存器CBUS_FIRSTx,CBUS_SECONDx,CBUS_THIRDx,CBUS_FOURTHx和CBUS_FIFTHx是以GPIOx为索引来设置复用的,而不是PADx。这也就是前面接口中为啥第一个参数是gpio,以gpio作为索引来设计复用的原因。

使用示例

比如将某个引脚复用为pwm,代码如下

// pwm引脚定义#define LS1C_PWM0_GPIO06                    (6)         // gpio06用作pwm0#define LS1C_PWM0_GPIO04                    (4)         // gpio04复用为pwm0#define LS1C_PWM1_GPIO92                    (92)        // gpio92用作pwm1#define LS1C_PWM1_GPIO05                    (5)         // gpio05复用为pwm1#define LS1C_PWM2_GPIO52                    (52)        // gpio52复用为pwm2#define LS1C_PWM2_GPIO46                    (46)        // gpio46复用为pwm2#define LS1C_PWM3_GPIO47                    (47)        // gpio47复用为pwm3#define LS1C_PWM3_GPIO53                    (53)        // gpio53复用为pwm3    // 配置相应引脚用作pwm,而非gpio    pin_set_purpose(gpio, PIN_PURPOSE_OTHER);    // 复用    switch (gpio)    {        // 不需要复用        case LS1C_PWM0_GPIO06:        case LS1C_PWM1_GPIO92:            break;        case LS1C_PWM0_GPIO04:          // gpio04的第三复用            pin_set_remap(LS1C_PWM0_GPIO04, PIN_REMAP_THIRD);            break;        case LS1C_PWM1_GPIO05:          // gpio05的第三复用            pin_set_remap(LS1C_PWM1_GPIO05, PIN_REMAP_THIRD);            break;        case LS1C_PWM2_GPIO52:          // gpio52的第四复用            pin_set_remap(LS1C_PWM2_GPIO52, PIN_REMAP_FOURTH);            break;        case LS1C_PWM2_GPIO46:          // gpio46的第四复用            pin_set_remap(LS1C_PWM2_GPIO46, PIN_REMAP_FOURTH);            break;        case LS1C_PWM3_GPIO47:          // gpio47的第四复用            pin_set_remap(LS1C_PWM3_GPIO47, PIN_REMAP_FOURTH);            break;        case LS1C_PWM3_GPIO53:          // gpio53的第四复用            pin_set_remap(LS1C_PWM3_GPIO53, PIN_REMAP_FOURTH);            break;        default:            break;    }

龙芯1c引脚复用简介

相关寄存器

来看看《龙芯1c处理器用户手册》中的描述

寄存器CBUS_FIRST0为GPIO[31:0]第一复用控制寄存器

寄存器CBUS_SECOND0为GPIO[31:0]的第二复用控制寄存器
寄存器CBUS_THIRD0为GPIO[31:0]的第三复用控制寄存器
寄存器CBUS_FOURTH0为GPIO[31:0]的第四复用控制寄存器
寄存器CBUS_FIFTH0为GPIO[31:0]的第五复用控制寄存器
依次类推
GPIO[63:32]的复用控制寄存器组为CBUS_xxx1,
GPIO[95:64]的复用控制寄存器组为CBUS_xxx2
GPIO[127:96]的复用控制寄存器组委CBUS_xxx3

复用表

这里就不一一粘贴了,更详细的请查看《龙芯1c300处理器数据手册》

代码清单

pin.h

// 引脚功能(普通gpio,pwm,复用等)相关接口#ifndef __OPENLOONGSON_PIN_H#define __OPENLOONGSON_PIN_H// 引脚用途typedef enum{    PIN_PURPOSE_GPIO = 0,               // 引脚用作普通gpio    PIN_PURPOSE_OTHER,                  // 引脚用作其它功能(非gpio)}pin_purpose_t;// 引脚复用typedef enum{    PIN_REMAP_FIRST = 0,                // 第一复用    PIN_REMAP_SECOND,                   // 第二复用    PIN_REMAP_THIRD,                    // 第三复用    PIN_REMAP_FOURTH,                   // 第四复用    PIN_REMAP_FIFTH,                    // 第五复用}pin_remap_t;/* * 把指定pin设置为指定用途(普通gpio,非gpio) * @gpio gpio引脚编号 * @purpose 用途 */void pin_set_purpose(unsigned int gpio, pin_purpose_t purpose);/* * 设置指定pin为第n复用 * @gpio gpio编号 * @remap 第n复用 */void pin_set_remap(unsigned int gpio, pin_remap_t remap);#endif

pin.c

// 引脚功能(普通gpio,pwm,复用等)相关接口#include "public.h"#include "ls1c_regs.h"#include "gpio.h"#include "pin.h"/* * 把指定pin设置为指定用途(普通gpio,非gpio) * @gpio gpio引脚编号 * @purpose 用途 */void pin_set_purpose(unsigned int gpio, pin_purpose_t purpose){    volatile unsigned int *gpio_cfgx;           // GPIO_CFGx寄存器    unsigned int pin = GPIO_GET_PIN(gpio);    gpio_cfgx = gpio_get_cfg_reg(gpio);    if (PIN_PURPOSE_GPIO == purpose)            // 引脚用作普通gpio    {        reg_set_one_bit(gpio_cfgx, pin);    }    else                                        // 引脚用作其它功能(非gpio)    {        reg_clr_one_bit(gpio_cfgx, pin);    }    return ;}/* * 设置指定pin为第n复用 * @gpio gpio编号 * @remap 第n复用 */void pin_set_remap(unsigned int gpio, pin_remap_t remap){    volatile unsigned int *reg = NULL;          // 复用寄存器    unsigned int port = GPIO_GET_PORT(gpio);    unsigned int pin  = GPIO_GET_PIN(gpio);    switch (port)    {        case 0:            switch (remap)            {                case PIN_REMAP_FIRST:                    reg = (volatile unsigned int *)LS1C_CBUS_FIRST0;                    break;                case PIN_REMAP_SECOND:                    reg = (volatile unsigned int *)LS1C_CBUS_SECOND0;                    break;                case PIN_REMAP_THIRD:                    reg = (volatile unsigned int *)LS1C_CBUS_THIRD0;                    break;                case PIN_REMAP_FOURTH:                    reg = (volatile unsigned int *)LS1C_CBUS_FOURTH0;                    break;                case PIN_REMAP_FIFTH:                    reg = (volatile unsigned int *)LS1C_CBUS_FIFTH0;                    break;            }            break;        case 1:            switch (remap)            {                case PIN_REMAP_FIRST:                    reg = (volatile unsigned int *)LS1C_CBUS_FIRST1;                    break;                case PIN_REMAP_SECOND:                    reg = (volatile unsigned int *)LS1C_CBUS_SECOND1;                    break;                case PIN_REMAP_THIRD:                    reg = (volatile unsigned int *)LS1C_CBUS_THIRD1;                    break;                case PIN_REMAP_FOURTH:                    reg = (volatile unsigned int *)LS1C_CBUS_FOURTH1;                    break;                case PIN_REMAP_FIFTH:                    reg = (volatile unsigned int *)LS1C_CBUS_FIFTH1;                    break;            }            break;        case 2:            switch (remap)            {                case PIN_REMAP_FIRST:                    reg = (volatile unsigned int *)LS1C_CBUS_FIRST2;                    break;                case PIN_REMAP_SECOND:                    reg = (volatile unsigned int *)LS1C_CBUS_SECOND2;                    break;                case PIN_REMAP_THIRD:                    reg = (volatile unsigned int *)LS1C_CBUS_THIRD2;                    break;                case PIN_REMAP_FOURTH:                    reg = (volatile unsigned int *)LS1C_CBUS_FOURTH2;                    break;                case PIN_REMAP_FIFTH:                    reg = (volatile unsigned int *)LS1C_CBUS_FIFTH2;                    break;            }            break;        case 3:            switch (remap)            {                case PIN_REMAP_FIRST:                    reg = (volatile unsigned int *)LS1C_CBUS_FIRST3;                    break;                case PIN_REMAP_SECOND:                    reg = (volatile unsigned int *)LS1C_CBUS_SECOND3;                    break;                case PIN_REMAP_THIRD:                    reg = (volatile unsigned int *)LS1C_CBUS_THIRD3;                    break;                case PIN_REMAP_FOURTH:                    reg = (volatile unsigned int *)LS1C_CBUS_FOURTH3;                    break;                case PIN_REMAP_FIFTH:                    reg = (volatile unsigned int *)LS1C_CBUS_FIFTH3;                    break;            }            break;        default:            return ;    }    // 置1    reg_set_one_bit(reg, pin);    return ;}

你可能感兴趣的文章
通俗理解ZooKeeper是如何保证数据一致性的
查看>>
Zookeeper核心工作机制(zookeeper特性、zookeeper数据结构、节点类型)
查看>>
基于Zookeeper的分布式锁
查看>>
程序员想提升工作效率,就别再做这七件事啦
查看>>
微信2015 年最热门的 10 篇技术文章,共 100 多篇精华
查看>>
程序员必须知道的10大基础实用算法及其讲解
查看>>
C/C++内存泄漏及检测
查看>>
nginx安装过程记录
查看>>
em单位的理解和使用
查看>>
localStorage的理解和应用
查看>>
base64图片编码大小与原图文件大小之间的联系
查看>>
安装和认识express框架
查看>>
三种主流的JVM(JDK)使用心得
查看>>
多核危机:Scala vs. Erlang
查看>>
未来系统中的编程语言
查看>>
函数式编程另类指南1
查看>>
kudu tablet design(kudu表设计)
查看>>
kudu master design(kudu主节点设计)
查看>>
第七章:druid.io实践分享之realtime+kafka 一
查看>>
第七章:druid.io实践分享之Realtime+kafka 二
查看>>