C > Anzahl an Words von übergebenen Bytes berechnen?

#7796244
Lesenswert?

Nabend,

kleine Verständnisfrage an euch: Was genau soll diese Berechnung machen? Soll sie ermitteln wie viel Words aus den übergebenen Bytes gebildet werden können?

1
  uint32_t words = (bytes + 3) / 4;  //16 max
1
static void __spiTransferBytes(spi_t *spi, const uint8_t *data, uint8_t *out, uint32_t bytes) {
2
  if (!spi) {
3
    return;
4
  }
5
  uint32_t i;
6

7
  if (bytes > 64) {
8
    bytes = 64;
9
  }
10

11
  uint32_t words = (bytes + 3) / 4;  //16 max
12

13
  uint32_t wordsBuf[16] = {
14
    0,
15
  };
16
  uint8_t *bytesBuf = (uint8_t *)wordsBuf;
17

18
  if (data) {
19
    memcpy(bytesBuf, data, bytes);  //copy data to buffer
20
  } else {
21
    memset(bytesBuf, 0xFF, bytes);
22
  }
23

24
  spi->dev->mosi_dlen.usr_mosi_dbitlen = ((bytes * 8) - 1);
25
  spi->dev->miso_dlen.usr_miso_dbitlen = ((bytes * 8) - 1);
26

27
  for (i = 0; i < words; i++) {
28
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4
29
    spi->dev->data_buf[i].val = wordsBuf[i];  //copy buffer to spi fifo
30
#else
31
    spi->dev->data_buf[i] = wordsBuf[i];  //copy buffer to spi fifo
32
#endif
33
  }
34

35
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2)
36
  spi->dev->cmd.update = 1;
37
  while (spi->dev->cmd.update);
38
#endif
39
  spi->dev->cmd.usr = 1;
40

41
  while (spi->dev->cmd.usr);
42

43
  if (out) {
44
    for (i = 0; i < words; i++) {
45
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4
46
      wordsBuf[i] = spi->dev->data_buf[i].val;  //copy spi fifo to buffer
47
#else
48
      wordsBuf[i] = spi->dev->data_buf[i];  //copy spi fifo to buffer
49
#endif
50
    }
51
    memcpy(out, bytesBuf, bytes);  //copy buffer to output
52
  }
53
}
Moderator (Firma: Titel) Persönliche Seite #7796252
Lesenswert?

Jan H. schrieb:

uint32_t words = (bytes + 3) / 4; //16 max

Soll sie ermitteln wie viel Words aus den übergebenen Bytes gebildet werden können?

Ja, sie ermittelt, wieviele 32-Bit-Worte für eine bestimmte Anzahl Bytes nötig sind. Spiel das doch einfach mal mit ein paar Werten für bytes (z.B. von 0..12) durch und denk daran: bei der Integerdivision /4 wird einfach der Rest abgeschnitten.

1
bytes   |   words
2
--------+---------
3
  0     |    0
4
  1     |    1
5
  2     |    1
6
  3     |    1
7
  4     |    1
8
  5     |    2
9
  6     |    2
10
  :     |    :
#7796254
Lesenswert?

Lothar M. schrieb:

Jan H. schrieb:

uint32_t words = (bytes + 3) / 4; //16 max Soll sie ermitteln wie viel Words aus den übergebenen Bytes gebildet werden können?

Ja, sie ermittelt, wieviele 32-Bitworte für eine bestimmte Anzahl Bytes nötig sind. Spiel das doch einfach mal mit ein paar Werten für bytes (z.B. von 0..12) durch und denk daran: bei der Integerdivision /4 wird einfach der Rest abgeschnitten.

Habe ich schon gemacht jedoch bin ich bei einer ungeraden Zahl an Bytes stutzig geworden. Wenn ich jetzt z.B 3 Bytes übertragen möchte, errechnet die Funktion ja nur ein Word was ja auch richtig ist, in der for Schleife wird dann das dritte Byte nicht mehr beachtet oder habe ich da einen Denkfehler?

Beitrag #7796351 wurde von einem Moderator gelöscht.
#7796368
Lesenswert?

Ich habe das eben noch mal mit dem "onlinegdb" durchgespielt. Wenn ich der Funktion als bsp.

1
        uint8_t buff[] = {1,2,3,4};
2
        spi_write_bytes( buff, 4 );

übergebe, ist das gebildete Word "67305985 Dec." Das währe dann in Bytes "0x04, 0x03, 0x02, 0x01 Hex."

Die Funktion zum schreiben der Daten auf dem SPI Bus ist auf MSB_First eingestellt. Das würde bedeuten das zuerst die "0x04" dann die "0x03" usw. gesendet werden müsste, richtig?

Jedoch ist komplett anders (siehe Foto).. So wie ich das jetzt verstanden habe, passen meine zu sendenen Bytes in ein 32 Bit Word. Da das SPI Senderegister 32 Bit breit ist, sollte es eigentlich der o.g. Reihenfolge gesendet werden oder=

Angehängte Dateien:
#7796374
Lesenswert?

Jan H. schrieb:

Die Funktion zum schreiben der Daten auf dem SPI Bus ist auf MSB_First eingestellt.

Richtig, sie sendet das höherwertige /Bit/ der übertragenen Bytes zuerst.

Jan H. schrieb:

Das würde bedeuten das zuerst die "0x04" dann die "0x03" usw. gesendet werden müsste, richtig?

Nö, um das Umsortieren von Bytes müsstest Du Dich schon selbst kümmern, das hat mit SPI nichts mehr zu tun.

#7796379
Lesenswert?

Harald K. schrieb:

Jan H. schrieb:

Die Funktion zum schreiben der Daten auf dem SPI Bus ist auf MSB_First eingestellt.

Richtig, sie sendet das höherwertige Bit der übertragenen Bytes zuerst.

Jan H. schrieb:

Das würde bedeuten das zuerst die "0x04" dann die "0x03" usw. gesendet werden müsste, richtig?

Nö, um das Umsortieren von Bytes müsstest Du Dich schon selbst kümmern, das hat mit SPI nichts mehr zu tun.

Wie "Nö"? Wenn meine 0x04 das MSB von uint32_t bildet, wird das doch zuerst gesendet?

#7796385
Lesenswert?

Habe gerade versucht einen uint32_t zu senden mit 0x000001. Laut LA kommt 0x000100 an. Scheint also irgendwas mit dem Registerzugriff nicht zu passen..

1
    while (1)
2
    {    
3
        //uint8_t buff[] = {1,2,3,4};
4
        //spi_write_bytes( buff, 4 );
5

6
          spi_write_dword( 0x000001 );
7
    }
1
void spi_write_dword( uint32_t _data )
2
{
3
  REG_WRITE( SPI_MS_DLEN_REG, 32 -1 );
4
  
5
  //#define REG_WRITE(_r, _b)      (*(volatile uint32_t*)(_r)) = (_b) 
6
  //##define SPI_Wn_REG(n)         SPI2_REG((0x98+(n*4))) 
7
  REG_WRITE( SPI_Wn_REG(0), _data );
8

9
  REG_SET_BIT( SPI_CMD_REG, SPI_UPDATE_bm );
10
  while ( REG_READ( SPI_CMD_REG ) & SPI_UPDATE_bm ){};
11

12
  REG_SET_BIT( SPI_CMD_REG, SPI_USR_bm );
13
  while ( REG_READ( SPI_CMD_REG ) & SPI_USR_bm ){};    
14
}
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren