打印
[FPGA]

MCU驱动使用(一)

[复制链接]
14|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
HIZYUAN|  楼主 | 2025-4-24 15:48 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
一、时钟的配置
二、管脚的配置
    1. 信号线和关键的分离
    2.管脚的配置方法
        1. 信号线名称
        2. 注意不可配置的管脚
三、GPIO的使用
    1.配置为输出(举例)
    2.配置为输入(举例)
    3.GPIO高级用法
四、MTimer的使用

一、时钟的配置:
AG32 通常使用 HSE 外部晶体(范围:4M~16M)。
AG32 中不需要手动设置 PLL 时钟(时钟树由系统自动配置,无须用户关注)。用户只需在配置文件中给出外部晶振频率和系统主频即可。
配置方式:
在 ve 文件中配置如下:


这里配置的值,会在mcu的系统初始化时,代码中自动获取并使能。
系统主频的可配置范围:参考 datasheet 中各型号的最高主频(通常是 248M)
外部晶振的可配置范围:4 ~ 16
这里是最简单的描述,只是使用MCU时可以简单如上配置。
如果需要使用外部有源晶振,或者使用内部振荡器(内部振荡器有 5%以内误差),或者 cpld 中需要额外主频输入。

二、管脚的配置:1. 信号线和关键的分离:
这里先描述两个概念:信号线和管脚。
信号线,是指MCU里能操作的信号线,比如gpio1_1/uart0_tx/spi_cs等等,在连接在mcu内核上的信号接点;
管脚,就是芯片裸露在外边的引脚(32PIN的有32个管脚,64PIN的有64个管脚...)
在传统芯片里(如ST、GD等),一颗芯片出来后,信号线和管脚是绑定死的(最多一个管脚可以复用成几种信号)。
但在AG32里,信号线和管脚是彻底分离的。
也就是说,可以把任意信号线绑定到任意引脚。
打个比方,比如管脚1,这个管脚用于什么功能,完全是由用户来自行配置的。用户可以把它配置成uart0_tx,也可以配置成GPIO1_2,还可以配置成spi_cs,等等。
这种管脚可配置性,为应用设计带来巨大的便利性:
首先,为PCB布线带来了很大的便利性。按最近的引脚走线,不用绕来绕去。
其次,可以提升管脚利用度(应用中没用到的外设不去配置,那它就不会占用管脚)。 比如,本来需要100脚的ST才能满足的外设需求,用AG芯片可能32脚的就够了。
2.管脚的配置方法:
管脚的配置,在ve文件中 信号线<->管脚 一行一行对应即可。
如:GPIO0_0 PIN_2


本文后续会逐项讲述各种外设怎么配置信号和管脚。
先概述下配置引脚的两个注意项:
1. 信号线名称:
信号线名称是在VE里配置使用的。
比如:uart0的tx信号线名称是UART0_UARTTXD,gpio第0组的第0个信号线名称是 GPIO0_0。
那么,对于mcu端来说,共有哪些信号线呢?
mcu的信号线名称,全部定义在《AGRV2K_逻辑设置.pdf》中的“Function_Pin 列表”。
配置举例:
  • 配置GPIO0_1为PIN2,则定义:GPIO0_1 PIN_2
  • 配置UART1_TX为PIN3,则定义:UART1_UARTTXD PIN_3
  • 配置SPI0的clk为PIN4,则定义:SPI0_SCK PIN_4
  • 配置CAN0的TX为PIN5,则定义:CAN0_TX0 PIN_5
2. 注意不可配置的管脚
上述描述的“任意信号线可以绑定到任意引脚”,只是便于理解。真实使用时,有少量管脚是不可配置的。
不可配置包括:基础类(电源、时钟、地、RESET、BOOT0)、ADC(DAC/CMP)、USB。
除去这些,其他的外设均为配置管脚。
另外,其中的ADC和USB的管脚,如果不接ADC和USB,仍然是可以被用做普通IO的。
具体每种封装下管脚的详细定义,请参考文档《AG32_pinout_100_64_48_32_2K.xlsx》。
打开后,如下图:

凡是带有IO的,都是可以被配置的管脚。
比如:上图的PIN_33,如果ADC的channal14在使用,那这个管脚只能用于这路ADC。如果这路adc没有使能,则PIN_33可以配置为其他信号线(用于其他功能)。
32/48/64/100,各种封装下的引脚定义是不同的,注意找到跟实际匹配的那组。
.
三、GPIO的使用:
可用GPIO(非管脚):
AG32芯片内部可用gpio共有80个,分为10组,每组8个。
代码中各组对应为:GPIO0、GPIO1、GPIO2、... GPIO9
组内各IO用bit表示:GPIO_BIT0、GPIO_BIT1、GPIO_BIT2、...、GPIO_BIT7
使用时,用【组ID+组内id】来标识唯一的IO。
这里和ST是相仿的,ST分为GPIOA/GPIOB/GPIOC..., PIN_1/PIN_2/PIN_3...
AG32为:GPIO0/GPIO1/GPIO2..., GPIO_BIT0/GPIO_BIT1/GPIO_BIT2...
在VE中的命名方式如:GPIO0_0,表示的是第0组的第0个IO。
对外映射:
上边已经讲述过,AG32中MCU信号线和管脚是分离的,GPIO信号线也不例外。
程序中用到的GPIO要连接到管脚PIN,才能最终使用。
GPIO在ve文件中配置如下图:


上图的示例,就是把 gpio4_1映射到管脚92。 (VE中的#为注释)
在AG32中,必须映射后,代码中操作gpio时,才会真正使能到硬件管脚。
这里GPIOx_y的角标取值范围:x (0 ~ 9), y (0 ~ 7)
PIN_z的取值范围:z小于所用芯片的最大引脚数
在取值范围内,满足限制条件下,任意GPIOx_y可以映射到任意PIN_z。
(“哪些管脚不能被使用”的限制条件,参考文档:AGRV2K_逻辑设置.pdf)
这里配置的GPIO0_0,等同于代码中的 (GPIO0, GPIO_BIT0)。
对SDK下gpio样例代码的解释:
在examples/example/example_gpio.c里,只有最简单的一个IO翻转示例:


GPIO_Toggle是反转函数。从这个函数点进去(Ctrl +鼠标左键),可以看到gpio函数集:


EXT_GPIO和EXT_GPIO_BITS是定义的gpio宏。
注:这里能用GPIO_Toggle,是因为在前边的board_init()函数里已经初始化过该gpio了。
点进去EXT_GPIO宏可以看到定义


注意,这里的EXT_GPIO_BITS值为0b1110(即:0x0e),意思是BIT1/BIT2/BIT3的3位一 起操作。0b1110这里等价为:GPIO_BIT1|GPIO_BIT2|GPIO_BIT3。
那么,GPIO_Toggle(EXT_GPIO, EXT_GPIO_BITS) 这句代码的意思,就是对GPIO4_1/GPIO4_2 /GPIO4_3的3个IO一起反转。
在样例的VE里,定义引脚如下:


那么,跑样例时,就可以看到开发板上的3个LED(LED1 LED2和LED3)闪烁了。
而LED4因为没有操作该IO,LED4依然是灭的状态。
1.配置为输出(举例)
用 pin3 引脚接 led 灯,并控制亮灯(高为亮)。
步骤一:
先在ve文件中定义引脚映射(gpio使用 4-1):


步骤二:
定义使用的宏:(也可以不定义,直接在代码中使用)


步骤三:
  代码中调用:


步骤四:
  编译并烧录ve文件,编译并烧录code;
补充,驱动开放的API包含:
GPIO_SetOutput/GPIO_SetInput    ---设置IO为输入输出
GPIO_SetHigh/GPIO_SetLow      ---置高置低
GPIO_Toggle                   ---高低切换
GPIO_IntConfig                 ---配置中断触发方式
GPIO_EnableInt/GPIO_DisableInt/GPIO_ClearInt  ---中断控制
GPIO_AF_ENABLE/GPIO_AF_DISABLE         ---切换GPIO模式(如果有复用)
Gpio中断函数SDK中已经默认指定:GPIOx_isr
如果要重定向为函数,通过 plic_isr[GPIOx_IRQn] = gpio_xxx_isr 的方式来设置;
2.配置为输入(举例)
用pin96接外部按键,处理按键消息;
步骤一:
  在ve文件中配置gpio4_5映射到pin96;


步骤二:
  在测试代码中,编写IO初始化,并实现中断函数:


注:这里的中断函数GPIO4_isr无需程序中再次指定。
步骤三:
如果外部电路没有上拉设计,需要内部上拉。设置方式(二选一):
  • 在工程的example_board.asf文件中,
  • 或者在\platforms\AgRV\boards\agrv2k_x0x\board.asf 文件中(不建议),
添加以下红框内的语句:


内容:set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to PIN_96
或者使用:set_instance_assignment -name CFG_KEEP -to PIN_96 2'b10 -extension
(以上两个上拉的语句意义等价,使用时二选一)
注意:如果是cpld中要实现上拉,这里的PIN_96要用cpld里的信号名字。
如果设置下拉,则使用以下方式:


内容:set_instance_assignment -name CFG_KEEP -to PIN_32 2'b01 -extension
注意:如果是cpld中要实现下拉,这里的PIN_32要用cpld里的信号名字。
注意:上边一行添加完后,务必在后边添加回车换行(保证这行不是文件最后一行)。
步骤四:
编译并烧录ve文件,编译并烧录code;
结束。
.
3.GPIO高级用法
1. 设置内部上拉/下拉:
  参考上边步骤3的描述。
2. 引脚复用:
AG32中也有引脚复用。
常见的复用引脚,默认都是IO功能。用做复用功能(如uart_rx/uart_tx)时,需要使用函数GPIO_AF_ENABLE来设置(参考具体的样例代码)。
特别的,JTAG引脚(JNTRST、JTDO、JTDI、JTMS、JTCK),默认是JTAG功能,而不是IO功能。用作普通IO时,需要先切换设置。
可使用如下函数来设置(在main函数进入后调用即可):
SYS_DisableNJTRST()、SYS_DisableJTDI()、SYS_DisableJTDO().
(AG32默认使用jtag的swd模式,保留JTMS、JTCK即可通过jtag烧录仿真)。
3. 设置为OD模式(开漏输出):
IO默认输出是PP模式(推挽输出)。
如果要设置为OD模式,有两种方式(二选一):
方式一、在ve里定义引脚如下(以34脚为例):
GPIO4_1 PIN_34:OUTPUT:!PIN_34_out_data
方式二、在asf文件(工程中example_board.asf)中设置:
set_instance_assignment -name AUTO_OPEN_DRAIN_PINS ON -to PIN_34
两种方式的输出效果是一样的。
注意:
如果用gpio模拟I2c的数据线,则只能使用第2种方式。
如果一定要使用方式一,必须要新增一个GPIO做为输入,绑定到一个PIN上。如:GPIO4_2 PIN_34:INPUT,然后在程序里SDA切换读的时候就用这个GPIO。
4. 配置电流输出驱动能力:
同上边上拉/下拉的设置文件(example_board.asf 文件),加入:
set_instance_assignment -name CURRENT_STRENGTH -to PIN_32 16MA
驱动电流默认为8MA,支持4MA/8MA/12MA/16MA。

四、MTimer的使用:
MTime是risc-v中定义的一个64位系统定时器。
在STM32中,我们一般用systick(滴答计时器)作为时基,而在riscv中我们用mechine timer(简称mtime)作为时基。
MTime中有两个主要寄存器:mtime和mtimecmp;
当mtime使能后,mtime寄存器里的值会随着tick自增,当自增到 大于等于 mtimecmp 寄存器的值时(无符号比较),就触发MTimer中断。
在移植操作系统时,mtime一般被用于系统时间片的调度定时。
相关函数:
INT_SetMtime:设置寄存器的值;
INT_SetMtimeCmp:设置比较寄存器的值;
INT_EnableIntTimer:打开timer中断;
中断函数SDK中已默认指定:void MTIMER_isr()
如果要重定向函数,通过clint_isr[IRQ_M_TIMER] = MTIMER_user_isr 来设置;

如果要设置1ms触发一次的连续定时,需要调用:

NT_SetMtime(0);
INT_SetMtimeCmp(SYS_GetSysClkFreq() / 1000); //1ms
然后在中断里重新计时:
INT_SetMtime(0);

完整代码样例请参考example部分:


MTIME较为简单,用法上只有上述用法。

联系海振远科技

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

27

帖子

2

粉丝