реклама на сайте
подробности

 
 
> Чудеса оптимизации кода GCC-ARM
Zol'berg
сообщение May 13 2013, 10:14
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 8-05-13
Пользователь №: 76 761



Всем привет!!
1. Из инструментов при себе имею STM32F407 - Discovery, CooCox и осцилл (2ch x 100MHz).
2. Задача: захватить 16 разрядные данные с ADC (4 канала) по протоколу SPI при тактовой частоте 5MHz (CLK).
3. Решение: программная реализация протокола ввиду наличия лишь 3_ёх SPI в STM32F407 и некоторых отклонений входного потока от стандарта SPI (исходные условия), при тактовой в 168 MHz хватает впритык и только с оптимизатором -O3.
Программка выглядит так:
Код
// Соответствие функций входных линий и ножек порта:

#define        SCK 1<<4
#define        NSS 1<<5
#define        MOSI_SPI0 1<<0
#define        MOSI_SPI1 1<<1
#define        MOSI_SPI2 1<<2
#define        MOSI_SPI3 1<<3

#define        N_DATA  10        // количество данных (выборок)

uint16_t     DATA_0[N_DATA];        // Массив отсчетов для 0_го канала
uint16_t     DATA_1[N_DATA];        // Массив отсчетов для 1_го канала
uint16_t     DATA_2[N_DATA];        // Массив отсчетов для 2_го канала
uint16_t     DATA_3[N_DATA];        // Массив отсчетов для 3_го канала

uint16_t       DATA_temp[16];        // Буфера для сохранения состояний порта, (для повышения быстродействия)

uint16_t     N_Data;            // Счетчик/номер текущего отсчета в периоде захвата или выдачи данных
uint8_t        i;            // Само собой разумеется

void SSS(void)    // Ф-ия преобразования сохраненных состояний порта DATA_temp[i] в отчеты DATA_0-3[N_Data]
    {

            i=0;
            DATA_0[N_Data] = 0;
            while(i<16)
            for(i=0;i<16;i++)
            {
           if((DATA_temp[i] & MOSI_SPI0 == MOSI_SPI0) )
                DATA_0[N_Data] |= (0x8000>>i);
            i++;
            }
          i=0;
            DATA_1[N_Data] = 0;
            while(i<16)
            {
            if((DATA_temp[i] & MOSI_SPI1) == MOSI_SPI1)
                DATA_1[N_Data] |= (0x8000>>i);
            i++;
            }
            i=0;
            DATA_2[N_Data] = 0;
            while(i<16)
            {
            if((DATA_temp[i] & MOSI_SPI2) == MOSI_SPI2)
                DATA_2[N_Data] |= (0x8000>>i);
            i++;
            }
            i=0;
            DATA_3[N_Data] = 0;
            while(i<16)
            {
            if((DATA_temp[i] & MOSI_SPI3) == MOSI_SPI3)
                DATA_3[N_Data] |= (0x8000>>i);
            i++;
            }

    }

void Flag(void)    // Ф-ия "Флаг" - "контрольная точка"
    {
    GPIOD->BSRRL =(1<<14);        // set
    GPIOD->BSRRH =(1<<14);        // clr
    }

void ProgramSPI(void)    // Программная реализация SPI где D0-MOSI(SPI0)|D1-MOSI(SPI1)|D2-MOSI(SPI2)|D3-MOSI(SPI3)   D4-SCK    D5-NSS
{
    N_Data=0;
    {
    while ((GPIOD->IDR & NSS) == 0)// NSS==0 (ждем начала выполнения преобразования ADC)
        {}

    while ((GPIOD->IDR & NSS) == NSS)// NSS==1 (ждем окончания выполнения преобразования ADC)
        {}
//    Flag();
    
// Процесс захвата данных (SPI0-3):
    i=0;
    while (i<16)
        {
        while ((GPIOD->IDR & (NSS|SCK)) != SCK)    // SCK!=1|NSS==0
        {}
        Flag();
        DATA_temp[i]=GPIOD->IDR;
        Flag();
        while ((GPIOD->IDR & (NSS|SCK)) != 0)    // SCK!=0|NSS==0
        {}
        //    Flag();
        i++;
        }
SSS();

// Проверка принятых байтов:

    if((DATA_0[N_Data]!= 0xA38C) | (DATA_1[N_Data]!= 0xA38C) | (DATA_2[N_Data]!= 0xA38C) | (DATA_3[N_Data] != 0xA38C))
        {
        Flag();
        }
    N_Data++;            // Инкремент счетчика отсчетов - подготовка к следующему полуслову
    if(N_Data==N_DATA)
        return;            // Переполнение буфера данных, возврат в main()
    }
}

int main(void)                // Очень странная функция !!!;)
{
    SystemInit();
    PortD_Init();
    while(1)
    {
        ProgramSPI();
    }
}


В общем все работает, ф-ия Flag() - контрольная точка (выводит строб на порт который контролируется осциллографом), ProgramSPI() сохраняет состояние ножек порта в нужное время 16 раз, ф-ия SSS() преобразует данные, но есть одно НО, при подключении вызова ф-ии SSS() компилятор отказывается оптимизировать код в сторону быстродействия, т.е. другими словами - в случае применения где либо этих массивов, скорости не хватает и появляются ошибки чтения.
Пытался применять квалификаторы типа volatile и restrict, не помогло.
Вопрос: как заставить компилятор оптимизировать или не оптимизировать нужные мне куски кода??
Спасибо sm.gif
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 00:37
Рейтинг@Mail.ru


Страница сгенерированна за 0.01298 секунд с 7
ELECTRONIX ©2004-2016