| Line No. | Rev | Author | Line | 
|---|---|---|---|
| 1 | 6 | kaklik | /*! \file spiflash.c \brief SPI Flash Memory Driver (M25Pxx/AT25Fxxx/etc). */ | 
| 2 | //***************************************************************************** | ||
| 3 | // | ||
| 4 | // File Name	: 'spiflash.c' | ||
| 5 | // Title		: SPI Flash Memory Driver (M25Pxx/AT25Fxxx/etc) | ||
| 6 | // Author		: Pascal Stang - Copyright (C) 2006 | ||
| 7 | // Created		: 2006-04-15 | ||
| 8 | // Revised		: 2006-07-02 | ||
| 9 | // Version		: 0.1 | ||
| 10 | // Target MCU	: AVR processors | ||
| 11 | // Editor Tabs	: 4 | ||
| 12 | // | ||
| 13 | // NOTE: This code is currently below version 1.0, and therefore is considered | ||
| 14 | // to be lacking in some functionality or documentation, or may not be fully | ||
| 15 | // tested.  Nonetheless, you can expect most functions to work. | ||
| 16 | // | ||
| 17 | //***************************************************************************** | ||
| 18 | |||
| 19 | // system includes | ||
| 20 | #include "avr/io.h" | ||
| 21 | #include "global.h" | ||
| 22 | |||
| 23 | // library includes | ||
| 24 | #include "spi.h" | ||
| 25 | #include "spiflash.h" | ||
| 26 | |||
| 27 | #define SPIFLASH_CONFIG_CS		DDRB  |= (1<<0) | ||
| 28 | #define SPIFLASH_ASSERT_CS		PORTB &= (1<<0) | ||
| 29 | #define SPIFLASH_RELEASE_CS		PORTB |= (1<<0) | ||
| 30 | |||
| 31 | // functions | ||
| 32 | void spiflashInit(void) | ||
| 33 | { | ||
| 34 | 	// initialize spi | ||
| 35 | 	spiInit(); | ||
| 36 | 	// initialize chip select | ||
| 37 | 	SPIFLASH_RELEASE_CS; | ||
| 38 | 	SPIFLASH_CONFIG_CS; | ||
| 39 | } | ||
| 40 | |||
| 41 | unsigned short spiflashGetID(void) | ||
| 42 | { | ||
| 43 | 	unsigned short id; | ||
| 44 | |||
| 45 | 	SPIFLASH_ASSERT_CS; | ||
| 46 | 	spiByte(0, SPIFLASH_CMD_RDID, 0); | ||
| 47 | 	id  = spiByte(0, 0x00, 0)<<8; | ||
| 48 | 	id |= spiByte(0, 0x00, 1); | ||
| 49 | 	SPIFLASH_RELEASE_CS; | ||
| 50 | |||
| 51 | 	return id; | ||
| 52 | } | ||
| 53 | |||
| 54 | void spiflashChipErase(void) | ||
| 55 | { | ||
| 56 | 	// enable write | ||
| 57 | 	SPIFLASH_ASSERT_CS; | ||
| 58 | 	spiByte(0, SPIFLASH_CMD_WREN, 1); | ||
| 59 | 	SPIFLASH_RELEASE_CS; | ||
| 60 | |||
| 61 | 	// clock out dummy byte to waste time | ||
| 62 | 	spiByte(0, 0x00, 1); | ||
| 63 | |||
| 64 | 	// do chip erase | ||
| 65 | 	SPIFLASH_ASSERT_CS; | ||
| 66 | 	spiByte(0, SPIFLASH_CMD_CHIPERASE, 1); | ||
| 67 | 	SPIFLASH_RELEASE_CS; | ||
| 68 | |||
| 69 | 	// clock out dummy byte to waste time | ||
| 70 | 	spiByte(0, 0x00, 1); | ||
| 71 | |||
| 72 | 	// wait until write is done | ||
| 73 | 	SPIFLASH_ASSERT_CS; | ||
| 74 | 	spiByte(0, SPIFLASH_CMD_RDSR, 0); | ||
| 75 | 	while(spiByte(0, 0x00, 0) & SPIFLASH_STATUS_BUSY); | ||
| 76 | 	SPIFLASH_RELEASE_CS; | ||
| 77 | } | ||
| 78 | |||
| 79 | void spiflashRead(unsigned long addr, unsigned long nbytes, unsigned char *data) | ||
| 80 | { | ||
| 81 | 	// begin read | ||
| 82 | 	SPIFLASH_ASSERT_CS; | ||
| 83 | 	// issue read command | ||
| 84 | 	spiByte(0, SPIFLASH_CMD_READ, 0); | ||
| 85 | 	// send address | ||
| 86 | 	spiByte(0, addr>>16, 0); | ||
| 87 | 	spiByte(0, addr>>8, 0); | ||
| 88 | 	spiByte(0, addr>>0, 0); | ||
| 89 | 	// read data | ||
| 90 | 	while(nbytes--) | ||
| 91 | 		*data++ = spiByte(0, 0x00, 0); | ||
| 92 | 	// end read | ||
| 93 | 	SPIFLASH_RELEASE_CS; | ||
| 94 | } | ||
| 95 | |||
| 96 | void spiflashWrite(unsigned long addr, unsigned long nbytes, unsigned char *data) | ||
| 97 | { | ||
| 98 | 	unsigned int page; | ||
| 99 | 	unsigned int i; | ||
| 100 | 	unsigned int pagelen; | ||
| 101 | |||
| 102 | 	// loop through pages to be programmed | ||
| 103 | 	for(page=0; page<((nbytes+SPIFLASH_PAGESIZE-1)>>8); page++) | ||
| 104 | 	{ | ||
| 105 | 		// program this page | ||
| 106 | |||
| 107 | 		// enable write | ||
| 108 | 		SPIFLASH_ASSERT_CS; | ||
| 109 | 		spiByte(0, SPIFLASH_CMD_WREN, 1); | ||
| 110 | 		SPIFLASH_RELEASE_CS; | ||
| 111 | |||
| 112 | 		// clock out dummy byte to waste time | ||
| 113 | 		spiByte(0, 0x00, 1); | ||
| 114 | |||
| 115 | 		// begin write | ||
| 116 | 		SPIFLASH_ASSERT_CS; | ||
| 117 | 		// issue write command | ||
| 118 | 		spiByte(0, SPIFLASH_CMD_PAGEPROG, 0); | ||
| 119 | 		// send address | ||
| 120 | 		spiByte(0, addr>>16, 0); | ||
| 121 | 		spiByte(0, addr>>8, 0); | ||
| 122 | 		spiByte(0, addr>>0, 0); | ||
| 123 | 		// program exactly the number of bytes requested | ||
| 124 | 		if( ((page<<8)+SPIFLASH_PAGESIZE) <= nbytes) | ||
| 125 | 			pagelen = SPIFLASH_PAGESIZE; | ||
| 126 | 		else | ||
| 127 | 			pagelen = nbytes-(page<<8); | ||
| 128 | 		// transfer data | ||
| 129 | 		for(i=0; i<pagelen; i++) | ||
| 130 | 			spiByte(0, *data++, 0); | ||
| 131 | 		// end write | ||
| 132 | 		SPIFLASH_RELEASE_CS; | ||
| 133 | |||
| 134 | 		// clock out dummy byte to waste time | ||
| 135 | 		spiByte(0, 0x00, 1); | ||
| 136 | |||
| 137 | 		// wait until write is done | ||
| 138 | 		SPIFLASH_ASSERT_CS; | ||
| 139 | 		spiByte(0, SPIFLASH_CMD_RDSR, 0); | ||
| 140 | 		while(spiByte(0, 0x00, 0) & SPIFLASH_STATUS_BUSY); | ||
| 141 | 		SPIFLASH_RELEASE_CS; | ||
| 142 | |||
| 143 | 		// clock out dummy byte to waste time | ||
| 144 | 		spiByte(0, 0x00, 1); | ||
| 145 | 	} | ||
| 146 | } | 
Powered by WebSVN v2.8.3