#include "RAMTRON.h" #include // register numbers #define RAMTRON_RDID 0x9f #define RAMTRON_READ 0x03 #define RAMTRON_RDSR 0x05 #define RAMTRON_WREN 0x06 #define RAMTRON_WRITE 0x02 struct ramtron_id { uint8_t id1, id2; uint16_t size_kbyte; uint8_t addrlen; }; /* list of supported devices. Thanks to NuttX ramtron driver */ static const struct ramtron_id ramtron_ids[] = { { 0x21, 0x00, 16, 2 }, // FM25V01 { 0x21, 0x08, 16, 2 }, // FM25V01A { 0x22, 0x00, 32, 2 }, // FM25V02 { 0x22, 0x08, 32, 2 }, // FM25V02A { 0x22, 0x01, 32, 2 }, // FM25VN02 { 0x23, 0x00, 64, 2 }, // FM25V05 { 0x23, 0x01, 64, 2 }, // FM25VN05 { 0x24, 0x00, 128, 3 }, // FM25V10 { 0x24, 0x01, 128, 3 }, // FM25VN10 { 0x25, 0x08, 256, 3 }, // FM25V20A { 0x26, 0x08, 512, 3 }, // CY15B104Q { 0x27, 0x03, 128, 3 }, // MB85RS1MT { 0x05, 0x09, 32, 3 }, // B85RS256B { 0x25, 0x00, 256, 3 }, // FM25V20GL }; uint32_t RAMTRON_size(RAMTRON *fram) { return ramtron_ids[fram->id].size_kbyte * 1024UL; } // initialise the driver int RAMTRON_init(RAMTRON *fram, SPI_DEV_t *dev) { if (!dev) { return -1; } fram->dev = dev; SPI_DEV_begin(fram->dev, -1); SPI_DEV_select(fram->dev); struct rdid { uint8_t manufacturer[6]; uint8_t memory; uint8_t id1; uint8_t id2; } rdid; if (!SPI_DEV_read_registers(fram->dev, RAMTRON_RDID, (uint8_t*) &rdid, sizeof(rdid))) { SPI_DEV_end(fram->dev); SPI_DEV_unselect(fram->dev); return -2; } SPI_DEV_unselect(fram->dev); SPI_DEV_end(fram->dev); for (uint8_t i = 0; i < sizeof(ramtron_ids)/sizeof(struct ramtron_id); i++) { if (ramtron_ids[i].id1 == rdid.id1 && ramtron_ids[i].id2 == rdid.id2) { fram->id = i; return 0; } } printf("Unknown RAMTRON manufacturer=%02x memory=%02x id1=%02x id2=%02x\n", rdid.manufacturer[0], rdid.memory, rdid.id1, rdid.id2); return -3; } /* send a command and offset */ static void send_offset(RAMTRON *fram, uint8_t cmd, uint32_t offset) { if (ramtron_ids[fram->id].addrlen == 3) { uint8_t b[4] = { cmd, (uint8_t) ((offset >> 16) & 0xFF), (uint8_t) ((offset >> 8) & 0xFF), (uint8_t) (offset & 0xFF) }; SPI_DEV_transfer(fram->dev, b, sizeof(b), NULL, 0, 2); } else /* len 2 */{ uint8_t b[3] = { cmd, (uint8_t) ((offset >> 8) & 0xFF), (uint8_t) (offset & 0xFF) }; SPI_DEV_transfer(fram->dev, b, sizeof(b), NULL, 0, 2); } } // read from device bool RAMTRON_read(RAMTRON *fram, uint32_t offset, uint8_t *buf, uint32_t size) { const uint8_t maxread = 128; while (size > maxread) { if (!RAMTRON_read(fram, offset, buf, maxread)) { return false; } offset += maxread; buf += maxread; size -= maxread; } SPI_DEV_begin(fram->dev, 10); SPI_DEV_select(fram->dev); send_offset(fram, RAMTRON_READ, offset); // get data SPI_DEV_transfer(fram->dev, NULL, 0, buf, size, 10); SPI_DEV_unselect(fram->dev); SPI_DEV_end(fram->dev); return true; } // write to device bool RAMTRON_write(RAMTRON *fram, uint32_t offset, uint8_t *buf, uint32_t size) { SPI_DEV_begin(fram->dev, 10); // write enable uint8_t r = RAMTRON_WREN; SPI_DEV_select(fram->dev); SPI_DEV_transfer(fram->dev, &r, 1, NULL, 0, 1); SPI_DEV_unselect(fram->dev); SPI_DEV_select(fram->dev); send_offset(fram, RAMTRON_WRITE, offset); SPI_DEV_transfer(fram->dev, buf, size, NULL, 0, 1); SPI_DEV_unselect(fram->dev); SPI_DEV_end(fram->dev); return true; }