COSA
An Object-Oriented Platform for Arduino Programming
W25X40CL.cpp
Go to the documentation of this file.
1 
21 #include "W25X40CL.hh"
22 
23 bool
25 {
26  // Check that the device is ready
27  if (!is_ready()) return (false);
28 
29  // Read identification
30  spi.acquire(this);
31  spi.begin();
32  spi.transfer(RDID);
33  spi.transfer(0);
34  spi.transfer(0);
35  spi.transfer(0);
36  uint8_t manufacturer = spi.transfer(0);
37  uint8_t device = spi.transfer(0);
38  spi.end();
39  spi.release();
40 
41  // And check
42  return (manufacturer == MANUFACTURER && device == DEVICE);
43 }
44 
45 bool
47 {
48  // Read Status Register
49  spi.acquire(this);
50  spi.begin();
51  spi.transfer(RDSR);
52  m_status = spi.transfer(0);
53  spi.end();
54  spi.release();
55 
56  // Return device is true if the device is not busy
57  return (!m_status.BUSY);
58 }
59 
60 int
61 W25X40CL::read(void* dest, uint32_t src, size_t size)
62 {
63  // Use READ with 24-bit address; Big-endian
64  uint8_t* sp = (uint8_t*) &src;
65  spi.acquire(this);
66  spi.begin();
67  spi.transfer(READ);
68  spi.transfer(sp[2]);
69  spi.transfer(sp[1]);
70  spi.transfer(sp[0]);
71  spi.read(dest, size);
72  spi.end();
73  spi.release();
74 
75  // Return number of bytes read
76  return ((int) size);
77 }
78 
79 int
80 W25X40CL::erase(uint32_t dest, uint8_t size)
81 {
82  uint8_t op;
83  switch (size) {
84  case 4: op = SER; break;
85  case 32: op = B32ER; break;
86  case 64: op = B64ER; break;
87  case 255: op = CER; break;
88  default: return (EINVAL);
89  }
90  spi.acquire(this);
91  // Write enable before page erase.
92  spi.begin();
93  spi.transfer(WREN);
94  spi.end();
95  // Use erase (SE/B32E/B64E/CER) with possible 24-bit address
96  uint8_t* dp = (uint8_t*) &dest;
97  spi.begin();
98  spi.transfer(op);
99  if (op != CER) {
100  spi.transfer(dp[2]);
101  spi.transfer(dp[1]);
102  spi.transfer(dp[0]);
103  }
104  spi.end();
105  spi.release();
106 
107  // Wait for completion and return no error
108  while (!is_ready()) yield();
109  return (0);
110 }
111 
112 int
113 W25X40CL::write(uint32_t dest, const void* src, size_t size)
114 {
115  // Check for zero buffer size
116  if (UNLIKELY(size == 0)) return (0);
117 
118  // Set up destination and source pointers
119  uint8_t* dp = (uint8_t*) &dest;
120  uint8_t* sp = (uint8_t*) src;
121  int res = (int) size;
122 
123  // Calculate block size of first program
124  size_t count = PAGE_MAX - (dest & PAGE_MASK);
125  if (UNLIKELY(count > size)) count = size;
126 
127  while (1) {
128  spi.acquire(this);
129  // Write enable before program
130  spi.begin();
131  spi.transfer(WREN);
132  spi.end();
133  // Use PP with 24-bit address; Big-endian
134  spi.begin();
135  spi.transfer(PP);
136  spi.transfer(dp[2]);
137  spi.transfer(dp[1]);
138  spi.transfer(dp[0]);
139  spi.write(sp, count);
140  spi.end();
141  spi.release();
142 
143  // Wait for completion
144  while (!is_ready()) yield();
145 
146  // Step to next page
147  size -= count;
148  if (size == 0) break;
149  dest += count;
150  sp += count;
151  count = (size > PAGE_MAX ? PAGE_MAX : size);
152  }
153 
154  // Return number of bytes programmed
155  return (res);
156 }
157 
158 int
159 W25X40CL::write_P(uint32_t dest, const void* src, size_t size)
160 {
161  // Check for zero buffer size
162  if (UNLIKELY(size == 0)) return (0);
163 
164  // Set up destination and source pointers
165  uint8_t* dp = (uint8_t*) &dest;
166  uint8_t* sp = (uint8_t*) src;
167  int res = (int) size;
168 
169  // Calculate block size of first program
170  size_t count = PAGE_MAX - (dest & PAGE_MASK);
171  if (UNLIKELY(count > size)) count = size;
172 
173  while (1) {
174  spi.acquire(this);
175  // Write enable before program
176  spi.begin();
177  spi.transfer(WREN);
178  spi.end();
179  // Use PP with 24-bit address; Big-endian
180  spi.begin();
181  spi.transfer(PP);
182  spi.transfer(dp[2]);
183  spi.transfer(dp[1]);
184  spi.transfer(dp[0]);
185  spi.write_P(sp, count);
186  spi.end();
187  spi.release();
188 
189  // Wait for completion
190  while (!is_ready()) yield();
191 
192  // Step to next page
193  size -= count;
194  if (size == 0) break;
195  dest += count;
196  sp += count;
197  count = (size > PAGE_MAX ? PAGE_MAX : size);
198  }
199 
200  // Return number of bytes programmed
201  return (res);
202 }
203 
204 uint8_t
206 {
207  spi.acquire(this);
208  spi.begin();
209  spi.transfer(cmd);
210  uint8_t res = spi.transfer(0);
211  spi.end();
212  spi.release();
213  return (res);
214 }
virtual int read(void *dest, uint32_t src, size_t size)
Definition: W25X40CL.cpp:61
#define EINVAL
Definition: Errno.h:49
uint8_t transfer(uint8_t data)
Definition: SOFT_SPI.cpp:87
Write Enable.
Definition: W25X40CL.hh:164
static const uint8_t DEVICE
Definition: W25X40CL.hh:189
static const size_t PAGE_MAX
Definition: W25X40CL.hh:43
void acquire(Driver *dev)
Definition: SOFT_SPI.cpp:43
uint8_t issue(Command cmd)
Definition: W25X40CL.cpp:205
Block Erase (32 kB).
Definition: W25X40CL.hh:174
static const size_t PAGE_MASK
Definition: W25X40CL.hh:44
void read(void *buf, size_t count)
Definition: SPI.hh:308
status_t m_status
Definition: W25X40CL.hh:199
virtual int write(uint32_t dest, const void *src, size_t size)
Definition: W25X40CL.cpp:113
Page Program.
Definition: W25X40CL.hh:172
Read Status Register.
Definition: W25X40CL.hh:167
virtual int write_P(uint32_t dest, const void *buf, size_t size)
Definition: W25X40CL.cpp:159
virtual bool begin()
Definition: W25X40CL.cpp:24
void write(const void *buf, size_t count)
Definition: SPI.hh:321
void(* yield)()
void begin()
Definition: SPI.hh:216
void end()
Definition: SPI.hh:226
Read Data.
Definition: W25X40CL.hh:169
virtual bool is_ready()
Definition: W25X40CL.cpp:46
uint8_t BUSY
< As bit-fields.
Definition: W25X40CL.hh:133
Sector Erase (4 kB).
Definition: W25X40CL.hh:173
static const uint8_t MANUFACTURER
Definition: W25X40CL.hh:186
void write_P(const uint8_t *buf, size_t count)
Definition: SPI.hh:334
Read Manufacturer/Device ID.
Definition: W25X40CL.hh:179
SPI spi
Definition: SPI.cpp:29
Chip Erase.
Definition: W25X40CL.hh:176
void release()
Definition: SOFT_SPI.cpp:64
virtual int erase(uint32_t dest, uint8_t size=4)
Definition: W25X40CL.cpp:80
#define UNLIKELY(x)
Definition: Types.h:153
Block Erase (64kB).
Definition: W25X40CL.hh:175