SergeyB 0 5 января, 2014 Опубликовано 5 января, 2014 · Жалоба Разбираюсь с проектом 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; } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 5 января, 2014 Опубликовано 5 января, 2014 · Жалоба ИМХО по поводу функции bsp_get_sys_uptime лучше бы читать только три первых переменных и если секунды отличаются, то миллисекунды обнулять. Возвращать ессно последние прочитанные секунды. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 5 января, 2014 Опубликовано 5 января, 2014 · Жалоба вы этой функцией получаете текущее значение секунд и миллисекунд делаете это не выключая прерывания. у вас между строчкой где вы сохраняете секунды и строчкой где вы сохраняете миллисекунды может произойти прерывание, и все испортить к примеру у вас 1 секунда и 999 мсек вы сохраняете значение 1 секунда ------------- происходит прерывание 1сек становиться 2 999 мсек - становится 0 м сек вы возвращаетесь обратно ------------- сохраняете миллисекунды 0 и вместо 2 сек 0 мсек имеете 1 сек (ее вы сохранили до прерывания) и 0 мсек (вы их сохранили после), то есть на 1 секунду меньше с этой же функцией если будет перекрут миллисекунд который вы пропустили, то сработает условие и число секунд увеличится... ИМХО по поводу функции bsp_get_sys_uptime лучше бы читать только три первых переменных и если секунды отличаются, то миллисекунды обнулять. Возвращать ессно последние прочитанные секунды. Не поможет если любая переменная читается не за 1 команду и изменяется в прерывании, то для работы с ней ОБЯЗАТЕЛЬНО надо запрещать прерывание или быть готовым к получению некорректных данных. Потому что во время ее чтения она может быть изменена, и часть переменной будет новой, а часть старой. тут фактически это и есть, переменная состоит из 2 частей секунду и миллисекунды. Считать ее за 1 такт нет возможности, это 2 значения. Эта переменная меняется в прерывании, значит надо либо его запретить, либо быть готовым что пока вы читаете переменную она может измениться, и часть переменной будет старая, а часть новая. Автор запрещать прерывание не стал, (не понятно почему, ведь ничего не теряется, все отработается через 1, 2 такта, возможно есть еще и другие прерывание более критичные чем от системного таймера), поэтому придумал как поправить некорректные данные. Можно было считать параметры 3 раза, и выбрать пару совпадающих. При повреждении 1 совпали 2 и 3, при повреждении 3 совпали бы 1 и 2, при повреждении 2, все были бы разными, во всех 3 случаях есть верная не поврежденная переменная... при изменении между переменными, опять же были бы совпадения 1 со 2 или 2 с 3. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergeyB 0 5 января, 2014 Опубликовано 5 января, 2014 · Жалоба спасибо за разъяснение, все понятно. в принципе зачем она нужна было понятно. мозг у меня застопорился на моменте, как вы описали ------------- происходит прерывание 1сек становиться 2 999 мсек - становится 0 м сек вы возвращаетесь обратно ------------- сохраняете миллисекунды 0 пора отдыхать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kolobok0 0 5 января, 2014 Опубликовано 5 января, 2014 · Жалоба ...ОБЯЗАТЕЛЬНО надо запрещать прерывание или быть готовым к получению некорректных данных. ....Можно было считать параметры 3 раза, и выбрать пару совпадающих.... Для корректного считывания двухбайтной временной переменной, без блокирования прерываний, делается 3 чтения. старшая часть, младшая часть, старшая часть. Далее сравниваются старшие части, и если они не равны - то берётся последнее считывание и младшая часть обнуляется. данный приём стар как мир. применяется на камнях не имеющих блокировки прерываний. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 5 января, 2014 Опубликовано 5 января, 2014 · Жалоба Для корректного считывания двухбайтной временной переменной, без блокирования прерываний, делается 3 чтения. старшая часть, младшая часть, старшая часть. Далее сравниваются старшие части, и если они не равны - то берётся последнее считывание и младшая часть обнуляется. данный приём стар как мир. применяется на камнях не имеющих блокировки прерываний. ну конечно же так нельзя, это верно только для счетчиков, да и то для тех что считают по 1. а если это экзотически 16 битный float? а если это дата, где младшая часть дни не имеет 0? в частном случае вы правы, в общем нет%) пример. счетчик старшая часть 1, младшая 95 считает по 10 каждое прерывание читаем старшую часть = 1 --- прерывание, счетчик становится 2 05 читаем младшую часть = 05 читаем старшую часть = 2 2 не равно 1, обнуляем младшую часть и получаем 2.00, вместо 1.95 или 2.05 - может в старом мире проканало бы, но в моем новом я говорю нее:) если кто-то перестроит системный таймер на инкремент по 100 мСек, или по 10, то такой подход опять же будет давать не совсем верные результаты... а если считать интервалы, ошибочка может и накопиться.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 5 января, 2014 Опубликовано 5 января, 2014 (изменено) · Жалоба Добавлю. 1. Переменные-счётчики секунд и мсек должны быть ессно волатильными. 2. Если бы считанные значения времени использовались для алгоритмов ЦОС (что такое DMX512/RDM - не знаю в деталях), то можно было бы и четвёртую переменную считывать из начального примера. Тогда если секунды не совпадают, то в качестве миллисекунд брать последние (вместо ранее предложеного обнуления), а если секунды совпадают, то брать ранее прочитанные. Это при сохранении исходной последовательности чтения переменных. 3. Непонятно, зачем в заголовке темы указание на LPC111x. Изменено 6 января, 2014 пользователем GetSmart Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 5 января, 2014 Опубликовано 5 января, 2014 · Жалоба 1. Это даже не обсуждается;) 2. Опять не так время 1 - 999 считали 1, потом 999, потом 1, прерывание (становится 2 - 0), считали 0 секунды совпадают, берем меньшие миллисекунды получаем 1 - 0, не верно. Если миллисекунды изменяются только на 1,то ваш алгоритм первоначальный с 3 чтениями подходит, если миллисекунды меняются на заданный интервал отличный от 1, или в обратную сторону, то надо 4 считывания и проверку как у ТС в примере. 3. да это и не важно%) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 6 января, 2014 Опубликовано 6 января, 2014 (изменено) · Жалоба Если миллисекунды изменяются только на 1,то ваш алгоритм первоначальный с 3 чтениями подходит, если миллисекунды меняются на заданный интервал отличный от 1, или в обратную сторону, то надо 4 считывания и проверку как у ТС в примере. Второй вариант подходит для любых шагов инкремента миллисекунд. С симметричным распределением джиттера, если это важно дальнейшему алгоритму. В обратную сторону чтобы счётчики изменялись - даже не рассматривается, т.к. не обоснована необходимость. Изменено 6 января, 2014 пользователем GetSmart Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 6 января, 2014 Опубликовано 6 января, 2014 (изменено) · Жалоба 2. Опять не так Исправил. Реальный чёрт слегка попутал. Показалось, что мсек считываются раньше секунд. Причём это резко "показалось" именно для второго варианта условия во второй версии :) Вместо джиттера лучше наверное сказать - распределение миллисекунд более равномерное. Изменено 7 января, 2014 пользователем GetSmart Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться