From 5faa69b5e416c64a8637eae9078c8daad0b107f6 Mon Sep 17 00:00:00 2001 From: igor-m Date: Wed, 9 Apr 2014 18:44:03 +0200 Subject: [PATCH] New PMP driver for 8MB Ramdisk v.1.1 and clones --- sys/pic32/rd_sramc.c | 289 ++++++++++++++++++---------------------- sys/pic32/rd_sramc_BB.c | 258 +++++++++++++++++++++++++++++++++++ 2 files changed, 390 insertions(+), 157 deletions(-) create mode 100644 sys/pic32/rd_sramc_BB.c diff --git a/sys/pic32/rd_sramc.c b/sys/pic32/rd_sramc.c index 5886672..0cc90b7 100644 --- a/sys/pic32/rd_sramc.c +++ b/sys/pic32/rd_sramc.c @@ -1,20 +1,22 @@ /* - * Driver for external RAM-based swap device. + * Driver for external SRAM-CPLD based Swap and Filesystem devices + * + * This version is for 8MB RAMDISK v.1.1 and compatible + * Pito 7.4.2014 - PIC32MX PMP bus version + * Under by retrobsd.org used Licence + * No warranties of any kind * * Interface: - * data[7:0] - connected to PORTx - * rd - fetch a byte from memory to data[7:0], increment address - * wr - write a byte data[7:0] to memory, increment address - * ldaddr - write address from data[7:0] in 3 steps: low-middle-high + * PMD<7:0> - connected to PMP data bus + * PMRD - fetch a byte from memory to data<7:0>, increment address, PMRD + * PMWR - write a byte data[7:0] to memory, increment address, PMWR + * PMA0 - HIGH - write Address from data<3:0> in 6 steps: high nibble ... low nibble + * - LOW - write/read Data + * + * Signals PMRD, PMWR are active LOW and idle HIGH + * Signal PMA0 is LOW when accessing RAM Data, and HIGH when accessing RAM Addresses + * * - * Signals rd, wr, ldadr are active LOW and idle HIGH. - * To activate, you need to pulse it high-low-high. - * CHANGE: IM 23.12.2011 - signals active LOW - * CHANGE: IM 24.12.2011 - finetuning for 55ns SRAM and 7ns CPLD - * - some nops removed - * - nops marked 55ns are required !!! - * - MAX performance settings for 55ns SRAM - * CHANGE: IM 28.12.2011 - dev_load_address is 6x4bit now */ #include "param.h" #include "systm.h" @@ -27,130 +29,86 @@ int sw_dkn = -1; /* Statistics slot number */ -/* - * Set data output value. - */ -static inline void data_set (unsigned char byte) -{ - LAT_CLR(SW_DATA_PORT) = 0xff << SW_DATA_PIN; - LAT_SET(SW_DATA_PORT) = byte << SW_DATA_PIN; -} +// Ramdisk v.1.1. wiring +// PMP RAMDISK +// =================== +// PMD D0-D7 +// PMRD /RD +// PMWR /WR +// PMA<0> /DATA + +// RD and WR pulses duration settings +// Minimal recommended settings, increase them when unstable +// No warranties of any kind +// for 120MHz clock, 70ns PSRAM, Ramdisk v.1.1. +#define ADR_PULSE 1 +#define WR_PULSE 5 +#define RD_PULSE 11 + +// for 80MHz clock, 70ns PSRAM, Ramdisk v.1.1. +//#define ADR_PULSE 1 +//#define WR_PULSE 3 +//#define RD_PULSE 8 + +// for 120MHz clock, 55ns SRAM +//#define ADR_PULSE 1 +//#define WR_PULSE 3 +//#define RD_PULSE 6 + +// for 80MHz clock, 55ns SRAM +//#define ADR_PULSE 1 +//#define WR_PULSE 2 +//#define RD_PULSE 4 + +typedef union { + unsigned value; + struct { +unsigned nib1: 4; // lowest nibble +unsigned nib2: 4; +unsigned nib3: 4; +unsigned nib4: 4; +unsigned nib5: 4; +unsigned nib6: 4; +unsigned nib7: 4; +unsigned nib8: 4; // highest nibble + }; +} nybbles ; + /* - * Switch data bus to input. + * Load the 24 bit address to Ramdisk. + * */ -static inline void data_switch_input () -{ - LAT_CLR(SW_DATA_PORT) = 0xff << SW_DATA_PIN; // !!! PIC32 errata - TRIS_SET(SW_DATA_PORT) = 0xff << SW_DATA_PIN; - asm volatile ("nop"); -} - -/* - * Switch data bus to output. - */ -static inline void data_switch_output () -{ - TRIS_CLR(SW_DATA_PORT) = 0xff << SW_DATA_PIN; - asm volatile ("nop"); -} - -/* - * Get data input value. - */ -static inline unsigned char data_get () -{ - return PORT_VAL(SW_DATA_PORT) >> SW_DATA_PIN; -} - -/* - * Send LDA pulse: high-low-high. - */ -static inline void lda_pulse () -{ - LAT_CLR(SW_LDA_PORT) = 1 << SW_LDA_PIN; - asm volatile ("nop"); - asm volatile ("nop"); - LAT_SET(SW_LDA_PORT) = 1 << SW_LDA_PIN; -} - -/* - * Set RD low. - * Minimal time between falling edge of RD to data valid is 50ns. - */ -static inline void rd_low () -{ - LAT_CLR(SW_RD_PORT) = 1 << SW_RD_PIN; - -#if BUS_KHZ > 33000 - asm volatile ("nop"); // 55ns - asm volatile ("nop"); // 55ns -#endif -#if BUS_KHZ > 66000 - asm volatile ("nop"); // 55ns - asm volatile ("nop"); // 55ns -#endif -} - -/* - * Set RD high. - */ -static inline void rd_high () -{ - LAT_SET(SW_RD_PORT) = 1 << SW_RD_PIN; -} - -/* - * Send WR pulse: high-low-high. - * It shall be minimally 40ns. - */ -static inline void wr_pulse () -{ - LAT_CLR(SW_WR_PORT) = 1 << SW_WR_PIN; - -#if BUS_KHZ > 33000 - asm volatile ("nop"); // 55ns - asm volatile ("nop"); // 55ns -#endif -#if BUS_KHZ > 66000 - asm volatile ("nop"); // 55ns -#endif - LAT_SET(SW_WR_PORT) = 1 << SW_WR_PIN; -} - -/* - * Load the 24 bit address to ramdisk. - * Leave data bus in input mode. - */ -static void +inline static void dev_load_address (addr) unsigned addr; { - /* Toggle rd: make one dummy read - this clears cpld's addr pointer */ - rd_low (); - rd_high (); + nybbles temp; + temp.value = addr; - data_switch_output(); /* switch data bus to output */ + while(PMMODE & 0x8000); // Poll - if busy, wait - data_set (addr); /* send lowest 4 bits */ - lda_pulse(); /* pulse ldaddr */ + PMADDR = 1; // set ADR mode (1) to write the Address - data_set (addr >> 4); /* send 4 bits */ - lda_pulse(); /* pulse ldaddr */ + PMMODE = 0b10<<8 | (ADR_PULSE<<2); // full ADR speed - data_set (addr >> 8); /* send 4 bits */ - lda_pulse(); /* pulse ldaddr */ + PMDIN = temp.nib6; /* write 4 bits */ + + while(PMMODE & 0x8000); // Poll - if busy, wait + PMDIN = temp.nib5; /* write 4 bits */ + + while(PMMODE & 0x8000); // Poll - if busy, wait + PMDIN = temp.nib4; /* write 4 bits */ + + while(PMMODE & 0x8000); // Poll - if busy, wait + PMDIN = temp.nib3; /* write 4 bits */ - data_set (addr >> 12); /* send 4 bits */ - lda_pulse(); /* pulse ldaddr */ + while(PMMODE & 0x8000); // Poll - if busy, wait + PMDIN = temp.nib2; /* write 4 bits */ - data_set (addr >> 16); /* send 4 bits */ - lda_pulse(); /* pulse ldaddr */ + while(PMMODE & 0x8000); // Poll - if busy, wait + PMDIN = temp.nib1; /* write 4 bits */ - data_set (addr >> 20); /* send highest 4 bits */ - lda_pulse(); /* pulse ldaddr */ - - data_switch_input(); } /* @@ -159,13 +117,13 @@ dev_load_address (addr) */ int sramc_size ( int unit ) { - return 4096; + return 8192; // 4096 for 4MB ramdisk } /* * Read a block of data. */ -int sramc_read (int unit, unsigned int blockno, char *data, unsigned int nbytes) +inline int sramc_read (int unit, unsigned int blockno, char *data, unsigned int nbytes) { int i; @@ -174,42 +132,49 @@ int sramc_read (int unit, unsigned int blockno, char *data, unsigned int nbytes) dev_load_address (blockno * DEV_BSIZE); - data_switch_input(); /* switch data bus to input */ + /* Read data. */ - /* Read data. */ + while(PMMODE & 0x8000); // Poll - if busy, wait + + PMADDR = 0; // set DATA mode (0) + + PMMODE = 0b10<<8 | (RD_PULSE<<2); // read slowly + + PMDIN; // Read the PMDIN to clear previous data and latch new data + for (i=0; i, use A0 only + + PMADDR = 0; // start with DATA mode + + PMCONSET = 1<<15; // PMP enabled + asm volatile ("nop"); + + // make a couple of dummy reads - it refreshes the cpld internals a little bit :) + while(PMMODE & 0x8000); // Poll - if busy, wait before reading + PMDIN; /* read a byte of data */ + while(PMMODE & 0x8000); // Poll - if busy, wait before reading + PMDIN; /* read a byte of data */ + + PMADDR = 1; // go with with ADDRESS mode now - /* Set idle HIGH rd, wr and ldaddr as output pins. */ - LAT_SET(SW_RD_PORT) = 1 << SW_RD_PIN; - LAT_SET(SW_WR_PORT) = 1 << SW_WR_PIN; - LAT_SET(SW_LDA_PORT) = 1 << SW_LDA_PIN; - TRIS_CLR(SW_RD_PORT) = 1 << SW_RD_PIN; - TRIS_CLR(SW_WR_PORT) = 1 << SW_WR_PIN; - TRIS_CLR(SW_LDA_PORT) = 1 << SW_LDA_PIN; - /* Toggle rd: make one dummy read. */ - rd_low(); /* set rd low */ - rd_high(); /* set rd high */ - } DEBUG3("sramc%d: init done\n",unit); bp = prepartition_device("sramc0"); if(bp) diff --git a/sys/pic32/rd_sramc_BB.c b/sys/pic32/rd_sramc_BB.c new file mode 100644 index 0000000..5886672 --- /dev/null +++ b/sys/pic32/rd_sramc_BB.c @@ -0,0 +1,258 @@ +/* + * Driver for external RAM-based swap device. + * + * Interface: + * data[7:0] - connected to PORTx + * rd - fetch a byte from memory to data[7:0], increment address + * wr - write a byte data[7:0] to memory, increment address + * ldaddr - write address from data[7:0] in 3 steps: low-middle-high + * + * Signals rd, wr, ldadr are active LOW and idle HIGH. + * To activate, you need to pulse it high-low-high. + * CHANGE: IM 23.12.2011 - signals active LOW + * CHANGE: IM 24.12.2011 - finetuning for 55ns SRAM and 7ns CPLD + * - some nops removed + * - nops marked 55ns are required !!! + * - MAX performance settings for 55ns SRAM + * CHANGE: IM 28.12.2011 - dev_load_address is 6x4bit now + */ +#include "param.h" +#include "systm.h" +#include "buf.h" +#include "errno.h" +#include "dk.h" +#include "rdisk.h" + +#include "debug.h" + +int sw_dkn = -1; /* Statistics slot number */ + +/* + * Set data output value. + */ +static inline void data_set (unsigned char byte) +{ + LAT_CLR(SW_DATA_PORT) = 0xff << SW_DATA_PIN; + LAT_SET(SW_DATA_PORT) = byte << SW_DATA_PIN; +} + +/* + * Switch data bus to input. + */ +static inline void data_switch_input () +{ + LAT_CLR(SW_DATA_PORT) = 0xff << SW_DATA_PIN; // !!! PIC32 errata + TRIS_SET(SW_DATA_PORT) = 0xff << SW_DATA_PIN; + asm volatile ("nop"); +} + +/* + * Switch data bus to output. + */ +static inline void data_switch_output () +{ + TRIS_CLR(SW_DATA_PORT) = 0xff << SW_DATA_PIN; + asm volatile ("nop"); +} + +/* + * Get data input value. + */ +static inline unsigned char data_get () +{ + return PORT_VAL(SW_DATA_PORT) >> SW_DATA_PIN; +} + +/* + * Send LDA pulse: high-low-high. + */ +static inline void lda_pulse () +{ + LAT_CLR(SW_LDA_PORT) = 1 << SW_LDA_PIN; + asm volatile ("nop"); + asm volatile ("nop"); + LAT_SET(SW_LDA_PORT) = 1 << SW_LDA_PIN; +} + +/* + * Set RD low. + * Minimal time between falling edge of RD to data valid is 50ns. + */ +static inline void rd_low () +{ + LAT_CLR(SW_RD_PORT) = 1 << SW_RD_PIN; + +#if BUS_KHZ > 33000 + asm volatile ("nop"); // 55ns + asm volatile ("nop"); // 55ns +#endif +#if BUS_KHZ > 66000 + asm volatile ("nop"); // 55ns + asm volatile ("nop"); // 55ns +#endif +} + +/* + * Set RD high. + */ +static inline void rd_high () +{ + LAT_SET(SW_RD_PORT) = 1 << SW_RD_PIN; +} + +/* + * Send WR pulse: high-low-high. + * It shall be minimally 40ns. + */ +static inline void wr_pulse () +{ + LAT_CLR(SW_WR_PORT) = 1 << SW_WR_PIN; + +#if BUS_KHZ > 33000 + asm volatile ("nop"); // 55ns + asm volatile ("nop"); // 55ns +#endif +#if BUS_KHZ > 66000 + asm volatile ("nop"); // 55ns +#endif + LAT_SET(SW_WR_PORT) = 1 << SW_WR_PIN; +} + +/* + * Load the 24 bit address to ramdisk. + * Leave data bus in input mode. + */ +static void +dev_load_address (addr) + unsigned addr; +{ + /* Toggle rd: make one dummy read - this clears cpld's addr pointer */ + rd_low (); + rd_high (); + + data_switch_output(); /* switch data bus to output */ + + data_set (addr); /* send lowest 4 bits */ + lda_pulse(); /* pulse ldaddr */ + + data_set (addr >> 4); /* send 4 bits */ + lda_pulse(); /* pulse ldaddr */ + + data_set (addr >> 8); /* send 4 bits */ + lda_pulse(); /* pulse ldaddr */ + + data_set (addr >> 12); /* send 4 bits */ + lda_pulse(); /* pulse ldaddr */ + + data_set (addr >> 16); /* send 4 bits */ + lda_pulse(); /* pulse ldaddr */ + + data_set (addr >> 20); /* send highest 4 bits */ + lda_pulse(); /* pulse ldaddr */ + + data_switch_input(); +} + +/* + * Get number of kBytes on the disk. + * Return nonzero if successful. + */ +int sramc_size ( int unit ) +{ + return 4096; +} + +/* + * Read a block of data. + */ +int sramc_read (int unit, unsigned int blockno, char *data, unsigned int nbytes) +{ + int i; + + //DEBUG9("sramc%d: read block %u, length %u bytes, addr %p\n", + // major(dev), blockno, nbytes, data); + + dev_load_address (blockno * DEV_BSIZE); + + data_switch_input(); /* switch data bus to input */ + + /* Read data. */ + for (i=0; ib_addr, 512); + brelse(bp); + } + + return; +} + +/* + * Open the disk. + */ +int sramc_open (int unit) +{ + DEBUG3("sramc%d: open\n",unit); + return 0; +}