Jump to content

    

IAR MSP430 оптимизатор кода

Здравтсвуйте.

Ситуация такая:

Есть 3 переменные, которые необходимо разместить во FLASH памяти.

 

#pragma memory = constseg(INFOD)      // адреса 1000-103F
const volatile signed char nst
            min_ust = 19, // 3 установленное по умолчанию отрицательное значение
            max_ust = 25, // 4 установленное по умолчанию положительное знание
            config = 1;

 

Кстати, без слова "const" переменные во флеш не размещаются. Кто-нибудь знает почему?

 

Эти переменные изменяются пользователем путём стирания и записывания флеш памяти. Значения меняются точно.

Далее

есть кусок кода:

 

if ((DATA.temperatura > max_ust) || (DATA.temperatura < min_ust)) // если температура вышла из диаппазона    
           {
              // делаем то-то
           }
           else // если норма
           {
              // делаем другое
           }

 

Без оптимизации в настройках компилятора всё нормально, но стоит включить оптимизацию, то в условии в место max_ust и min_ust компилятор ставит 25 и 19 соответственно. Вся загвоздка скорее всего в ключевом слове const. Но без него переменные оказываются в оперативной памяти.

Без оптимизации не могу, т.к. уже код не умещается в памяти контроллера.

 

Как выйти из сложившейся ситуации?

Share this post


Link to post
Share on other sites
Как выйти из сложившейся ситуации?

Свести все данные в структуру и разместить её во флеше.

Мне однажды помогло :)

Вообще, ИАР иногда выкидывает коленца...

Share this post


Link to post
Share on other sites

Да имеется такое в IAR я решаю эту проблему путем введения указателей на const и все операции делаю с указателями

Share this post


Link to post
Share on other sites
Как выйти из сложившейся ситуации?
Внимательно изучить документацию на компилятор. У него есть специальные директивы препроцессора по размещению переменных. Квалификатор const к размещению переменных во Flash имеет лишь косвенное отношение.

Если вас устроит способ сделать "втупую", то я практиковал такой финт.

 

Создаем структуру констант

typedef struct InfoSeg_t
{ float a; 
  unsigned int b;
  unsigned int c;
  char d;
  char e;
} InfoSeg_t;

Объявляем константную структуру, инициализируем ее явными значениями и явно задаем адрес размещения

#pragma location=0x1000
const InfoSeg_t InfoSegConst=
{ 1.0f,
  0x1234,
  5678,
  0x0A,
  0x0D
};
#pragma required=InfoSegConst

Вторая прагма нужна для того, чтобы компилятор не выкинул эту структуру в процессе оптимизации.

 

Объявляем еще одну структуру, но неинициализированную, расположенную по тому же адресу, что и первая.

#pragma location=0x1000
__no_init InfoSeg_t InfoSeg;

Далее в программе везде работаем именно со структурой InfoSeg. Поскольку она не инициализирована явными значениями, то компилятор подстановку этих значений не делает, а каждый раз обращается к элементам данной структуры.

При компиляции конечно же выдается Warning, но я на него чихаю потому, что понимаю причину по которой он возникает.

Можно использовать и другие директивы #pragma, которые влияют на размещение переменных. Эта прагма еще из старых версий IAR.

Share this post


Link to post
Share on other sites

Спосибо всем, особенно rezident. Возможно я поступил по Вашему, но через ассемблер. А именно

Создаётся файл info.s43

 

public max_ust, min_ust, config, count_clear
ASEG 0x1000
max_ust DB 25
min_ust DB 19
config DB 1
count_clear DB 0
end

 

А до майна у меня вот что:

 

extern signed char  max_ust, min_ust, config;
extern unsigned char count_clear;

 

И никаких указателей и структур не надо. Хотя кому как удобно. И обращаемся к ним прямо по именам. Это при оптимизации медиум, при более сложных не проверю, т.к. уже многое не работает при этом)))

Share this post


Link to post
Share on other sites

