Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.69/29: Рейтинг темы: голосов - 29, средняя оценка - 4.69
31 / 30 / 4
Регистрация: 22.03.2010
Сообщений: 126
1

Stm32F4 USB MSD internal flash

24.12.2018, 18:03. Показов 5451. Ответов 22

Author24 — интернет-сервис помощи студентам
Всем привет.
Уже несколько дней борюсь с кодом и не вижу где ошибка.

В наличии плата stm32F429I-DiSCO. Пытаюсь на этой плате контроллер сконфигурировать как USB Devise класс MSC. Хочу записывать данные с хоста во внутреннюю flash с адреса 0x08020000 ( Из даташита: Sector 5 0x08020000 - 0x0803 FFFF 128 Kbytes). Конечно, перед записью я очищаю сектор 5 и отладчиком вижу по этому адресу 0xFF. Когда подключаю к компу то Host видит подключение и предлагает отформатировать Flash. Я соглашаюсь, и вот тут - то начинаются странности. Операция записи не работает, то есть под отладчиком я вижу, что начинаю с адреса 0x08020000 располагается что угодно, но не таблица FAT. Ок, далее я решил облегчить себе задачу и заменил flash на RAM. C RAM все работает, форматирование проходит успешно. Ок, решил сделать так. Принятый от хоста пакет перед тем как записать в RAM пишу во flash (так сказать дублирую его). Смотрю отладчиком данные во flash и RAM не совпадают. Вот код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int8_t STORAGE_Write_HS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 14 */
  uint32_t j;
  uint16_t i;
    uint8_t k;
fBusy = 1;
  switch(lun){
    case 0 :
             HAL_FLASH_Unlock();
             for(i = 0; i < blk_len * STORAGE_BLK_SIZ; i++){
               HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, 0x08020000 + blk_addr * STORAGE_BLK_SIZ + i, buf[i]);
//               HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, 0x08020000 + blk_addr * STORAGE_BLK_SIZ + i, i);
                             usb_buf[blk_addr * STORAGE_BLK_SIZ + i] = buf[i];
             }
             HAL_FLASH_Lock();
             break;
 
    case 1 : break;
    default: fBusy = 0;
             return (USBD_FAIL);
  }
  fBusy = 0;
  return (USBD_OK);
  /* USER CODE END 14 */
}
А вот скриншет отладчика для RAM и flash. Видно, что данные во flash неправильные.
Stm32F4 USB MSD internal flash

Stm32F4 USB MSD internal flash



Хорошо пытаюсь писать во flas не содержимое массива, а индекс массива, т. е. просто счетчик. И меняю код на такой:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int8_t STORAGE_Write_HS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 14 */
  uint32_t j;
  uint16_t i;
    uint8_t k;
fBusy = 1;
  switch(lun){
    case 0 :
             HAL_FLASH_Unlock();
             for(i = 0; i < blk_len * STORAGE_BLK_SIZ; i++){
//               HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, 0x08020000 + blk_addr * STORAGE_BLK_SIZ + i, buf[i]);
               HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, 0x08020000 + blk_addr * STORAGE_BLK_SIZ + i, i);
                             usb_buf[blk_addr * STORAGE_BLK_SIZ + i] = buf[i];
             }
             HAL_FLASH_Lock();
             break;
 
    case 1 : break;
    default: fBusy = 0;
             return (USBD_FAIL);
  }
  fBusy = 0;
  return (USBD_OK);
  /* USER CODE END 14 */
}
И в результате во flesf все пишется правильно (увеличивающееся значение счетчика):
Stm32F4 USB MSD internal flash


Где моя ошибка?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.12.2018, 18:03
Ответы с готовыми решениями:

STM32F4 + Xbee + USB-flash-накопитель
Плохо дружу с микроконтроллерами (только начал изучение), появилась необходимость в создании одного...

STM32F4 + USB FLASH + DMA + USART + CAN + DSP + FreeRTOS ?
Добрый вечер! Нужен совет. Делаю проект на STM32F4Dyscovery. К USB подключил FLASHку (Transcend на...

stm32f407+usb msd + fatfs
Добрый день Прошу помощи, хочу на stm32 сделать флешку. С памятью работает нормально, fatfs...

STM32F4xx + SD + USB MSD [РЕШЕНО]
Добрый вечер! Помоги ответить на несколько вопросов? 1. Можно ли писать из контроллера (серия...

USB Audio + USB CDC на одной STM32F4
Итак, есть ЦАП с входом I2S, есть FMприёмник с выходом I2S, есть STM32F405 с двумя I2S. Задача...

22
Модератор
Эксперт по электронике
8908 / 6677 / 918
Регистрация: 14.02.2011
Сообщений: 23,523
24.12.2018, 19:45 2
Цитата Сообщение от Caruso Посмотреть сообщение
Видно, что данные во flash неправильные.
учитываешь ли ты то, что данные пишутся во флешь не байтами, а uint32_t мне удавалась записать и uint16_t но надежность гарантировать не могу
и писать только с в ячейки со значением 0xFFFFFFFF, хоть один бит в 0, запись не происходит
1
Эксперт .NET
10566 / 6490 / 1506
Регистрация: 25.05.2015
Сообщений: 19,662
Записей в блоге: 14
25.12.2018, 08:07 3
Цитата Сообщение от Caruso Посмотреть сообщение
Где моя ошибка?
В использовании внутренней флешки.
Цитата Сообщение от Rius Посмотреть сообщение
  1. Попробуйте сначала сделать накопитель на базе RAM. Это же плата Discovery? Её там дофига. Когда это отладите, можно и что-то другое пробовать, т.к. на связь с ПК можно будет не оглядываться.
  2. Юзать набортную память программ для такой цели- плохая идея, понимаете, надеюсь? У неё ресурс очень ограниченный.
  3. Как эти факты совмещать думаете? -
    • Память программ у STM32F429ZIT6 стирается сразу секторами, размером минимум в 16 кБ.
    • У вас в коде видна запись секторами по 512 байт.
    • Запись возможна только в заранее стёртые ячейки.
...
1
31 / 30 / 4
Регистрация: 22.03.2010
Сообщений: 126
25.12.2018, 12:03  [ТС] 4
Попытаюсь ответить всем в порядке живой очереди.
Как только процессор стартует и попадает в main производится стирание Sector 5 0x08020000 - 0x0803FFFF 128 Kbytes. Я совершенно точно в этом уверен. St Link подтверждает это, показывая мне с адреса 0x08020000 сплошные FF. Впрочем, вот код стирания:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  uint32_t PageError = 0;
  FLASH_EraseInitTypeDef vFLASH_EraseInitTypeDef;   
    HAL_StatusTypeDef status;   
    
  vFLASH_EraseInitTypeDef.TypeErase = FLASH_TYPEERASE_SECTORS;
  vFLASH_EraseInitTypeDef.Banks = NULL;
  vFLASH_EraseInitTypeDef.Sector = FLASH_SECTOR_5;
  vFLASH_EraseInitTypeDef.NbSectors = 1;
  vFLASH_EraseInitTypeDef.VoltageRange = FLASH_VOLTAGE_RANGE_3;
  HAL_GPIO_WritePin(GPIOG, LD3_Pin, GPIO_PIN_SET);
  HAL_FLASH_Unlock();
  status = HAL_FLASHEx_Erase(&vFLASH_EraseInitTypeDef, &PageError);
  HAL_FLASH_Lock();
  CLEAR_BIT(FLASH->CR, FLASH_CR_SER);
  HAL_GPIO_WritePin(GPIOG, LD3_Pin, GPIO_PIN_RESET);
По поводу размерности записываемых данных. Мне удается записывать в память байтами, словами и полусловами. Я это проверял через отладчик. Я не вижу причин почему это не должно работать. В описании регистров нужно указывать какой тип данных хотите записать. Проблема в том, что когда данные для записи берутся из переменной, то запись проходит. Когда данные берутся из массива - уже нет.

Накопитель на базе RAM сделан, и он работает как надо, то есть форматируется, записывает, читает файлы. Там все просто:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#define STORAGE_LUN_NBR                  1
#define STORAGE_BLK_NBR                  0x60
#define STORAGE_BLK_SIZ                  0x200
 
uint8_t usb_buf[STORAGE_BLK_NBR * STORAGE_BLK_SIZ];
 
//Так читю:
for(i = 0; i < blk_len * STORAGE_BLK_SIZ; i++)
  buf[i] = usb_buf[blk_addr * STORAGE_BLK_SIZ + i];
 
//Так пишу:
for(i = 0; i < blk_len * STORAGE_BLK_SIZ; i++)
  usb_buf[blk_addr * STORAGE_BLK_SIZ + i] = buf[i];
Xочу использовать набортную память для реализации Bootloadera. Не думаю, что я когда - нибудь смогу выработать ресурс flash. Насколько я помню гарантированный ресурс 10000 циклов.
Для своей памяти я выбрал сектор №5 размером 128К. Не понимаю почему я не могу писать в сектор по 512 байт?

Теперь у меня вопросы:
Посмотрите на мой код, приведенный мной в первом посте:
C++
1
2
3
4
5
for(i = 0; i < blk_len * STORAGE_BLK_SIZ; i++){
//  HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, 0x08020000 + blk_addr * STORAGE_BLK_SIZ + i, buf[i]);
//  HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, 0x08020000 + blk_addr * STORAGE_BLK_SIZ + i, i);
  usb_buf[blk_addr * STORAGE_BLK_SIZ + i] = buf[i];
}
По USB я получил буфер с данными buf размером 512 байт.
В первом случае пишу:
C++
1
2
HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, 0x08020000 + blk_addr * STORAGE_BLK_SIZ + i, buf[i]);
usb_buf[blk_addr * STORAGE_BLK_SIZ + i] = buf[i];
Во flash записываются неверные данные. В usb_buf верные.

Во втором случае делаю так:
C++
1
2
HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, 0x08020000 + blk_addr * STORAGE_BLK_SIZ + i, i);
usb_buf[blk_addr * STORAGE_BLK_SIZ + i] = buf[i];
Во flash записываются верные данные (инкрементные значения). В usb_buf верные.
Не понимаю почему так.
0
Эксперт .NET
10566 / 6490 / 1506
Регистрация: 25.05.2015
Сообщений: 19,662
Записей в блоге: 14
25.12.2018, 14:20 5
Цитата Сообщение от Caruso Посмотреть сообщение
Насколько я помню гарантированный ресурс 10000 циклов.
Для своей памяти я выбрал сектор №5 размером 128К. Не понимаю почему я не могу писать в сектор по 512 байт?
ФС - штука с произвольным доступом на чтение/запись.
Подумайте, чем это грозит?
1
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
25.12.2018, 14:43 6
Caruso,
Цитата Сообщение от Caruso Посмотреть сообщение
Не понимаю почему так.
У вас итератор i какой тип имеет? Явно не uint8_t, так как массив имеет больше 255 байт. Скорее всего uint16_t или uint32_t.
Это к тому, ValeryS, Вам намекал, что по uint8_t в память не пишется, минимум uint16_t
1
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
25.12.2018, 15:12 7
Caruso, ну и заодно посмотрите, что там у вас в регистре CR
Stm32F4 USB MSD internal flash
1
31 / 30 / 4
Регистрация: 22.03.2010
Сообщений: 126
25.12.2018, 17:26  [ТС] 8
Цитата Сообщение от _SayHello Посмотреть сообщение
ну и заодно посмотрите, что там у вас в регистре CR
В таблице указаны напряжения питания микроконтроллера? Тогда в моем случае я могу писать только x32 или x64. Я правильно понимаю?
0
31 / 30 / 4
Регистрация: 22.03.2010
Сообщений: 126
25.12.2018, 18:01  [ТС] 9
Вот изменил код:
C++
1
2
3
4
5
6
7
HAL_FLASH_Unlock();
for(i = 0; i < blk_len * STORAGE_BLK_SIZ; i = i + 4){
  HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08020000 + blk_addr * STORAGE_BLK_SIZ + i, *(uint32_t*)&buf[i]);
  //HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08020000 + blk_addr * STORAGE_BLK_SIZ + i, 0x12345678);                          
  *(uint32_t*)&usb_buf[blk_addr * STORAGE_BLK_SIZ + i] = *(uint32_t*)&buf[i];
}
HAL_FLASH_Lock();
Когда пишу содержимое массива
C++
1
  HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08020000 + blk_addr * STORAGE_BLK_SIZ + i, *(uint32_t*)&buf[i]);
в памяти вот что:
Stm32F4 USB MSD internal flash


Когда пишу константу
C++
1
  HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08020000 + blk_addr * STORAGE_BLK_SIZ + i, 0x12345678);
в памяти все записано как надо:
Stm32F4 USB MSD internal flash
0
Эксперт .NET
10566 / 6490 / 1506
Регистрация: 25.05.2015
Сообщений: 19,662
Записей в блоге: 14
25.12.2018, 18:10 10
Caruso, попробуйте не из usb буфера писать, а из статического массива собственного производства. Однократно, при запуске программы.
И вместо постоянного приведения типа указателя на каждой итерации, проще сразу привести указатель на массив к нужному типу.
1
31 / 30 / 4
Регистрация: 22.03.2010
Сообщений: 126
25.12.2018, 18:15  [ТС] 11
Сейчас попробоваль в main создать массив и заполнить его счетчиком:
C++
1
2
for(i = 0; i < 512; i++)
  b_buf[i] = i;
Потом изменил функцию записи в память уже с массива b_buf.
C++
1
  HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08020000 + blk_addr * STORAGE_BLK_SIZ + i, *(uint32_t*)&b_buf[i]);
Тоже записалось все правильно:
Stm32F4 USB MSD internal flash


PS. Опередил Вас. уже сделал это.


Цитата Сообщение от Rius Посмотреть сообщение
И вместо постоянного приведения типа указателя на каждой итерации, проще сразу привести указатель на массив к нужному типу.
Как это сделать?
0
31 / 30 / 4
Регистрация: 22.03.2010
Сообщений: 126
25.12.2018, 18:19  [ТС] 12
Вот почему - то в ОЗУ из USB буфера пишется правильно, а во flash из этого буфера - неправильно.
0
Эксперт .NET
10566 / 6490 / 1506
Регистрация: 25.05.2015
Сообщений: 19,662
Записей в блоге: 14
25.12.2018, 18:35 13
Как?
Например
C++
1
2
uint8_t buf1[] =..... 
uint32_t *buf2 = (uint32_t *) buf1;
Добавлено через 1 минуту
Caruso, почему-почему... В 3 посте написал почему.
Вся идея обречена на провал. И не смотрите, что у кого-то там работает. Это поделки.

Добавлено через 2 минуты
Caruso, вы знаете вообще, что flash надо стирать перед записью?

Добавлено через 41 секунду
И что стирание идёт огромными блоками, по сравнению с записью?

Добавлено через 10 минут
Кстати, смотреть память через jflash в данном случае - плохая идея. Вы видите уже то, что получилось после.
А в отладчике могли могли бы увидеть, почему так происходит, пошагово. Хотя это и теоретически понятно.
1
31 / 30 / 4
Регистрация: 22.03.2010
Сообщений: 126
25.12.2018, 18:35  [ТС] 14
Цитата Сообщение от Rius Посмотреть сообщение
вы знаете вообще, что flash надо стирать перед записью?
Конечно знаю и более того, я это делаю:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration----------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_CRC_Init();
  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN 2 */
    
  uint32_t PageError = 0;
  FLASH_EraseInitTypeDef vFLASH_EraseInitTypeDef;   
    HAL_StatusTypeDef status;   
    
  vFLASH_EraseInitTypeDef.TypeErase = FLASH_TYPEERASE_SECTORS;
  vFLASH_EraseInitTypeDef.Banks = NULL;
  vFLASH_EraseInitTypeDef.Sector = FLASH_SECTOR_5;
  vFLASH_EraseInitTypeDef.NbSectors = 1;
  vFLASH_EraseInitTypeDef.VoltageRange = FLASH_VOLTAGE_RANGE_3;
  HAL_GPIO_WritePin(GPIOG, LD3_Pin, GPIO_PIN_SET);
  HAL_FLASH_Unlock();
  status = HAL_FLASHEx_Erase(&vFLASH_EraseInitTypeDef, &PageError);
  HAL_FLASH_Lock();
  CLEAR_BIT(FLASH->CR, FLASH_CR_SER);
  HAL_GPIO_WritePin(GPIOG, LD3_Pin, GPIO_PIN_RESET);
Нажимаю кнопку Reset на плате.
Смотрю память
Stm32F4 USB MSD internal flash


Подтыкаю USB кабель к компу и форматирую.
0
Эксперт .NET
10566 / 6490 / 1506
Регистрация: 25.05.2015
Сообщений: 19,662
Записей в блоге: 14
25.12.2018, 18:48 15
Caruso, нет, вы не знаете. Точнее знаете факт, что стирание вызывается в примере от ST перед записью. Но не понимаете причин и следствия
Ну подумайте, пожалуйста

Добавлено через 11 минут
Для данной темы это понимание фундаментально. Без него будет так:
Цитата Сообщение от Caruso Посмотреть сообщение
Уже несколько дней борюсь с кодом и не вижу где ошибка.
1
31 / 30 / 4
Регистрация: 22.03.2010
Сообщений: 126
25.12.2018, 18:48  [ТС] 16
Rius,

Мне не так смешно как вам.

Расскажите, где моя ошибка.
0
Эксперт .NET
10566 / 6490 / 1506
Регистрация: 25.05.2015
Сообщений: 19,662
Записей в блоге: 14
25.12.2018, 18:53 17
Ну как же может быть не смешно, если ответ в 3 посте?)))

Добавлено через 2 минуты
Запись во флешку это установка нуля.
Стирание это установка единицы.
Запись можно произвести даже одним битом.
Стирание производится только большими блоками, и никак иначе.
1
31 / 30 / 4
Регистрация: 22.03.2010
Сообщений: 126
25.12.2018, 18:55  [ТС] 18
Прошу конкретнее дать ответ.

Мне понятно что вы написали. Но я не понимаю как это относится ко мне.
0
Эксперт .NET
10566 / 6490 / 1506
Регистрация: 25.05.2015
Сообщений: 19,662
Записей в блоге: 14
25.12.2018, 19:00 19
Это что касается флешки.

Теперь файловая система:
Минимальный размер кластера 512 байт. Если это ФС от Чана, то там можно поболее поставить, но это ничего не меняет принципиально.
Файловая система предназначена для дисков. Которые могут стирать и записывать сектора отдельно, и по многу раз. В случае с некоторыми внешними SPI Flash и SD Card это не проблема, т.к. минимальный юнит там меньше или совпадает с сектором ФС.

Добавлено через 2 минуты
И теперь вопрос, который вы абсолютно проигнорировали в 3 посте:
Как эти факты совмещать думаете? -
  • Память программ у STM32F429ZIT6 стирается сразу секторами, размером минимум в 16 кБ.
  • У вас в коде видна запись секторами по 512 байт.
  • Запись возможна только в заранее стёртые ячейки.
И ещё вопрос: а как вы думаете, что будет при многократной записи различных данных в одну и ту же ячейку флеша, если её перед каждой записью не стирать?
1
31 / 30 / 4
Регистрация: 22.03.2010
Сообщений: 126
25.12.2018, 19:02  [ТС] 20
Винда очищает перед записью нулевой сектор, а затем пытается разместить в него что - то (FAT)?

Добавлено через 2 минуты
Цитата Сообщение от Rius Посмотреть сообщение
И ещё вопрос: а как вы думаете, что будет при многократной записи различных данных в одну и ту же ячейку флеша, если её перед каждой записью не стирать?
Нули там будут
0
25.12.2018, 19:02
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.12.2018, 19:02
Помогаю со студенческими работами здесь

STM32F4: Самопрограммирование flash
когда писал на avr то часто применял из своих программ самопрограммирование flash памяти при...

STM32F4+HY27US0821(NAND FLASH).
Всем привет)) Итак, к STM32 по FSMC подключена NAND FLASH(интерфейс 8 бит). И вот какой вопрос...

stm32f4 скорость записи во Flash
Подскажите как ускорить процесс записи. Стирание одного блока длится 240ms. Это нормально или...

Установка Windows XP на USB HDD (USB Flash Drive, Compact Flash, .)
Установка Windows XP на USB HDD (USB Flash Drive, Compact Flash, ...) Кто пробовал, у кого будут...

А возможно ли драйверу программно задать, чтобы подал питание на USB-MSD, после отключения питания?
Приветствую! Powered ON после Powered OFF Ведь ещё из системы не удалено. Имена и адреса...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru