rfdsatt: add low-level EEPROM read/write support

This commit is contained in:
Harald Welte 2021-05-07 19:03:20 +02:00
parent 3b39d671fe
commit e63259baaa
4 changed files with 164 additions and 1 deletions

View File

@ -19,7 +19,7 @@
BINARY = rfdsatt
OBJS = attenuator.o board_rfdsatt_4ch.o
OBJS = attenuator.o eeprom.o board_rfdsatt_4ch.o
# when building for M0
#LDSCRIPT = ./stm32f051-openblt.ld

125
projects/rfdsatt/eeprom.c Normal file
View File

@ -0,0 +1,125 @@
#include <libopencm3/stm32/i2c.h>
#include <errno.h>
#include "eeprom.h"
/* wait for I2C status register flags to appear */
static bool i2c_wait(uint32_t i2c, uint32_t sr1, uint32_t sr2)
{
unsigned int i;
for (i = 0; i < 1000000; i++) {
if (((I2C_SR1(i2c) & sr1) == sr1) &&
((I2C_SR2(i2c) & sr2) == sr2))
return true;
}
return false;
}
int eeprom_read(uint8_t *buf_out, unsigned int num_bytes, uint16_t read_addr)
{
unsigned int i;
if (num_bytes > 255)
return -EINVAL; /* no reload cycles yet */
i2c_send_start(I2C1);
/* Wait for the end of the start condition, master mode selected, and BUSY bit set */
if (!i2c_wait(I2C1, I2C_SR1_SB, I2C_SR2_MSL|I2C_SR2_BUSY))
return -EIO;
/* Send Address, wait until it is transferred */
i2c_send_7bit_address(I2C1, 0x50, I2C_WRITE);
if (!i2c_wait(I2C1, I2C_SR1_ADDR, 0))
return -EIO;
/* Send memory address */
#if 0 /* 16bit address */
i2c_send_data(I2C1, read_addr >> 8);
if (!i2c_wait(I2C1, I2C_SR1_BTF, 0))
return -EIO;
#endif
i2c_send_data(I2C1, read_addr & 0xff);
if (!i2c_wait(I2C1, I2C_SR1_BTF, 0))
return -EIO;
/* re-start */
i2c_send_start(I2C1);
i2c_enable_ack(I2C1);
/* Wait for the end of the start condition, master mode selected, and BUSY bit set */
if (!i2c_wait(I2C1, I2C_SR1_SB, I2C_SR2_MSL|I2C_SR2_BUSY))
return -EIO;
/* Send Address, wait until it is transferred */
i2c_send_7bit_address(I2C1, 0x50, I2C_READ);
if (!i2c_wait(I2C1, I2C_SR1_ADDR, 0))
return -EIO;
for (i = 0; i < num_bytes; i++) {
if (i == num_bytes - 1)
i2c_disable_ack(I2C1);
if (!i2c_wait(I2C1, I2C_SR1_RxNE, 0))
return -EIO;
buf_out[i] = i2c_get_data(I2C1);
}
i2c_send_stop(I2C1);
return i;
}
static int wait_write_complete(void)
{
unsigned int i;
for (i = 0; i < 100; i++) {
i2c_send_start(I2C1);
/* Wait for the end of the start condition, master mode selected, and BUSY bit set */
if (!i2c_wait(I2C1, I2C_SR1_SB, I2C_SR2_MSL|I2C_SR2_BUSY))
return -EIO;
/* Send Address, wait until it is transferred */
i2c_send_7bit_address(I2C1, 0x50, I2C_WRITE);
if (i2c_wait(I2C1, I2C_SR1_ADDR, 0)) {
/* slave has sent an ACK, we may proceed */
return 0;
}
i2c_send_stop(I2C1);
}
}
int eeprom_write_byte(uint16_t write_addr, uint8_t byte)
{
i2c_send_start(I2C1);
/* Wait for the end of the start condition, master mode selected, and BUSY bit set */
if (!i2c_wait(I2C1, I2C_SR1_SB, I2C_SR2_MSL|I2C_SR2_BUSY))
return -EIO;
/* Send Address, wait until it is transferred */
i2c_send_7bit_address(I2C1, 0x50, I2C_WRITE);
if (!i2c_wait(I2C1, I2C_SR1_ADDR, 0))
return -EIO;
/* Send memory address */
#if 0 /* 16bit address */
i2c_send_data(I2C1, write_addr >> 8);
if (!i2c_wait(I2C1, I2C_SR1_BTF, 0))
return -EIO;
#endif
i2c_send_data(I2C1, write_addr & 0xff);
if (!i2c_wait(I2C1, I2C_SR1_BTF, 0))
return -EIO;
/* Send data to write */
i2c_send_data(I2C1, byte);
if (!i2c_wait(I2C1, I2C_SR1_BTF, 0))
return -EIO;
i2c_send_stop(I2C1);
wait_write_complete();
return 1;
}

View File

@ -0,0 +1,5 @@
#pragma once
#include <stdint.h>
int eeprom_read(uint8_t *buf_out, unsigned int num_bytes, uint16_t read_addr);
int eeprom_write_byte(uint16_t write_addr, uint8_t byte);

View File

@ -38,6 +38,7 @@
#include <stdlib.h>
#include "attenuator.h"
#include "eeprom.h"
#include "misc.h"
static uint32_t last_reset_cause;
@ -337,6 +338,36 @@ DEFUN(test, test_cmd, "test", "Enter interactive test-ramp mode")
}
DEFUN(i2c_read, i2c_read_cmd, "i2c-read", "Read from I2C EEPROM")
{
uint16_t mem_addr = 0;
uint8_t rbuf[16];
unsigned int i;
i = eeprom_read(rbuf, sizeof(rbuf), mem_addr);
printf("Read result: %d\r\n", i);
for (i = 0; i < sizeof(rbuf); i++)
printf("%02x ", rbuf[i]);
printf("\r\n");
}
DEFUN(i2c_write, i2c_write_cmd, "i2c-write", "write to I2C EEPROM")
{
int rc, addr, val;
if (argc < 3) {
printf("you have to specify address + value\r\n");
return;
}
addr = atoi(argv[1]);
val = atoi(argv[2]);
printf("Writing 0x%02x to address 0x%02x\r\n", val, addr);
rc = eeprom_write_byte(addr, val);
printf("Write result: %d\r\n", rc);
}
/***********************************************************************
* main
***********************************************************************/
@ -403,6 +434,8 @@ int main(void)
microvty_register(&att_set_cmd);
microvty_register(&interact_cmd);
microvty_register(&test_cmd);
microvty_register(&i2c_read_cmd);
microvty_register(&i2c_write_cmd);
print_banner();
microvty_print_prompt();