[GO] Speichern Sie Daten zum Flashen mit STM32 Nucleo Board

Einführung

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.

Entwicklungsziel

STM32F303K8

Umfrage

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. flash_org.png 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.

Lesevorgang

Der Lesevorgang wird wie folgt beschrieben.

flash_read.png

Es kann wie im normalen Speicher zugegriffen werden.

sample_read


uint8_t read(uint8_t* address){
    return *address;
}

Schreib- / Löschvorgang

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.

Freischalten

Die Entsperrmethode wird wie folgt beschrieben. flash_unlock.png 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;
}

Schreiben

Der Schreibvorgang wird wie folgt beschrieben. flash_prog.png 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;
    }
}

Löschen

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. flash_ers.png 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.

erstellen

Testcode

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. gtest_flash.png

Produktcode

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();
}

Bewegung

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. flash_rw.png

RINDFLEISCH wurde geschrieben !!

schließlich

Ich möchte dies verwenden, um einen Bootloader zu erstellen, der Code in Flash schreibt, ihn in den Speicher liest und bootet.

Recommended Posts

Speichern Sie Daten zum Flashen mit STM32 Nucleo Board
Ich habe versucht, die Daten mit Zwietracht zu speichern
Verwenden Sie Django, um Tweet-Daten zu speichern
Speichern und laden Sie Daten mit joblib, pickle
Umgang mit unausgeglichenen Daten
Aufblasen von Daten (Datenerweiterung) mit PyTorch
Speichern Sie das Ergebnis des Crawls mit Scrapy im Google Data Store
Senden Sie Daten mit Vue.js an die DRF-API
Versuchen Sie, mit Pandas in ordentliche Daten umzuwandeln
Wie man Problemdaten mit Paiza liest
Erstellen von CSV-Beispieldaten mit Hypothese
Konvertieren Sie Daten mit Form (Anzahl der Daten, 1) in (Anzahl der Daten,) mit numpy.
Ich möchte 100 Datenwissenschaften mit Colaboratory schlagen
Ich habe versucht, CloudWatch-Daten mit Python abzurufen
So kratzen Sie Pferderenndaten mit Beautiful Soup
[Einführung zur Minimierung] Datenanalyse mit SEIR-Modell ♬
Speichern Sie das Objekt in einer Datei mit pickle
Schreiben Sie CSV-Daten mit AWS-Lambda + Python in AWS-S3
Speichern Sie Pandas-Daten mit Cloud Pak for Data (Watson Studio) im Excel-Format in Datenbeständen.
Verwendung von xgboost: Mehrklassenklassifizierung mit Irisdaten
Ich habe versucht, mit VOICEROID2 2 automatisch zu lesen und zu speichern
So kratzen Sie Bilddaten von Flickr mit Python
Lesehinweis: Einführung in die Datenanalyse mit Python
Ich habe versucht, mit VOICEROID2 automatisch zu lesen und zu speichern
So erhalten Sie mit SQLAlchemy + MySQLdb mehr als 1000 Daten
So extrahieren Sie mit Pandas Daten, denen der Wert nan nicht fehlt
Geben Sie Zaim-Daten mit Logstash in den Amazon Elasticsearch Service ein
Übertragen Sie Daten mit Streamlit auf eine andere Seite (Registerkarte)
So extrahieren Sie mit Pandas Daten, denen der Wert nan nicht fehlt