Jump to content
    

МК после сброса по WatchDog

Всем привет.

 

Проблема такая: Необходимо завести такую переменную, которая после сброса МК по WatchDog сохранит свое значение.

 

Пробовал через static. Но видимо я чего-то глубоко не понимаю. Если переменную не инициализировать, то в ней рандомное значение, которое нельзя никак изменить. (А писать static int i=0 глупо, т.к. оно каждый раз будет обнуляться).

 

Вообще возможно ли это? или МК после сброса по WatchDog затирает память?

Share this post


Link to post
Share on other sites

Компилятор по умолчанию при сбросе устанавливает указатель стека, обнуляет ОЗУ ( .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");
//}
//

Edited by mcheb

Share this post


Link to post
Share on other sites

Всем привет.

 

Проблема такая: Необходимо завести такую переменную, которая после сброса МК по 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;

итд

 

 

 

 

 

Share this post


Link to post
Share on other sites

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         */ 
}

Share this post


Link to post
Share on other sites

Так вы бы сразу указали, что не IARом пользуетесь.

 

А можете подсказать как в CCS решить эту проблему ?

Share this post


Link to post
Share on other sites

А можете подсказать как в CCS решить эту проблему ?

 

ps - это не есть проблема :)

 

В CCS не работал. Наверняка есть аналогичные ф-ии.

Почитайте раздел помощи, нечто вроде "pragma directive" для CCS

Там могут быть директивы - команды препроцессору компилятора, в каких сегментах

размещать данную переменную или модуль в целом.

Также - работа с абсолютными адресами.

(например, вектора прерываний всегда размещаются по указанным абс. адресам)

"Покурите" h-файлы CCS.

Edited by k155la3

Share this post


Link to post
Share on other sites

Но видимо я чего-то глубоко не понимаю. Если переменную не инициализировать, то в ней рандомное значение, которое нельзя никак изменить.

 

Вообще возможно ли это?

Возможно - что?

Кажется, вы каких-то чудес хотите - чтобы переменная не инициализировалась, но чтобы в ней не было рандомного значения.

"Горячий лед", "сухая вода" ?

Share this post


Link to post
Share on other sites

обратите внимание на сегмент DATA16_N.

Если переменную разместить там, то она не дожна инициализироваться при пергрузке.

Это конечно всё правильно, только прочитайте внимательнее что именно пишет ТС. А пишет он, что неинициализированные переменные у него после указанного сброса принимают рандомные значения.

А теперь вопрос - какие именно секции линкер указывает как заполняемые рандомно при старте???

Я что-то не слышал о таком, чтобы стандартный стартап-код заполнял что-то рандомно. Обычно он обнуляет или не обнуляет (ну или максимум - заполняет неким шаблоном) секции.

Так что сначала копать надо в сторону выяснения - откуда берутся эти рандомные значения? Стартап-код генерить их не должен.

Share this post


Link to post
Share on other sites

В компиляторе IAR есть такая функция - int __low_level_init(void). Посмотрите, похоже, это ваш случай.

Share this post


Link to post
Share on other sites

Это конечно всё правильно, только прочитайте внимательнее что именно пишет ТС. А пишет он, что неинициализированные переменные у него после указанного сброса принимают рандомные значения.

А теперь вопрос - какие именно секции линкер указывает как заполняемые рандомно при старте???

Я что-то не слышал о таком, чтобы стандартный стартап-код заполнял что-то рандомно. Обычно он обнуляет или не обнуляет (ну или максимум - заполняет неким шаблоном) секции.

Так что сначала копать надо в сторону выяснения - откуда берутся эти рандомные значения? Стартап-код генерить их не должен.

 

:) нечто вроде RANDOM_INIT_SEGMENT

Случайное значение попадает в SRAM процессора только при холодном старте (и то не факт). И при выходе из какогонибудь LPM5.

Это значение может быть случайно-случайным или случайно-постоянным.

В общем, эта тема для меня еще недостаточно раскурена. Буду прикручивать к проекту работу WD - тогда разберемся.

(в RAM планирую сохранять данные причине сработки WDT и состоянии программы)

 

Share this post


Link to post
Share on other sites

Случайное значение попадает в SRAM процессора только при холодном старте (и то не факт). И при выходе из какогонибудь LPM5.

Это понятно. Но раз ТС пишет, что у него переменная принимает случайное значение, то советы перенести её в неинициализируемую секцию излишни - она и так уже там.

Ну только если она не находится в какой-то спец.секции рандомно инициализируемой. :)

Share this post


Link to post
Share on other sites

Возможно - что?

Кажется, вы каких-то чудес хотите - чтобы переменная не инициализировалась, но чтобы в ней не было рандомного значения.

"Горячий лед", "сухая вода" ?

 

Вы видимо не правильно поняли.

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;" - значение переменной не меняется.

Share this post


Link to post
Share on other sites

При этом в случае, когда "int countWatchDog;" переменная всегда = 0
Так и должно быть.

В случае, когда "static int countWatchDog;" переменная всегда равна 0х261. И в отладчике, после прохождения строчки "countWatchDog=0;" - значение переменной не меняется.
Вот это странно. Должна быть ==0.

А как Вы отладчиком подключаетесь? Он сброс на МК выставляет при подключении? Возможно, что он подключается на лету, без сброса, тогда переменная содержит значение, присвоенное её в ходе выполнения ПО.

И вообще контролировать надо не отладчиком, а без него. Например - вывести значение переменной в UART при старте.

 

Как правильно объявить переменную - Вам уже сказали. Как сделать это в Вашем компиляторе - не знаю, а в IAR например:

static __root __no_init int var @ ".myNoInitSection";

Потом в командном файле компоновщика говорите компоновать секцию .myNoInitSection в отдельный регион памяти, который не надо инитить нулями.

 

А можете подсказать как в 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, если конечно хотя-бы попытаться его открыть и почитать...

Share this post


Link to post
Share on other sites

Спасибо всем за помощь. Впредь буду детальнее читать Help :blush:

 

На всякий случай оставлю пример. Программа считает количество 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;
}

 

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...