|
МК после сброса по WatchDog |
|
|
|
Jan 21 2016, 09:47
|
Участник

Группа: Участник
Сообщений: 19
Регистрация: 2-04-15
Из: Железногорск
Пользователь №: 86 023

|
Всем привет.
Проблема такая: Необходимо завести такую переменную, которая после сброса МК по WatchDog сохранит свое значение.
Пробовал через static. Но видимо я чего-то глубоко не понимаю. Если переменную не инициализировать, то в ней рандомное значение, которое нельзя никак изменить. (А писать static int i=0 глупо, т.к. оно каждый раз будет обнуляться).
Вообще возможно ли это? или МК после сброса по WatchDog затирает память?
|
|
|
|
|
Jan 21 2016, 10:49
|
Местный
  
Группа: Участник
Сообщений: 326
Регистрация: 30-05-06
Пользователь №: 17 602

|
Компилятор по умолчанию при сбросе устанавливает указатель стека, обнуляет ОЗУ ( .bss область) и затем инициализирует переменные. Напишите свой ResetHandler. Я так пробовал Код //#pragma vector=RESET_VECTOR //__interrupt void _reset_vector__(void) //{ // WDTCTL = WDTPW | WDTHOLD; // Stop WDT // asm(" mov #0x23fe,r1");// #0x23fe // asm("br #main");//main(); //} //#pragma vector=UNMI_VECTOR /* 0xFFFA User Non-maskable */ //__interrupt void _unmi_vector__(void) //{ // nop(); //// asm("reti"); //} //#pragma vector=SYSNMI_VECTOR /* 0xFFFC System Non-maskable */ //__interrupt void _sysnmi_vector__(void) //{ // nop(); //// asm("reti"); //} //
Сообщение отредактировал mcheb - Jan 21 2016, 10:52
|
|
|
|
|
Jan 21 2016, 14:39
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(ListenReality @ Jan 21 2016, 12:47)  Всем привет.
Проблема такая: Необходимо завести такую переменную, которая после сброса МК по WatchDog сохранит свое значение. . . . Вообще возможно ли это? или МК после сброса по WatchDog затирает память? В опциях проекта подключите файл линкера не по умолчанию, а с Вашими настройками. (скопировать стандартный в каталог проекта) В шапке лин-файла ( для MSP430F149 это файл lnk430F149.xcl ) есть такое: Код // segment Restrictions Usage // ------- ------------ -------------------------- // DATA16_I < 10000 Data16 initialized variables // DATA16_Z < 10000 Data16 zero initialized variables // DATA16_N < 10000 Data16 uninitialized variables // DATA16_HEAP < 10000 Data16 heap used by malloc and free // DATA20_I Data20 initialized variables // DATA20_Z Data20 zero initialized variables // DATA20_N Data20 uninitialized variables // DATA20_HEAP Data20 heap used by malloc and free // CSTACK < 10000 Runtime stack обратите внимание на сегмент DATA16_N. Если переменную разместить там, то она не дожна инициализироваться при пергрузке. int my_data @ "MY_DATA_IN_SEG" = 123; MY_DATA_IN_SEG - указать в списке для DATA16_N в lnk430F149.xcl Я сам это не проверял, но кажется в этом направлении. также префикс __no_init __no_init volatile unsigned __READ char U0RXBUF @ 0x0076; итд
|
|
|
|
|
Jan 22 2016, 03:07
|
Участник

Группа: Участник
Сообщений: 19
Регистрация: 2-04-15
Из: Железногорск
Пользователь №: 86 023

|
mcheb, k155la3 Спасибо за ваши ответы. Не вижу файла "lnk430F149.xcl" или подобного для моего МК. Есть только "lnk_msp430f2012.cmd", но содержимое его не похоже на то, что писали вы. Код MEMORY { SFR : origin = 0x0000, length = 0x0010 PERIPHERALS_8BIT : origin = 0x0010, length = 0x00F0 PERIPHERALS_16BIT : origin = 0x0100, length = 0x0100 RAM : origin = 0x0200, length = 0x0080 INFOA : origin = 0x10C0, length = 0x0040 INFOB : origin = 0x1080, length = 0x0040 INFOC : origin = 0x1040, length = 0x0040 INFOD : origin = 0x1000, length = 0x0040 FLASH : origin = 0xF800, length = 0x07E0 INT00 : origin = 0xFFE0, length = 0x0002 INT01 : origin = 0xFFE2, length = 0x0002 INT02 : origin = 0xFFE4, length = 0x0002 INT03 : origin = 0xFFE6, length = 0x0002 INT04 : origin = 0xFFE8, length = 0x0002 INT05 : origin = 0xFFEA, length = 0x0002 INT06 : origin = 0xFFEC, length = 0x0002 INT07 : origin = 0xFFEE, length = 0x0002 INT08 : origin = 0xFFF0, length = 0x0002 INT09 : origin = 0xFFF2, length = 0x0002 INT10 : origin = 0xFFF4, length = 0x0002 INT11 : origin = 0xFFF6, length = 0x0002 INT12 : origin = 0xFFF8, length = 0x0002 INT13 : origin = 0xFFFA, length = 0x0002 INT14 : origin = 0xFFFC, length = 0x0002 RESET : origin = 0xFFFE, length = 0x0002 }
/****************************************************************************/ /* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY */ /****************************************************************************/
SECTIONS { .bss : {} > RAM /* GLOBAL & STATIC VARS */ .data : {} > RAM /* GLOBAL & STATIC VARS */ .sysmem : {} > RAM /* DYNAMIC MEMORY ALLOCATION AREA */ .stack : {} > RAM (HIGH) /* SOFTWARE SYSTEM STACK */
.text : {} > FLASH /* CODE */ .cinit : {} > FLASH /* INITIALIZATION TABLES */ .const : {} > FLASH /* CONSTANT DATA */ .cio : {} > RAM /* C I/O BUFFER */
.pinit : {} > FLASH /* C++ CONSTRUCTOR TABLES */ .init_array : {} > FLASH /* C++ CONSTRUCTOR TABLES */ .mspabi.exidx : {} > FLASH /* C++ CONSTRUCTOR TABLES */ .mspabi.extab : {} > FLASH /* C++ CONSTRUCTOR TABLES */
.infoA : {} > INFOA /* MSP430 INFO FLASH MEMORY SEGMENTS */ .infoB : {} > INFOB .infoC : {} > INFOC .infoD : {} > INFOD
/* MSP430 INTERRUPT VECTORS */ .int00 : {} > INT00 .int01 : {} > INT01 PORT1 : { * ( .int02 ) } > INT02 type = VECT_INIT PORT2 : { * ( .int03 ) } > INT03 type = VECT_INIT USI : { * ( .int04 ) } > INT04 type = VECT_INIT ADC10 : { * ( .int05 ) } > INT05 type = VECT_INIT .int06 : {} > INT06 .int07 : {} > INT07 TIMERA1 : { * ( .int08 ) } > INT08 type = VECT_INIT TIMERA0 : { * ( .int09 ) } > INT09 type = VECT_INIT WDT : { * ( .int10 ) } > INT10 type = VECT_INIT .int11 : {} > INT11 .int12 : {} > INT12 .int13 : {} > INT13 NMI : { * ( .int14 ) } > INT14 type = VECT_INIT .reset : {} > RESET /* MSP430 RESET VECTOR */ }
|
|
|
|
|
Jan 22 2016, 08:35
|
Участник

Группа: Участник
Сообщений: 19
Регистрация: 2-04-15
Из: Железногорск
Пользователь №: 86 023

|
Цитата(Obam @ Jan 22 2016, 14:56)  Так вы бы сразу указали, что не IARом пользуетесь. А можете подсказать как в CCS решить эту проблему ?
|
|
|
|
|
Jan 22 2016, 10:50
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(ListenReality @ Jan 22 2016, 12:35)  А можете подсказать как в CCS решить эту проблему ? ps - это не есть проблема  В CCS не работал. Наверняка есть аналогичные ф-ии. Почитайте раздел помощи, нечто вроде "pragma directive" для CCS Там могут быть директивы - команды препроцессору компилятора, в каких сегментах размещать данную переменную или модуль в целом. Также - работа с абсолютными адресами. (например, вектора прерываний всегда размещаются по указанным абс. адресам) "Покурите" h-файлы CCS.
Сообщение отредактировал k155la3 - Jan 22 2016, 10:51
|
|
|
|
|
Jan 30 2016, 18:57
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(ListenReality @ Jan 21 2016, 12:47)  Но видимо я чего-то глубоко не понимаю. Если переменную не инициализировать, то в ней рандомное значение, которое нельзя никак изменить.
Вообще возможно ли это? Возможно - что? Кажется, вы каких-то чудес хотите - чтобы переменная не инициализировалась, но чтобы в ней не было рандомного значения. "Горячий лед", "сухая вода" ?
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jan 31 2016, 07:46
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(k155la3 @ Jan 21 2016, 20:39)  обратите внимание на сегмент DATA16_N. Если переменную разместить там, то она не дожна инициализироваться при пергрузке. Это конечно всё правильно, только прочитайте внимательнее что именно пишет ТС. А пишет он, что неинициализированные переменные у него после указанного сброса принимают рандомные значения. А теперь вопрос - какие именно секции линкер указывает как заполняемые рандомно при старте??? Я что-то не слышал о таком, чтобы стандартный стартап-код заполнял что-то рандомно. Обычно он обнуляет или не обнуляет (ну или максимум - заполняет неким шаблоном) секции. Так что сначала копать надо в сторону выяснения - откуда берутся эти рандомные значения? Стартап-код генерить их не должен.
|
|
|
|
|
Jan 31 2016, 09:51
|
Участник

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

|
В компиляторе IAR есть такая функция - int __low_level_init(void). Посмотрите, похоже, это ваш случай.
|
|
|
|
|
Jan 31 2016, 12:24
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(jcxz @ Jan 31 2016, 10:46)  Это конечно всё правильно, только прочитайте внимательнее что именно пишет ТС. А пишет он, что неинициализированные переменные у него после указанного сброса принимают рандомные значения. А теперь вопрос - какие именно секции линкер указывает как заполняемые рандомно при старте??? Я что-то не слышал о таком, чтобы стандартный стартап-код заполнял что-то рандомно. Обычно он обнуляет или не обнуляет (ну или максимум - заполняет неким шаблоном) секции. Так что сначала копать надо в сторону выяснения - откуда берутся эти рандомные значения? Стартап-код генерить их не должен.  нечто вроде RANDOM_INIT_SEGMENT Случайное значение попадает в SRAM процессора только при холодном старте (и то не факт). И при выходе из какогонибудь LPM5. Это значение может быть случайно-случайным или случайно-постоянным. В общем, эта тема для меня еще недостаточно раскурена. Буду прикручивать к проекту работу WD - тогда разберемся. (в RAM планирую сохранять данные причине сработки WDT и состоянии программы)
|
|
|
|
|
Feb 2 2016, 02:43
|
Участник

Группа: Участник
Сообщений: 19
Регистрация: 2-04-15
Из: Железногорск
Пользователь №: 86 023

