kopia lustrzana https://github.com/Jean-MarcHarvengt/MCUME
159 wiersze
6.8 KiB
Plaintext
Executable File
159 wiersze
6.8 KiB
Plaintext
Executable File
; rp2040-psram
|
|
;
|
|
; Copyright © 2023 Ian Scott
|
|
;
|
|
; Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
; this software and associated documentation files (the “Software”), to deal in
|
|
; the Software without restriction, including without limitation the rights to
|
|
; use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
; of the Software, and to permit persons to whom the Software is furnished to do
|
|
; so, subject to the following conditions:
|
|
;
|
|
; The above copyright notice and this permission notice shall be included in all
|
|
; copies or substantial portions of the Software.
|
|
;
|
|
; THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
; SOFTWARE.
|
|
|
|
; SPI, customized as the PSRAM chips like to implement it:
|
|
; - Data is always written first, then optionally read
|
|
; Depending on PCB layout, introduce fudge factor:
|
|
; - Reads in high speed mode need an extra clock cycle to synchronize
|
|
; - Reads are done on the falling edge of SCK when > 83MHz
|
|
|
|
.program spi_psram_fudge
|
|
.side_set 2 ; sideset bit 1 is SCK, bit 0 is CS
|
|
begin:
|
|
out x, 8 side 0b01 ; x = number of bits to output. CS deasserted
|
|
out y, 8 side 0b01 ; y = number of bits to input
|
|
jmp x--, writeloop side 0b01 ; Pre-decement x by 1 so loop has correct number of iterations
|
|
writeloop: ; Put the data and rise the clock!!!!
|
|
out pins, 1 side 0b00 ; Write value on pin on lower clock. CS asserted
|
|
jmp x--, writeloop side 0b10 ; Raise clock: this is when PSRAM reads the value. Loop if we have more to write
|
|
jmp !y, begin side 0b00 ; If this is a write-only operation, jump back to beginning
|
|
|
|
nop side 0b10 ; Fudge factor of extra clock cycle; the PSRAM needs 1 extra for output to start appearing
|
|
jmp readloop_mid side 0b00 ; Jump to middle of readloop to decrement y and get right clock phase
|
|
readloop:
|
|
in pins, 1 side 0b00 ; Read value on pin, lower clock. Datasheet says to read on falling edge > 83MHz
|
|
readloop_mid:
|
|
jmp y--, readloop side 0b10 ; Raise clock. Loop if we have more to read
|
|
|
|
% c-sdk {
|
|
#include "hardware/gpio.h"
|
|
static inline void pio_spi_psram_cs_init(bool init_done, PIO pio, uint sm, uint prog_offs, uint n_bits, float clkdiv, bool fudge, uint pin_cs, uint pin_mosi, uint pin_miso) {
|
|
pio_sm_set_enabled(pio, sm, false);
|
|
pio_sm_clear_fifos(pio, sm);
|
|
pio_sm_restart(pio, sm);
|
|
pio_sm_config c;
|
|
|
|
c = spi_psram_fudge_program_get_default_config(prog_offs);
|
|
|
|
|
|
sm_config_set_out_pins(&c, pin_mosi, 1);
|
|
sm_config_set_in_pins(&c, pin_miso);
|
|
sm_config_set_sideset_pins(&c, pin_cs);
|
|
sm_config_set_out_shift(&c, false, true, n_bits);
|
|
sm_config_set_in_shift(&c, false, true, n_bits);
|
|
sm_config_set_clkdiv(&c, clkdiv);
|
|
|
|
pio_sm_set_consecutive_pindirs(pio, sm, pin_cs, 2, true);
|
|
pio_sm_set_consecutive_pindirs(pio, sm, pin_mosi, 1, true);
|
|
pio_sm_set_consecutive_pindirs(pio, sm, pin_miso, 1, false);
|
|
pio_gpio_init(pio, pin_mosi);
|
|
pio_gpio_init(pio, pin_miso);
|
|
pio_gpio_init(pio, pin_cs);
|
|
pio_gpio_init(pio, pin_cs + 1);
|
|
|
|
hw_set_bits(&pio->input_sync_bypass, 1u << pin_miso);
|
|
|
|
if (!init_done) {
|
|
pio_sm_init(pio, sm, prog_offs, &c);
|
|
}
|
|
pio_sm_set_enabled(pio, sm, true);
|
|
}
|
|
%}
|
|
|
|
.program qspi_psram
|
|
.side_set 2
|
|
begin:
|
|
out x, 8 side 0b01 ; x = number of nibbles to output. CS deasserted
|
|
out y, 8 side 0b01 ; y = number of nibbles to input
|
|
jmp x--, writeloop side 0b01 ; Pre-decement x by 1 so loop has correct number of iterations
|
|
writeloop:
|
|
out pins, 4 side 0b00 ; Write value on pins on lower clock. CS asserted
|
|
jmp x--, writeloop side 0b10 ; Raise clock: this is when PSRAM reads the value. Loop if we have more to write
|
|
jmp !y, begin side 0b00 ; If this is a write-only operation, jump back to beginning
|
|
|
|
nop side 0b10 ; 1
|
|
nop side 0b00
|
|
nop side 0b10 ; 2
|
|
nop side 0b00
|
|
nop side 0b10 ; 3
|
|
nop side 0b00
|
|
nop side 0b10 ; 4
|
|
|
|
nop side 0b00 ; data to read is put now by PSRAM
|
|
nop side 0b10
|
|
set pindirs 0 side 0b00 ; Fudge factor of extra clock cycle; the PSRAM needs 1 extra for output to start appearing
|
|
jmp readloop_mid side 0b10 ; Jump to middle of readloop to decrement y and get right clock phase
|
|
readloop:
|
|
in pins, 4 side 0b10 ; Read value on s, lower clock. Datasheet says to read on falling edge > 83MHz
|
|
readloop_mid:
|
|
jmp y--, readloop side 0b00 ; Raise clock. Loop if we have more to read
|
|
set pindirs 0xF side 0b01
|
|
|
|
|
|
; set pindirs 0 side 0b00 ; data to read is put now by PSRAM
|
|
; nop side 0b10 ; Fudge factor of extra clock cycle; the PSRAM needs 1 extra for output to start appearing
|
|
; jmp readloop_mid side 0b00 ; Jump to middle of readloop to decrement y and get right clock phase
|
|
;readloop:
|
|
; in pins, 4 side 0b00 ; Read value on s, lower clock. Datasheet says to read on falling edge > 83MHz
|
|
;readloop_mid:
|
|
; jmp y--, readloop side 0b10 ; Raise clock. Loop if we have more to read
|
|
; set pindirs 0xF side 0b00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
% c-sdk {
|
|
#include "hardware/gpio.h"
|
|
static inline void pio_qspi_psram_cs_init(bool init_done, PIO pio, uint sm, uint prog_offs, uint n_bits, float clkdiv, uint pin_cs, uint pin_sio0) {
|
|
pio_sm_set_enabled(pio, sm, false);
|
|
pio_sm_clear_fifos(pio, sm);
|
|
pio_sm_restart(pio, sm);
|
|
pio_sm_config c;
|
|
c = qspi_psram_program_get_default_config(prog_offs);
|
|
sm_config_set_out_pins(&c, pin_sio0, 4);
|
|
sm_config_set_in_pins(&c, pin_sio0);
|
|
sm_config_set_set_pins(&c, pin_sio0, 4);
|
|
sm_config_set_sideset_pins(&c, pin_cs);
|
|
sm_config_set_out_shift(&c, false, true, n_bits);
|
|
sm_config_set_in_shift(&c, false, true, n_bits);
|
|
sm_config_set_clkdiv(&c, clkdiv);
|
|
|
|
pio_sm_set_consecutive_pindirs(pio, sm, pin_cs, 2, true);
|
|
pio_sm_set_consecutive_pindirs(pio, sm, pin_sio0, 4, true);
|
|
pio_gpio_init(pio, pin_sio0);
|
|
pio_gpio_init(pio, pin_sio0 + 1);
|
|
pio_gpio_init(pio, pin_sio0 + 2);
|
|
pio_gpio_init(pio, pin_sio0 + 3);
|
|
pio_gpio_init(pio, pin_cs);
|
|
pio_gpio_init(pio, pin_cs + 1);
|
|
|
|
hw_set_bits(&pio->input_sync_bypass, 0xfu << pin_sio0);
|
|
|
|
if (!init_done) {
|
|
pio_sm_init(pio, sm, prog_offs, &c);
|
|
}
|
|
pio_sm_set_enabled(pio, sm, true);
|
|
}
|
|
%}
|