首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >编译器优化如何加快简单操作之间的时间?

编译器优化如何加快简单操作之间的时间?
EN

Stack Overflow用户
提问于 2014-09-22 13:22:31
回答 1查看 176关注 0票数 0

我有一个使用SPI的嵌入式C++项目。当我编译和运行我的程序没有优化(-O0),外围设备(一个液晶面板)工作良好。当我用优化(-O1)一起编译它时,外围设备不能正常工作。

我用逻辑分析器检查了这两种情况,唯一的区别是,用优化的代码(时钟速率、写入的字节等)编写的字节之间的时间要短得多。编译器优化如何能够影响后续操作之间的时间,这些操作只是一个接一个地写入硬件寄存器?如果我在SPI类中的每个写命令之后添加一个延迟,那么它在优化的情况下工作。

与下面的示例不同,在原始代码中,对WriteCommand()WriteData()的调用是通过指针进行的。

代码片段,通过SPI连续写入外围设备:

代码语言:javascript
复制
{
    SPI m_spiPort();
    m_spiPort.Init();

    m_spiPort.WriteCommand(SLEEPOUT);

    // Color Interface Pixel Format (command 0x3A)
    m_spiPort.WriteCommand(COLMOD);
    m_spiPort.WriteData(0x03); // 0x03 = 12 bits-per-pixel

    // Memory access controller (command 0x36)
    m_spiPort.WriteCommand(MADCTL);
    m_spiPort.WriteData(0x00);

    // Write contrast (command 0x25)
    m_spiPort.WriteCommand(SETCON);
    m_spiPort.WriteData(0x39); // contrast 0x30

    // Display On (command 0x29)
    m_spiPort.WriteCommand(DISPON);

}

SPI课程:

代码语言:javascript
复制
class SPI {
public:
    void Init();
    void WriteCommand(unsigned int command);
    void WriteData(unsigned int data);
private:
    void Write(unsigned int value);
};

这个类的实现是:

代码语言:javascript
复制
void SPI::WriteCommand(unsigned int command)
{
    command &= ~0x100;   //clear bit 8
    Write(command);
}

void SPI::WriteData(unsigned int data)
{
    data |= 0x100;   //set bit 8
    Write(data);
}

void SPI::Write(unsigned int value)
{
    LPC_SSP->DR = value;
}
void SPI::Init( void )
{
  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<11);  //Enables clock for SPI
  LPC_SYSCON->SSPCLKDIV = 0x01;

  LPC_IOCON->PIO0_14 &= ~(0x7); // SCK
  LPC_IOCON->PIO0_14 |= 0x2;

  LPC_IOCON->PIO0_17 &= ~(0x7); // MOSI
  LPC_IOCON->PIO0_17 |= 0x2;

  /* SSP SSEL is a GPIO pin */
  LPC_IOCON->PIO0_27 = 0x0;     // configure as GPIO pin
  LPC_GPIO0->MASK = (1<<27);
  LPC_GPIO0->DIR |= (1<<27);    // set in output mode */
  LPC_GPIO0->CLR = 1 << 27;

  /* Set DSS data to 9-bit, Frame format SPI, CPOL = 0, CPHA = 0, and SCR is 0 */
  LPC_SSP->CR0 = 0x0008;

  /* SSPCPSR clock prescale register, master mode, minimum divisor is 0x02 */
  LPC_SSP->CPSR = 0x4;  // SPI clock will run at 6 MHz

  /* set Master mode and enable the SPI */
  LPC_SSP->CR1 = 0x2;
}

编辑-从SPI::Write()中删除DelayInCycles()。如果没有它,差异仍然很明显,我并不打算把它包括在这篇文章中。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-09-22 14:18:30

对于每个命令和数据字节,代码调用两个函数,这两个函数都没有局部变量或许多临时变量。

当忠实地实现这些函数时,每个函数都将创建一个堆栈框架(安装和拆卸需要几个指令),以存储无法保存在寄存器中的任何局部变量和临时变量。这可能是在-O0编译模式下发生的情况。

影响此类代码执行时间的两个重要优化是:

  • 堆栈帧省略:编译器注意到Write (可能还有WriteCommandWriteData)的堆栈框架未使用,因此决定取消设置(和拆下)堆栈帧的指令。
  • 函数内联:由于WriteWriteCommandWriteData都是非常简单的函数,编译器可以决定完全消除函数调用,并生成代码,就像编写了代码一样(不考虑任何可访问性问题): { SPI m_spiPort();m_spiPort.Init();m_spiportt.lpc_SSP->DR= (SLEEPOUT & ~0x100);//彩色接口象素格式(命令0x3A) m_spportt.lpc_SSP->DR= (COLMOD & ~0x100);m_spirt.lpc_SSP->DR= (0x03 & 0x100);//内存访问控制器(命令0x36) m_spirt.lpc_SSP->DR= (MADCTL & ~0x100);M_spportt.lpc_SSP->DR= (0x00 & 0x100);//写对比度(命令0x25) m_spportt.lpc_SSP->DR= (SETCON & ~0x100);m_spirt.lpc_SSP->DR= (0x39 & 0x100);// Display On (命令0x29) m_port.LPC_SSP->DR= (DISPON & ~0x100);}};

这两种优化都消除了对寄存器的实际写入之间的大量(簿记)指令,从而使写入速度更快。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25975249

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档