grbl移植日志第二天移植串口数据接收

zynq的串口发送中断总是不能进入中断函数 . . . 看了好几天. 找不到原因了. 后来用了官方的串口中断示例代码也不行…
后来终于找到原因了…我的妈呀. 卡了我好几天, 原来是中断函数里面有个函数指针指向了Null.

if(rec_data == CMD_TOOL_ACK ) {   // If tool change acknowledged
	 hal.stream.read = serialGetC;                    // and restore normal input.
}
else if (!hal.stream.enqueue_rt_command((char)rec_data)) 
{
	fifo_push(&rxbuffer, (char)rec_data);
}

这个hal.stream.enqueue_rt_command 因为没有初始化, 导致指向的是Null. 执行过后就停止了.中断也不再进入了. C语言真的是要命啊.这种也不报异常,全靠人工逐行排查…
不知道C++能不能补货到这种异常.

zynq的串口中断示例中, 有些bug. 提供的库也不是很好用. 因为封装好的库里面内置了一些固定的逻辑, 里面默认进行了中断的开启和关闭. 用起来并不是很顺手.

因为grbl 有一个循环缓冲队列, 为了实现此数据的上传, 需要在中断中修改此队列的指针.
索性摸索了一下zynq的的uart库, 直接基于寄存器自己写了一个. 要简单简洁的多.
不再需要像下面这使用uart官方提供的函数XUartPs_InterruptHandler, 也就不需要再使用
XUartPs_SetHandler 进行绑定了. 因为 XUartPs_InterruptHandler 中调用了XUartPs_SetHandler 设置的函数.

 XScuGic_Connect(gicPtr, XPAR_PS7_UART_0_INTR, Xil_InterruptHandler)XUartPs_InterruptHandler, (void *)xUart0Ptr);  
 XUartPs_SetHandler(xUart0Ptr, (XUartPs_Handler)uartIntrHandler, xUart0Ptr); 

据到FIFO

 /* Fill the FIFO from the buffer 
   填充发送数据到TX 的FIFO
*/
XUartPs_WriteReg(InstancePtr->Config.BaseAddress,  XUARTPS_FIFO_OFFSET,
		   ((u32)InstancePtr->SendBuffer.
		   NextBytePtr[SentCount]));

禁用TXEMPTY中断

 
//禁用TXEMPTY中断
XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL));

启用TXEMPTY中断

//启用TXEMPTY中断
XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IER_OFFSET, ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL));

读取当前中断寄存器ISR的状态

//读取当前中断寄存器ISR的状态
/*
 * Read the interrupt ID register to determine which
 * interrupt is active
 */
u32 IsrStatus;
IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,  XUARTPS_IMR_OFFSET); 
IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress,  XUARTPS_ISR_OFFSET);

判断是不是FITO TX发送完成触发的中断

//判断是不是FITO TX发送完成触发的中断
if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL))  != (u32)0)
{
	/* Transmit data interrupt */
	SendDataHandler(InstancePtr, IsrStatus);
}

判断是不是接收溢出或接收空或者接收满的触发的状态.

/* Dispatch an appropriate handler. */
//判断是不是接收溢出或接收空或者接收满的触发的状态.
if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY |
		(u32)XUARTPS_IXR_RXFULL)) != (u32)0)
 { 
 	ReceiveDataHandler(InstancePtr);
}

上面的这些代码都是参考自 xuartps_intr.c,xuartps.c

void XUartPs_InterruptHandler(XUartPs *InstancePtr)
{
.....
}

把官方提供的库XUartPs_InterruptHandler 抄过来
改个名

void MyXUartPs_InterruptHandler(XUartPs *InstancePtr){
		u32 IsrStatus;

		Xil_AssertVoid(InstancePtr != NULL);
		Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

		/*
		 * Read the interrupt ID register to determine which
		 * interrupt is active
		 */
		IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,  XUARTPS_IMR_OFFSET);

		IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress,  XUARTPS_ISR_OFFSET);

		/* Dispatch an appropriate handler. */
		if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY |
				(u32)XUARTPS_IXR_RXFULL)) != (u32)0) {
			/* Received data interrupt */
//			ReceiveDataHandler(InstancePtr);
		}

		if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL))  != (u32)0)
		{
			/* Transmit data interrupt */
			SendDataHandler(InstancePtr, IsrStatus);
		}

		/* XUARTPS_IXR_RBRK is applicable only for Zynq Ultrascale+ MP */
		if ((IsrStatus & ((u32)XUARTPS_IXR_OVER | (u32)XUARTPS_IXR_FRAMING |
				(u32)XUARTPS_IXR_PARITY | (u32)XUARTPS_IXR_RBRK)) != (u32)0) {
			/* Received Error Status interrupt */
//			ReceiveErrorHandler(InstancePtr, IsrStatus);
		}

		if((IsrStatus & ((u32)XUARTPS_IXR_TOUT)) != (u32)0) {
			/* Received Timeout interrupt */
//			ReceiveTimeoutHandler(InstancePtr);
		}

		if((IsrStatus & ((u32)XUARTPS_IXR_DMS)) != (u32)0) {
			/* Modem status interrupt */
//			ModemHandler(InstancePtr);
		}

		/* Clear the interrupt status. */
		XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET, IsrStatus);

}

中断管理器中把函数和中断管理器进行连接. 这里连接到的是我上面自己修改过的MyXUartPs_InterruptHandler

	Status = XScuGic_Connect(IntcInstancePtr, UartIntrId,  (Xil_InterruptHandler) MyXUartPs_InterruptHandler,  (void *) UartInstancePtr);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值