Forum: Mikrocontroller und Digitale Elektronik STM32 FRAM Modul WREN Bit wird nicht gesetzt


von Fragenhagel (Gast)


Lesenswert?

Hallo zusammen und frohes Neues,

über SPI möchte ich ein 256-Kbit FM25W256 FRAM Modul von Cypress 
Semoconductors beschreiben und auslesen -  was man damit eben so macht. 
Leider funktioniert das noch nicht so wirklich hervorragend.

Genauer gesagt scheint das Auslesen wohl zu funktioieren allerdings 
hapert es es beim Schreiben. Das WEN Bit wird anscheinend nicht gesetzt.

Meine Funktion zum Beschreiben sieht wie folgt aus:
1
const uint8_t FRAM_READ = 0b00000011;
2
const uint8_t FRAM_WRITE = 0b00000010;
3
const uint8_t FRAM_WRDI = 0b00000100;
4
const uint8_t FRAM_WREN = 0b00000110;
5
const uint8_t FRAM_RDSR = 0b00000101;
6
const uint8_t FRAM_WRSR = 0b00000001;
1
void SPI_FRAM_WRITE(uint16_t adress, uint8_t* pdata){
2
3
  HAL_GPIO_WritePin(FRAM_CS_GPIO_Port, FRAM_CS_Pin, RESET);    //Enable FRAM SPI
4
  HAL_SPI_Transmit(FRAM_hspi, (uint8_t *)&FRAM_WREN, 1,100);
5
  HAL_GPIO_WritePin(FRAM_CS_GPIO_Port, FRAM_CS_Pin, SET);
6
  spi_buf[0] = FRAM_WRITE;
7
  spi_buf[1] = (uint8_t)(adress >> 8);
8
  spi_buf[2] = (uint8_t)(adress);
9
  for(int i = 0; i < sizeof(pdata) / sizeof(pdata[0]); i++){
10
    spi_buf[i+3] = pdata[i];
11
  }
12
  HAL_GPIO_WritePin(FRAM_CS_GPIO_Port, FRAM_CS_Pin, RESET);    //Enable FRAM SPI
13
  HAL_SPI_Transmit_DMA(FRAM_hspi, spi_buf, (sizeof(pdata) / sizeof(pdata[0]))+3);
14
  HAL_GPIO_WritePin(FRAM_CS_GPIO_Port, FRAM_CS_Pin, SET);
15
16
}

Wenn ich anschließend den Speicher auslese hat sich nichts verändert.
Das Statusregister hat den Wert 0b00100000.

Ich finde einfach nicht meinen Fehler...

von AVerr (Gast)


Lesenswert?

Es gibt einen Grund dafür warum man zusammen mit einem Array (Pointer) 
immer die Länge übergibt ... sizeof(pdata) ist nicht das was du glaubst.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Fragenhagel schrieb:
> void SPI_FRAM_WRITE(uint16_t adress, uint8_t* pdata){
> ...
>   for(int i = 0; i < sizeof(pdata) / sizeof(pdata[0]); i++){

Du gibst einen Pointer auf einen Buffer runter und berechnest dann die 
zu übertragende Länge als sizeof(pdata) / sizeof(pdata[0]). Das ist hier 
aber nicht zielführend, denn der Trick funktioniert nur für Arrays, 
nicht für Pointer.

Erweitere die Funktion um die Angabe der Länge:
1
void SPI_FRAM_WRITE(uint16_t adress, uint8_t* pdata, uint16_t len){
2
...
3
    for(uint16_t i = 0; i < len; i++){

Wenn Du in der aufrufenden Funktion ein "echtes" Array hast, kannst Du 
dort den Divisionstrick anwenden, um die Länge auszurechnen.

P.S.
Und nein, komm jetzt nicht auf die Idee, in der Parameterliste jetzt 
"uint8_t pdata[]" zu schreiben. Das ist auch kein Array, nur eine andere 
Schreibweise für den Pointer. Die Längeninformation hast Du hier einfach 
nicht mehr, daher musst Du diese übergeben.

: Bearbeitet durch Moderator
von Fragenhagel (Gast)


Lesenswert?

Ah, das werde ich morgen früh direkt Mal testen! Klar, dass man so nicht 
auf die Größe des Arrays kommt. Aber müsste dann nicht trotzdem immerhin 
das WREN Bit gesetzt werden?

von Fragenhagel (Gast)


Lesenswert?

Fragenhagel schrieb:
> Aber müsste dann nicht trotzdem immerhin das WREN Bit gesetzt werden?

Quatsch.. das wird ja durchs schreiben wieder zurückgesetzt. Bzw. durch 
die High Flanke vom NSS...

von Bastian (Gast)


Lesenswert?

Bist Du sicher das die Funktion HAL_SPI_Transmit_DMA(..) blockiert? 
Falls nicht wird direkt nach dem Start der Übertragung das Interface mit 
writePin wieder deaktiviert.

von Fragenhagel (Gast)


Lesenswert?

Auch ein guter Ansatz... Kann sehr gut sein dass da der Hund begraben 
liegt...

von Fragenhagel (Gast)


Lesenswert?

Beide Ansätze haben bisher noch keinen Erfolg erbracht. Langsam habe ich 
die Vermnutung, dass ich generell bei der SPI-Übertragung Fehler mache. 
Selbst wenn ich einfach nur in der while-Schleife, ohne irgendetwas 
anderes im Programm zu tun, versuche nur das WREN-Bit zu setzen und 
anschließend auszulesen klappt dies bei mir nicht.

Das ganze sieht dann so aus:
1
uint8_t WREN = 0b00000110;
2
uint8_t WRITE = 0b00000010;
3
4
uint8_t tx_buf[2];
5
uint8_t rx_buf[2];
1
while (1)
2
{
3
    tx_buf[0] = WRITE;
4
5
    HAL_GPIO_WritePin(FRAM_CS_GPIO_Port, FRAM_CS_Pin, RESET);    //Enable FRAM SPI
6
    HAL_SPI_Transmit(&hspi1, &WREN, 1, 100);
7
    HAL_GPIO_WritePin(FRAM_CS_GPIO_Port, FRAM_CS_Pin, SET);
8
    HAL_Delay(1);
9
    HAL_GPIO_WritePin(FRAM_CS_GPIO_Port, FRAM_CS_Pin, RESET);    //Enable FRAM SPI
10
    HAL_SPI_TransmitReceive(&hspi1, tx_buf, rx_buf, 2,100);
11
    HAL_GPIO_WritePin(FRAM_CS_GPIO_Port, FRAM_CS_Pin, SET);
12
    HAL_Delay(1000);
13
}

Das Array rx_buf wird nicht beschrieben und behält die Werte 0,0...

von AVerr (Gast)


Angehängte Dateien:

Lesenswert?

Fragenhagel schrieb:
> Das Array rx_buf wird nicht beschrieben und behält die Werte 0,0...

Das ist erwartet ... du sendest einen WRITE Befehl (keinen 
vollständigen), dabei wird nur vom Master gesendet, der FRAM sendet 
keine Daten zurück (siehe Datenblatt Memory Write: SO ist Hi-Z). Dann 
liest der SPI halt nur 0/1 (je nach Pull-up/down Situation am MISO Pin) 
oder zufällige Daten.

Um herauszufinden ob dein WREN Befehl geklappt hat kannst du es mit 
einem RDSR (Read Status Register, 0000 0101b) versuchen. WEL (Bit 1) 
müsste gesetzt sein wenn der WREN Befehl vorher geklappt hat.

von Fragenhagel (Gast)


Lesenswert?

AVerr schrieb:
> Fragenhagel schrieb:
>> Das Array rx_buf wird nicht beschrieben und behält die Werte 0,0...
>
> Das ist erwartet ... du sendest einen WRITE Befehl (keinen
> vollständigen), dabei wird nur vom Master gesendet, der FRAM sendet
> keine Daten zurück (siehe Datenblatt Memory Write: SO ist Hi-Z). Dann
> liest der SPI halt nur 0/1 (je nach Pull-up/down Situation am MISO Pin)
> oder zufällige Daten.
>
> Um herauszufinden ob dein WREN Befehl geklappt hat kannst du es mit
> einem RDSR (Read Status Register, 0000 0101b) versuchen. WEL (Bit 1)
> müsste gesetzt sein wenn der WREN Befehl vorher geklappt hat.

Das ist natürlich ein dummer Fehler. Ich hatte eigentlich vor das 
Statusregister auszulesen. Werde das sofort mal ausprobieren.

von Fragenhagel (Gast)


Lesenswert?

Es funktioniert leider immernoch nicht. Ich werde mal mit dem Oszi 
schauen, was beim SI Pin und SCK tatsächlich so geschieht.

von jo mei (Gast)


Lesenswert?

Fragenhagel schrieb:
> Es funktioniert leider immernoch nicht.

Ich finde leider gerade den Thread nicht, aber es gab einen wo
der Problemsteller mit seinem Aufbau (Flash-EPROM) zu kämpfen
hatte. Das leidige Stichwort Abblock-Kondensator. Also wenn du
mal deinen Aufbau zeigen könntest ob da vielleich ein rein
elektisches Problem drin steckt? Ob jetzt FRAMs gegenüber
Flash-EPROMs empfindlicher oder unempfindlicher sind wage ich
nicht einzuschätzen.

Und dann wie üblich: Leitungslängen bzw. Flanken-Empfindlich-
keit bei SPI Leitungen und Massebezug ist auch ein Thema für
den Aufbau.

von Werner P. (werner4096)


Lesenswert?

Hi,

ich verwende hier auch FRAM von Cypress. Auszug aus meinem Programm:
1
#define FRAM_CMD_READ            0x03
2
3
#define FRAM_CMD_WRITE           0x02
4
5
#define FRAM_CMD_READ_STATUS     0x05
6
#define FRAM_CMD_WRITE_ENABLED   0x06
7
#define FRAM_CMD_WRITE_STATUS    0x01
8
#define FRAM_CMD_READ_ID         0x9F
9
#define FRAM_CMD_READ_SN         0xC3
10
11
int fram_read(uint16_t address, uint8_t *buffer, int len)
12
{
13
  int result = 0;
14
15
  if (fram_prepare(FRAM_CMD_READ, address)) {
16
    if (HAL_SPI_Receive(m_spi, buffer, len, HAL_MAX_DELAY) == HAL_OK) {
17
      result = 1;
18
    }
19
  }
20
  HAL_GPIO_WritePin(m_fram_port, m_fram_cs, GPIO_PIN_SET);
21
22
  return result;
23
}
24
25
int fram_write(uint16_t address, uint8_t *buffer, int len)
26
{
27
  int result = 0;
28
29
  if (fram_prepare(FRAM_CMD_WRITE, address)) {
30
    if (HAL_SPI_Transmit(m_spi, buffer, len, HAL_MAX_DELAY) == HAL_OK) {
31
      result = 1;
32
    }
33
  }
34
  HAL_GPIO_WritePin(m_fram_port, m_fram_cs, GPIO_PIN_SET);
35
36
  return result;
37
}
38
39
int fram_prepare(uint8_t cmd, uint16_t address)
40
{
41
  int result = 0;
42
  uint8_t buffer[3];
43
  int len = 0;
44
45
  buffer[0] = FRAM_CMD_WRITE_ENABLED;
46
  len = 1;
47
48
  if(cmd == FRAM_CMD_WRITE) {
49
    HAL_GPIO_WritePin(m_fram_port, m_fram_cs, GPIO_PIN_RESET);
50
    HAL_SPI_Transmit(m_spi, buffer, len, HAL_MAX_DELAY);
51
    HAL_GPIO_WritePin(m_fram_port, m_fram_cs, GPIO_PIN_SET);
52
  }
53
54
  HAL_GPIO_WritePin(m_fram_port, m_fram_cs, GPIO_PIN_RESET);
55
56
  buffer[0] = cmd;
57
  buffer[1] = address >> 8;
58
  buffer[2] = address & 0xFF;
59
  len = 3;
60
  if (HAL_SPI_Transmit(m_spi, buffer, len, HAL_MAX_DELAY) == HAL_OK) {
61
    result = 1;
62
  }
63
64
  return result;
65
}

vielleicht hilft dir das weiter

von Fragenhagel (Gast)


Lesenswert?

jo mei schrieb:
> Fragenhagel schrieb:
>> Es funktioniert leider immernoch nicht.
>
> Ich finde leider gerade den Thread nicht, aber es gab einen wo
> der Problemsteller mit seinem Aufbau (Flash-EPROM) zu kämpfen
> hatte. Das leidige Stichwort Abblock-Kondensator. Also wenn du
> mal deinen Aufbau zeigen könntest ob da vielleich ein rein
> elektisches Problem drin steckt? Ob jetzt FRAMs gegenüber
> Flash-EPROMs empfindlicher oder unempfindlicher sind wage ich
> nicht einzuschätzen.
>
> Und dann wie üblich: Leitungslängen bzw. Flanken-Empfindlich-
> keit bei SPI Leitungen und Massebezug ist auch ein Thema für
> den Aufbau.

Eigentlich sollte der Aufbau keine Probleme bereiten, da ich das 
CY15FRAMKIT-001 Development kit von Cypress direkt über den Arduino 
Connector auf einem NUCLEO Board verbunden. Ich sehe auch dass gesendet 
wird allerdings kann ich momentan leider nur ein Signal zur selben Zeit 
auf meinem Oszilloskop betrachten. Das macht es schwierig zu erkennen, 
ob wirklich die richtigen Bytes gesendet werden.

von Fragenhagel (Gast)


Lesenswert?

Werner P. schrieb:
> vielleicht hilft dir das weiter

Vielen Dank schon einmal für die Bereitstellung deines Codes. Ich werde 
mich dransetzen und versuchen das ganze wie bei dir umzusetzen.

von A. B. (Gast)


Lesenswert?

Zur Abklärung, ob Soft- oder Hardwareproblem: Unter
http://openocd.zylin.com/#/c/4760/
gibt's einen Patch für OpenOCD für das ganze SPI/QPI/I2C-Zeugs.

von Werner P. (werner4096)


Lesenswert?

Fragenhagel schrieb:
> Werner P. schrieb:
>> vielleicht hilft dir das weiter
>
> Vielen Dank schon einmal für die Bereitstellung deines Codes. Ich werde
> mich dransetzen und versuchen das ganze wie bei dir umzusetzen.

Hab mir grad mal den Schaltplan von dem Dev Board angesehen.

Hast Du mal geprüft ob die Pins WP und Hold des SPI FRAM auch die 
richtigen Pegel haben? Sollten beide auf HIGH liegen.

von Anguel S. (anguel)


Lesenswert?

Moin in die Runde,

Fragenhagel schrieb:

> Eigentlich sollte der Aufbau keine Probleme bereiten, da ich das
> CY15FRAMKIT-001 Development kit von Cypress direkt über den Arduino
> Connector auf einem NUCLEO Board verbunden.

Ich kämpfe zufälligerweise auch gerade mit einem Nucleo64-Board und dem 
Cypress FRAM Kit :-) Ich hatte zuerst das Problem, dass meistens nur 
"Müll" über SPI gekommen ist, egal welche SPI-Geschwindigkeit. Erst als 
ich die 2. Masse vom Nucleo-CN10-Connector zum GND neben SCK am 
FRAM-Board verbunden habe lief alles, sogar mit 20 MHz über 15 cm 
Drätchen.

Hast du den CyKit Jumper auf 3.3V umgestellt? Wie ist denn deine SPI 
konfiguriert (CubeMX)? Welche SPI und CPU-Geschwindigkeit?

Ich selbst habe nun immer noch ein komisches Problem, und zwar dass 
manchmal beim ersten Schreiben (oder Lesen?) von 9 Bytes ab Adresse 0 
nur Nullen geschrieben (oder gelesen?) werden. Die darauffolgenden 
Burst-Writes/Burst-Reads (nutzen dieselbe Funktion) an Adressen weiter 
hinten im FRAM klappen dagegen immer problemlos.

UPDATE: Sieht so aus, dass es bei mir das Auslesen ist, was die Nullen 
zurückliefert. Manchmal werden nach dem Reset die 9 richtigen Bytes 
ausgelesen, manchmal 9 mal 0x00. Es hängt auch NICHT von der 
SPI-Geschwindigkeit ab. Bin momentan ratlos.

Grüße

Anguel

: Bearbeitet durch User
von Anguel S. (anguel)


Lesenswert?

Noch ein Update zu meinem Problem:
Ich glaube ich habe es gelöst :-) Ich hatte das FRAM-Board "zum Schutz" 
in seiner Plastikverpackung drin. Wahrscheinlich ein 
super-antistatisches Material.
Als ich es jetzt da heraus nehme, treten keine Probleme mehr auf. Kommt 
das irgendwie hin? Wenn es drin ist sehe ich die Fehler, draußen nicht. 
Jetzt brauche ich auch die 2. Masse vom Nucleo-Board nicht.

Ich hoffe das hilft,

Anguel

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.