VxWorks中高精度实时时钟的实现及C语言汇编混合编程

        最近一个项目中需要在VxWorks下使用一个高精度实时时钟,要求精度为1ms,溢 出时间大于5小时。VxWorks提供系统时钟,该时钟在操作系统启动后开始计数,精度为1个tick,可以通过tickGet()获取当前计数值。因为 系统时钟默认工作频率为60Hz,则1个tick相当于16.7ms,不符号我们的精度要求。虽然可以通过sysClkRateSet(1000),把精度提高到1ms,但1kHz的系统时钟中断频率会使得CPU的开销大增。考虑到像nanoSleep()这样的应用其计时精度可以达到纳秒级,CPU中肯定有相应的ns级的时钟提供。项目使用的硬件平台为PC104,处理器为300MHz X86兼容CPU,在VxWorks函数手册(vxworks_os_libraries_api_reference)中察看CPU相关的函数库,果然在pentiumALib.h中找到pentiumTscGet32()、pentiumTscGet64()、pentiumTscReset() 这3个API可以对CPU中内建的TSC进行操作。TSC即Time Stamp Counter,为Pentium系列CPU提供的64位时戳计数器,该计数器在CPU上电或复位后每个指令周期计数一次,Intel保证TSC的溢出周 期大于10年。像我们使用的300MHz的CPU,其TSC精度约为33ns,溢出周期约为19303年,这完全符合我们项目的要求。

       但令人faint的 是,在downloadable project中包括了pentiumALib.h这个头文件后项目竟然不能编译通过!无奈之下仔细察看手册中对TSC相关函数的说明,手册曰:这三个函数都是通过汇编实现的,要读TSC寄存器只需使用RDTSC这条指令,它会将TSC的当前值低32位放入EAX寄存器,高32位放入EDX寄存器。那我岂不只要在我的应用程序中插入这么一段汇编就可以了,关键是怎么在VxWorks下使用C语言跟汇编混合编程呢?还好以前看过一点《Linux内核源代码情景分析》,在上册的第一章中就有关于GCC中C语言汇编混合编程的介绍,而VxWorks使用的编译器正是GCC!

       那不妨就来试一试吧,于是有了下面的代码:

/*****************getTsc - Get TSC count************************************* 
获取TSC(时戳计数器)计数值,将计数器高位存入pHi,低位存入pLo** RETURNS: N/A
****************************************************************************/
void getTsc(unsigned int *pHi, unsigned int *pLo)
{ 
     unsigned int hi, lo;        
     __asm__ __volatile__("rdtsc\n movl %%eax, %0\n movl %%edx, %1":"=b"(lo),"=c"(hi)::"memory");
     *pHi = hi;
     *pLo = lo;
}
/****************getTsc - Get the lower half of TSC count*************** 
获取TSC(时戳计数器)低32位计数值** RETURNS: TSC低32位计数值
***********************************************************************/
unsigned int getTsc32(void)
{
     unsigned int tmp;        
     __asm__ __volatile__("rdtsc\n movl %%edx, %0":"=c"(tmp)::"memory");
     return tmp;
}

 

       如果使用PowerPC平台,PowerPC提供的TB(Time Base)寄存器类似于Pentium的TSC,VxALib中提供vxTimeBaseSet() 和 vxTimeBaseGet()两个函数来对TB寄存器进行读写操作。

 


我们团队有着十几年的期货程序化交易算法与软件研发经验,基于C++ Qt技术研发了具有自主知识产权的期货智能程序化交易一体化系统平台,该平台封装了二百多个量化指标,具有低时延、高性能、小滑点、可定制和跨平台的特点。团队致力于将人工智能技术与传统的程序化交易技术相结合为客户提供灵活可定制的期货智能程序化交易服务和产品。

       

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基本的 VxWorks C 语言 XDMA 断处理程序的代码示例: ```c #include <vxWorks.h> #include <vxLib.h> #include <vxInterruptLib.h> #include <vxMemLib.h> #include <vxStdio.h> #include <vxIpiLib.h> #include <vmLib.h> #include <vxbFdtDev.h> #define DMA_IRQ_NUM 5 LOCAL int dmaCh = 0; // DMA channel LOCAL BOOL dmaDone = FALSE; // DMA done flag LOCAL VOID dmaHandler(int irqNum) { if (dmaCh == irqNum) { dmaDone = TRUE; // Set DMA done flag } } int dmaSetup(UINT32 *srcAddr, UINT32 *dstAddr, UINT32 len) { int status; // Map source and destination addresses char *mappedSrc = (char *)vxMemProbe((char *)srcAddr, VX_READ, sizeof(UINT32)); char *mappedDst = (char *)vxMemProbe((char *)dstAddr, VX_WRITE, sizeof(UINT32)); if (mappedSrc == NULL || mappedDst == NULL) { return ERROR; } // Set up DMA transfer status = dmaSetupTransfer(dmaCh, srcAddr, dstAddr, len, DMA_MODE); if (status != OK) { return status; } // Enable DMA channel status = dmaEnable(dmaCh); if (status != OK) { return status; } // Wait for DMA completion while (!dmaDone) { taskDelay(1); } // Disable DMA channel status = dmaDisable(dmaCh); if (status != OK) { return status; } return OK; } void dmaInit(void) { // Install DMA interrupt handler if (intConnect(INUM_TO_IVEC(DMA_IRQ_NUM), (VOIDFUNCPTR)dmaHandler, dmaCh) == ERROR) { printf("Failed to install DMA interrupt handler\n"); return; } // Enable DMA interrupt if (intEnable(DMA_IRQ_NUM) == ERROR) { printf("Failed to enable DMA interrupt\n"); return; } // Initialize DMA controller if (dmaInitController() == ERROR) { printf("Failed to initialize DMA controller\n"); return; } // Set up DMA channel dmaCh = dmaAllocChannel(DMA_CONTROLLER, DMA_DIRECTION); if (dmaCh == ERROR) { printf("Failed to allocate DMA channel\n"); return; } } ``` 此代码示例,`dmaInit()` 函数初始化 DMA 控制器并分配 DMA 通道。在 `dmaSetup()` 函数,使用 `dmaSetupTransfer()` 函数设置 DMA 传输并启用 DMA 通道。在 DMA 传输完成后,`dmaHandler()` 函数被调用,将 `dmaDone` 标志设置为 TRUE。在主程序,可以使用 `dmaSetup()` 函数来启动 DMA 传输,并等待传输完成。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值