nanorobot 3 8 апреля, 2018 Опубликовано 8 апреля, 2018 (изменено) · Жалоба CRC->CR = CRC_CR_RESET; // сбросим регистр данных CRC Engine for(i = 0; i < FRAME_SIZE - 1; i++) // цикл по всем словам данных, кроме последнего CRC->DR = TxData[i]; // вычисляем CRC TxData[i] = CRC->DR; // и заносим в последнее слово данных spiStartExchange(&SPID2, 12, TxData, RxData); Контрольная сумма вычисляется неверно (не совпадает с CRC на принимающей стороне, при одинаковых данных на обеих сторонах). Если поставить брекпоинт на любой из первых трех строчек, и прогнать по шагам, CRC вычисляется верно. Если брекпоинт поставить на 4 или 5 строке - CRC неверно. Запрещать прерывания нв время вычисления CRC пробовал - не помогло. CRC Engine используется только в одном Thread. P.S. TxData - uint32_t Изменено 8 апреля, 2018 пользователем nanorobot Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 8 апреля, 2018 Опубликовано 8 апреля, 2018 · Жалоба Если поставить брекпоинт на любой из первых трех строчек, и прогнать по шагам, CRC вычисляется верно. Если брекпоинт поставить на 4 или 5 строке - CRC неверно.Если непосредственно перед этим кодом включается тактирование модуля CRC, то после него надо вставить __DSB() - тактирование не успевает включиться и CRC->CR = CRC_CR_RESET не отрабатывается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nanorobot 3 8 апреля, 2018 Опубликовано 8 апреля, 2018 (изменено) · Жалоба Если непосредственно перед этим кодом включается тактирование модуля CRC, то после него надо вставить __DSB() - тактирование не успевает включиться и CRC->CR = CRC_CR_RESET не отрабатывается. Нет, тактирование включается модуля CRC значительно раньше. Тем не менее совет проверил - не помогло. __DSB() поставил после строки CRC->CR = CRC_CR_RESET - заработало! Спасибо за помощь. Жаль только, чт понимания не прибавилось. Не первый раз поьзуюсь расчетом CRC, в том числе и на STM32F401, но такая проблема первый раз. Изменено 8 апреля, 2018 пользователем nanorobot Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 14 8 апреля, 2018 Опубликовано 8 апреля, 2018 · Жалоба Что-то мне смутно припоминается, что после CRC->CR = CRC_CR_RESET надо 3 nop-а. (Как раз Сергей это и раскопал, кстати). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 9 апреля, 2018 Опубликовано 9 апреля, 2018 · Жалоба Что-то мне смутно припоминается, что после CRC->CR = CRC_CR_RESET надо 3 nop-а. (Как раз Сергей это и раскопал, кстати). Не, в тот раз мне понадобилось __DSB(); между включением тактирования и RESET. А дальше у меня ПДП настраивалось и этого времени, вероятно, хватало. А вот сегодня напаролся на такое (ARPE = 1): Timer->ARR = DELAY1_TICKS; // cache Timer->EGR = TIM_EGR_UG; // write cache to ARR Timer->ARR = DELAY2_TICKS; // cache Ожидаю прерывание через DELAY1_TICKS (ну плюс-минус), а получаю через DELAY2_TICKS. И пока методом тыка не сделал вот так, ничего не работало: Timer->ARR = DELAY1_TICKS; // cache Timer->EGR = TIM_EGR_UG; // write cache to ARR __DSB(); Timer->ARR = DELAY2_TICKS; // cache Кто-нибудь может это объяснить? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 14 9 апреля, 2018 Опубликовано 9 апреля, 2018 · Жалоба Не, в тот раз мне понадобилось __DSB(); между включением тактирования и RESET. А дальше у меня ПДП настраивалось и этого времени, вероятно, хватало. А, нашёл. Это дальше в той же теме было: Что-то мне подсказывает, что вот это computation done in 4 AHB clock cycles (HCLK) надо относить и к тому, когда CRC калькулятор будет готов принять данные не только после записи очередного байта, но и к тому, когда он будет готов после RESET. После этого я вставляю 3 нопа после сброса. Одного DSB может и не хватить. Кто-нибудь может это объяснить? Наверное то же самое, асинхронность таймера по отношению к CPU. Какой делитель у этого таймера? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 9 апреля, 2018 Опубликовано 9 апреля, 2018 · Жалоба Какой делитель у этого таймера?1:1, на шине тоже 1:1. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 14 9 апреля, 2018 Опубликовано 9 апреля, 2018 · Жалоба То есть, таймер работает на частоте CPU? Тогда совсем странно. Или всё же на половинной? Какой контроллер? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 10 апреля, 2018 Опубликовано 10 апреля, 2018 · Жалоба То есть, таймер работает на частоте CPU? Тогда совсем странно. Или всё же на половинной? Какой контроллер? F100, PPRE1 = 3, PPRE2 = 3, PSC = 0. Что-то мне эта версия кажется сомнительной, потому что в процессе инициализации я всегда пишу все регистры таймера подряд и никаких проблем никогда не было, да и таймер во время этой записи остановлен. Полный код сейчас выглядит так: Timer->CR1 = 0 | 0 * (TIM_CR1_CKD & -TIM_CR1_CKD) // Dead-time clock, 0 = /1, 1 = /2, 2 = /4 | 1 * TIM_CR1_ARPE // ARR buffering, 0 = not buffered, 1 = buffered | 0 * (TIM_CR1_CMS & -TIM_CR1_CMS) // 0 = unidirectional, 1 = up/down, OC flags set when counting up // 2 = up/down, OC flags set when counting down, 3 = up/down, OC flags set when counting up or down | 0 * TIM_CR1_DIR // 0 = up, 1 = down | 0 * TIM_CR1_OPM // 1 = stop at update event | 1 * TIM_CR1_URS // Update request source, 0 = any, 1 = only counter wrap | 0 * TIM_CR1_UDIS // Update event generation disable | 0 * TIM_CR1_CEN // Counter enable ; ....... Timer->ARR = DELAY1; // cache __DSB(); Timer->EGR = TIM_EGR_UG; // write cache to ARR __DSB(); Timer->ARR = DELAY2; // cache Timer->CR1 = 0 | 0 * (TIM_CR1_CKD & -TIM_CR1_CKD) // Dead-time clock, 0 = /1, 1 = /2, 2 = /4 | 1 * TIM_CR1_ARPE // ARR buffering, 0 = not buffered, 1 = buffered | 0 * (TIM_CR1_CMS & -TIM_CR1_CMS) // 0 = unidirectional, 1 = up/down, OC flags set when counting up // 2 = up/down, OC flags set when counting down, 3 = up/down, OC flags set when counting up or down | 0 * TIM_CR1_DIR // 0 = up, 1 = down | 0 * TIM_CR1_OPM // 1 = stop at update event | 1 * TIM_CR1_URS // Update request source, 0 = any, 1 = only counter wrap | 0 * TIM_CR1_UDIS // Update event generation disable | 1 * TIM_CR1_CEN // Counter enable ; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться