Teensy 4.1 Beta Test

@mjs513 - Dropped that change in startup.c and the log test here seemed to run okay.

Thanks for testing with the latest changes to the logger. I tried it with the memTest, flashtest6, and the last loggerv3 sketches which showed it working. BTW did try at 1Ghz and seemed to work as well. Only ran at 88Mhz.
 
in 1.52-beta5, PSRAM clock is not being set correctly see post

EDIT

(fixed on github 18 hours ago with 88 mhz update)
 
Last edited:
at the moment I am experimenting with using 2 PSRAMs with T4.1 for audio processing (guitar cabinet impulse - partitioned convolution filtering).
However, it seems the PSRAM is too slow for large filters. (I use TD1.52 beta-5 and the fix in startup.c to adjust for 88MHz PSRAM speed: or is that only the speed for FLASH?)
So I tried to increase the speed in startup.c, but I do not understand the syntax correctly:
* CCM_CBCMR_FLEXSPI2_PODF is the divider
* but what is the reference frequency that is divided?
* CCM_CBCMR_FLEXSPI2_CLK_SEL : this selects the clock, but which one should I use
Sorry for my non-existent knowledge of fundamental clock management in the T4.x, but how can I calculate the speed of the PSRAM

this setting below speeds up things a lot, but obviously I do not know what I am doing here . . . and I have not yet attached ADC/DAC, so I do not know whether the PSRAM really works properly at this kind of speed.
Code:
    // turn on clock  (TODO: increase clock speed later, slow & cautious for first release)
    CCM_CBCMR = (CCM_CBCMR & ~(CCM_CBCMR_FLEXSPI2_PODF_MASK | CCM_CBCMR_FLEXSPI2_CLK_SEL_MASK))
        | CCM_CBCMR_FLEXSPI2_PODF(1) | CCM_CBCMR_FLEXSPI2_CLK_SEL(0); // much faster than allowed??
 
@KurtE
I can give this a try - do I put it in startup.c? Have the perfect test for it.

There are two parts. The function mentioned, which is pretty straight forward and we can place anywhere.
And then the init stuff that would need to probably go in startup.c... Although in theory could be self contained, within the actual function.

That is we could have
uint8_t *extmem_next_free = nullptr;
And then have the code here if nullptr, there are two cases.
It checks to see value of external_psram_size setup in startup.c

The problem I see right now is we are now is I am not seeing anything defined in the executable about what is the end of variables that were defined for this area of memory.
If I run nm on the the ILI9488_t3 code using that as frame buffer and then look at what nm spits out and sort it I see:
Code:
60001b00 T __init_array_end
6001513c A _sdataload
70000000 b $d
70000000 B extmem_frame_buffer
aaaaaabf A _flexram_bank_config
So probably need linker script change to make it work this way.

However could probably hack it to instead setup to point at the end of external RAM and instead of incrementing the pointer, we instead decrement and return the decremented pointer.
We run the risk if you do it too much it will collide with your statically defined vars... But would get us up and running.

Got to run...
 
at the moment I am experimenting with using 2 PSRAMs with T4.1 for audio processing (guitar cabinet impulse - partitioned convolution filtering).
However, it seems the PSRAM is too slow for large filters. (I use TD1.52 beta-5 and the fix in startup.c to adjust for 88MHz PSRAM speed: or is that only the speed for FLASH?)
So I tried to increase the speed in startup.c, but I do not understand the syntax correctly:
* CCM_CBCMR_FLEXSPI2_PODF is the divider
* but what is the reference frequency that is divided?
* CCM_CBCMR_FLEXSPI2_CLK_SEL : this selects the clock, but which one should I use
Sorry for my non-existent knowledge of fundamental clock management in the T4.x, but how can I calculate the speed of the PSRAM

this setting below speeds up things a lot, but obviously I do not know what I am doing here . . . and I have not yet attached ADC/DAC, so I do not know whether the PSRAM really works properly at this kind of speed.
Code:
    // turn on clock  (TODO: increase clock speed later, slow & cautious for first release)
    CCM_CBCMR = (CCM_CBCMR & ~(CCM_CBCMR_FLEXSPI2_PODF_MASK | CCM_CBCMR_FLEXSPI2_CLK_SEL_MASK))
        | CCM_CBCMR_FLEXSPI2_PODF(1) | CCM_CBCMR_FLEXSPI2_CLK_SEL(0); // much faster than allowed??

The PSRAM data sheet says max SPI CLK is 133 mhz. try
Code:
CCM_CBCMR = (CCM_CBCMR & ~(CCM_CBCMR_FLEXSPI2_PODF_MASK | CCM_CBCMR_FLEXSPI2_CLK_SEL_MASK))
              | CCM_CBCMR_FLEXSPI2_PODF(4) | CCM_CBCMR_FLEXSPI2_CLK_SEL(2);  //133 mhz
SEL() selects from these frequencies, clocks[4] = {396.0f, 720.0f, 664.62f, 528.0f}

some memcpy() performance numbers here
 
at the moment I am experimenting with using 2 PSRAMs with T4.1 for audio processing (guitar cabinet impulse - partitioned convolution filtering).
However, it seems the PSRAM is too slow for large filters. (I use TD1.52 beta-5 and the fix in startup.c to adjust for 88MHz PSRAM speed: or is that only the speed for FLASH?)
So I tried to increase the speed in startup.c, but I do not understand the syntax correctly:
* CCM_CBCMR_FLEXSPI2_PODF is the divider
* but what is the reference frequency that is divided?
* CCM_CBCMR_FLEXSPI2_CLK_SEL : this selects the clock, but which one should I use
Sorry for my non-existent knowledge of fundamental clock management in the T4.x, but how can I calculate the speed of the PSRAM

this setting below speeds up things a lot, but obviously I do not know what I am doing here . . . and I have not yet attached ADC/DAC, so I do not know whether the PSRAM really works properly at this kind of speed.
Code:
    // turn on clock  (TODO: increase clock speed later, slow & cautious for first release)
    CCM_CBCMR = (CCM_CBCMR & ~(CCM_CBCMR_FLEXSPI2_PODF_MASK | CCM_CBCMR_FLEXSPI2_CLK_SEL_MASK))
        | CCM_CBCMR_FLEXSPI2_PODF(1) | CCM_CBCMR_FLEXSPI2_CLK_SEL(0); // much faster than allowed??

