vovken1997 0 17 марта, 2016 Опубликовано 17 марта, 2016 · Жалоба Здравствуйте! Мне не удаётся скомпилировать прошивку для pic16f1825 компилятором xc8 (PRO mode) после того, как указываю codeoffset на 512 слов (в этой области загрузчик). При обычной компиляции (без смещения) пишет 85% занято, бутлоадер занимает 7%. Экспериментировал с различными значениями codeoffset, максимальное смещение при котором он ещё компилируется 340 слов, при чем если посмотреть код программы, то там остаётся куча незанятого места. Есть ли какая нибудь возможность заставить компилятор скомпоновать код и создать hex со смещением. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Redguy 0 17 марта, 2016 Опубликовано 17 марта, 2016 (изменено) · Жалоба Для начала я бы ушел от процентного представления занятой памяти. Более точно все-таки в байтах в map-файле посмотреть сколько конкретно занимает ваша программа. Второй момент нужно посмотреть linker файл после того, как вы установили смещение, убедиться, что смещение происходит действительно на нужное количество байт. А потом посмотреть чисто математически укладывается ли программа в предоставленный ей объем. Самое главное: а ошибку-то какую получаете, ошибку компилятора или линковщика, какую конкретно? Есть ли какая нибудь возможность заставить компилятор скомпоновать код и создать hex со смещением. Компилятор не компонует код, он только формиует рабочие куски кода с определенными входными аргументами, выходными параметрами, определенной длины. А вот линковщик уже эти готовые рабочие (100% проверенные) куски размещает в памяти по правилам заданным в линкер-файле и настраивает взаимосвязи между ними. Изменено 17 марта, 2016 пользователем Redguy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vovken1997 0 17 марта, 2016 Опубликовано 17 марта, 2016 (изменено) · Жалоба Спасибо за ценный ответ. Посмотрел map при смещении на 150: Name Link Load Length Selector Space Scale C:\Users\NIR\AppData\Local\Temp\s71g.obj end_init 285 285 2 2A8 0 reset_vec 150 150 2 2A0 0 config 8007 8007 2 1000E 0 dist/default/production\medic.X.production.obj cinit 951 951 6AF 12A2 0 intentry 154 154 131 2A8 0 text54 764 764 15 2A8 0 text41 287 287 4DD 2A8 0 text12 858 858 F9 10B0 0 text11 1990 1990 670 3320 0 cstackBANK0 20 20 33 20 1 cstackCOMMON 70 70 B 70 1 clrtext 779 779 C 2A8 0 bssBANK2 120 120 28 120 1 bssBANK1 A0 A0 46 A0 1 dataBANK0 6C 6C 4 20 1 bssBANK0 53 53 19 20 1 bssCOMMON 7B 7B 3 70 1 stringtext 1000 1000 6BE 20 0 Psect | Contents | Memory Range | Size ------------|--------------------------------|---------------|-------------- | | | reset_vec | Reset vector | 0150h - 0151h | 2 words intentry | Interrupt context entry code | 0154h - 0284h | 305 words end_init | Initialization code | 0285h - 0286h | 2 words text41 | Program and library code | 0287h - 0763h | 1245 words text54 | Program and library code | 0764h - 0778h | 21 words clrtext | Memory clearing code | 0779h - 0784h | 12 words text12 | Program and library code | 0858h - 0950h | 249 words cinit Microchip MPLAB XC8 C Compiler (PRO Mode) V1.33 Program space: CONST used 0h ( 0) of 1EB0h words ( 0.0%) CODE used 144Bh ( 5195) of 1EB0h words ( 66.1%) STRCODE used 6BEh ( 1726) of 1EB0h words ( 22.0%) ENTRY used 0h ( 0) of 1EB0h words ( 0.0%) STRING used 0h ( 0) of 1EB0h words ( 0.0%) Memory Summary: Program space used 1B09h ( 6921) of 2000h words ( 84.5%)... Видно, что смещение происходит и на нужную величину. Так же памяти у него достаточно, около 1000 слов, а надо всего 512. Настораживает строчка: hlink "--edf=C:\Program Files (x86)\Microchip\xc8\v1.33\dat\en_msgs.txt" -cs -h+dist/default/production\medic.X.production.sym --cmf=dist/default/production\medic.X.production.cmf -z -Q16F1825 -oC:\Users\NIR\AppData\Local\Temp\s8m8.6 -Mdist/default/production/medic.X.production.map -ver=XC8#PRO##V1.33 -ASTACK=020C8h-0225fh -pstack=STACK -ACONST=0150h-01FFh,0200h-02FFhx30 -ACODE=0150h-07FFh,0800h-0FFFhx3 -ASTRCODE=0150h-01FFFh -AENTRY=0150h-01FFh,0200h-02FFhx30 -ASTRING=0150h-01FFh,0200h-02FFhx30 -ACOMMON=070h-07Fh -ABANK0=020h-06Fh -ABANK1=0A0h-0EFh -ABANK2=0120h-016Fh -ABANK3=01A0h-01EFh -ABANK4=0220h-026Fh -ABANK5=02A0h-02EFh -ABANK6=0320h-036Fh -ABANK7=03A0h-03EFh -ABANK8=0420h-046Fh -ABANK9=04A0h-04EFh -ABANK10=0520h-056Fh -ABANK11=05A0h-05EFh -ABANK12=0620h-064Fh -ABIGRAM=02000h-023EFh -ARAM=020h-06Fh,0A0h-0EFh,0120h-016Fh,01A0h-01EFh,0220h-026Fh,02A0h-02EFh,0320h-036Fh,03A0h-03EFh,0420h-046Fh,04A0h-04EFh,0520h-056Fh,05A0h-05EFh,0620h-064Fh -AABS1=020h-07Fh,0A0h-0EFh,0120h-016Fh,01A0h-01EFh,0220h-026Fh,02A0h-02EFh,0320h-036Fh,03A0h-03EFh,0420h-046Fh,04A0h-04EFh,0520h-056Fh,05A0h-05EFh,0620h-064Fh -ASFR0=00h-01Fh -ASFR1=080h-09Fh -ASFR2=0100h-011Fh -ASFR3=0180h-019Fh -ASFR4=0200h-021Fh -ASFR5=0280h-029Fh -ASFR6=0300h-031Fh -ASFR7=0380h-039Fh -ASFR8=0400h-041Fh -ASFR9=0480h-049Fh -ASFR10=0500h-051Fh -ASFR11=0580h-059Fh -ASFR12=0600h-061Fh -ASFR13=0680h-06EFh -ASFR14=0700h-076Fh -ASFR15=0780h-07EFh -ASFR16=0800h-086Fh -ASFR17=0880h-08EFh -ASFR18=0900h-096Fh -ASFR19=0980h-09EFh -ASFR20=0A00h-0A6Fh -ASFR21=0A80h-0AEFh -ASFR22=0B00h-0B6Fh -ASFR23=0B80h-0BEFh -ASFR24=0C00h-0C6Fh -ASFR25=0C80h-0CEFh -ASFR26=0D00h-0D6Fh -ASFR27=0D80h-0DEFh -ASFR28=0E00h-0E6Fh -ASFR29=0E80h-0EEFh -ASFR30=0F00h-0F6Fh -ASFR31=0F80h-0FEFh -preset_vec=0150h,intentry=0154h,init,end_init -ppowerup=CODE -pcinit=CODE -pfunctab=CODE -ACONFIG=08007h-08008h -pconfig=CONFIG -DCONFIG=2 -AIDLOC=08000h-08003h -pidloc=IDLOC -DIDLOC=2 -AEEDATA=00h-0FFh/0F000h -peeprom_data=EEDATA -DEEDATA=2 -DCODE=2 -DSTRCODE=2 -DSTRING=2 -DCONST=2 -DENTRY=2 -k C:\Users\NIR\AppData\Local\Temp\s8m8.obj dist/default/production\medic.X.production.obj А именно -ACODE=0150h-07FFh,0800h-0FFFhx3 -ASTRCODE=0150h-01FFFh. Почему то класс кода делится на сегменты, один от 150 до 800, а остальные по 2к. слова далее до конца. При смещении на 200, линковщик после выше указанного текста hlink... выдаёт ошибку 0: (1347) can't find 0x58F words (0x58f withtotal) for psect "text41" in class "CODE" (largest unused contiguous range 0x493). Да, после изменения смещения параметр в линковщике меняется на -ACODE=0200h-07FFh,0800h-0FFFhx3. К сожалению я не знаю, возможно ли вручную задать -ACODE=0200h-1FFF и будет ли это иметь какой то смысл, но это единственная моя догадка на данный момент. Если не сложно, подскажите пожалуйста. Добавлено: Нашёл такой текст в документации: The second cause of this message is when the total amount of memory needed by the psect being positioned is sufficient, but that this memory is fragmented in such a way that the largest contiguous block is too small to accommodate the psect. The linker is unable to split psects in this situation. That is, the linker cannot place part of a psect at one location and part somewhere else. Thus, the linker must be able to find a contiguous block of memory large enough for every psect. If this is the cause of the error, then the psect must be split into smaller psects if possible. To find out what memory is still available, generate and look in the map file, see Section 4.8.8 “-M: Generate Map File” for information on how to generate a map file. Search for the string UNUSED ADDRESS RANGES. Under this heading, look for the name of the segment specified in the error message. If the name is not present, then all the memory available for this psect has been allocated. If it is present, there will be one address range specified under this segment for each free block of memory. Determine the size of each block and compare this with the number of words specified in the error message. Psects containing code can be reduced by using all the compiler’s optimizations, or restructuring the program. If a code psect must be split into two or more small psects, this requires splitting a function into two or more smaller functions (which may call each other). These functions may need to be placed in new modules. Psects containing data may be reduced when invoking the compiler optimizations, but the effect is less dramatic. The program may need to be rewritten so that it needs less variables. If the default linker options must be changed, this can be done indirectly through the driver using the driver -L- option, see Section 4.8.7 “-L-: Adjust Linker Options Directly”. Section 4.8.8 “-M: Generate Map File” has information on interpreting the map file’s call graph if the compiler you are using uses a compiled stack. (If the string Call graph: is not present in the map file, then the compiled code uses a hardware stack.) If a data psect needs to be split into smaller psects, the definitions for variables will need to be moved to new modules or more evenly spread in the existing modules. Memory allocation for auto variables is entirely handled by the compiler. Other than reducing the number of these variables used, the programmer has little control over their operation. This applies whether the compiled code uses a hardware or compiled stack. На сколько я понимаю, предлагается разбивать функции или же редактировать параметры линковщика. Я изменил параметр линковщика на -L-ACODE=0200h-07FFh,800h-1FFFh (это вставил в Additional option в настройках проекта XC8 Linker). В map файле проверил что установил правильно, проект скомпилировался. Когда добавил смещение, то получил новую ошибку: 1297: (1357) fixup overflow storing 0x92D in 2 bytes at 0x3254/0x2 -> 0x192A (dist/default/production\medic.X.production.obj 232/0x24) Что это то такое? Изменено 17 марта, 2016 пользователем vovken1997 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
varostov 0 18 марта, 2016 Опубликовано 18 марта, 2016 (изменено) · Жалоба Здравствуйте! В своё время сам мучился с бутлоадером, требующим сдвига кода. В конце концов перебрался на загрузчик, который прописывается "на чердаке" программной памяти, позволяя отлаживать и компилировать программу так, как будто бутлоадера нет вовсе, а позже загружать полученный hex через бутлоадер. Могу порекомендовать популярный и хорошо документированный ds30Loader: Home page, Исходники. За пару вечеров изучил и запустил под PIC24. Не обращайте внимание на название, в исходниках коды на ассемблере для PIC12, 16, 18, 24, dsPIC, PIC32 + GUI под Windows (включая консольную версию). P.S. GUI достаточно гибкое и позволяет настраивать, помимо прочего, скорость загрузки (включая autobaud) и способ сброса для загрузки - ручной, по сигналам DTR/RTS, по спец. команде (я, например, вбил модбасовскую команду дистанционного сброса устройства). Изменено 18 марта, 2016 пользователем varostov Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vovken1997 0 18 марта, 2016 Опубликовано 18 марта, 2016 · Жалоба varostov, к сожалению размещать загрузчик "на чердаке" я не могу, так как эта область не защищается аппаратно и я использую прерывания, которые бы не хотелось передавать через программу. Загрузчик я писал сам из-за достаточно уникальной задачи. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
varostov 0 19 марта, 2016 Опубликовано 19 марта, 2016 · Жалоба Ok, тогда желаю успеха. Подсказать, к сожалению, ничего не смогу (давно это было). На будущее: в PIC24 можно задавать количество защищаемых страниц с начала или конца программной памяти + другие фичи ("CodeGuard Security"). Что-то внедрено и в PIC18, но точно не изучал. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vovken1997 0 19 марта, 2016 Опубликовано 19 марта, 2016 · Жалоба Спасибо! Вчера пытался разбить на 20 подфункций. Ничего не получилось, все также ошибка при смещении... Неужели ни у кого не было такой проблемы??? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 19 марта, 2016 Опубликовано 19 марта, 2016 · Жалоба Здравствуйте! В своё время сам мучился с бутлоадером, требующим сдвига кода. В конце концов перебрался на загрузчик, который прописывается "на чердаке" программной памяти, позволяя отлаживать и компилировать программу так, как будто бутлоадера нет вовсе, а позже загружать полученный hex через бутлоадер. Дела давно минувших дней... Когда делал загрузчик, для PIC16, то он у меня грузил программу сделанную "так, как будто бутлоадера нет вовсе". Только и сам был, как "обычная программа". Я пиками практчески не занимаюсь, так что разных кошерных загрузчиков не изучал за ненедобностью, а сделал, как сделал :). Всего делов-то и было, что в нем по вектору сброса были 4 NOP, а при загрузке "программы" он слегка правил образ: void main(void) { ..... ..... #asm global _application_reset_vector _application_reset_vector nop nop nop nop #endasm // Wait watchdog in case the first four bytes are not a jmp instruction for(;; ); } -------------------- // The bootloader remaps the first four bytes of the application code into a secondary area. // This is done to preserve the initial reset vector that jumps to the bootloader. // By doing this, we make sure that the bootloader always fires up before the application // code and passes control onto it. if( uhf.cdd_st.address < 0x0004 ) { // Remap the reset vector byte len = uhf.cdd_st.len_u8 + uhf.cdd_st.address; if( len > 4 ) len = 4; len -= uhf.cdd_st.address; // Write whatever part of the reset vector into our reserved appication_reset_vector. // Write the remaining bytes into their original location. if( flash_block_write( (ushort)&application_reset_vector + uhf.cdd_st.address, uhf.cdd_st.data_word, len )|| flash_block_write( uhf.cdd_st.address+len, &uhf.cdd_st.data_word[len], uhf.cdd_st.len_u8-len ) ) { Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vovken1997 0 20 марта, 2016 Опубликовано 20 марта, 2016 · Жалоба Да, хороший способ. Но очень ненадежный... Не защищены ни первые четыре слова, ни последние. Если сломался загрузчик у человека, у которого нет программатора, устройство можно выкинуть... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 20 марта, 2016 Опубликовано 20 марта, 2016 · Жалоба Если сломался загрузчик у человека, у которого нет программатора, устройство можно выкинуть... Это ужасно. У меня очевидно по незнанию :) и такой живет с 2007 года в 40 тысячах с гаком экземпляров не выключаясь никогда. Загрузчик и прошивка делалась для уже готовых, устройств одной юаровской фирмы, которые будучи поставлены на обьект в количестве пары тысяч штук, действительно окирпичивались в темпе 10 штук в день. А что такое ломающийся загрузчик?. Или, скажем так, не ломающийся :)? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vovken1997 0 21 марта, 2016 Опубликовано 21 марта, 2016 · Жалоба Не ломающийся загрузчик (в моём понимании) - это загрузчик, который не может сам себя перезатереть при программировании И не дать себя перезатереть программе, которой отдал управление. Такой загрузчик если и зависнет при прошивке по каким то обстоятельствам, то передёргивание питания всё должно вернуть на место. Другими совами ему ничего не должно быть страшно и, следовательно, он должен без посредников получать управление чтобы корявый загружаемый код (возможно даже нацеленный на поломку устройства), не смог ничего попортить. Делается такая защита при помощи конфигурационных бит, которые указываются при прошивке программатором. Эти биты защищают какую то часть программы от перезаписи самой программой. Например в pic16f1825 можно либо вообще не защитить, либо защитить 0x200, либо 0x1000, либо всю. У меня стоит защита 0x200, следовательно первые 512 слов сама программа не может перезаписать. Это отдельно проверял, команды на стирание отправляются, а страница остаётся невредима. Но тем ни менее моя проблема так и не решена! Есть загрузчик, но нет возможности сделать прошивку. Столько про эти загрузчики разговоров в сети, неужели никто не загружал код, который занимает много памяти? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vovken1997 0 24 марта, 2016 Опубликовано 24 марта, 2016 · Жалоба Прошивка скомпилировалась и слинковалась! Компилятор: XC8 v1.37 (PRO mode) - бесплатная лицензия от Microchip на 60 дней Среда разработки: MPLAB X IDE v3.25 Проблема была в том, что память в этом микроконтроллере разделена на 4 страницы, каждая страница 2К слова (если нужно перейти по адресу, находящемуся на другой странице, то необходима дополнительная команда смены страницы). Компилятор подготавливает так называемые psect (раздел памяти) в которых объединены функции. Если я правильно понимаю, то это такие своеобразные "чёрные ящики", которые компилятор отдаёт линковщику в виде объектных файлов, чтобы тот их разместил в памяти. Так как эти объектные файлы не могут находиться на стыке двух страниц, то есть пересекать их, то может возникнуть ситуация, когда памяти вроде бы хватает, но линковщик отказывается размещать "чёрные ящики", говоря, что максимальная не занятая область внутри страниц меньше, чем то, что необходимо разместить. Следовательно чтобы решить данную проблему, необходимо разбить "чёрные ящики" на части. Я это сделал при помощи спецификатора __section(), который добавил у больших функций, чтобы компилятор подготовил для них отдельный psect и линковщик мог разместить их в памяти по своему желанию. Да, при использовании данного метода, у меня съелось около 160 слов. Они были использованы компилятором для смены страниц при переходах. Собственно вот пример: void __section("main") main (void) { ... } byte __section("settings") my_settings(byte mod){ ... } Ну и позволю себе привести цитату из документации на компилятор: The __section() specifier may be used to indicate that an object should be located in the named section (or psect, using the XC8 terminology). This is typically used when the object has special and unique linking requirements which cannot be addressed by existing compiler features. Use the native keywords discussed in the Differences section to look up information on the semantics of this specifier. 2.5.13.1 EXAMPLE The following shows a variable which uses the __section keyword. int __section("comSec") commonFlag; 2.5.13.2 DIFFERENCES The 8-bit compilers have used the #pragma psect directive to redirect objects to a new section, or psect. The operation of the __section() specifier is different to this pragma in several ways, described below. Unlike with the pragma, the new psect created with __section() does not inherit the flags of the psect in which the object would normally have been allocated. This means that the new psect can be linked in any memory area, including any data bank. The compiler will also make no assumptions about the location of the object in the new section. Objects redirected to new psects using the pragma must always be linked in the same memory area, albeit at any address in that area. The __section() specifier allows objects that are initialized to be placed in a different psect. Initialization of the object will still be performed even in the new psect. This will require the automatic allocation of an additional psect (whose name will be the same as the new psect prefixed with the letter i), which will contain the initial values. The pragma cannot be used with objects that are initialized. Objects allocated a different psect with __section() will be cleared by the runtime startup code, unlike objects which use the pragma. You must reserve memory, and locate via a linker option, for any new psect created with a __section() specifier in the current XC8 compiler implementation. The 16- and 32-bit compilers have used the section attribute to indicate a different destination section name. The __section() specifier works in a similar way to the attribute. Если кто то знает другое решение данной проблемы, прошу сообщить мне об этом. Спасибо большое за помощь zltigo и остальным! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться