2014-09-22 4 views
0

SPI를 사용하는 임베디드 C++ 프로젝트가 있습니다. 최적화없이 프로그램을 컴파일하고 실행할 때 (-O0) 주변 장치 (LCD 패널)가 정상적으로 작동합니다. 컴파일 할 때 최적화 (-O1)로 설정하면 주변 장치가 올바르게 작동하지 않습니다.컴파일러 최적화는 간단한 작업 사이의 시간을 어떻게 단축합니까?

로직 애널라이저를 사용하여 두 경우를 모두 검사했는데, 유일한 차이점은 최적화 된 코드 (클록 속도, 작성된 바이트 등은 동일 함)로 작성되는 바이트 간 시간이 훨씬 짧다는 점입니다. 컴파일러 최적화는 하드웨어 레지스터에 순차적으로 쓰는 후속 작업 사이의 시간에 어떤 영향을 미칠 수 있습니까? SPI 클래스의 각 쓰기 명령 이후에 지연을 추가하면 최적화 된 경우에 작동합니다.

아래 샘플과 달리 원래 코드에서 WriteCommand()WriteData()에 대한 호출은 포인터를 통해 발생합니다.

코드, 연속 쓰기는 SPI를 통해 주변 장치 :

{ 
    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 클래스 :

class SPI { 
public: 
    void Init(); 
    void WriteCommand(unsigned int command); 
    void WriteData(unsigned int data); 
private: 
    void Write(unsigned int value); 
}; 

이 클래스의 구현입니다 :

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()가 제거되었습니다. 그 차이는 여전히 그것 없이는 분명하고 나는이 게시물에 그것을 포함하는 것을 의미하지는 않습니다.

+0

어떤 대상에서 어떤 컴파일러를 사용합니까? 최적화는 종종 실행 시간을 가속화합니다 .... –

+0

'gcc -fverbose-asm -S'를 사용하여 최적화 여부에 따라 컴파일하고 생성 된 어셈블러 코드를 비교합니다. –

+5

최적화 된 코드가 더 빨리 실행되는 이유는 무엇입니까? 이것이 최적화의 핵심입니다. –

답변

3

각 명령 및 데이터 바이트에 대해 코드는 두 개의 함수를 호출하며 두 함수에는 지역 변수 또는 많은 임시 변수가 없습니다.

충실히 구현되면 각 함수는 레지스터에 보관할 수없는 모든 로컬 변수와 임시 변수를 저장하기 위해 스택 프레임을 만듭니다 (설정 및 분해에 대한 몇 가지 지침이 있음). 이것은 아마도 -O0 컴파일 모드에서 발생합니다. 이러한 코드의 실행 시간에 영향을 미칠 수

두 가지 중요한 최적화는 다음과 같습니다

  • 스택 프레임 누락 : (아마도 또한 WriteCommandWriteData과) Write에 대한 스택 프레임이 사용되지 않고 결정 컴파일러 고지 스택 프레임 설정 (및 분리) 지시 사항을 제거하십시오.
  • 기능 인라인 : Write, WriteCommandWriteData 모든 매우 간체 기능은, 컴파일러는 당신이 쓴 것처럼 (어떤 접근성 문제를 무시하고) 모두 함수 호출을 제거하고 코드를 생성하도록 결정할 수 있습니다 :

    { 
        SPI m_spiPort(); 
        m_spiPort.Init(); 
    
        m_spiPort.LPC_SSP->DR = (SLEEPOUT & ~0x100); 
    
        // Color Interface Pixel Format (command 0x3A) 
        m_spiPort.LPC_SSP->DR = (COLMOD & ~0x100); 
        m_spiPort.LPC_SSP->DR = (0x03 & 0x100); 
    
        // Memory access controller (command 0x36) 
        m_spiPort.LPC_SSP->DR = (MADCTL & ~0x100); 
        m_spiPort.LPC_SSP->DR = (0x00 & 0x100); 
    
        // Write contrast (command 0x25) 
        m_spiPort.LPC_SSP->DR = (SETCON & ~0x100); 
        m_spiPort.LPC_SSP->DR = (0x39 & 0x100); 
    
        // Display On (command 0x29) 
        m_spiPort.LPC_SSP->DR = (DISPON & ~0x100); 
    } 
    

두 가지 최적화를 모두 사용하면 레지스터에 대한 실제 쓰기 사이에 여러 가지 (부기) 명령어가 제거되고 쓰기가 서로 빨리 수행됩니다.