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

Подскажите по записи флэш

Голова уже опухла, вроде читает но явно нули  не пишет, все что можно прочитал, мануал 10 раз.

Читает точно, стирает не знаю, но все биты единицы, где то засада после комента "пишем", нужно записать 64 бита вроде что  и делается.

 

// stm32g070

#define   FLASH_KEY1            0x45670123
#define   FLASH_KEY2            0xCDEF89AB
#define   FLASH_address         0x0801F800  // последняя страница  
  
uint32_t  dwr, drd;   

void Flash_write(void)
{
//---------- разблокируем ---------
 
 FLASH->KEYR = FLASH_KEY1;
 FLASH->KEYR = FLASH_KEY2;
 
 //---------- стираем -------------
 
 while (FLASH->SR & FLASH_SR_BSY1);
 
	if (FLASH->SR & FLASH_SR_EOP) {
		FLASH->SR = FLASH_SR_EOP;
	}

	FLASH->CR |= FLASH_CR_PER;
	FLASH->CR |= (62<<FLASH_CR_PNB_Pos);   // Задаем её адрес
	FLASH->CR |= FLASH_CR_STRT;
	while (!(FLASH->SR & FLASH_SR_EOP));
	FLASH->SR = FLASH_SR_EOP;
	FLASH->CR &= ~FLASH_CR_PER;
 
 
 
 //--------- пишем --------------------
 
 FLASH->CR |= FLASH_CR_PG;
 while(!(FLASH->SR & FLASH_SR_EOP));

 *(uint32_t *)(FLASH_address) = 0;//dwr;
 *(uint32_t *)(FLASH_address+4) = 0;//dwr;

 while(!(FLASH->SR & FLASH_SR_EOP));
 FLASH->CR &= ~(FLASH_CR_PG);
 
 //----------------------------------

 FLASH->CR |= FLASH_CR_LOCK;
}
///-------------------- Читает  -------------------------

void Flash_read(void)
{
uint32_t address; 
address=0x0801F800;
drd=(*(__IO uint32_t*) address);

}

 

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

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


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

У меня на этом камне такой код работает (правда, у меня в библиотеке номер бита, а не маска).

//-----------------------------------------------------------------------------
//	int flash_write(const void *dst, const void *src, const DWORD size)
//-----------------------------------------------------------------------------
int flash_write(const void *dst, const void *src, const DWORD size)
{
	DWORD	*w_dst = (DWORD *)dst;
	DWORD	*w_src = (DWORD *)src;

	if(FLASH->CR & (1 << FLASH_CR_LOCK))
	{
		FLASH->KEYR = KEY1;
		FLASH->KEYR = KEY2;
	}

	while(FLASH->SR & (1 << FLASH_SR_BSY1));

	FLASH->SR = 0
		| (1 << FLASH_SR_OPERR)
		| (1 << FLASH_SR_PROGERR)
		| (1 << FLASH_SR_WRPERR)
		| (1 << FLASH_SR_PGAERR)
		| (1 << FLASH_SR_SIZERR)
		| (1 << FLASH_SR_PGSERR)
		| (1 << FLASH_SR_MISSERR)
		| (1 << FLASH_SR_FASTERR)
		| (1 << FLASH_SR_OPTVERR);

	for(int i = 0; i < size / sizeof(DWORD) / 2; i++)
	{
		FLASH->CR = (1 << FLASH_CR_PG);
		w_dst[0] = w_src[0];
		w_dst[1] = w_src[1];
		while((FLASH->SR) & (1 << FLASH_SR_BSY1));
		if((w_dst[0] != w_src[0]) || (w_dst[1] != w_src[1])) return FLASH_RESULT_ERROR;
		w_dst += 2;
		w_src += 2;
	}
	return FLASH_RESULT_OK;
}

//-----------------------------------------------------------------------------
//	void flash_erase(const DWORD start, const DWORD size)
//-----------------------------------------------------------------------------
void flash_erase(const DWORD start, const DWORD size)
{
	if(FLASH->CR & (1 << FLASH_CR_LOCK))
	{
		FLASH->KEYR = KEY1;
		FLASH->KEYR = KEY2;
	}

	while(FLASH->SR & (1 << FLASH_SR_BSY1));

	FLASH->SR = 0
		| (1 << FLASH_SR_OPERR)
		| (1 << FLASH_SR_PROGERR)
		| (1 << FLASH_SR_WRPERR)
		| (1 << FLASH_SR_PGAERR)
		| (1 << FLASH_SR_SIZERR)
		| (1 << FLASH_SR_PGSERR)
		| (1 << FLASH_SR_MISSERR)
		| (1 << FLASH_SR_FASTERR)
		| (1 << FLASH_SR_OPTVERR);

	for(int i = (start / FLASH_PAGE_SIZE); i < ((start + size) / FLASH_PAGE_SIZE); i++)
	{
		FLASH->CR = (1 << FLASH_CR_PER) + (i << FLASH_CR_PNB);
		FLASH->CR = (1 << FLASH_CR_PER) + (i << FLASH_CR_PNB) + (1 << FLASH_CR_STRT);
		while(FLASH->SR & (1 << FLASH_SR_BSY1));
	}
}

У вас тут

	FLASH->CR |= (62<<FLASH_CR_PNB_Pos);   // Задаем её адрес

точно нули в регистре, чтобы без очистки биты только устанавливать?

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


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

2 часа назад, whale сказал:

#define FLASH_address 0x0801F800 // последняя страница

 

2 часа назад, whale сказал:

FLASH->CR |= (62<<FLASH_CR_PNB_Pos); // Задаем её адрес

последняя страница 63

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


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

1 hour ago, adnega said:

w_dst += 2; w_src += 2;

А почему адрес увеличиваем на 2 если двойное слово 4 байта ?

А наверно адресация двойными словами. У меня там на 4 скачет может по этому не работает.

 

1 hour ago, adnega said:

точно нули в регистре

 

По сбросу вроде нули должны, к тому же память читаются все 1 так что очистку можно пропустить )

 

57 minutes ago, heavyC1oud said:

последняя страница 63

с 63 тоже пробовал тоже самое

 

1 hour ago, adnega said:

if((w_dst[0] != w_src[0]) || (w_dst[1] != w_src[1]))

тут не понял, вы сравниваете адрес и данные ???

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

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


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

7 часов назад, whale сказал:

А почему адрес увеличиваем на 2 если двойное слово 4 байта ?

А наверно адресация двойными словами. У меня там на 4 скачет может по этому не работает.

Да, т.к. указатель на DWORD, то скакать будет по 8 байт.

7 часов назад, whale сказал:

тут не понял, вы сравниваете адрес и данные ???

Я сравниваю записанные данные с источником. Если записалось не то, что записывали, то выход с ошибкой.

У вас RCC_AHBENR_FLASH в RCC->AHBENR установлен?

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


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

Я себе напсал такой код:

// Разблокировка записи/стирания флеш-памяти
uint8_t Flash_UnLock(void) {
    if (FLASH->CR & FLASH_CR_LOCK) {
        FLASH->KEYR = FLASH_KEY1;
        FLASH->KEYR = FLASH_KEY2;
    };
    return Flash_Lock_Status();
};
// Блокировка записи/стирания флеша
void    Flash_Lock(void) {
    FLASH->CR |= FLASH_CR_LOCK;
};
// Проверка статуса блокировки. Если 1 - заблокирована.
uint8_t Flash_Lock_Status(void) {
    // FLASH->CR[7] == LOCK bit. If 1 - locked
    while (FLASH->SR & FLASH_SR_BSY);
    return ((FLASH->CR & FLASH_CR_LOCK) & 0xFF);
};
// Старание страницы. Принимается АДРЕС 0x08000000~0x08...
// Может потребоваться переделать под номера страниц.
uint8_t Flash_ErasePage(uint32_t Address) {
    uint16_t i;
    uint32_t Start;
    uint8_t DoErase = 0;
    if (Address < APP_SECTION_START) return -1;
    if (Address >= APP_SECTION_END) return -1;
    Start = (Address & 0x0801FC00);         // 1024 bytes
    for (i=0; i<1024; i++) {
        if ( *(uint16_t*)(Start + i) != 0xFFFF) {
            DoErase = 1;
            break;
        };
    };
    if (DoErase) {
        if (Flash_Lock_Status() == 0) {
            __disable_irq();        // Single thread
            FLASH->CR &= ~(FLASH_CR_PER | FLASH_CR_MER | FLASH_CR_PG | FLASH_CR_OPTER | FLASH_CR_OPTPG);
            FLASH->CR |= FLASH_CR_PER;
            FLASH->AR = Start;
            FLASH->CR |= FLASH_CR_STRT;
            while (FLASH->SR & FLASH_SR_BSY) {};
            FLASH->CR &= ~FLASH_CR_PER;
            __enable_irq();            // Interrupt mode
            return 0;
        } else {
            return -1;
        };
    } else {
        return 0;
    };
};
// Запись двух байт в память по указанному адресу. Если результат отличается - возвзаращает 1, если совпадает - 0.
uint8_t Flash_WriteWord(uint32_t Address, uint16_t Data) {
    while (FLASH->SR & FLASH_SR_BSY) {};
    FLASH->CR &= ~(FLASH_CR_PER | FLASH_CR_MER | FLASH_CR_PG | FLASH_CR_OPTER | FLASH_CR_OPTPG);
    FLASH->CR |= FLASH_CR_PG;
    *(uint16_t*)(Address) = Data;
    while (FLASH->SR & FLASH_SR_BSY) {};
    FLASH->CR &= ~(FLASH_CR_PER | FLASH_CR_MER | FLASH_CR_PG | FLASH_CR_OPTER | FLASH_CR_OPTPG);
    if (*(uint16_t*)(Address) == Data) {
        return 0;
    } else {
        return 1;
    };
};
Изменено пользователем AlanDrakes
Добавил комментарии

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


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

9 минут назад, AlanDrakes сказал:

Я себе напсал такой код:

Смущает (т.к. G070): вроде, страница 2 кБ и писать нужно по 8 байт

Цитата

FLASH Main memory programming sequences
The Flash memory is programmed 72 bits (64-bit data plus 8-bit ECC) at a time.
Programming a previously programmed address with a non-zero data is not allowed. Any
such attempt sets PROGERR flag of the FLASH status register (FLASH_SR).
It is only possible to program a double word (2 x 32-bit data).
• Any attempt to write byte (8 bits) or half-word (16 bits) sets SIZERR flag of the FLASH
status register (FLASH_SR).
• Any attempt to write a double word that is not aligned with a double word address sets
PGAERR flag of the FLASH status register (FLASH_SR).

Я так понял, что там ECC, поэтому дозаписывать в пределах 8 байт уже не получится.

Ну и про 8, 16 бит явно написано, что будет ошибка. И отсутствие выравнивания на границу двойного слова (8 байт) - тоже ошибка.

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


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

15 минут назад, adnega сказал:

...писать нужно по 8 байт...

Писать нужно два раза по 32-битному слову, по адресам A и A + 4, где A - выровнен на границу двойного (64 бит) слова. В RM все об этом есть.

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


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

1 hour ago, adnega said:

У вас RCC_AHBENR_FLASH в RCC->AHBENR установлен?

Точно пропустил ) надо попробовать, понапридумывают всяких флагов и что характерно в мануале в теме про флэш про это ни  слов,

пишут как для шпионов )

У меня было смутное подозрение что где то в RCC чего нить надо вставить но не нашел .

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

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


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

К сожалению тактирование было включено в дргуом модуле (

Буду ошибки смотреть. 

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

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


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

Ура ! заработало в таком виде, для G70

висла на  

while (!(FLASH->SR & FLASH_SR_EOP));

и не работало 

 *(uint32_t *)(FLASH_address) = 0;//dwr;

 

Подскажите как удобнее разбить 4 байта на байты чтобы читать и записывать по отдельности, какая нить структура или сдвигать  ?

 

 

void  Flash_init(void) 
{

 FLASH->ACR |= 2;   // задержка 2 такта 
  
}

///-------------------- Записывает dwr ----------------------
void Flash_write(void)
{
 
 err=0;  
 errN=0;
 
  //---------- разблокируем ---------
 
 if(FLASH->CR & FLASH_CR_LOCK)
	{
		FLASH->KEYR = KEY1;
		FLASH->KEYR = KEY2;
	} else err = 1;
 
 errN++; //1
 
 //---------- стираем -------------
 
 while (FLASH->SR & FLASH_SR_BSY1); // пока BSY1==1
 
 errN++; //2
 
 if (FLASH->SR & FLASH_SR_EOP) FLASH->SR = FLASH_SR_EOP;
	
 FLASH->SR = 0
		|  FLASH_SR_OPERR
		|  FLASH_SR_PROGERR
		|  FLASH_SR_WRPERR
		|  FLASH_SR_PGAERR
		|  FLASH_SR_SIZERR
		|  FLASH_SR_PGSERR
	//	|  FLASH_SR_MISSERR // не находит
		|  FLASH_SR_FASTERR
		|  FLASH_SR_OPTVERR;      
        
	FLASH->CR |= FLASH_CR_PER;
	FLASH->CR |= (63<<FLASH_CR_PNB_Pos);   // Задаем её адрес
	FLASH->CR |= FLASH_CR_STRT;
	
        while( FLASH->SR & FLASH_SR_BSY1);
  
 errN++;//3
	
        FLASH->CR &= ~FLASH_CR_PER;
 
        
 if(FLASH->SR & FLASH_SR_PROGERR )err=2;
  
 //--------- пишем --------------------
  
 FLASH->CR |= FLASH_CR_PG;
 
 (*(__IO uint32_t*)FLASH_address) = dwr;
 (*(__IO uint32_t*)(FLASH_address+4)) = dwr2;


 while(FLASH->SR & FLASH_SR_BSY1);
 
errN++;//4

 if(FLASH->SR & FLASH_SR_PROGERR )err= 3;
 if(FLASH->SR & FLASH_SR_SIZERR  )err= 4;
 if(FLASH->SR & FLASH_SR_PGAERR  )err= 5;
 if(FLASH->SR & FLASH_SR_WRPERR  )err= 6; 
 
 FLASH->CR &= ~FLASH_CR_PG;
 
 FLASH->CR |= FLASH_CR_LOCK;

errN++;//5
 //----------------------------------

 
}

///-------------------- Читает  drd --------------------------

void Flash_read(void)
{

 uint32_t address; 
 address= FLASH_address;
 drd=(*(__IO uint32_t*) address); // Читать данные 
 drd2=(*(__IO uint32_t*)( address+4)); // Читать данные 


}

 

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

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


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

немного гугления привело к такой рабочей штуке 

struct tpSettings       { char d1,d2,d3,d4;};
struct tpSettings       Flash_data1;
uint32_t                *source_data1 = (void *)&Flash_data1;

вместо dwr/drd  ставим *source_data1 и будет счастье.

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

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


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

5 часов назад, whale сказал:

немного гугления привело к такой рабочей штуке

До волшебного слова union не догуглили? Прочитайте об этом пару страниц в любой книжке по Си и многое станет делать проще. Не понадобится приведение указателей.

Скрытый текст

typedef union {

  uint32_t w;

  uint8_t b[4];

} tpSettings;

tpSettings Flash_data1;

uint32_t *source_data1 = &Flash_data1.w;

 

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


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

27.05.2021 в 08:52, AlanDrakes сказал:

Я себе написал такой код...

Вы как-то неравнодушны к символу "точка с запятой":biggrin:

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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