Weird PROGMEM behaviours

I'm experiencing some weird issues when using PROGMEM to store an array of values in flash memory.

The code is:

#include <avr/pgmspace.h>

const PROGMEM uint32_t common_values[] = {
  10, 11, 12, 13, 15, 16, 18, 20, 22, 24, 27, 30, 33, 36, 39, 43, 47, 51, 56, 62, 68, 75, 82, 91,
  100, 110, 120, 130, 150, 160, 180, 200, 220, 240, 270, 300, 330, 360, 390, 430, 470, 510, 560, 620, 680, 750, 820, 910,
  1000, 1100, 1200, 1300, 1500, 1600, 1800, 2000, 2200, 2400, 2700, 3000, 3300, 3600, 3900, 4300, 4700, 5100, 5600, 6200, 6800, 7500, 8200, 9100,
  10000, 11000, 12000, 13000, 15000, 16000, 18000, 20000, 22000, 24000, 27000, 30000, 33000, 36000, 39000, 43000, 47000, 51000, 56000, 62000, 68000, 75000, 82000, 91000,
  100000, 110000, 120000, 130000, 150000, 160000, 180000, 200000, 220000, 240000, 270000, 300000, 330000, 360000, 390000, 430000, 470000, 510000, 560000, 620000, 680000, 750000, 820000, 910000,
  1000000, 1100000, 1200000, 1300000, 1500000, 1600000, 1800000, 2000000, 2200000, 2400000, 2700000, 3000000, 3300000, 3600000, 3900000, 4300000, 4700000, 5100000, 5600000, 6200000, 6800000, 7500000, 8200000, 9100000,
  10000000, 11000000, 12000000, 13000000, 15000000, 16000000, 18000000, 20000000, 22000000, 24000000, 27000000, 30000000, 33000000, 36000000, 39000000, 43000000, 47000000, 51000000, 56000000, 62000000, 68000000, 75000000, 82000000, 91000000,
  100000000, 110000000, 120000000, 130000000, 150000000, 160000000, 180000000, 200000000, 220000000, 240000000, 270000000, 300000000, 330000000, 360000000, 390000000, 430000000, 470000000, 510000000, 560000000, 620000000, 680000000, 750000000, 820000000, 910000000
};

#define NUM_COMMON_VALS 192

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
for (unsigned int i = 0; i < NUM_COMMON_VALS; i++)
  {
    uint32_t i_th_common_value = pgm_read_word_near(common_values + i);
    Serial.println(i_th_common_value);
  }
}

The results I'm getting are:

10
11
12
13
15
16
18
20
22
24
27
30
33
36
39
43
47
51
56
62
68
75
82
91
100
110
120
130
150
160
180
200
220
240
270
300
330
360
390
430
470
510
560
620
680
750
820
910
1000
1100
1200
1300
1500
1600
1800
2000
2200
2400
2700
3000
3300
3600
3900
4300
4700
5100
5600
6200
6800
7500
8200
9100
10000
11000
12000
13000
15000
16000
18000
20000
22000
24000
27000
30000
33000
36000
39000
43000
47000
51000
56000
62000
2464
9464
16464
25464
34464
44464
54464
64464
18928
28928
48928
3392
23392
43392
7856
37856
2320
32320
62320
36784
11248
51248
35712
30176
24640
29104
33568
58032
16960
51424
20352
54816
58208
27136
30528
33920
37312
40704
13024
50880
23200
61056
33376
40160
46944
53728
29440
39616
49792
28896
8000
56032
38528
55488
6912
23872
57792
9216
43136
11520
45440
13824
64704
50048
35392
20736
6080
8384
10688
12992
32256
2944
39168
26816
14464
36032
57600
30592
3584
42112
53632
26624
38144
49664
61184
7168
57216
41728
26240
10752
60800
18304
41344
64384
60416
29440
64000
6016
13568
32640

As you can see it goes a bit screwey after 62000. I'm using uint32_t, so I wouldn't have expected this to be a roll-over issue.

Am I missing somethign basic?

Any help much appreciated!

What type does pgm_read_word_near() read?

PaulS:
What type does pgm_read_word_near() read?

it reads uint16_t, as far as I know, NOT uint32_t!

It says here (PROGMEM - Arduino Reference) that "The PROGMEM keyword .... should be used only with the datatypes defined in pgmspace.h" and uint32_t is defined in pgmspace.h (avr-libc: <avr/pgmspace.h>: Program Space Utilities) so that's really disappointing if the Arduino documentation is misleading.

But yes, as uint16_t's upper limit is close to 2^16, that makes sense why it's not working, and going wrong after 62000 and before 68000 (>2^16)!

It says here (PROGMEM - Arduino Reference) that "The PROGMEM keyword .... should be used only with the datatypes defined in pgmspace.h" and uint32_t is defined in pgmspace.h (avr-libc: <avr/pgmspace.h>: Program Space Utilities) so that's really disappointing if the Arduino documentation is misleading

I see nothing misleading there - am I missing something basic?
There's nothing at all with using PROGMEM and uint32_t, it's the read function you've used which is incorrect.

You CAN store uint32_ts in PROGMEM. You just need to KNOW that they are uint32_ts and read all 4 bytes, 2 at a time using pgm_read_word_near().

PaulS:
You CAN store uint32_ts in PROGMEM. You just need to KNOW that they are uint32_ts and read all 4 bytes, 2 at a time using pgm_read_word_near().

Or use pgm_read_dword_near() as most people would.

Or use pgm_read_dword_near() as most people would.

Well, most people would look at the stupid PROGMEM reference page, where that function isn't even mentioned.

PaulS:
Well, most people would look at the stupid PROGMEM reference page, where that function isn't even mentioned.

The dword reading function is mentioned in the AVR LIBC manual.

And in case, someone needs an explanation of "dword":
dword has the meaning of "double-word", this is two words of 16 bit each = 32 bis total.