microblaze例程 - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki

寄存器操作函数(xil_io.h)

#include "xil_io.h"

u8 Xil_In8(UINTPTR Addr)
u16 Xil_In16(UINTPTR Addr)
u32 Xil_In32(UINTPTR Addr)
u64 Xil_In64(UINTPTR Addr)

void Xil_Out8(UINTPTR Addr, u8 Value)
void Xil_Out16(UINTPTR Addr, u16 Value)
void Xil_Out32(UINTPTR Addr, u32 Value)
void Xil_Out64(UINTPTR Addr, u64 Value)

Cache操作函数

DDR访问,一般会关闭Dcache

#include "xil_cache.h"

Xil_ICacheDisable();
Xil_DCacheDisable();
Xil_DCacheFlush();

2个mb访问公共资源,可以用blockram做互斥信号量mutex。构造方法是

#define BRAM_BASE_ADDR 0xC0000000
#define LOCK_ADDR (BRAM_BASE_ADDR+0x0100)

// process-0
Xil_Out32(LOCK_ADDR, 1);

while(1){
	u32 lock=Xil_In32(LOCK_ADDR);
	if(lock==1){
		Xil_Out32(LOCK_ADDR, 0);

			 do_something();

		Xil_Out32(LOCK_ADDR, 1);
	}
	usleep(800*1000);
}

// process-1
while(1){
	u32 lock=Xil_In32(LOCK_ADDR);
	if(lock==1){
		Xil_Out32(LOCK_ADDR, 0);
			
			do_something();

		Xil_Out32(LOCK_ADDR, 1);
	}
	usleep(500*1000);
}

GPIO

#include <stdio.h>
#include "xparameters.h"
#include "xgpio.h"
#include "sleep.h"

#define GPIO_DEVICE_ID XPAR_AXI_GPIO_0_DEVICE_ID // 根据实际硬件配置修改
#define LED_CHANNEL 1

int main() {
    XGpio gpio;
    int Status;

    xil_printf("Microblaze GPIO test!\r\n");

    // 初始化GPIO
    Status = XGpio_Initialize(&gpio, GPIO_DEVICE_ID);
    if (Status != XST_SUCCESS) {
        printf("GPIO Initialization failed\n");
        return XST_FAILURE;
    }

    // 设置GPIO为输出
    XGpio_SetDataDirection(&gpio, LED_CHANNEL, 0x00);

    while (1) {
        // 依次翻转四个GPIO引脚
        XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b0001);
        usleep(500000); // 等待500毫秒

        XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b0010);
        usleep(500000);

        XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b0100);
        usleep(500000);

        XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b1000);
        usleep(500000);
    }

    return 0;
}

Key_Interrupt

#include "xparameters.h"
#include "xintc.h"
#include "xgpio.h"
#include "sleep.h"

#define KEY_DEV_ID       XPAR_AXI_GPIO_1_DEVICE_ID  //按键 AXI GPIO ID
#define LED_DEV_ID       XPAR_AXI_GPIO_0_DEVICE_ID  //LED AXI GPIO ID
#define INTC_DEVICE_ID   XPAR_INTC_0_DEVICE_ID      //中断控制器ID
#define EXCEPTION_ID     XIL_EXCEPTION_ID_INT       //中断异常ID
#define AXI_GPIO_INTR_ID XPAR_INTC_0_GPIO_1_VEC_ID  //AXI GPIO中断ID

static XIntc    Intc;                              //中断控制器实例
static XGpio    KEY_Gpio;                          //GPIO中断实例 按键
static XGpio    LED_Gpio;                          //GPIO实例

int led_value;          //LED值
int key_value;          //按键值
int Intr_times = 0;     //有效中断计数
int key_intr_flag = 0;  //中断标志

void GpioHandler(void *CallbackRef);

int main(){
    xil_printf("AXI GPIO INTERRUPT TEST!\r\n");
    //AXI_GPIO器件初始化
    XGpio_Initialize(&KEY_Gpio, KEY_DEV_ID);
    XGpio_Initialize(&LED_Gpio, LED_DEV_ID);
    //为指定的GPIO信道设置所有独立信号的输入/输出方向
    XGpio_SetDataDirection(&LED_Gpio, 1, 0);
    //设置LED初始值
    XGpio_DiscreteWrite(&LED_Gpio, 1, 0x0f);
//    sleep(2);
//    XGpio_DiscreteWrite(&LED_Gpio, 1, 0x00);


    XGpio_SetDataDirection(&KEY_Gpio, 1, 1);
//    while(1){
//    int v=XGpio_DiscreteRead(&KEY_Gpio, 1);
//    xil_printf("%d\r\n",v);
//    sleep(1);
//    }


    //初始化中断控制器
    XIntc_Initialize(&Intc, INTC_DEVICE_ID);
    //关联中断ID和中断服务函数
    XIntc_Connect(&Intc,AXI_GPIO_INTR_ID,(Xil_ExceptionHandler)GpioHandler,&KEY_Gpio );
    //使能中断
    XGpio_InterruptEnable(&KEY_Gpio, 1);
    //使能全局中断
    XGpio_InterruptGlobalEnable(&KEY_Gpio);
    //在中断控制器上启用中断向量
    XIntc_Enable(&Intc,AXI_GPIO_INTR_ID);
    //启动中断控制器
    XIntc_Start(&Intc, XIN_REAL_MODE);
    //设置并打开中断异常处理
    Xil_ExceptionInit();
    Xil_ExceptionRegisterHandler(EXCEPTION_ID,
            (Xil_ExceptionHandler)XIntc_InterruptHandler,&Intc);
    Xil_ExceptionEnable();

    while(1){
        if(key_intr_flag){        //检测中断标志信号有效
            key_value = XGpio_DiscreteRead(&KEY_Gpio, 1);  //读取按键值
            if(key_value != 3){             //检测按键是否按下
                if(Intr_times == 0)         //根据有效中断数点亮LED
                    led_value = 0x01;
                else if(Intr_times == 1)
                    led_value = 0x02;
                else if(Intr_times == 2)
                    led_value = 0x04;
                else
                    led_value = 0x08;
            //按键按下后点亮对应LED灯
            XGpio_DiscreteWrite(&LED_Gpio, 1, led_value);
            xil_printf("i = %d\r\n",Intr_times);  //打印当前的Intr_times
            Intr_times = (Intr_times + 1)%4;    //将计数值约束在0到3之间
            //延迟1秒
            sleep(1);
            }
        key_intr_flag = 0;              //中断标志清零
        }
    }
    return 0;
}

void GpioHandler(void *CallbackRef){
    XGpio *GpioPtr = (XGpio *)CallbackRef;
        key_intr_flag = 1;                   //接收到中断,标志信号拉高
        XGpio_InterruptDisable(GpioPtr, 1);  //关闭中断
        XGpio_InterruptClear(GpioPtr, 1);    //清除中断
        XGpio_InterruptEnable(GpioPtr, 1);   //使能中断
}

Uartlite_Interrupt

#include "xil_exception.h"
#include "xdebug.h"
#include "xparameters.h"
#include "xintc.h"
#include "xuartlite.h"
#include "xuartlite_l.h"

#define UART_DEVICE_ID XPAR_UARTLITE_0_DEVICE_ID     //串口器件ID
#define UART_INTR_ID   XPAR_INTC_0_UARTLITE_0_VEC_ID //串口中断ID
#define INTC_ID        XPAR_INTC_0_DEVICE_ID         //中断控制器ID

#define RX_NOEMPTY     XUL_SR_RX_FIFO_VALID_DATA     // 接收FIFO非空

static XIntc Intc;          //中断控制器实例
static XUartLite Uart;      //串口实例

void uart_handler(void *CallbackRef);

int main(void){
    //初始化串口设备
    XUartLite_Initialize(&Uart , UART_DEVICE_ID);

    xil_printf("hello!\r\n");
    //初始化中断控制器
    XIntc_Initialize(&Intc, INTC_ID);
    //关联处理函数
    XIntc_Connect(&Intc, UART_INTR_ID,(XInterruptHandler)uart_handler,&Uart);
    //使能串口
    XUartLite_EnableInterrupt(&Uart);
    //打开中断控制器
    XIntc_Start(&Intc, XIN_REAL_MODE);
    //使能中断控制器
    XIntc_Enable(&Intc,UART_INTR_ID);
    //设置并打开中断异常处理功能
    Xil_ExceptionInit();
        Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                (Xil_ExceptionHandler)XIntc_InterruptHandler , &Intc);
        Xil_ExceptionEnable();
    while(1);
}

void uart_handler(void *CallbackRef)//中断处理函数
{
    u8 Read_data;
    u32 isr_status;
    XUartLite *InstancePtr= (XUartLite *)CallbackRef;

    //读取状态寄存器
    isr_status = XUartLite_ReadReg(InstancePtr->RegBaseAddress ,
                                   XUL_STATUS_REG_OFFSET);
    if(isr_status & RX_NOEMPTY){  //接收FIFO中有数据
        //读取数据
        Read_data=XUartLite_ReadReg(InstancePtr->RegBaseAddress ,
                                    XUL_RX_FIFO_OFFSET);
        //发送数据
        XUartLite_WriteReg(InstancePtr->RegBaseAddress ,
                           XUL_TX_FIFO_OFFSET, Read_data);
    }
}

Uartlite_send_recv

#include "xil_exception.h"
#include "xdebug.h"
#include "xparameters.h"
#include "xintc.h"
#include "xuartlite.h"
#include "xuartlite_l.h"
#include "sleep.h"

#define UART_DEVICE_ID XPAR_UARTLITE_0_DEVICE_ID     //串口器件ID
static XUartLite Uart;      //串口实例

int main(void) {
	//初始化串口设备
	XUartLite_Initialize(&Uart, UART_DEVICE_ID);

	//initial send
	char str[] =
			"hello world! i'm xujch! hello world! i'm xujch! hello world! i'm xujch!\r\n";
	char *p = &str[0];
	while (*p) {
		XUartLite_SendByte(Uart.RegBaseAddress, *p);
		p++;
	}

	//echo back
	while (1){
		char c=XUartLite_RecvByte(Uart.RegBaseAddress);
		XUartLite_SendByte(Uart.RegBaseAddress, c);
	}
}

以上程序,我们使用了XUartLite_RecvByte()和XUartLite_SendByte()这2个库函数,可以看看它是怎么写的:

void XUartLite_SendByte(UINTPTR BaseAddress, u8 Data)
{
	while (XUartLite_IsTransmitFull(BaseAddress));

	XUartLite_WriteReg(BaseAddress, XUL_TX_FIFO_OFFSET, Data);
}

u8 XUartLite_RecvByte(UINTPTR BaseAddress)
{
	while (XUartLite_IsReceiveEmpty(BaseAddress));

	return (u8)XUartLite_ReadReg(BaseAddress, XUL_RX_FIFO_OFFSET);
}

Timer_Interrupt

#include <stdio.h>
#include "xparameters.h"
#include "xintc.h"
#include "xtmrctr.h"
#include "xil_exception.h"
#include "xgpio.h"
#include "xil_printf.h"

#define LED_DEV_ID          XPAR_GPIO_0_DEVICE_ID   //LED ID
#define INTC_ID             XPAR_INTC_0_DEVICE_ID   //中断控制器ID
#define TMRCTR_DEVICE_ID    XPAR_TMRCTR_0_DEVICE_ID //定时器中断ID

#define TMRCTR_INTR_ID  XPAR_INTC_0_TMRCTR_0_VEC_ID //定时中断ID

#define XIL_EXCEPTION_ID_INT    16U                 //中断异常ID

#define LED_Channel     1

XIntc Intc;     //中断控制器实例
XGpio led_gpio; //LED实例
XTmrCtr Timer;    //定时器实例

void timer_intr_hander(void *InstancePtr);

