1 /*
2 * Copyright (c) 2016 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <errno.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/sys/printk.h>
10 #include <zephyr/device.h>
11 #include <zephyr/drivers/spi.h>
12
13 /**
14 * @file Sample app using the Fujitsu MB85RS64V FRAM through SPI.
15 */
16
17 #define MB85RS64V_MANUFACTURER_ID_CMD 0x9f
18 #define MB85RS64V_WRITE_ENABLE_CMD 0x06
19 #define MB85RS64V_READ_CMD 0x03
20 #define MB85RS64V_WRITE_CMD 0x02
21 #define MAX_USER_DATA_LENGTH 1024
22
23 static uint8_t data[MAX_USER_DATA_LENGTH], cmp_data[MAX_USER_DATA_LENGTH];
24
mb85rs64v_access(const struct device * spi,struct spi_config * spi_cfg,uint8_t cmd,uint16_t addr,void * data,size_t len)25 static int mb85rs64v_access(const struct device *spi,
26 struct spi_config *spi_cfg,
27 uint8_t cmd, uint16_t addr, void *data, size_t len)
28 {
29 uint8_t access[3];
30 struct spi_buf bufs[] = {
31 {
32 .buf = access,
33 },
34 {
35 .buf = data,
36 .len = len
37 }
38 };
39 struct spi_buf_set tx = {
40 .buffers = bufs
41 };
42
43 access[0] = cmd;
44
45 if (cmd == MB85RS64V_WRITE_CMD || cmd == MB85RS64V_READ_CMD) {
46 access[1] = (addr >> 8) & 0xFF;
47 access[2] = addr & 0xFF;
48
49 bufs[0].len = 3;
50 tx.count = 2;
51
52 if (cmd == MB85RS64V_READ_CMD) {
53 struct spi_buf_set rx = {
54 .buffers = bufs,
55 .count = 2
56 };
57
58 return spi_transceive(spi, spi_cfg, &tx, &rx);
59 }
60 } else {
61 tx.count = 1;
62 }
63
64 return spi_write(spi, spi_cfg, &tx);
65 }
66
67
mb85rs64v_read_id(const struct device * spi,struct spi_config * spi_cfg)68 static int mb85rs64v_read_id(const struct device *spi,
69 struct spi_config *spi_cfg)
70 {
71 uint8_t id[4];
72 int err;
73
74 err = mb85rs64v_access(spi, spi_cfg,
75 MB85RS64V_MANUFACTURER_ID_CMD, 0, &id, 4);
76 if (err) {
77 printk("Error during ID read\n");
78 return -EIO;
79 }
80
81 if (id[0] != 0x04) {
82 return -EIO;
83 }
84
85 if (id[1] != 0x7f) {
86 return -EIO;
87 }
88
89 if (id[2] != 0x03) {
90 return -EIO;
91 }
92
93 if (id[3] != 0x02) {
94 return -EIO;
95 }
96
97 return 0;
98 }
99
write_bytes(const struct device * spi,struct spi_config * spi_cfg,uint16_t addr,uint8_t * data,uint32_t num_bytes)100 static int write_bytes(const struct device *spi, struct spi_config *spi_cfg,
101 uint16_t addr, uint8_t *data, uint32_t num_bytes)
102 {
103 int err;
104
105 /* disable write protect */
106 err = mb85rs64v_access(spi, spi_cfg,
107 MB85RS64V_WRITE_ENABLE_CMD, 0, NULL, 0);
108 if (err) {
109 printk("unable to disable write protect\n");
110 return -EIO;
111 }
112
113 /* write cmd */
114 err = mb85rs64v_access(spi, spi_cfg,
115 MB85RS64V_WRITE_CMD, addr, data, num_bytes);
116 if (err) {
117 printk("Error during SPI write\n");
118 return -EIO;
119 }
120
121 return 0;
122 }
123
read_bytes(const struct device * spi,struct spi_config * spi_cfg,uint16_t addr,uint8_t * data,uint32_t num_bytes)124 static int read_bytes(const struct device *spi, struct spi_config *spi_cfg,
125 uint16_t addr, uint8_t *data, uint32_t num_bytes)
126 {
127 int err;
128
129 /* read cmd */
130 err = mb85rs64v_access(spi, spi_cfg,
131 MB85RS64V_READ_CMD, addr, data, num_bytes);
132 if (err) {
133 printk("Error during SPI read\n");
134 return -EIO;
135 }
136
137 return 0;
138 }
139
main(void)140 int main(void)
141 {
142 const struct device *spi;
143 struct spi_config spi_cfg = {0};
144 int err;
145
146 printk("fujitsu FRAM example application\n");
147
148 spi = DEVICE_DT_GET(DT_ALIAS(spi_1));
149 if (!device_is_ready(spi)) {
150 printk("SPI device %s is not ready\n", spi->name);
151 return 0;
152 }
153
154 spi_cfg.operation = SPI_WORD_SET(8);
155 spi_cfg.frequency = 256000U;
156
157
158 err = mb85rs64v_read_id(spi, &spi_cfg);
159 if (err) {
160 printk("Could not verify FRAM ID\n");
161 return 0;
162 }
163
164 /* Do one-byte read/write */
165 data[0] = 0xAE;
166 err = write_bytes(spi, &spi_cfg, 0x00, data, 1);
167 if (err) {
168 printk("Error writing to FRAM! error code (%d)\n", err);
169 return 0;
170 } else {
171 printk("Wrote 0xAE to address 0x00.\n");
172 }
173
174 data[0] = 0x86;
175 err = write_bytes(spi, &spi_cfg, 0x01, data, 1);
176 if (err) {
177 printk("Error writing to FRAM! error code (%d)\n", err);
178 return 0;
179 } else {
180 printk("Wrote 0x86 to address 0x01.\n");
181 }
182
183 data[0] = 0x00;
184 err = read_bytes(spi, &spi_cfg, 0x00, data, 1);
185 if (err) {
186 printk("Error reading from FRAM! error code (%d)\n", err);
187 return 0;
188 } else {
189 printk("Read 0x%X from address 0x00.\n", data[0]);
190 }
191
192 data[0] = 0x00;
193 err = read_bytes(spi, &spi_cfg, 0x01, data, 1);
194 if (err) {
195 printk("Error reading from FRAM! error code (%d)\n", err);
196 return 0;
197 } else {
198 printk("Read 0x%X from address 0x01.\n", data[0]);
199 }
200
201 /* Do multi-byte read/write */
202 /* get some random data, and clear out data[] */
203 for (uint32_t i = 0; i < sizeof(cmp_data); i++) {
204 cmp_data[i] = k_cycle_get_32() & 0xFF;
205 data[i] = 0x00;
206 }
207
208 /* write them to the FRAM */
209 err = write_bytes(spi, &spi_cfg, 0x00, cmp_data, sizeof(cmp_data));
210 if (err) {
211 printk("Error writing to FRAM! error code (%d)\n", err);
212 return 0;
213 } else {
214 printk("Wrote %d bytes to address 0x00.\n",
215 (uint32_t) sizeof(cmp_data));
216 }
217
218 err = read_bytes(spi, &spi_cfg, 0x00, data, sizeof(data));
219 if (err) {
220 printk("Error reading from FRAM! error code (%d)\n", err);
221 return 0;
222 } else {
223 printk("Read %d bytes from address 0x00.\n",
224 (uint32_t) sizeof(data));
225 }
226
227 err = 0;
228 for (uint32_t i = 0; i < sizeof(cmp_data); i++) {
229 if (cmp_data[i] != data[i]) {
230 printk("Data comparison failed @ %d.\n", i);
231 err = -EIO;
232 }
233 }
234 if (err == 0) {
235 printk("Data comparison successful.\n");
236 }
237 return 0;
238 }
239