|
IAR MSP430 оптимизатор кода |
|
|
|
Oct 27 2010, 09:24
|

Знающий
   
Группа: Свой
Сообщений: 604
Регистрация: 5-05-06
Из: Нижегородская обл.
Пользователь №: 16 819

|
Здравтсвуйте. Ситуация такая: Есть 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. Но без него переменные оказываются в оперативной памяти. Без оптимизации не могу, т.к. уже код не умещается в памяти контроллера. Как выйти из сложившейся ситуации?
--------------------
Кризис - это не отсутствие денег, а отсутствие идей! Учитесь и никаких кризисов не будет.
|
|
|
|
|
Oct 27 2010, 11:32
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(KARLSON @ Oct 27 2010, 15:24)  Как выйти из сложившейся ситуации? Внимательно изучить документацию на компилятор. У него есть специальные директивы препроцессора по размещению переменных. Квалификатор 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.
|
|
|
|
|
Oct 27 2010, 11:54
|

Знающий
   
Группа: Свой
Сообщений: 604
Регистрация: 5-05-06
Из: Нижегородская обл.
Пользователь №: 16 819

|
Спосибо всем, особенно 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; И никаких указателей и структур не надо. Хотя кому как удобно. И обращаемся к ним прямо по именам. Это при оптимизации медиум, при более сложных не проверю, т.к. уже многое не работает при этом)))
--------------------
Кризис - это не отсутствие денег, а отсутствие идей! Учитесь и никаких кризисов не будет.
|
|
|
|
|
Oct 27 2010, 12:58
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(KARLSON @ Oct 27 2010, 15:54)  Спосибо всем, особенно rezident. Возможно я поступил по Вашему, но через ассемблер. А именно Создаётся файл info.s43
И никаких указателей и структур не надо. Хотя кому как удобно. И обращаемся к ним прямо по именам. Это при оптимизации медиум, при более сложных не проверю, т.к. уже многое не работает при этом))) А вот это, извините, совершенно через жопу, не побоюсь аллюзий. Хотя кажется, что проще. А если что-то не работает при максимальной оптимизации, надо добиваться, чтобы работало. Иначе может вылезти потом каким-нибудь боком. Когда "щас я тут чуток поменяю" выливается в неделю борьбы с чудесами на [казалось бы] уже отлаженном проекте.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Oct 27 2010, 17:16
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Mahagam @ Oct 27 2010, 19:53)  "Кстати, без слова "const" переменные во флеш не размещаются. Кто-нибудь знает почему?" ну потому что без конст - это именно переменные. а как могу переменные располагаться в ПЗУ??? Переменные имеющие статический тип объекта - глобальные или static располагаются в ОЗУ, auto (локальные) - на стеке, register - в регистрах. Но переменные имеющие квалификатор типа const совсем не обязательно должны размещаться в ПЗУ. Они могут размещаться там же, где и перечисленные. Хотя переменную const register весьма трудно себе представить
|
|
|
|
|
Oct 27 2010, 20:43
|

тут может быть ваша реклама
    
Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280

|
Цитата(KARLSON @ Oct 27 2010, 13:24)  Кстати, без слова "const" переменные во флеш не размещаются. Кто-нибудь знает почему? Для вашего же блага, чтоб вы не пробовали записать в эти переменные обычным синтаксисом, а работали с флешью как полагается в данном МК. Цитата(jorikdima @ Oct 27 2010, 16:46)  К ИАР для МСП у меня тоже есть ряд вопросов. Вечером напишу в эту же тему, если автор не против. Ну автор, видимо, не против.  Итак, есть один 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 не живется дальше? Естественно оптимизация полная по скорости. Спасибо.
|
|
|
|
|
Oct 29 2010, 18:41
|
Частый гость
 
Группа: Участник
Сообщений: 180
Регистрация: 5-04-09
Пользователь №: 47 205

|
QUOTE (jorikdima @ Oct 28 2010, 00:43)  CODE volatile REG_STRUCT* volatile registers; Что ему с R14 не живется дальше? Имхо надо стандарт (и возможно мануал на иар) читать, как там в иаровских плюсах квалификаторы ассоциируются. Может попробовать так: CODE REG_STRUCT volatile * registers; или CODE REG_STRUCT * volatile registers; Ну и третий вариант (самый корректный) CODE REG_STRUCT * registers; , а volatile прикрутить непосредственно внутри определения структуры к каждому полю.
|
|
|
|
|
Nov 5 2015, 15:07
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(KARLSON @ Oct 27 2010, 12:24)  Здравтсвуйте. Ситуация такая: Есть 3 переменные, которые необходимо разместить во FLASH памяти.
[code]#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" может вместо обращения к этой памти заменять на присвоение константы.
Сообщение отредактировал k155la3 - Nov 5 2015, 15:20
|
|
|
|
|
Dec 4 2015, 12:59
|
Частый гость
 
Группа: Участник
Сообщений: 180
Регистрация: 5-04-09
Пользователь №: 47 205

|
QUOTE (k155la3 @ Nov 5 2015, 18:07)  Эхо войны ....  #pragma location=0x1000 __root const TTestFlashStr InfoSegConst= { '1', '2', '3', '4', '5', '6' }; #pragma required=InfoSegConst Так вроде не должно самоуправничать. (по крайней мере остается в области флеш на любой оптимизации). Хотя компилятор умнее нас, и если есть слово "const" может вместо обращения к этой памти заменять на присвоение константы. Поставьте __root const volatile TTestFlashStr и будет щастье
|
|
|
|
|
Dec 4 2015, 13:32
|
Частый гость
 
Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315

|
Цитата(k155la3 @ Nov 5 2015, 18:07)  #pragma location=0x1000 __root const TTestFlashStr InfoSegConst= { '1', '2', '3', '4', '5', '6' }; #pragma required=InfoSegConst Хм. А разве pragma required не перед определением используется?
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|