Улыбает конечно смотреть на название переменных, написанных латиницей :) DATA.temperatura :) Ну назовите вы DATA.temperature

А по теме, да, на мой взгляд тоже работать тут надо через константные указатели. Странно что компайлер не принимает во внимание тут volatile, пусть и совместно с const.

К ИАР для МСП у меня тоже есть ряд вопросов. Вечером напишу в эту же тему, если автор не против.

Share this post


Link to post
Share on other sites
Спосибо всем, особенно rezident. Возможно я поступил по Вашему, но через ассемблер. А именно

Создаётся файл info.s43

 

И никаких указателей и структур не надо. Хотя кому как удобно. И обращаемся к ним прямо по именам. Это при оптимизации медиум, при более сложных не проверю, т.к. уже многое не работает при этом)))

А вот это, извините, совершенно через жопу, не побоюсь аллюзий.

Хотя кажется, что проще.

 

А если что-то не работает при максимальной оптимизации, надо добиваться, чтобы работало.

Иначе может вылезти потом каким-нибудь боком.

Когда "щас я тут чуток поменяю" выливается в неделю борьбы с чудесами на [казалось бы] уже отлаженном проекте.

Share this post


Link to post
Share on other sites

никаких чудес. простая логика.

 

"Кстати, без слова "const" переменные во флеш не размещаются. Кто-нибудь знает почему?"

ну потому что без конст - это именно переменные. а как могу переменные располагаться в ПЗУ???

 

но стоит включить оптимизацию, то в условии в место max_ust и min_ust компилятор ставит 25 и 19 соответственно.

ещё бы. он не дурак, он видит, что при инициализации туда вписали 25 и 19, а потом ни разу нигде по ходу программы прямо не изменяли - он справедливо считает что там 25 и 19. и что нефик их оттуда вычитывать, что можно подставить банальные константы.

 

весь вопрос как грамотно обмануть компилятор.

Share this post


Link to post
Share on other sites
"Кстати, без слова "const" переменные во флеш не размещаются. Кто-нибудь знает почему?"

ну потому что без конст - это именно переменные. а как могу переменные располагаться в ПЗУ???

Переменные имеющие статический тип объекта - глобальные или static располагаются в ОЗУ, auto (локальные) - на стеке, register - в регистрах. Но переменные имеющие квалификатор типа const совсем не обязательно должны размещаться в ПЗУ. Они могут размещаться там же, где и перечисленные. Хотя переменную const register весьма трудно себе представить :)

 

Share this post


Link to post
Share on other sites
Кстати, без слова "const" переменные во флеш не размещаются. Кто-нибудь знает почему?

Для вашего же блага, чтоб вы не пробовали записать в эти переменные обычным синтаксисом, а работали с флешью как полагается в данном МК.

 

К ИАР для МСП у меня тоже есть ряд вопросов. Вечером напишу в эту же тему, если автор не против.

Ну автор, видимо, не против. :)

Итак, есть один cpp модуль и h файл к нему:

main.cpp

#include "io430.h"
#include "b.h"

A a;
B bb;


A::A()
{
    b = &bb;
}


void main()
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;

  a.b->f();
  a.b->f();
  a.b->f();
}

b.h

#include "io430.h"

class B
{
    typedef  unsigned char UINT8;
    typedef  unsigned short UINT16;
    typedef struct 
    {
        UINT8 UCCTL1;
        UINT8 UCCTL0;
        UINT16 UCRES[2];
        UINT16 UCBR;
        UINT8 UCMCTL;
        UINT8 UCRES1;
        UINT8 UCSTAT;
        UINT8 UCRES2;
        UINT8 UCRXBUF;
        UINT8 UCRES3;
        UINT8 UCTXBUF;
        UINT8 UCRES4;
        UINT8 UCABCTL;
        UINT8 UCRES5;
        UINT16 UCIRCTL; 
        UINT16 UCRES6[4];
        UINT8 UCIE;
        UINT8 UCIFG;
        UINT8 UCIV;
    } REG_STRUCT;
    
