基于亚博K210开发板——串口中断以及开启双核任务

开发板

亚博K210开发板
在这里插入图片描述

实验目的

本实验配置串口通信,并开启接收中断,主程序开启双核,核心0任务实现LED灯交替亮灭并打印数据,核心1任务实现实时读取串口数据,当达到一定条件开启或RGB交替亮灭并打印对应数据

实验准备

硬件原理图

Tpye-C 接口连接 K210 的 IO4 和 IO5 接口,其中 IO4 为 K210 芯片的接收引脚,IO5
为 K210 芯片的发送引脚。
在这里插入图片描述

软件对应SDK

对应的头文件 uart.h

通用 UART 为 UART1、UART2 和 UART3,支持异步通信(RS232 和 RS485 和IRDA,通信速率可达到 5Mbps。UART 支持 CTS 和 RTS 信号的硬件管理以及软件流控(XON 和 XOFF)。3 个接口均可被 DMA 访问或者 CPU 直接访问。每次传输数据为 8 字节,支持异步时钟,可单独配置数据时钟,实现全双工模式,保证两个时钟域中数据同步。

uart 默认为 RS232 模式,也可以配置为软件可编程式 RS485 模式。

用 THRE 中断模式来提升串口性能。当 THRE 模式和 FIFO 模式被选择之后,如果 FIFO 中少于阈值便触发 THRE 中断。

uart.h接口函数

• uart_init:初始化 uart
• uart_config (0.6.0 后不再支持,请使用 uart_configure)
• uart_configure:配置串口的波特率等
• uart_send_data:通过串口发送数据
• uart_send_data_dma:通过 dma 通道发送数据
• uart_send_data_dma_irq:UART 通过 DMA 发送数据,并注册 DMA 接收完成中断函数,仅单次中断
• uart_receive_data:读取串口数据
• uart_receive_data_dma:串口通过 dma 接收数据
• uart_receive_data_dma_irq:UART 通过 DMA 接收数据,并注册 DMA 接收完成中断函数,仅单次中断
• uart_irq_register:注册串口中断函数
• uart_irq_deregister:注销串口中断
• uart_set_work_mode:设置 uart 工作模式。有四种模式:普通 uart、红外、RS485 全双工、RS485 半双工。
• uart_set_rede_polarity:设置 RS485 re de 管脚有效时的极性。
• uart_set_rede_enable:使能 re de 管脚,主要用在 rs485 全双工模式,re 和 de 必须手动控制。单双工模式不用调用该函数,单双工时硬件会自动设置 re de。
• uart_set_tat:配置 re de 互相的时间间隔,这个与外部的 485 模块有关。
• uart_set_det:设置 de 有效无效转换时数据的时间延时。
• uart_debug_init:配置调试串口。系统默认使用 UART3 做为调试串口,调用该函数用户可以自定义使用哪个 uart 做为调试串口,如果使用 UART1 或 UART2 需要使用 fpioa 设置管脚。因此调试脚不局限于 fpioa4、5
• uart_handle_data_dma:UART 通过 DMA 传输数据

高速通用异步收发传输器(UARTHS)对应的头文件 uarths.h

高速 UART 为 UARTHS(UART0),通讯速率可达到 5Mbps,8 字节发送和接收FIFO,可编程式 THRE 中断,不支持硬件流控制或者其他调制解调器控制信号,或同步串行数据转换器。系统的 printf 调试函数默认就是调用 UARTHS 串口来实现发送数据的。

uarths.h接口函数

• uarths_init:初始化 UARTHS,系统默认波特率为 115200 8bit 1 位停止位无检验位。因为uarths 时钟源为 PLL0,在设置 PLL0 后需要重新调用该函数设置波特率,否则会打印乱码。
• uarths_config:设置 UARTHS 的参数。默认 8bit 数据,无校验位。
• uarths_receive_data:通过 UARTHS 读取数据。
• uarths_send_data:通过 UART 发送数据。
• uarths_set_irq:设置 UARTHS 中断回调函数。
• uarths_get_interrupt_mode:获取 UARTHS 的中断类型。接收、发送或接收发送同时中断。
• uarths_set_interrupt_cnt : 设 置 UARTHS 中断时的 FIFO 深度。 当中断类UARTHS_SEND_RECEIVE,发送接收 FIFO 中断深度均为 cnt;

板级对应的头文件 bsp.h

bsp.h 头文件是与平台相关的通用函数,核之间锁的相关操作。提供获取当前运行程序的 CPU 核编号的接口以及启动第二个核的入口。
K210 是双核 CPU,那么什么是双核 CPU 呢?双核 CPU 是在一个 CPU 中拥有两个一样功能的处理器芯片,从而提高计算能力。K210 的核心 0 和核心 1 都可以单独工作,系统默认使用核心 0,如果需要使用核心 1 需要手动开启核心 1 的服务。

bsp.h接口函数

• register_core1:向核心 1 注册函数,并启动核心 1
• current_coreid:获取当前 CPU 的核心编号(0/1)
• read_cycle:获取 CPU 开机至今的时钟数。可以用使用这个函数精准的确定程序运行时钟。可以配合 sysctl_clock_get_freq(SYSCTL_CLOCK_CPU)计算运行的时间。
• spinlock_lock:自旋锁,不可嵌套,不建议在中断使用,中断中可以使用 spinlock_trylock。
• spinlock_unlock:自旋锁解锁。
• spinlock_trylock:获取自旋锁,成功获取锁会返回 0,失败返回-1。
• corelock_lock:获取核间锁,核之间互斥的锁,同核内该锁会嵌套,只有异核之间会阻塞。不建议在中断使用该函数,中断中可以使用 corelock_trylock。
• corelock_trylock:获取核间锁,同核时锁会嵌套,异核时非阻塞。成功获取锁会返回 0,失败返回-1。
• corelock_unlock:核间锁解锁。
• sys_register_putchar:注册系统输出回调函数,printf 时会调用该函数。系统默认使用UART3,如果需要修改 UART 则调用 uart_debug_init 函数。
• sys_register_getchar:注册系统输入回调函数,scanf 时会调用该函数。系统默认使用UART3,如果需要修改 UART 则调用 uart_debug_init 函数。
• sys_stdin_flush:清理 stdin 缓存。
• get_free_heap_size:获取空闲内存大小。
• printk:打印核心调试信息,用户不必理会。

实验代码

bsp_led_rgb.h

#ifndef __BSP_LED_RGB_H_
#define __BSP_LED_RGB_H_
/*****************************HEAR-FILE************************************/
#include "fpioa.h"
#include "gpiohs.h"
#include "gpio.h"
#include "fpioa.h"
#include "sleep.h"

/*****************************HARDWARE-PIN*********************************/

#define IS_HIGH_GPIO  1


// 硬件IO口,与原理图对应

//led
#define PIN_LED_0             (0)
#define PIN_LED_1             (17)

//rgb
#define PIN_RGB_R                 (6)
#define PIN_RGB_G                 (7)
#define PIN_RGB_B                 (8)

/*****************************SOFTWARE-GPIO********************************/
// 软件GPIO口,与程序对应

//led
#define LED0_GPIONUM          (3)
#define LED1_GPIONUM          (4)

//rgb
#define RGB_R_GPIONUM          (0)
#define RGB_G_GPIONUM          (1)
#define RGB_B_GPIONUM          (2)

/*****************************FUNC-GPIO************************************/
// GPIO口的功能,绑定到硬件IO口

//led
#define FUNC_LED0             (FUNC_GPIO0 + LED0_GPIONUM)
#define FUNC_LED1             (FUNC_GPIO0 + LED1_GPIONUM)

//rgb
#if  IS_HIGH_GPIO
#define FUNC_RGB_R             (FUNC_GPIOHS0 + RGB_R_GPIONUM)
#define FUNC_RGB_G             (FUNC_GPIOHS0 + RGB_G_GPIONUM)
#define FUNC_RGB_B             (FUNC_GPIOHS0 + RGB_B_GPIONUM)
#else
#define FUNC_RGB_R             (FUNC_GPIO0 + RGB_R_GPIONUM)
#define FUNC_RGB_G             (FUNC_GPIO0 + RGB_G_GPIONUM)
#define FUNC_RGB_B             (FUNC_GPIO0 + RGB_B_GPIONUM)
#endif

void rgbInit(void);
void ledInit(void);
void rgbClose(void);
void ledClose(void);
void ledFlash(int ms);
void rgbFlash(int ms);


#endif /* __BSP_LED_RGB_H_ */

bsp_led_rgb.c

#include "bsp_led_rgb.h"

void hardware_init(void)
{

    fpioa_set_function(PIN_LED_0, FUNC_LED0);
    fpioa_set_function(PIN_LED_1, FUNC_LED1);

    fpioa_set_function(PIN_RGB_R, FUNC_RGB_R);
    fpioa_set_function(PIN_RGB_G, FUNC_RGB_G);
    fpioa_set_function(PIN_RGB_B, FUNC_RGB_B);
}

void rgbInit()
{
    gpio_init();
    //硬件初始化,绑定GPIO口
    fpioa_set_function(PIN_RGB_R, FUNC_RGB_R);
    fpioa_set_function(PIN_RGB_G, FUNC_RGB_G);
    fpioa_set_function(PIN_RGB_B, FUNC_RGB_B);

    //设置模式为输出
#if  IS_HIGH_GPIO     
    gpiohs_set_drive_mode(RGB_R_GPIONUM, GPIO_DM_OUTPUT);
    gpiohs_set_drive_mode(RGB_G_GPIONUM, GPIO_DM_OUTPUT);
    gpiohs_set_drive_mode(RGB_B_GPIONUM, GPIO_DM_OUTPUT);
#else
    gpio_set_drive_mode(RGB_R_GPIONUM, GPIO_DM_OUTPUT);
    gpio_set_drive_mode(RGB_G_GPIONUM, GPIO_DM_OUTPUT);
    gpio_set_drive_mode(RGB_B_GPIONUM, GPIO_DM_OUTPUT);
 #endif 
}


void ledInit()
{
    gpio_init();
    //硬件初始化,绑定GPIO口
    fpioa_set_function(PIN_LED_0, FUNC_LED0);
    fpioa_set_function(PIN_LED_1, FUNC_LED1);
    //设置LED0和LED1的GPIO模式为输出
    gpio_set_drive_mode(LED0_GPIONUM, GPIO_DM_OUTPUT);
    gpio_set_drive_mode(LED1_GPIONUM, GPIO_DM_OUTPUT);

}

void rgbClose()
{
#if  IS_HIGH_GPIO    
    gpiohs_set_pin(RGB_R_GPIONUM, GPIO_PV_HIGH);
    gpiohs_set_pin(RGB_G_GPIONUM, GPIO_PV_HIGH);
    gpiohs_set_pin(RGB_B_GPIONUM, GPIO_PV_HIGH);
#else
    gpio_set_pin(RGB_R_GPIONUM, GPIO_PV_HIGH);
    gpio_set_pin(RGB_G_GPIONUM, GPIO_PV_HIGH);
    gpio_set_pin(RGB_B_GPIONUM, GPIO_PV_HIGH);
#endif    
}


void ledClose()
{
    // 先关闭LED0和LED1
    gpio_pin_value_t value = GPIO_PV_HIGH;
    gpio_set_pin(LED0_GPIONUM, value);
    gpio_set_pin(LED1_GPIONUM, value);

}

void ledFlash(int ms)
{
    static gpio_pin_value_t value = GPIO_PV_HIGH;
    msleep(ms);
    gpio_set_pin(LED0_GPIONUM, value);
    gpio_set_pin(LED1_GPIONUM, value = !value);
}

void rgbFlash(int ms)
{
    static uint8_t rgbIndex = 0;
    rgbIndex %= 3; 
    rgbClose();
    gpiohs_set_pin(rgbIndex, GPIO_PV_LOW);
    rgbIndex++;
    msleep(ms);
}
bsp_usart.h

```c
#ifndef __BSP_USART_H
#define __BSP_USART_H
/*****************************HEAR-FILE************************************/
#include "fpioa.h"
#include "uart.h"
#include "sysctl.h"

/*****************************HARDWARE-PIN*********************************/
// 硬件IO口,与原理图对应
#define PIN_UART_USB_RX       (4)
#define PIN_UART_USB_TX       (5)

/*****************************SOFTWARE-GPIO********************************/
// 软件GPIO口,与程序对应
#define UART_USB_NUM           UART_DEVICE_3

/*****************************FUNC-GPIO************************************/
// GPIO口的功能,绑定到硬件IO口
#define FUNC_UART_USB_RX       (FUNC_UART1_RX + UART_USB_NUM * 2)
#define FUNC_UART_USB_TX       (FUNC_UART1_TX + UART_USB_NUM * 2)



typedef struct UsartRecData
{
    uint8_t reclen;
    char recData;
    /* data */
}UsartRecData;
 



void usartInit(int uartNum,int baudRrate);
void uartSendData(int uartNum,char *data,int size);
bool waitForMessage(int uartNum);

extern UsartRecData usartData;

#endif /* _PIN_CONFIG_H_ */

bsa_usart.c

#include "bsp_usart.h"
#include "string.h"

UsartRecData usartData;


void uart_hardware_init(void)
{

    fpioa_set_function(PIN_UART_USB_RX, FUNC_UART_USB_RX);
    fpioa_set_function(PIN_UART_USB_TX, FUNC_UART_USB_TX);

}

int uartCallBack(void *ctx)
{       
    char temp;
    while(uart_receive_data(UART_USB_NUM,&usartData.recData,1)){
       
    }
    
    return 0;
}

void usartInit(int uartNum,int baudRrate)
{

    uart_hardware_init();
     // 初始化串口,设置波特率为115200
    uart_init(uartNum);
    // 设置 uart 工作模式
    uart_set_work_mode (UART_USB_NUM , UART_NORMAL);
    // 初始化串口
    uart_configure(UART_USB_NUM,baudRrate,UART_BITWIDTH_8BIT, UART_STOP_1, UART_PARITY_NONE);
     // 初始化外部中断 
    uart_irq_register(UART_USB_NUM, UART_RECEIVE, uartCallBack,NULL,2);
    // 设置接收中断 触发 FIFO 深度
    uart_set_receive_trigger(UART_USB_NUM, UART_RECEIVE_FIFO_1);
    

}

void uartSendData(int uartNum,char *data,int size)
{

    uart_send_data(UART_USB_NUM, data, size);
  
}

bool waitForMessage(int uartNum)
{
    char rec = 0;
    while(uart_receive_data(uartNum,&rec,1)){
        if(1 == rec){
            return true;
        }else{
            return false;
        }
    }
}
    

mian.c

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "bsp.h"
#include "bsp_led_rgb.h"
#include "bsp_usart.h"


int core1TaskRun(void *ctx)
{
    char core1Log1[40] = "rgb state is opened\r\n";
    char core1Log2[40] = "wait for open rgb\r\n";

     while(1){
        if(usartData.recData == 1){
            rgbFlash(300);
            uartSendData(UART_USB_NUM,core1Log1,sizeof(core1Log1));
        }else{
           sleep(1);
           uartSendData(UART_USB_NUM,core1Log2,sizeof(core1Log2));
        }
        
    }
}

void core1Init()
{
    register_core1(core1TaskRun,NULL);
}


int main(void)
{

    char core0Log[50] = "this is core0 task!\r\n";
    
    plic_init();
    sysctl_enable_irq();
    ledInit();
    rgbInit();

    usartInit(UART_USB_NUM,115200);

    core1Init();

    while (1){
       
        ledFlash(1000);
        uartSendData(UART_USB_NUM,core0Log,sizeof(core0Log));       
    }
    
        
    
    return 0;
}

实验结果

编译烧录之后LED0和LED1会依次交替亮灭,串口助手上会打印任务0信息,当在串口助手上发送字符1时,任务1会开启RGB灯的交替亮灭并打印信息,若发送字符0后,任务1会关闭rgb的交替亮灭。

效果

发送 0 后(rgb停止闪烁)
发送字符0后
发送 1 后(rgb开始闪烁)
发送字符1后

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值