px-fwlib 0.10.0
Cross-platform embedded library and documentation for 8/16/32-bit microcontrollers generated with Doxygen 1.9.2
px_at25s.c
1/* =============================================================================
2 ____ ___ ____ ___ _ _ ___ __ __ ___ __ __ TM
3 | _ \ |_ _| / ___| / _ \ | \ | | / _ \ | \/ | |_ _| \ \/ /
4 | |_) | | | | | | | | | | \| | | | | | | |\/| | | | \ /
5 | __/ | | | |___ | |_| | | |\ | | |_| | | | | | | | / \
6 |_| |___| \____| \___/ |_| \_| \___/ |_| |_| |___| /_/\_\
7
8 Copyright (c) 2018 Pieter Conradie <https://piconomix.com>
9
10 License: MIT
11 https://github.com/piconomix/px-fwlib/blob/master/LICENSE.md
12
13 Title: px_at25s.h : Adesto AT25S Serial Flash Driver
14 Author(s): Pieter Conradie
15 Creation Date: 2018-10-12
16
17============================================================================= */
18
19/* _____STANDARD INCLUDES____________________________________________________ */
20
21/* _____PROJECT INCLUDES_____________________________________________________ */
22#include "px_at25s.h"
23#include "px_log.h"
24
25/* _____LOCAL DEFINITIONS____________________________________________________ */
26PX_LOG_NAME("px_at25s");
27
28/// @name Read commands
29/// @{
30#define PX_AT25S_CMD_READ_ARRAY 0x03
31/// @}
32
33/// @name Program and Erase commands
34/// @{
35#define PX_AT25S_CMD_BLOCK_ERASE_4KB 0x20
36#define PX_AT25S_CMD_BLOCK_ERASE_32KB 0x52
37#define PX_AT25S_CMD_BLOCK_ERASE_64KB 0xd8
38#define PX_AT25S_CMD_CHIP_ERASE 0x60
39#define PX_AT25S_CMD_BYTE_PAGE_PROG 0x02
40/// @}
41
42/// @name Protection commands
43/// @{
44#define PX_AT25S_CMD_WR_ENABLE 0x06
45#define PX_AT25S_CMD_WR_DISABLE 0x04
46/// @}
47
48/// @name Status Register commands
49/// @{
50#define PX_AT25S_CMD_RD_STATUS_REG_BYTE_1 0x05
51#define PX_AT25S_CMD_RD_STATUS_REG_BYTE_2 0x35
52#define PX_AT25S_CMD_WR_STATUS_REG 0x01
53#define PX_AT25S_CMD_WR_EN_VOL_STATUS_REG 0x50
54/// @}
55
56/// @name Miscellaneous commands
57/// @{
58#define PX_AT25S_CMD_RD_MAN_AND_DEVICE_ID 0x9f
59#define PX_AT25S_CMD_RD_ID 0x90
60#define PX_AT25S_CMD_DEEP_PWR_DN 0xb9
61#define PX_AT25S_CMD_RESUME_FROM_DEEP_PWR_DN 0xab
62/// @}
63
64/* _____MACROS_______________________________________________________________ */
65
66/* _____GLOBAL VARIABLES_____________________________________________________ */
67
68/* _____LOCAL VARIABLES______________________________________________________ */
69static bool px_at25s_ready_flag;
70static px_spi_handle_t * px_at25s_spi_handle;
71
72/* _____LOCAL FUNCTION DECLARATIONS__________________________________________ */
73
74/* _____LOCAL FUNCTIONS______________________________________________________ */
75static void px_at25s_tx_adr(uint32_t adr)
76{
77 uint8_t data[3];
78
79 data[0] = PX_U32_MH8(adr);
80 data[1] = PX_U32_ML8(adr);
81 data[2] = PX_U32_LO8(adr);
82
83 px_spi_wr(px_at25s_spi_handle, data, 3, 0);
84}
85
86static void px_at25s_write_enable(void)
87{
88 uint8_t data[1];
89
90 data[0] = PX_AT25S_CMD_WR_ENABLE;
91 px_spi_wr(px_at25s_spi_handle, data, 1, PX_SPI_FLAG_START_AND_STOP);
92}
93
94/* _____GLOBAL FUNCTIONS_____________________________________________________ */
96{
97 // Set flag
98 px_at25s_ready_flag = true;
99 // Save SPI slave device handle
100 px_at25s_spi_handle = handle;
101}
102
104{
105 uint8_t data[1];
106
107 data[0] = PX_AT25S_CMD_DEEP_PWR_DN;
108 px_spi_wr(px_at25s_spi_handle, data, 1, PX_SPI_FLAG_START_AND_STOP);
109}
110
112{
113 uint8_t data[1];
114
115 data[0] = PX_AT25S_CMD_RESUME_FROM_DEEP_PWR_DN;
116 px_spi_wr(px_at25s_spi_handle, data, 1, PX_SPI_FLAG_START_AND_STOP);
117}
118
119void px_at25s_rd(void * buf, uint32_t adr, uint16_t nr_of_bytes)
120{
121 uint8_t data[1];
122
123 // See if specified address is out of bounds
125 // Wait until Serial Flash is not busy
126 while(!px_at25s_ready()) {;}
127 // Send command
128 data[0] = PX_AT25S_CMD_READ_ARRAY;
129 px_spi_wr(px_at25s_spi_handle, data, 1, PX_SPI_FLAG_START);
130 // Send address
131 px_at25s_tx_adr(adr);
132 // Read data
133 px_spi_rd(px_at25s_spi_handle, buf, nr_of_bytes, PX_SPI_FLAG_STOP);
134}
135
136void px_at25s_rd_page(void * buf, uint16_t page)
137{
139}
140
142 uint16_t page,
143 uint8_t start_byte_in_page,
144 uint16_t nr_of_bytes)
145{
146 px_at25s_rd(buf, page * PX_AT25S_PAGE_SIZE + start_byte_in_page, nr_of_bytes);
147}
148
149void px_at25s_wr_page(const void * buf, uint16_t page)
150{
151 uint8_t data[1];
152
153 // Wait until Serial Flash is not busy
154 while(!px_at25s_ready()) {;}
155 // Send Write Enable command
156 px_at25s_write_enable();
157 // Send command
158 data[0] = PX_AT25S_CMD_BYTE_PAGE_PROG;
159 px_spi_wr(px_at25s_spi_handle, data, 1, PX_SPI_FLAG_START);
160 // Send address
161 px_at25s_tx_adr(page * PX_AT25S_PAGE_SIZE);
162 // Send data to be written
163 px_spi_wr(px_at25s_spi_handle, buf, PX_AT25S_PAGE_SIZE, PX_SPI_FLAG_STOP);
164 // Set flag to busy
165 px_at25s_ready_flag = false;
166}
167
168void px_at25s_wr_page_offset(const void * buf,
169 uint16_t page,
170 uint8_t start_byte_in_page,
171 uint16_t nr_of_bytes)
172{
173 uint8_t data[1];
174
175 // Wait until Serial Flash is not busy
176 while(!px_at25s_ready()) {;}
177 // Send Write Enable command
178 px_at25s_write_enable();
179 // Send command
180 data[0] = PX_AT25S_CMD_BYTE_PAGE_PROG;
181 px_spi_wr(px_at25s_spi_handle, data, 1, PX_SPI_FLAG_START);
182 // Send address
183 px_at25s_tx_adr(page * PX_AT25S_PAGE_SIZE + start_byte_in_page);
184 // Send data to be written
185 px_spi_wr(px_at25s_spi_handle, buf, nr_of_bytes, PX_SPI_FLAG_STOP);
186 // Set flag to busy
187 px_at25s_ready_flag = false;
188}
189
190void px_at25s_erase(px_at25s_block_t block, uint16_t page)
191{
192 uint8_t data[1];
193 uint32_t adr;
194
195 // Wait until Serial Flash is not busy
196 while(!px_at25s_ready()) {;}
197 // Send Write Enable command
198 px_at25s_write_enable();
199 // Select command according to specified block size
200 switch(block)
201 {
202 case PX_AT25S_BLOCK_4KB:
203 data[0] = PX_AT25S_CMD_BLOCK_ERASE_4KB;
204 if(page % PX_AT25S_PAGES_PER_BLOCK_4KB != 0)
205 {
206 PX_LOG_E("page nr %u is not on a erase block boundary", page);
207 }
208 break;
209 case PX_AT25S_BLOCK_32KB:
210 data[0] = PX_AT25S_CMD_BLOCK_ERASE_32KB;
211 if(page % PX_AT25S_PAGES_PER_BLOCK_32KB != 0)
212 {
213 PX_LOG_E("page nr %u is not on a erase block boundary", page);
214 }
215 break;
216 case PX_AT25S_BLOCK_64KB :
217 data[0] = PX_AT25S_CMD_BLOCK_ERASE_64KB;
218 if(page % PX_AT25S_PAGES_PER_BLOCK_64KB != 0)
219 {
220 PX_LOG_E("page nr %u is not on a erase block boundary", page);
221 }
222 break;
223 default:
224 PX_LOG_E("Invalid block size specified");
225 return;
226 }
227 // Calculate address
228 adr = page * PX_AT25S_PAGE_SIZE;
229 // Send command
230 px_spi_wr(px_at25s_spi_handle, data, 1, PX_SPI_FLAG_START);
231 // Send address
232 px_at25s_tx_adr(adr);
233 // Deselect Serial Flash
234 px_spi_wr(px_at25s_spi_handle, NULL, 0, PX_SPI_FLAG_STOP);
235 // Set flag to busy
236 px_at25s_ready_flag = false;
237}
238
239void px_at25s_erase_chip(void)
240{
241 uint8_t data[1];
242
243 // Wait until Serial Flash is not busy
244 while(!px_at25s_ready()) {;}
245 // Send Write Enable command
246 px_at25s_write_enable();
247 // Send command
248 data[0] = PX_AT25S_CMD_CHIP_ERASE;
249 px_spi_wr(px_at25s_spi_handle, data, 1, PX_SPI_FLAG_START_AND_STOP);
250 // Set flag to busy
251 px_at25s_ready_flag = false;
252}
253
255{
256 uint8_t data;
257
258 // If flag has already been set, then take shortcut
259 if(px_at25s_ready_flag)
260 {
261 return true;
262 }
263 // Read status
265 // See if Serial Flash is ready
267 {
268 // Set flag
269 px_at25s_ready_flag = true;
270 return true;
271 }
272 else
273 {
274 return false;
275 }
276}
277
279{
280 uint8_t data[1];
281
282 // Send command
283 data[0] = PX_AT25S_CMD_RD_STATUS_REG_BYTE_1;
284 px_spi_wr(px_at25s_spi_handle, data, 1, PX_SPI_FLAG_START);
285 // Read status
286 px_spi_rd(px_at25s_spi_handle, data, 1, PX_SPI_FLAG_STOP);
287
288 return data[0];
289}
290
291void px_at25s_rd_man_and_dev_id(uint8_t * buf)
292{
293 uint8_t data[1];
294
295 // Send command
296 data[0] = PX_AT25S_CMD_RD_MAN_AND_DEVICE_ID;
297 px_spi_wr(px_at25s_spi_handle, data, 1, PX_SPI_FLAG_START);
298 // Read manufacturer and device ID
299 px_spi_rd(px_at25s_spi_handle, buf, 3, PX_SPI_FLAG_STOP);
300}
void px_at25s_rd_man_and_dev_id(uint8_t *buf)
Read Manufacturer and Device ID.
Definition: px_at25s.c:291
px_at25s_block_t
AT25S block selection.
Definition: px_at25s.h:71
void px_at25s_init(px_spi_handle_t *handle)
Initialise driver.
Definition: px_at25s.c:95
void px_at25s_wr_page_offset(const void *buf, uint16_t page, uint8_t start_byte_in_page, uint16_t nr_of_bytes)
Partial write of data in a page of Serial Flash.
Definition: px_at25s.c:168
#define PX_AT25S_PAGE_SIZE
AT25S page size.
Definition: px_at25s.h:67
void px_at25s_rd_page(void *buf, uint16_t page)
Read a page from Serial Flash.
Definition: px_at25s.c:136
void px_at25s_resume_from_deep_power_down(void)
Power up device to resume communication.
Definition: px_at25s.c:111
void px_at25s_rd(void *buf, uint32_t adr, uint16_t nr_of_bytes)
Read data from Serial Flash.
Definition: px_at25s.c:119
void px_at25s_wr_page(const void *buf, uint16_t page)
Write a page from Serial Flash.
Definition: px_at25s.c:149
uint8_t px_at25s_rd_status_reg1(void)
Read status register 1 of the Serial Flash.
Definition: px_at25s.c:278
#define PX_AT25S_STATUS_REG1_BSY
Ready/Busy Status.
Definition: px_at25s.h:121
bool px_at25s_ready(void)
Check if Serial Flash is ready for the next read or write access.
Definition: px_at25s.c:254
void px_at25s_erase(px_at25s_block_t block, uint16_t page)
Erase a block of Serial Flash.
Definition: px_at25s.c:190
#define PX_AT25S_ADR_MAX
Maximum address.
Definition: px_at25s.h:110
void px_at25s_rd_page_offset(void *buf, uint16_t page, uint8_t start_byte_in_page, uint16_t nr_of_bytes)
Partial read of data in a page of Serial Flash.
Definition: px_at25s.c:141
void px_at25s_deep_power_down(void)
Power down device to minimise power consumption.
Definition: px_at25s.c:103
#define NULL
NULL pointer.
Definition: px_defs.h:49
#define PX_U32_LO8(data)
Extract the low 8 bits (bits 7..0) of a 32-bit value.
Definition: px_defs.h:240
#define PX_BIT_IS_LO(var, bit)
Test if a bit is cleared (0?)
Definition: px_defs.h:190
#define PX_U32_MH8(data)
Extract the middle high 8 bits (bits 23..16) of a 32-bit value.
Definition: px_defs.h:234
#define PX_U32_ML8(data)
Extract the middle low 8 bits (bits 15..8) of a 32-bit value.
Definition: px_defs.h:237
#define PX_LOG_NAME(name)
Macro to declare a log name string once for each file to reduce code size.
Definition: px_log.h:349
#define PX_LOG_E(format,...)
Macro to display a formatted ERROR message.
Definition: px_log.h:377
#define PX_LOG_ASSERT(expression)
Macro that will test an expression, and block indefinitely if false.
Definition: px_log.h:440
#define PX_SPI_FLAG_START_AND_STOP
Begin and finish SPI transaction.
Definition: px_spi.h:121
#define PX_SPI_FLAG_START
Begin SPI transaction (take SPI slave's Chip Select line low)
Definition: px_spi.h:117
void px_spi_wr(px_spi_handle_t *handle, const void *data, size_t nr_of_bytes, uint8_t flags)
Perform an SPI write transaction with an SPI slave.
Definition: px_spi.c:396
void px_spi_rd(px_spi_handle_t *handle, void *data, size_t nr_of_bytes, uint8_t flags)
Perform an SPI read transaction with an SPI slave.
Definition: px_spi.c:479
#define PX_SPI_FLAG_STOP
Finish SPI transaction (take SPI slave's Chip Select line high)
Definition: px_spi.h:119
Define SPI handle.
Definition: px_spi.h:126