Der STM32F303K8, den ich habe, hat einen 64KB-Blitz. In der Vergangenheit wurde Flash zum Speichern von Code verwendet. Ich kannte die detaillierte Methode nicht, weil ich den Code über gdb geschrieben habe. Daher wird eine Blitzsteuerung durchgeführt, damit Daten frei in Ihrer eigenen Software gespeichert werden können.
STM32F303K8
Das Referenzhandbuch beschreibt, wie das geht. Es kann gelesen, geschrieben und gelöscht werden. Aufgrund der Eigenschaften des Blitzes ist der Bereich in Seiten unterteilt. Das Lesen ist in Byte-Einheiten möglich, das Schreiben jedoch in 16-Bit-Einheiten (Half Word) und das Löschen in 2-KByte-Einheiten.
Der Lesevorgang wird wie folgt beschrieben.
Es kann wie im normalen Speicher zugegriffen werden.
sample_read
uint8_t read(uint8_t* address){
return *address;
}
Der Blitz verschlechtert sich nach wiederholtem Schreiben und Löschen, sodass er nach dem Zurücksetzen gesperrt zu sein scheint. Schreiben / Löschen Sie daher nach dem Entsperren. Das Schreiben kann auch nur im gelöschten (ungeschriebenen) Bereich erfolgen. Vor dem Schreiben muss der entsprechende Bereich gelöscht werden.
Die Entsperrmethode wird wie folgt beschrieben. Durch die aufeinanderfolgende Einstellung von KEY1 und KEY2 im FLASH_KEYR-Register wird die Sperre aufgehoben und der Zugriff auf das FLASH_CR-Register ermöglicht.
sample_unlock
void unlock(void){
FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2;
}
Der Schreibvorgang wird wie folgt beschrieben. Der Code sieht folgendermaßen aus:
sample_write
okng_t write(uint16_t* address, uint16_t data){
while(FLASH->FLASH_SR & FLASH_SR_BSY);
FLASH->CR |= FLASH_CR_PG;
*address = data;
while(FLASH->FLASH_SR & FLASH_SR_BSY);
if(FLASH->FLASH_SR & FLASH_SR_EOP){
FLASH->FLASH_SR &= ~FLASH_SR_EOP;
return OK;
}else{
return NG;
}
}
Es gibt Seitenlöschung und vollständige Löschung, aber hier werden wir die Seitenlöschung erklären. Der Löschvorgang wird wie folgt beschrieben. Der Code sieht folgendermaßen aus:
sample_erase
okng_t erase(uint8_t* address){
while(FLASH->FLASH_SR & FLASH_SR_BSY);
FLASH->CR |= FLASH_CR_PER;
FLASH->AR = (uint32_t)address;
FLASH->CR |= FLASH_CR_STRT;
while(FLASH->FLASH_SR & FLASH_SR_BSY);
if(FLASH->FLASH_SR & FLASH_SR_EOP){
FLASH->FLASH_SR &= ~FLASH_SR_EOP;
return OK;
}else{
return NG;
}
}
Ich habe eine Adresse angegeben, aber die gesamte Seite einschließlich der Adresse wird gelöscht. Bei dieser Geschwindigkeit ist es schwer zu verstehen, daher müssen Sie möglicherweise etwas in der Benutzeroberfläche entwickeln.
Embedded-Software mit Google-Test testen ist bereit, TDD zu installieren. Schreiben Sie also zuerst den Testcode. Da der gesamte Testcode lang ist, werde ich den Write OK-Test veröffentlichen. Das Ganze ist unter hier. Da STM32 32 Bit ist, muss die Adresse des virtuellen Flash-Bereichs des Host-PCs ebenfalls 32 Bit sein. Daher funktioniert dieser Test nur in einer 32-Bit-Umgebung. Bitte lassen Sie die Gegenmaßnahmen als zukünftige Ausgabe.
class FlashTest : public ::testing::Test {
protected:
virtual void SetUp()
{
mock = new MockIo();
//Virtuelles Flash-Register
virtualFlash = new FLASH_TypeDef();
//Virtueller Flash-Bereich Nur ein Array
virtualAddress = new uint8_t[100];
//Legen Sie die Start- und Endadressen des Arrays fest, um den Flash-Bereich zu bestimmen
virtualStart = (uint32_t)&virtualAddress[0];
virtualEnd = (uint32_t)&virtualAddress[100]; //Adressen außerhalb des Bereichs abrufen
FlashCreate(virtualFlash, virtualStart, virtualEnd);
}
virtual void TearDown()
{
delete mock;
delete virtualFlash;
delete virtualAddress;
}
};
TEST_F(FlashTest, WriteOK)
{
mock->DelegateToVirtual();
//Löschen Sie den geplanten Schreibbereich auf 0
virtualAddress[0] = 0;
virtualAddress[1] = 0;
//Virtuelle Flash-Schreibadresse
uint16_t* dummy = (uint16_t*)&virtualAddress[0];
//Daten schreiben
uint16_t data = 0xBEEF;
EXPECT_CALL(*mock, ReadBit(&virtualFlash->CR, FLASH_CR_LOCK)).WillOnce(Return(0));
EXPECT_CALL(*mock, ReadBit(&virtualFlash->SR, FLASH_SR_BSY)).WillRepeatedly(Return(FLASH_SR_BSY));
EXPECT_CALL(*mock, ReadBit(&virtualFlash->SR, FLASH_SR_BSY)).WillRepeatedly(Return(0));
EXPECT_CALL(*mock, SetBit(&virtualFlash->CR, FLASH_CR_PG));
EXPECT_CALL(*mock, ReadBit(&virtualFlash->SR, FLASH_SR_BSY)).WillRepeatedly(Return(FLASH_SR_BSY));
EXPECT_CALL(*mock, ReadBit(&virtualFlash->SR, FLASH_SR_BSY)).WillRepeatedly(Return(0));
EXPECT_CALL(*mock, ReadBit(&virtualFlash->SR, FLASH_SR_EOP)).WillOnce(Return(FLASH_SR_EOP));
EXPECT_CALL(*mock, ClearBit(&virtualFlash->SR, FLASH_SR_EOP));
EXPECT_EQ(FLASH_RESULT_OK, FlashWrite(dummy, data));
EXPECT_EQ(*dummy, data);
}
Der Test bereitete Folgendes vor. ・ Lesen Sie OK ・ Lesen Sie NG (Adresse vorbei) ・ OK schreiben ・ NG schreiben (Schreibfehler) ・ NG schreiben (Adresse über) ・ OK löschen ・ NG löschen (Löschfehler) ・ NG löschen (Adresse über) Implementieren Sie schließlich, um den Test auf den Pfad zu bringen.
Es ist kein Produkt, aber es ist ein Mainstream-Code. Details wie Registeroperationen sind interne Funktionen. Der gesamte Quellcode ist hier.
python
//Erstellt für virtuelle Einstellungen in Tests
void FlashCreate(FLASH_TypeDef* flash_address, uint32_t start_address, uint32_t end_address)
{
flashAddress = flash_address;
flashStart = start_address;
flashEnd = end_address;
}
//Adresseinstellung und Entsperrung
void FlashInit(void)
{
#ifndef DEBUG_GTEST
FlashCreate(FLASH, (uint32_t)&_flash_addr, (uint32_t)&_flash_addr + (uint32_t)&_flash_size);
#endif
flash_unlock();
}
//lesen
uint8_t FlashRead(uint8_t* address)
{
if(!is_flash_area((uint32_t)address, sizeof(*address))){
return 0;
}
return *address;
}
//Schreiben
flash_result_t FlashWrite(uint16_t* address, uint16_t data)
{
if(!is_flash_area((uint32_t)address, sizeof(*address))){
return FLASH_RESULT_NG;
}
if(is_flash_locked()){
return FLASH_RESULT_NG;
}
while(is_flash_busy());
flash_write(address, data);
while(is_flash_busy());
return check_flash_eop();
}
//Löschen
flash_result_t FlashPageErase(uint8_t* address)
{
if(!is_flash_area((uint32_t)address, sizeof(*address))){
return FLASH_RESULT_NG;
}
if(is_flash_locked()){
return FLASH_RESULT_NG;
}
while(is_flash_busy());
flash_page_erase(address);
while(is_flash_busy());
return check_flash_eop();
}
Ich werde es tatsächlich auf den Blitz schreiben.
python
static int flash(int argc, char *argv[])
{
flash_result_t ret;
FlashInit();
ret = FlashPageErase((uint8_t*)0x0800F800);
if(ret != FLASH_RESULT_OK){
printf("ERASE ERROR!!\n");
return 0;
}
printf("0x%X%X\n", FlashRead((uint8_t*)0x0800F801), FlashRead((uint8_t*)0x0800F800));
ret = FlashWrite((uint16_t*)0x0800F800, 0xBEEF);
if(ret != FLASH_RESULT_OK){
printf("WRITE ERROR!!\n");
return 0;
}
printf("0x%X%X\n", FlashRead((uint8_t*)0x0800F801), FlashRead((uint8_t*)0x0800F800));
return 0;
}
Ich werde das machen.
RINDFLEISCH wurde geschrieben !!
Ich möchte dies verwenden, um einen Bootloader zu erstellen, der Code in Flash schreibt, ihn in den Speicher liest und bootet.