| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 | //w25x20cl.c#include "w25x20cl.h"#include <avr/io.h>#include <avr/pgmspace.h>#include "io_atmega2560.h"#include "spi.h"#define _MFRID             0xEF#define _DEVID             0x11#define _CMD_ENABLE_WR     0x06#define _CMD_ENABLE_WR_VSR 0x50#define _CMD_DISABLE_WR    0x04#define _CMD_RD_STATUS_REG 0x05#define _CMD_WR_STATUS_REG 0x01#define _CMD_RD_DATA       0x03#define _CMD_RD_FAST       0x0b#define _CMD_RD_FAST_D_O   0x3b#define _CMD_RD_FAST_D_IO  0xbb#define _CMD_PAGE_PROGRAM  0x02#define _CMD_SECTOR_ERASE  0x20#define _CMD_BLOCK32_ERASE 0x52#define _CMD_BLOCK64_ERASE 0xd8#define _CMD_CHIP_ERASE    0xc7#define _CMD_CHIP_ERASE2   0x60#define _CMD_PWR_DOWN      0xb9#define _CMD_PWR_DOWN_REL  0xab#define _CMD_MFRID_DEVID   0x90#define _CMD_MFRID_DEVID_D 0x92#define _CMD_JEDEC_ID      0x9f#define _CMD_RD_UID        0x4b#define _CS_LOW()  PORT(W25X20CL_PIN_CS) &= ~__MSK(W25X20CL_PIN_CS)#define _CS_HIGH() PORT(W25X20CL_PIN_CS) |= __MSK(W25X20CL_PIN_CS)//#define _SPI_TX swspi_tx//#define _SPI_RX swspi_rx#define _SPI_TX(b)   spi_txrx(b)#define _SPI_RX()    spi_txrx(0xff)int w25x20cl_mfrid_devid(void);int8_t w25x20cl_init(void){	PIN_OUT(W25X20CL_PIN_CS);	_CS_HIGH();	W25X20CL_SPI_ENTER();	if (!w25x20cl_mfrid_devid()) return 0;	return 1;}void w25x20cl_enable_wr(void){	_CS_LOW();	_SPI_TX(_CMD_ENABLE_WR);             // send command 0x06	_CS_HIGH();}void w25x20cl_disable_wr(void){	_CS_LOW();	_SPI_TX(_CMD_DISABLE_WR);            // send command 0x04	_CS_HIGH();}uint8_t w25x20cl_rd_status_reg(void){	_CS_LOW();	_SPI_TX(_CMD_RD_STATUS_REG);         // send command 0x90	uint8_t val = _SPI_RX();             // receive value	_CS_HIGH();	return val;}void w25x20cl_wr_status_reg(uint8_t val){	_CS_LOW();	_SPI_TX(_CMD_WR_STATUS_REG);         // send command 0x90	_SPI_TX(val);                        // send value	_CS_HIGH();}void w25x20cl_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt){	_CS_LOW();	_SPI_TX(_CMD_RD_DATA);               // send command 0x03	_SPI_TX(((uint8_t*)&addr)[2]);       // send addr bits 16..23	_SPI_TX(((uint8_t*)&addr)[1]);       // send addr bits 8..15	_SPI_TX(((uint8_t*)&addr)[0]);       // send addr bits 0..7	while (cnt--)                        // receive data		*(data++) = _SPI_RX();	_CS_HIGH();}void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt){	_CS_LOW();	_SPI_TX(_CMD_PAGE_PROGRAM);          // send command 0x02	_SPI_TX(((uint8_t*)&addr)[2]);       // send addr bits 16..23	_SPI_TX(((uint8_t*)&addr)[1]);       // send addr bits 8..15	_SPI_TX(((uint8_t*)&addr)[0]);       // send addr bits 0..7	while (cnt--)                        // send data		_SPI_TX(*(data++));	_CS_HIGH();}void w25x20cl_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt){	_CS_LOW();	_SPI_TX(_CMD_PAGE_PROGRAM);          // send command 0x02	_SPI_TX(((uint8_t*)&addr)[2]);       // send addr bits 16..23	_SPI_TX(((uint8_t*)&addr)[1]);       // send addr bits 8..15	_SPI_TX(((uint8_t*)&addr)[0]);       // send addr bits 0..7	while (cnt--)                        // send data		_SPI_TX(pgm_read_byte(data++));	_CS_HIGH();}void w25x20cl_erase(uint8_t cmd, uint32_t addr){	_CS_LOW();	_SPI_TX(cmd);          			     // send command 0x20	_SPI_TX(((uint8_t*)&addr)[2]);       // send addr bits 16..23	_SPI_TX(((uint8_t*)&addr)[1]);       // send addr bits 8..15	_SPI_TX(((uint8_t*)&addr)[0]);       // send addr bits 0..7	_CS_HIGH();}void w25x20cl_sector_erase(uint32_t addr){	return w25x20cl_erase(_CMD_SECTOR_ERASE, addr);}void w25x20cl_block32_erase(uint32_t addr){	return w25x20cl_erase(_CMD_BLOCK32_ERASE, addr);}void w25x20cl_block64_erase(uint32_t addr){	return w25x20cl_erase(_CMD_BLOCK64_ERASE, addr);}void w25x20cl_chip_erase(void){	_CS_LOW();	_SPI_TX(_CMD_CHIP_ERASE);            // send command 0xc7	_CS_HIGH();}void w25x20cl_rd_uid(uint8_t* uid){	_CS_LOW();	_SPI_TX(_CMD_RD_UID);                // send command 0x4b	uint8_t cnt = 4;                     // 4 dummy bytes	while (cnt--)                        // receive dummy bytes		_SPI_RX();	cnt = 8;                             // 8 bytes UID	while (cnt--)                        // receive UID		uid[7 - cnt] = _SPI_RX();	_CS_HIGH();}int w25x20cl_mfrid_devid(void){	_CS_LOW();	_SPI_TX(_CMD_MFRID_DEVID);           // send command 0x90	uint8_t cnt = 3;                     // 3 address bytes	while (cnt--)                        // send address bytes		_SPI_TX(0x00);	uint8_t w25x20cl_mfrid = _SPI_RX();  // receive mfrid	uint8_t w25x20cl_devid = _SPI_RX();  // receive devid	_CS_HIGH();	return ((w25x20cl_mfrid == _MFRID) && (w25x20cl_devid == _DEVID));}void w25x20cl_wait_busy(void){	while (w25x20cl_rd_status_reg() & W25X20CL_STATUS_BUSY) ;}
 |