Например TDA7294

Форум РадиоКот • Просмотр темы - Проблема с записью в внутреннюю Flash на МК STM32F407VGT6
Форум РадиоКот
Здесь можно немножко помяукать :)





Текущее время: Пт июн 27, 2025 13:07:46

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 5 ] 
Автор Сообщение
Не в сети
 Заголовок сообщения: Проблема с записью в внутреннюю Flash на МК STM32F407VGT6
СообщениеДобавлено: Пт мар 14, 2025 11:56:18 
Родился
Аватар пользователя

Зарегистрирован: Ср июн 20, 2012 01:55:24
Сообщений: 16
Рейтинг сообщения: 0
Здравствуй сообщество! Столкнулся с проблемой об которую бьюсь целую неделю, а решения так и не вижу. :cry: Суть проблемы достаточно проста. Я пытаюсь с помощью библиотеки HAL записать во внутреннюю память FLASH МК STM32F407VGT6 данные. Сейчас это просто "магические числа". Проект прилагаю. :facepalm:

Так вот, в данном проекте, уже собралась целая куча вариантов записи в эту самую внутреннюю Flash-память. И все они действительно пишут значения в Flash.
Изображение

Но проблема в том, что после записи программы в контроллер (через китайский свисток st-link или стандартный программатор расположенный на плате STM32F4DISCOVERY Discovery kit) и повторной попытке отладчиком подключится к МК получаю следующую ошибку:
Изображение

Если с помощью STM32 ST-LINK Utility очистить МК или хотя бы 0 сектор, то при записи программы в отладочном режиме получаем следующее:
Изображение

Такая картина наблюдается при попытке записи/стирание в Flash. Чтение такого эффекта не вызывает.

Вопрос, где я ошибся? Если лень качать проект, прилагаю функцию (одну из) в самом низу и саму функцию main(){..} и инициализации сделанные с помощью STM32Cube.

Так же немного слов о скрипте компоновщика (для не внимательных). Скрипт я немного модифицировал, так как основная идея была создания bootloader-а с памятью под сам загрузчик, под данные о загрузчике/прошивке и выделение памяти под основную программу.

Код:
MEMORY
{
  CCMRAM    (xrw)    : ORIGIN = 0x10000000,   LENGTH = 64K
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 128K
  FLASH    (rx)    : ORIGIN = 0x8000000,   LENGTH = 32K
  BOOT_DATA (rx)   : ORIGIN = 0x8008000, LENGTH = 16K
  APP   (rx)   : ORIGIN = 0x800C000, LENGTH = 976K
}

.boot_data 0x08008000 :
  {
    _smem = ORIGIN(BOOT_DATA);
    KEEP(*(.boot_data))       
  } > BOOT_DATA

  _siccmram = LOADADDR(.ccmram);


Возможно, что-то здесь напутал :oops:

В общем, люди добрые, не проходите мимо! Покажите неопытному "котенку", где он ошибся! Можно прям тапкам или носом потыкать :oops:

Весь мозг уже себе вынес :cry: :cry: :cry:

Архив проект на STM32CubeIDE сюда: https://wdfiles.ru/1tW67~d?c91db132b4e9 ... 2b7994ea1d

Код:
/**
 * @brief Стирает сектора в Flash-памяти.
 * @param sector Номер начального сектора.
 * @param nbSectors Количество секторов для стирания.
 * @param voltageRange Диапазон напряжения для операции стирания.
 * @return Код ошибки (0 - успех, иначе код ошибки).
 */
FlashError_t bl_flash_erase_main_application(uint32_t sector, uint32_t nbSectors, uint32_t voltageRange){
    HAL_StatusTypeDef status;          // Статус выполнения операций HAL
    FLASH_EraseInitTypeDef erase_init; // Структура для настройки стирания
    uint32_t sector_error = 0;         // Переменная для хранения ошибки стирания

    // Проверка корректности параметров
    if (sector >= FLASH_SECTOR_TOTAL || nbSectors == 0 || (sector + nbSectors) > FLASH_SECTOR_TOTAL) {
       return FLASH_ERR_INVALID_PARAM; // Некорректные параметры
    }

    // Отключение прерываний для обеспечения атомарности операции
    __disable_irq();

    // Разблокировка Flash-памяти
    status = HAL_FLASH_Unlock();
    if(status != HAL_OK){
       __enable_irq(); // Включение прерываний в случае ошибки
       return FLASH_ERR_UNLOCK_FAILED; // Ошибка разблокировки
    }

    // Настройка структуры для стирания сектора
    erase_init.TypeErase = FLASH_TYPEERASE_SECTORS;  // Тип стирания: сектор
    erase_init.Sector = sector;                      // Номер сектора
    erase_init.NbSectors = nbSectors;                // Количество секторов для стирания
    erase_init.VoltageRange = voltageRange;          // Диапазон напряжения

    // Стирание сектора
    status = HAL_FLASHEx_Erase(&erase_init, &sector_error);
    while((FLASH->SR & FLASH_SR_BSY)!= 0);
    if(status != HAL_OK || sector_error != 0xFFFFFFFF){
       HAL_FLASH_Lock();
       __enable_irq(); // Включение прерываний в случае ошибки
       return FLASH_ERR_ERASE_FAILED; // Ошибка стирания Flash-памяти
    }
    // Блокировка Flash-памяти
    HAL_FLASH_Lock();
    //   Включение прерываний после завершения операций
    __enable_irq();
    return FLASH_OK; // Успешное завершение операции
}



Код:
/**
 * @brief Записывает данные в Flash-память.
 *
 * Эта функция позволяет записывать данные в Flash-память с поддержкой записи байтами, 16-битными словами и 32-битными словами.
 * Перед записью необходимо убедиться, что сектор Flash-памяти был стерт.
 *
 * @param addres Адрес в Flash-памяти, по которому начнется запись. Должен быть выровнен в соответствии с типом данных.
 * @param data Указатель на массив данных для записи.
 * @param length Количество элементов данных для записи.
 * @param type Тип данных для записи:
 *             - FLASH_TYPEPROGRAM_BYTE: Запись байтов (8 бит).
 *             - FLASH_TYPEPROGRAM_HALFWORD: Запись 16-битных слов.
 *             - FLASH_TYPEPROGRAM_WORD: Запись 32-битных слов.
 * @return FlashError_t:
 *         - FLASH_OK: Успешная запись.
 *         - FLASH_ERR_INVALID_PARAM: Некорректный адрес, длина или тип данных.
 *         - FLASH_ERR_WRITE_FAILED: Ошибка записи в Flash-память.
 */
FlashError_t bl_flash_write(const uint32_t addres, const void* data, const uint32_t length, uint32_t type) {
    HAL_StatusTypeDef status;

    // Проверка на нулевой указатель данных
   if (data == NULL) {
      return FLASH_ERR_INVALID_DATA;
   }

    // Проверка корректности типа данных
    if (type != FLASH_TYPEPROGRAM_BYTE && type != FLASH_TYPEPROGRAM_HALFWORD && type != FLASH_TYPEPROGRAM_WORD) {
        return FLASH_ERR_INVALID_PARAM; // Некорректный тип данных
    }

    // Определение размера элемента данных
    uint32_t data_size;
    switch (type) {
        case FLASH_TYPEPROGRAM_BYTE:
            data_size = 1;
            break;
        case FLASH_TYPEPROGRAM_HALFWORD:
            data_size = 2;
            break;
        case FLASH_TYPEPROGRAM_WORD:
            data_size = 4;
            break;
        default:
            return FLASH_ERR_INVALID_PARAM; // Некорректный тип данных
    }

    // Проверка корректности адреса и длины
   const uint32_t FLASH_START = 0x08008000; // Начальный адрес разрешённой области

    // Проверка корректности адреса и длины
    if (addres < FLASH_START  || addres + length * data_size - 1 > FLASH_END) {
        return FLASH_ERR_INVALID_PARAM; // Некорректный адрес или длина
    }

    // Проверка выравнивания адреса
    if (addres % data_size != 0) {
        return FLASH_ERR_INVALID_PARAM; // Адрес не выровнен
    }

    // Разблокировка Flash-памяти
    __disable_irq();
    status = HAL_FLASH_Unlock();
   if (status != HAL_OK) {
      __enable_irq();
      return FLASH_ERR_UNLOCK_FAILED;
   }

    // Цикл записи
    for (uint32_t i = 0; i < length; i++) {
        uint32_t current_address = addres + i * data_size;
        uint32_t current_data;

        // Получение данных в зависимости от типа
        switch (type) {
            case FLASH_TYPEPROGRAM_BYTE:
                current_data = ((uint8_t*)data)[i];
                break;
            case FLASH_TYPEPROGRAM_HALFWORD:
                current_data = ((uint16_t*)data)[i];
                break;
            case FLASH_TYPEPROGRAM_WORD:
                current_data = ((uint32_t*)data)[i];
                break;
            default:
                HAL_FLASH_Lock(); // Блокировка Flash-памяти в случае ошибки
                __enable_irq();
                return FLASH_ERR_INVALID_PARAM; // Некорректный тип данных
        }

        // Запись данных
        while (FLASH->SR & FLASH_SR_BSY);
        status = HAL_FLASH_Program(type, current_address, current_data);
        if (status != HAL_OK) {
            HAL_FLASH_Lock(); // Блокировка Flash-памяти в случае ошибки
            __enable_irq();
            return FLASH_ERR_WRITE_FAILED; // Ошибка записи
        }
    }

    // Блокировка Flash-памяти
    HAL_FLASH_Lock();
    __enable_irq();

    return FLASH_OK; // Успешная запись
}


в хедере:
Код:
#define BOOT_DATA_SECTOR_START  0x08008000
#define BOOT_DATA_SECTOR_END    0x0800BFFF
#define BOOT_DATA_SECTOR        FLASH_SECTOR_2
#define MAIN_APP_SECTOR_START   FLASH_SECTOR_3
#define MAIN_APP_SECTOR_END     FLASH_SECTOR_11
#define BOOT_FLAG_B             0xFFEECCBB

typedef struct{
   uint32_t magic;
   uint32_t version;
   uint32_t crc;
   uint32_t size;
}BootData;

// Определение кодов ошибок
typedef enum {
    FLASH_OK = 0,
    FLASH_ERR_UNLOCK_FAILED = -1,
    FLASH_ERR_ERASE_FAILED = -2,
    FLASH_ERR_INVALID_PARAM = -3,
   FLASH_ERR_WRITE_FAILED = - 4,
   FLASH_ERR_INVALID_DATA = -5
} FlashError_t;


функция main() {...} и инициализация:
Код:
// Переменная, размещенная в секции .boot_data сектор 2
__attribute__((section(".boot_data"))) BootData_1 bootaddress;

/* Private function prototypes ----------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();

  BootData bootData;
  bootData.magic = 0x22AA55AA;      // Пример значения для magic
  bootData.version = 1;            // Версия
  bootData.size = sizeof(BootData); // Размер структуры
  bootData.crc = 0;

  FlashError_t write_status;
  Стираем необходимые сектора перед записью
  write_status = bl_flash_erase_main_application(2, 1, VOLTAGE_RANGE_3); // Например, стираем сектор 2
  if (write_status != FLASH_OK) {
      __asm__("BKPT #0");
  }

  write_status = bl_flash_write((uint32_t)&bootaddress, &bootData, sizeof(bootData), FLASH_TYPEPROGRAM_BYTE);
  if (write_status != FLASH_OK) {
      __asm__("BKPT #0");
  }

  BootData readDataBoot;
  memcpy(&readDataBoot, (void*)&bootaddress, sizeof(bootData));

   while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
}

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 80;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Проблема с записью в внутреннюю Flash на МК STM32F407VGT
СообщениеДобавлено: Сб мар 15, 2025 12:25:01 
Держит паяльник хвостом
Аватар пользователя

Карма: 16
Рейтинг сообщений: 196
Зарегистрирован: Вс дек 02, 2012 16:58:33
Сообщений: 915
Откуда: от туда
Рейтинг сообщения: 0
Текст на скринах не виден совершенно. Задача не понятна. Сверните код под спойлеры.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Проблема с записью в внутреннюю Flash на МК STM32F407VGT
СообщениеДобавлено: Сб мар 15, 2025 13:34:08 
Это не хвост, это антенна

Карма: -10
Рейтинг сообщений: 171
Зарегистрирован: Вт авг 15, 2017 10:51:13
Сообщений: 1492
Рейтинг сообщения: 0
Для записи во flash этих STM32 нужно прочитать описание всего двух регистров: FLASH_SR и FLASH_CR. В которых всего-то с десяток полезных бит. И написать процедуру записи во флешь (вместе с чтением мануала на эти регистры) можно всего за час.
Непонятно - на кой тут калокуб? :dont_know:

Функцию:
FlashError_t bl_flash_write(const uint32_t addres, const void* data, const uint32_t length, uint32_t type) {
Выполняете откуда? Из ОЗУ? А все функции, которые она вызывает - где расположены? В ОЗУ или флешь? И можно ли выполнять код из флешь на вашем МК при записи стирании/флешь?
Аналогично - функция стирающая флешь.

Добавлено after 6 minutes 54 seconds:
Re: Проблема с записью в внутреннюю Flash на МК STM32F407VGT6
// Запись данных
while (FLASH->SR & FLASH_SR_BSY);
status = HAL_FLASH_Program(type, current_address, current_data);
if (status != HAL_OK) {
HAL_FLASH_Lock(); // Блокировка Flash-памяти в случае ошибки
__enable_irq();
return FLASH_ERR_WRITE_FAILED; // Ошибка записи
}
}

// Блокировка Flash-памяти
HAL_FLASH_Lock();
__enable_irq();

return FLASH_OK; // Успешная запись
}[/code]
Перед началом записи ждёте готовности флешь, а после HAL_FLASH_Program() - не ждёте. Если внутри HAL_FLASH_Program() сама ждёт завершения записи (опросом бита занятости флешь), то начальный цикл ожидания - не нужен. А если не ждёт, то выйти из своей функции можете когда флешь ещё занята. Что будет при этом с чтением из флеша исполняющегося кода программы? Видимо - будет сбой.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Проблема с записью в внутреннюю Flash на МК STM32F407VGT
СообщениеДобавлено: Сб мар 15, 2025 21:46:49 
Родился
Аватар пользователя

Зарегистрирован: Ср июн 20, 2012 01:55:24
Сообщений: 16
Рейтинг сообщения: 0
Да вы абсолютно правы на счет оперативной памяти. Действительно адрес передаваемый в функцию записи по факту из оперативной памяти, заменил его:
Код:
#define BOOT_DATA_SECTOR_START  0x08008000

Теперь запись выглядит так:
Код:
write_status = bl_flash_write((uint32_t)BOOT_DATA_SECTOR_START, &bootData, sizeof(bootData), FLASH_TYPEPROGRAM_BYTE);
  if (write_status != FLASH_OK) {
     __asm__("BKPT #0");
  }

Спойлер
Код:
FlashError_t bl_flash_write(const uint32_t addres, const void* data, const uint32_t length, uint32_t type) {
    HAL_StatusTypeDef status;

    // Проверка на нулевой указатель данных
   if (data == NULL) {
      return FLASH_ERR_INVALID_DATA;
   }

    // Проверка корректности типа данных
    if (type != FLASH_TYPEPROGRAM_BYTE && type != FLASH_TYPEPROGRAM_HALFWORD && type != FLASH_TYPEPROGRAM_WORD) {
        return FLASH_ERR_INVALID_PARAM; // Некорректный тип данных
    }

    // Определение размера элемента данных
    uint32_t data_size;
    switch (type) {
        case FLASH_TYPEPROGRAM_BYTE:
            data_size = 1;
            break;
        case FLASH_TYPEPROGRAM_HALFWORD:
            data_size = 2;
            break;
        case FLASH_TYPEPROGRAM_WORD:
            data_size = 4;
            break;
        default:
            return FLASH_ERR_INVALID_PARAM; // Некорректный тип данных
    }

    // Проверка корректности адреса и длины
   const uint32_t FLASH_START = 0x08008000; // Начальный адрес разрешённой области

    // Проверка корректности адреса и длины
    if (addres < FLASH_START  || addres + length * data_size - 1 > FLASH_END) {
        return FLASH_ERR_INVALID_PARAM; // Некорректный адрес или длина
    }

    // Проверка выравнивания адреса
    if (addres % data_size != 0) {
        return FLASH_ERR_INVALID_PARAM; // Адрес не выровнен
    }

    // Разблокировка Flash-памяти
    __disable_irq();
    status = HAL_FLASH_Unlock();
   if (status != HAL_OK) {
      __enable_irq();
      return FLASH_ERR_UNLOCK_FAILED;
   }

    // Цикл записи
    for (uint32_t i = 0; i < length; i++) {
        uint32_t current_address = addres + i * data_size;
        uint32_t current_data;

        // Получение данных в зависимости от типа
        switch (type) {
            case FLASH_TYPEPROGRAM_BYTE:
                current_data = ((uint8_t*)data)[i];
                break;
            case FLASH_TYPEPROGRAM_HALFWORD:
                current_data = ((uint16_t*)data)[i];
                break;
            case FLASH_TYPEPROGRAM_WORD:
                current_data = ((uint32_t*)data)[i];
                break;
            default:
                HAL_FLASH_Lock(); // Блокировка Flash-памяти в случае ошибки
                __enable_irq();
                return FLASH_ERR_INVALID_PARAM; // Некорректный тип данных
        }

        // Запись данных
        status = HAL_FLASH_Program(type, current_address, current_data);
        if (status != HAL_OK) {
            HAL_FLASH_Lock(); // Блокировка Flash-памяти в случае ошибки
            __enable_irq();
            return FLASH_ERR_WRITE_FAILED; // Ошибка записи
        }
    }

    // Блокировка Flash-памяти
    HAL_FLASH_Lock();
    __enable_irq();

    return FLASH_OK; // Успешная запись
}

и да, Вы правы, ждать не надо. Библиотека HAL все это уже делает за нас. Для пример возьмем стандартную функцию стирания памяти:
Спойлер
Код:
HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *SectorError)
{
  HAL_StatusTypeDef status = HAL_ERROR;
  uint32_t index = 0U;

  /* Process Locked */
  __HAL_LOCK(&pFlash);

  /* Check the parameters */
  assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));

  /* Wait for last operation to be completed */
  status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);

  if (status == HAL_OK)
  {
    /*Initialization of SectorError variable*/
    *SectorError = 0xFFFFFFFFU;

    if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
    {
      /*Mass erase to be done*/
      FLASH_MassErase((uint8_t) pEraseInit->VoltageRange, pEraseInit->Banks);

      /* Wait for last operation to be completed */
      status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);

      /* if the erase operation is completed, disable the MER Bit */
      FLASH->CR &= (~FLASH_MER_BIT);
    }
    else
    {
      /* Check the parameters */
      assert_param(IS_FLASH_NBSECTORS(pEraseInit->NbSectors + pEraseInit->Sector));

      /* Erase by sector by sector to be done*/
      for (index = pEraseInit->Sector; index < (pEraseInit->NbSectors + pEraseInit->Sector); index++)
      {
        FLASH_Erase_Sector(index, (uint8_t) pEraseInit->VoltageRange);

        /* Wait for last operation to be completed */
        status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);

        /* If the erase operation is completed, disable the SER and SNB Bits */
        CLEAR_BIT(FLASH->CR, (FLASH_CR_SER | FLASH_CR_SNB));

        if (status != HAL_OK)
        {
          /* In case of error, stop erase procedure and return the faulty sector*/
          *SectorError = index;
          break;
        }
      }
    }
    /* Flush the caches to be sure of the data consistency */
    FLASH_FlushCaches();
  }

  /* Process Unlocked */
  __HAL_UNLOCK(&pFlash);

  return status;
}

В ней есть задержка
Спойлер
Код:
HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
{
  uint32_t tickstart = 0U;
 
  /* Clear Error Code */
  pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
 
  /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
     Even if the FLASH operation fails, the BUSY flag will be reset and an error
     flag will be set */
  /* Get tick */
  tickstart = HAL_GetTick();

  while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != RESET)
  {
    if(Timeout != HAL_MAX_DELAY)
    {
      if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))
      {
        return HAL_TIMEOUT;
      }
    }
  }

  /* Check FLASH End of Operation flag  */
  if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP) != RESET)
  {
    /* Clear FLASH End of Operation pending bit */
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
  }
#if defined(FLASH_SR_RDERR) 
  if(__HAL_FLASH_GET_FLAG((FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | \
                           FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR | FLASH_FLAG_RDERR)) != RESET)
#else
  if(__HAL_FLASH_GET_FLAG((FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | \
                           FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR)) != RESET)
#endif /* FLASH_SR_RDERR */
  {
    /*Save the error code*/
    FLASH_SetErrorCode();
    return HAL_ERROR;
  }

  /* If there is no error flag set */
  return HAL_OK;
 


Но все это проблему не снимает. Почему даже без записи, а при простом стирании получаю такую ошибку при повторной попытки войти в отладку:
СпойлерИзображение

При этом если использовать в качестве отладчика ST-LINK(OpenOCD) в место ST-LINK GDB Server, то повторно войти в отладку можно. Ни кто не знает, это причуды GDB или я все же накосячел? Я склонен ко второму, т.к. при любой другой ситуации, данный отладчик работал штатно и без нариканий.

Добавлено after 2 hours 53 minutes 53 seconds:
Re: Проблема с записью в внутреннюю Flash на МК STM32F407VGT6
А ларчик просто открывался! :shock: Спасибо сообществу ST, :write: которые пока не отправили мой пост в бан по "расовым признакам" модераторами :kill: , пояснили что FLASH не совсем корректно работает с отладчиками если не дать задержку в секунду.
По этому перед стирание и записью в нее родимую просто поставил
Код:
HAL_Delay(1000);

Вот и все. Можно отлаживаться дальше.

Пользуйтесь! :beer:


Вернуться наверх
 
В продаже новые LED-драйверы XLC компании MEAN WELL с диммингом нового поколения

Компания MEAN WELL пополнила ассортимент своей широкой линейки светодиодных драйверов новым семейством XLC для внутреннего освещения. Главное отличие – поддержка широкого спектра проводных и беспроводных технологий диммирования. Новинки представлены в MEANWELL.market моделями с мощностями 25 Вт, 40 Вт и 60 Вт. В линейке есть модели, работающие как в режиме стабилизации тока (СС), так и в режиме стабилизации напряжения (CV) значением 12, 24 и 48 В.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Проблема с записью в внутреннюю Flash на МК STM32F407VGT
СообщениеДобавлено: Вс мар 16, 2025 02:29:10 
Друг Кота
Аватар пользователя

Карма: 61
Рейтинг сообщений: 1533
Зарегистрирован: Вт окт 22, 2013 04:37:23
Сообщений: 3307
Откуда: Казань
Рейтинг сообщения: 0
Rudthaky, надеюсь до бана Вы успели сообщить сообществу ST, что их STM прекрасно работают в новой модификации "Орешника"? Должно же сообщество ST тоже порадоваться её (модификации) скорому выходу.

_________________
Платы для HLDI - установки лазерной засветки фоторезиста.
Фоторезисты Ordyl Alpha 350 и AM 140.
Жидкое олово для лужения плат (видео) - самое лучшее и только у меня.
Паяльная маска XV501T-4 и KSM-S6189 (5 цветов).
Заказ печатных плат - pcbsmac@gmail.com


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 5 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: HardWareMan и гости: 12


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y