|
Цитата(Dog Pawlowa @ Jan 31 2016, 01:57)  Возможно - что? Кажется, вы каких-то чудес хотите - чтобы переменная не инициализировалась, но чтобы в ней не было рандомного значения. "Горячий лед", "сухая вода" ? Вы видимо не правильно поняли. 1) Включение МК по питанию(сигнал POR и PUC) 2) Сброс МК по WatchDog(только сигнал PUC). Программа начинает выполняться с начала, но есть бит, который указывает, что мы сбросились именно по WatchDog. Код if((IFG1&WDTIFG)==WDTIFG)//сбросились по собаке { IFG1&=~WDTIFG;//обнуляем флаг countWatchDog++; } Поставлю вопрос тогда так. Где и как мне объявить переменную countWatchDog, чтобы: 1) Если включились по питанию, countWatchDog=0; 2) Если сброс по WatchDog, то countWatchDog++; По сути нужно посчитать кол-во сбросов по WatchDog. Пробовал: Объявлял переменную за функцией main по-разному: Код int countWatchDog; static int countWatchDog; При этом main выглядит примерно так: Код int main(void) { /*настройка сторожевого таймера*/ WDTCTL = WDTPW // ключ защиты + WDTCNTCL // Обнуляем таймер + WDTSSEL; // 0 - тактовый сигнал от SMCLK, 1 - ACLK IE1 = WDTIE;// разрешаем прерывания от сторожевого таймера
BCSCTL3 = LFXT1S_2;//задаем для ACLK источник тактирования VLO
if((IFG1&WDTIFG)!=WDTIFG)//по питанию { countWatchDog=0; } if((IFG1&WDTIFG)==WDTIFG)//сбросились по собаке { IFG1&=~WDTIFG;//обнуляем флаг countWatchDog++; } } При этом в случае, когда "int countWatchDog;" переменная всегда = 0 В случае, когда "static int countWatchDog;" переменная всегда равна 0х261. И в отладчике, после прохождения строчки "countWatchDog=0;" - значение переменной не меняется.
|
|
|
|
|
Feb 2 2016, 03:49
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(ListenReality @ Feb 2 2016, 08:43)  При этом в случае, когда "int countWatchDog;" переменная всегда = 0 Так и должно быть. Цитата(ListenReality @ Feb 2 2016, 08:43)  В случае, когда "static int countWatchDog;" переменная всегда равна 0х261. И в отладчике, после прохождения строчки "countWatchDog=0;" - значение переменной не меняется. Вот это странно. Должна быть ==0. А как Вы отладчиком подключаетесь? Он сброс на МК выставляет при подключении? Возможно, что он подключается на лету, без сброса, тогда переменная содержит значение, присвоенное её в ходе выполнения ПО. И вообще контролировать надо не отладчиком, а без него. Например - вывести значение переменной в UART при старте. Как правильно объявить переменную - Вам уже сказали. Как сделать это в Вашем компиляторе - не знаю, а в IAR например: static __root __no_init int var @ ".myNoInitSection"; Потом в командном файле компоновщика говорите компоновать секцию .myNoInitSection в отдельный регион памяти, который не надо инитить нулями. Цитата(ListenReality @ Jan 22 2016, 14:35)  А можете подсказать как в CCS решить эту проблему ? В CCS я делал так (это для ARM926 ядра), в файле .cmd: Код #define RAM_SDRAM_ARM_NC_RW_BEGIN 0xC0010000 #define RAM_SDRAM_ARM_NC_RW_LEN 0x000E0000
MEMORY { PAGE 0: //!<RAM ... RAM_SDRAM_ARM_NC_RW (RWX): o = RAM_SDRAM_ARM_NC_RW_BEGIN l = RAM_SDRAM_ARM_NC_RW_LEN //!<read-write noncached SDRAM is accessible only ARM }
SECTIONS { ... .mmuTTable > RAM_SDRAM_ARM_NC_RW, type = NOINIT } Это легко узнаётся из описания компоновщика CCS, если конечно хотя-бы попытаться его открыть и почитать...
|
|
|
|
|
Mar 10 2016, 03:43
|
Участник

Группа: Участник
Сообщений: 19
Регистрация: 2-04-15
Из: Железногорск
Пользователь №: 86 023

|
Спасибо всем за помощь. Впредь буду детальнее читать Help  На всякий случай оставлю пример. Программа считает количество WatchDog'ов Код #pragma NOINIT (x ); int x; int main(void) { /*настройка сторожевого таймера*/ WDTCTL = WDTPW // ключ защиты //+ WDTNMI // 0 - Вход аппаратного сброса, 1 - вход прервания //+ WDTTMSEL // 0 - режим сторожевого таймера, 1 - интервальный таймер + WDTCNTCL // Обнуляем таймер + WDTSSEL; // 0 - тактовый сигнал от SMCLK, 1 - ACLK //+ WDTIS0; //+ WDTIS1; IE1 = WDTIE;// разрешаем прерывания от сторожевого таймера
BCSCTL3 = LFXT1S_2;//задаем для ACLK источник тактирования VLO
DCOCTL = CALDCO_1MHZ; BCSCTL1 = CALBC1_1MHZ;
if((IFG1&WDTIFG)==WDTIFG)//сбросились по собаке { IFG1&=~WDTIFG;//обнуляем флаг x++; } else x=0; }
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|