    volatile REG_STRUCT* registers;
    
public:
_Pragma("inline=forced")
     void f() {
        volatile REG_STRUCT* const regs = registers;
        while (!(regs->UCIFG & UCTXIFG));    // wait while not ready / for RX
        regs->UCTXBUF = 0xFF;                // write
        while (!(regs->UCIFG & UCRXIFG));    // wait for RX buffer (full)
        volatile UINT8 dummy = regs->UCRXBUF;
    }
    

};



class A
{
public:
    B* b;
    A();

};


extern A a;
extern B bb;

Просьба не обращать внимание на цель кода, код выдернут из рабочего проекта, возможно для демонстрации моего вопроса можно было бы и еще укоротить код. Изначально это был класс-обертка для UART, но не суть.

Есть класс B который имеет важно инлайновый метод f(), есть класс A, который имеет в себе поле-указатель на объект типа B.

 

В main() я трижды подряд вызываю функцию f(), которую компайлер по моей просьбе инлайнит.

Листинг выглядит так:

        volatile REG_STRUCT* const regs = registers;
005C38    421F 1C00          mov.w   &a,R15                                               ЭТО ПОНЯТНО
005C3C    4F2F               mov.w   @R15,R15
        while (!(regs->UCIFG & UCTXIFG));    // wait while not ready / for RX
005C3E    B3EF 001D          bit.b   #0x2,0x1D(R15)
005C42    2BFD               jnc     0x5C3E
        regs->UCTXBUF = 0xFF;                // write
005C44    43FF 000E          mov.b   #0xFF,0xE(R15)
        while (!(regs->UCIFG & UCRXIFG));    // wait for RX buffer (full)
005C48    B3DF 001D          bit.b   #0x1,0x1D(R15)
005C4C    2BFD               jnc     0x5C48
        volatile UINT8 dummy = regs->UCRXBUF;
005C4E    4FD1 000C 0000     mov.b   0xC(R15),0x0(SP)
        volatile REG_STRUCT* const regs = registers;
005C54    421F 1C00          mov.w   &a,R15                                                НО ЗАЧЕМ ОПЯТЬ?
005C58    4F2F               mov.w   @R15,R15
        while (!(regs->UCIFG & UCTXIFG));    // wait while not ready / for RX
005C5A    B3EF 001D          bit.b   #0x2,0x1D(R15)
005C5E    2BFD               jnc     0x5C5A
        regs->UCTXBUF = 0xFF;                // write
005C60    43FF 000E          mov.b   #0xFF,0xE(R15)
        while (!(regs->UCIFG & UCRXIFG));    // wait for RX buffer (full)
005C64    B3DF 001D          bit.b   #0x1,0x1D(R15)
005C68    2BFD               jnc     0x5C64
        volatile UINT8 dummy = regs->UCRXBUF;
005C6A    4FD1 000C 0000     mov.b   0xC(R15),0x0(SP)
        volatile REG_STRUCT* const regs = registers;
005C70    421F 1C00          mov.w   &a,R15
005C74    4F2F               mov.w   @R15,R15

В начале он определяет адрес начала структуры registers и кладет ее в R15. Затем этим адресом активно пользуется. Но зачем он при каждом вызове f() делает это??? Ведь встраивая функцию компайлер прекрасно видит, что с этим регистром ничего не происходит между вызовами ф-ций.

Второй вопрос. Модифицируем f() так:

_Pragma("inline=forced")
     void f() {
        //volatile REG_STRUCT* const regs = registers;
        while (!(registers->UCIFG & UCTXIFG));    // wait while not ready / for RX
        registers->UCTXBUF = 0xFF;                // write
        while (!(registers->UCIFG & UCRXIFG));    // wait for RX buffer (full)
        volatile UINT8 dummy = registers->UCRXBUF;
    }

Листинг такой () кусок только f():

  a.b->f();
