Skocz do zawartości

Obsługa tablicy Flash <-> RAM


Pomocna odpowiedź

Napisano (edytowany)

Witam,

Zaczynam amatorsko przygodę z STM32F103C8T6 i przepraszam za ewentualne amatorskie pytania 😉

Chcę w programie obsługiwać dużą tablicę dwuwymiarową:

int8_t tablica[500][16];

Jest ona umieszczona w RAM, a także umieszczona pod koniec pamięci FLASH STM32 w celu przepisania do RAM po włączeniu zasilania.

Tablica będzie też przesyłana przez USART do PC.

Wstępnie mam taki kod do zapisu:

	FLASH->KEYR = FLASH_KEY1;
	FLASH->KEYR = FLASH_KEY2;
	//FLASH_Erase Page
	while((FLASH->SR&FLASH_SR_BSY));
	FLASH->CR |= FLASH_CR_PER; //Page Erase Set
	FLASH->AR = 0x0801FC00; //Page Address
	FLASH->CR |= FLASH_CR_STRT; //Start Page Erase
	while((FLASH->SR&FLASH_SR_BSY));
	FLASH->CR &= ~FLASH_CR_PER; //Page Erase Clear
	FLASH->CR |= FLASH_CR_PG;

	uint16_t i;
	uint16_t d;
	for(i=0; i<15; i++){
		while((FLASH->SR&FLASH_SR_BSY));
		d=(uint16_t)(((tablica[0][i+1])<<8) + tablica[0][i]);
		*(__IO uint16_t*)(0x0801FC00 + i) = d;
	}

	FLASH->CR &= ~FLASH_CR_PG;
	FLASH->CR |= FLASH_CR_LOCK;

1. Czym są FLASH_KEY1 i FLASH_KEY2?

2. Jak sensowniej obsłużyć przepisanie danych tablicy? Zakładam, że chyba lepiej przez wskaźniki, ale dopiero się uczę i nie jestem pewny jak to zrobić.

 

Pozdrawiam.

Edytowano przez Pawel88

@Pawel88 Zadając pytanie o STM32 warto chociaż raz wspomnieć o którym modelu mikrokontrolera piszesz. Bo pytać o stm32 to jakby napisać, że masz problem z samochodem, ale bez podawania modelu.

Druga sprawa, to może napisz skąd masz ten kod - bo jak rozumieć pytanie:

6 minut temu, Pawel88 napisał:

1. Czym są FLASH_KEY1 i FLASH_KEY2?

Napisałeś program i nie wiesz jak?

Ale ja już wcześniej wpisałem do tych rejestrów:

#define FLASH_KEY1 ((uint32_t)0x45670123)
#define FLASH_KEY2 ((uint32_t)0xCDEF89AB)

Tylko nie wiem, skąd biorą się te wartości. Ale pomińmy te pytanie, bo będę odsyłany do dokumentacji, które już oglądałem 🙂

 

Jak zapisać obsługę tej tablicy przez wskaźniki? Ponieważ są tu też różne wielkości zmiennych.

A zaglądałeś do dokumentu który podlinkowałem? Na stronie 12 (podpunkt 2.3.1) są te wartości wymienione.

Ich wartości nie mają jakiegoś szczególnego znaczenia. Jest to zabezpieczenie przed błędem w programie - inaczej program mógłby skasować lub nadpisać pamięć Flash przez przypadek. Natomiast błąd w programie, który akurat do rejestru KEYR wpisze oczekiwaną wartość jest znacznie mniej prawdopodobny. Jakby co to wszystko masz we wspomnianej dokumentacji - podpunkt 2.3.2 tym razem.

A co do drugiego pytania - to może najpierw sprawdź, czy to co masz działa poprawnie. Ulepszanie kodu to dobry pomysł, ale może najpierw lepiej się upewnić, że to co mamy działa.

Stąd moje pytanie: czy program działa? I pytanie pomocnicze -  jak to testujesz?

  • Lubię! 2

No, OK. Przecież mówiłem, że zaglądałem, ale nie znalazłem sensu tych wartości. Czyli to przypadkowe liczby które wymyślił sobie producent 😉

Ale jak już wspomniałem tematem jest obsługa tablicy Flash / RAM.

Więc jeszcze raz zapytam, Jak zapisać obsługę tej tablicy przez wskaźniki dla różnych wielkości zmiennych?

Proszę tylko o pomoc na ten temat.

Napisałem wcześniej, ale wiadomości się połączyły, więc powtórzę - zacznij od poprawienia i przetestowania programu, który napisałeś. Używanie wskaźników to dobry pomysł, ale program napisany w takim stylu jak teraz też powinien działać. Jako ułatwienie podpowiem:

	for(i=0; i<15; i++){
		d=(uint16_t)(((tablica[0][i+1])<<8) + tablica[0][i]);

Teraz zadanie dla Ciebie - gdzie tu jest błąd?

 

A co do wskaźników, to wystarczy brutalnie rzutować to co masz w tablicy, czyli uint8_t na uint16_t - procesor używa trybu little-endian, więc liczby 16 bitowe będą interpretowane tak jak powinno działać przypisanie do d.

Pisałem kod na szybko, więc trochę offset na tablicy przesunięty 😉

 

W międzyczasie pojawiło mi się pytanie: Czy trzeba przepisywać tablicę z Flash do RAM, czy podczas startu procesora jest to robione automatycznie?

Wszystko zależy co chcesz uzyskać. Najprościej jest zamienić dane na kod w C i skompilować wraz z resztą programu - w sieci znajdziesz gotowe skrypty które to robią.

Jeśli tablica będzie zadeklarowana jako stała, to zostanie umieszczona w pamięci Flash i nie będziesz mógł jej modyfikować. Natomiast zadeklarowanie jej jako zmiennej z początkową wartością daje dokładnie to co próbujesz zrobić. Wartości początkowe zostaną zapisane w pamięci Flash i przepisane do RAM przed wejściem do funkcji main.

(edytowany)

Tylko chyba przy deklaracji tablicy jako zmiennej z początkowymi wartościami, nie będę mógł jej zapisywać na stałe i po uruchomieniu procesora mieć nowe dane jakie zapisałem przed wyłączeniem?

 

Chyba żeby jakoś zmusić kompilator, aby zapisywał pod koniec Flash w ściśle określonym miejscu i tam z poziomu programu modyfikować ją.

Edytowano przez Pawel88
(edytowany)

OK, to przejdę do kodu.

Czy tak można wykorzystać wskaźnik?:

for(i=0; i<1023; i++){
  *(__IO uint16_t*)(Page_127 + i) = *(tablica + i);
  {

gdzie: int8_t tablica[500][16];

Edytowano przez Pawel88

Nie, tak nie można. Jednak radziłbym wrócić do pierwszej wersji, wydaje mi się że rozumiałeś ją trochę lepiej, więc poprawienie kodu byłoby dobrym ćwiczeniem.

W tej wersji wszystko jest źle. Zaczynając od tego że po lewej stronie jest wartość 16-bitowa, a po prawej 8-bitowa, kończąc na innym kroku indeksowania - to było źle w pierwszym kodzie i dlatego chciałem żebyś spędził nad nim trochę czasu.

Z drugiej strony nie mam już siły. Proponuję więc zrobić tak:

uint16_t *tablica16 = (uint16_t*)&tablica[0][0]

Teraz możesz używać tablica16 do zapisywania / odczytywania danych z pamięci, masz po obu stronach taki sam typ (uint16_t), nie ma 2 wymiarów, więc same plusy.

Czy taki zapis też jest poprawny?

uint16_t *tablica16 = (uint16_t*)&tablica

 

PS: Co do tej prostej wersji bez wskaźników, to napisałem żartobliwie wyżej, że "trochę offset na tablicy przesunięty". A dokładniej to trzeba było indeksować co 2 a nie co 1 jak w tamtym kodzie.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...