Forum Rule: Always post complete source code & details to reproduce any issue!
Page 22 of 32 FirstFirst ... 12 20 21 22 23 24 ... LastLast
Results 526 to 550 of 798

Thread: Teensy 4.1 Beta Test

  1. #526
    Junior Member
    Join Date
    Feb 2019
    Posts
    5
    When you declare an array, that's right. When you want to read it with an AVR, you need to use pgm_read_xxx functions afaik.

  2. #527
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,338
    @Frank B
    Having a little issue with SPIFFS with the address change.

    In the original SPIFF code we had a offset of 0x01000000u and now I think the new offset for FlashRam is 0x00800000. If I change the offset in the SPIFFs it no longer seems to be working. In otherwords this works:
    Code:
    static const void* extBase = (void*)0x70000000u;
    static const uint32_t flashBaseAddr = 0x01000000u;
    static uint32_t flashCapacity = 16u * 1024u * 1024u;
    this doesn't work
    Code:
    static const void* extBase = (void*)0x70000000u;
    static const uint32_t flashBaseAddr = 0x00800000u;
    static uint32_t flashCapacity = 16u * 1024u * 1024u;
    What am I missing?

    EDIT: Maybe not missing anything. When I uncomment the a test to print the flash ID I only see the correct address if I use 0x01000000u. Anything else gives me all 0xFFs.

    Here is the code (NOTE you have to change 0x2000 to 0x4000 otherwise it hangs:
    Code:
    	FLEXSPI2_FLSHA1CR0 = 0x4000; // 8 MByte
    	FLEXSPI2_FLSHA1CR1 = FLEXSPI_FLSHCR1_CSINTERVAL(2)
    		| FLEXSPI_FLSHCR1_TCSH(3) | FLEXSPI_FLSHCR1_TCSS(3);
    	FLEXSPI2_FLSHA1CR2 = FLEXSPI_FLSHCR2_AWRSEQID(6) | FLEXSPI_FLSHCR2_AWRSEQNUM(0)
    		| FLEXSPI_FLSHCR2_ARDSEQID(5) | FLEXSPI_FLSHCR2_ARDSEQNUM(0);
    
    	FLEXSPI2_FLSHA2CR0 = 0x4000; // 8 MByte
    Code:
    /*
       This test uses the optional quad spi flash on Teensy 4.1
       https://github.com/pellepl/spiffs/wiki/Using-spiffs
       https://github.com/pellepl/spiffs/wiki/FAQ
    
       ATTENTION: Flash needs to be empty before first use of SPIFFS
    
    
       Frank B, 2020
    */
    
    
    #include <spiffs.h>
    
    static spiffs fs; //filesystem
    
    char buf[512] = "Hello World! What a wonderful World :) Hello World! What a wonderful World :) Hello World! What a wonderful World :) Hello World! What a wonderful World :) Hello World! What a wonderful World :) Hello World! What a wonderful World :) Hello World! What a wonderful World :) Hello World! What a wonderful World :) Hello World! What a wonderful World :) Hello World! What a wonderful World :) Hello World! What a wonderful World :)";
    int szLen = strlen( buf );
    
    void test_spiffs_write() {
      // Surely, I've mounted spiffs before entering here
      spiffs_file fd = SPIFFS_open(&fs, "my_file", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0);
      if (SPIFFS_write(&fs, fd, (u8_t *)buf, szLen) < 0) Serial.printf("errno %i\n", SPIFFS_errno(&fs));
      SPIFFS_close(&fs, fd);
      SPIFFS_fflush(&fs, fd);
    }
    
    static void test_spiffs_read() {
      // Surely, I've mounted spiffs before entering here
      spiffs_file  fd = SPIFFS_open(&fs, "my_file", SPIFFS_RDWR, 0);
      if (SPIFFS_read(&fs, fd, (u8_t *)buf, szLen) < 0) Serial.printf("errno %i\n", SPIFFS_errno(&fs));
      SPIFFS_close(&fs, fd);
    }
    
    static void test_spiffs_listDir() {
      spiffs_DIR d;
      struct spiffs_dirent e;
      struct spiffs_dirent *pe = &e;
    
      SPIFFS_opendir(&fs, "/", &d);
      while ((pe = SPIFFS_readdir(&d, pe))) {
        Serial.printf("%s [%04x] size:%i\n", pe->name, pe->obj_id, pe->size);
      }
      SPIFFS_closedir(&d);
    }
    
    void setup() {
      while (!Serial);
    
    #if 1
      Serial.println("\n Enter 'y' in 6 seconds to format FlashChip - other to skip");
      uint32_t pauseS = millis();
      char chIn = 9;
      while ( pauseS + 6000 > millis() && 9 == chIn ) {
        if ( Serial.available() ) {
          do {
            if ( chIn != 'y' )
              chIn = Serial.read();
            else
              Serial.read();
          }
          while ( Serial.available() );
        }
      }
      if ( chIn == 'y' ) {
        eraseFlashChip();
      }
    #endif
    
      Serial.println("Mount SPIFFS:");
      int res = my_spiffs_mount();
      Serial.printf("mount res: %i\n", res);
    
    #if 1
      Serial.println("Write file:");
      Serial.println(buf);
      test_spiffs_write();
    #endif
    
      Serial.println("Directoy contents:");
      test_spiffs_listDir();
    
      memset(buf, 0, sizeof(buf)); //emtpy buffer
      Serial.println("Read file:");
      test_spiffs_read();
      Serial.println(buf);
    
    }
    
    void loop() {
    }
    
    //********************************************************************************************************
    //********************************************************************************************************
    //********************************************************************************************************
    /*
       QSPI Flash Interface
    */
    
    #define LUT0(opcode, pads, operand) (FLEXSPI_LUT_INSTRUCTION((opcode), (pads), (operand)))
    #define LUT1(opcode, pads, operand) (FLEXSPI_LUT_INSTRUCTION((opcode), (pads), (operand)) << 16)
    #define CMD_SDR         FLEXSPI_LUT_OPCODE_CMD_SDR
    #define ADDR_SDR        FLEXSPI_LUT_OPCODE_RADDR_SDR
    #define READ_SDR        FLEXSPI_LUT_OPCODE_READ_SDR
    #define WRITE_SDR       FLEXSPI_LUT_OPCODE_WRITE_SDR
    #define DUMMY_SDR       FLEXSPI_LUT_OPCODE_DUMMY_SDR
    #define PINS1           FLEXSPI_LUT_NUM_PADS_1
    #define PINS4           FLEXSPI_LUT_NUM_PADS_4
    
    #define FLASH_MEMMAP 1 //Use memory-mapped access
    
    static const void* extBase = (void*)0x70000000u;
    static const uint32_t flashBaseAddr = 0x01000000u;
    static uint32_t flashCapacity = 16u * 1024u * 1024u;
    static char flashID[8];
    
    void setupFlexSPI2() {
      memset(flashID, 0, sizeof(flashID));
    
    
      // cmd index 7 = read ID bytes SPI
      FLEXSPI2_LUT28 = LUT0(CMD_SDR, PINS1, 0x9F) | LUT1(READ_SDR, PINS1, 1); //RAM, FLASH
    
      // ----------------- FLASH only ----------------------------------------------
    
      // cmd index 8 = read Status register #1 SPI
      FLEXSPI2_LUT32 = LUT0(CMD_SDR, PINS1, 0x05) | LUT1(READ_SDR, PINS1, 1);
    
      // cmd index 9 = read Status register #2 SPI
      FLEXSPI2_LUT36 = LUT0(CMD_SDR, PINS1, 0x35) | LUT1(READ_SDR, PINS1, 1);
    
      //cmd index 10 = exit QPI mode
      FLEXSPI2_LUT40 = LUT0(CMD_SDR, PINS4, 0xFF);
    
      //cmd index 11 = write enable QPI
      FLEXSPI2_LUT44 = LUT0(CMD_SDR, PINS4, 0x06);
    
      //cmd index 12 = sector erase
      FLEXSPI2_LUT48 = LUT0(CMD_SDR, PINS4, 0x20) | LUT1(ADDR_SDR, PINS4, 24);
    
      //cmd index 13 = page program
      FLEXSPI2_LUT52 = LUT0(CMD_SDR, PINS4, 0x02) | LUT1(ADDR_SDR, PINS4, 24);
      FLEXSPI2_LUT53 = LUT0(WRITE_SDR, PINS4, 1);
    
      //cmd index 14 = set read parameters
      FLEXSPI2_LUT56 = LUT0(CMD_SDR, PINS4, 0xc0) | LUT1(CMD_SDR, PINS4, 0x20);
    
      //cmd index 15 = enter QPI mode
      FLEXSPI2_LUT60 = LUT0(CMD_SDR, PINS1, 0x38);
    }
    
    void printStatusRegs() {
    #if 0
      uint8_t val;
    
      flexspi_ip_read(8, flashBaseAddr, &val, 1 );
      Serial.print("Status 1:");
      Serial.printf(" %02X", val);
      Serial.printf("\n");
    
      // cmd index 9 = read Status register #2 SPI
      flexspi_ip_read(9, flashBaseAddr, &val, 1 );
      Serial.print("Status 2:");
      Serial.printf(" %02X", val);
      Serial.printf("\n");
    #endif
    }
    
    /*
       Waits for busy bit = 0 (statusregister #1 )
       Timeout is optional
    */
    bool waitFlash(uint32_t timeout = 0) {
      uint8_t val;
      uint32_t t = millis();
      FLEXSPI_IPRXFCR = FLEXSPI_IPRXFCR_CLRIPRXF; // clear rx fifo
      do {
        flexspi_ip_read(8, flashBaseAddr, &val, 1 );
        if (timeout && (millis() - t > timeout)) return 1;
      } while  ((val & 0x01) == 1);
      return 0;
    }
    
    void setupFlexSPI2Flash() {
    
      // reset the chip
      flexspi_ip_command(10, flashBaseAddr); //exit QPI
      flexspi_ip_command(1, flashBaseAddr); //reset enable
      flexspi_ip_command(2, flashBaseAddr); //reset
      delayMicroseconds(50);
    
      flexspi_ip_read(7, flashBaseAddr, flashID, sizeof(flashID) );
    
    #if 1
      Serial.print("ID:");
      for (unsigned i = 0; i < sizeof(flashID); i++) Serial.printf(" %02X", flashID[i]);
      Serial.printf("\n");
    #endif
    
      printStatusRegs();
      //TODO!!!!! set QPI enable bit in status reg #2 if not factory set!!!!!
    
      //  Serial.println("ENTER QPI MODE");
      flexspi_ip_command(15, flashBaseAddr);
    
      //patch LUT for QPI:
      // cmd index 8 = read Status register #1
      FLEXSPI2_LUT32 = LUT0(CMD_SDR, PINS4, 0x05) | LUT1(READ_SDR, PINS4, 1);
      // cmd index 9 = read Status register #2
      FLEXSPI2_LUT36 = LUT0(CMD_SDR, PINS4, 0x35) | LUT1(READ_SDR, PINS4, 1);
    
      flexspi_ip_command(14, flashBaseAddr);
    
      printStatusRegs();
    
    }
    
    void flexspi_ip_command(uint32_t index, uint32_t addr)
    {
      uint32_t n;
      FLEXSPI2_IPCR0 = addr;
      FLEXSPI2_IPCR1 = FLEXSPI_IPCR1_ISEQID(index);
      FLEXSPI2_IPCMD = FLEXSPI_IPCMD_TRG;
      while (!((n = FLEXSPI2_INTR) & FLEXSPI_INTR_IPCMDDONE)); // wait
      if (n & FLEXSPI_INTR_IPCMDERR) {
        Serial.printf("Error: FLEXSPI2_IPRXFSTS=%08lX\n", FLEXSPI2_IPRXFSTS);
      }
      FLEXSPI2_INTR = FLEXSPI_INTR_IPCMDDONE;
    }
    
    void flexspi_ip_read(uint32_t index, uint32_t addr, void *data, uint32_t length)
    {
      uint32_t n;
      uint8_t *p = (uint8_t *)data;
      const uint8_t *src;
    
      FLEXSPI2_IPCR0 = addr;
      FLEXSPI2_IPCR1 = FLEXSPI_IPCR1_ISEQID(index) | FLEXSPI_IPCR1_IDATSZ(length);
      FLEXSPI2_IPCMD = FLEXSPI_IPCMD_TRG;
      while (!((n = FLEXSPI2_INTR) & FLEXSPI_INTR_IPCMDDONE)) {
        if (n & FLEXSPI_INTR_IPRXWA) {
          //Serial.print("*");
          if (length >= 8) {
            length -= 8;
            *(uint32_t *)(p + 0) = FLEXSPI2_RFDR0;
            *(uint32_t *)(p + 4) = FLEXSPI2_RFDR1;
            p += 8;
          } else {
            src = (const uint8_t *)&FLEXSPI2_RFDR0;
            while (length > 0) {
              length--;
              *p++ = *src++;
            }
          }
          FLEXSPI2_INTR = FLEXSPI_INTR_IPRXWA;
        }
      }
      if (n & FLEXSPI_INTR_IPCMDERR) {
        Serial.printf("Error: FLEXSPI2_IPRXFSTS=%08lX\r\n", FLEXSPI2_IPRXFSTS);
      }
      FLEXSPI2_INTR = FLEXSPI_INTR_IPCMDDONE;
      //printf(" FLEXSPI2_RFDR0=%08lX\r\n", FLEXSPI2_RFDR0);
      //if (length > 4) Serial.printf(" FLEXSPI2_RFDR1=%08lX\n", FLEXSPI2_RFDR1);
      //if (length > 8) Serial.printf(" FLEXSPI2_RFDR1=%08lX\n", FLEXSPI2_RFDR2);
      //if (length > 16) Serial.printf(" FLEXSPI2_RFDR1=%08lX\n", FLEXSPI2_RFDR3);
      src = (const uint8_t *)&FLEXSPI2_RFDR0;
      while (length > 0) {
        *p++ = *src++;
        length--;
      }
      if (FLEXSPI2_INTR & FLEXSPI_INTR_IPRXWA) FLEXSPI2_INTR = FLEXSPI_INTR_IPRXWA;
    }
    
    static void flexspi_ip_write(uint32_t index, uint32_t addr, const void *data, uint32_t length)
    {
      const uint8_t *src;
      uint32_t n, wrlen;
    
      FLEXSPI2_IPCR0 = addr;
      FLEXSPI2_IPCR1 = FLEXSPI_IPCR1_ISEQID(index) | FLEXSPI_IPCR1_IDATSZ(length);
      src = (const uint8_t *)data;
      FLEXSPI2_IPCMD = FLEXSPI_IPCMD_TRG;
    
      while (!((n = FLEXSPI2_INTR) & FLEXSPI_INTR_IPCMDDONE)) {
    
        if (n & FLEXSPI_INTR_IPTXWE) {
          wrlen = length;
          if (wrlen > 8) wrlen = 8;
          if (wrlen > 0) {
    
            //memcpy((void *)&FLEXSPI2_TFDR0, src, wrlen); !crashes sometimes!
            //src += wrlen;
            uint8_t *p = (uint8_t *) &FLEXSPI2_TFDR0;
            for (unsigned i = 0; i < wrlen; i++) *p++ = *src++;
            length -= wrlen;
            FLEXSPI2_INTR = FLEXSPI_INTR_IPTXWE;
          }
        }
    
      }
    
      if (n & FLEXSPI_INTR_IPCMDERR) {
        Serial.printf("Error: FLEXSPI2_IPRXFSTS=%08lX\r\n", FLEXSPI2_IPRXFSTS);
      }
    
      FLEXSPI2_INTR = FLEXSPI_INTR_IPCMDDONE;
    }
    
    void eraseFlashChip() {
      setupFlexSPI2();
      setupFlexSPI2Flash();
    
      waitFlash();
      flexspi_ip_command(11, flashBaseAddr);
    
      Serial.println("Erasing... (may take some time)");
      uint32_t t = millis();
      FLEXSPI2_LUT60 = LUT0(CMD_SDR, PINS4, 0x60); //Chip erase
      flexspi_ip_command(15, flashBaseAddr);
    
    #ifdef FLASH_MEMMAP
      arm_dcache_delete((void*)((uint32_t)extBase + flashBaseAddr), flashCapacity);
    #endif
    
      while (waitFlash(500)) {
        Serial.print(".");
      }
    
      t = millis() - t;
      Serial.printf("\nChip erased in %d seconds.\n", t / 1000);
    }
    
    //********************************************************************************************************
    //********************************************************************************************************
    //********************************************************************************************************
    /*
       SPIFFS interface
    */
    
    #define LOG_PAGE_SIZE       256
    
    static u8_t spiffs_work_buf[LOG_PAGE_SIZE * 2];
    static u8_t spiffs_fds[32 * 4];
    static u8_t spiffs_cache_buf[(LOG_PAGE_SIZE + 32) * 4];
    
    //********************************************************************************************************
    static const u32_t blocksize = 4096; //or 32k or 64k (set correct flash commands above)
    
    static s32_t my_spiffs_read(u32_t addr, u32_t size, u8_t *dst) {
    
    #ifdef FLASH_MEMMAP
      memcpy(dst, (uint8_t *)extBase + addr, size);
    #else
      flexspi_ip_read(5, addr, dst, size);
    #endif
      return SPIFFS_OK;
    }
    
    static s32_t my_spiffs_write(u32_t addr, u32_t size, u8_t *src) {
      flexspi_ip_command(11, flashBaseAddr); // write enable
      flexspi_ip_write(13, addr, src, size); // write
    
    #ifdef FLASH_MEMMAP
      arm_dcache_delete((void*)((uint32_t)extBase + addr), size);
    #endif
      waitFlash();
      return SPIFFS_OK;
    }
    
    static s32_t my_spiffs_erase(u32_t addr, u32_t size) {
      int s = size;
      while (s > 0) { //TODO: Is this loop needed, or is size max 4096?
        flexspi_ip_command(11, flashBaseAddr);  //write enable
        flexspi_ip_command(12, addr);
    
    #ifdef FLASH_MEMMAP
        arm_dcache_delete((void*)((uint32_t)extBase + addr), blocksize);
    #endif
    
        addr += blocksize;
        s -= blocksize;
        waitFlash();
      }
      return SPIFFS_OK;
    }
    
    //********************************************************************************************************
    
    int my_spiffs_mount() {
    
      setupFlexSPI2();
      setupFlexSPI2Flash();
    
      spiffs_config cfg;
    
      cfg.phys_size = flashCapacity; // use 16 MB flash TODO use ID to get capacity
      cfg.phys_addr = /* 0x70000000 + */flashBaseAddr; // start spiffs here (physical adress)
      cfg.phys_erase_block = blocksize; //4K sectors
      cfg.log_block_size = cfg.phys_erase_block; // let us not complicate things
      cfg.log_page_size = LOG_PAGE_SIZE; // as we said
    
      cfg.hal_read_f = my_spiffs_read;
      cfg.hal_write_f = my_spiffs_write;
      cfg.hal_erase_f = my_spiffs_erase;
    
      int res = SPIFFS_mount(&fs,
                             &cfg,
                             spiffs_work_buf,
                             spiffs_fds,
                             sizeof(spiffs_fds),
                             spiffs_cache_buf,
                             sizeof(spiffs_cache_buf),
                             0);
      return res;
    }
    Last edited by mjs513; 05-14-2020 at 12:18 AM.

  3. #528
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,531
    Quote Originally Posted by mjs513 View Post
    What am I missing?
    I'm just guessin, but Paul said default size for 2nd flash/ram was 8 MB in his latest core. so for 16MB you need
    FLEXSPI2_FLSHA1CR0 = 0x4000;
    FLEXSPI2_FLSHA2CR0 = 0x40000;

  4. #529
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,338
    Quote Originally Posted by manitou View Post
    I'm just guessin, but Paul said default size for 2nd flash/ram was 8 MB in his latest core. so for 16MB you need
    FLEXSPI2_FLSHA1CR0 = 0x4000;
    FLEXSPI2_FLSHA2CR0 = 0x40000;
    Thanks @manitou. Gave it a try but still didn't work. Reading the flash chip id give me 0xffs. See the edit I made in post 527

  5. #530
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    11,777
    Quote Originally Posted by jmr View Post
    When you declare an array, that's right. When you want to read it with an AVR, you need to use pgm_read_xxx functions afaik.
    As long as the pointer is sent that is all the compiler does ? it is a normal RAM ptr*. No need to PROGMEM decorate the ptr* on passing it?

    Then it would be up to the called code to have knowledge when the data needs to come from PROGMEM?

    Code:
     func1( short *progmemData ) {
    #ifdef ARM
    // use ptr direct
    #endif
    #ifdef AVR
    // use ptr to get PROGMEM data
    #endif

  6. #531
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,914
    Quote Originally Posted by PaulStoffregen View Post
    You can't know at compile time whether the PSRAM chip will be installed on the board.

    I would create 2 different constructors for the library which initialize a constexpr pointer or other variable you use. If it's constexpr and initialized by the constructor, the compiler should optimize away code which reads it and decides which memory to use.
    Thanks Paul,

    I guess the real question will be if there should be a way for the user to specify that I am using memory chips or please don't try to initialize memory chips for their different setups. But I will drop that for now

    But as back to the display driver. The interesting issue is currently the code that deals with the frame buffer is all over every function. Like:
    Code:
    void ILI9488_t3::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
    {
    ....
    	#ifdef ENABLE_ILI9488_FRAMEBUFFER
    	if (_use_fbtft) {
    		RAFB color_index = mapColorToPalletIndex(color);
    		RAFB * pfbPixel_row = &_pfbtft[ y*_width + x];
    		for (;h>0; h--) {
    			RAFB * pfbPixel = pfbPixel_row;
    			for (int i = 0 ;i < w; i++) {
    				*pfbPixel++ = color_index;
    			}
    			pfbPixel_row += _width;
    		}
    	} else 
    	#endif
    	{
    ...
    Where RAFB is defined in the header file as either a uint8_t (pallet usage for T3.5/6), uint16_t for T4.x and maybe uint32_t for T4.1 with external memroy. And the compiler takes care of the memory indexing.

    There are obviously some other ways of doing this. Try to use templates where RAFB is a template setting. But if I understand correctly all of the code would then need to be within the header file. Or at least anything that RAFB influences. Not sure if I will go this route as may be hard to teach this old...

    Instead if I get beyond my procrastination here may try to rework the frame buffer code, that all of the places that touch the frame buffer get reduced down to a hand full of methods.
    like setPixel, setRepeatedPixel, ... getPixel... And all of these places that update the frame buffer will call these methods. Not sure yet if then have sub-classes for the different pixel sizes or have function to set which mode we are in and have these methods do their own memory addressing, which is again like RA8875 does. But for this round (release) will probably just punt.

    @all back to PROGMEM - Thanks Frank, Maybe the simplest thing would be to avr support for the program. But again I am wondering why I did not run into this earlier.

  7. #532
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,338
    Quote Originally Posted by manitou View Post
    I'm just guessin, but Paul said default size for 2nd flash/ram was 8 MB in his latest core. so for 16MB you need
    FLEXSPI2_FLSHA1CR0 = 0x4000;
    FLEXSPI2_FLSHA2CR0 = 0x40000;
    @manitou - @Frank B - @PaulStoffregen
    Ok think I figured out what the problem was. Basically its with the settings for FLEXSPI2_FLSHA1CR0 and FLEXSPI2_FLSHA2CR0. Decided to go back to the manual. FLSHAnCR0 is the memory size of the chips that are in use. So to get it to work with an offset of 0x0800000

    Code:
    FLEXSPI2_FLSHA1CR0 = 0x2000;  //8MB PSRAM chip
    FLEXSPI2_FLSHA2CR0 = 0x4000;   //16MB FLASH Chip
    Now if you have 2 PSRAM chips then
    Code:
    FLEXSPI2_FLSHA1CR0 = 0x2000;  //8MB PSRAM chip
    FLEXSPI2_FLSHA2CR0 = 0x2000;   //16MB FLASH Chip
    which is what is there currently for the 2 PSRAM chips. Not sure if I can change these on the fly with out having to reinitialize the PSRAM settings?

  8. #533
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,914
    I will ask a naive question, that I think may come up, and which I can probably guess the answer.

    Suppose I am only going to solder on one PSRAM chip. Is it OK for me to use the larger pattern on the back of the T4.1? What will the address be then?

  9. #534
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,338
    Don’t even want to make a guess at this point, but from start up code 0x70800000 same as the flash. I think.

  10. #535
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,088
    Quote Originally Posted by defragster View Post
    Will get back {Code has ping/ponged between myself and mjs513 recently} and post a clearer example. Have seen it repro today with PJRC PSRAM init so that removes the need for external lib - and it is also now running PSRAM at slower speed - but still shows up in repro case.
    Looking forward to seeing an example. If there's a memory corruption issue, I really want to find a way to reproduce it.

    I created a memory test program which fills the entire PSRAM with pseudo-random and fixed patters, then checks them. So far it's showing no errors, even at 132 MHz clocks.

    https://github.com/PaulStoffregen/te...am_memtest.ino

    If all testing passes, it also prints the total time taken for a simple benchmark.

    I committed this change to the startup code to default to 88 MHz. Also fixes a bug where the other CCM_CBCMR bits were being clobbered.

    https://github.com/PaulStoffregen/co...8308f2c0b2a52a

  11. #536
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,088
    Hmm... looks like overclocking Teensy 4.1 to 720 MHz makes this memory test occasionally fail. Overclocking to 816 MHz fails quickly, but still well into the 8MB range.

    Strange, since the memory speed is based on PLL2 or PLL3 which don't change with overclocking.

  12. #537
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,088
    Quote Originally Posted by KurtE View Post
    Suppose I am only going to solder on one PSRAM chip. Is it OK for me to use the larger pattern on the back of the T4.1?
    Nope. The startup code checks the smaller pads first. If no PSRAM chip is found there, the larger pads aren't checked.

    FlexSPI is highly configurable. You could create different code that uses only the larger pads and maps the chip at 70000000, which is where the linker script puts EXTMEM variables.

    But if using the startup code in the core library, for 8MB RAM the smaller pads must be used.

  13. #538
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    11,777
    Quote Originally Posted by PaulStoffregen View Post
    Nope. The startup code checks the smaller pads first. If no PSRAM chip is found there, the larger pads aren't checked.

    ...
    I had the same question - nice to have the answer up front - I was going to put first PSRAM on larger pads and test … won't bother with two trips to the iron.

  14. #539
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,914
    I sort of assumed that, but asked as maybe should be documented

  15. #540
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    11,777
    Quote Originally Posted by PaulStoffregen View Post
    Looking forward to seeing an example. If there's a memory corruption issue, I really want to find a way to reproduce it.

    I created a memory test program which fills the entire PSRAM with pseudo-random and fixed patters, then checks them. So far it's showing no errors, even at 132 MHz clocks.

    https://github.com/PaulStoffregen/te...am_memtest.ino

    If all testing passes, it also prints the total time taken for a simple benchmark.

    I committed this change to the startup code to default to 88 MHz. Also fixes a bug where the other CCM_CBCMR bits were being clobbered.

    https://github.com/PaulStoffregen/co...8308f2c0b2a52a
    There seems to be an issue. Should have something clean to post in coming hours.

    Goes back to this post on 5/7 p#287 forum.pjrc.com/threads/60532-Teensy-4-1-Beta-Test. @mjs513 has been going back and fourth with about 4 refinements from each of us since it was posted.

    Could write 9 GB binary data file w/SD Fat Beta in short order (20K _isr samp/sec of 16 bytes) - parsing the data was a bit much - did some program compare checks and detected the issue - been looking/posting at it on and off and on and on and off since.

    Eliminated SD write and it persisted. It has to do with _isr - because just as many updates celled from loop works fine - as well the other alternatives and changes tried it persists in the same way.

    With 1.52_B5 change to PSRAM init in startup it still persists - though it seems to have moved unless that was just my last Address * address change and allow further simplification as noted not using any external PSRAM lib. So will get back to that.

    Seeing your p#536 test fail when OC's - I just tested at 528 Mhz - and current repro code still fails as before.

    In weeks past other mem testing was done and all looked good and right. Doing it with real world SD logger seemed more real type use - and this showed up ...

  16. #541
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    3,744

    Cool

    Quote Originally Posted by mjs513 View Post
    You can probably use:
    Code:
    extern "C" uint8_t external_psram_size;
    and test if external_psram_size > 0 to include the buffer?
    If you still want to run on older versions of 1.52 beta 1-4, you probably want:
    Code:
    #if (TEENSYDUINO > 151) && defined(ARDUINO_TEENSY41)
    extern "C" uint8_t external_psram_size __attribute__((weak));
    #endif
    
    // ...
    
    #if (TEENSYDUINO > 151) && defined(ARDUINO_TEENSY41)
      if (&external_psram_size)
        {
          if (external_psram_size > 0) {
            Serial.printf("PSRAM: %d MB\n", external_psram_size);
          } else {
            Serial.println("PSRAM: none");
          }
        }
    #endif

  17. #542
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    11,777
    Paul: Getting close to an example that @mjs513 found usable and editable - as noted it started from what seemed a nice SD log RAM buffer by @MBorgerson.

    Just thought of something to add - do you want it here or a new thread?

    <EDIT>: Added drop in sample rate and as @mjs513 noted before - lower sample rate of _isr() stops the failure

    In so doing the output got really ugly when no error - fixing that makes it look cleaner only showing error lines : where buffer1 data is injected into buffer0

    I'll put on this thread shortly if no reply ...
    Last edited by defragster; 05-14-2020 at 06:49 AM.

  18. #543
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    11,777
    Paul: False Alarm … PSRAM test with _isr() - HEX math error apparently and buffer overlap.

    Hopfully eRam_malloc() makes it into TD 1.53

  19. #544
    Senior Member
    Join Date
    Oct 2015
    Location
    Roma (IT, EU)
    Posts
    336
    Quote Originally Posted by PaulStoffregen View Post
    if using the startup code in the core library, for 8MB RAM the smaller pads must be used.
    Nearly missed that! Very good to know.
    I would write this all over the place: users would almost certainly go for the larger pad first (a bit easier to solder).

  20. #545
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,088
    Quote Originally Posted by defragster View Post
    False Alarm … PSRAM test with _isr() - HEX math error apparently and buffer overlap.
    Whew, that's a big relief.

    I'm feeling pretty good about wrapping up 1.52. Anyone see any issues that should block a full non-beta release?

  21. #546
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,906
    Quote Originally Posted by MichaelMeissner View Post
    If you still want to run on older versions of 1.52 beta 1-4, you probably want:
    Code:
    #if (TEENSYDUINO > 151) && defined(ARDUINO_TEENSY41)
    extern "C" uint8_t external_psram_size __attribute__((weak));
    #endif
    @Michael, a question: What means the "weak" attribute here?

    I've seen it for functions only, so far.

  22. #547
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,338
    Quote Originally Posted by PaulStoffregen View Post
    Hmm... looks like overclocking Teensy 4.1 to 720 MHz makes this memory test occasionally fail. Overclocking to 816 MHz fails quickly, but still well into the 8MB range.

    Strange, since the memory speed is based on PLL2 or PLL3 which don't change with overclocking.
    Morning Paul - was this resolved. I just ran a simple test sketch at 960Mhz using a modified lib (uses startup for PSRAM and just initializers FLASH) as well as the library example flashtest6.ino and don't seem to be getting errors anymore. I was getting last night before sleep took over. The only thing I did this morning was copied the latest startup.c to the core?

    EDIT: Well just reran the tests after testing your memTest sketch which failed at clock >600Mhz and the other tests failed. So more work.
    Last edited by mjs513; 05-14-2020 at 01:08 PM.

  23. #548
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,338
    Quote Originally Posted by MichaelMeissner View Post
    If you still want to run on older versions of 1.52 beta 1-4, you probably want:
    Code:
    #if (TEENSYDUINO > 151) && defined(ARDUINO_TEENSY41)
    extern "C" uint8_t external_psram_size __attribute__((weak));
    #endif
    
    // ...
    
    #if (TEENSYDUINO > 151) && defined(ARDUINO_TEENSY41)
      if (&external_psram_size)
        {
          if (external_psram_size > 0) {
            Serial.printf("PSRAM: %d MB\n", external_psram_size);
          } else {
            Serial.println("PSRAM: none");
          }
        }
    #endif
    Thanks Michael - just added this to my code snippets list that I just started

  24. #549
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,338
    Quote Originally Posted by PaulStoffregen View Post
    Whew, that's a big relief.

    I'm feeling pretty good about wrapping up 1.52. Anyone see any issues that should block a full non-beta release?
    Don't see any issues with the changes to the PSRAM startup - especially since I figure out my problem Now have to rewicker the lib, mostly because of the possibility for using 2 PSRAM chips.

  25. #550
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,088
    Quote Originally Posted by KurtE View Post
    but asked as maybe should be documented
    I've updated the PSRAM chip page with photos of the 1 and 2 chip cases, as well as RAM+Flash.

    https://www.pjrc.com/store/psram.html

    Also added the memory test program and a part at the end to document use of EXTMEM in Arduino.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •