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