1 #include "projectconfig.h"
4 #include "core/ssp/ssp.h"
6 #include <r0ketports.h>
9 #define OP_POWERDOWN (0xB9)
10 #define OP_RESUME (0xAB)
11 #define OP_PAGEREAD (0xD2)
12 #define OP_BUFFER1READ (0xD1) /* Low Frequency (<=33MHz) */
13 #define OP_BUFFER2READ (0xD3) /* Low Frequency (<=33MHz) */
14 #define OP_BUFFER1WRITE (0x84)
15 #define OP_BUFFER2WRITE (0x87)
16 #define OP_BUFFER1PROG (0x83) /* with builtin erase */
17 #define OP_BUFFER2PROG (0x86) /* with builtin erase */
18 #define OP_STATUSREAD (0xD7)
19 #define OP_DEVICEID (0x9F)
20 #define OP_PAGE2BUFFER1 (0x53)
21 #define OP_PAGE2BUFFER2 (0x55)
22 #define OP_BUFFER1PAGECMP (0x60)
23 #define OP_BUFFER2PAGECMP (0x61)
24 #define OP_AUTOREWRITE1 (0x58) /* Auto Page Rewrite throught Buffer 1 */
25 #define OP_AUTOREWRITE2 (0x59) /* Auto Page Rewrite throught Buffer 2 */
27 #define SB_READY (1 << 7)
28 #define SB_COMP (1 << 6)
29 #define SB_PROTECT (1 << 1)
30 #define SB_PAGESIZE (1 << 0)
32 #define MAX_PAGE (2048)
34 #define CS_LOW() gpioSetValue(RB_SPI_CS_DF, 0)
35 #define CS_HIGH() gpioSetValue(RB_SPI_CS_DF, 1)
37 static volatile DSTATUS status
= STA_NOINIT
;
39 static void wait_for_ready() {
40 BYTE reg_status
= 0xFF;
43 xmit_spi(OP_STATUSREAD
);
45 rcvr_spi_m((uint8_t *) ®_status
);
46 } while (!(reg_status
& SB_READY
));
50 static void dataflash_powerdown() {
52 xmit_spi(OP_POWERDOWN
);
56 static void dataflash_resume() {
62 DSTATUS
dataflash_initialize() {
63 sspInit(0, sspClockPolarity_Low
, sspClockPhase_RisingEdge
);
65 gpioSetDir(RB_SPI_CS_DF
, gpioDirection_Output
);
68 status
&= ~STA_NOINIT
;
72 DSTATUS
dataflash_status() {
76 DRESULT
dataflash_random_read(BYTE
*buff
, DWORD offset
, DWORD length
) {
77 if (!length
) return RES_PARERR
;
78 if (status
& STA_NOINIT
) return RES_NOTRDY
;
79 if (offset
+length
> MAX_PAGE
*256) return RES_PARERR
;
83 DWORD pageaddr
= ((offset
/256) << 9) | (offset
%256);
84 DWORD remaining
= 256 - offset
%256;
85 if (remaining
> length
) {
92 xmit_spi(OP_PAGEREAD
);
93 xmit_spi((BYTE
)(pageaddr
>> 16));
94 xmit_spi((BYTE
)(pageaddr
>> 8));
95 xmit_spi((BYTE
)pageaddr
);
96 xmit_spi(0x00); // follow up with 4 don't care bytes
102 } while (--remaining
);
106 return length
? RES_ERROR
: RES_OK
;
109 DRESULT
dataflash_read(BYTE
*buff
, DWORD sector
, BYTE count
) {
110 return dataflash_random_read(buff
, sector
*512, count
*512);
114 DRESULT
dataflash_random_write(const BYTE
*buff
, DWORD offset
, DWORD length
) {
115 if (!length
) return RES_PARERR
;
116 if (status
& STA_NOINIT
) return RES_NOTRDY
;
117 if (offset
+length
> MAX_PAGE
*256) return RES_PARERR
;
121 DWORD pageaddr
= (offset
/256) << 9;
122 DWORD buffaddr
= (offset
%256);
123 DWORD remaining
= 256 - offset
%256;
124 if (remaining
> length
) {
130 // read page into the internal buffer
132 xmit_spi(OP_PAGE2BUFFER1
);
133 xmit_spi((BYTE
)(pageaddr
>> 16));
134 xmit_spi((BYTE
)(pageaddr
>> 8));
135 xmit_spi((BYTE
)pageaddr
);
139 // write bytes into the dataflash buffer
141 xmit_spi(OP_BUFFER1WRITE
);
142 xmit_spi((BYTE
)(buffaddr
>> 16));
143 xmit_spi((BYTE
)(buffaddr
>> 8));
144 xmit_spi((BYTE
)buffaddr
);
147 } while (--remaining
);
151 // compare buffer with target memory page
153 xmit_spi(OP_BUFFER1PAGECMP
);
154 xmit_spi((BYTE
)(pageaddr
>> 16));
155 xmit_spi((BYTE
)(pageaddr
>> 8));
156 xmit_spi((BYTE
)pageaddr
);
160 BYTE reg_status
= 0xFF;
161 xmit_spi(OP_STATUSREAD
);
162 rcvr_spi_m((uint8_t *) ®_status
);
165 // trigger program only if data changed
166 if (reg_status
& SB_COMP
) {
168 xmit_spi(OP_BUFFER1PROG
);
169 xmit_spi((BYTE
)(pageaddr
>> 16));
170 xmit_spi((BYTE
)(pageaddr
>> 8));
171 xmit_spi((BYTE
)pageaddr
);
176 return length
? RES_ERROR
: RES_OK
;
179 DRESULT
dataflash_write(const BYTE
*buff
, DWORD sector
, BYTE count
) {
180 return dataflash_random_write(buff
, sector
*512, count
*512);
182 #endif /* _READONLY */
185 DRESULT
dataflash_ioctl(BYTE ctrl
, void *buff
) {
192 if (ctrl
== CTRL_POWER
) {
194 case 0: /* Sub control code == 0 (POWER_OFF) */
195 dataflash_powerdown();
198 case 1: /* Sub control code == 1 (POWER_ON) */
202 case 2: /* Sub control code == 2 (POWER_GET) */
203 // TODO: figure out a way to retrieve the powerstate
211 if (status
& STA_NOINIT
) return RES_NOTRDY
;
218 case GET_SECTOR_COUNT
:
219 // TODO: read from device ID register
220 *(WORD
*)buff
= MAX_PAGE
/2;
223 case GET_SECTOR_SIZE
:
238 #endif /* _USE_IOCTL != 0 */
240 DWORD
get_fattime () {
243 struct tm* tm=mygmtime(getSeconds());
244 DWORD t= (((tm->tm_year-80)<<9)|
This page took 0.059956 seconds and 5 git commands to generate.