microblaze 串口学习·2
microblaze 串口学习·2
串口初始化函数1int XUartLite_Initialize(XUartLite *InstancePtr, u16 DeviceId)
int XUartLite_Initialize(XUartLite *InstancePtr, u16 DeviceId)
{
XUartLite_Config *ConfigPtr;
Xil_AssertNonvoid(InstancePtr != NULL);
ConfigPtr = XUartLite_LookupConfig(DeviceId);
if (ConfigPtr == (XUartLite_Config *)NULL) {
return XST_DEVICE_NOT_FOUND;
}
return XUartLite_CfgInitialize(InstancePtr, ConfigPtr,
ConfigPtr->RegBaseAddr);
}
##1 串口初始化 XUartLite_Config *ConfigPtr;
typedef struct {
u16 DeviceId; /**< Unique ID of device */
UINTPTR RegBaseAddr; /**< Register base address */
u32 BaudRate; /**< Fixed baud rate */
u8 UseParity; /**< Parity generator enabled when TRUE */
u8 ParityOdd; /**< Parity generated is odd when TRUE, even
when FALSE */
u8 DataBits; /**< Fixed data bits */
} XUartLite_Config;
ConfigPtr是一个指向结构体的指针,这个结构体中包含了串口配置的一些参数,需要注意的是。MDM串口的一些参数无法在寄存器级别进行修改。因此需要在硬件工程例化的时候。进行设置
2 Xil_AssertNonvoid(InstancePtr != NULL);
xlinx的断言函数,用于检测参数输入的合法性,猜测是重定向了assert的输出,这个以后再研究。不影响整体的逻辑实现。
3 ConfigPtr = XUartLite_LookupConfig(DeviceId);
XUartLite_Config *XUartLite_LookupConfig(u16 DeviceId)
{
XUartLite_Config *CfgPtr = NULL;
u32 Index;
for (Index=0; Index < XPAR_XUARTLITE_NUM_INSTANCES; Index++) {
if (XUartLite_ConfigTable[Index].DeviceId == DeviceId) {
CfgPtr = &XUartLite_ConfigTable[Index];
break;
}
}
return CfgPtr;
}
控制向量在这个函数中被赋值。
首先初始化空指针,然后检查外设ID,然后通过IC查询,将XUartLite_ConfigTable中的参数传递给XUartLite_Configptr。XUartLite_ConfigTable的结构和CfgPtr的结构完全一致。XUartLite_ConfigTable是由vitis自动生成的参数配置文件,XUartLite_ConfigTable本质是一个结构体常量,内部全都是用宏来定义参数,具体的参数被保存在xparameter中。
如果输入的DeviceID不合法,那么函数就会返回空指针,导致配置失败。
4 return XUartLite_CfgInitialize(InstancePtr, ConfigPtr,ConfigPtr->RegBaseAddr);
int XUartLite_CfgInitialize(XUartLite *InstancePtr, XUartLite_Config *Config,
UINTPTR EffectiveAddr)
{
(void) Config;
/*
* Assert validates the input arguments
*/
Xil_AssertNonvoid(InstancePtr != NULL);
/*
* Set some default values, including setting the callback
* handlers to stubs.
*/
InstancePtr->SendBuffer.NextBytePtr = NULL;
InstancePtr->SendBuffer.RemainingBytes = 0;
InstancePtr->SendBuffer.RequestedBytes = 0;
InstancePtr->ReceiveBuffer.NextBytePtr = NULL;
InstancePtr->ReceiveBuffer.RemainingBytes = 0;
InstancePtr->ReceiveBuffer.RequestedBytes = 0;
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
#if (XPAR_XUARTLITE_USE_DCR_BRIDGE != 0)
InstancePtr->RegBaseAddress = ((EffectiveAddr >> 2)) & 0xFFF;
#else
InstancePtr->RegBaseAddress = EffectiveAddr;
#endif
InstancePtr->RecvHandler = StubHandler;
InstancePtr->SendHandler = StubHandler;
/* Write to the control register to disable the interrupts, don't
* reset the FIFOs are the user may want the data that's present
*/
XUartLite_WriteReg(InstancePtr->RegBaseAddress,
XUL_CONTROL_REG_OFFSET, 0);
/*
* Clear the statistics for this driver
*/
XUartLite_ClearStats(InstancePtr);
return XST_SUCCESS;
}
传入的参数是外设指针,外设配置参数指针,外设寄存器起始地址。首先将传入的Config结构体指针强制转换成无类型(这里没理解上去,为什么要这么转换?)
对外设结构体中的一些变量赋初值
对于 XPAR_XUARTLITE_USE_DCR_BRIDGE
这个的理解我找到了Xlinx的一篇文档。
On-Chip Periphaeral Bus (OPB)
**device control register (DCR) **
可以看到对于外设寄存器的访问有很多不同的方式,文章中就提到了一种CPU-OPB的桥路。
这个地方先挖个坑,以后再研究实现细节和区别。
5 XUartLite_WriteReg(BaseAddress, RegOffset, Data)
#define XUartLite_WriteReg(BaseAddress, RegOffset, Data)
XUartLite_Out32((BaseAddress) + (RegOffset), (u32)(Data))
然后按照配置,写入地址+地址偏移+数据
然后清空外设的Stats reg标志,至此初始化完成。
- 点赞
- 收藏
- 关注作者
评论(0)