LingYun Studio embeded system framwork software, such as thirdparty build shell and lingyun library
guowenxue
2024-09-25 e8d34d11799fc79c7c53bdcd40f9b4ee7be7a2c5
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*********************************************************************************
 *      Copyright:  (C) 2023 LingYun IoT System Studio
 *                  All rights reserved.
 *
 *       Filename:  at24c.c
 *    Description:  This file is AT24Cxx EEPROM code
 *
 *        Version:  1.0.0(10/08/23)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "10/08/23 17:52:00"
 *
 * Pin connection:
 *                 W25QXX       Raspberry Pi 40Pin
 *                   VCC   <--->   Pin#1 (3.3V)
 *                   CS    <--->   Pin#24(CS)
 *                   DO    <--->   Pin#21(MISO)
 *                   GND   <--->   Pin#9 (GND)
 *                   CLK   <--->   Pin#23(SCLK)
 *                   DI    <--->   Pin#19(MOSI)
 *
 * /boot/config.txt:
 *                  dtparam=spi=on
 *
 ********************************************************************************/
 
#ifndef _W25QFLASH_H
#define _W25QFLASH_H
 
#include <stdbool.h>
 
#define _W25QXX_DEBUG           1
 
/* W25Q SPI Norflash page/sector/block size */
#define W25Q_PAGSIZE            256     /* 1Page=256B */
#define W25Q_SECSIZE            4096    /* 1Sector=16Pages=4KB */
#define W25Q_BLKSIZE            65536   /* 1Block=16Sector=64KB */
 
/* Flash opcodes. Refer to <<W25Q256JV.pdf>> P26 Table 8.1.2 Instruction Set Table */
#define SPINOR_OP_RDID          0x9f    /* Read JEDEC ID */
#define SPINOR_OP_RDUID         0x4b    /* Read unique ID */
#define SPINOR_OP_WRSR1         0x01    /* Write status register-1 */
#define SPINOR_OP_WRSR2         0x31    /* Write status register-2 */
#define SPINOR_OP_WRSR3         0x11    /* Write status register-3 */
#define SPINOR_OP_BP            0x02    /* Byte program */
#define SPINOR_OP_READ          0x03    /* Read data bytes (low frequency) */
#define SPINOR_OP_WRDI          0x04    /* Write disable */
#define SPINOR_OP_RDSR1         0x05    /* Read status register-1 */
#define SPINOR_OP_RDSR2         0x35    /* Read status register-2 */
#define SPINOR_OP_RDSR3         0x15    /* Read status register-3 */
#define SPINOR_OP_WREN          0x06    /* Write enable */
#define SPINOR_OP_READ_FAST     0x0b    /* Read data bytes (high frequency) */
#define SPINOR_OP_READ_FAST_4B  0x0c    /* Read data bytes (high frequency) */
 
#define SPINOR_OP_CHIP_ERASE    0xc7    /* Erase whole flash chip */
#define SPINOR_OP_BE_4K_4B      0xdc    /* Block erase (64KiB) with 4-Byte Address */
#define SPINOR_OP_BE_4K         0xd8    /* Block erase (64KiB) */
#define SPINOR_OP_SE_4B         0x21    /* Sector erase (4KiB) with 4-Byte Address */
#define SPINOR_OP_SE            0x20    /* Sector erase (4KiB)  */
#define SPINOR_OP_PP_4B         0x12    /* Page Program (up to 256 bytes) with 4-Byte Address */
#define SPINOR_OP_PP            0x02    /* Page program (up to 256 bytes) */
#define SPINOR_OP_SRSTEN        0x66    /* Software Reset Enable */
#define SPINOR_OP_SRST          0x99    /* Software Reset */
 
/* All the above command default work as 4 bytes mode */
#define OVERHEAD_SIZE            6
 
typedef struct spi_bus
{
    int  hspi; /* SPI bus handler */
    int  cs;   /* SPI cs pin number */
 
    void (*select)(struct spi_bus *spi);   /* CS enable function  */
    void (*deselect)(struct spi_bus *spi); /* CS disable function */
    void (*xcmd)(struct spi_bus *spi, uint8_t command); /* Send a byte command */
    void (*xfer)(struct spi_bus *spi, uint8_t *send_buf, uint8_t *recv_buf, int bytes); /* Transmit and Receive N byte */
} spi_bus_t;
 
typedef struct flash_s 
{
    char            *name;          /* Chip name */
    uint32_t         jedec_id;      /* JEDEC ID, 3 bytes */
    uint64_t         capacity;      /* Chip   size in bytes */
    uint32_t         block_size;    /* Block  size in bytes */
    uint32_t         sector_size;   /* Sector size in bytes */
    uint32_t         page_size;     /* Page   size in bytes */
    uint32_t         n_blocks;      /* Number of blocks */
    uint32_t         n_sectors;     /* Number of sectors */
    uint32_t         n_pages;       /* Number of pages */
} flash_t;
 
 
typedef struct spinor_s
{
    spi_bus_t       *spi;
    flash_t         *flash;
    uint8_t          lock;
} spinor_t;
 
 
/*+-------------------------------+
 *|   SPI Norflash HighLevel API  |
 *+-------------------------------+*/
 
/* SPI Norflash API test function */
extern void spinor_test(void);
 
/* Initial SPI and detect the flash chip */
extern int spinor_init(spinor_t *spinor);
 
/* Description:  Erase whole flash chip.
 * Reference  :  P60, 8.2.32 Chip Erase (C7h / 60h)
 */
extern int spinor_erase_chip(spinor_t *spinor);
 
/* Description:  Erase blocks by 64KiB,
 * Reference  :  P59, 8.2.31 64KB Block Erase with 4-Byte Address (DCh)
 *  @address is the erase start physical address, which can be not block alignment such as 0x10001.
 *  @size is the erase size, which can be larger than a block such as 4097, and it will erase 2 blocks;
 */
extern int spinor_erase_block(spinor_t *spinor, uint32_t address, uint32_t size);
 
/* Description:  Erase sectors by 4KiB
 * Reference  :  P56, 8.2.28 Sector Erase with 4-Byte Address (21h)
 *  @address is the erase start physical address, which can be not sector alignment such as 0x1001.
 *  @size is the erase size, which can be larger than a sector such as 4097, and it will erase 2 sectors;
 */
extern int spinor_erase_sector(spinor_t *spinor, uint32_t address, uint32_t size);
 
/* Description:  Page random write by 256B
 *  @addr is the write start physical address, which can be not page alignment such as 0x101.
 *  @size is the write size, which can be larger than a page such as 257, and it will write 2 pages;
 */
extern int spinor_write(spinor_t *spinor, uint32_t address, uint8_t *data, uint32_t bytes);
 
/* Description:  The Fast Read instruction can read the entire memory chip.
 * Reference  :  P41, 8.2.13 Fast Read with 4-Byte Address (0Ch)
 *  @address is the read start physical address, which can be not page alignment such as 0x101.
 *  @size is the read size, which can be larger than a page such as 257, and it will read 2 pages;
 */
extern int spinor_read(spinor_t *spinor, uint32_t address, uint8_t *buf, uint32_t bytes);
 
/*+-------------------------------+
 *|   SPI Norflash LowLevel API   |
 *+-------------------------------+*/
 
/* Description:  Read the chipset UNIQUE ID.
 * Reference  :  P68, 8.2.40 Read Unique ID Number (4Bh)
 */
int spinor_read_uniqid(spi_bus_t *spi, uint8_t *uniq_id);
 
/* Description:  Read the chipset JEDEC ID.
 * Reference  :  P69, 8.2.41 Read JEDEC ID (9Fh)
 */
uint32_t spinor_read_jedecid(spi_bus_t *spi);
 
/* Description:  Write Enable
 * Reference  :  P31, 8.2.1 Write Enable (06h)
 */
void spinor_write_enable(spi_bus_t *spi);
 
/* Description:  Write Disable
 * Reference  :  P32, 8.2.3 Write Disable (04h)
 */
void spinor_write_disable(spi_bus_t *spi);
 
/* Description:  Read Status Register
 * Reference  :  P32, 8.2.4 Read Status Register-1 (05h), Status Register-2 (35h) & Status Register-3 (15h)
 */
uint8_t spinor_read_status_reg(spi_bus_t *spi, uint8_t reg);
 
/* Description:  Write Status Register
 * Reference  :  P33, 8.2.5 Write Status Register-1 (01h), Status Register-2 (31h) & Status Register-3 (11h)
 */
void spinor_write_status_reg(spi_bus_t *spi, uint8_t reg, uint8_t value);
 
/* Description:  Wait flash program/erase finished by read Status Register for BUSY bit
 * Reference  :  P15, 7.1 Status Registers
 */
void spinor_WaitForReady(spi_bus_t *spi);
 
#endif