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

Stm32f405 запись во Flash 16bit

Не могу не как понять почему запись по 16bit не работает, устанавливает флаг ошибки  PGPERR (Programming parallelism error) и записывает все равно 32bit

Из Дашашита

Quote

PSIZE[1:0]:Program size
These bits select the program parallelism.
00 program x8
01 program x16
10 program x32
11 program x64

uint8_t FLASH_Program_16Bit(uint32_t address,uint16_t data)
{
    while(!flash_ready()); //Ожидаем готовности флеша к записи


    FLASH->CR = FLASH_CR_PG              //Разрешаем программирование флеша
              |1*FLASH_CR_PSIZE_0        //PSIZE[1:0]:Program size
              |0*FLASH_CR_PSIZE_1;        //    01 program x16
    *(__IO uint32_t*)address = (uint16_t)data; //Пишем  2 байта
    while(!flash_ready());//Ждем завершения операции
    if(!check_EOP())return 0;
    FLASH->CR &= ~(FLASH_CR_PG); //Запрещаем программирование флеша

    return check_EOP();
}

Запись по 32bit работает
 

uint8_t FLASH_Program_32bit(uint32_t address,uint32_t data)
{
    while(!flash_ready()); //Ожидаем готовности флеша к записи
    FLASH->CR = FLASH_CR_PG              //Разрешаем программирование флеша
              |0*FLASH_CR_PSIZE_0        //PSIZE[1:0]:Program size
              |1*FLASH_CR_PSIZE_1;        //    10 program x32
    *(__IO uint32_t*)address = (uint32_t)data; //Пишем  4 байта
    while(!flash_ready());//Ждем завершения операции
    if(!check_EOP())return 0;
    FLASH->CR &= ~(FLASH_CR_PG); //Запрещаем программирование флеша

    return check_EOP();
}

 

 

 

 

Изменено пользователем pokk

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


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

45 minutes ago, pokk said:

*(__IO uint32_t*)address = (uint16_t)data; //Пишем 2 байта

Из мануала:

Quote

3. Perform the data write operation(s) to the desired memory address (inside main memory block or OTP area):
– Byte access in case of x8 parallelism
– Half-word access in case of x16 parallelism
– Word access in case of x32 parallelism
– Double word access in case of x64 parallelism

Установили 16 бит, а пишете 32.

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


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

FLASH->CR = FLASH_CR_PG              //Разрешаем программирование флеша
           |0*FLASH_CR_PSIZE_0       //PSIZE[1:0]:Program size
           |1*FLASH_CR_PSIZE_1;      //    10 program x32

Зачем вы меняете значение ВСЕХ битовых полей регистра, когда вам нужно изменить только два? Не боитесь записью всего регистра испортить то, что лежит вне интересующих вас разрядов?

Разделите это на 2 операции: установка битового поля PSIZE и разрешение программирования с использованием метода чтение-модификация-запись. Тогда ничего постороннего не пострадает.

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


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

2 часа назад, Darth Vader сказал:

Зачем вы меняете значение ВСЕХ битовых полей регистра, когда вам нужно изменить только два?

Так и следует делать. А чтобы "не бояться" нужно мануал на периферию читать.

Да к тому же из приведённого кода никак не следует что автор "меняет значение ВСЕХ битовых полей регистра".

А вот "FLASH->CR &= ~(FLASH_CR_PG);" - тут чтение совершенно лишнее, достаточно только записи.

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


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

49 minutes ago, jcxz said:

Да к тому же из приведённого кода никак не следует что автор "меняет значение ВСЕХ битовых полей регистра".

Присваивание нового значения регистру потенциально может изменить любое битовое поле в нём. А не только те, что хотел изменить автор.

Например, в приведённой строке он "попутно" сбрасывает биты ERRIE и IOPIE (25 и 24 позиции). А если до этого они были выставлены в 1? Намеренно, чтобы получить запрос на прерывания по этим событиям. А после такой записи в регистр логика работы программы нарушится и надо будет искать, а почему же программа не заходит в обработчик прерываний, которые я разрешил? А потом оказывается, что в функции записи флеша ты, сам того не желая,  сбрасываешь разрешения на эти прерывания. А всё потому, что делаешь запись вместо чтения-модификации-запись.

Я не настаиваю. Я предупреждаю и предостерегаю о возможных последствиях. Запись надо применять осторожно, точно убедившись, что значения всех соседних бит в регистре можно безнаказанно занулять.

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


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

30 минут назад, Darth Vader сказал:

Например, в приведённой строке он "попутно" сбрасывает биты ERRIE и IOPIE (25 и 24 позиции). А если до этого они были выставлены в 1?

А если нет? Если не были выставлены? Очевидно что это - не весь код, а только его кусок. По которому нельзя сделать таких выводов.

Если где-то в начале кода содержимое регистра было проинициализировано, все биты? А потом дальше, последующими записями изменяются только нужные биты в регистре, а в другие записываются те же значения, что были раньше (так как предыдущее значение их известно). Я всегда так делаю в своих драйверах. Какой смысл читать регистр, если его значение известно из предыдущего кода? Чтобы замедлить работу программы и сделать её более громоздкой?

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


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

49 minutes ago, jcxz said:

А если нет? Если не были выставлены? Очевидно что это - не весь код, а только его кусок. По которому нельзя сделать таких выводов.

Это законченный унифицированный кусок кода, оформленный в функцию. Он не должен иметь таких побочных действий.

Если бы это был просто выдранный из контекста кусок кода - я бы согласился. Но для функции такое поведение недопустимо. Она не должна изменять (портить) того, что её не касается. Если она это делает - значит она неправильно спроектирована либо реализована.

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


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

2 часа назад, Darth Vader сказал:

Если бы это был просто выдранный из контекста кусок кода - я бы согласился. Но для функции такое поведение недопустимо. Она не должна изменять (портить) того, что её не касается.

Кто Вам сказал, что она что-то "портит"? Если функция - часть некоего драйвера (часть его API) и в данном драйвере какие-то биты каких-то используемых регистров периферии (периферии принадлежащей этому драйверу) имеют предопределённое значение (например - установлены на этапе инициализации драйвера), то почему эта функция не может туда эти значения записать? Раз она их определённо "знает", то зачем ей их читать из этого регистра? Она может сразу записать туда нужную константу, сформированную в build-time.

А может эта функция - вообще не часть API, а какая-то внутренняя функция драйвера (что скорей всего и есть).

Какие-то надуманные ограничения.... :unknw:

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


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

22 minutes ago, jcxz said:

Какие-то надуманные ограничения

Пусть автор сам решает. Моё дело предупредить.

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


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

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

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

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

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

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

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

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

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

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