0

I have an array uint8_t data[256]. But each element is single byte. My data bus is 32 bit long. So, If I want to access 32 bits, I do:

DATA = data[i] + (data[i + 1] << 8) + (data[i + 2] << 16) + (data[i + 3] << 24);

But this translates into 4 separate read requests in the memory of one byte each.

How can I access all the 4 bytes in the form of single transaction?

chqrlie
  • 131,814
  • 10
  • 121
  • 189
Rgarg
  • 496
  • 3
  • 6
  • 13
  • 1
    If `data` is of type `int [256]`, not only one byte is read for each summand. – mafso Oct 12 '14 at 21:29
  • 1
    You would have to be using a very non-standard compiler to have `int data[256];` be composed of single-bytes. The 'bytes' would have to be at least 16 bits each (CHAR_BIT == 16). There is some confusion in the assumptions you're making, I think. If, as one of your comments suggests, you mean `uint8_t data[256];`, then one question is 'are you going to index at values of `i` that are not multiples of 4'? and another question is 'what happens if you try to access an 'improperly aligned' memory address as a 4-byte unit?' You need to know the answers to both before risking short-cuts. – Jonathan Leffler Oct 12 '14 at 23:03

4 Answers4

2

If you know the endian-ness of your data (or if you don't care), and your data is aligned (or have a byte-addressing process and you don't care about efficiency) you can cast data to a uint32_t * and access it in 4-byte chucks, like so:

DATA = ((uint32_t *)data)[i/4];

This of course assumes i is a multiple of 4.

Dwayne Towell
  • 8,154
  • 4
  • 36
  • 49
1

Just cast data to uint32_t.

uint8_t data[256] = {1,2,3,4,5,6,7,8} ;

int main(int argc, char **argv)
{
  int index = 1 ;
  uint32_t d = *(uint32_t *)(data + index) ;
  printf ("%08x\n", d) ;
}

Output on a little endian architecture will be

05040302

Output on a big endian architecture will be

02030405

However depending on the achitecture of the processor your progam is running on, you might run into memory alignment problems (performance hit if you address an unaligned memory, or even a crash if your processor doesn't support unaligned memory addressing).

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • I tried this and this almost worked: The data that I have is 01,02,03,04,05,06,07,08... When I access the first location as *(long *)(data+0), I get 0x01030201 instead of 0x04030201. And when I access *(long *) (data+1), I get 0x05040302. This means data[4]=4, But the value returned is incorrect, do you have any idea, why this is the case? – Rgarg Oct 14 '14 at 21:08
  • The code works fine here. Ask a new question on stackoverflow with this specific issue. – Jabberwocky Oct 15 '14 at 07:42
  • Will the output depend on the chip architecture? I was under the impression that the output will be architecture-independent, just like bit-shifting, etc. This would explain why @Rgarg got 0x05040302 and not the little-endian representation even though he/she is likely on a chip using little-endian representation under the hood. – Adam Thompson Jul 29 '18 at 02:51
  • `uint32_t d = *(uint32_t *)(data + index) ;` with `index = 1` is an unaligned access, with potential undefined behavior. – chqrlie Mar 03 '20 at 13:44
  • @chqrlie that was already mentioned in the last sentence of the answer. – Jabberwocky Mar 03 '20 at 14:09
  • @Jabberwocky: indeed you mention it as a possibility, but given the index value, the probability is quite high for an unaligned memory access, which, as you say, may or may not cause a crash depending on the architecture and configuration. – chqrlie Mar 03 '20 at 22:17
0

Maybe you should store data as an array of 32-bit:

uint32_t data[64];
DATA = data[i];
DATA = data[i+1];
...
Darkhan
  • 1,258
  • 2
  • 13
  • 21
  • I cannot modify the array. Its a constraint. But if we look at it, from the memory perspective, isn't it the same thing? uint32_t data[64] and uint8_t data[256]? – Rgarg Oct 12 '14 at 22:05
  • @Rgarg: What is the type of your array? In the question, you say `int data[256];` but here in your comment you seem to be saying `uint8_t data[256];` — these are very different! It makes a wreck out of your question, in fact. – Jonathan Leffler Oct 12 '14 at 23:05
-1

As @dwayne-towell mentioned - you need to care of endianness of you data. In one transaction it might be realized like an example below:

#include <stdio.h>
#include <stdint.h>

int
main()
{
        uint8_t data[256];
        uint32_t i, *p;

        // Add some 32bit numbers
        p = (uint32_t *)data;
        for (i = 0; i < sizeof(data)/sizeof(uint32_t); ++i) {
                *(p++) = i;
        }

        // Print some 32bit numbers
        p = (uint32_t *)data;
        for (i = 0; i < sizeof(data)/sizeof(uint32_t); ++i) {
                printf("value=%u\n", *(p++));
        }

        return (0);
}
soerium
  • 573
  • 4
  • 12