005C38    421F 1C00          mov.w   &a,R15
     void f() {
005C3C    4F2E               mov.w   @R15,R14
        while (!(registers->UCIFG & UCTXIFG));    // wait while not ready / for RX
005C3E    B3EE 001D          bit.b   #0x2,0x1D(R14)
005C42    2BFD               jnc     0x5C3E
        registers->UCTXBUF = 0xFF;                // write
005C44    43FE 000E          mov.b   #0xFF,0xE(R14)
005C48    4F2F               mov.w   @R15,R15                                                          ЗАЧЕМ?
        while (!(registers->UCIFG & UCRXIFG));    // wait for RX buffer (full)
005C4A    B3DF 001D          bit.b   #0x1,0x1D(R15)
005C4E    2BFD               jnc     0x5C4A
        volatile UINT8 dummy = registers->UCRXBUF;
005C50    4FD1 000C 0000     mov.b   0xC(R15),0x0(SP)

Зачем он при проверке флага на прием опять пытается определить начало структуры registers? Ведь в R14 этот адрес уже есть, почему он требует константного указателя? Ведь код линеен и сам указатель registers не объявлен как

    volatile REG_STRUCT* volatile registers;

Что ему с R14 не живется дальше?

Естественно оптимизация полная по скорости.

Спасибо.

Share this post


Link to post
Share on other sites
    volatile REG_STRUCT* volatile registers;

Что ему с R14 не живется дальше?

Имхо надо стандарт (и возможно мануал на иар) читать, как там в иаровских плюсах квалификаторы ассоциируются. Может попробовать так:

 REG_STRUCT volatile * registers;

или

 REG_STRUCT * volatile registers;

Ну и третий вариант (самый корректный)

 REG_STRUCT * registers;

, а volatile прикрутить непосредственно внутри определения структуры к каждому полю.

Share this post


Link to post
Share on other sites
Здравтсвуйте.

Ситуация такая:

Есть 3 переменные, которые необходимо разместить во FLASH памяти.

 

#pragma memory = constseg(INFOD)	  // адреса 1000-103F

 

. . . . . . . . .

. . . . . . . . .

Без оптимизации в настройках компилятора всё нормально, но стоит включить оптимизацию, то в условии в место max_ust и min_ust компилятор ставит 25 и 19 соответственно. Вся загвоздка скорее всего в ключевом слове const. Но без него переменные оказываются в оперативной памяти.

Без оптимизации не могу, т.к. уже код не умещается в памяти контроллера.

 

Как выйти из сложившейся ситуации?

 

Эхо войны .... :)

 

#pragma location=0x1000

__root const TTestFlashStr InfoSegConst=

{ '1',

'2',

'3',

'4',

'5',

'6'

};

#pragma required=InfoSegConst

 

Так вроде не должно самоуправничать.

(по крайней мере остается в области флеш на любой оптимизации).

Хотя компилятор умнее нас, и если есть слово "const" может вместо обращения к этой памти заменять на присвоение константы.

 

Edited by k155la3

Share this post


Link to post
Share on other sites
Эхо войны .... :)

 

#pragma location=0x1000

__root const TTestFlashStr InfoSegConst=

{ '1',

'2',

'3',

'4',

'5',

'6'

};

#pragma required=InfoSegConst

 

Так вроде не должно самоуправничать.

(по крайней мере остается в области флеш на любой оптимизации).

Хотя компилятор умнее нас, и если есть слово "const" может вместо обращения к этой памти заменять на присвоение константы.

Поставьте __root const volatile TTestFlashStr и будет щастье

Share this post


Link to post
Share on other sites
#pragma location=0x1000

__root const TTestFlashStr InfoSegConst=

{ '1',

'2',

'3',

'4',

'5',

'6'

};

#pragma required=InfoSegConst

Хм. А разве pragma required не перед определением используется?

Share this post


Link to post
Share on other sites
Хм. А разве pragma required не перед определением используется?

перед! только не перед тем которое где то требуется!

А перед тем которое требует.

 

т.е. если B для работы нужно А - перед B должна стоять прагма - требуется A

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this