I2C. Merge code to trunk.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3576 35acf78f-673a-0410-8e92-d51de3d6d3f4
master
barthess 2011-12-08 07:11:08 +00:00
commit 87ea7c6eec
27 changed files with 2366 additions and 1274 deletions

View File

@ -87,67 +87,15 @@ typedef enum {
I2C_READY = 2, /**< Ready. */ I2C_READY = 2, /**< Ready. */
I2C_ACTIVE_TRANSMIT = 3, /**< Transmitting. */ I2C_ACTIVE_TRANSMIT = 3, /**< Transmitting. */
I2C_ACTIVE_RECEIVE = 4, /**< Receiving. */ I2C_ACTIVE_RECEIVE = 4, /**< Receiving. */
I2C_ACTIVE_TRANSCEIVE = 5, /**< Receiving after transmit. */
} i2cstate_t; } i2cstate_t;
#include "i2c_lld.h" #include "i2c_lld.h"
/**
* @brief I2C notification callback type.
* @details This callback invoked when byte transfer finish event occurs,
* no matter if sending or reading.
*
* @param[in] i2cp pointer to the @p I2CDriver object triggering the
* callback
* @param[in] i2cscfg pointer to the @p I2CSlaveConfig object triggering the
* callback
*/
typedef void (*i2ccallback_t)(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg);
/**
* @brief I2C error notification callback type.
*
* @param[in] i2cp pointer to the @p I2CDriver object triggering the
* callback
* @param[in] i2cscfg pointer to the @p I2CSlaveConfig object triggering the
* callback
*/
typedef void (*i2cerrorcallback_t)(I2CDriver *i2cp,
const I2CSlaveConfig *i2cscfg);
/**
* @brief I2C transmission data block size.
*/
typedef uint8_t i2cblock_t;
/**
* @brief Structure representing an I2C slave configuration.
* @details Each slave device has its own config structure with input and
* output buffers for temporally storing data.
*/
struct I2CSlaveConfig{
/**
* @brief Callback pointer.
* @note Transfer finished callback. Invoke when all data transferred.
* If set to @p NULL then the callback is disabled.
*/
i2ccallback_t id_callback;
/**
* @brief Callback pointer.
* @note This callback will be invoked when error condition occur.
* If set to @p NULL then the callback is disabled.
*/
i2cerrorcallback_t id_err_callback;
#if defined(I2C_SLAVECONFIG_EXT_FIELDS)
I2C_SLAVECONFIG_EXT_FIELDS
#endif
};
/*===========================================================================*/ /*===========================================================================*/
/* Driver macros. */ /* Driver macros. */
/*===========================================================================*/ /*===========================================================================*/
#if I2C_USE_WAIT || defined(__DOXYGEN__)
/** /**
* @brief Waits for operation completion. * @brief Waits for operation completion.
* @details This function waits for the driver to complete the current * @details This function waits for the driver to complete the current
@ -185,58 +133,40 @@ struct I2CSlaveConfig{
chSysUnlockFromIsr(); \ chSysUnlockFromIsr(); \
} \ } \
} }
#else /* !I2C_USE_WAIT */
#define _i2c_wait_s(i2cp)
#define _i2c_wakeup_isr(i2cp)
#endif /* !I2C_USE_WAIT */
/** /**
* @brief Common ISR code. * @brief Common ISR code.
* @details This code handles the portable part of the ISR code: * @details This code handles the portable part of the ISR code:
* - Callback invocation. * - Waiting thread wakeup.
* - Waiting thread wakeup, if any.
* - Driver state transitions. * - Driver state transitions.
* *
* @note This macro is meant to be used in the low level drivers * @note This macro is meant to be used in the low level drivers
* implementation only. * implementation only.
* *
* @param[in] i2cp pointer to the @p I2CDriver object * @param[in] i2cp pointer to the @p I2CDriver object
* @param[in] i2cscfg pointer to the @p I2CSlaveConfig object
* *
* @notapi * @notapi
*/ */
#define _i2c_isr_code(i2cp, i2cscfg) { \ #define _i2c_isr_code(i2cp, i2cscfg) { \
if(((i2cp)->id_slave_config)->id_callback) { \ (i2cp)->id_state = I2C_READY; \
((i2cp)->id_slave_config)->id_callback(i2cp, i2cscfg); \
(i2cp)->id_state = I2C_READY; \
} \
else \
(i2cp)->id_state = I2C_READY; \
_i2c_wakeup_isr(i2cp); \ _i2c_wakeup_isr(i2cp); \
} }
/** /**
* @brief Error ISR code. * @brief Error ISR code.
* @details This code handles the portable part of the ISR code: * @details This code handles the portable part of the ISR code:
* - Error callback invocation. * - Waiting thread wakeup.
* - Waiting thread wakeup, if any.
* - Driver state transitions. * - Driver state transitions.
* *
* @note This macro is meant to be used in the low level drivers * @note This macro is meant to be used in the low level drivers
* implementation only. * implementation only.
* *
* @param[in] i2cp pointer to the @p I2CDriver object * @param[in] i2cp pointer to the @p I2CDriver object
* @param[in] i2cscfg pointer to the @p I2CSlaveConfig object
* *
* @notapi * @notapi
*/ */
#define _i2c_isr_err_code(i2cp, i2cscfg) { \ #define _i2c_isr_err_code(i2cp, i2cscfg) { \
if(((i2cp)->id_slave_config)->id_err_callback) { \ (i2cp)->id_state = I2C_READY; \
((i2cp)->id_slave_config)->id_err_callback(i2cp, i2cscfg); \
(i2cp)->id_state = I2C_READY; \
} \
else \
(i2cp)->id_state = I2C_READY; \
_i2c_wakeup_isr(i2cp); \ _i2c_wakeup_isr(i2cp); \
} }
@ -251,15 +181,16 @@ extern "C" {
void i2cObjectInit(I2CDriver *i2cp); void i2cObjectInit(I2CDriver *i2cp);
void i2cStart(I2CDriver *i2cp, const I2CConfig *config); void i2cStart(I2CDriver *i2cp, const I2CConfig *config);
void i2cStop(I2CDriver *i2cp); void i2cStop(I2CDriver *i2cp);
void i2cMasterTransmit(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, i2cflags_t i2cMasterTransmit(I2CDriver *i2cp,
uint16_t slave_addr, uint8_t slave_addr,
uint8_t *txbuf, size_t txbytes, uint8_t *txbuf, size_t txbytes,
uint8_t *rxbuf, size_t rxbytes); uint8_t *rxbuf, size_t rxbytes);
void i2cMasterReceive(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, i2cflags_t i2cMasterReceive(I2CDriver *i2cp,
uint16_t slave_addr, uint8_t *rxbuf, size_t rxbytes); uint8_t slave_addr, uint8_t *rxbuf, size_t rxbytes);
void i2cMasterStart(I2CDriver *i2cp); void i2cMasterStart(I2CDriver *i2cp);
void i2cMasterStop(I2CDriver *i2cp); void i2cMasterStop(I2CDriver *i2cp);
void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask); void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask);
i2cflags_t i2cGetAndClearFlags(I2CDriver *i2cp);
#if I2C_USE_MUTUAL_EXCLUSION #if I2C_USE_MUTUAL_EXCLUSION
void i2cAcquireBus(I2CDriver *i2cp); void i2cAcquireBus(I2CDriver *i2cp);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,318 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file STM32/i2c_lld.h
* @brief STM32 I2C subsystem low level driver header.
* @addtogroup I2C
* @{
*/
#ifndef _I2C_LLD_H_
#define _I2C_LLD_H_
#if HAL_USE_I2C || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief Switch between callback based and synchronouse driver.
* @note The default is synchronouse.
*/
#if !defined(I2C_SUPPORTS_CALLBACKS) || defined(__DOXYGEN__)
#define I2C_SUPPORTS_CALLBACKS TRUE
#endif
/**
* @brief I2C1 driver synchronization choice between GPT and polling.
* @note The default is polling wait.
*/
#if !defined(STM32_I2C_I2C1_USE_GPT_TIM) || \
!defined(STM32_I2C_I2C1_USE_POLLING_WAIT) || \
defined(__DOXYGEN__)
#define STM32_I2C_I2C1_USE_POLLING_WAIT TRUE
#endif
/**
* @brief I2C2 driver synchronization choice between GPT and polling.
* @note The default is polling wait.
*/
#if !defined(STM32_I2C_I2C2_USE_GPT_TIM) || \
!defined(STM32_I2C_I2C2_USE_POLLING_WAIT) || \
defined(__DOXYGEN__)
#define STM32_I2C_I2C2_USE_POLLING_WAIT TRUE
#endif
/**
* @brief I2C1 driver enable switch.
* @details If set to @p TRUE the support for I2C1 is included.
* @note The default is @p TRUE.
*/
#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__)
#define STM32_I2C_USE_I2C1 TRUE
#endif
/**
* @brief I2C2 driver enable switch.
* @details If set to @p TRUE the support for I2C2 is included.
* @note The default is @p TRUE.
*/
#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__)
#define STM32_I2C_USE_I2C2 TRUE
#endif
/**
* @brief I2C1 interrupt priority level setting.
* @note @p BASEPRI_KERNEL >= @p STM32_I2C_I2C1_IRQ_PRIORITY > @p PRIORITY_PENDSV.
*/
#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_I2C_I2C1_IRQ_PRIORITY 0xA0
#endif
/**
* @brief I2C2 interrupt priority level setting.
* @note @p BASEPRI_KERNEL >= @p STM32_I2C_I2C2_IRQ_PRIORITY > @p PRIORITY_PENDSV.
*/
#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_I2C_I2C2_IRQ_PRIORITY 0xA0
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/** @brief EV5 */
#define I2C_EV5_MASTER_MODE_SELECT ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY)<< 16)|I2C_SR1_SB)) /* BUSY, MSL and SB flag */
/** @brief EV6 */
#define I2C_EV6_MASTER_TRA_MODE_SELECTED ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY|I2C_SR2_TRA)<< 16)|I2C_SR1_ADDR|I2C_SR1_TXE)) /* BUSY, MSL, ADDR, TXE and TRA flags */
#define I2C_EV6_MASTER_REC_MODE_SELECTED ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY)<< 16)|I2C_SR1_ADDR)) /* BUSY, MSL and ADDR flags */
/** @brief EV7 */
#define I2C_EV7_MASTER_REC_BYTE_RECEIVED ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY)<< 16)|I2C_SR1_RXNE)) /* BUSY, MSL and RXNE flags */
#define I2C_EV7_MASTER_REC_BYTE_QUEUED ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY)<< 16)|I2C_SR1_BTF|I2C_SR1_RXNE)) /* BUSY, MSL, RXNE and BTF flags*/
/** @brief EV8 */
#define I2C_EV8_MASTER_BYTE_TRANSMITTING ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY|I2C_SR2_TRA)<< 16)|I2C_SR1_TXE)) /* TRA, BUSY, MSL, TXE flags */
/** @brief EV8_2 */
#define I2C_EV8_2_MASTER_BYTE_TRANSMITTED ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY|I2C_SR2_TRA)<< 16)|I2C_SR1_BTF|I2C_SR1_TXE)) /* TRA, BUSY, MSL, TXE and BTF flags */
/** @brief EV9 */
#define I2C_EV9_MASTER_ADDR_10BIT ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY)<< 16)|I2C_SR1_ADD10)) /* BUSY, MSL and ADD10 flags */
#define I2C_EV_MASK 0x00FFFFFF /* First byte zeroed because there is no need of PEC register part from SR2 */
#define I2C_FLG_1BTR 0x01 /* Single byte to be received and processed */
#define I2C_FLG_2BTR 0x02 /* Two bytes to be received and processed */
#define I2C_FLG_3BTR 0x04 /* Last three received bytes to be processed */
#define I2C_FLG_MASTER_RECEIVER 0x10
#define I2C_FLG_HEADER_SENT 0x80
#define I2C_FLG_TIMER_ARMED 0x40 /* Used to check locks on the bus */
#define EV6_SUBEV_MASK (I2C_FLG_1BTR|I2C_FLG_2BTR|I2C_FLG_MASTER_RECEIVER)
#define EV7_SUBEV_MASK (I2C_FLG_2BTR|I2C_FLG_3BTR|I2C_FLG_MASTER_RECEIVER)
#define I2C_EV6_1_MASTER_REC_2BTR_MODE_SELECTED (I2C_FLG_2BTR|I2C_FLG_MASTER_RECEIVER)
#define I2C_EV6_3_MASTER_REC_1BTR_MODE_SELECTED (I2C_FLG_1BTR|I2C_FLG_MASTER_RECEIVER)
#define I2C_EV7_2_MASTER_REC_3BYTES_TO_PROCESS (I2C_FLG_3BTR|I2C_FLG_MASTER_RECEIVER)
#define I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS (I2C_FLG_2BTR|I2C_FLG_MASTER_RECEIVER)
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief I2C Driver condition flags type.
*/
typedef uint32_t i2cflags_t;
typedef enum {
OPMODE_I2C = 1,
OPMODE_SMBUS_DEVICE = 2,
OPMODE_SMBUS_HOST = 3,
} i2copmode_t;
typedef enum {
STD_DUTY_CYCLE = 1,
FAST_DUTY_CYCLE_2 = 2,
FAST_DUTY_CYCLE_16_9 = 3,
} i2cdutycycle_t;
/**
* @brief Driver configuration structure.
*/
typedef struct {
i2copmode_t op_mode; /**< @brief Specifies the I2C mode.*/
uint32_t clock_speed; /**< @brief Specifies the clock frequency. Must be set to a value lower than 400kHz */
i2cdutycycle_t duty_cycle; /**< @brief Specifies the I2C fast mode duty cycle */
uint8_t own_addr_7; /**< @brief Specifies the first device 7-bit own address. */
uint16_t own_addr_10; /**< @brief Specifies the second part of device own address in 10-bit mode. Set to NULL if not used. */
uint8_t nbit_own_addr; /**< @brief Specifies if 7-bit or 10-bit address is acknowledged */
} I2CConfig;
/**
* @brief Type of a structure representing an I2C driver.
*/
typedef struct I2CDriver I2CDriver;
/**
* @brief Type of a structure representing an I2C slave config.
*/
typedef struct I2CSlaveConfig I2CSlaveConfig;
/**
* @brief Structure representing an I2C driver.
*/
struct I2CDriver{
/**
* @brief Driver state.
*/
i2cstate_t id_state;
#if I2C_USE_WAIT
/**
* @brief Thread waiting for I/O completion.
*/
Thread *id_thread;
#endif /* I2C_USE_WAIT */
#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
/**
* @brief Mutex protecting the bus.
*/
Mutex id_mutex;
#elif CH_USE_SEMAPHORES
Semaphore id_semaphore;
#endif
#endif /* I2C_USE_MUTUAL_EXCLUSION */
/**
* @brief Current configuration data.
*/
const I2CConfig *id_config;
/**
* @brief Current slave configuration data.
*/
const I2CSlaveConfig *id_slave_config;
__IO size_t txbytes; /*!< @brief Number of bytes to be transmitted. */
__IO size_t rxbytes; /*!< @brief Number of bytes to be received. */
uint8_t *rxbuf; /*!< @brief Pointer to receive buffer. */
uint8_t *txbuf; /*!< @brief Pointer to transmit buffer.*/
uint8_t *rxbuff_p; /*!< @brief Pointer to the current byte in slave rx buffer. */
uint8_t *txbuff_p; /*!< @brief Pointer to the current byte in slave tx buffer. */
__IO i2cflags_t errors; /*!< @brief Error flags.*/
__IO i2cflags_t flags; /*!< @brief State flags.*/
uint16_t slave_addr; /*!< @brief Current slave address. */
uint8_t slave_addr1;/*!< @brief 7-bit address of the slave with r\w bit.*/
uint8_t slave_addr2;/*!< @brief Uses in 10-bit address mode. */
#if CH_USE_EVENTS
EventSource sevent; /*!< @brief Status Change @p EventSource.*/
#endif
/*********** End of the mandatory fields. **********************************/
/**
* @brief Pointer to the I2Cx registers block.
*/
I2C_TypeDef *id_i2c;
#if !(STM32_I2C_I2C1_USE_POLLING_WAIT)
/* TODO: capability to switch this GPT fields off */
/**
* @brief Timer for waiting STOP condition on the bus.
* @details This is workaround for STM32 buggy I2C cell.
*/
GPTDriver *timer;
/**
* @brief Config for workaround timer.
*/
const GPTConfig *timer_cfg;
#endif /* !(STM32_I2C_I2C1_USE_POLLING_WAIT) */
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
#define i2c_lld_bus_is_busy(i2cp) \
(i2cp->id_i2c->SR2 & I2C_SR2_BUSY)
/* Wait until BUSY flag is reset: a STOP has been generated on the bus
* signaling the end of transmission. Normally this wait function
* does not block thread, only if slave not response it does.
*/
#define i2c_lld_wait_bus_free(i2cp) { \
uint32_t tmo = 0xfffff; \
while((i2cp->id_i2c->SR2 & I2C_SR2_BUSY) && tmo--) \
; \
}
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/** @cond never*/
#if STM32_I2C_USE_I2C1
extern I2CDriver I2CD1;
#endif
#if STM32_I2C_USE_I2C2
extern I2CDriver I2CD2;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void i2c_lld_init(void);
void i2c_lld_reset(I2CDriver *i2cp);
void i2c_lld_set_clock(I2CDriver *i2cp);
void i2c_lld_set_opmode(I2CDriver *i2cp);
void i2c_lld_set_own_address(I2CDriver *i2cp);
void i2c_lld_start(I2CDriver *i2cp);
void i2c_lld_stop(I2CDriver *i2cp);
void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr,
uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes);
void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr,
uint8_t *rxbuf, size_t rxbytes);
void i2c_lld_master_transceive(I2CDriver *i2cp);
#ifdef __cplusplus
}
#endif
/** @endcond*/
#endif /* CH_HAL_USE_I2C */
#endif /* _I2C_LLD_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -42,50 +42,32 @@
* @name Configuration options * @name Configuration options
* @{ * @{
*/ */
/**
* @brief Switch between callback based and synchronouse driver.
* @note The default is synchronouse.
*/
#if !defined(I2C_SUPPORTS_CALLBACKS) || defined(__DOXYGEN__)
#define I2C_SUPPORTS_CALLBACKS TRUE
#endif
/**
* @brief I2C1 driver synchronization choice between GPT and polling.
* @note The default is polling wait.
*/
#if !defined(STM32_I2C_I2C1_USE_GPT_TIM) || \
!defined(STM32_I2C_I2C1_USE_POLLING_WAIT) || \
defined(__DOXYGEN__)
#define STM32_I2C_I2C1_USE_POLLING_WAIT TRUE
#endif
/**
* @brief I2C2 driver synchronization choice between GPT and polling.
* @note The default is polling wait.
*/
#if !defined(STM32_I2C_I2C2_USE_GPT_TIM) || \
!defined(STM32_I2C_I2C2_USE_POLLING_WAIT) || \
defined(__DOXYGEN__)
#define STM32_I2C_I2C2_USE_POLLING_WAIT TRUE
#endif
/** /**
* @brief I2C1 driver enable switch. * @brief I2C1 driver enable switch.
* @details If set to @p TRUE the support for I2C1 is included. * @details If set to @p TRUE the support for I2C1 is included.
* @note The default is @p TRUE. * @note The default is @p FALSE.
*/ */
#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__) #if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__)
#define STM32_I2C_USE_I2C1 TRUE #define STM32_I2C_USE_I2C1 FALSE
#endif #endif
/** /**
* @brief I2C2 driver enable switch. * @brief I2C2 driver enable switch.
* @details If set to @p TRUE the support for I2C2 is included. * @details If set to @p TRUE the support for I2C2 is included.
* @note The default is @p TRUE. * @note The default is @p FALSE.
*/ */
#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__) #if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__)
#define STM32_I2C_USE_I2C2 TRUE #define STM32_I2C_USE_I2C2 FALSE
#endif
/**
* @brief I2C3 driver enable switch.
* @details If set to @p TRUE the support for I2C3 is included.
* @note The default is @p FALSE.
*/
#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__)
#define STM32_I2C_USE_I2C3 FALSE
#endif #endif
/** /**
@ -103,42 +85,157 @@
#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) #if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_I2C_I2C2_IRQ_PRIORITY 0xA0 #define STM32_I2C_I2C2_IRQ_PRIORITY 0xA0
#endif #endif
/**
* @brief I2C2 interrupt priority level setting.
* @note @p BASEPRI_KERNEL >= @p STM32_I2C_I2C2_IRQ_PRIORITY > @p PRIORITY_PENDSV.
*/
#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_I2C_I2C3_IRQ_PRIORITY 0xA0
#endif
/**
* @brief I2C1 DMA error hook.
* @note The default action for DMA errors is a system halt because DMA
* error can only happen because programming errors.
*/
#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_I2C_DMA_ERROR_HOOK(uartp) chSysHalt()
#endif
#if STM32_ADVANCED_DMA || defined(__DOXYGEN__)
/**
* @brief DMA stream used for I2C1 RX operations.
* @note This option is only available on platforms with enhanced DMA.
*/
#if !defined(STM32_I2C_I2C1_RX_DMA_STREAM) || defined(__DOXYGEN__)
#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
#endif
/**
* @brief DMA stream used for I2C1 TX operations.
* @note This option is only available on platforms with enhanced DMA.
*/
#if !defined(STM32_I2C_I2C1_TX_DMA_STREAM) || defined(__DOXYGEN__)
#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
#endif
/**
* @brief DMA stream used for I2C2 RX operations.
* @note This option is only available on platforms with enhanced DMA.
*/
#if !defined(STM32_I2C_I2C2_RX_DMA_STREAM) || defined(__DOXYGEN__)
#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
#endif
/**
* @brief DMA stream used for I2C2 TX operations.
* @note This option is only available on platforms with enhanced DMA.
*/
#if !defined(STM32_I2C_I2C2_TX_DMA_STREAM) || defined(__DOXYGEN__)
#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
#endif
/**
* @brief DMA stream used for I2C3 RX operations.
* @note This option is only available on platforms with enhanced DMA.
*/
#if !defined(STM32_I2C_I2C3_RX_DMA_STREAM) || defined(__DOXYGEN__)
#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
#endif
/**
* @brief DMA stream used for I2C3 TX operations.
* @note This option is only available on platforms with enhanced DMA.
*/
#if !defined(STM32_I2C_I2C3_TX_DMA_STREAM) || defined(__DOXYGEN__)
#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
#endif
#else /* !STM32_ADVANCED_DMA */
/* Fixed streams for platforms using the old DMA peripheral, the values are
valid for both STM32F1xx and STM32L1xx.*/
#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
#endif /* !STM32_ADVANCED_DMA*/
/** @} */ /** @} */
/*===========================================================================*/ /*===========================================================================*/
/* Derived constants and error checks. */ /* Derived constants and error checks. */
/*===========================================================================*/ /*===========================================================================*/
/** @brief EV5 */ /** @brief flags for interrupt handling */
#define I2C_EV5_MASTER_MODE_SELECT ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY)<< 16)|I2C_SR1_SB)) /* BUSY, MSL and SB flag */ #define I2C_EV5_MASTER_MODE_SELECT ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY) << 16) | I2C_SR1_SB)) /* BUSY, MSL and SB flag */
/** @brief EV6 */
#define I2C_EV6_MASTER_TRA_MODE_SELECTED ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY|I2C_SR2_TRA)<< 16)|I2C_SR1_ADDR|I2C_SR1_TXE)) /* BUSY, MSL, ADDR, TXE and TRA flags */ #define I2C_EV6_MASTER_TRA_MODE_SELECTED ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY|I2C_SR2_TRA)<< 16)|I2C_SR1_ADDR|I2C_SR1_TXE)) /* BUSY, MSL, ADDR, TXE and TRA flags */
#define I2C_EV6_MASTER_REC_MODE_SELECTED ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY)<< 16)|I2C_SR1_ADDR)) /* BUSY, MSL and ADDR flags */ #define I2C_EV6_MASTER_REC_MODE_SELECTED ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY)<< 16)|I2C_SR1_ADDR)) /* BUSY, MSL and ADDR flags */
/** @brief EV7 */ #define I2C_EV8_2_MASTER_BYTE_TRANSMITTED ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) | I2C_SR1_BTF | I2C_SR1_TXE)) /* TRA, BUSY, MSL, TXE and BTF flags */
#define I2C_EV7_MASTER_REC_BYTE_RECEIVED ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY)<< 16)|I2C_SR1_RXNE)) /* BUSY, MSL and RXNE flags */
#define I2C_EV7_MASTER_REC_BYTE_QUEUED ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY)<< 16)|I2C_SR1_BTF|I2C_SR1_RXNE)) /* BUSY, MSL, RXNE and BTF flags*/
/** @brief EV8 */
#define I2C_EV8_MASTER_BYTE_TRANSMITTING ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY|I2C_SR2_TRA)<< 16)|I2C_SR1_TXE)) /* TRA, BUSY, MSL, TXE flags */
/** @brief EV8_2 */
#define I2C_EV8_2_MASTER_BYTE_TRANSMITTED ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY|I2C_SR2_TRA)<< 16)|I2C_SR1_BTF|I2C_SR1_TXE)) /* TRA, BUSY, MSL, TXE and BTF flags */
/** @brief EV9 */
#define I2C_EV9_MASTER_ADDR_10BIT ((uint32_t)(((I2C_SR2_MSL|I2C_SR2_BUSY)<< 16)|I2C_SR1_ADD10)) /* BUSY, MSL and ADD10 flags */
#define I2C_EV_MASK 0x00FFFFFF /* First byte zeroed because there is no need of PEC register part from SR2 */ #define I2C_EV_MASK 0x00FFFFFF /* First byte zeroed because there is no need of PEC register part from SR2 */
#define I2C_FLG_1BTR 0x01 /* Single byte to be received and processed */ #define I2C_FLG_MASTER_RECEIVER 0x10
#define I2C_FLG_2BTR 0x02 /* Two bytes to be received and processed */ #define I2C_FLG_HEADER_SENT 0x80
#define I2C_FLG_3BTR 0x04 /* Last three received bytes to be processed */
#define I2C_FLG_MASTER_RECEIVER 0x10
#define I2C_FLG_HEADER_SENT 0x80
#define I2C_FLG_TIMER_ARMED 0x40 /* Used to check locks on the bus */
#define EV6_SUBEV_MASK (I2C_FLG_1BTR|I2C_FLG_2BTR|I2C_FLG_MASTER_RECEIVER) /** @brief error checks */
#define EV7_SUBEV_MASK (I2C_FLG_2BTR|I2C_FLG_3BTR|I2C_FLG_MASTER_RECEIVER) #if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1
#error "I2C1 not present in the selected device"
#endif
#define I2C_EV6_1_MASTER_REC_2BTR_MODE_SELECTED (I2C_FLG_2BTR|I2C_FLG_MASTER_RECEIVER) #if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2
#define I2C_EV6_3_MASTER_REC_1BTR_MODE_SELECTED (I2C_FLG_1BTR|I2C_FLG_MASTER_RECEIVER) #error "I2C2 not present in the selected device"
#define I2C_EV7_2_MASTER_REC_3BYTES_TO_PROCESS (I2C_FLG_3BTR|I2C_FLG_MASTER_RECEIVER) #endif
#define I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS (I2C_FLG_2BTR|I2C_FLG_MASTER_RECEIVER)
#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3
#error "I2C3 not present in the selected device"
#endif
#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && \
!STM32_I2C_USE_I2C3
#error "I2C driver activated but no I2C peripheral assigned"
#endif
#if STM32_I2C_USE_I2C1 && \
!STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \
STM32_I2C1_RX_DMA_MSK)
#error "invalid DMA stream associated to I2C1 RX"
#endif
#if STM32_I2C_USE_I2C1 && \
!STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \
STM32_I2C1_TX_DMA_MSK)
#error "invalid DMA stream associated to I2C1 TX"
#endif
#if STM32_I2C_USE_I2C2 && \
!STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \
STM32_I2C2_RX_DMA_MSK)
#error "invalid DMA stream associated to I2C2 RX"
#endif
#if STM32_I2C_USE_I2C2 && \
!STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \
STM32_I2C2_TX_DMA_MSK)
#error "invalid DMA stream associated to I2C2 TX"
#endif
#if STM32_I2C_USE_I2C3 && \
!STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_RX_DMA_STREAM, \
STM32_I2C3_RX_DMA_MSK)
#error "invalid DMA stream associated to I2C3 RX"
#endif
#if STM32_I2C_USE_I2C3 && \
!STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_TX_DMA_STREAM, \
STM32_I2C3_TX_DMA_MSK)
#error "invalid DMA stream associated to I2C3 TX"
#endif
#if !defined(STM32_DMA_REQUIRED)
#define STM32_DMA_REQUIRED
#endif
/*===========================================================================*/ /*===========================================================================*/
/* Driver data structures and types. */ /* Driver data structures and types. */
@ -168,9 +265,6 @@ typedef struct {
i2copmode_t op_mode; /**< @brief Specifies the I2C mode.*/ i2copmode_t op_mode; /**< @brief Specifies the I2C mode.*/
uint32_t clock_speed; /**< @brief Specifies the clock frequency. Must be set to a value lower than 400kHz */ uint32_t clock_speed; /**< @brief Specifies the clock frequency. Must be set to a value lower than 400kHz */
i2cdutycycle_t duty_cycle; /**< @brief Specifies the I2C fast mode duty cycle */ i2cdutycycle_t duty_cycle; /**< @brief Specifies the I2C fast mode duty cycle */
uint8_t own_addr_7; /**< @brief Specifies the first device 7-bit own address. */
uint16_t own_addr_10; /**< @brief Specifies the second part of device own address in 10-bit mode. Set to NULL if not used. */
uint8_t nbit_own_addr; /**< @brief Specifies if 7-bit or 10-bit address is acknowledged */
} I2CConfig; } I2CConfig;
@ -179,11 +273,6 @@ typedef struct {
*/ */
typedef struct I2CDriver I2CDriver; typedef struct I2CDriver I2CDriver;
/**
* @brief Type of a structure representing an I2C slave config.
*/
typedef struct I2CSlaveConfig I2CSlaveConfig;
/** /**
* @brief Structure representing an I2C driver. * @brief Structure representing an I2C driver.
*/ */
@ -191,72 +280,46 @@ struct I2CDriver{
/** /**
* @brief Driver state. * @brief Driver state.
*/ */
i2cstate_t id_state; i2cstate_t id_state;
#if I2C_USE_WAIT
/** /**
* @brief Thread waiting for I/O completion. * @brief Thread waiting for I/O completion.
*/ */
Thread *id_thread; Thread *id_thread;
#endif /* I2C_USE_WAIT */
#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) #if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
#if CH_USE_MUTEXES || defined(__DOXYGEN__) #if CH_USE_MUTEXES || defined(__DOXYGEN__)
/** /**
* @brief Mutex protecting the bus. * @brief Mutex protecting the bus.
*/ */
Mutex id_mutex; Mutex id_mutex;
#elif CH_USE_SEMAPHORES #elif CH_USE_SEMAPHORES
Semaphore id_semaphore; Semaphore id_semaphore;
#endif #endif
#endif /* I2C_USE_MUTUAL_EXCLUSION */ #endif /* I2C_USE_MUTUAL_EXCLUSION */
/** /**
* @brief Current configuration data. * @brief Current configuration data.
*/ */
const I2CConfig *id_config; const I2CConfig *id_config;
/**
* @brief Current slave configuration data.
*/
const I2CSlaveConfig *id_slave_config;
__IO size_t txbytes; /*!< @brief Number of bytes to be transmitted. */ __IO size_t txbytes; /*!< @brief Number of bytes to be transmitted. */
__IO size_t rxbytes; /*!< @brief Number of bytes to be received. */ __IO size_t rxbytes; /*!< @brief Number of bytes to be received. */
uint8_t *rxbuf; /*!< @brief Pointer to receive buffer. */ uint8_t *rxbuf; /*!< @brief Pointer to receive buffer. */
uint8_t *txbuf; /*!< @brief Pointer to transmit buffer.*/ uint8_t *txbuf; /*!< @brief Pointer to transmit buffer.*/
uint8_t *rxbuff_p; /*!< @brief Pointer to the current byte in slave rx buffer. */
uint8_t *txbuff_p; /*!< @brief Pointer to the current byte in slave tx buffer. */
__IO i2cflags_t errors; /*!< @brief Error flags.*/ __IO i2cflags_t errors; /*!< @brief Error flags.*/
__IO i2cflags_t flags; /*!< @brief State flags.*/ __IO i2cflags_t flags; /*!< @brief State flags.*/
uint16_t slave_addr; /*!< @brief Current slave address. */ uint8_t slave_addr; /*!< @brief Current slave address without R/W bit. */
uint8_t slave_addr1;/*!< @brief 7-bit address of the slave with r\w bit.*/
uint8_t slave_addr2;/*!< @brief Uses in 10-bit address mode. */
#if CH_USE_EVENTS
EventSource sevent; /*!< @brief Status Change @p EventSource.*/
#endif
/*********** End of the mandatory fields. **********************************/ /*********** End of the mandatory fields. **********************************/
/** uint32_t dmamode; /*!< @brief DMA mode bit mask.*/
* @brief Pointer to the I2Cx registers block. const stm32_dma_stream_t *dmarx; /*!< @brief Receive DMA channel.*/
*/ const stm32_dma_stream_t *dmatx; /*!< @brief Transmit DMA channel.*/
I2C_TypeDef *id_i2c;
#if !(STM32_I2C_I2C1_USE_POLLING_WAIT) I2C_TypeDef *id_i2c; /*!< @brief Pointer to the I2Cx registers block. */
/* TODO: capability to switch this GPT fields off */
/**
* @brief Timer for waiting STOP condition on the bus.
* @details This is workaround for STM32 buggy I2C cell.
*/
GPTDriver *timer;
/**
* @brief Config for workaround timer.
*/
const GPTConfig *timer_cfg;
#endif /* !(STM32_I2C_I2C1_USE_POLLING_WAIT) */
}; };
@ -268,8 +331,7 @@ struct I2CDriver{
(i2cp->id_i2c->SR2 & I2C_SR2_BUSY) (i2cp->id_i2c->SR2 & I2C_SR2_BUSY)
/* Wait until BUSY flag is reset: a STOP has been generated on the bus /* Wait until BUSY flag is reset. Normally this wait function
* signaling the end of transmission. Normally this wait function
* does not block thread, only if slave not response it does. * does not block thread, only if slave not response it does.
*/ */
#define i2c_lld_wait_bus_free(i2cp) { \ #define i2c_lld_wait_bus_free(i2cp) { \
@ -291,6 +353,10 @@ extern I2CDriver I2CD1;
extern I2CDriver I2CD2; extern I2CDriver I2CD2;
#endif #endif
#if STM32_I2C_USE_I2C3
extern I2CDriver I2CD3;
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -299,14 +365,12 @@ void i2c_lld_init(void);
void i2c_lld_reset(I2CDriver *i2cp); void i2c_lld_reset(I2CDriver *i2cp);
void i2c_lld_set_clock(I2CDriver *i2cp); void i2c_lld_set_clock(I2CDriver *i2cp);
void i2c_lld_set_opmode(I2CDriver *i2cp); void i2c_lld_set_opmode(I2CDriver *i2cp);
void i2c_lld_set_own_address(I2CDriver *i2cp);
void i2c_lld_start(I2CDriver *i2cp); void i2c_lld_start(I2CDriver *i2cp);
void i2c_lld_stop(I2CDriver *i2cp); void i2c_lld_stop(I2CDriver *i2cp);
void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, void i2c_lld_master_transmit(I2CDriver *i2cp, uint8_t slave_addr,
uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes); uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes);
void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, void i2c_lld_master_receive(I2CDriver *i2cp, uint8_t slave_addr,
uint8_t *rxbuf, size_t rxbytes); uint8_t *rxbuf, size_t rxbytes);
void i2c_lld_master_transceive(I2CDriver *i2cp);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -295,8 +295,22 @@
/* I2C attributes.*/ /* I2C attributes.*/
#define STM32_HAS_I2C1 TRUE #define STM32_HAS_I2C1 TRUE
#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7))
#define STM32_I2C1_RX_DMA_CHN 0x00000000
#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6))
#define STM32_I2C1_TX_DMA_CHN 0x00000000
#define STM32_HAS_I2C2 TRUE #define STM32_HAS_I2C2 TRUE
#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5))
#define STM32_I2C2_RX_DMA_CHN 0x00000000
#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4))
#define STM32_I2C2_TX_DMA_CHN 0x00000000
#define STM32_HAS_I2C3 FALSE #define STM32_HAS_I2C3 FALSE
#define STM32_I2C3_RX_DMA_MSK 0
#define STM32_I2C3_RX_DMA_CHN 0x00000000
#define STM32_I2C3_TX_DMA_MSK 0
#define STM32_I2C3_TX_DMA_CHN 0x00000000
/* RTC attributes.*/ /* RTC attributes.*/
#define STM32_HAS_RTC TRUE #define STM32_HAS_RTC TRUE

View File

@ -306,8 +306,24 @@
/* I2C attributes.*/ /* I2C attributes.*/
#define STM32_HAS_I2C1 TRUE #define STM32_HAS_I2C1 TRUE
#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7))
#define STM32_I2C1_RX_DMA_CHN 0x00000000
#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6))
#define STM32_I2C1_TX_DMA_CHN 0x00000000
#define STM32_HAS_I2C2 TRUE #define STM32_HAS_I2C2 TRUE
#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5))
#define STM32_I2C2_RX_DMA_CHN 0x00000000
#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4))
#define STM32_I2C2_TX_DMA_CHN 0x00000000
#define STM32_HAS_I2C3 FALSE #define STM32_HAS_I2C3 FALSE
#define STM32_I2C3_RX_DMA_MSK 0
#define STM32_I2C3_RX_DMA_CHN 0x00000000
#define STM32_I2C3_TX_DMA_MSK 0
#define STM32_I2C3_TX_DMA_CHN 0x00000000
/* RTC attributes.*/ /* RTC attributes.*/
#define STM32_HAS_RTC TRUE #define STM32_HAS_RTC TRUE

View File

@ -166,8 +166,22 @@
/* I2C attributes.*/ /* I2C attributes.*/
#define STM32_HAS_I2C1 TRUE #define STM32_HAS_I2C1 TRUE
#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7))
#define STM32_I2C1_RX_DMA_CHN 0x00000000
#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6))
#define STM32_I2C1_TX_DMA_CHN 0x00000000
#define STM32_HAS_I2C2 TRUE #define STM32_HAS_I2C2 TRUE
#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5))
#define STM32_I2C2_RX_DMA_CHN 0x00000000
#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4))
#define STM32_I2C2_TX_DMA_CHN 0x00000000
#define STM32_HAS_I2C3 FALSE #define STM32_HAS_I2C3 FALSE
#define STM32_I2C3_RX_DMA_MSK 0
#define STM32_I2C3_RX_DMA_CHN 0x00000000
#define STM32_I2C3_TX_DMA_MSK 0
#define STM32_I2C3_TX_DMA_CHN 0x00000000
/* RTC attributes.*/ /* RTC attributes.*/
#define STM32_HAS_RTC TRUE #define STM32_HAS_RTC TRUE

