WIP: bit-banging I2C support for EEPROM access on QMOD

for now, it just continuously reads the EEPROM bytes and dumps them to
the serial console for testing.
This commit is contained in:
Harald Welte
2016-08-21 19:33:24 +02:00
parent a02b641650
commit 226b40aba4
4 changed files with 225 additions and 1 deletions

View File

@@ -147,7 +147,7 @@ C_CMSIS = core_cm3.o
C_LOWLEVEL = board_cstartup_gnu.o board_lowlevel.o syscalls.o exceptions.o
C_LIBLEVEL = spi.o pio.o pmc.o usart.o pio_it.o pio_capture.o uart_console.o iso7816_4.o wdt.o led.o tc.o unique_id.o
C_CCID = cciddriver.o USBD.o USBDDriver.o USBD_HAL.o USBRequests.o USBDCallbacks.o USBDescriptors.o USBDDriverCallbacks.o
C_SIMTRACE = simtrace_iso7816.o usb.o ccid.o sniffer.o mitm.o ringbuffer.o host_communication.o iso7816_fidi.o tc_etu.o req_ctx.o card_emu.o mode_cardemu.o
C_SIMTRACE = simtrace_iso7816.o usb.o ccid.o sniffer.o mitm.o ringbuffer.o host_communication.o iso7816_fidi.o tc_etu.o req_ctx.o card_emu.o mode_cardemu.o i2c.o
C_APPLEVEL = main.o
C_OBJECTS = $(C_CMSIS) $(C_LOWLEVEL) $(C_LIBLEVEL) $(C_APPLEVEL) $(C_CCID) $(C_SIMTRACE)

206
firmware/src_simtrace/i2c.c Normal file
View File

@@ -0,0 +1,206 @@
#include "board.h"
#include <stdbool.h>
/* Low-Level I2C Routines */
static const Pin pin_sda = {PIO_PA30, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_OPENDRAIN };
static const Pin pin_sda_in = {PIO_PA30, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT };
static const Pin pin_scl = {PIO_PA31, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_OPENDRAIN };
void i2c_pin_init(void)
{
PIO_Configure(&pin_scl, PIO_LISTSIZE(pin_scl));
PIO_Configure(&pin_sda, PIO_LISTSIZE(pin_sda));
}
static void set_scl(void)
{
PIO_Set(&pin_scl);
}
static void set_sda(void)
{
PIO_Set(&pin_sda);
}
static void clear_scl(void)
{
PIO_Clear(&pin_scl);
}
static void clear_sda(void)
{
PIO_Clear(&pin_sda);
}
static bool read_sda(void)
{
bool ret;
PIO_Configure(&pin_sda_in, PIO_LISTSIZE(pin_sda_in));
if (PIO_Get(&pin_sda))
ret = true;
else
ret = false;
PIO_Configure(&pin_sda, PIO_LISTSIZE(pin_sda));
return ret;
}
/* Core I2C Routines */
static bool i2c_started = false;
static void i2c_delay()
{
volatile int v;
int i;
for (i = 0; i < 100; i++) {
v = 0;
}
}
static void i2c_start_cond(void)
{
if (i2c_started) {
set_sda();
i2c_delay();
set_scl();
i2c_delay();
}
i2c_delay();
clear_sda();
i2c_delay();
clear_scl();
i2c_started = true;
}
static void i2c_stop_cond(void)
{
clear_sda();
i2c_delay();
set_scl();
i2c_delay();
set_sda();
i2c_delay();
i2c_started = false;
}
static void i2c_write_bit(bool bit)
{
if (bit)
set_sda();
else
clear_sda();
i2c_delay();
set_scl();
i2c_delay();
clear_scl();
i2c_delay();
}
static bool i2c_read_bit(void)
{
bool bit;
set_sda();
i2c_delay();
set_scl();
i2c_delay();
bit = read_sda();
clear_scl();
return bit;
}
bool i2c_write_byte(bool send_start, bool send_stop, uint8_t byte)
{
uint8_t bit;
bool nack;
if (send_start)
i2c_start_cond();
for (bit = 0; bit < 8; bit++) {
i2c_write_bit((byte & 0x80) != 0);
byte <<= 1;
}
nack = i2c_read_bit();
if (send_stop)
i2c_stop_cond();
return nack;
}
uint8_t i2c_read_byte(bool nack, bool send_stop)
{
uint8_t byte = 0;
uint8_t bit;
for (bit = 0; bit < 8; bit++) {
byte = (byte << 1) | i2c_read_bit();
}
i2c_write_bit(nack);
if (send_stop)
i2c_stop_cond();
return byte;
}
/* EEPROM related code */
int eeprom_write_byte(uint8_t slave, uint8_t addr, uint8_t byte)
{
bool nack;
/* Write slave address */
nack = i2c_write_byte(true, false, slave << 1);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, false, addr);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, true, byte);
if (nack)
goto out_stop;
out_stop:
i2c_stop_cond();
if (nack)
return -1;
else
return 0;
}
int eeprom_read_byte(uint8_t slave, uint8_t addr)
{
bool nack;
/* dummy write cycle */
nack = i2c_write_byte(true, false, slave << 1);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, false, addr);
if (nack)
goto out_stop;
/* Re-start with read */
nack = i2c_write_byte(true, false, (slave << 1) | 1);
if (nack)
goto out_stop;
return i2c_read_byte(true, true);
out_stop:
i2c_stop_cond();
if (nack)
return -1;
else
return 0;
}

View File

@@ -0,0 +1,5 @@
#pragma once
void i2c_pin_init(void);
int eeprom_write_byte(uint8_t slave, uint8_t addr, uint8_t byte);
int eeprom_read_byte(uint8_t slave, uint8_t addr);

View File

@@ -97,6 +97,7 @@ void USART0_IrqHandler(void)
config_func_ptrs[simtrace_config].usart0_irq();
}
#include "i2c.h"
/*------------------------------------------------------------------------------
* Main
*------------------------------------------------------------------------------*/
@@ -131,6 +132,18 @@ extern int main(void)
g_unique_id[0], g_unique_id[1],
g_unique_id[2], g_unique_id[3]);
#if 1
static const Pin pin_hub_rst = {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT};
PIO_Configure(&pin_hub_rst, 1);
i2c_pin_init();
while (1) {
for (i = 0; i < 256; i ++) {
int byte = eeprom_read_byte(0x50, i);
TRACE_INFO("0x%02x: %02x\r\n", i, byte);
}
}
#endif
TRACE_INFO("USB init...\r\n");
while (USBD_GetState() < USBD_STATE_CONFIGURED) {
if (i >= MAX_USB_ITER * 3) {