реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> STM32VLDISCOVERY + Keil
ohmjke
сообщение Mar 29 2012, 09:47
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 116
Регистрация: 27-01-10
Из: СПб
Пользователь №: 55 094



Здравствуйте, недавно начал изучать МК с этим ядром. Пока что в основном все понятно, попробовал написать простую прогу на ассемблере по примерам с сайта http://stm32asm.ru. Все работает, но т.к. писать весь код на ассемблере для кортексов - не вариант, решил по-тихоньку переходить на СИ. Появились кое-какие вопросы. К примеру, написал код, аналогичный коду на ассемблере, скомпилировал, запустил отладку. И вижу, что выполнение программы начинается с каких-то "левых" функций/процедур(см. вложение). Что это такое, для чего нужно? Можно ли как-то сделать, чтобы компилятор СИ не добавлял их в программу?
Прикрепленное изображение
Go to the top of the page
 
+Quote Post
RabidRabbit
сообщение Mar 29 2012, 11:48
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040



Настройки таргета, закладка Linker, поставить галочку Don't Search Standard Libraries (хотя это верхушка айсберга sm.gif )
Go to the top of the page
 
+Quote Post
ohmjke
сообщение Mar 29 2012, 14:14
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 116
Регистрация: 27-01-10
Из: СПб
Пользователь №: 55 094



Цитата(RabidRabbit @ Mar 29 2012, 15:48) *
Настройки таргета, закладка Linker, поставить галочку Don't Search Standard Libraries (хотя это верхушка айсберга sm.gif )

Спасибо, думаю, сработало, ибо вылезла ошибка:
Код
discovery_C2.axf: Error: L6218E: Undefined symbol __main (referred from startup_stm32f10x_ld_vl.o).

Как мне теперь передать управление мэйну из стартап-файла? Сейчас там такая бадяга:
Код
IMPORT  __main
LDR R0, =__main
BX R0


Сообщение отредактировал ohmjke - Mar 29 2012, 14:14
Go to the top of the page
 
+Quote Post
RabidRabbit
сообщение Mar 30 2012, 10:06
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040



Проще всего переименовать свой main() в __main() sm.gif
Go to the top of the page
 
+Quote Post
ohmjke
сообщение Mar 30 2012, 13:41
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 116
Регистрация: 27-01-10
Из: СПб
Пользователь №: 55 094



Цитата(RabidRabbit @ Mar 30 2012, 14:06) *
Проще всего переименовать свой main() в __main() sm.gif

Большое спасибо, работает! Правда, вылез один warning:
Код
discovery_C2.sct(8): warning: L6314W: No section matches pattern *(InRoot$$Sections).

Но, насколько я понял, на работоспособность моей программы это не влияет. В железе все норм. В отладчике видно, что код во flash размещается с адреса 0x08000000, как и должно быть.
А не подскажете, где можно почитать про все эти взаимодействия между СИ и asm файлами проекта?
Go to the top of the page
 
+Quote Post
RabidRabbit
сообщение Mar 31 2012, 20:12
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040



Как-то сейчас и не вспомню, теоретически в хелпе того же кейла можно посмотреть...
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 2 2012, 15:59
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(ohmjke @ Mar 29 2012, 13:47) *
И вижу, что выполнение программы начинается с каких-то "левых" функций/процедур(см. вложение). Что это такое, для чего нужно? Можно ли как-то сделать, чтобы компилятор СИ не добавлял их в программу?

Освоение языка Си точно не следует начинать с этого. К чему этот минимализм? Он будет только мешать. Кстати, если я правильно помню, в Кейле есть опция MicroLib: по сути это обезжиренная версия стандартной библиотеки, оптимизированная по размеру, а не по скорости.
Go to the top of the page
 
+Quote Post
ohmjke
сообщение Apr 2 2012, 18:18
Сообщение #8


Частый гость
**

Группа: Участник
Сообщений: 116
Регистрация: 27-01-10
Из: СПб
Пользователь №: 55 094



Цитата(scifi @ Apr 2 2012, 19:59) *
Освоение языка Си точно не следует начинать с этого. К чему этот минимализм? Он будет только мешать. Кстати, если я правильно помню, в Кейле есть опция MicroLib: по сути это обезжиренная версия стандартной библиотеки, оптимизированная по размеру, а не по скорости.

Осваивать СИ я начал относительно давно. Просто хочется знать за что отвечает каждый кусок программы, дело не том, что мне жалко флеша rolleyes.gif

А вообще спасибо! Попробовал microlib - доволен. Намного понятнее, чем стандартная библиотека.
Go to the top of the page
 
+Quote Post
lead_seller
сообщение Apr 3 2012, 17:21
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 53
Регистрация: 27-10-08
Пользователь №: 41 225



Цитата(ohmjke @ Apr 2 2012, 21:18) *
Осваивать СИ я начал относительно давно. Просто хочется знать за что отвечает каждый кусок программы, дело не том, что мне жалко флеша rolleyes.gif

А вообще спасибо! Попробовал microlib - доволен. Намного понятнее, чем стандартная библиотека.


Учтите, что за MicroLIB придется заплатить. К примеру, функции из этой библиотеки нельзя использовать при работе с KEIL RTX.
Go to the top of the page
 
+Quote Post
ohmjke
сообщение Apr 3 2012, 17:30
Сообщение #10


Частый гость
**

Группа: Участник
Сообщений: 116
Регистрация: 27-01-10
Из: СПб
Пользователь №: 55 094



Цитата(lead_seller @ Apr 3 2012, 21:21) *
Учтите, что за MicroLIB придется заплатить. К примеру, функции из этой библиотеки нельзя использовать при работе с KEIL RTX.

Я пока не настольно крут, чтобы использовать KEIL RTX rolleyes.gif
Go to the top of the page
 
+Quote Post
ohmjke
сообщение Apr 9 2012, 20:19
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 116
Регистрация: 27-01-10
Из: СПб
Пользователь №: 55 094



Потихоньку изучаю свой cm3, дошел до RTC.
Проблема с функцией для получения даты и времени зная значение счетчика RTC.
Набыдлокодил такую фиговину:
CODE

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 файле следующее:
CODE

#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-у приходила верная информация. Никак не могу понять, что я поменял, после чего начались эти траблы.
Ну и, дизассемблер:
CODE
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. Надо будет как-нибудь со всем этим рзобраться.

Сообщение отредактировал ohmjke - Apr 9 2012, 20:21
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 12:03
Рейтинг@Mail.ru


Страница сгенерированна за 0.01473 секунд с 7
ELECTRONIX ©2004-2016