1 /* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
4 * 2019/8/11 - ROBIN KRENS
8 * Driver for AT24C256 EEPROM for STM32 based boards. Communication protocol is I2C
9 * Maximum write in limited to 64 bytes. Reading bytes is unlimited, but memory should
10 * be allocated accordingly.
12 * I2C protocol : (W)rite or (R)ead
13 * MCU is in master mode: either as transmitter or receiver
14 * | P | DEVICEADDR + R/W bit | ACK | ADDR_PART1 | ACK | ADDR_PART2 | (d+a*n) | (N)ACK | S
15 * Sending data: wait for ACK from EEPROM
16 * Receiving data: send (n)ACK to EEPROM after receiving data
18 * STM32F1 microcontrollers do not provide the ability to pull-up SDA and SCL lines. Their
19 * GPIOs must be configured as open-drain. So, you have to add two additional resistors to
20 * pull-up I2C lines. Something between 4K and 10K is a proven value.
29 #include <sys/robsys.h>
31 #include <lib/regfunc.h>
32 #include <lib/string.h>
33 #include <lib/tinyprintf.h>
35 #include <drivers/at24c.h>
39 #define WRITE_CMD 0xA0
40 #define PAGE 64 /* Bytes that can be written continiously */
41 #define BUFFER 64 /* Reading buffer */
44 static char eeprombuf[BUFFER];
46 void eeprom_at24c_init() {
48 /* Program the peripheral input clock generate correct timings.
49 * Configure the clock control registers CCR
50 * Configure the rise time register TRIS
51 * Program the I2C_CR1 register to enable the peripheral
52 * Enable GPIOB6 and B7*/
54 rsetbit(RCC_APB1ENR, 21); // enable GPIOB
55 rsetbit(RCC_APB2ENR, 3); // enable I2C
56 rwrite(GPIOB_CRL, 0xEE444444); // open-drain
57 rsetbitsfrom(I2C_CR2, 0, 0x2); // 2 MHz
58 rwrite(I2C_TRISE, 0x3); // MAX = 1000ns, TPCLK1 = 500ns (+1)
59 rwrite(I2C_CCR, 0x000A); // standard mode
60 rsetbit(I2C_CR2, 10); // buffer interrupt
61 rsetbit(I2C_CR1, 0); // enable
66 /* Writes data to the EEPROM starting at address addr. Size can not
67 * be more than one PAGE (64 bytes) */
68 int eeprom_write(uint16_t addr, char * data, size_t size) {
71 printf("Error: Maximum writable page size: %d\n", PAGE);
75 uint8_t hi_lo[] = { (uint8_t)(addr >> 8), (uint8_t)addr };
78 rwrite(I2C_DR, WRITE_CMD);
83 rwrite(I2C_DR, hi_lo[0]); // higher part of address
87 rwrite(I2C_DR,hi_lo[1]); // lower part of address
92 for (int i = 0; i < size; i++) {
93 rwrite(I2C_DR, *data++);
100 delay(); // wait for write action to finish
104 /* Erase (write all 0xFF) data on EEPROM
105 * Maximum hardware allowed sequential writes of 64 bytes */
108 uint16_t cur_addr = 0x0000;
110 for (int i = 0; i < 512; i++) {
112 printf("Writing at address: %#x (64 bytes) ", cur_addr);
113 uint8_t hi_lo[] = { (uint8_t)(cur_addr >> 8), (uint8_t)cur_addr };
116 rwrite(I2C_DR, WRITE_CMD);
121 rwrite(I2C_DR, hi_lo[0]); // higher part of address
125 rwrite(I2C_DR,hi_lo[1]); // lower part of address
130 for (int i = 0; i < PAGE; i++) {
131 rwrite(I2C_DR, 0xFF); // write all ones
137 printf("[COMPLETE]\n");
138 cur_addr += 0x40; // 64 bytes; next PAGE
139 delay(); // wait for write to finish
145 /* Random access read of num bytes
146 * Initialize dummy write first to set correct address location
147 * The read function differentiate between num = 1 num = 2 and num > 3
148 * Data is saved to rvalues */
149 int eeprom_read(uint16_t addr, int num, char * rvalues) {
151 uint8_t hi_lo[] = { (uint8_t)(addr >> 8), (uint8_t)addr };
153 /* Dummy write to set address */
155 rwrite(I2C_DR, WRITE_CMD);
159 rwrite(I2C_DR, hi_lo[0]); // higher part of address
163 rwrite(I2C_DR,hi_lo[1]); // lower part of address
169 delay(); // wait form EEPROM
173 start_condition(); // restart condition
174 rwrite(I2C_DR, READ_CMD); // read? to address CMD
182 rvalues[0] = (char) *I2C_DR;
187 rsetbit(I2C_CR1, 10); // set ACK
188 rsetbit(I2C_CR1, 11); // set POS
189 start_condition(); // restart condition
190 rwrite(I2C_DR, READ_CMD); // read to address CMD
193 rclrbit(I2C_CR1, 10); // clear ACK
199 rvalues[0] = (char) *I2C_DR;
200 rvalues[1] = (char) *I2C_DR;
205 rsetbit(I2C_CR1, 10); // set ACK
206 start_condition(); // restart condition
207 rwrite(I2C_DR, READ_CMD); // read to address CMD
211 for(int i = 0; i < num-3; i++) {
214 rvalues[i] = (char) *I2C_DR;
220 rclrbit(I2C_CR1, 10);
221 rvalues[num-3] = *I2C_DR;
223 rvalues[num-2] = *I2C_DR;
227 rvalues[num-1] = *I2C_DR;
235 /* Dump all data on EEPROM to std out */
238 uint16_t curr_addr = 0x0000;
240 for (int i = 0; i < 512; i++) {
242 if(eeprom_read(curr_addr, 64, eeprombuf) == -1) {
243 printf("Error: Can't (continue) dump");
246 printf("%#x:\n", curr_addr);
247 for (int i = 0; i < strlen(eeprombuf); i++) {
248 printf("%x ", eeprombuf[i]);
249 if (((i % 16) == 0) && (i != 0))
253 curr_addr += 0x40; // 64 bytes
259 /* HELPER SUBROUTINES */
261 static void start_condition() {
262 rsetbit(I2C_CR1, 8); //start bit
265 static void stop_condition() {
266 rsetbit(I2C_CR1, 9); //stop bit
269 /* Initial ACK received after address lookup
270 * read registers clear ADDR bit */
271 static int ack_recv() {
273 while(!(*I2C_SR1 & 0x2)) {
276 printf("Error: Can't reach device\n");
285 * Note: BLOCKING function */
286 static int buf_empty() {
288 while(!(*I2C_SR1 & 0x80)) {
291 printf("Error: Can't send data\n");
298 /* Check data receive buffer
299 * Note: BLOCKING function */
300 static int data_recv() {
302 while(!(*I2C_SR1 & 0x40)) {
305 printf("Error: Timeout receiving data\n");
312 /* Similar as above, waits for two packages to be received
313 * one in DR and one in the shadow register */
314 static int late_recv() {
316 while(!(*I2C_SR1 & 0x4)) {
319 printf("Error: Timeout receiving data\n");
327 /* Write delay form EEPROM chip */
330 for (int i = 0; i < 0xFFFF; i++)
336 char * gd = "Testing the EEPROM chip AT24C256 write and read function";
337 eeprom_write(0x1000, gd, strlen(gd));
339 uint16_t curr_addr = 0x1000;
341 for (int i = 0; i < 4; i++) {
343 if(eeprom_read(curr_addr, 16, eeprombuf) == -1) {
344 printf("Can't (continue) dump");
347 printf("%#x: ", curr_addr);
348 for (int i = 0; i < strlen(eeprombuf); i++) {
349 printf("%x ", eeprombuf[i]);
352 curr_addr += 0x10; // 16 bytes