mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-01-30 15:52:12 +01:00
I2C: Some more fixes. I2C test passes at 400KBit and 200KBit but needs to be investigated further
git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@280 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
parent
ac93d532b7
commit
dbde2b1bac
@ -30,14 +30,12 @@
|
|||||||
/* Project Includes */
|
/* Project Includes */
|
||||||
#include "pios.h"
|
#include "pios.h"
|
||||||
|
|
||||||
// FIXME: temp assert
|
|
||||||
#define assert(exp) {if (!(exp)) while(1);}
|
|
||||||
|
|
||||||
|
|
||||||
#if !defined(PIOS_DONT_USE_I2C)
|
#if !defined(PIOS_DONT_USE_I2C)
|
||||||
|
|
||||||
/* Options */
|
/* Options */
|
||||||
#define USE_DEBUG_PINS
|
// #define USE_DEBUG_PINS
|
||||||
|
|
||||||
/* Global Variables */
|
/* Global Variables */
|
||||||
volatile uint32_t PIOS_I2C_UnexpectedEvent;
|
volatile uint32_t PIOS_I2C_UnexpectedEvent;
|
||||||
@ -84,6 +82,7 @@ static I2CRecTypeDef I2CRec;
|
|||||||
#ifdef USE_DEBUG_PINS
|
#ifdef USE_DEBUG_PINS
|
||||||
#define DEBUG_PIN_ISR 0
|
#define DEBUG_PIN_ISR 0
|
||||||
#define DEBUG_PIN_BUSY 1
|
#define DEBUG_PIN_BUSY 1
|
||||||
|
#define DEBUG_PIN_ASSERT 7
|
||||||
#define DebugPinHigh(x) PIOS_DEBUG_PinHigh(x)
|
#define DebugPinHigh(x) PIOS_DEBUG_PinHigh(x)
|
||||||
#define DebugPinLow(x) PIOS_DEBUG_PinLow(x)
|
#define DebugPinLow(x) PIOS_DEBUG_PinLow(x)
|
||||||
#else
|
#else
|
||||||
@ -91,6 +90,10 @@ static I2CRecTypeDef I2CRec;
|
|||||||
#define DebugPinLow(x)
|
#define DebugPinLow(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// FIXME: temp assert
|
||||||
|
#define assert(exp) {if (!(exp)) while(1){DebugPinHigh(DEBUG_PIN_ASSERT);DebugPinLow(DEBUG_PIN_ASSERT);};};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes IIC driver
|
* Initializes IIC driver
|
||||||
* \param[in] mode currently only mode 0 supported
|
* \param[in] mode currently only mode 0 supported
|
||||||
@ -128,6 +131,8 @@ int32_t PIOS_I2C_Init(void)
|
|||||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PIOS_I2C_IRQ_ER_PRIORITY;
|
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PIOS_I2C_IRQ_ER_PRIORITY;
|
||||||
NVIC_Init(&NVIC_InitStructure);
|
NVIC_Init(&NVIC_InitStructure);
|
||||||
|
|
||||||
|
DebugPinLow(2);
|
||||||
|
|
||||||
/* No error */
|
/* No error */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -298,6 +303,9 @@ int32_t PIOS_I2C_TransferWait(void)
|
|||||||
uint32_t repeat_ctr = PIOS_I2C_TIMEOUT_VALUE;
|
uint32_t repeat_ctr = PIOS_I2C_TIMEOUT_VALUE;
|
||||||
uint16_t last_buffer_ix = i2cx->buffer_ix;
|
uint16_t last_buffer_ix = i2cx->buffer_ix;
|
||||||
|
|
||||||
|
DebugPinHigh(3);
|
||||||
|
//while(i2cx->transfer_state.BUSY);
|
||||||
|
|
||||||
while(--repeat_ctr > 0) {
|
while(--repeat_ctr > 0) {
|
||||||
/* Check if buffer index has changed - if so, reload repeat counter */
|
/* Check if buffer index has changed - if so, reload repeat counter */
|
||||||
if(i2cx->buffer_ix != last_buffer_ix) {
|
if(i2cx->buffer_ix != last_buffer_ix) {
|
||||||
@ -314,6 +322,7 @@ int32_t PIOS_I2C_TransferWait(void)
|
|||||||
/* Release semaphore for easier programming at user level */
|
/* Release semaphore for easier programming at user level */
|
||||||
i2cx->i2c_semaphore = 0;
|
i2cx->i2c_semaphore = 0;
|
||||||
}
|
}
|
||||||
|
DebugPinLow(3);
|
||||||
return check_state;
|
return check_state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -329,6 +338,8 @@ int32_t PIOS_I2C_TransferWait(void)
|
|||||||
/* Release semaphore (!) */
|
/* Release semaphore (!) */
|
||||||
i2cx->i2c_semaphore = 0;
|
i2cx->i2c_semaphore = 0;
|
||||||
|
|
||||||
|
DebugPinLow(3);
|
||||||
|
|
||||||
return (i2cx->last_transfer_error = I2C_ERROR_TIMEOUT);
|
return (i2cx->last_transfer_error = I2C_ERROR_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,6 +368,7 @@ int32_t PIOS_I2C_Transfer(I2CTransferTypeDef transfer, uint8_t address, uint8_t
|
|||||||
I2CRecTypeDef *i2cx = &I2CRec;
|
I2CRecTypeDef *i2cx = &I2CRec;
|
||||||
int32_t error;
|
int32_t error;
|
||||||
|
|
||||||
|
|
||||||
/* Wait until previous transfer finished */
|
/* Wait until previous transfer finished */
|
||||||
if((error = PIOS_I2C_TransferWait())) {
|
if((error = PIOS_I2C_TransferWait())) {
|
||||||
/* Transmission error during previous transfer */
|
/* Transmission error during previous transfer */
|
||||||
@ -374,6 +386,7 @@ int32_t PIOS_I2C_Transfer(I2CTransferTypeDef transfer, uint8_t address, uint8_t
|
|||||||
i2cx->transfer_state.ALL = 0;
|
i2cx->transfer_state.ALL = 0;
|
||||||
i2cx->transfer_error = 0;
|
i2cx->transfer_error = 0;
|
||||||
|
|
||||||
|
|
||||||
/* Set buffer length and start index */
|
/* Set buffer length and start index */
|
||||||
i2cx->buffer_len = len;
|
i2cx->buffer_len = len;
|
||||||
i2cx->buffer_ix = 0;
|
i2cx->buffer_ix = 0;
|
||||||
@ -404,8 +417,10 @@ int32_t PIOS_I2C_Transfer(I2CTransferTypeDef transfer, uint8_t address, uint8_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start the transfer
|
// Start the transfer
|
||||||
TransferStart(i2cx);
|
|
||||||
I2C_GenerateSTART(i2cx->base, ENABLE);
|
I2C_GenerateSTART(i2cx->base, ENABLE);
|
||||||
|
TransferStart(i2cx);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// All is fine
|
// All is fine
|
||||||
return 0;
|
return 0;
|
||||||
@ -420,6 +435,7 @@ static void EV_IRQHandler(I2CRecTypeDef *i2cx)
|
|||||||
|
|
||||||
DebugPinHigh(DEBUG_PIN_ISR);
|
DebugPinHigh(DEBUG_PIN_ISR);
|
||||||
|
|
||||||
|
|
||||||
/* Read SR1 and SR2 at the beginning (if not done so, flags may get lost) */
|
/* Read SR1 and SR2 at the beginning (if not done so, flags may get lost) */
|
||||||
uint32_t event = I2C_GetLastEvent(i2cx->base);
|
uint32_t event = I2C_GetLastEvent(i2cx->base);
|
||||||
|
|
||||||
@ -440,6 +456,7 @@ static void EV_IRQHandler(I2CRecTypeDef *i2cx)
|
|||||||
i2cx->rx_buffer_ptr[i2cx->buffer_ix++] = b;
|
i2cx->rx_buffer_ptr[i2cx->buffer_ix++] = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Last byte received, disable interrupts and return. */
|
/* Last byte received, disable interrupts and return. */
|
||||||
if(i2cx->transfer_state.STOP_REQUESTED) {
|
if(i2cx->transfer_state.STOP_REQUESTED) {
|
||||||
TransferEnd(i2cx);
|
TransferEnd(i2cx);
|
||||||
@ -491,13 +508,14 @@ static void EV_IRQHandler(I2CRecTypeDef *i2cx)
|
|||||||
|
|
||||||
/* Peripheral is transfering last byte, request stop condition / */
|
/* Peripheral is transfering last byte, request stop condition / */
|
||||||
/* On write-without-stop transfer-type, request start condition instead */
|
/* On write-without-stop transfer-type, request start condition instead */
|
||||||
if(!i2cx->transfer_state.WRITE_WITHOUT_STOP) {
|
|
||||||
DebugPinHigh(2);
|
|
||||||
I2C_GenerateSTOP(i2cx->base, ENABLE);
|
|
||||||
i2cx->transfer_state.STOP_REQUESTED = 1;
|
i2cx->transfer_state.STOP_REQUESTED = 1;
|
||||||
DebugPinLow(2);
|
if(!i2cx->transfer_state.WRITE_WITHOUT_STOP)
|
||||||
} else {
|
{
|
||||||
TransferEnd(i2cx);
|
I2C_GenerateSTOP(i2cx->base, ENABLE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugPinHigh(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i2cx->buffer_len == 0) {
|
if(i2cx->buffer_len == 0) {
|
||||||
@ -511,6 +529,7 @@ static void EV_IRQHandler(I2CRecTypeDef *i2cx)
|
|||||||
goto isr_return;
|
goto isr_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send address
|
||||||
/* SB set, cleared by reading SR1 (done by I2C_GetLastEvent) followed by writing DR register */
|
/* SB set, cleared by reading SR1 (done by I2C_GetLastEvent) followed by writing DR register */
|
||||||
if(event & I2C_FLAG_SB) {
|
if(event & I2C_FLAG_SB) {
|
||||||
/* Don't send address if stop was requested (WRITE_WITHOUT_STOP - mode, start condition was sent) */
|
/* Don't send address if stop was requested (WRITE_WITHOUT_STOP - mode, start condition was sent) */
|
||||||
@ -529,20 +548,30 @@ static void EV_IRQHandler(I2CRecTypeDef *i2cx)
|
|||||||
goto isr_return;
|
goto isr_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This code is only reached if something got wrong, e.g. interrupt handler is called too late, */
|
DebugPinHigh(DEBUG_PIN_ASSERT);DebugPinLow(DEBUG_PIN_ASSERT);
|
||||||
/* The device reset itself (while testing, it was always event 0x00000000). we have to stop the transfer, */
|
|
||||||
/* Else read/write of corrupt data may be the result. */
|
|
||||||
|
|
||||||
/* Notify error */
|
//
|
||||||
PIOS_I2C_UnexpectedEvent = event;
|
// FredericG: Despite the comments below, it seems to me that this situation can happen and can
|
||||||
i2cx->transfer_error = I2C_ERROR_UNEXPECTED_EVENT;
|
// be ignored without ill effects...
|
||||||
|
// For now this condition does not stop the transfer, but further investigation in needed
|
||||||
|
//
|
||||||
|
|
||||||
TransferEnd(i2cx);
|
// assert(0);
|
||||||
|
//
|
||||||
/* Do dummy read to send NAK + STOP condition */
|
// /* This code is only reached if something got wrong, e.g. interrupt handler is called too late, */
|
||||||
I2C_AcknowledgeConfig(i2cx->base, DISABLE);
|
// /* The device reset itself (while testing, it was always event 0x00000000). we have to stop the transfer, */
|
||||||
b = I2C_ReceiveData(i2cx->base);
|
// /* Else read/write of corrupt data may be the result. */
|
||||||
I2C_GenerateSTOP(i2cx->base, ENABLE);
|
//
|
||||||
|
// /* Notify error */
|
||||||
|
// PIOS_I2C_UnexpectedEvent = event;
|
||||||
|
// i2cx->transfer_error = I2C_ERROR_UNEXPECTED_EVENT;
|
||||||
|
//
|
||||||
|
// TransferEnd(i2cx);
|
||||||
|
//
|
||||||
|
// /* Do dummy read to send NAK + STOP condition */
|
||||||
|
// I2C_AcknowledgeConfig(i2cx->base, DISABLE);
|
||||||
|
// b = I2C_ReceiveData(i2cx->base);
|
||||||
|
// I2C_GenerateSTOP(i2cx->base, ENABLE);
|
||||||
|
|
||||||
isr_return:
|
isr_return:
|
||||||
DebugPinLow(DEBUG_PIN_ISR);
|
DebugPinLow(DEBUG_PIN_ISR);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user