@manitou
This is what we had in lib originally that we were testing with a clock of 132Mhz
Code:
	  // turn on clock  (TODO: increase clock speed later, slow & cautious for first release)
	  CCM_CBCMR = (CCM_CBCMR & ~(CCM_CBCMR_FLEXSPI2_PODF_MASK | //CCM_CBCMR_FLEXSPI2_CLK_SEL_MASK))
		  | CCM_CBCMR_FLEXSPI2_PODF(4) | CCM_CBCMR_FLEXSPI2_CLK_SEL(2); // 528/5 = 132 MHz
	  CCM_CCGR7 |= CCM_CCGR7_FLEXSPI2(CCM_CCGR_ON);
 
Well, if you do a 6th beta, it might make sense to add my Audio-GUI patch..
Otherwise, or if it's too late, do it for 1.53.
 
@KurtE
I can give this a try - do I put it in startup.c? Have the perfect test for it.
@Paul and @mjs513, I know it is too late for this release, but here is a quick and dirty and test sketch that probably beats the heck out of memory. Needs no core changes...


Code:
#define COUNT_ALLOC 1250000
extern "C" {
  extern uint8_t external_psram_size;
}
uint8_t *extmem_next_free = nullptr;  // set in startup NULL if we don't have external memory
extern uint8_t *malloc_extmem(size_t cb_alloc);

uint16_t *buffer1;
uint16_t *buffer2;
uint16_t *buffer3;

void setup() {
  pinMode(13, OUTPUT);
  while (!Serial && millis() < 4000) ;
  Serial.begin(115200);

  Serial.printf("External PSRAM size: %d\n", external_psram_size);
  Serial.flush();
  [COLOR="#006400"]if (external_psram_size == 8) {
    extmem_next_free = (uint8_t*)(0x70800000l);
  } else if (external_psram_size == 16) {
    extmem_next_free = (uint8_t*)(0x71000000l);
  } else {
    Serial.println("No external memory");
    for (;;) {
      digitalWrite(13, !digitalRead(13));
      delay(250);
    }
  }[/COLOR]
  buffer1 = (uint16_t*)malloc_extmem(COUNT_ALLOC * sizeof(uint16_t));
  buffer2 = (uint16_t*)malloc_extmem(COUNT_ALLOC * sizeof(uint16_t));
  buffer3 = (uint16_t*)malloc_extmem(COUNT_ALLOC * sizeof(uint16_t));
  Serial.printf("B1:%x B2:%x B3: %x\n", (uint32_t)buffer1, (uint32_t)buffer2, (uint32_t)buffer3);
  Serial.flush();
}
[COLOR="#006400"]uint8_t *malloc_extmem(size_t cb_alloc) {
  if (!extmem_next_free) return nullptr;
  // lets allocate and return on 16 byte boundaries.
  uint8_t *ret_val = (uint8_t *)((uint32_t)(extmem_next_free - cb_alloc) & 0xfffffff0);

  // BUGBUG only comparing that we run of EXTERNAL memory not that we overrun pre allocated
  if (ret_val < 0x70000000l) return nullptr;
  extmem_next_free = ret_val;
  return ret_val;
}
void free_extmem(char *p) {
  // we don't do any free yet
}[/COLOR]
uint32_t loop_count = 0;
void loop() {
  digitalWrite(13, !digitalRead(13));
  loop_count++;
  for (uint32_t i = 0; i < COUNT_ALLOC; i++) {
    buffer1[i] = i & 0xffff;
    buffer2[i] = loop_count & 0xff;
    buffer3[i] = buffer1[i] ^ buffer2[i];
  }
  uint32_t error_count = 0;
  for (uint32_t i = 0; i < COUNT_ALLOC; i++) {
    if ((buffer1[i] != (i & 0xffff)) || (buffer2[i] != (loop_count & 0xffff)) || (buffer3[i] != (buffer1[i] ^ buffer2[i]))) {
      error_count++;
      if (error_count < 5) Serial.printf("%u %x %x %x\n", i, buffer1[i], buffer2[i], buffer3[i]);
    }
  }
  Serial.printf("Pass %d error count: %d\n", loop_count, error_count);
}


Output:
Code:
External PSRAM size: 8
B1:7059da60 B2:7033b4c0 B3: 700d8f20
Pass 1 error count: 0
Pass 2 error count: 0
Pass 3 error count: 0
Would be pretty easy to hack in...

I am running beta 6
 
Soldered a pair of 8MB (IPUS) PSRAMs to a new T_4.1 - powered up and found 16 MB PSRAM.

Found Paul's Random test and that worked - with TD 1.52 B6 ::
Code:
T:\tCode\RAM\PJRCtestPSRAM\PJRCtestPSRAM.ino May 14 2020 19:20:10
PSRAM: 16 MB
EXTMEM Memory Test, 16 Mbyte
 CCM_CBCMR=B5AE8304 (88.0 MHz)
testing with fixed pattern 5A698421
testing with pseudo-random sequence, seed=2976674124
testing with pseudo-random sequence, seed=1438200953
...
testing with fixed pattern FFFFFFFF
testing with fixed pattern 00000000
 test ran for 73.31 seconds
All memory tests passed :-)

Just added KurtE p#586 sketch to that and it is running 250+ Passes and error count =0;

EDIT: As soon as I posted ::
Code:
Pass 253 error count: 0
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
Pass 254 error count: 0
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
Pass 255 error count: 0
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
0 0 0 0
1 1 0 1
2 2 0 2
3 3 0 3
Pass 256 error count: 1250000
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
0 0 1 1
1 1 1 0
2 2 1 3
3 3 1 2
Pass 257 error count: 1250000
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
0 0 2 2
1 1 2 3
2 2 2 0
3 3 2 1
Pass 258 error count: 1250000
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
0 0 3 3
1 1 3 2
2 2 3 1
3 3 3 0
Pass 259 error count: 1250000
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
0 0 4 4
1 1 4 5
2 2 4 6
3 3 4 7
Pass 260 error count: 1250000
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20

Similar/same repeat at the same point on starting KurtE code again:
Code:
Pass 254 error count: 0
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
Pass 255 error count: 0
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
0 0 0 0
1 1 0 1
2 2 0 2
3 3 0 3
Pass 256 error count: 1250000
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
0 0 1 1
1 1 1 0
2 2 1 3
3 3 1 2
Pass 257 error count: 1250000
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
 
Last edited:
Back to that PSRAM logger - bumped each of two buffers to 7,864,320 Bytes and running fine with 2.47 seconds of samples at 200,000 _isr()'s per second

Like above it was running well a long time - and typed a line and something went wrong.

Restarted it … all well so far.

>> EDIT >> Restart cycling a full hour now and no issue? First run was way less than that - a few minutes?
 
Last edited:
Just added KurtE p#586 sketch to that and it is running 250+ Passes and error count =0;

EDIT: As soon as I posted ::
Code:
Pass 253 error count: 0
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
Pass 254 error count: 0
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
Pass 255 error count: 0
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
0 0 0 0
1 1 0 1
2 2 0 2
3 3 0 3
Pass 256 error count: 1250000

The errors beginning at pass 256 are due to this line:

Code:
    buffer2[i] = loop_count & 0xff;

It should be this:

Code:
    buffer2[i] = loop_count & 0xffff;

Here is a complete copy with that issue fixed.

Code:
#define COUNT_ALLOC 1250000
extern "C" {
  extern uint8_t external_psram_size;
}
uint8_t *extmem_next_free = nullptr;  // set in startup NULL if we don't have external memory
extern uint8_t *malloc_extmem(size_t cb_alloc);

uint16_t *buffer1;
uint16_t *buffer2;
uint16_t *buffer3;

void setup() {
  pinMode(13, OUTPUT);
  while (!Serial && millis() < 4000) ;
  Serial.begin(115200);

  Serial.printf("External PSRAM size: %d\n", external_psram_size);
  Serial.flush();
  if (external_psram_size == 8) {
    extmem_next_free = (uint8_t*)(0x70800000l);
  } else if (external_psram_size == 16) {
    extmem_next_free = (uint8_t*)(0x71000000l);
  } else {
    Serial.println("No external memory");
    for (;;) {
      digitalWrite(13, !digitalRead(13));
      delay(250);
    }
  }
  buffer1 = (uint16_t*)malloc_extmem(COUNT_ALLOC * sizeof(uint16_t));
  buffer2 = (uint16_t*)malloc_extmem(COUNT_ALLOC * sizeof(uint16_t));
  buffer3 = (uint16_t*)malloc_extmem(COUNT_ALLOC * sizeof(uint16_t));
  Serial.printf("B1:%x B2:%x B3: %x\n", (uint32_t)buffer1, (uint32_t)buffer2, (uint32_t)buffer3);
  Serial.flush();
}
uint8_t *malloc_extmem(size_t cb_alloc) {
  if (!extmem_next_free) return nullptr;
  // lets allocate and return on 16 byte boundaries.
  uint8_t *ret_val = (uint8_t *)((uint32_t)(extmem_next_free - cb_alloc) & 0xfffffff0);

  // BUGBUG only comparing that we run of EXTERNAL memory not that we overrun pre allocated
  if (ret_val < 0x70000000l) return nullptr;
  extmem_next_free = ret_val;
  return ret_val;
}
void free_extmem(char *p) {
  // we don't do any free yet
}
uint32_t loop_count = 0;
void loop() {
  digitalWrite(13, !digitalRead(13));
  loop_count++;
  for (uint32_t i = 0; i < COUNT_ALLOC; i++) {
    buffer1[i] = i & 0xffff;
    buffer2[i] = loop_count & 0xffff;
    buffer3[i] = buffer1[i] ^ buffer2[i];
  }
  uint32_t error_count = 0;
  for (uint32_t i = 0; i < COUNT_ALLOC; i++) {
    if ((buffer1[i] != (i & 0xffff)) || (buffer2[i] != (loop_count & 0xffff)) || (buffer3[i] != (buffer1[i] ^ buffer2[i]))) {
      error_count++;
      if (error_count < 5) Serial.printf("%u %x %x %x\n", i, buffer1[i], buffer2[i], buffer3[i]);
    }
  }
  Serial.printf("Pass %d error count: %d\n", loop_count, error_count);
}
 
Thanks Paul - figured it was something simple - I moved on hoping KurtE might be online for an answer ...

Odd that Log code p#588 ... died quickly once then just finished 1406238719 _isr() calls which at 200K/sec is 1.95 hours.

Edited that line and returned to that sketch and all looks well. Ran your RND() test then it falls into KurtE's … just hit Pass 350 …

<edit> : just stopped that KurtE extended run:
Code:
Pass 3000 error count: 0
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
Pass 3001 error count: 0
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
 
Last edited:
Good Morning all
Guess I missed fun stuff again last night (at least for me it 6am). A couple of additional tests with PSRAM:

1. Ran the memtest sketch and @KurtE's new malloc test at 24Mhz all is working with PSRAM even at low speeds.
2. Ran sketch is post #589 again at 816Mhz and no errors - right now up to 550.
 
Sorry about that, at times I was switching around sizes of variables... Also it was more setup to see if the quick and dirty allocater would work.
Here is an updated version which is more self contained.
Code:
#define COUNT_ALLOC 1250000


//===============================================================================
#if defined(ARDUINO_TEENSY41)
extern "C" {
  extern uint8_t external_psram_size;
}
uint8_t *extmem_next_free = nullptr;  // set in startup NULL if we don't have external memory

uint8_t *malloc_extmem(size_t cb_alloc) {
  if (!extmem_next_free) extmem_next_free = 0x70000000l + (uint32_t)(external_psram_size * 1048576);
        // lets allocate and return on 16 byte boundaries.
        uint8_t *ret_val = (uint8_t *)((uint32_t)(extmem_next_free - cb_alloc) & 0xfffffff0);

  // BUGBUG only comparing that we run of EXTERNAL memory not that we overrun pre allocated
  if (ret_val < 0x70000000l) return nullptr;
  extmem_next_free = ret_val;
  return ret_val;
}
#else
uint8_t *malloc_extmem(size_t cb_alloc) {
  return nullptr;
}
#endif
void free_extmem(char *p) {
  // we don't do any free yet
}
//===============================================================================


extern uint8_t *malloc_extmem(size_t cb_alloc);

uint16_t *buffer1;
uint16_t *buffer2;
uint16_t *buffer3;

void setup() {
  pinMode(13, OUTPUT);
  while (!Serial && millis() < 4000) ;
  Serial.begin(115200);

#if defined(ARDUINO_TEENSY41)
  Serial.printf("External PSRAM size: %d\n", external_psram_size);
#endif
  buffer1 = (uint16_t*)malloc_extmem(COUNT_ALLOC * sizeof(uint16_t));
  buffer2 = (uint16_t*)malloc_extmem(COUNT_ALLOC * sizeof(uint16_t));
  buffer3 = (uint16_t*)malloc_extmem(COUNT_ALLOC * sizeof(uint16_t));
  Serial.printf("B1:%x B2:%x B3: %x\n", (uint32_t)buffer1, (uint32_t)buffer2, (uint32_t)buffer3);
  if (!buffer1 || !buffer2 || !buffer3) {
    Serial.println("Failed to allocate external memory");
    for (;;) {
      digitalWrite(13, !digitalRead(13));
      delay(250);
    }
  }
}

uint32_t loop_count = 0;
void loop() {
  digitalWrite(13, !digitalRead(13));
  loop_count++;
  for (uint32_t i = 0; i < COUNT_ALLOC; i++) {
    buffer1[i] = i & 0xffff;
    buffer2[i] = loop_count & 0xffff;
    buffer3[i] = buffer1[i] ^ buffer2[i];
  }
  uint32_t error_count = 0;
  for (uint32_t i = 0; i < COUNT_ALLOC; i++) {
    if ((buffer1[i] != (i & 0xffff)) || (buffer2[i] != (loop_count & 0xffff)) || (buffer3[i] != (buffer1[i] ^ buffer2[i]))) {
      error_count++;
      if (error_count < 5) Serial.printf("%u %x %x %x\n", i, buffer1[i], buffer2[i], buffer3[i]);
    }
  }
  Serial.printf("Pass %d error count: %d\n", loop_count, error_count);
}
Ran it on two T4.1s. One with no extra memory and the other with 8. Have not tried 16 yet. Don't have one setup for that yet. Although I do have 1 (meant to order 2 or 3) new T4.1 and 3 memory chips so could setup.

EDIT: Also compiled and ran on T4 which failed the allocates and went into blinking...

But again I assume an addition like this would need to wait until the next Teensyduino.
 
@KurtE

Same here. Have a couple of T4.1's and extra memory chips but haven't soldered one up with the 2 PSRAMs. Maybe today will solder one up:)

Maybe Mr. S. will get inspired and not wait until 1.53 :) but I think he has enough on his plate at this point make a change like this at this point in the release cycle for 1.52.
 
@manitou, @mjs513: thanks for pointing me to the speed change code for PSRAM SPI!

I tried using T4.1 plus two soldered PSRAM chips and Teensy audio shield with partitioned convolution filtering @44.1kHz sample rate using this code: [https://forum.pjrc.com/threads/60886-Teensyduino-1-52-Beta-6?p=239417&viewfull=1#post239417]

Tried to substitute the buffers using DMAMEM with EXTMEM. EXTMEM is a little slow, so I put SPI freq to 132MHz in startup.c: that made the code run faster (14.1% vs. 18% processor load), but the audio is scrambled then.

Maybe 132MHz is not suitable for the PSRAM chips, as some of you mentioned? I think it is not the audio processing itself, because processor load is quite low, so the cause must be incorrect reading from the EXTMEM @132MHz. The array variable (float32_t fmask[16][512]) in EXTMEM is written once in setup and then it is only read during audio processing.
 
would someone point to where Vbat is?
The "welcome to teensy 4.1" pinout image doesn't mention what the pads between 27 and 38 do?
 
would someone point to where Vbat is?
The "welcome to teensy 4.1" pinout image doesn't mention what the pads between 27 and 38 do?

Same things as T4 except moved back... (ON/OFF, Program, GND, 3.3v, VBat) - Most of these are the same as the T3.5 or T3.6, except on T3.6...
On/OFF is Program...
 
would someone point to where Vbat is?
The "welcome to teensy 4.1" pinout image doesn't mention what the pads between 27 and 38 do?

Vbat is the pin you connect the positive lead from a coin battery (you connect the negative lead to ground). With the coin battery, the real time clock will be powered when there is no power to the main Teensy.

In terms of pinouts (on/off, program, ground, 3.3v, vbat), look at the back of the Teensy 4.0. The 5 pins are in the same order in the 4.1, they are just moved further away.
 
Sorry about that, at times I was switching around sizes of variables... Also it was more setup to see if the quick and dirty allocater would work.
Here is an updated version which is more self contained.
...
Ran it on two T4.1s. One with no extra memory and the other with 8. Have not tried 16 yet. Don't have one setup for that yet. Although I do have 1 (meant to order 2 or 3) new T4.1 and 3 memory chips so could setup.

EDIT: Also compiled and ran on T4 which failed the allocates and went into blinking...

But again I assume an addition like this would need to wait until the next Teensyduino.

@KurtE
Did a little hacking (since I don't know how to do it right) but I added this to startup.c:
Code:
__attribute__((weak))
uint8_t *extmem_next_free = 0;  // set in startup NULL if we don't have external memory

__attribute__((weak))
uint8_t *malloc_extmem(size_t cb_alloc) {
  if (!extmem_next_free) return 0;
  // lets allocate and return on 16 byte boundaries.
  uint8_t *ret_val = (uint8_t *)((uint32_t)(extmem_next_free - cb_alloc) & 0xfffffff0);

  // BUGBUG only comparing that we run of EXTERNAL memory not that we overrun pre allocated
  if (ret_val < 0x70000000l) return 0;
  extmem_next_free = ret_val;
  return ret_val;
}

__attribute__((weak))
void free_extmem(char *p) {
  // we don't do any free yet
}
I made changed nullptr to 0 since the compiler didn't like nullptr (no clue on how to fix that)

and added this to the sketch:

Code:
extern "C" {
  extern uint8_t external_psram_size;
[COLOR="#FF0000"]  uint8_t *extmem_next_free;  // set in startup NULL if we don't have external memory
  uint8_t *malloc_extmem(size_t cb_alloc);
  void free_extmem(char *p);[/COLOR]
}
The code ran and is still running.
Code:
#define COUNT_ALLOC 1250000
extern "C" {
  extern uint8_t external_psram_size;
  uint8_t *extmem_next_free;  // set in startup NULL if we don't have external memory
  uint8_t *malloc_extmem(size_t cb_alloc);
  void free_extmem(char *p);
}

uint16_t *buffer1;
uint16_t *buffer2;
uint16_t *buffer3;

void setup() {
  pinMode(13, OUTPUT);
  while (!Serial && millis() < 4000) ;
  Serial.begin(115200);

  Serial.printf("External PSRAM size: %d\n", external_psram_size);
  Serial.flush();
  if (external_psram_size == 8) {
    extmem_next_free = (uint8_t*)(0x70800000l);
  } else if (external_psram_size == 16) {
    extmem_next_free = (uint8_t*)(0x71000000l);
  } else {
    Serial.println("No external memory");
    for (;;) {
      digitalWrite(13, !digitalRead(13));
      delay(250);
    }
  }
  buffer1 = (uint16_t*)malloc_extmem(COUNT_ALLOC * sizeof(uint16_t));
  buffer2 = (uint16_t*)malloc_extmem(COUNT_ALLOC * sizeof(uint16_t));
  buffer3 = (uint16_t*)malloc_extmem(COUNT_ALLOC * sizeof(uint16_t));
  Serial.printf("B1:%x B2:%x B3: %x\n", (uint32_t)buffer1, (uint32_t)buffer2, (uint32_t)buffer3);
  Serial.flush();
}

uint32_t loop_count = 0;
void loop() {
  digitalWrite(13, !digitalRead(13));
  loop_count++;
  for (uint32_t i = 0; i < COUNT_ALLOC; i++) {
    buffer1[i] = i & 0xffff;
    buffer2[i] = loop_count & 0xffff;
    buffer3[i] = buffer1[i] ^ buffer2[i];
  }
  uint32_t error_count = 0;
  for (uint32_t i = 0; i < COUNT_ALLOC; i++) {
    if ((buffer1[i] != (i & 0xffff)) || (buffer2[i] != (loop_count & 0xffff)) || (buffer3[i] != (buffer1[i] ^ buffer2[i]))) {
      error_count++;
      if (error_count < 5) Serial.printf("%u %x %x %x\n", i, buffer1[i], buffer2[i], buffer3[i]);
    }
  }
  Serial.printf("Pass %d error count: %d\n", loop_count, error_count);
}
Did it more out of curiosity. Now to try it on something.
 
@KurtE
Did a little hacking (since I don't know how to do it right) but I added this to startup.c:

Did it more out of curiosity. Now to try it on something.

Put that post #598 into startup and made a sketch of T_4.1__w/8 and T_4.1__w/16 on stock td 1.52 B6

Code:
T:\tCode\RAM\ExtAlloc\ExtAlloc.ino May 15 2020 10:41:09
External PSRAM size: 8
B1:7059da60 B2:7033b4c0 B3: 700d8f20
Pass 1 error count: 0
Pass 2 error count: 0
…
Pass 211 error count: 0
Pass 212 error count: 0
…
Pass 783 error count: 0
Pass 784 error count: 0

Code:
T:\tCode\RAM\ExtAlloc\ExtAlloc.ino May 15 2020 10:41:09
External PSRAM size: 16
B1:70d9da60 B2:70b3b4c0 B3: 708d8f20
Pass 1 error count: 0
Pass 2 error count: 0
Pass 3 error count: 0
…
Pass 254 error count: 0
Pass 255 error count: 0
Pass 256 error count: 0
...

<EDIT> Changed to var :: COUNT_ALLOC = (external_psram_size *1024*1024/3/sizeof(uint16_t))-16;

Code:
T:\tCode\RAM\ExtAlloc\ExtAlloc.ino May 15 2020 10:51:32
External PSRAM size: 16
B1:70aaaac0 B2:70555580 B3: 70000040
Pass 1 error count: 0
Pass 2 error count: 0
Pass 3 error count: 0

and
Code:
T:\tCode\RAM\ExtAlloc\ExtAlloc.ino May 15 2020 10:51:32
External PSRAM size: 8
B1:70555570 B2:702aaae0 B3: 70000050
Pass 1 error count: 0
Pass 2 error count: 0
Pass 3 error count: 0

<edit 2> Also keep seeing these lines reversed - we know it doesn't matter - but it is just odd to see as above:
Code:
  [B]Serial.begin(115200);[/B]
  while (!Serial && millis() < 4000) ;
 
Last edited:
@defragster

Great that it worked for you :) was busy soldering up a T4.1 with 2 PSRAMs for testing :)
 
Back
Top