[GO] Enregistrez les données pour flasher avec la carte Nucleo STM32

introduction

Le STM32F303K8 que j'ai a un flash de 64 Ko. Dans le passé, le flash était utilisé pour stocker le code. Je ne connaissais pas la méthode détaillée car j'ai écrit le code via gdb. Par conséquent, le contrôle du flash est effectué afin que les données puissent être librement enregistrées sur votre propre logiciel.

Objectif de développement

STM32F303K8

Enquête

Le manuel de référence décrit comment procéder. Il peut être lu, écrit et effacé. En raison des caractéristiques du flash, la zone est divisée en pages. flash_org.png La lecture est possible en unités d'octets, mais l'écriture est en unités d'un demi-mot (16 bits) et l'effacement est en unités de page (2 Ko).

Lire la procédure

La procédure de lecture est décrite comme suit.

flash_read.png

Il est accessible comme la mémoire normale.

sample_read


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

Procédure d'écriture / d'effacement

Le flash se détériore après une écriture et un effacement répétés, il semble donc être verrouillé après la réinitialisation. Par conséquent, écrivez / effacez après le déverrouillage. De plus, l'écriture ne peut être effectuée que dans la zone effacée (non écrite). Il est nécessaire d'effacer la zone correspondante avant d'écrire.

ouvrir

La méthode de déverrouillage est décrite comme suit. flash_unlock.png La définition séquentielle de KEY1 et KEY2 dans le registre FLASH_KEYR déverrouille et autorise l'accès au registre FLASH_CR.

sample_unlock


void unlock(void){
    FLASH->KEYR = FLASH_KEY1;
    FLASH->KEYR = FLASH_KEY2;
}

l'écriture

La procédure d'écriture est décrite comme suit. flash_prog.png Le code ressemble à ceci:

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

Effacer

Il y a l'effacement de page et l'effacement complet, mais ici nous expliquerons l'effacement de page. La procédure d'effacement est décrite comme suit. flash_ers.png Le code ressemble à ceci:

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

J'ai spécifié une adresse, mais la page entière, y compris l'adresse, est effacée. C'est difficile à comprendre à ce rythme, vous devrez peut-être concevoir quelque chose dans l'interface.

créer

Code de test

Tester le logiciel embarqué avec Google test a permis d'installer TDD, alors écrivons d'abord le code de test. Puisque le code de test entier est long, je publierai le test Write OK. Le tout est à ici. Puisque STM32 est 32 bits, l'adresse de la zone flash virtuelle du PC hôte doit également être 32 bits. Par conséquent, ce test ne fonctionne que dans un environnement 32 bits. Veuillez laisser les contre-mesures comme un problème futur.

class FlashTest : public ::testing::Test {
    protected:
        virtual void SetUp()
        {
            mock = new MockIo();
            //Registre flash virtuel
            virtualFlash = new FLASH_TypeDef();
            //Zone flash virtuelle Juste un tableau
	        virtualAddress = new uint8_t[100];
            //Définissez les adresses de début et de fin de la baie pour déterminer la zone flash
	        virtualStart = (uint32_t)&virtualAddress[0];
	        virtualEnd = (uint32_t)&virtualAddress[100]; //Obtenir une adresse hors de portée
            FlashCreate(virtualFlash, virtualStart, virtualEnd);
        }
        
        virtual void TearDown()
        {
            delete mock;
            delete virtualFlash;
            delete virtualAddress;
        }
};

TEST_F(FlashTest, WriteOK)
{
    mock->DelegateToVirtual();

    //Effacez la zone d'écriture prévue à 0
    virtualAddress[0] = 0;
    virtualAddress[1] = 0;
  //Adresse d'écriture flash virtuelle
    uint16_t* dummy = (uint16_t*)&virtualAddress[0];
  //Écrire des données
    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);
}

Le test a préparé ce qui suit. ・ Lire OK ・ Lire NG (adresse terminée) ・ Écriture OK ・ Write NG (échec d'écriture) ・ Ecrire NG (adresse over) ・ Effacer OK ・ Erase NG (échec de l'effacement) ・ Effacer NG (adresse terminée) Enfin, implémentez pour amener le test sur le chemin. gtest_flash.png

Code produit

Ce n'est pas un produit, mais c'est un code grand public. Les détails tels que les opérations de registre sont des fonctions internes. Le code source complet est ici.

python


//Créé pour les paramètres virtuels dans les tests
void FlashCreate(FLASH_TypeDef* flash_address, uint32_t start_address, uint32_t end_address)
{
    flashAddress = flash_address;
    flashStart = start_address;
    flashEnd = end_address;
}

//Réglage de l'adresse et déverrouillage
void FlashInit(void)
{
#ifndef DEBUG_GTEST
    FlashCreate(FLASH, (uint32_t)&_flash_addr, (uint32_t)&_flash_addr + (uint32_t)&_flash_size);
#endif
    flash_unlock();
}

//en train de lire
uint8_t FlashRead(uint8_t* address)
{
    if(!is_flash_area((uint32_t)address, sizeof(*address))){
        return 0;
    }

    return *address;
}

//l'écriture
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();
}

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

bouge toi

Je vais en fait l'écrire sur le flash.

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

Je le ferai. flash_rw.png

BEEF a été écrit !!

à la fin

Je voudrais l'utiliser pour créer un chargeur de démarrage qui écrit le code sur le flash, le lit en mémoire et démarre.

Recommended Posts

Enregistrez les données pour flasher avec la carte Nucleo STM32
J'ai essayé de sauvegarder les données avec discorde
Utilisez Django pour enregistrer les données de tweet
Enregistrer et charger des données avec joblib, pickle
Comment gérer les données déséquilibrées
Comment augmenter les données avec PyTorch
Enregistrez le résultat de l'exploration avec Scrapy dans Google Data Store
Envoyer des données à l'API DRF avec Vue.js
Convertissez des données FX 1 minute en données 5 minutes avec Python
Essayez de convertir en données ordonnées avec les pandas
Comment lire les données de problème avec Paiza
Comment créer des exemples de données CSV avec hypothèse
Convertissez les données avec la forme (nombre de données, 1) en (nombre de données,) avec numpy.
Je veux frapper 100 sciences des données avec Colaboratory
J'ai essayé d'obtenir des données CloudWatch avec Python
Comment récupérer des données de courses de chevaux avec Beautiful Soup
[Introduction à minimiser] Analyse des données avec le modèle SEIR ♬
Enregistrer l'objet dans un fichier avec pickle
Écrire des données CSV sur AWS-S3 avec AWS-Lambda + Python
Enregistrez les données pandas dans des actifs de données au format Excel avec Cloud Pak for Data (Watson Studio)
Comment utiliser xgboost: classification multi-classes avec des données d'iris
J'ai essayé de lire et d'enregistrer automatiquement avec VOICEROID2 2
Comment récupérer des données d'image de Flickr avec Python
Note de lecture: Introduction à l'analyse de données avec Python
J'ai essayé de lire et d'enregistrer automatiquement avec VOICEROID2
Comment obtenir plus de 1000 données avec SQLAlchemy + MySQLdb
Comment extraire des données qui ne manquent pas de valeur nan avec des pandas
Entrez les données Zaim dans Amazon Elasticsearch Service avec Logstash
Transférer les données vers une autre page (onglet) avec streamlit
Comment extraire des données qui ne manquent pas de valeur nan avec des pandas