复制数据花费太多时间 [英] Too much time taking for the copy the data

查看:42
本文介绍了复制数据花费太多时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 for 循环副本的时间有一些问题我不明白为什么 for 循环要花费很多时间来复制小数据大小.我正在使用 PIC24FJ256GL406 MCU,一切正常,但是在操作 UART 微控制器时运行缓慢,因为复制缓冲区数据时发生了一些延迟.让我用代码和调试日志为您解释.

I have a some problem with for loop copies' time I don't why for loop is taking much time for the copy small data size. I am using PIC24FJ256GL406 MCU and everything is fine but when operate the UART micro-controller is running slow because some delay is occurring while copy the buffer data. Let me explain you with code and debug log.

这里我发布了 UART 传输的函数.该函数一般只传输第一个字符,其余字节将在中断例程服务中传输.

Here I am posting the function for the UART transmission. this function is generally transfer only FIRST character and Rest of the byte will be transfer in the Interrupt routine service.

我的时钟频率是 32Mhz,所以外设是 16Mhz.

My clock Frequency is 32Mhz So peripheral will be 16 Mhz.

我不明白为什么 for 循环只复制 16 字节数据需要将近 20 毫秒.所以如果数据更多,这个时间会增加.

I did not understand why for loop is taking Almost 20 MS for the copy the 16 byte data only. So This time will be increase if data is more.

unsigned int UART1_WriteBuffer(const uint8_t *buffer, const unsigned int bufLen)
{
    //transmit first char

    U1TXREG = buffer[0];

    while (!U1STAbits.TRMT);

    numBytesWritten = bufLen - 1;

    totalByte = 0;

    //get the current time stamp
    WSTimestamp currentTimeStamp = WSGetCurrTimestamp();

    WMLogInfo(GEN_LOG, "current time stamp %ld", currentTimeStamp);

    uint16_t i = 0;

    //memset
    memset(&uart1_txByteQ, 0x00, sizeof(uart1_txByteQ));
    
    for (i = 0; i < numBytesWritten; i++)
    {
        uart1_txByteQ = buffer[i + 1]; //copy the data
    }
    
    _U1TXIE = 1;

    //get last time stamp
    WSTimestamp lastTimeStamp = WSGetCurrTimestamp();

    WMLogInfo(GEN_LOG, "last time stamp %ld ", lastTimeStamp);
     
    ///print the debug
    WMLogInfo(GEN_LOG, "total = %ld MS time taken fo copy the = %d byte", lastTimeStamp - currentTimeStamp, numBytesWritten);

    return bufLen;

}

My Interrupt Routine service.

void __attribute__((interrupt, no_auto_psv)) _U1TXInterrupt(void)
{
    if (totalByte < numBytesWritten)
    {
        U1TXREG = uart1_txByteQ[totalByte++];

        while (!U1STAbits.TRMT);
    }
    else
    {
        _U1TXIE = 0;
        _U1TXIE = 0;
    }

}
 
Console Log.
This is function log. please note.

GEN:main loop current time stamp 6503<\r><\n>
GEN:current time stamp 6506<\r><\n>
GEN:last time stamp 6526 <\r><\n>
GEN:total = 20 MS time taken fo copy the = 16 byte<\r><\n>
GEN:command "AT+QREFUSECS=1,1<\r>" send with len [17]

推荐答案

长时间的延迟是由于忙于等待标志以及一些用例错误导致的.如果您打算忙等待轮询标志,为什么首先要使用 Tx 中断?ISR 没有意义 - 您似乎应该完全放弃 Tx 中断.

The long delays are caused by busy-waiting for flags in combination with some use-case bug. Why are you using Tx interrupt in the first place in case you intend to busy-wait poll for a flag anyhow? The ISR doesn't make sense - it would seem that you should simply drop Tx interrupts entirely.

此外,您有一个简单的缓冲区副本实现.不必要地硬拷贝RAM缓冲区是一个非常常见的嵌入式系统初学者错误.在极少数情况下您实际上需要进行硬拷贝,而这不是一种.相反,您应该使用具有双缓冲区的系统并简单地在它们之间交换一个指针:

In addition, you have a naive implementation of buffer copies. It's a very common embedded systems beginner bug to hard copy RAM buffers needlessly. There's very few cases where you actually need to do hard copies and this isn't one. Instead you should use a system with double buffers and simply swap a pointer between them:

static uint8_t buf1 [n];
static uint8_t buf2 [n];
static uint8_t* rx_buf = buf1;   // buffer used by rx ISR
static uint8_t* app_buf = buf2;  // buffer used by the application

...

if(rx_done)
{ // swap buffers
  uint8_t* tmp = rx_buf;
  rx_buf = app_buf;
  app_buf = tmp;
}

这也解决了双缓冲问题,即 UART 接收中断需要在主程序使用数据的同时将其传入数据存储在某处.您需要以某种方式防止竞争条件 - 使用信号量等.并且您需要声明与 ISR volatile 共享的变量,以防止错误的编译器优化器.

This also solves the double-buffering problem where an UART rx interrupt needs to store it's incoming data somewhere at the same time as the main program uses data. You'll need to protect against race conditions somehow - with a semaphore etc. And you'll need to declare variables shared with ISRs volatile to protect against bad compiler optimizers.

这篇关于复制数据花费太多时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