const
Участник-
Постов
65 -
Зарегистрирован
-
Посещение
Весь контент const
-
подскажите, что прописать в .icf я пробую так place at address mem:__ICFEDIT_region_FLASH_start__+0x20 { readonly section .checksum }; выдает ошибку Error[Lp015]: section placement failure: overcommitted content in [0x800'0000-0x800'001f]
-
Вы кладете в восьмое прерывание отсчитывая с нуля? То есть КС будет тут? __vector_table DCD sfe(CSTACK) DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler DCD BusFault_Handler ; Bus Fault Handler DCD UsageFault_Handler ; Usage Fault Handler DCD 0 ; Reserved DCD 0 ; Reserved /* ТУТ */ DCD 0 ; Reserved DCD 0 ; Reserved DCD SVC_Handler ; SVCall Handler DCD DebugMon_Handler ; Debug Monitor Handler DCD 0 ; Reserved DCD PendSV_Handler ; PendSV Handler DCD SysTick_Handler ; SysTick Handler
-
И с КС прошивки вопрос решил. Считаю как jcxz - "с разрывом". Только куда ложить КС линкеру не говорю (сморю куда положил так: &__checksum). Он ее по разному ложит при изменении исходника, но это уже не проблема, как и хотел, диапазон задаю только в одном месте - на вкладке линкера Checksum.
-
Я так и не понял, вы ее сами располагаете или линкер без указаний ее туда ложит? Мой, если без указаний, ложит сюда: .checksum const 0x800'38e8 4 0x4 Place holder __checksum похоже, что это далеко за таблицей векторов.
-
Потратил время, разобрался. Вопрос отпал. Как понимаю, считая КС вашим способом нет разницы по какому адресу лежит подсчитанная линкером КС. Какой смысл ее помещать в таблицу векторов? Покажите как это выглядит в линкере и как передать адрес расположения размера прошивки (в прошивке) в программу, пожалуйста. И как положить КС в конец прошивки.
-
патч у вас автоматом запускается после компиляции?
-
1) Как я уже писал, считаю КС от 0х0 до 0хFFFB (КС по 0хFFFС). Если не указывать где располагать КС у меня ее кидает куда попало (в диапазоне от 0х0 до 0хFFFB). Как при этом быть с программным подсчетом, пропускать тот адрес где лежит КС в алгоритме? Или считать с ним и должен в итоге получиться "ноль". Если я считаю программно КС от 0х0 до 0хFFFF (КС по 0хFFFС) "нуля" не получаю. 2) В самой таблице векторов или сразу после? Если в самой таблице, то место какого то прерывания неиспользуемого? У вас считается вся доступная флешь с таблицей прерываний (какой диапазон адресов, для примера)? При программном подсчете КС вы результат сверяете с подсчетом линкера или у вас на выходе "ноль" когда все ОК? Читал. С лету не вышло разобраться. Ваш пример почти весь понятен (мне подходит), разбираюсь пока. Понимаю, поэтому тут с вопросами.
-
IAR 9.50.1.69506 Приветствую. Помогите разобраться. 1. Вопрос первый а) Считаю КС способом как на скрине. б) В линкере есть такие строки для размещения КС по определенному адресу: define symbol __addr_calc_cs_end__ = 0x0800FFFB; place at address mem:__addr_calc_cs_end__ +1 { readonly section .checksum }; в) В исходнике используя константы линкера __checksum_begin, __checksum_end, __checksum счтитаю и сверяю КС (в файле .icf они не видны). Могу ли я "расширить область видимости" __checksum_end для файла линкера .icf, что бы адресс 0x0800FFFB не прописывать два раза (во вкладке Checksum и файле .icf)? 2. Вопрос второй Можно ли передать глобальную константу в inline asm, что бы вместо MOV R0, #0x20000000 было MOV R0, RAM_START? asm ( "MOV R0, #0x20000000 \n" "ADD R4, R0, #0x4000 \n" "ADD R0, R0, #0x000C \n" ... сейчас делаю это так: void r0_r1_r2(int r0, int r1, int r2) { asm ("nop"); }, после вызова ф-ции значения ее входных параметров оказываются в соответствующих регистрах, а потом уже мой inline asm учитывает это. Только не уверен, что это надежно. Понимаю, что "костыль".
-
@Arlleex Есть такое, не обратил внимания. С "Multi-file Compilation" компилируется. Листинг тот же. Ничего не выкидывает даже когда забираю обращения к портам. При дополнительном выборе "Discard Unused Publics" - не компилируется вообще - ошибка.
-
а как это включаеся в ИАР. Понятия не имею, что такое LTO.
-
Если я не ошибаюсь, в С++ глобальные переменные по умолчанию static, если не указано иного (extern напр.), может в этом дело. Тогда действительно, компилятор видит, что в данной единице компиляции объект не используется и выкидывает его.
-
вот так https://electronix.ru/forum/topic/192075-pri-maksimalnoy-optimizatsii-oshibka/?do=findComment&comment=1944224
-
после добавления роботы с портами у вас "пустой зацикленный код" остался? Или все же не пустой цикл?
-
в моем примере только такие файлы: 1. startup_stm32f4xx.s 2. system_stm32f4xx.c 3. main.c (весь код которого приведен) 4. foo.c (с одной лишь ф-цей foo)
-
extern void foo(uint8_t b); uint8_t glb; void tst(void) { static uint8_t sv; uint8_t tmp; if (sv != (glb & (1 << 6))) { sv = (glb & (1 << 6)); tmp = (sv)? 0x00 : 0xFF; foo(tmp); } } int main() { while(1) { glb = GPIOA->IDR; tst(); } } ф-ция foo (в др. файле) void foo(uint8_t b) { GPIOB->ODR = b; } так не выкинет. У меня с добавлением строк работы с портами листинг не поменялся - есть ошибка 40 int main() 41 { \ main: \ 00000000 0xB570 PUSH {R4-R6,LR} \ 00000002 0x.... LDR.N R5,??DataTable3_1 \ 00000004 0x.... LDR.N R6,??DataTable3_2 ;; 0x40020010 \ 00000006 0xE001 B.N ??main_0 42 while(1) { 43 44 glb = GPIOA->IDR; 45 tst(); \ ??main_1: \ 00000008 0x.... 0x.... BL foo \ ??main_0: \ 0000000C 0x6830 LDR R0,[R6, #+0] // читаем порт \ 0000000E 0x7869 LDRB R1,[R5, #+1] // sv \ 00000010 0x7028 STRB R0,[R5, #+0] // glb = GPIOA->IDR \ 00000012 0x7828 LDRB R0,[R5, #+0] // glb \ 00000014 0xF000 0x0240 AND R2,R0,#0x40 // glb & (1 << 6) \ 00000018 0x4291 CMP R1,R2 \ 0000001A 0xD0F7 BEQ.N ??main_0 \ 0000001C 0x7068 STRB R0,[R5, #+1] // sv = glb (без маскирования) \ 0000001E 0x0640 LSLS R0,R0,#+25 \ 00000020 0xBF4C ITE MI \ 00000022 0x2000 MOVMI R0,#+0 \ 00000024 0x20FF MOVPL R0,#+255 \ 00000026 0xE7EF B.N ??main_1 46 47 } 48 }
-
вынесите ф-цию foo в другой файл. Неужели и в таком случае выкинет. Потому что по приведенной мной ссылке выражение "On optimization level High..." встречается довольно часто. Как я понял, большенство ошибок именно при такой оптимизации, если неправ - поправьте. А на счет высокого уровня оптимизации как инструмента по вылавливанию багов непонял. Всегда пишу на максимальном и в ту закладку даже не заглядываю. Как может алгоритм зависить от уровня оптимизации?
-
Посмотрел историю IAR: ICCARM History Хватает ошибок разных, особенно на уровне оптимизации High. Вот возможно разновидность моего случая (не утверждаю): "In EWARM 6.50.4: An indirect assignment could be optimized incorrectly if the right hand side expression was masked with a constant and the only use was in a test, comparing the value, possibly masked with the same constant as in the assignment or a constant with fewer bits set, to zero. For example: p->foo = x & 0x02; ... if (p->foo & 0x02) This has been corrected. [EW23796]" Кроме перехода на более свежую версию, наверное, и оптимизацию буду ставить не више Medium (всегда ставил High Balanced или High Speed).
-
да мне без разницы, что и где будет хранить компилятор, мне важен алгоритм, а он нарушается. При таком поведении компилятора, ф-ция foo будет вызыватся всегда, пока glb != 0 && glb != (1 << 6). И как писал выше, когда добавляю дополнительную (временную) переменую, все встает на свои места. А более новий IAR ведет себя предсказуемо всегда.
-
@Сергей Борщ При повторном вызове ф-ции tst при неизменной переменной glb, ф-ция foo вызываться не должна я прошу sv = glb & (1 << 6) а получаю sv = glb
-
@jcxz не заставляют. После найденой ошибки буду переходить на более свежий IAR. Имя неповторимое (оно не glb). Проблема же в неправильном присвоении значения переменной sv. Вопрос задал так как решил, что что-то упускаю. Видемо и в самом деле компилятор глючит.
-
@jcxz нет, переменная с таким именем одна. Ну а как же мой "изолированный" пример, разве такое поведение компилятора корректно? З.Ы. Оно соответствует поведению в моем проекте.
-
почему же компиляция при разных уровнях оптимизации разнится, как и при добавлении дополнительной переменной. Да и более свежий компилятор дает правильный код. Что по вашему надо добавить, что бы код для компилятора был "правильный"? Проект на 1000+ строк не вижу надобности выкладывать. Проблему изолировал. вот что получается когда делаю переменную glb volatile (оптимизация High Balanced) 27 void tst(void) 28 { 29 static uint8_t sv; 30 uint8_t tmp; 31 32 if (sv != (glb & (1 << 6))) { \ `tst`: \ 00000000 0x.... LDR.N R0,??DataTable3_1 \ 00000002 0x7841 LDRB R1,[R0, #+1] \ 00000004 0x7802 LDRB R2,[R0, #+0] \ 00000006 0xF002 0x0240 AND R2,R2,#0x40 \ 0000000A 0x4291 CMP R1,R2 \ 0000000C 0xD007 BEQ.N ??tst_0 33 sv = (glb & (1 << 6)); \ 0000000E 0x7801 LDRB R1,[R0, #+0] // операция "& (1 << 6)" игнорируется \ 00000010 0x7041 STRB R1,[R0, #+1] 34 tmp = (sv)? 0x00 : 0xFF; \ 00000012 0x0648 LSLS R0,R1,#+25 \ 00000014 0xBF4C ITE MI \ 00000016 0x2000 MOVMI R0,#+0 \ 00000018 0x20FF MOVPL R0,#+255 35 foo(tmp); \ 0000001A 0x.... 0x.... B.W foo 36 } 37 38 } \ ??tst_0: \ 0000001E 0x4770 BX LR ;; return
-
@Arlleex Программа корректна, а результат компиляции нет. Не изменяя программу, а только уровень оптимизации, получаем разный результат (алгоритм). А добавляя промежуточную переменную в "нерабочую" оптимизацию, получаем корректный результат. И еще. IAR ARM 8.30.1.17148 - компилирует правильно