int main() {
	print("timer interrupt test\n");
	//初始化LED
	XGpio_Initialize(&led_gpio, LED_DEV_ID);
	//为指定的GPIO信道设置所有独立信号的输入/输出方向
	XGpio_SetDataDirection(&led_gpio, 1, 0);
	//设置LED初始值
	XGpio_DiscreteWrite(&led_gpio, 1, 0x0f);
	//定时器初始化
	XTmrCtr_Initialize(&Timer, TMRCTR_DEVICE_ID);
	//为指定的计时器启用指定的选项。
	XTmrCtr_SetOptions(&Timer, 0, XTC_INT_MODE_OPTION |    //中断操作
			XTC_AUTO_RELOAD_OPTION | //自动加载
			XTC_DOWN_COUNT_OPTION);  //递减计数

	//设置指定计时器的重置值
	XTmrCtr_SetResetValue(&Timer, 0, 50000000);
	//设置计时器回调函数,指定的计时器满一个周期时驱动程序将调用该回调函数
	XTmrCtr_SetHandler(&Timer, timer_intr_hander, &Timer);
	//开启定时器
	XTmrCtr_Start(&Timer, 0);
	//中断控制器初始化
	XIntc_Initialize(&Intc, INTC_ID);
	//关联中断源和中断处理函数
	XIntc_Connect(&Intc, TMRCTR_INTR_ID,
			(XInterruptHandler) XTmrCtr_InterruptHandler, &Timer);
	//开启中断控制器
	XIntc_Start(&Intc, XIN_REAL_MODE);
	//使能中断控制器
	XIntc_Enable(&Intc, TMRCTR_INTR_ID);
	//设置并打开中断异常处理
	Xil_ExceptionInit();
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
			(Xil_ExceptionHandler) XIntc_InterruptHandler, &Intc);
	Xil_ExceptionEnable();

	while (1)
		;
}

void timer_intr_hander(void *InstancePtr)  //回调函数
{
	static int led_state = 0x00;
	//检测计数是否满一个周期
	if (XTmrCtr_IsExpired(&Timer, 0)) {
		led_state = ~led_state;                       //LED状态翻转
		XGpio_DiscreteWrite(&led_gpio, 1, led_state); //输出LED值
	}
}

Timer_PWM

#include "xtmrctr.h"
#include "xparameters.h"
#include "xil_exception.h"
#include "xintc.h"
#include <stdio.h>
#include "sleep.h"


#define TMRCTR_DEVICE_ID        XPAR_TMRCTR_0_DEVICE_ID
#define TMRCTR_INTERRUPT_ID     XPAR_INTC_0_TMRCTR_0_VEC_ID

#define INTC_DEVICE_ID          XPAR_INTC_0_DEVICE_ID
#define INTC                    XIntc
#define INTC_HANDLER            XIntc_InterruptHandler

#define PWM_PERIOD              50000000    /* PWM period in (50 ms) */
#define TMRCTR_0                0            /* Timer 0 ID */
#define TMRCTR_1                1            /* Timer 1 ID */


int TmrCtrPwmExample_my(INTC *IntcInstancePtr, XTmrCtr *InstancePtr, u16 DeviceId,
								u16 IntrId);
INTC InterruptController;  /* The instance of the Interrupt Controller */
XTmrCtr TimerCounterInst;  /* The instance of the Timer Counter */


int main(void)
{
	int Status;

	/* Run the Timer Counter PWM example */
	Status = TmrCtrPwmExample_my(&InterruptController, &TimerCounterInst,
				  TMRCTR_DEVICE_ID, TMRCTR_INTERRUPT_ID);
}

int TmrCtrPwmExample_my(INTC *IntcInstancePtr, XTmrCtr *TmrCtrInstancePtr,
						u16 DeviceId, u16 IntrId)
{

	u8 DutyCycle;
	u32 Period;
	u32 HighTime;
	int Status;

	Status = XTmrCtr_Initialize(TmrCtrInstancePtr, DeviceId);
	Status = XTmrCtr_SelfTest(TmrCtrInstancePtr, TMRCTR_0);


	Period = PWM_PERIOD;
	HighTime = PWM_PERIOD;
	do {
		XTmrCtr_PwmDisable(TmrCtrInstancePtr);
		DutyCycle = XTmrCtr_PwmConfigure(TmrCtrInstancePtr, Period, HighTime); /*Config PWM*/
		XTmrCtr_PwmEnable(TmrCtrInstancePtr);
		xil_printf("PWM Configured for Duty Cycle = %d\r\n", DutyCycle);
		HighTime -= PWM_PERIOD / 20;
		sleep(1);
	} while (DutyCycle > 0);

	return Status;
}
⚠️ **GitHub.com Fallback** ⚠️