View File

@ -157,8 +157,27 @@
#define STM32_HAS_GPIOH TRUE #define STM32_HAS_GPIOH TRUE
#define STM32_HAS_GPIOI TRUE #define STM32_HAS_GPIOI TRUE
/* I2C attributes.*/
#define STM32_HAS_I2C1 TRUE #define STM32_HAS_I2C1 TRUE
#define STM32_I2C1_RX_DMA_MSK ((STM32_DMA_STREAM_ID_MSK(1, 0) | \
STM32_DMA_STREAM_ID_MSK(1, 5)))
#define STM32_I2C1_RX_DMA_CHN 0x00100001
#define STM32_I2C1_TX_DMA_MSK ((STM32_DMA_STREAM_ID_MSK(1, 7)) | \
(STM32_DMA_STREAM_ID_MSK(1, 6)))
#define STM32_I2C1_TX_DMA_CHN 0x10000000
#define STM32_HAS_I2C2 TRUE #define STM32_HAS_I2C2 TRUE
#define STM32_I2C2_RX_DMA_MSK ((STM32_DMA_STREAM_ID_MSK(1, 2) | \
STM32_DMA_STREAM_ID_MSK(1, 3)))
#define STM32_I2C2_RX_DMA_CHN 0x00007700
#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7))
#define STM32_I2C2_TX_DMA_CHN 0x70000000
#define STM32_HAS_I2C3 TRUE
#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2))
#define STM32_I2C3_RX_DMA_CHN 0x00000300
#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4))
#define STM32_I2C3_TX_DMA_CHN 0x00030000
#define STM32_HAS_RTC TRUE #define STM32_HAS_RTC TRUE

View File

@ -9,6 +9,7 @@ PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32F4xx/stm32_dma.c \
${CHIBIOS}/os/hal/platforms/STM32/serial_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/serial_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/spi_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/spi_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/uart_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/uart_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/i2c_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c
# Required include directories # Required include directories

View File

@ -198,8 +198,22 @@
/* I2C attributes.*/ /* I2C attributes.*/
#define STM32_HAS_I2C1 TRUE #define STM32_HAS_I2C1 TRUE
#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7))
#define STM32_I2C1_RX_DMA_CHN 0x00000000
#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6))
#define STM32_I2C1_TX_DMA_CHN 0x00000000
#define STM32_HAS_I2C2 TRUE #define STM32_HAS_I2C2 TRUE
#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5))
#define STM32_I2C2_RX_DMA_CHN 0x00000000
#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4))
#define STM32_I2C2_TX_DMA_CHN 0x00000000
#define STM32_HAS_I2C3 FALSE #define STM32_HAS_I2C3 FALSE
#define STM32_I2C3_RX_DMA_MSK 0
#define STM32_I2C3_RX_DMA_CHN 0x00000000
#define STM32_I2C3_TX_DMA_MSK 0
#define STM32_I2C3_TX_DMA_CHN 0x00000000
/* RTC attributes.*/ /* RTC attributes.*/
#define STM32_HAS_RTC TRUE #define STM32_HAS_RTC TRUE

View File

@ -73,15 +73,9 @@ void i2cObjectInit(I2CDriver *i2cp) {
i2cp->id_state = I2C_STOP; i2cp->id_state = I2C_STOP;
i2cp->id_config = NULL; i2cp->id_config = NULL;
i2cp->rxbuff_p = NULL;
i2cp->txbuff_p = NULL;
i2cp->rxbuf = NULL; i2cp->rxbuf = NULL;
i2cp->txbuf = NULL; i2cp->txbuf = NULL;
i2cp->id_slave_config = NULL;
#if I2C_USE_WAIT
i2cp->id_thread = NULL; i2cp->id_thread = NULL;
#endif /* I2C_USE_WAIT */
#if I2C_USE_MUTUAL_EXCLUSION #if I2C_USE_MUTUAL_EXCLUSION
#if CH_USE_MUTEXES #if CH_USE_MUTEXES
@ -111,10 +105,6 @@ void i2cStart(I2CDriver *i2cp, const I2CConfig *config) {
"i2cStart(), #1", "i2cStart(), #1",
"invalid state"); "invalid state");
#if (!(STM32_I2C_I2C2_USE_POLLING_WAIT) && I2C_SUPPORTS_CALLBACKS)
gptStart(i2cp->timer, i2cp->timer_cfg);
#endif /* !(STM32_I2C_I2C2_USE_POLLING_WAIT) */
chSysLock(); chSysLock();
i2cp->id_config = config; i2cp->id_config = config;
i2c_lld_start(i2cp); i2c_lld_start(i2cp);
@ -136,10 +126,6 @@ void i2cStop(I2CDriver *i2cp) {
"i2cStop(), #1", "i2cStop(), #1",
"invalid state"); "invalid state");
#if (!(STM32_I2C_I2C2_USE_POLLING_WAIT) && I2C_SUPPORTS_CALLBACKS)
gptStop(i2cp->timer);
#endif /* !(STM32_I2C_I2C2_USE_POLLING_WAIT) */
chSysLock(); chSysLock();
i2c_lld_stop(i2cp); i2c_lld_stop(i2cp);
i2cp->id_state = I2C_STOP; i2cp->id_state = I2C_STOP;
@ -153,35 +139,33 @@ void i2cStop(I2CDriver *i2cp) {
* paradigm. If you want transmit data without any further read, * paradigm. If you want transmit data without any further read,
* than set @b rxbytes field to 0. * than set @b rxbytes field to 0.
* *
* @details Number of receiving byts must be 0 or more than 1 because of stm32
* hardware restrictions.
*
* @param[in] i2cp pointer to the @p I2CDriver object * @param[in] i2cp pointer to the @p I2CDriver object
* @param[in] i2cscfg pointer to the @p I2C slave config * @param[in] slave_addr Slave device address (7 bits) without R/W bit
* @param[in] slave_addr Slave device address. Bits 0-9 contain slave
* device address. Bit 15 must be set to 1 if 10-bit
* addressing mode used. Otherwise keep it cleared.
* Bits 10-14 unused.
* @param[in] txbuf pointer to transmit buffer * @param[in] txbuf pointer to transmit buffer
* @param[in] txbytes number of bytes to be transmitted * @param[in] txbytes number of bytes to be transmitted
* @param[in] rxbuf pointer to receive buffer * @param[in] rxbuf pointer to receive buffer
* @param[in] rxbytes number of bytes to be received, set it to 0 if * @param[in] rxbytes number of bytes to be received, set it to 0 if
* you want transmit only * you want transmit only
*
* @return Zero if no errors, otherwise return error code.
*/ */
void i2cMasterTransmit(I2CDriver *i2cp, i2cflags_t i2cMasterTransmit(I2CDriver *i2cp,
const I2CSlaveConfig *i2cscfg, uint8_t slave_addr,
uint16_t slave_addr,
uint8_t *txbuf, uint8_t *txbuf,
size_t txbytes, size_t txbytes,
uint8_t *rxbuf, uint8_t *rxbuf,
size_t rxbytes) { size_t rxbytes) {
chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ chDbgCheck((i2cp != NULL) &&\
(slave_addr != 0) &&\ (slave_addr != 0) &&\
(txbytes > 0) &&\ (txbytes > 0) &&\
(txbuf != NULL), (txbuf != NULL) &&\
((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL))),
"i2cMasterTransmit"); "i2cMasterTransmit");
/* init slave config field in driver */
i2cp->id_slave_config = i2cscfg;
i2c_lld_wait_bus_free(i2cp); i2c_lld_wait_bus_free(i2cp);
chDbgAssert(!(i2c_lld_bus_is_busy(i2cp)), "i2cMasterReceive(), #1", "time is out"); chDbgAssert(!(i2c_lld_bus_is_busy(i2cp)), "i2cMasterReceive(), #1", "time is out");
@ -190,40 +174,34 @@ void i2cMasterTransmit(I2CDriver *i2cp,
i2cp->id_state = I2C_ACTIVE_TRANSMIT; i2cp->id_state = I2C_ACTIVE_TRANSMIT;
i2c_lld_master_transmit(i2cp, slave_addr, txbuf, txbytes, rxbuf, rxbytes); i2c_lld_master_transmit(i2cp, slave_addr, txbuf, txbytes, rxbuf, rxbytes);
#if I2C_SUPPORTS_CALLBACKS
_i2c_wait_s(i2cp); _i2c_wait_s(i2cp);
#else
i2cp->id_state = I2C_READY; return i2cGetAndClearFlags(i2cp);
#endif /* I2C_SUPPORTS_CALLBACKS */
} }
/** /**
* @brief Receives data from the I2C bus. * @brief Receives data from the I2C bus.
* @details Number of receiving byts must be more than 1 because of stm32
* hardware restrictions.
* *
* @param[in] i2cp pointer to the @p I2CDriver object * @param[in] i2cp pointer to the @p I2CDriver object
* @param[in] i2cscfg pointer to the @p I2C slave config * @param[in] slave_addr slave device address (7 bits) without R/W bit
* @param[in] slave_addr Slave device address. Bits 0-9 contain slave
* device address. Bit 15 must be set to 1 if 10-bit
* addressing mode used. Otherwise keep it cleared.
* Bits 10-14 unused.
* @param[in] rxbytes number of bytes to be received * @param[in] rxbytes number of bytes to be received
* @param[in] rxbuf pointer to receive buffer * @param[in] rxbuf pointer to receive buffer
*
* @return Zero if no errors, otherwise return error code.
*/ */
void i2cMasterReceive(I2CDriver *i2cp, i2cflags_t i2cMasterReceive(I2CDriver *i2cp,
const I2CSlaveConfig *i2cscfg, uint8_t slave_addr,
uint16_t slave_addr,
uint8_t *rxbuf, uint8_t *rxbuf,
size_t rxbytes){ size_t rxbytes){
chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ chDbgCheck((i2cp != NULL) &&\
(slave_addr != 0) &&\ (slave_addr != 0) &&\
(rxbytes > 0) && \ (rxbytes > 1) && \
(rxbuf != NULL), (rxbuf != NULL),
"i2cMasterReceive"); "i2cMasterReceive");
/* init slave config field in driver */
i2cp->id_slave_config = i2cscfg;
i2c_lld_wait_bus_free(i2cp); i2c_lld_wait_bus_free(i2cp);
chDbgAssert(!(i2c_lld_bus_is_busy(i2cp)), "i2cMasterReceive(), #1", "time is out"); chDbgAssert(!(i2c_lld_bus_is_busy(i2cp)), "i2cMasterReceive(), #1", "time is out");
@ -232,20 +210,10 @@ void i2cMasterReceive(I2CDriver *i2cp,
i2cp->id_state = I2C_ACTIVE_RECEIVE; i2cp->id_state = I2C_ACTIVE_RECEIVE;
i2c_lld_master_receive(i2cp, slave_addr, rxbuf, rxbytes); i2c_lld_master_receive(i2cp, slave_addr, rxbuf, rxbytes);
#if I2C_SUPPORTS_CALLBACKS
_i2c_wait_s(i2cp); _i2c_wait_s(i2cp);
#else
i2cp->id_state = I2C_READY;
#endif /* I2C_SUPPORTS_CALLBACKS */
}
return i2cGetAndClearFlags(i2cp);
/* FIXME: I do not know what this function must do. And can not test it
uint16_t i2cSMBusAlertResponse(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) {
i2cMasterReceive(i2cp, i2cscfg);
return i2cp->id_slave_config->slave_addr;
} }
*/
/** /**
* @brief Handles communication events/errors. * @brief Handles communication events/errors.
@ -262,7 +230,6 @@ void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask) {
chDbgCheck(i2cp != NULL, "i2cAddFlagsI"); chDbgCheck(i2cp != NULL, "i2cAddFlagsI");
i2cp->errors |= mask; i2cp->errors |= mask;
chEvtBroadcastI(&i2cp->sevent);
} }
/** /**
@ -323,7 +290,6 @@ void i2cReleaseBus(I2CDriver *i2cp) {
chDbgCheck(i2cp != NULL, "i2cReleaseBus"); chDbgCheck(i2cp != NULL, "i2cReleaseBus");
#if CH_USE_MUTEXES #if CH_USE_MUTEXES
(void)i2cp;
chMtxUnlock(); chMtxUnlock();
#elif CH_USE_SEMAPHORES #elif CH_USE_SEMAPHORES
chSemSignal(&i2cp->id_semaphore); chSemSignal(&i2cp->id_semaphore);

View File

@ -31,7 +31,7 @@ endif
# Enable this if you want to see the full log while compiling. # Enable this if you want to see the full log while compiling.
ifeq ($(USE_VERBOSE_COMPILE),) ifeq ($(USE_VERBOSE_COMPILE),)
USE_VERBOSE_COMPILE = no USE_VERBOSE_COMPILE = yes
endif endif
# #
@ -63,7 +63,7 @@ LDSCRIPT= $(PORTLD)/STM32F103xB.ld
# Imported source files # Imported source files
CHIBIOS = ../../.. CHIBIOS = ../../..
include $(CHIBIOS)/boards/OLIMEX_STM32_P103/board.mk include $(CHIBIOS)/boards/OLIMEX_STM32_103STK/board.mk
include $(CHIBIOS)/os/hal/platforms/STM32F1xx/platform.mk include $(CHIBIOS)/os/hal/platforms/STM32F1xx/platform.mk
include $(CHIBIOS)/os/hal/hal.mk include $(CHIBIOS)/os/hal/hal.mk
include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F1xx/port.mk include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F1xx/port.mk
@ -82,9 +82,9 @@ CSRC = $(PORTSRC) \
$(CHIBIOS)/os/various/syscalls.c \ $(CHIBIOS)/os/various/syscalls.c \
main.c \ main.c \
i2c_pns.c \ i2c_pns.c \
tmp75.c\ lis3.c \
max1236.c\ tmp75.c \
lis3.c\ fake.c
@ -127,7 +127,6 @@ INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \
# Compiler settings # Compiler settings
# #
# -lm <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
MCU = cortex-m3 MCU = cortex-m3
#TRGT = arm-elf- #TRGT = arm-elf-

View File

@ -0,0 +1,58 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Not responding slave test
*/
#include <stdlib.h>
#include "ch.h"
#include "hal.h"
#include "fake.h"
/* input buffer */
static uint8_t rx_data[2];
/* temperature value */
static int16_t temperature = 0;
#define addr 0b1001100
/* This is main function. */
void request_fake(void){
i2cflags_t errors = 0;
i2cAcquireBus(&I2CD1);
errors = i2cMasterReceive(&I2CD1, addr, rx_data, 2);
i2cReleaseBus(&I2CD1);
if (errors == I2CD_ACK_FAILURE){
__NOP();
}
else{
temperature = (rx_data[0] << 8) + rx_data[1];
}
}

View File

@ -0,0 +1,26 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FAKE_H_
#define FAKE_H_
void request_fake(void);
#endif /* FAKE_H_ */

View File

@ -44,7 +44,7 @@
* @brief Enables the ADC subsystem. * @brief Enables the ADC subsystem.
*/ */
#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
#define HAL_USE_ADC TRUE #define HAL_USE_ADC FALSE
#endif #endif
/** /**
@ -100,7 +100,7 @@
* @brief Enables the PWM subsystem. * @brief Enables the PWM subsystem.
*/ */
#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
#define HAL_USE_PWM TRUE #define HAL_USE_PWM FALSE
#endif #endif
/** /**
@ -121,7 +121,7 @@
* @brief Enables the SERIAL subsystem. * @brief Enables the SERIAL subsystem.
*/ */
#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) #if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL TRUE #define HAL_USE_SERIAL FALSE
#endif #endif
/** /**
@ -192,7 +192,7 @@
* @note Disabling this option saves both code and data space. * @note Disabling this option saves both code and data space.
*/ */
#if !defined(I2C_USE_WAIT) || defined(__DOXYGEN__) #if !defined(I2C_USE_WAIT) || defined(__DOXYGEN__)
#define I2C_USE_WAIT FALSE #define I2C_USE_WAIT TRUE
#endif #endif
/** /**
@ -202,13 +202,6 @@
#define I2C_USE_MUTUAL_EXCLUSION TRUE #define I2C_USE_MUTUAL_EXCLUSION TRUE
#endif #endif
/**
* @brief Switch to asynchronouse driver with callbacks.
*/
#if !defined(I2C_SUPPORTS_CALLBACKS) || defined(__DOXYGEN__)
#define I2C_SUPPORTS_CALLBACKS TRUE
#endif
/*===========================================================================*/ /*===========================================================================*/
/* MAC driver related settings. */ /* MAC driver related settings. */
/*===========================================================================*/ /*===========================================================================*/

View File

@ -1,32 +1,35 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ch.h" #include "ch.h"
#include "hal.h" #include "hal.h"
#include "i2c_pns.h" #include "i2c_pns.h"
#include "lis3.h" #include "lis3.h"
#include "tmp75.h"
#include "max1236.h"
/* I2C1 */ /* I2C1 */
static const I2CConfig i2cfg1 = { static const I2CConfig i2cfg1 = {
OPMODE_I2C, OPMODE_I2C,
100000, 400000,
STD_DUTY_CYCLE, FAST_DUTY_CYCLE_16_9,
0,
0,
0,
0,
};
/* I2C2 */
static const I2CConfig i2cfg2 = {
OPMODE_I2C,
100000,
STD_DUTY_CYCLE,
0,
0,
0,
0,
}; };
@ -35,22 +38,14 @@ void I2CInit_pns(void){
i2cInit(); i2cInit();
i2cStart(&I2CD1, &i2cfg1); i2cStart(&I2CD1, &i2cfg1);
i2cStart(&I2CD2, &i2cfg2);
/* tune ports for I2C1*/ /* tune ports for I2C1*/
palSetPadMode(IOPORT2, 6, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); palSetPadMode(IOPORT2, 6, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
palSetPadMode(IOPORT2, 7, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); palSetPadMode(IOPORT2, 7, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
/* tune ports for I2C2*/
palSetPadMode(IOPORT2, 10, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
palSetPadMode(IOPORT2, 11, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
/* startups. Pauses added just to be safe */ /* startups. Pauses added just to be safe */
chThdSleepMilliseconds(1000); chThdSleepMilliseconds(100);
init_max1236();
chThdSleepMilliseconds(1000);
init_lis3(); init_lis3();
chThdSleepMilliseconds(1000);
} }

View File

@ -1,3 +1,23 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef I2C_PNS_H_ #ifndef I2C_PNS_H_
#define I2C_PNS_H_ #define I2C_PNS_H_

View File

@ -1,7 +1,26 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** /**
* This is most complex and difficult device. * This is device realize "read through write" paradigm. This is not
* It realize "read through write" paradigm. This is not standard, but * standard, but most of I2C devices use this paradigm.
* most of I2C devices use this paradigm.
* You must write to device reading address, send restart to bus, * You must write to device reading address, send restart to bus,
* and then begin reading process. * and then begin reading process.
*/ */
@ -18,34 +37,13 @@
/* buffers */ /* buffers */
static i2cblock_t accel_rx_data[ACCEL_RX_DEPTH]; static uint8_t accel_rx_data[ACCEL_RX_DEPTH];
static i2cblock_t accel_tx_data[ACCEL_TX_DEPTH]; static uint8_t accel_tx_data[ACCEL_TX_DEPTH];
static int16_t acceleration_x = 0; static int16_t acceleration_x = 0;
static int16_t acceleration_y = 0; static int16_t acceleration_y = 0;
static int16_t acceleration_z = 0; static int16_t acceleration_z = 0;
/* Error trap */
static void i2c_lis3_error_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){
(void)i2cscfg;
int status = 0;
status = i2cp->id_i2c->SR1;
while(TRUE);
}
/* This callback raise up when transfer finished */
static void i2c_lis3_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){
(void)i2cp;
(void)i2cscfg;
}
/* Accelerometer lis3lv02dq config */
static const I2CSlaveConfig lis3 = {
i2c_lis3_cb,
i2c_lis3_error_cb,
};
/** /**
* Init function. Here we will also start personal serving thread. * Init function. Here we will also start personal serving thread.
@ -58,7 +56,9 @@ int init_lis3(void){
accel_tx_data[3] = 0b00000000; accel_tx_data[3] = 0b00000000;
/* sending */ /* sending */
i2cMasterTransmit(&I2CD1, &lis3, lis3_addr, accel_tx_data, 4, accel_rx_data, 0); i2cAcquireBus(&I2CD1);
i2cMasterTransmit(&I2CD1, lis3_addr, accel_tx_data, 4, accel_rx_data, 0);
i2cReleaseBus(&I2CD1);
return 0; return 0;
} }
@ -67,9 +67,9 @@ int init_lis3(void){
*/ */
void request_acceleration_data(void){ void request_acceleration_data(void){
accel_tx_data[0] = ACCEL_OUT_DATA | AUTO_INCREMENT_BIT; // register address accel_tx_data[0] = ACCEL_OUT_DATA | AUTO_INCREMENT_BIT; // register address
//i2cAcquireBus(&I2CD1); i2cAcquireBus(&I2CD1);
i2cMasterTransmit(&I2CD1, &lis3, lis3_addr, accel_tx_data, 1, accel_rx_data, 6); i2cMasterTransmit(&I2CD1, lis3_addr, accel_tx_data, 1, accel_rx_data, 6);
//i2cReleaseBus(&I2CD1); i2cReleaseBus(&I2CD1);
acceleration_x = accel_rx_data[0] + (accel_rx_data[1] << 8); acceleration_x = accel_rx_data[0] + (accel_rx_data[1] << 8);
acceleration_y = accel_rx_data[2] + (accel_rx_data[3] << 8); acceleration_y = accel_rx_data[2] + (accel_rx_data[3] << 8);

View File

@ -1,3 +1,23 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h> #include <stdlib.h>
#include "ch.h" #include "ch.h"

View File

@ -1,21 +1,22 @@
/** /*
* Lets imagine that we have board with LIS3LV02DL accelerometer on channel #1 ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
* and MAX1236 ADC, TMP75 thermometer on channel #2. 2011 Giovanni Di Sirio.
*
* NOTE: I assume, that you have datasheets on all this stuff. This file is part of ChibiOS/RT.
*
* NOTE: Also, I assume, that you know how to I2C works. ChibiOS/RT is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* In order from simplicity to complexity: the Free Software Foundation; either version 3 of the License, or
* TMP75 (at your option) any later version.
* MAX1236
* LIS3LV02DL ChibiOS/RT is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* Project splitted to separate source files for each device. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* Data from sensors we will be read from different thread sleeping different
* amount of time. You should have received a copy of the GNU General Public License
*/ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h> #include <stdlib.h>
@ -23,10 +24,9 @@
#include "hal.h" #include "hal.h"
#include "i2c_pns.h" #include "i2c_pns.h"
#include "tmp75.h"
#include "max1236.h"
#include "lis3.h" #include "lis3.h"
#include "tmp75.h"
#include "fake.h"
/* /*
@ -44,55 +44,51 @@ static msg_t Blink(void *arg) {
return 0; return 0;
} }
/*
* Accelerometer thread
*/
static WORKING_AREA(PollAccelThreadWA, 128);
static msg_t PollAccelThread(void *arg) {
chRegSetThreadName("PollAccel");
(void)arg;
while (TRUE) {
// chThdSleepMilliseconds(rand() & 31);
chThdSleepMilliseconds(32);
request_acceleration_data();
}
return 0;
}
/* Temperature polling thread */ /* Temperature polling thread */
static WORKING_AREA(PollTmp75ThreadWA, 128); static WORKING_AREA(PollTmp75ThreadWA, 128);
static msg_t PollTmp75Thread(void *arg) { static msg_t PollTmp75Thread(void *arg) {
chRegSetThreadName("PollTmp75");
(void)arg; (void)arg;
systime_t time = chTimeNow();
while (TRUE) { while (TRUE) {
time += MS2ST(1001); // chThdSleepMilliseconds(rand() & 31);
chThdSleepMilliseconds(15);
/* Call reading function */ /* Call reading function */
request_temperature(); request_temperature();
chThdSleepUntil(time);
} }
return 0; return 0;
} }
/* MAX1236 polling thread */
static WORKING_AREA(PollMax1236ThreadWA, 128);
static msg_t PollMax1236Thread(void *arg) {
(void)arg;
systime_t time = chTimeNow();
/* Temperature polling thread */
static WORKING_AREA(PollFakeThreadWA, 128);
static msg_t PollFakeThread(void *arg) {
chRegSetThreadName("PollFake");
(void)arg;
while (TRUE) { while (TRUE) {
time += MS2ST(200); chThdSleepMilliseconds(16);
/* Call reading function */ /* Call reading function */
read_max1236(); request_fake();
chThdSleepUntil(time);
} }
return 0; return 0;
} }
static WORKING_AREA(PollAccelThreadWA, 128);
static msg_t PollAccelThread(void *arg) {
(void)arg;
systime_t time = chTimeNow();
while (TRUE) {
time += MS2ST(20);
request_acceleration_data();
chThdSleepUntil(time);
}
return 0;
}
/* /*
* Entry point, note, the main() function is already a thread in the system * Entry point, note, the main() function is already a thread in the system
* on entry. * on entry.
@ -102,8 +98,16 @@ int main(void) {
halInit(); halInit();
chSysInit(); chSysInit();
chThdSleepMilliseconds(200);
I2CInit_pns(); I2CInit_pns();
/* Create accelerometer thread */
chThdCreateStatic(PollAccelThreadWA,
sizeof(PollAccelThreadWA),
NORMALPRIO,
PollAccelThread,
NULL);
/* Create temperature thread */ /* Create temperature thread */
chThdCreateStatic(PollTmp75ThreadWA, chThdCreateStatic(PollTmp75ThreadWA,
sizeof(PollTmp75ThreadWA), sizeof(PollTmp75ThreadWA),
@ -111,24 +115,15 @@ int main(void) {
PollTmp75Thread, PollTmp75Thread,
NULL); NULL);
/* Create not responding thread */
/* Create max1236 thread */ chThdCreateStatic(PollFakeThreadWA,
chThdCreateStatic(PollMax1236ThreadWA, sizeof(PollFakeThreadWA),
sizeof(PollMax1236ThreadWA),
NORMALPRIO, NORMALPRIO,
PollMax1236Thread, PollFakeThread,
NULL);
/* Create accelerometer thread */
chThdCreateStatic(PollAccelThreadWA,
sizeof(PollAccelThreadWA),
HIGHPRIO,
PollAccelThread,
NULL); NULL);
/* Creates the blinker thread. */ /* Creates the blinker thread. */
chThdCreateStatic(BlinkWA, sizeof(BlinkWA), LOWPRIO, Blink, NULL); chThdCreateStatic(BlinkWA, sizeof(BlinkWA), HIGHPRIO, Blink, NULL);
/* main loop that do nothing */ /* main loop that do nothing */
while (TRUE) { while (TRUE) {

View File

@ -1,19 +0,0 @@
/*
* main.h
*
* Created on: 25.03.2011
* Author: barthess
*/
#ifndef MAIN_H_
#define MAIN_H_
// ãëîáàëüíûå ôëàãè
#define GET_FILTERED_RAW_GYRO TRUE
#define GET_FILTERED_RAW_ACCEL TRUE
#endif /* MAIN_H_ */

View File

@ -1,75 +0,0 @@
/**
* Maxim ADC has not so suitable default settings after startup.
* So we will create init function to tune this ADC.
*/
#include <stdlib.h>
#include "ch.h"
#include "hal.h"
#include "max1236.h"
#define max1236_addr 0b0110100
/* Data buffers */
static i2cblock_t max1236_rx_data[MAX1236_RX_DEPTH];
static i2cblock_t max1236_tx_data[MAX1236_TX_DEPTH];
/* ADC results */
static uint16_t ch1 = 0, ch2 = 0, ch3 = 0, ch4 = 0;
/* Error trap */
static void i2c_max1236_error_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){
(void)i2cscfg;
int status = 0;
status = i2cp->id_i2c->SR1;
while(TRUE);
}
/* This callback raise up when transfer finished */
static void i2c_max1236_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){
(void)*i2cp;
(void)*i2cscfg;
/* get ADC data */
}
/* ADC maxim MAX1236 config */
static const I2CSlaveConfig max1236 = {
i2c_max1236_cb,
i2c_max1236_error_cb,
};
/**
* Initilization routine. See datasheet on page 13 to understand
* how to initialize ADC.
*/
void init_max1236(void){
/* this data we must send via IC to setup ADC */
max1236_tx_data[0] = 0b10000011; /* config register content. Consult datasheet */
max1236_tx_data[1] = 0b00000111; /* config register content. Consult datasheet */
/* transmit out 2 bytes */
i2cAcquireBus(&I2CD2);
i2cMasterTransmit(&I2CD2, &max1236, max1236_addr, max1236_tx_data, 2, max1236_rx_data, 0);
i2cReleaseBus(&I2CD2);
}
/* Now simply read 8 bytes to get all 4 ADC channels */
void read_max1236(void){
i2cAcquireBus(&I2CD2);
i2cMasterReceive(&I2CD2, &max1236, max1236_addr, max1236_rx_data, 8);
i2cReleaseBus(&I2CD2);
ch1 = ((max1236_rx_data[0] & 0xF) << 8) + max1236_rx_data[1];
ch2 = ((max1236_rx_data[2] & 0xF) << 8) + max1236_rx_data[3];
ch3 = ((max1236_rx_data[4] & 0xF) << 8) + max1236_rx_data[5];
ch4 = ((max1236_rx_data[6] & 0xF) << 8) + max1236_rx_data[7];
}

View File

@ -1,14 +0,0 @@
#include "ch.h"
#ifndef MAX1236_H_
#define MAX1236_H_
#define MAX1236_RX_DEPTH 8
#define MAX1236_TX_DEPTH 2
void init_max1236(void);
void read_max1236(void);
#endif /* MAX1236_H_ */

View File

@ -47,7 +47,7 @@
/* /*
* ADC driver system settings. * ADC driver system settings.
*/ */
#define STM32_ADC_USE_ADC1 TRUE #define STM32_ADC_USE_ADC1 FALSE
#define STM32_ADC_ADC1_DMA_PRIORITY 3 #define STM32_ADC_ADC1_DMA_PRIORITY 3
#define STM32_ADC_ADC1_IRQ_PRIORITY 5 #define STM32_ADC_ADC1_IRQ_PRIORITY 5
#define STM32_ADC_ADC1_DMA_ERROR_HOOK() chSysHalt() #define STM32_ADC_ADC1_DMA_ERROR_HOOK() chSysHalt()
@ -122,8 +122,8 @@
/* /*
* SERIAL driver system settings. * SERIAL driver system settings.
*/ */
#define STM32_SERIAL_USE_USART1 TRUE #define STM32_SERIAL_USE_USART1 FALSE
#define STM32_SERIAL_USE_USART2 TRUE #define STM32_SERIAL_USE_USART2 FALSE
#define STM32_SERIAL_USE_USART3 FALSE #define STM32_SERIAL_USE_USART3 FALSE
#define STM32_SERIAL_USE_UART4 FALSE #define STM32_SERIAL_USE_UART4 FALSE
#define STM32_SERIAL_USE_UART5 FALSE #define STM32_SERIAL_USE_UART5 FALSE
@ -138,8 +138,8 @@
/* /*
* SPI driver system settings. * SPI driver system settings.
*/ */
#define STM32_SPI_USE_SPI1 TRUE #define STM32_SPI_USE_SPI1 FALSE
#define STM32_SPI_USE_SPI2 TRUE #define STM32_SPI_USE_SPI2 FALSE
#define STM32_SPI_USE_SPI3 FALSE #define STM32_SPI_USE_SPI3 FALSE
#define STM32_SPI_SPI1_DMA_PRIORITY 1 #define STM32_SPI_SPI1_DMA_PRIORITY 1
#define STM32_SPI_SPI2_DMA_PRIORITY 1 #define STM32_SPI_SPI2_DMA_PRIORITY 1
@ -167,25 +167,18 @@
* I2C driver system settings. * I2C driver system settings.
*/ */
#define STM32_I2C_USE_I2C1 TRUE #define STM32_I2C_USE_I2C1 TRUE
#define STM32_I2C_USE_I2C2 TRUE #define STM32_I2C_USE_I2C2 FALSE
#define STM32_I2C_I2C1_IRQ_PRIORITY 10 #define STM32_I2C_I2C1_IRQ_PRIORITY 10
#define STM32_I2C_I2C2_IRQ_PRIORITY 10 #define STM32_I2C_I2C2_IRQ_PRIORITY 10
#define STM32_I2C_I2C1_DMA_PRIORITY 4 #define STM32_I2C_I2C1_DMA_PRIORITY 1
#define STM32_I2C_I2C2_DMA_PRIORITY 4 #define STM32_I2C_I2C2_DMA_PRIORITY 1
#define STM32_I2C_I2C1_DMA_ERROR_HOOK() chSysHalt() #define STM32_I2C_I2C1_DMA_ERROR_HOOK() chSysHalt()
#define STM32_I2C_I2C2_DMA_ERROR_HOOK() chSysHalt() #define STM32_I2C_I2C2_DMA_ERROR_HOOK() chSysHalt()
/* I2C1 */
#define STM32_I2C_I2C1_USE_GPT_TIM GPTD1
#define STM32_I2C_I2C1_USE_POLLING_WAIT TRUE
/* I2C2 */
#define STM32_I2C_I2C2_USE_GPT_TIM GPTD2
#define STM32_I2C_I2C2_USE_POLLING_WAIT TRUE
/* /*
* USB driver system settings. * USB driver system settings.
*/ */
#define STM32_USB_USE_USB1 TRUE #define STM32_USB_USE_USB1 FALSE
#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE #define STM32_USB_LOW_POWER_ON_SUSPEND FALSE
#define STM32_USB_USB1_HP_IRQ_PRIORITY 6 #define STM32_USB_USB1_HP_IRQ_PRIORITY 6
#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 #define STM32_USB_USB1_LP_IRQ_PRIORITY 14

View File

@ -1,3 +1,23 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** /**
* TMP75 is most simple I2C device in our case. It is already useful with * TMP75 is most simple I2C device in our case. It is already useful with
* default settings after powerup. * default settings after powerup.
@ -13,40 +33,25 @@
/* input buffer */ /* input buffer */
static i2cblock_t tmp75_rx_data[TMP75_RX_DEPTH]; static uint8_t tmp75_rx_data[TMP75_RX_DEPTH];
/* temperature value */ /* temperature value */
static int16_t temperature = 0; static int16_t temperature = 0;
/* Simple error trap */
static void i2c_tmp75_error_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){
(void)i2cscfg;
int status = 0;
status = i2cp->id_i2c->SR1;
while(TRUE);
}
/* This callback raise up when transfer finished */
static void i2c_tmp75_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){
(void)*i2cp;
(void)*i2cscfg;
/* store temperature value */
}
/* Fill TMP75 config. */
static const I2CSlaveConfig tmp75 = {
i2c_tmp75_cb,
i2c_tmp75_error_cb,
};
#define tmp75_addr 0b1001000 #define tmp75_addr 0b1001000
/* This is main function. */ /* This is main function. */
void request_temperature(void){ void request_temperature(void){
i2cAcquireBus(&I2CD2); int16_t t_int = 0, t_frac = 0;
i2cMasterReceive(&I2CD2, &tmp75, tmp75_addr, tmp75_rx_data, 2);
i2cReleaseBus(&I2CD2); i2cAcquireBus(&I2CD1);
temperature = (tmp75_rx_data[0] << 8) + tmp75_rx_data[1]; i2cMasterReceive(&I2CD1, tmp75_addr, tmp75_rx_data, 2);
i2cReleaseBus(&I2CD1);
t_int = tmp75_rx_data[0] * 100;
t_frac = (tmp75_rx_data[1] * 100) >> 8;
temperature = t_int + t_frac;
} }

View File

@ -1,3 +1,23 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TMP75_H_ #ifndef TMP75_H_
#define TMP75_H_ #define TMP75_H_