Потихоньку изучаю свой 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