diff options
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/components/mx25r_flash/mx25r_flash.c')
-rw-r--r-- | lib/chibios-contrib/ext/mcux-sdk/components/mx25r_flash/mx25r_flash.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/components/mx25r_flash/mx25r_flash.c b/lib/chibios-contrib/ext/mcux-sdk/components/mx25r_flash/mx25r_flash.c new file mode 100644 index 000000000..f50eb1fda --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/components/mx25r_flash/mx25r_flash.c | |||
@@ -0,0 +1,142 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016, Freescale Semiconductor, Inc. | ||
3 | * Copyright 2016-2017 NXP | ||
4 | * All rights reserved. | ||
5 | * | ||
6 | * SPDX-License-Identifier: BSD-3-Clause | ||
7 | */ | ||
8 | |||
9 | #include "mx25r_flash.h" | ||
10 | |||
11 | #define MX25R_BYTE_ADDR1(address) ((address >> 16) & 0xf) | ||
12 | #define MX25R_BYTE_ADDR2(address) ((address >> 8) & 0xf) | ||
13 | #define MX25R_BYTE_ADDR3(address) (address & 0xf) | ||
14 | |||
15 | /* initialize 'mx25r_instance' */ | ||
16 | mx25r_err_t mx25r_init(struct mx25r_instance *instance, transfer_cb_t callback, void *callback_prv) | ||
17 | { | ||
18 | instance->callback = callback; | ||
19 | instance->prv = callback_prv; | ||
20 | return mx25r_err_ok; | ||
21 | } | ||
22 | |||
23 | /* read 'rdid' to 'result' */ | ||
24 | mx25r_err_t mx25r_cmd_rdid(struct mx25r_instance *instance, struct mx25r_rdid_result *result) | ||
25 | { | ||
26 | instance->cmd[0] = 0x9f; | ||
27 | instance->callback(instance->prv, instance->cmd, NULL, 1, false); | ||
28 | instance->callback(instance->prv, NULL, (uint8_t *)result, sizeof(*result), true); | ||
29 | return mx25r_err_ok; | ||
30 | } | ||
31 | |||
32 | /* read n bytes starting at 'address' */ | ||
33 | mx25r_err_t mx25r_cmd_read(struct mx25r_instance *instance, uint32_t address, uint8_t *buffer, uint32_t size) | ||
34 | { | ||
35 | if (address & 0xFF000000U) | ||
36 | { | ||
37 | return mx25r_err_out_of_range; | ||
38 | } | ||
39 | instance->cmd[0] = 0x03; | ||
40 | instance->cmd[1] = MX25R_BYTE_ADDR1(address); | ||
41 | instance->cmd[2] = MX25R_BYTE_ADDR2(address); | ||
42 | instance->cmd[3] = MX25R_BYTE_ADDR3(address); | ||
43 | instance->callback(instance->prv, instance->cmd, NULL, 4, false); | ||
44 | instance->callback(instance->prv, NULL, (uint8_t *)buffer, size, true); | ||
45 | return mx25r_err_ok; | ||
46 | } | ||
47 | |||
48 | /* no operation */ | ||
49 | mx25r_err_t mx25r_cmd_nop(struct mx25r_instance *instance) | ||
50 | { | ||
51 | instance->callback(instance->prv, instance->cmd, NULL, 1, true); | ||
52 | return mx25r_err_ok; | ||
53 | } | ||
54 | |||
55 | /* read status register */ | ||
56 | mx25r_err_t mx25r_cmd_rdsr(struct mx25r_instance *instance, struct mx25r_rdsr_result *result) | ||
57 | { | ||
58 | instance->cmd[0] = 0x05; | ||
59 | instance->callback(instance->prv, instance->cmd, NULL, 1, false); | ||
60 | instance->callback(instance->prv, NULL, (uint8_t *)result, sizeof(*result), true); | ||
61 | return mx25r_err_ok; | ||
62 | } | ||
63 | |||
64 | /* disable write operations */ | ||
65 | mx25r_err_t mx25r_cmd_wrdi(struct mx25r_instance *instance) | ||
66 | { | ||
67 | instance->cmd[0] = 0x04; | ||
68 | instance->callback(instance->prv, instance->cmd, NULL, 1, true); | ||
69 | return mx25r_err_ok; | ||
70 | } | ||
71 | |||
72 | /* enable write operations */ | ||
73 | mx25r_err_t mx25r_cmd_wren(struct mx25r_instance *instance) | ||
74 | { | ||
75 | instance->cmd[0] = 0x06; | ||
76 | instance->callback(instance->prv, instance->cmd, NULL, 1, true); | ||
77 | return mx25r_err_ok; | ||
78 | } | ||
79 | |||
80 | /* write n bytes (256 max) starting at 'address' aligned to 256 */ | ||
81 | mx25r_err_t mx25r_cmd_write(struct mx25r_instance *instance, | ||
82 | uint32_t address_256_align, | ||
83 | uint8_t *buffer, | ||
84 | uint32_t size_256_max) | ||
85 | { | ||
86 | struct mx25r_rdsr_result result; | ||
87 | if (address_256_align & 0xFF000000U) | ||
88 | { | ||
89 | return mx25r_err_out_of_range; | ||
90 | } | ||
91 | if (address_256_align & 0xFFU) | ||
92 | { | ||
93 | return mx25r_err_alignement; | ||
94 | } | ||
95 | if (size_256_max > 256) | ||
96 | { | ||
97 | return mx25r_err_out_of_range; | ||
98 | } | ||
99 | /* enable write and wait until WEL is 1 */ | ||
100 | mx25r_cmd_wren(instance); | ||
101 | do | ||
102 | { | ||
103 | mx25r_cmd_rdsr(instance, &result); | ||
104 | } while (!(result.sr0 & 0x2)); | ||
105 | /* write sequence */ | ||
106 | instance->cmd[0] = 0x02; | ||
107 | instance->cmd[1] = MX25R_BYTE_ADDR1(address_256_align); | ||
108 | instance->cmd[2] = MX25R_BYTE_ADDR2(address_256_align); | ||
109 | instance->cmd[3] = 0; | ||
110 | instance->callback(instance->prv, instance->cmd, NULL, 4, false); | ||
111 | instance->callback(instance->prv, (uint8_t *)buffer, NULL, size_256_max, true); | ||
112 | /* wait until WRI is 0 and WEL is 0 */ | ||
113 | do | ||
114 | { | ||
115 | mx25r_cmd_rdsr(instance, &result); | ||
116 | } while (result.sr0 & 0x3); | ||
117 | return mx25r_err_ok; | ||
118 | } | ||
119 | |||
120 | /* erase sector at 'address' aligned to sector size = 4kB */ | ||
121 | mx25r_err_t mx25r_cmd_sector_erase(struct mx25r_instance *instance, uint32_t address) | ||
122 | { | ||
123 | struct mx25r_rdsr_result result; | ||
124 | /* enable write and wait until WEL is 1 */ | ||
125 | mx25r_cmd_wren(instance); | ||
126 | do | ||
127 | { | ||
128 | mx25r_cmd_rdsr(instance, &result); | ||
129 | } while (!(result.sr0 & 0x2)); | ||
130 | /* write sequence */ | ||
131 | instance->cmd[0] = 0x20; | ||
132 | instance->cmd[1] = MX25R_BYTE_ADDR1(address); | ||
133 | instance->cmd[2] = MX25R_BYTE_ADDR2(address); | ||
134 | instance->cmd[3] = MX25R_BYTE_ADDR3(address); | ||
135 | instance->callback(instance->prv, instance->cmd, NULL, 4, true); | ||
136 | /* wait until WRI is 0 and WEL is 0 */ | ||
137 | do | ||
138 | { | ||
139 | mx25r_cmd_rdsr(instance, &result); | ||
140 | } while (result.sr0 & 0x3); | ||
141 | return mx25r_err_ok; | ||
142 | } | ||