1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
#include <clock.h>
#include <gpio.h>
#include <heap.h>
#include <stm32l476xx.h>
#include <string.h>
#define READ 0x03
#define WRITE 0x02
#define WREN 0x06
#define WRDS 0x04
#define SCK GPIO_PORT(D, 2)
#define SI GPIO_PORT(C, 3)
#define SO GPIO_PORT(C, 2)
#define CS GPIO_PORT(B, 7)
void flash_spi_xchg(char *buf, unsigned int count)
{
gpio_dout(CS, 0);
// for each byte
for (unsigned int i = 0; i < count; i++) {
for (int b = 7; b >= 0; b--) {
gpio_dout(SI, buf[i] & (1 << b));
gpio_dout(SCK, 1);
if (gpio_din(SO))
buf[i] |= 1 << b;
else
buf[i] &= ~(1 << b);
gpio_dout(SCK, 0);
}
}
gpio_dout(CS, 1);
}
void flash_init(void)
{
gpio_mode(SCK, OUTPUT);
gpio_mode(SI, OUTPUT);
gpio_mode(CS, OUTPUT);
gpio_mode(SO, OUTPUT);
gpio_dout(SO, 0);
gpio_mode(SO, INPUT);
gpio_dout(CS, 1);
gpio_dout(SCK, 0);
gpio_dout(SI, 0);
}
void flash_read(char *buf, uint32_t addr, unsigned int count)
{
if (buf == 0)
return;
char *spibuf = malloc(count + 4);
spibuf[0] = READ;
spibuf[1] = (addr >> 16) & 0xFF;
spibuf[2] = (addr >> 8) & 0xFF;
spibuf[3] = addr & 0xFF;
memcpy(spibuf + 4, buf, count);
flash_spi_xchg(spibuf, count + 4);
memcpy(buf, spibuf + 4, count);
free(spibuf);
}
void flash_small_write(char *buf, uint32_t addr, unsigned int count)
{
char wren = WREN;
flash_spi_xchg(&wren, 1);
delay(10);
buf[0] = WRITE;
buf[1] = (addr >> 16) & 0xFF;
buf[2] = (addr >> 8) & 0xFF;
buf[3] = addr & 0xFF;
flash_spi_xchg(buf, count);
delay(10);
}
void flash_write(const char *buf, uint32_t addr, unsigned int count)
{
if (buf == 0)
return;
char *spibuf = malloc(260); // 4 header + 256 page size
uint32_t startaddr = addr;
uint16_t counter = 0;
unsigned int offset = 0;
for (uint32_t i = 0; i < count; i++) {
if (i > 0 && ((addr + i) & 0xFF) == 0) {
memcpy(spibuf + 4, buf + offset, counter);
flash_small_write(spibuf, startaddr, 4 + counter);
offset += counter;
startaddr += counter;
counter = 0;
}
counter++;
}
if (offset < count) {
memcpy(spibuf + 4, buf + offset, count - offset);
flash_small_write(spibuf, startaddr, 4 + count - offset);
}
free(spibuf);
}
|