Перейти к содержанию
    

Имеется 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 доступен.

Спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нужно убедиться, что 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.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 минут назад, Dron_Gus сказал:

Если бы он останавливался сразу - было бы хотя бы понятно, что ошибка где-то в коде работы с флешкой. А тут скорее сочетание факторов.

Меня это тоже сначала смутило, но вы пишите, что приоритет задачи низкий. У вас прерывания срабатывают с частотой порядка 20 кГц - может из-за этого потоку стирания совсем времени не достается.

Стирание - процесс долгий. Если проверку BSY совместить с delay на 10 мс, а приоритет поднять на максимум, то как изменится поведение?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 облась есть в линкер файле. Видимо, надо внимательно разобраться, не кладет ли линкер туда что-то.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проверил - все нормально работает. Правда, на 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.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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. Возможно какой-то из кэшей/акселераторов пытается забить себе кеши и обращается к этой области. Как это отловить - не представляю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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;
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 кэши на время стирания. Надо попробовать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Отключение кэшей усугубило проблему. Теперь сталится почти сразу после запуска стирания. Но не сразу.

Видимо стоит отложить эту проблему и поднять таки QSPI + NOR flash и на этом успокоиться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 минуты назад, Dron_Gus сказал:

Отключение кэшей усугубило проблему.

Это означает, что вы приблизились к решению проблемы :))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

20 minutes ago, adnega said:

Это означает, что вы приблизились к решению проблемы :))

Пока не понимаю, какие выводы из этой вводной можно сделать. Что без кэшей процессор раньше образается к этому банку флеза за данными/кодом. Так не должен же.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

41 минуту назад, Dron_Gus сказал:

Пока не понимаю, какие выводы из этой вводной можно сделать. Что без кэшей процессор раньше образается к этому банку флеза за данными/кодом. Так не должен же.

Значит у вас есть обращение к этому банку во время стирания. Просто раньше данные брались из кэша и не так часто проблема проявлялась.

А если MPU настроить для этого банка на время стирания? Так можно отловить виновника.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 minute ago, adnega said:

Значит у вас есть обращение к этому банку во время стирания. Просто раньше данные брались из кэша и не так часто проблема проявлялась.

А если MPU настроить для этого банка на время стирания? Так можно отловить виновника.

Уже. https://github.com/dron0gus/rusefi/blob/board-subaru-eg33-dev/firmware/main.cpp#L50 . Не отлавливается. Настройки верные, проверил тестовым образщением - ловит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, Dron_Gus сказал:

Уже. https://github.com/dron0gus/rusefi/blob/board-subaru-eg33-dev/firmware/main.cpp#L50 . Не отлавливается. Настройки верные, проверил тестовым образщением - ловит.

Ну, теперь с отключенным кэшем может что и поймает...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...