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

 
 
> Подскажите по хитрой функции работы с таймерами в lcp111x
Сергей Б
сообщение Jan 5 2014, 12:06
Сообщение #1


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

Группа: Свой
Сообщений: 80
Регистрация: 14-04-06
Из: Russia, Orel
Пользователь №: 16 115



Разбираюсь с проектом DMX512/RDM
Заинтересовала функция работы с таймером

Код
void bsp_get_sys_uptime(uint32_t *psec_cnt, uint16_t *pmsec_cnt)
{
    // we do not want to disable the systick interrupt, so we have to deal
    // with a systick during the execution of this function
    uint32_t sec_cnt_1  = sys_seconds_cnt;
    uint16_t msec_cnt_1 = sys_millisec_cnt;
    uint32_t sec_cnt_2  = sys_seconds_cnt;
    uint16_t msec_cnt_2 = sys_millisec_cnt;
    if ((sec_cnt_1 == sec_cnt_2) && (msec_cnt_2 < msec_cnt_1))
    {
        sec_cnt_2 += 1;
    }
    *psec_cnt  = sec_cnt_2;
    *pmsec_cnt = msec_cnt_2;
}


переменные sys_seconds_cnt и sys_millisec_cnt инкрементируются в SysTick прерывании.
Зачем нужна такая функция?

Предположим,
если сработало прерывание во время инициализации локальных переменных, то увеличить счетчик секунд?
не совсем понимаю назначение, подскажите может кто встречал такие варианты.

код перывания
Код
void TickHandler(void)
{
    uint32_t i;
    uint32_t millisec_increment = 1000 / SYS_TICK_RATE_HZ;

    sys_millisec_cnt += millisec_increment;
    if (sys_millisec_cnt >= 1000)
    {
        sys_millisec_cnt -= 1000;
        sys_seconds_cnt++;
    }
    for (i=0; i<NR_OF_MSEC_COUNTERS; i++)
    {
        app_millisec_cnt[i] += millisec_increment;
    }
}

Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Golikov A.
сообщение Jan 5 2014, 14:02
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



вы этой функцией получаете текущее значение секунд и миллисекунд

делаете это не выключая прерывания.

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

к примеру у вас 1 секунда и 999 мсек
вы сохраняете значение 1 секунда
-------------
происходит прерывание
1сек становиться 2
999 мсек - становится 0 м сек
вы возвращаетесь обратно
-------------
сохраняете миллисекунды 0

и вместо 2 сек 0 мсек имеете
1 сек (ее вы сохранили до прерывания) и 0 мсек (вы их сохранили после), то есть на 1 секунду меньше


с этой же функцией если будет перекрут миллисекунд который вы пропустили, то сработает условие и число секунд увеличится...

Цитата(GetSmart @ Jan 5 2014, 17:51) *
ИМХО по поводу функции bsp_get_sys_uptime лучше бы читать только три первых переменных и если секунды отличаются, то миллисекунды обнулять. Возвращать ессно последние прочитанные секунды.


Не поможет
если любая переменная читается не за 1 команду и изменяется в прерывании, то для работы с ней ОБЯЗАТЕЛЬНО надо запрещать прерывание или быть готовым к получению некорректных данных. Потому что во время ее чтения она может быть изменена, и часть переменной будет новой, а часть старой.

тут фактически это и есть, переменная состоит из 2 частей секунду и миллисекунды. Считать ее за 1 такт нет возможности, это 2 значения. Эта переменная меняется в прерывании, значит надо либо его запретить, либо быть готовым что пока вы читаете переменную она может измениться, и часть переменной будет старая, а часть новая.

Автор запрещать прерывание не стал, (не понятно почему, ведь ничего не теряется, все отработается через 1, 2 такта, возможно есть еще и другие прерывание более критичные чем от системного таймера), поэтому придумал как поправить некорректные данные.

Можно было считать параметры 3 раза, и выбрать пару совпадающих. При повреждении 1 совпали 2 и 3, при повреждении 3 совпали бы 1 и 2, при повреждении 2, все были бы разными, во всех 3 случаях есть верная не поврежденная переменная...
при изменении между переменными, опять же были бы совпадения 1 со 2 или 2 с 3.
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Jan 5 2014, 14:30
Сообщение #3


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(Golikov A. @ Jan 5 2014, 18:02) *
...ОБЯЗАТЕЛЬНО надо запрещать прерывание или быть готовым к получению некорректных данных.
....Можно было считать параметры 3 раза, и выбрать пару совпадающих....


Для корректного считывания двухбайтной временной переменной, без блокирования прерываний, делается 3 чтения.
старшая часть, младшая часть, старшая часть.
Далее сравниваются старшие части, и если они не равны - то берётся последнее считывание и младшая часть обнуляется.

данный приём стар как мир. применяется на камнях не имеющих блокировки прерываний.
Go to the top of the page
 
+Quote Post



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

 


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


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