Dron_Gus 2 31 июля, 2021 Опубликовано 31 июля, 2021 · Жалоба Имеется STM32F765 c 2Мб флешки. Флешка в двухбанковом режме. Согласно документации - можно беспроблемно стирать/писать в один банк пока код исполняется из другого. Пытаюсь это сделать. Все это под ChibiOS. Запись во флеш из низкоприоритетного треда. Никаких прерываний, тупой полинг. С завидной периодичностью (>90%) процессор останавливается в процессе стирания страницы. После стирания продолжает исполнение. Прикрутил к ChibiOS'овскому трейсингу счетчик событий и начал смотреть на количество переключений контекста и обработанных прерываний на разных этапах работы с флешкой. Хорошая ситуация: [2072335144]13 intFlashSectorErase:194 +053766068 ( 320 mS): sw 684, irq 6510 320 мС на стирание одной страницы, в это время случлось 684 переключения контекста, и 6510 прерываний. (Очень) Плохая ситуация: [3225204673]05 intFlashSectorErase:194 +053656865 ( 319 mS): sw 18, irq 199 Чаше - что-то среднее. Т.е. процессор не сразу останавливается. Логично предположив, что кто-то лезет в стираемый банк. Разобрался и настроил MPU: для начала запретил доступ ко всему второму банку. Ожидаемо получил MemoryFault от функции записи флешки. Закоментировал непосредственную запись по адресам флешки. И тишина, код работает, проц фризится. Почитал документацию, предположил, что возможно и в FLASH Option Bytes нельзя лезть в процессе работы с флешкой. Запретил доступ и туда. И снова тишина. Т.е. как минимум процессор туда не лезет. DMA и другие мастера тоже не должны туда лезть. Два вопроса: 1. видел кто что подобное? 2. какой еще инструментарий можно применить? Jtag доступен. Спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 31 июля, 2021 Опубликовано 31 июля, 2021 · Жалоба Нужно убедиться, что nDBANK=0. По умолчанию этот бит взведен. Установить соответствующий барьер при стирании: Цитата When setting the STRT bit in the FLASH_CR register and before polling the BSY bit to be cleared, the software can issue a DSB instruction to guarantee the completion of a previous access to FLASH_CR register. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dron_Gus 2 31 июля, 2021 Опубликовано 31 июля, 2021 · Жалоба 6 minutes ago, adnega said: Нужно убедиться, что nDBANK=0. По умолчанию этот бит взведен. Установить соответствующий барьер при стирании: Бит точно сброшен. Да, на чистом чипе он стоял. Пришлось воспользоваться https://github.com/danielinux/stm32f7-dualbank-tool Барьер тоже присутствует #define intFlashWaitWhileBusy() do { __DSB(); } while (FLASH->SR & FLASH_SR_BSY); CPU останавливается в случайный момент, когда идет стирание страницы. Если бы он останавливался сразу - было бы хотя бы понятно, что ошибка где-то в коде работы с флешкой. А тут скорее сочетание факторов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 31 июля, 2021 Опубликовано 31 июля, 2021 · Жалоба 8 минут назад, Dron_Gus сказал: Если бы он останавливался сразу - было бы хотя бы понятно, что ошибка где-то в коде работы с флешкой. А тут скорее сочетание факторов. Меня это тоже сначала смутило, но вы пишите, что приоритет задачи низкий. У вас прерывания срабатывают с частотой порядка 20 кГц - может из-за этого потоку стирания совсем времени не достается. Стирание - процесс долгий. Если проверку BSY совместить с delay на 10 мс, а приоритет поднять на максимум, то как изменится поведение? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dron_Gus 2 31 июля, 2021 Опубликовано 31 июля, 2021 · Жалоба 33 minutes ago, adnega said: Меня это тоже сначала смутило, но вы пишите, что приоритет задачи низкий. У вас прерывания срабатывают с частотой порядка 20 кГц - может из-за этого потоку стирания совсем времени не достается. Стирание - процесс долгий. Если проверку BSY совместить с delay на 10 мс, а приоритет поднять на максимум, то как изменится поведение? Попробую. Но есть опасение, что добавление задержки просто замаскирует проблему. Тем временем мне показали вот этот вопрос https://community.st.com/s/question/0D50X00009XkXpA/stm32f7-dual-bank-flash-erase-stall на форуме ST. К сожалению без ответа. Попытка отключить ITCM в лоб SCB->ITCMCR = 0 Приводит к HardFault из случайного места, но опять же только когда запущенно стирание. ITCM облась есть в линкер файле. Видимо, надо внимательно разобраться, не кладет ли линкер туда что-то. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 31 июля, 2021 Опубликовано 31 июля, 2021 · Жалоба Проверил - все нормально работает. Правда, на F767ZI с 2МБ. Одна задача мигает диодиком с периодом 200 мс. В однобанковом режиме при стирании сектора светодиодик перестает мигать. В двухбанковом режиме - мигание не останавливается. void StartDefaultTask(void *argument) { for(;;) { HAL_GPIO_WritePin(GPIOB, LD2_Pin, GPIO_PIN_SET); osDelay(100); HAL_GPIO_WritePin(GPIOB, LD2_Pin, GPIO_PIN_RESET); osDelay(100); } } void StartTaskErase(void *argument) { FLASH_EraseInitTypeDef erase; uint32_t SectorError; while(HAL_GPIO_ReadPin(USER_Btn_GPIO_Port, USER_Btn_Pin) == GPIO_PIN_RESET); printf("wr0 %08X\r\n", *(int *)(0x081E0000)); HAL_FLASH_Unlock(); HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x081E0000, 0); HAL_GPIO_WritePin(GPIOB, LD3_Pin, GPIO_PIN_SET); printf("wr1 %08X\r\n", *(int *)(0x081E0000)); TIM2->CR1 = 0; TIM2->ARR = 0xFFFFFFFF; TIM2->PSC = 0; TIM2->EGR = TIM_EGR_UG; TIM2->CNT = 0; TIM2->CR1 = TIM_CR1_CEN; erase.Banks = FLASH_BANK_2; erase.NbSectors = 1; erase.Sector = FLASH_SECTOR_23; erase.TypeErase = FLASH_TYPEERASE_SECTORS; erase.VoltageRange = FLASH_VOLTAGE_RANGE_3; HAL_FLASHEx_Erase(&erase, &SectorError); TIM2->CR1 = 0; printf("wr2 %08X\r\n", *(int *)(0x081E0000)); printf("Test %d, %d\r\n", (int)TIM2->CNT, (int)SectorError); for(;;) { HAL_GPIO_WritePin(GPIOB, LD3_Pin, GPIO_PIN_SET); osDelay(100); HAL_GPIO_WritePin(GPIOB, LD3_Pin, GPIO_PIN_RESET); osDelay(100); } } Сначала две попытки в однобанковом режиме, затем две в двухбанковом (частота TIM2 96МГц, запись порядка 1 секунды) Цитата wr0 FFFFFFFF wr1 00000000 wr2 FFFFFFFF Test 99231568, -1 wr0 FFFFFFFF wr1 00000000 wr2 FFFFFFFF Test 99390292, -1 wr0 FFFFFFFF wr1 00000000 wr2 FFFFFFFF Test 98076188, -1 wr0 FFFFFFFF wr1 00000000 wr2 FFFFFFFF Test 99128786, -1 И ОСь FreeRTOS. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dron_Gus 2 1 августа, 2021 Опубликовано 1 августа, 2021 · Жалоба 9 hours ago, adnega said: Проверил - все нормально работает. Правда, на F767ZI с 2МБ. Большое спасибо, что потратили свое время и проверили. Видимо не при любых условиях эти грабли всплывают. У меня тоже это происходит только при "естественном" выполнении. Попытался дергать тот же код по команде из дебажной консоли - работает, зараза. На всякий случай, наш спагетти-код https://github.com/dron0gus/rusefi/blob/board-subaru-eg33-dev/firmware/hw_layer/ports/stm32/flash_int.c Но я уже его насквозь проглядел, ничего странного не вижу. Продолжу ковырять в сторону ITCM. Возможно какой-то из кэшей/акселераторов пытается забить себе кеши и обращается к этой области. Как это отловить - не представляю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 1 августа, 2021 Опубликовано 1 августа, 2021 · Жалоба 13 минут назад, Dron_Gus сказал: Продолжу ковырять в сторону ITCM. Возможно какой-то из кэшей/акселераторов пытается забить себе кеши и обращается к этой области. Как это отловить - не представляю. У вас в стираемом банке память под данные или под код тоже? С кешем данных не останавливается, но и после стирания данные берутся из кеша (в моем случае 0x00000000), а не меняются на 0xFFFFFFFF. Можно попробовать код разместить во втором банке, выполнить его, чтоб он закешировался, а потом стереть - это не пробовал. Подозрительно: проверка nDBANK выключена static bool isDualBank(void) { // cleared bit indicates dual bank //return (FLASH->OPTCR & FLASH_OPTCR_nDBANK) == 0; return true; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dron_Gus 2 1 августа, 2021 Опубликовано 1 августа, 2021 · Жалоба 31 minutes ago, adnega said: У вас в стираемом банке память под данные или под код тоже? С кешем данных не останавливается, но и после стирания данные берутся из кеша (в моем случае 0x00000000), а не меняются на 0xFFFFFFFF. Можно попробовать код разместить во втором банке, выполнить его, чтоб он закешировался, а потом стереть - это не пробовал. Подозрительно: проверка nDBANK выключена Проверка nDBANK выключена парой комитов раньше, от безисходности. :) https://github.com/dron0gus/rusefi/commit/95a27a4363abe7629f10120f992269801384afcc#diff-10e65bab0eab4058dfb569de13b7a4c214449c497aeda04b3d88b4808346dfd7 В DS есть такой коментарий про FLASH_OPTCR/FLASH_OPTCR1: Access: no wait state when no Flash memory operation is ongoing, word, half-word and byte access. Хотя эта функция вроде и не должна вызываться в процессе записи, все решил подстраховаться. Да, во втором банке только данные. Туда сохраняются настройки в процессе работы. Читаются оттуда однократно при старте, потом работа идет с копией в ОЗУ. Кстати, еще не пробовал отключать I/D кэши на время стирания. Надо попробовать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dron_Gus 2 2 августа, 2021 Опубликовано 2 августа, 2021 · Жалоба Отключение кэшей усугубило проблему. Теперь сталится почти сразу после запуска стирания. Но не сразу. Видимо стоит отложить эту проблему и поднять таки QSPI + NOR flash и на этом успокоиться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 2 августа, 2021 Опубликовано 2 августа, 2021 · Жалоба 2 минуты назад, Dron_Gus сказал: Отключение кэшей усугубило проблему. Это означает, что вы приблизились к решению проблемы :)) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dron_Gus 2 2 августа, 2021 Опубликовано 2 августа, 2021 · Жалоба 20 minutes ago, adnega said: Это означает, что вы приблизились к решению проблемы :)) Пока не понимаю, какие выводы из этой вводной можно сделать. Что без кэшей процессор раньше образается к этому банку флеза за данными/кодом. Так не должен же. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 2 августа, 2021 Опубликовано 2 августа, 2021 · Жалоба 41 минуту назад, Dron_Gus сказал: Пока не понимаю, какие выводы из этой вводной можно сделать. Что без кэшей процессор раньше образается к этому банку флеза за данными/кодом. Так не должен же. Значит у вас есть обращение к этому банку во время стирания. Просто раньше данные брались из кэша и не так часто проблема проявлялась. А если MPU настроить для этого банка на время стирания? Так можно отловить виновника. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dron_Gus 2 2 августа, 2021 Опубликовано 2 августа, 2021 · Жалоба 1 minute ago, adnega said: Значит у вас есть обращение к этому банку во время стирания. Просто раньше данные брались из кэша и не так часто проблема проявлялась. А если MPU настроить для этого банка на время стирания? Так можно отловить виновника. Уже. https://github.com/dron0gus/rusefi/blob/board-subaru-eg33-dev/firmware/main.cpp#L50 . Не отлавливается. Настройки верные, проверил тестовым образщением - ловит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 2 августа, 2021 Опубликовано 2 августа, 2021 · Жалоба 1 минуту назад, Dron_Gus сказал: Уже. https://github.com/dron0gus/rusefi/blob/board-subaru-eg33-dev/firmware/main.cpp#L50 . Не отлавливается. Настройки верные, проверил тестовым образщением - ловит. Ну, теперь с отключенным кэшем может что и поймает... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться