RISC-V 32架构实践专题六(从零开始写操作系统-板级外设初始化)

        完成时钟初始化后,接下来就可以对各总线下的外设进行配置,并实现其相关驱动接口功能。接下来我们以串口为例来进行外设初始化流程。

一、确认串口时钟源

        在我的开发板上,使用usart1作为调试串口使用,所以需要用到PA9与PA10两个gpio管脚。如下图所示:

         同时usart1串口使用的时钟源为PCLK2(也就是APB2),其时钟配置如下代码所示:

    /* HCLK = SYSCLK */
    RCC->CFGR0 |= (uint32_t)0x00;
    /* PCLK2 = HCLK */
    RCC->CFGR0 |= (uint32_t)0x00;
    /* PCLK1 = HCLK / 2 */
    RCC->CFGR0 |= (uint32_t)0x400;

        SYSCLK == HCLK == PCLK2 == PCLK1 * 2

        如上就是系统时钟的配置关系,所以可知usart1串口的时钟源频率为96MHz。

        其时钟树路径如下图所示:

 

 

 二、初始化串口

        确认好串口的时钟源后,接下来就可以使能usart1对应的总线时钟,以及配置usart1的波特率等设置。

        初始化串口代码如下所示:

/*********************************************************************
 * @fn      usart1_init
 *
 * @brief   初始化usart1串口,并默认配置其波特率为115200.
 *
 * @param   none
 *
 * @return  none
 */
void usart1_init(void)
{
    uint32_t div = 0;

    // 使能usart1时钟和GPIOA的时钟
    RCC->APB2PCENR |= USART1EN | IOPAEN;

    // 配置PA9引脚为功能复用输出,PA10为带上拉输入
    GPIOA->CFGHR |= 0x000008B0;
    GPIOA->OUTDR |= 0x00000400;

    // 默认配置usart1的波特率为115200
    div = (PCLK2 / 16) / 115200;
    USART1->BRR = (div << 4) + 1;

    // 使能usart1的发送器
    USART1->CTLR1 |= CTRL1_TE;
    // 使能usart1的串口
    USART1->CTLR1 |= CTRL1_UE;
}
  1. 首先使能usart1与gpio_a的时钟,使能了它们的时钟才能使对应的外设正常工作;
  2. 配置PA9与PA10引脚的复用模式,对于PA9应该配置为复用输出,P10应该配置为上拉输入;
  3. 然后再设置usart1的波特率、数据位长度、奇偶校验以及停止位,这里默认设置为:115200,8,none,1;
  4. 最后再打开usart1的发送器,以及usart1串口总使能。

三、实现串口输出接口

        此时就可以通过串口数据寄存器来进行操作串口的输出了,代码如下所示:

/*********************************************************************
 * @fn      usart1_put
 *
 * @brief   使用usart1串口输出单个字符.
 *
 * @param   c,需要输出的字符数据.
 *
 * @return  none
 */
void usart1_put(uint8_t c)
{
    uint16_t data = c & 0xff;

    // 检测发送状态,等待发送完毕
    while((USART1->STATR & STATUS_TC) == 0);
    // 填入待发送数据
    USART1->DATAR = data;
}

/*********************************************************************
 * @fn      usart1_puts
 *
 * @brief   使用usart1串口输出字符串.
 *
 * @param   c,需要输出的字符串指针.
 *
 * @return  返回总共发送的字符个数
 */
int usart1_puts(char *c)
{
    int cnt = 0;

    // 检测是否到字符串的结尾,如果到了字符串结尾,则退出循环
    while(*c)
    {
        // 进行单个字符数据的发送
        usart1_put((uint8_t)*c);
        // 对发送数据个数进行计数
        cnt++;
        c++;
    }

    return cnt;
}

        在代码中通过调用usart1_puts函数即可进行字符串的输出打印。

四、实现效果

        在start_kernel函数中进行打印输出,相关代码与输出打印如下所示:

void start_kernel(void)
{
	// 设置sysclk系统时钟为96MHz
	clock_hse_96Mhz();
	// 设置usart1,并初始化配置为115200,8,none,1
	usart1_init();

	usart1_puts("hello RVOS!\r\n");
	usart1_puts("\r\n======== RVOS ========\r\n");

	led2_ctrl(1);

	while (1) {} // stop here!
}

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值