Skip to content

Commit

Permalink
chg: i2c comms, first try to recover i2c hangs.
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris committed Nov 14, 2018
1 parent 9bff2ab commit e4cb74f
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 6 deletions.
48 changes: 42 additions & 6 deletions common/i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
//-----------------------------------------------------------------------------
#include "i2c.h"

// 定义连接引脚
#define GPIO_RST AT91C_PIO_PA1
#define GPIO_SCL AT91C_PIO_PA5
#define GPIO_SDA AT91C_PIO_PA7
Expand Down Expand Up @@ -41,20 +40,54 @@ void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {

#define ISO7618_MAX_FRAME 255

// try i2c bus recovery at 100kHz = 5uS high, 5uS low
void I2C_recovery(void) {

DbpString("Performing i2c bus recovery");

// reset I2C
SDA_H; SCL_H;

//9nth cycle acts as NACK
for (int i = 0; i < 10; i++) {
SCL_H; WaitUS(5);
SCL_L; WaitUS(5);
}

//a STOP signal (SDA from low to high while CLK is high)
SDA_L; WaitUS(5);
SCL_H; WaitUS(2);
SDA_H; WaitUS(2);

bool isok = (SCL_read && SDA_read);
if (!SDA_read)
DbpString("I2C bus recovery error: SDA still LOW");
if (!SCL_read)
DbpString("I2C bus recovery error: SCL still LOW");
if (isok)
DbpString("I2C bus recovery complete");
}

void I2C_init(void) {
// Configure reset pin, close up pull up, push-pull output, default high
AT91C_BASE_PIOA->PIO_PPUDR = GPIO_RST;
AT91C_BASE_PIOA->PIO_MDDR = GPIO_RST;

// Configure I2C pin, open up, open leakage
AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_SCL | GPIO_SDA); // 打开上拉 Open up the pull up
AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_SCL | GPIO_SDA);
AT91C_BASE_PIOA->PIO_MDER |= (GPIO_SCL | GPIO_SDA);

// default three lines all pull up
AT91C_BASE_PIOA->PIO_SODR |= (GPIO_SCL | GPIO_SDA | GPIO_RST);

AT91C_BASE_PIOA->PIO_OER |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
AT91C_BASE_PIOA->PIO_PER |= (GPIO_SCL | GPIO_SDA | GPIO_RST);


bool isok = (SCL_read && SDA_read);
if ( !isok )
I2C_recovery();

}

// set the reset state
Expand All @@ -78,6 +111,8 @@ void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) {
// Reset the SIM_Adapter, then enter the main program
// Note: the SIM_Adapter will not enter the main program after power up. Please run this function before use SIM_Adapter.
void I2C_Reset_EnterMainProgram(void) {
I2C_init();

I2C_SetResetStatus(0, 0, 0);
SpinDelay(30);
I2C_SetResetStatus(1, 0, 0);
Expand Down Expand Up @@ -157,7 +192,7 @@ bool I2C_Start(void) {
}

bool I2C_WaitForSim() {
// variable delay here.

if (!WaitSCL_L_300ms())
return false;

Expand Down Expand Up @@ -631,6 +666,7 @@ void SmartCardAtr(void) {
LED_D_ON();
clear_trace();
set_tracing(true);
I2C_init();
I2C_Reset_EnterMainProgram();
bool isOK = GetATR( &card );
cmd_send(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
Expand All @@ -650,12 +686,12 @@ void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) {
clear_trace();

set_tracing(true);

if ((flags & SC_CONNECT)) {

if ((flags & SC_CONNECT)) {

I2C_Reset_EnterMainProgram();

if ( !(flags & SC_NO_SELECT) ) {
if ((flags & SC_SELECT)) {
smart_card_atr_t card;
bool gotATR = GetATR( &card );
//cmd_send(CMD_ACK, gotATR, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
Expand Down
1 change: 1 addition & 0 deletions common/i2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define I2C_DEVICE_CMD_GETVERSION 0x06


void I2C_recovery(void);
void I2C_init(void);
void I2C_Reset(void);
void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA);
Expand Down

0 comments on commit e4cb74f

Please sign in to comment.