在VXWORKS7.0 里,如果直接访问某个寄存器地址,往一个寄存器里写入数据时,系统会报错,原因是VXWORKS7.0 里采用了虚拟地址访问,不能直接进行读写寄存器。因此vx提供了很多访问寄存器接口:
#define CSR_READ_4(pDev, addr) \
vxbRead32 (FEI_HANDLE(pDev), (UINT32 *)((char *)FEI_BAR(pDev) + addr))
#define CSR_WRITE_4(pDev, addr, data) \
vxbWrite32 (FEI_HANDLE(pDev), \
(UINT32 *)((char *)FEI_BAR(pDev) + addr), data)
#define CSR_READ_2(pDev, addr) \
vxbRead16 (FEI_HANDLE(pDev), (UINT16 *)((char *)FEI_BAR(pDev) + addr))
#define CSR_WRITE_2(pDev, addr, data) \
vxbWrite16 (FEI_HANDLE(pDev), \
(UINT16 *)((char *)FEI_BAR(pDev) + addr), data)
#define CSR_READ_1(pDev, addr) \
vxbRead8 (FEI_HANDLE(pDev), (UINT8 *)((char *)FEI_BAR(pDev) + addr))
#define CSR_WRITE_1(pDev, addr, data) \
vxbWrite8 (FEI_HANDLE(pDev), \
(UINT8 *)((char *)FEI_BAR(pDev) + addr), data)
但是这些接口不能直接使用,需要传递一个pDev的句柄,如果需要直接修改如何做呢,我们顺藤摸瓜查看这些接口的原型,以vxbWrite8 为例子。
vxbWrite8 ->vxbRegMap。
STATUS vxbRegMap
(
VXB_RESOURCE * pRes /* description of register to map */
)
{
VXB_RESOURCE_ADR * pResAdr = NULL;
...............
/* req: VX7-13696 */
if (VXB_RES_TYPE(pRes->id) == VXB_RES_IO)
{
/* req: VX7-13697 */
pResAdr->virtual = VXB_ARCH_IO_MAP (pResAdr->start, pResAdr->size);
pResAdr->pHandle = (void *) VXB_ARCH_IO_HANDLE;
}
else
{
/* req: VX7-13698 */
pResAdr->virtual = VXB_ARCH_MEM_MAP (pResAdr->start, pResAdr->size);
pResAdr->pHandle = (void *) VXB_ARCH_MEM_HANDLE;
}
if (pResAdr->virtual == (VIRT_ADDR)PMAP_FAILED)
{
/* req: VX7-13699 */
return ERROR;
}
/* req: VX7-13696 */
pRes->id |= VXB_RES_FLAG_MAPPED;
return (OK);
}
vxbRegMap 函数调用了VXB_ARCH_IO_MAP 和VXB_ARCH_MEM_MAP 宏,
#define VXB_ARCH_IO_MAP(paddr, len) \
((VIRT_ADDR)pmapGlobalMap (paddr, len, VXB_REG_MAP_MMU_ATTR))
#define VXB_ARCH_MEM_MAP(paddr, len) \
((VIRT_ADDR)pmapGlobalMap (paddr, len, VXB_REG_MAP_MMU_ATTR))
这个pmapGlobalMap函数最终的虚实地址转换,VXB_REG_MAP_MMU_ATTR属性为关闭CACHE。这里应用程序调用pmapGlobalMap函数其实就看可以访问寄存器地址了。
debugSioBase= pmapGlobalMap (0x21C0500, 0x30, VXB_REG_MAP_MMU_ATTR);
debugSioBase[0]=0XFFF;
LOCAL VIRT_ADDR _pmapGlobalMap
(
PHYS_ADDR physAddr, /* physical address */
size_t len, /* number of bytes to map */
UINT attr /* MMU attributes */
)
{
VIRT_ADDR virtAddr;
size_t pageSize = vmPageSizeGet();
UINT mapAttr;
RTP_ID rtpId = MY_CTX_ID();
/* check if the function is being called in the kernel context. */
if (rtpId != kernelId) /* req: VX7-7157 */
{
/* req: VX7-7158 */
errno = S_adrSpaceLib_INVALID_CONTEXT;
return ((VIRT_ADDR)NONE);
}
mapAttr = attr | ADR_SPACE_OPT_RGN_KERNEL | ADR_SPACE_OPT_MAPPED |
ADR_SPACE_OPT_NOPHYSALLOC | VM_MAP_GLOBAL;
/* req: VX7-7159 */
virtAddr = adrSpacePageAlloc (0, (VIRT_ADDR)NULL, physAddr,
len / pageSize, mapAttr);
return (virtAddr);
}
pmapGlobalMap函数还可以往下继续追溯,pmapGlobalMap->adrSpacePageAlloc->adrSpacePageMap->vmPgMap->MMU_GLOBAL_PAGE_MAP->mmuArchPageMap