Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 7 of 7

Thread: Is there any way to force an array to be in Teensy 3.6 SRAM_U?

  1. #1
    Senior Member
    Join Date
    Nov 2012
    Posts
    294

    Is there any way to force an array to be in Teensy 3.6 SRAM_U?

    I have written a ring buffer class for buffering data during SD busy time. It works well if I use it for buffering full sectors. I have declared the buffer array like this. Size is a multiple of 512 bytes so everything is 32-bit aligned and sizes are a multiple of 32-bits.

    Code:
    uint8_t __attribute__ ((aligned (4))) m_buf[Size];
    I also use it with Print as a base class and I have implemented write required by print with memcpy. It's really handy in a logger to print into the ring buffer. Even though memcpy is called in the class with type uint8_t arguments, the compiler optimizes it so a hard fault occurs when copying across the RAM_L/RAMU boundary in cases where the destination is not 32-bit aligned.

    Is there an attribute that would cause the entire array to be in RAM_U?

    Anyone have a custom memcpy for Teensy 3.6 that is efficient?

  2. #2
    Senior Member
    Join Date
    Nov 2012
    Posts
    294
    This seems to work. It is efficient except at the 0X20000000 boundary.
    Code:
    // Tensy3 memcpy
    inline bool is_aligned(const void* ptr, uintptr_t alignment) {
        auto iptr = reinterpret_cast<uintptr_t>(ptr);
        return !(iptr % alignment);
    }
    void memcpyT3(void* dst, const void* src, size_t len) {
      const uint8_t* b = (const uint8_t*)0X20000000UL;
      uint8_t* d = (uint8_t*)dst;
      const uint8_t *s = (const uint8_t*)src;
      if (((d < b && (d + len) >= b) || (s < b && (s + len) >= b)) &&
        (!is_aligned(d, 4) || !is_aligned(s, 4) || len & 3)) {
        while (len--) {
          *d++ = *s++;
        }
      } else {
        memcpy(dst, src, len);
      }
    }

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,727
    It can be more efficient if you can arrange for even 1 of the buffers to be 32 bit aligned.

  4. #4
    Senior Member
    Join Date
    Nov 2012
    Posts
    294
    Unfortunately the source buffer comes from the Print class and the destination buffer alignment depends on how many bytes have been written to the file.

    I tested the above on a demo of a data logger that uses mods I am doing to the Teensy SDIO driver that include file.isBusy(). The logger can log adc value as text at over 25 ksps.

    It's really simple so novice users can log a sensor at high rates without a sophisticated ISR approach. Here is the simplified code for the logger:

    Code:
    // 400 sector ring buffer for FsFile type.
    RingBuf<FsFile, 400*512> rb;
    
      // Initialize the RingBuf - use a large pre-allocated exFAT file.
      rb.begin(&file); 
      
      // Used for controlling the log interval.
      uint32_t logTime = micros();
      while (!Serial.available()) {
    
        // Write data to SD if a sector is in the RingBuf.   
        if (rb.bytesUsed() >= 512 && !file.isBusy()) {
          // Writing full sectors assures no copy to SdFat internal cache buffer.
          // Write of first sector takes about 11 usec on Teensy 4.1, 5 usec each after the first.
          if (512 != rb.writeOut(512)) {
            // Handle SD write error here.
          }
        }
        // Time for next point - log at 25 kHz.
        logTime += 40;
        // Spare time before next point - negative if time overrun.
        int32_t spareMicros = logTime - micros();
        // Wait until time to log data.
        while (micros() < logTime) {}    
        
        // Read ADC0 this takes about 17 usec on Teensy 4.
        uint16_t adc = analogRead(0);
        // Print spareMicros into the RingBuf as test data.
        rb.print(spareMicros);
        rb.write(',');
        // Print adc into RingBuf.
        rb.println(adc);
        if (rb.getWriteError()) {
          // Handle error caused by too few free bytes in RingBuf.
        }
      }

  5. #5
    Senior Member
    Join Date
    Nov 2012
    Posts
    294
    The RingBuf class can be used in an ISR. I did a ping-pong ADC DMA test with Teensy 3.6 over-clocking the ADC and am able to log 6MB/sec.

    Here is a link to that demo.

    https://forum.pjrc.com/threads/65836...092#post267092

    Click image for larger version. 

Name:	TeensySqr.jpg 
Views:	9 
Size:	71.4 KB 
ID:	23338

  6. #6
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    7,916
    WOw.. is that fast enough to record a TV (F)BAS / CVBS signal?

  7. #7
    Senior Member
    Join Date
    Nov 2012
    Posts
    294
    I have posted the mods to the Teensy SDIO driver that allow fast simple loggers and the ring buffer for use in SRAM_L/SRAM_U on Teensy 3.6.

    Try the TeensyDmaAdcLogger and TeensySdioLogger examples.

    Enable this line in TeensyDmaAdcLogger on a Teensy 3.6 to log an overclocked ADC at 6 MB/sec or 3 Msps.

    Code:
    // in loop()
    //overclock(); // 3 Msps on Teensy 3.6 - requires high quality card.

Posting Permissions

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