1 #include "projectconfig.h"
4 #include "core/ssp/ssp.h"
7 #include <r0ketports.h>
9 #include <badge/pinconfig.h>
10 #define RB_SPI_CS_DF HOB_PORT(HOB_DATAFLASH_CS), HOB_PIN(HOB_DATAFLASH_CS)
14 #define OP_POWERDOWN (0xB9)
15 #define OP_RESUME (0xAB)
16 #define OP_PAGEREAD (0xD2)
17 #define OP_BUFFER1READ (0xD1) /* Low Frequency (<=33MHz) */
18 #define OP_BUFFER2READ (0xD3) /* Low Frequency (<=33MHz) */
19 #define OP_BUFFER1WRITE (0x84)
20 #define OP_BUFFER2WRITE (0x87)
21 #define OP_BUFFER1PROG (0x83) /* with builtin erase */
22 #define OP_BUFFER2PROG (0x86) /* with builtin erase */
23 #define OP_STATUSREAD (0xD7)
24 #define OP_DEVICEID (0x9F)
25 #define OP_PAGE2BUFFER1 (0x53)
26 #define OP_PAGE2BUFFER2 (0x55)
27 #define OP_BUFFER1PAGECMP (0x60)
28 #define OP_BUFFER2PAGECMP (0x61)
29 #define OP_AUTOREWRITE1 (0x58) /* Auto Page Rewrite throught Buffer 1 */
30 #define OP_AUTOREWRITE2 (0x59) /* Auto Page Rewrite throught Buffer 2 */
32 #define SB_READY (1 << 7)
33 #define SB_COMP (1 << 6)
34 #define SB_PROTECT (1 << 1)
35 #define SB_PAGESIZE (1 << 0)
37 #define MAX_PAGE (2048)
39 #define CS_LOW() gpioSetValue(RB_SPI_CS_DF, 0)
40 #define CS_HIGH() gpioSetValue(RB_SPI_CS_DF, 1)
42 static volatile DSTATUS status
= STA_NOINIT
;
44 static void wait_for_ready() {
45 BYTE reg_status
= 0xFF;
48 xmit_spi(OP_STATUSREAD
);
50 rcvr_spi_m((uint8_t *) ®_status
);
51 } while (!(reg_status
& SB_READY
));
55 static void dataflash_powerdown() {
57 xmit_spi(OP_POWERDOWN
);
61 static void dataflash_resume() {
67 DSTATUS
dataflash_initialize() {
68 sspInit(0, sspClockPolarity_Low
, sspClockPhase_RisingEdge
);
70 gpioSetDir(RB_SPI_CS_DF
, gpioDirection_Output
);
73 status
&= ~STA_NOINIT
;
77 DSTATUS
dataflash_status() {
81 DRESULT
dataflash_random_read(BYTE
*buff
, DWORD offset
, DWORD length
) {
82 if (!length
) return RES_PARERR
;
83 if (status
& STA_NOINIT
) return RES_NOTRDY
;
84 if (offset
+length
> MAX_PAGE
*256) return RES_PARERR
;
88 DWORD pageaddr
= ((offset
/256) << 9) | (offset
%256);
89 DWORD remaining
= 256 - offset
%256;
90 if (remaining
> length
) {
97 xmit_spi(OP_PAGEREAD
);
98 xmit_spi((BYTE
)(pageaddr
>> 16));
99 xmit_spi((BYTE
)(pageaddr
>> 8));
100 xmit_spi((BYTE
)pageaddr
);
101 xmit_spi(0x00); // follow up with 4 don't care bytes
107 } while (--remaining
);
111 return length
? RES_ERROR
: RES_OK
;
114 DRESULT
dataflash_read(BYTE
*buff
, DWORD sector
, BYTE count
) {
115 return dataflash_random_read(buff
, sector
*512, count
*512);
119 DRESULT
dataflash_random_write(const BYTE
*buff
, DWORD offset
, DWORD length
) {
120 if (!length
) return RES_PARERR
;
121 if (status
& STA_NOINIT
) return RES_NOTRDY
;
122 if (offset
+length
> MAX_PAGE
*256) return RES_PARERR
;
126 DWORD pageaddr
= (offset
/256) << 9;
127 DWORD buffaddr
= (offset
%256);
128 DWORD remaining
= 256 - offset
%256;
129 if (remaining
> length
) {
135 // read page into the internal buffer
137 xmit_spi(OP_PAGE2BUFFER1
);
138 xmit_spi((BYTE
)(pageaddr
>> 16));
139 xmit_spi((BYTE
)(pageaddr
>> 8));
140 xmit_spi((BYTE
)pageaddr
);
144 // write bytes into the dataflash buffer
146 xmit_spi(OP_BUFFER1WRITE
);
147 xmit_spi((BYTE
)(buffaddr
>> 16));
148 xmit_spi((BYTE
)(buffaddr
>> 8));
149 xmit_spi((BYTE
)buffaddr
);
152 } while (--remaining
);
156 // compare buffer with target memory page
158 xmit_spi(OP_BUFFER1PAGECMP
);
159 xmit_spi((BYTE
)(pageaddr
>> 16));
160 xmit_spi((BYTE
)(pageaddr
>> 8));
161 xmit_spi((BYTE
)pageaddr
);
165 BYTE reg_status
= 0xFF;
166 xmit_spi(OP_STATUSREAD
);
167 rcvr_spi_m((uint8_t *) ®_status
);
170 // trigger program only if data changed
171 if (reg_status
& SB_COMP
) {
173 xmit_spi(OP_BUFFER1PROG
);
174 xmit_spi((BYTE
)(pageaddr
>> 16));
175 xmit_spi((BYTE
)(pageaddr
>> 8));
176 xmit_spi((BYTE
)pageaddr
);
181 return length
? RES_ERROR
: RES_OK
;
184 DRESULT
dataflash_write(const BYTE
*buff
, DWORD sector
, BYTE count
) {
185 return dataflash_random_write(buff
, sector
*512, count
*512);
187 #endif /* _READONLY */
190 DRESULT
dataflash_ioctl(BYTE ctrl
, void *buff
) {
197 if (ctrl
== CTRL_POWER
) {
199 case 0: /* Sub control code == 0 (POWER_OFF) */
200 dataflash_powerdown();
203 case 1: /* Sub control code == 1 (POWER_ON) */
207 case 2: /* Sub control code == 2 (POWER_GET) */
208 // TODO: figure out a way to retrieve the powerstate
216 if (status
& STA_NOINIT
) return RES_NOTRDY
;
223 case GET_SECTOR_COUNT
:
224 // TODO: read from device ID register
225 *(WORD
*)buff
= MAX_PAGE
/2;
228 case GET_SECTOR_SIZE
:
243 #endif /* _USE_IOCTL != 0 */
245 DWORD
get_fattime () {
248 struct tm* tm=mygmtime(getSeconds());
249 DWORD t= (((tm->tm_year-80)<<9)|
This page took 0.057669 seconds and 5 git commands to generate.