Shop Learn
Memory drivers for P2 - PSRAM/SRAM/HyperRAM (was HyperRAM driver for P2) - Page 33 — Parallax Forums

Memory drivers for P2 - PSRAM/SRAM/HyperRAM (was HyperRAM driver for P2)

1272829303133»

Comments

  • roglohrogloh Posts: 4,217

    @evanh said:
    Got it, smaller drivers aren't specifically documented. Actually, the document doesn't name any files at all. Probably need to add something for that.

    Check the release notes file for file details.

  • evanhevanh Posts: 13,106

    Oh, that's not a great solution. At least name the driver that the doc covers.

  • evanhevanh Posts: 13,106

    Here's the corrected auto-delays in psram.spin2 for use on Edge EC32MB card. First line I've retained as commented out original table. Second line is the updated table.

    'delayTable  long    7,92_000000,150_000000,206_000000,258_000000,310_000000,333_000000,0  'Eval + Add-on
    delayTable  long    7,130_000000,190_000000,240_000000,290_000000,340_000000  'Edge EC32MB
    
  • roglohrogloh Posts: 4,217

    Good. People using the P2-EC32MB boards should probably use that adjusted setting for now until there is a better way to auto detect optimized timing somehow...

    For other PSRAM systems, you can always run the supplied psram_delay_test program to work out where the various frequency breakpoints are and create your own custom timing table optimized for your own setup. Unfortunately with this board timing stuff there is no one size fits all set of values. And even temperature can affect timing. We should figure out a routine to call periodically to monitor for optimized read input timing at the current temperature. For that I know we can create secondary overlapping banks in the driver with new timing values that don't affect the regular bank timing, so the test can be run in parallel to normal operation, and the actual operational banks can be adjusted only once the new values are determined. The only real issue is there just needs to be a COG to perform this operation, as the driver is busy servicing COGs and can't really stop to go off and do this work on its own, so it will need a client COG to make the read requests and set the timing registers and hunt for timing with minimum read errors etc.

  • evanhevanh Posts: 13,106

    I'd do it as a user callable tuning - that is also used by init function. If, say, clock speed is adjusted then the application program should be the one to manage the transition. Then the application can not only decide when to tune but also designate a block of RAM to tune with.

  • evanhevanh Posts: 13,106
    edited 2022-06-27 22:50

    Roger,
    I'd like to offer my PLL setting routine for your use. Or at least the clkmode_ / clkfreq_ logic. They offer a more streamlined solution to correctly calculating the sysclock mode and frequency. No need to require particular defining of constants.
    Their use recently gained compatibility in Flexspin - https://forums.parallax.com/discussion/comment/1539723/#Comment_1539723

    PS: It has two internal arbitrary presets:

    pub  pllset( targetfreq ) : xinfreq | mode, mult, divd, divp, post, Fpfd, Fvco, error, besterror, vcolimit
    
        mode := clkmode_
    
        if clkmode_ >> 24 & 1                           ' compiled with PLL on
            divd := clkmode_ >> 18 & $3f + 1
            mult := clkmode_ >> 8 & $3ff + 1
            divp := (clkmode_ >> 4 + 1) & $f
            divp := divp ? divp * 2 : 1
            xinfreq := muldiv65( divp * divd, clkfreq_, mult )
    
        elseif clkmode_ >> 2 & 3                        ' compiled with PLL off
            xinfreq := clkfreq_                     ' clock pass-through
        else                                            ' unknown build mode
            xinfreq := 20_000_000                   ' default to 20 MHz crystal
            mode := %10_00                          ' default to 15 pF loading
    
        mode := %11_11 & mode | %11                     ' keep %CC, force %SS, ditch the rest
    
        besterror := div33( targetfreq, 100 )           ' _errfreq at 1.0% of targetfreq
        vcolimit := targetfreq + besterror
        vcolimit := vcolimit < 201_000_000 ? 201_000_000 : vcolimit
    
        repeat post from 0 to 15
            divp := post ? post * 2 : 1
    
            repeat divd from 64 to 1
                Fpfd := div33( xinfreq, divd )
                mult := muldiv65( divp * divd, targetfreq, xinfreq )
                Fvco := muldiv65( xinfreq, mult, divd )
    
                if Fpfd >= 250_000 and mult <= 1024 and Fvco > 99_000_000 and Fvco <= vcolimit
                    error := div33( Fvco, divp ) - targetfreq
    
                    if abs( error ) <= abs( besterror )     ' the last iteration at equality gets priority
                        besterror := error
                        mode := (mode&%11_11) | 1<<24 | (divd-1)<<18 | (mult-1)<<8 | ((post-1)&15)<<4
    
        if mode.[24]                                            ' PLL-ON bit set when calculation is valid
            clkset( mode, targetfreq + besterror )          ' make the frequency change
    '       baudval()                                       ' recalibrate debug comms as well
        else
            xinfreq := -1                                   ' failed, no change
    

    EDIT: Oops, forgot it also uses my rounding-to-nearest dividing routines too ... here's the simpler versions:

    PUB  div33( dividend, divisor ) : r
        org
            mov     r, divisor
            shr     r, #1
            add     dividend, r
            qdiv    dividend, divisor
            getqx   r
        end
    
    
    
    PUB  muldiv65( mult1, mult2, divisor ) : r
        org
            qmul    mult1, mult2
            mov     r, divisor
            shr     r, #1
            getqx   mult1
            getqy   mult2
            add     mult1, r    wc
            addx    mult2, #0
            setq    mult2
            qdiv    mult1, divisor
            getqx   r
        end
    
  • evanhevanh Posts: 13,106
    edited 2022-06-28 02:18

    I offer it because, in your existing code, the %CC bits and the XIN frequency are somewhat assumed to be %11 and 20 MHz respectively.

    EDIT: Err, the %CC bits are being calculated, not unreasonably on assumption, rather than maintained.

  • roglohrogloh Posts: 4,217

    Am distracted by other things right now but will try to take a look at this soon.

  • roglohrogloh Posts: 4,217

    Briefly comparing the code...

    • Your version uses the existing PLL settings if enabled to compute the input frequency and can also determine it when using a direct pass through clock source, while mine needs to be specified... win to you. This part is especially useful.
    • Your version uses extra precision in the computation by introducing your own rounding divide and multiply code and rounding in multiple places - now whether they are all needed or not, or is extra overkill is TBD. Mine achieves rounding via testing twice per mult value (with simple addition) to see which value is the closer match.
    • Yours looks for percent error less than 1% while mine uses a frequency difference as the tolerance (500kHz). Probably not that significant.
    • Mine exits when best match is found at lowest DIVD, DIVP values, and is a slight optimization in my code. Yours will test every possible value and do the calculations for all combinations which may be slower to run.
    • Your source code is much tighter, mine is more verbose although a little more commented. Perhaps it's unnecessarily verbose as it was never really optimized as such.

    I don't know, maybe I'll start with just the clockmode_ stuff you added. That part seems handy.

  • evanhevanh Posts: 13,106

    @rogloh said:
    ... maybe I'll start with just the clockmode_ stuff you added. That part seems handy.

    I'd be happy with that alone updated.

    It required the recent change in Flexspin to operate below top-level anyway. I'd put it all aside a year or so back when it failed to compile in Flexspin as an object.

  • roglohrogloh Posts: 4,217

    @evanh said:

    @rogloh said:
    ... maybe I'll start with just the clockmode_ stuff you added. That part seems handy.

    I'd be happy with that alone updated.

    It required the recent change in Flexspin to operate below top-level anyway. I'd put it all aside a year or so back when it failed to compile in Flexspin as an object.

    Yeah I know it was a problem in the past, but does this scheme now also work in PropTool?

  • evanhevanh Posts: 13,106
    edited 2022-06-28 07:10

    Sure does, it was a feature parity improvement for Flexspin.

  • roglohrogloh Posts: 4,217

    Sure does, it was a feature parity improvement for Flexspin.

    Ok good, cheers.

    By the way this PLL setting topic is probably relevant to my p2 video driver thread not this memory driver thread, but as I've already followed it up here, who am I to mention that...? The memory driver doesn't specifically touch the PLL, only my video driver.

  • roglohrogloh Posts: 4,217

    Also @evanh , I see this comment in the SPIN2 documentation...I take it this means the documenation is out of date with reality? This was the old behavior, right? Now clkmode_ is inherited from the top level file...

    The 'clkmode_' value may differ in each file of the application hierarchy. Files below the top-level file do not inherit the top-level file's value.

  • evanhevanh Posts: 13,106

    @rogloh said:
    By the way this PLL setting topic is probably relevant to my p2 video driver thread not this memory driver thread, but as I've already followed it up here, who am I to mention that...? The memory driver doesn't specifically touch the PLL, only my video driver.

    Yeah, I realised that myself after I'd posted. In my defence, I was reading the video driver code in the memory driver archive.

  • evanhevanh Posts: 13,106
    edited 2022-06-28 08:28

    @rogloh said:
    Also @evanh , I see this comment in the SPIN2 documentation...I take it this means the documenation is out of date with reality? This was the old behavior, right? Now clkmode_ is inherited from the top level file...

    The 'clkmode_' value may differ in each file of the application hierarchy. Files below the top-level file do not inherit the top-level file's value.

    Wow, you're right. I didn't read it all. It's weird because how can an undefined be anything other than inherited? Inheritance is basically exactly what I got added to Flexspin. Before the improvement there was no such symbols below top-level so I just got compile errors when my code was put in an object file.

    And that is how it appears to work in Pnut and Proptool. Those two symbols aren't source defined at any level. They are compiler built from the board config constants, or defaults if no config. And they exist below top-level.

Sign In or Register to comment.