ohmjke 0 29 марта, 2012 Опубликовано 29 марта, 2012 · Жалоба Здравствуйте, недавно начал изучать МК с этим ядром. Пока что в основном все понятно, попробовал написать простую прогу на ассемблере по примерам с сайта http://stm32asm.ru. Все работает, но т.к. писать весь код на ассемблере для кортексов - не вариант, решил по-тихоньку переходить на СИ. Появились кое-какие вопросы. К примеру, написал код, аналогичный коду на ассемблере, скомпилировал, запустил отладку. И вижу, что выполнение программы начинается с каких-то "левых" функций/процедур(см. вложение). Что это такое, для чего нужно? Можно ли как-то сделать, чтобы компилятор СИ не добавлял их в программу? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RabidRabbit 0 29 марта, 2012 Опубликовано 29 марта, 2012 · Жалоба Настройки таргета, закладка Linker, поставить галочку Don't Search Standard Libraries (хотя это верхушка айсберга :) ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ohmjke 0 29 марта, 2012 Опубликовано 29 марта, 2012 (изменено) · Жалоба Настройки таргета, закладка Linker, поставить галочку Don't Search Standard Libraries (хотя это верхушка айсберга :) ) Спасибо, думаю, сработало, ибо вылезла ошибка: discovery_C2.axf: Error: L6218E: Undefined symbol __main (referred from startup_stm32f10x_ld_vl.o). Как мне теперь передать управление мэйну из стартап-файла? Сейчас там такая бадяга: IMPORT __main LDR R0, =__main BX R0 Изменено 29 марта, 2012 пользователем ohmjke Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RabidRabbit 0 30 марта, 2012 Опубликовано 30 марта, 2012 · Жалоба Проще всего переименовать свой main() в __main() :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ohmjke 0 30 марта, 2012 Опубликовано 30 марта, 2012 · Жалоба Проще всего переименовать свой main() в __main() :) Большое спасибо, работает! Правда, вылез один warning: discovery_C2.sct(8): warning: L6314W: No section matches pattern *(InRoot$$Sections). Но, насколько я понял, на работоспособность моей программы это не влияет. В железе все норм. В отладчике видно, что код во flash размещается с адреса 0x08000000, как и должно быть. А не подскажете, где можно почитать про все эти взаимодействия между СИ и asm файлами проекта? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RabidRabbit 0 31 марта, 2012 Опубликовано 31 марта, 2012 · Жалоба Как-то сейчас и не вспомню, теоретически в хелпе того же кейла можно посмотреть... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 2 апреля, 2012 Опубликовано 2 апреля, 2012 · Жалоба И вижу, что выполнение программы начинается с каких-то "левых" функций/процедур(см. вложение). Что это такое, для чего нужно? Можно ли как-то сделать, чтобы компилятор СИ не добавлял их в программу? Освоение языка Си точно не следует начинать с этого. К чему этот минимализм? Он будет только мешать. Кстати, если я правильно помню, в Кейле есть опция MicroLib: по сути это обезжиренная версия стандартной библиотеки, оптимизированная по размеру, а не по скорости. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ohmjke 0 2 апреля, 2012 Опубликовано 2 апреля, 2012 · Жалоба Освоение языка Си точно не следует начинать с этого. К чему этот минимализм? Он будет только мешать. Кстати, если я правильно помню, в Кейле есть опция MicroLib: по сути это обезжиренная версия стандартной библиотеки, оптимизированная по размеру, а не по скорости. Осваивать СИ я начал относительно давно. Просто хочется знать за что отвечает каждый кусок программы, дело не том, что мне жалко флеша :rolleyes: А вообще спасибо! Попробовал microlib - доволен. Намного понятнее, чем стандартная библиотека. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lead_seller 0 3 апреля, 2012 Опубликовано 3 апреля, 2012 · Жалоба Осваивать СИ я начал относительно давно. Просто хочется знать за что отвечает каждый кусок программы, дело не том, что мне жалко флеша :rolleyes: А вообще спасибо! Попробовал microlib - доволен. Намного понятнее, чем стандартная библиотека. Учтите, что за MicroLIB придется заплатить. К примеру, функции из этой библиотеки нельзя использовать при работе с KEIL RTX. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ohmjke 0 3 апреля, 2012 Опубликовано 3 апреля, 2012 · Жалоба Учтите, что за MicroLIB придется заплатить. К примеру, функции из этой библиотеки нельзя использовать при работе с KEIL RTX. Я пока не настольно крут, чтобы использовать KEIL RTX :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ohmjke 0 9 апреля, 2012 Опубликовано 9 апреля, 2012 (изменено) · Жалоба Потихоньку изучаю свой cm3, дошел до RTC. Проблема с функцией для получения даты и времени зная значение счетчика RTC. Набыдлокодил такую фиговину: extern void rtc_decoder (uint32_t counter, date_t *date, time_t *time) { static const int8_t mth_vls [] = {1, -1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1}; int64_t temp; uint32_t temp_2, temp_3; uint8_t i = 0; temp = (uint32_t)(counter % SEC_PER_4Y); if (temp > SEC_PER_LY) { temp -= SEC_PER_LY; i++; while (temp > SEC_PER_Y) { temp -= SEC_PER_Y; i++; }; }; date->year = 2012 + ((counter / SEC_PER_4Y) << 2) + i; i = 0; do { temp_2 = (uint32_t)temp; if (mth_vls [i] == 1) { temp -= 31 * SEC_PER_D; } else if (mth_vls [i] == 0) { temp -= 30 * SEC_PER_D; } else { if (!(date->year % 4)) { temp -= 29 * SEC_PER_D; } else { temp -= 28 * SEC_PER_D; }; }; i++; } while (temp > 0); date->month = (month_t)i; date->day = (temp_2 / SEC_PER_D) + 1; temp_3 = temp_2 % SEC_PER_D; time->hour = temp_3 / 3600; temp_2 = temp_3 % 3600; time->minute = temp_2 / 60; time->second = temp_2 % 60; }; В *.h файле следующее: #define START_YEAR (2012UL) #define SEC_PER_4Y (126230400UL) #define SEC_PER_LY (31622400UL) #define SEC_PER_Y (31536000UL) #define SEC_PER_D (86400UL) typedef enum { Sunday = 0, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday } weekday_t; typedef enum { January = 1, February, March, April, May, June, July, August, September, October, November, December } month_t; typedef struct { uint8_t second; uint8_t minute; uint8_t hour; } time_t; typedef struct { uint8_t day; month_t month; uint16_t year; } date_t; static time_t system_time; static date_t system_date; В мэйне один раз при запуске вызываю эту функцию: rtc_decoder (0x00F156CB, &system_date, &system_time); И затем в обработчике внешнего прерывания вывожу такую бадягу: usart1_putchar (system_date.year / 1000); usart1_putchar ((system_date.year % 1000) / 100); usart1_putchar ((system_date.year % 100) / 10); usart1_putchar (system_date.year % 10); Проблема в том, что в режиме отладки, когда проц переходит к началу этой функции, начинают вываливаться ошибки. Сначала появляется окно с текстом "Internal command error", затем "Error while attempting to read 64 bytes from 0x20001ffc", затем опять первое окно, после него опять второе... Если же запустить МК не в режиме отладки, а в реальном времени, то на терминал приходят одни нули, т.к. как будто бы функция вообще не вызывалась. Причем интересно то, что чуть раньше все работало, по крайней мере по usart-у приходила верная информация. Никак не могу понять, что я поменял, после чего начались эти траблы. Ну и, дизассемблер: 0x08000490 B5F0 PUSH {r4-r7,lr} 16: 0x08000492 4B43 LDR r3,[pc,#268] ; @0x080005A0 0x08000494 4E43 LDR r6,[pc,#268] ; @0x080005A4 0x08000496 FBB0F7F3 UDIV r7,r0,r3 0x0800049A FB030017 MLS r0,r3,r7,r0 15: uint8_t i = 0; 16: 0x0800049E 2400 MOVS r4,#0x00 0x080004A0 4623 MOV r3,r4 0x080004A2 1A36 SUBS r6,r6,r0 0x080004A4 EB740503 SBCS r5,r4,r3 17: temp = (uint32_t)(counter % SEC_PER_4Y); 0x080004A8 DA12 BGE 0x080004D0 18: if (temp > SEC_PER_LY) { 0x080004AA 4C3E LDR r4,[pc,#248] ; @0x080005A4 0x080004AC 4264 RSBS r4,r4,#0 0x080004AE 1900 ADDS r0,r0,r4 0x080004B0 F14333FF ADC r3,r3,#0xFFFFFFFF 19: temp -= SEC_PER_LY; 0x080004B4 2401 MOVS r4,#0x01 20: i++; 0x080004B6 E005 B 0x080004C4 21: while (temp > SEC_PER_Y) { 0x080004B8 4D3B LDR r5,[pc,#236] ; @0x080005A8 0x080004BA 1940 ADDS r0,r0,r5 0x080004BC F14333FF ADC r3,r3,#0xFFFFFFFF 22: temp -= SEC_PER_Y; 23: i++; 24: }; 0x080004C0 1C64 ADDS r4,r4,#1 0x080004C2 B2E4 UXTB r4,r4 0x080004C4 4E38 LDR r6,[pc,#224] ; @0x080005A8 0x080004C6 2500 MOVS r5,#0x00 0x080004C8 4276 RSBS r6,r6,#0 0x080004CA 1A36 SUBS r6,r6,r0 0x080004CC 419D SBCS r5,r5,r3 20: i++; 21: while (temp > SEC_PER_Y) { 22: temp -= SEC_PER_Y; 23: i++; 24: }; 0x080004CE DBF3 BLT 0x080004B8 25: }; 26: date->year = 2012 + ((counter / SEC_PER_4Y) << 2) + i; 27: i = 0; 28: do { 0x080004D0 EB040487 ADD r4,r4,r7,LSL #2 0x080004D4 F20474DC ADDW r4,r4,#0x7DC 0x080004D8 FA1FFE84 UXTH lr,r4 29: temp_2 = (uint32_t)temp; 30: if (mth_vls [i] == 1) { 0x080004DC F8DFC0CC LDR.W r12,[pc,#204] ; @0x080005AC 0x080004E0 F8A1E002 STRH lr,[r1,#0x02] 26: date->year = 2012 + ((counter / SEC_PER_4Y) << 2) + i; 27: i = 0; 0x080004E4 2400 MOVS r4,#0x00 0x080004E6 F91C6004 LDRSB r6,[r12,r4] 28: do { 29: temp_2 = (uint32_t)temp; 30: if (mth_vls [i] == 1) { 0x080004EA 4605 MOV r5,r0 0x080004EC 2E01 CMP r6,#0x01 0x080004EE D025 BEQ 0x0800053C 31: temp -= 31 * SEC_PER_D; 32: } else if (mth_vls [i] == 0) { 33: temp -= 30 * SEC_PER_D; 0x080004F0 B336 CBZ r6,0x08000540 34: } else { 35: if (!(date->year % 4)) { 36: temp -= 29 * SEC_PER_D; 0x080004F2 EA5F768E LSLS r6,lr,#30 0x080004F6 D025 BEQ 0x08000544 37: } else { 38: temp -= 28 * SEC_PER_D; 39: }; 0x080004F8 4E2D LDR r6,[pc,#180] ; @0x080005B0 40: }; 0x080004FA 2700 MOVS r7,#0x00 0x080004FC 1980 ADDS r0,r0,r6 0x080004FE F14333FF ADC r3,r3,#0xFFFFFFFF 0x08000502 1C64 ADDS r4,r4,#1 0x08000504 463E MOV r6,r7 0x08000506 1A3F SUBS r7,r7,r0 0x08000508 B2E4 UXTB r4,r4 0x0800050A 419E SBCS r6,r6,r3 41: i++; 42: } while (temp > 0); 0x0800050C DBEB BLT 0x080004E6 43: date->month = (month_t)i; 0x0800050E 4B29 LDR r3,[pc,#164] ; @0x080005B4 42: } while (temp > 0); 43: date->month = (month_t)i; 0x08000510 704C STRB r4,[r1,#0x01] 0x08000512 FBB5F0F3 UDIV r0,r5,r3 0x08000516 1C44 ADDS r4,r0,#1 44: date->day = (temp_2 / SEC_PER_D) + 1; 0x08000518 FB035010 MLS r0,r3,r0,r5 43: date->month = (month_t)i; 44: date->day = (temp_2 / SEC_PER_D) + 1; 0x0800051C 700C STRB r4,[r1,#0x00] 45: temp_3 = temp_2 % SEC_PER_D; 0x0800051E F44F6361 MOV r3,#0xE10 0x08000522 FBB0F1F3 UDIV r1,r0,r3 46: time->hour = temp_3 / 3600; 0x08000526 FB030011 MLS r0,r3,r1,r0 0x0800052A 7091 STRB r1,[r2,#0x02] 47: temp_2 = temp_3 % 3600; 0x0800052C 233C MOVS r3,#0x3C 0x0800052E FBB0F1F3 UDIV r1,r0,r3 48: time->minute = temp_2 / 60; 0x08000532 FB030011 MLS r0,r3,r1,r0 0x08000536 7051 STRB r1,[r2,#0x01] 0x08000538 7010 STRB r0,[r2,#0x00] 49: time->second = temp_2 % 60; 50: }; 0x0800053A BDF0 POP {r4-r7,pc} 30: if (mth_vls [i] == 1) { Использую MICROLIB. /***************************************************************************/ Блин. Как часто со мной бывает - нашел косяк вскоре после того как задал здесь вопрос. Проблема со стеком. В чем именно она была, я так и не понял, но решить ее удалось. У меня был вручную подправлен scatter-файл: LR_IROM1 0x08000000 0x00020000 {; load region size_region ER_IROM1 0x08000000 0x00020000 {; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM2 0x20001000 0x00001000 {; stack *.o (STACK, +First) } RW_IRAM1 0x20000000 0x00001000 {; RW data .ANY (+RW +ZI) } } Убрал кусок RW_IRAM2 0x20001000 0x00001000 {; stack *.o (STACK, +First) } и исправил размер RW_IRAM2 с 0x00001000 на 0x00002000, и ошибки перестали выскакивать. Раньше при запуску содержимое SP было таким - 0x20002000, теперь такое - 0x20001114. Надо будет как-нибудь со всем этим рзобраться. Изменено 9 апреля, 2012 пользователем ohmjke Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться