From a1b70ed3012d499f25ba94ee2c53f1ce2c89809f Mon Sep 17 00:00:00 2001 From: barthess Date: Tue, 25 Jan 2011 18:53:36 +0000 Subject: [PATCH 02/92] test commit git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2683 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- Copy of todo.txt | 114 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 Copy of todo.txt diff --git a/Copy of todo.txt b/Copy of todo.txt new file mode 100644 index 000000000..29d13f84d --- /dev/null +++ b/Copy of todo.txt @@ -0,0 +1,114 @@ +Status: +- = Planned. +X = In progress, some work done. +* = Done. +? = Not sure if worth the effort or useful at all. +N = Decided against. + +Within 2.1.x +* Binary Semaphores on top of Counting Semaphores. +* Direct unbuffered UART driver. + Requirements: low level, callbacks, DMA capable, state machines buildable + on top, support data words greater than 8 bits, callback for + "last byte transmitted (RS485)", simple implementation, + verifiable. +* Rework STM32 drivers to use friendly IRQ names and centralized DMA macros. +* I-class functions for the ADC/PWM drivers. +* All the device driver structures must have a fields extension macro and + initializer hook. +* All the device driver callbacks must have the driver pointer as first + parameter. +* Change the SPI driver to be able to work asynchronously using callbacks, + keep the synchronous APIs available as option. +* Add an optional spiPolledExchange() API to the SPI driver model. +* Update the STM32 SPI driver to the new model. +* Make the ADC driver have the same synchronous/asynchronous API of the + new SPI driver model. +* General HAL improvements. +* Update the AT91SAM7 SPI driver (DMA and/or ISR). + * Verify the FatFs demo on both the AT91SAM7X and AT91SAM7S. +* Update the LPC214x SPI driver (ISR). + * Verify the LPC214x FatFs demo. +* Write a new SPI driver for LPC1xxx (ISR)(it should be very close to the + LPC214x one). +N Evaluate if to add a synchronous API to the UART driver, eventually do so. +* Global documentation reorganization in order to allow both separate documents + and the usual blob document. +* PDF generation from the documentation system (only separate documents, not + the blob). +* Automatic compilation and upload of the various documents on the web site + (doxygen + rsync). +* New STM8S/A SPI driver. +* Reorganization of the STM32 family port-level support. +* Remove preprocessor directives from the assembler files and restore the + RIDE7 build files in the STM32 demo. +* Move dynamic APIs into a separate source file. +* Improved support in the STM32 HAL support for multiple sub-families. Do + not check for the family in the various drivers but simply check for + switch macros like STM32_HAS_USART3, STM32_HAS_SPI3. This what the + drivers will not need changes when adding new sub-families. +* STM8L official HAL support, it will have to be separated from the STM8S/STM8A + HAL because it is very different. + * Shared ISR management. + * STM8L-Discovery demo. +* Add the STM32F100 (Value Line) sub-family to the official STM32 HAL support. + * STM32VL-Discovery demo. +* Remove the PAL default configuration from the various hal_lld.c and move + them into board.c files, this will remove an ugly dependency. +* Realign the STM8 port to the new STM8L one as options, naming conventions + and general solutions. +* Support for more compilers (IAR, Keil, ARMCMx only initially). +X Support for not just Makefiles (Ride7, Crossworks etc). +* IAR port for Cortex-Mx, add demos for all the supported families. +* Keil port for Cortex-Mx, add demos for all the supported families. +* Change the serial drivers to have a single event source instead of three. + Add Rx and Tx to the existing flags mechanism. Move up the flags handling in + the superclass. +X Except for the above, bug fixing only until the 2.2.0 release. + +Within 2.3.x (hopefully) +- Resist doing more changes and optimizations to the kernel. +? Make thread functions return void. +- Introduce a "THREAD" function prefix in order to hide compiler-specific + optimizations for thread functions. +X Add an USB abstract device driver class. +X USB driver implementation for STM32F103/STM32F102. +X Add a Serial over USB generic device driver implementing a USB Communication + Device Class and offering a Serial-like interface to the applications. +- Add a switch to enable/disable the priority inheritance algorithm in mutexes. +X File System infrastructure. + - Official FatFs wrapper using the new infrastructure, dedicated test suite. +X Transactional flash file system implementation. +X I2C device driver class support and at least one implementation. +- Serial over UART complex driver driver, evaluate from the performance + results if to make obsolete the current dedicated Serial driver. +X Shared DMA channels support in the STM32/STM8L HALs. +X New device driver models: Clock, Systick, RTC, WDG, DAC, Power Monitor. +- MAC driver for STM32F107 (hardware missing). +- Device drivers for STM8/STM8L (ADC, PWM, bring them on par with STM32). +- Batch testing of the ARM7/ARMCMx port using OpenOCD, with reports. +- Debug-related features and tools. +- Add a *very simple* ADC API for single one shot sampling (implement it as + an injected conversion on the STM32). +- Update C++ wrapper (Heap, Pools, Mailboxes and any new feature). +- Threads Pools manager in the library. + +Later but within 2.x.x +- Dedicated TCP/IP stack. +? ISO7816 driver over UART driver, both reader and card side (hardware + missing). +- Merge the Coldfire branch in mainline (hardware missing). +- Merge the H8S branch in mainline (hardware missing). +- MAC driver revision in order to support copy-less operations, this will + require changes to lwIP or a new TCP/IP stack however. + +Ideas for 3.x.x: +- MMU/MPU support. +- High resolution timers and tickless kernel. +- Multicore support. + +Side projects: +X ChibiOS Wizard, UML modeling and ChibiOS applications code and + documentation generator. +? File System +- Visual debugger/monitor interfaced through OpenOCD. From 063c6e138d59529b911235fe537bdefe60e0cfb8 Mon Sep 17 00:00:00 2001 From: barthess Date: Tue, 25 Jan 2011 18:59:18 +0000 Subject: [PATCH 03/92] Initial commit of I2C driver code git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2684 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- Copy of todo.txt | 114 ---------- os/hal/include/i2c.h | 16 +- os/hal/platforms/STM32/i2c_lld.c | 343 +++++++++++++++++++++++++++++ os/hal/platforms/STM32/i2c_lld.h | 234 ++++++++++++++++++++ os/hal/platforms/STM32/platform.mk | 3 +- os/hal/src/i2c.c | 163 +++++++++----- 6 files changed, 689 insertions(+), 184 deletions(-) delete mode 100644 Copy of todo.txt create mode 100644 os/hal/platforms/STM32/i2c_lld.c create mode 100644 os/hal/platforms/STM32/i2c_lld.h diff --git a/Copy of todo.txt b/Copy of todo.txt deleted file mode 100644 index 29d13f84d..000000000 --- a/Copy of todo.txt +++ /dev/null @@ -1,114 +0,0 @@ -Status: -- = Planned. -X = In progress, some work done. -* = Done. -? = Not sure if worth the effort or useful at all. -N = Decided against. - -Within 2.1.x -* Binary Semaphores on top of Counting Semaphores. -* Direct unbuffered UART driver. - Requirements: low level, callbacks, DMA capable, state machines buildable - on top, support data words greater than 8 bits, callback for - "last byte transmitted (RS485)", simple implementation, - verifiable. -* Rework STM32 drivers to use friendly IRQ names and centralized DMA macros. -* I-class functions for the ADC/PWM drivers. -* All the device driver structures must have a fields extension macro and - initializer hook. -* All the device driver callbacks must have the driver pointer as first - parameter. -* Change the SPI driver to be able to work asynchronously using callbacks, - keep the synchronous APIs available as option. -* Add an optional spiPolledExchange() API to the SPI driver model. -* Update the STM32 SPI driver to the new model. -* Make the ADC driver have the same synchronous/asynchronous API of the - new SPI driver model. -* General HAL improvements. -* Update the AT91SAM7 SPI driver (DMA and/or ISR). - * Verify the FatFs demo on both the AT91SAM7X and AT91SAM7S. -* Update the LPC214x SPI driver (ISR). - * Verify the LPC214x FatFs demo. -* Write a new SPI driver for LPC1xxx (ISR)(it should be very close to the - LPC214x one). -N Evaluate if to add a synchronous API to the UART driver, eventually do so. -* Global documentation reorganization in order to allow both separate documents - and the usual blob document. -* PDF generation from the documentation system (only separate documents, not - the blob). -* Automatic compilation and upload of the various documents on the web site - (doxygen + rsync). -* New STM8S/A SPI driver. -* Reorganization of the STM32 family port-level support. -* Remove preprocessor directives from the assembler files and restore the - RIDE7 build files in the STM32 demo. -* Move dynamic APIs into a separate source file. -* Improved support in the STM32 HAL support for multiple sub-families. Do - not check for the family in the various drivers but simply check for - switch macros like STM32_HAS_USART3, STM32_HAS_SPI3. This what the - drivers will not need changes when adding new sub-families. -* STM8L official HAL support, it will have to be separated from the STM8S/STM8A - HAL because it is very different. - * Shared ISR management. - * STM8L-Discovery demo. -* Add the STM32F100 (Value Line) sub-family to the official STM32 HAL support. - * STM32VL-Discovery demo. -* Remove the PAL default configuration from the various hal_lld.c and move - them into board.c files, this will remove an ugly dependency. -* Realign the STM8 port to the new STM8L one as options, naming conventions - and general solutions. -* Support for more compilers (IAR, Keil, ARMCMx only initially). -X Support for not just Makefiles (Ride7, Crossworks etc). -* IAR port for Cortex-Mx, add demos for all the supported families. -* Keil port for Cortex-Mx, add demos for all the supported families. -* Change the serial drivers to have a single event source instead of three. - Add Rx and Tx to the existing flags mechanism. Move up the flags handling in - the superclass. -X Except for the above, bug fixing only until the 2.2.0 release. - -Within 2.3.x (hopefully) -- Resist doing more changes and optimizations to the kernel. -? Make thread functions return void. -- Introduce a "THREAD" function prefix in order to hide compiler-specific - optimizations for thread functions. -X Add an USB abstract device driver class. -X USB driver implementation for STM32F103/STM32F102. -X Add a Serial over USB generic device driver implementing a USB Communication - Device Class and offering a Serial-like interface to the applications. -- Add a switch to enable/disable the priority inheritance algorithm in mutexes. -X File System infrastructure. - - Official FatFs wrapper using the new infrastructure, dedicated test suite. -X Transactional flash file system implementation. -X I2C device driver class support and at least one implementation. -- Serial over UART complex driver driver, evaluate from the performance - results if to make obsolete the current dedicated Serial driver. -X Shared DMA channels support in the STM32/STM8L HALs. -X New device driver models: Clock, Systick, RTC, WDG, DAC, Power Monitor. -- MAC driver for STM32F107 (hardware missing). -- Device drivers for STM8/STM8L (ADC, PWM, bring them on par with STM32). -- Batch testing of the ARM7/ARMCMx port using OpenOCD, with reports. -- Debug-related features and tools. -- Add a *very simple* ADC API for single one shot sampling (implement it as - an injected conversion on the STM32). -- Update C++ wrapper (Heap, Pools, Mailboxes and any new feature). -- Threads Pools manager in the library. - -Later but within 2.x.x -- Dedicated TCP/IP stack. -? ISO7816 driver over UART driver, both reader and card side (hardware - missing). -- Merge the Coldfire branch in mainline (hardware missing). -- Merge the H8S branch in mainline (hardware missing). -- MAC driver revision in order to support copy-less operations, this will - require changes to lwIP or a new TCP/IP stack however. - -Ideas for 3.x.x: -- MMU/MPU support. -- High resolution timers and tickless kernel. -- Multicore support. - -Side projects: -X ChibiOS Wizard, UML modeling and ChibiOS applications code and - documentation generator. -? File System -- Visual debugger/monitor interfaced through OpenOCD. diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 01d3739e8..273c9f57a 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -34,6 +34,7 @@ /* Driver constants. */ /*===========================================================================*/ + /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ @@ -112,23 +113,20 @@ typedef enum { /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ - #ifdef __cplusplus extern "C" { #endif void i2cInit(void); void i2cObjectInit(I2CDriver *i2cp); - void i2cStart(I2CDriver *i2cp, const I2CConfig *config); + void i2cStart(I2CDriver *i2cp, I2CConfig *config); void i2cStop(I2CDriver *i2cp); - void i2cMasterStartI(I2CDriver *i2cp, - uint16_t header, - i2ccallback_t callback); + void i2cMasterTransmit(I2CDriver *i2cp, uint8_t slave_addr1, uint8_t slave_addr2, size_t n, const void *txbuf); + void i2cMasterReceive(I2CDriver *i2cp, uint8_t slave_addr1, uint8_t slave_addr2, size_t n, void *rxbuf); + void i2cMasterStartI(I2CDriver *i2cp,uint16_t header,i2ccallback_t callback); void i2cMasterStopI(I2CDriver *i2cp, i2ccallback_t callback); void i2cMasterRestartI(I2CDriver *i2cp, i2ccallback_t callback); - void i2cMasterTransmitI(I2CDriver *i2cp, size_t n, const uint8_t *txbuf, - i2ccallback_t callback); - void i2cMasterReceiveI(I2CDriver *i2cp, size_t n, uint8_t *rxbuf, - i2ccallback_t callback); + void i2cMasterTransmitI(I2CDriver *i2cp, size_t n, const uint8_t *txbuf, i2ccallback_t callback); + void i2cMasterReceiveI(I2CDriver *i2cp, size_t n, uint8_t *rxbuf, i2ccallback_t callback); #if I2C_USE_MUTUAL_EXCLUSION void i2cAcquireBus(I2CDriver *i2cp); void i2cReleaseBus(I2CDriver *i2cp); diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c new file mode 100644 index 000000000..85ca16b2f --- /dev/null +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -0,0 +1,343 @@ +/** + * @file STM32/i2c_lld.c + * @brief STM32 I2C subsystem low level driver source. Slave mode not implemented. + * @addtogroup STM32_I2C + * @{ + */ + +#include "ch.h" +#include "hal.h" +#include "i2c_lld.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief I2C1 driver identifier.*/ +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +I2CDriver I2CD1; +#endif + +/** @brief I2C2 driver identifier.*/ +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +I2CDriver I2CD2; +#endif + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief TODO: Status bits translation. + * + * @param[in] sr USART SR register value + * + * @return The error flags. + */ +static i2cflags_t translate_errors(uint16_t sr) { + i2cflags_t sts = 0; + + if (sr & USART_SR_ORE) + sts |= UART_OVERRUN_ERROR; + if (sr & USART_SR_PE) + sts |= UART_PARITY_ERROR; + if (sr & USART_SR_FE) + sts |= UART_FRAMING_ERROR; + if (sr & USART_SR_NE) + sts |= UART_NOISE_ERROR; + if (sr & USART_SR_LBD) + sts |= UART_BREAK_DETECTED; + return sts; +} + + + + + + + +static void i2c_serve_event_interrupt(I2CDriver *i2cp) { + +} + +static void i2c_serve_error_interrupt(I2CDriver *i2cp) { + +} + +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +/** + * @brief I2C1 event interrupt handler. + */ +CH_IRQ_HANDLER(VectorBC) { + + CH_IRQ_PROLOGUE(); + i2c_serve_event_interrupt(&I2CD1); + CH_IRQ_EPILOGUE(); +} + +/** + * @brief I2C1 error interrupt handler. + */ +CH_IRQ_HANDLER(VectorC0) { + + CH_IRQ_PROLOGUE(); + i2c_serve_error_interrupt(&I2CD1); + CH_IRQ_EPILOGUE(); +} +#endif + +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +/** + * @brief I2C2 event interrupt handler. + */ +CH_IRQ_HANDLER(VectorC4) { + + CH_IRQ_PROLOGUE(); + i2c_serve_event_interrupt(&I2CD2); + CH_IRQ_EPILOGUE(); +} + +/** + * @brief I2C2 error interrupt handler. + */ +CH_IRQ_HANDLER(VectorC8) { + + CH_IRQ_PROLOGUE(); + i2c_serve_error_interrupt(&I2CD2); + CH_IRQ_EPILOGUE(); +} +#endif + +/** + * @brief Low level I2C driver initialization. + */ +void i2c_lld_init(void) { + +#if STM32_I2C_USE_I2C1 + RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; // reset I2C 1 + RCC->APB1RSTR = 0; + i2cObjectInit(&I2CD1); + I2CD1.id_i2c = I2C1; +#endif + +#if STM32_I2C_USE_I2C2 + RCC->APB1RSTR = RCC_APB1RSTR_I2C2RST; // reset I2C 2 + RCC->APB1RSTR = 0; + i2cObjectInit(&I2CD2); + I2CD2.id_i2c = I2C2; +#endif +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2c_lld_start(I2CDriver *i2cp) { + + /* If in stopped state then enables the I2C clock.*/ + if (i2cp->id_state == I2C_STOP) { +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + NVICEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); + NVICEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); + RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // I2C 1 clock enable + } +#endif +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + NVICEnableVector(I2C2_EV_IRQn, STM32_I2C2_IRQ_PRIORITY); + NVICEnableVector(I2C2_ER_IRQn, STM32_I2C2_IRQ_PRIORITY); + RCC->APB1ENR |= RCC_APB1ENR_I2C2EN; // I2C 2 clock enable + } +#endif + } + + /* I2C setup.*/ + i2cp->id_i2c->CR1 = I2C_CR1_SWRST; // reset i2c peripherial + i2cp->id_i2c->CR1 = 0; + + i2cp->id_i2c->CR1 = i2cp->id_config->i2cc_cr1; + i2cp->id_i2c->CR2 = i2cp->id_config->i2cc_cr2 | + //I2C_CR2_ITERREN | + //I2C_CR2_ITEVTEN | + //I2C_CR2_ITBUFEN | + 36; //TODO: replace this by macro calculation + /* TODO: + * 1. macro timing calculator + * 2. parameter checker + * 3. definitions in halconf.h: i2c-freq, i2c_mode, etc + * 4. trise time calculator/checker + */ + i2cp->id_i2c->CCR = i2cp->id_config->i2cc_ccr | 180; + i2cp->id_i2c->TRISE = i2cp->id_config->i2cc_trise | 37; + i2cp->id_i2c->CR1 |= 1; // enable interface +} + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2c_lld_stop(I2CDriver *i2cp) { + + /* If in ready state then disables the I2C clock.*/ + if (i2cp->id_state == I2C_READY) { +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + NVICDisableVector(I2C1_EV_IRQn); + NVICDisableVector(I2C1_ER_IRQn); + RCC->APB1ENR &= ~RCC_APB1ENR_I2C1EN; + } +#endif +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + NVICDisableVector(I2C2_EV_IRQn); + NVICDisableVector(I2C2_ER_IRQn); + RCC->APB1ENR &= ~RCC_APB1ENR_I2C2EN; + } +#endif + } + i2cp->id_state = I2C_STOP; +} + +/** + * @brief Transmits data ever the I2C bus as master. + * TODO:@details + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object + * @param[in] restart bool. If TRUE then generate restart condition insted of stop + */ +void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart) { + //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hylevel API + + chSysLock(); + + int i = 0; + + i2cp->id_slave_config = i2cscfg; + i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate start condition + while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)){ + i++; // wait start bit + } + i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | I2C_WRITE; // write slave addres in DR + while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){ + i++; // wait Address sent + } + i = i2cp->id_i2c->SR2; // TODO: check is it need to read this register for I2C to proper functionality + i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit + + // now write data byte by byte in DR register + uint32_t n = 0; + for (n = 0; n < i2cp->id_slave_config->txbytes; n++){ + i2cp->id_i2c->DR = i2cscfg->txbuf[n]; + while (!(i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ + i++; + } + } + + while (!(i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ + i++; + } + + if (restart){ + i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate restart condition + } + else i2cp->id_i2c->CR1 |= I2C_CR1_STOP; // generate stop condition + + chSysUnlock(); +} + +/** + * @brief Receives data from the I2C bus. + * @details To receive data from I2C slave you must sent them some + * control bytes first. Driver takes this data from @p I2CSlaveConfig + * structure (*txbuf and txbytes fields), so you must manually + * fill this fields before invocating receiving function + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object + */ +void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { + + chSysLock(); + + i2cp->id_slave_config = i2cscfg; + + uint16_t i = 0; + uint16_t tmp = 0; + + // send control secuence to slave + //i2c_lld_master_transmit(i2cp, i2cscfg, TRUE); + + + + + + i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate start condition + while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)){ + i++; // wait start bit + } + i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | I2C_WRITE; // write slave addres in DR + while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){ + i++; // wait Address sent + } + i = i2cp->id_i2c->SR2; // TODO: check is it need to read this register for I2C to proper functionality + i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit + + // now write data byte by byte in DR register + uint32_t n = 0; + for (n = 0; n < i2cp->id_slave_config->txbytes; n++){ + i2cp->id_i2c->DR = i2cscfg->txbuf[n]; + while (!(i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ + i++; + } + } + + while (!(i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ + i++; + } + + i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate restart condition + while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)){ + i++; // wait start bit + } + + + + + // send slave addres with read-bit + i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | I2C_READ; + while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){ + i++; // wait Address sent + } + i = i2cp->id_i2c->SR2; // TODO: check is it need to read this register for I2C to proper functionality + i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit + + // set ACK bit + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; + + // collect data from slave + for (i = 0; i < i2cp->id_slave_config->rxbytes; i++){ + if ((i2cp->id_slave_config->rxbytes - i) == 1){ // TODO: is it better <= in place of == ? + // clear ACK bit for automatically send NACK + i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);} + while (!(i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ + tmp++; + } + i2cp->id_slave_config->rxbuf[i] = i2cp->id_i2c->DR; + } + // generate STOP + i2cp->id_i2c->CR1 |= I2C_CR1_STOP; + + chSysUnlock(); +} + +#endif // HAL_USE_I2C diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h new file mode 100644 index 000000000..427e72896 --- /dev/null +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -0,0 +1,234 @@ +/** + * @file STM32/i2c_lld.h + * @brief STM32 I2C subsystem low level driver header. + * @addtogroup STM32_I2C + * @{ + */ + +#ifndef _I2C_LLD_H_ +#define _I2C_LLD_H_ + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @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 No pending conditions.*/ +#define I2C_NO_ERROR 0 +/*@brief external Stop or Start condition during an address or a data transfer*/ +#define I2C_BUS_ERROR 1 +/** @brief */ +#define I2C_ARBITRATION_LOSS 2 +/** @brief */ +#define I2C_ACK_FAIL 4 +/** @brief */ +#define I2C_OVERRUN_UNDERRUN 8 +/** @brief */ +#define I2C_PEC_ERROR 16 +/** @brief */ +#define I2C_TIMEOUT 32 +/** @brief */ +#define I2C_SMBUS_ALERT 64 + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief I2C notification callback type. + * + * @param[in] i2cp FIXME: pointer to the @p I2CDriver object triggering the + * callback + */ +typedef void (*i2ccallback_t)(void); + +/** + * @brief I2C error notification callback type. + * + * @param[in] i2cp FIXME: pointer to the @p I2CDriver object triggering the + * callback + */ +typedef void (*i2cerrorcallback_t)(void); + +/** + * @brief Driver configuration structure. + */ +typedef struct { + /** + * @brief I2C initialization data. + */ + uint16_t i2cc_cr1; + uint16_t i2cc_cr2; + uint16_t i2cc_ccr; + uint16_t i2cc_trise; + +} I2CConfig; + + +/** + * @brief TODO: + */ +typedef uint32_t i2cflags_t; + +/** + * @brief TODO: + */ +typedef uint8_t i2cblock_t; + + +/** + * @brief Structure representing an I2C slave configuration. + * @details Each slave has its own data buffers, adress, and error flags. + */ +typedef struct { + /** + * @brief Callback pointer. + * @note TODO: I don't know, when this callback is inwoked + * @p NULL then the callback is disabled. + */ + i2ccallback_t id_callback; + /** + * @brief Callback pointer. + * @note TODO: I don't know, when this callback is inwoked + * @p NULL then the callback is disabled. + */ + i2cerrorcallback_t id_errcallback; + + i2cblock_t *rxbuf; // pointer to buffer + size_t rxdepth;// depth of buffer + size_t rxbytes;// count of bytes to sent in one sending + + i2cblock_t *txbuf; + size_t txdepth; + size_t txbytes; + + uint8_t slave_addr1; // 7-bit address of the slave + uint8_t slave_addr2; // used in 10-bit address mode + + uint16_t error_flags; + +}I2CSlaveConfig; + + + +/** + * @brief Structure representing an I2C driver. + */ +typedef struct { + /** + * @brief Driver state. + */ + i2cstate_t id_state; +#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. + */ + I2CConfig *id_config; + /** + * @brief Current slave configuration data. + */ + I2CSlaveConfig *id_slave_config; + + /* End of the mandatory fields.*/ + /** + * @brief Thread waiting for I/O completion. + */ + Thread *id_thread; + /** + * @brief Pointer to the I2Cx registers block. + */ + I2C_TypeDef *id_i2c; + +} I2CDriver; + + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* 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_start(I2CDriver *i2cp); +void i2c_lld_stop(I2CDriver *i2cp); +void i2c_lld_master_start(I2CDriver *i2cp, uint16_t header); +void i2c_lld_master_stop(I2CDriver *i2cp); +void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); +void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); +//static i2cflags_t translate_errors(uint16_t sr); + +#ifdef __cplusplus +} +#endif +/** @endcond*/ + +#endif // CH_HAL_USE_I2C + +#endif // _I2C_LLD_H_ diff --git a/os/hal/platforms/STM32/platform.mk b/os/hal/platforms/STM32/platform.mk index 35e732116..35717687f 100644 --- a/os/hal/platforms/STM32/platform.mk +++ b/os/hal/platforms/STM32/platform.mk @@ -7,7 +7,8 @@ PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32/hal_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/serial_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/spi_lld.c \ ${CHIBIOS}/os/hal/platforms/STM32/uart_lld.c \ - ${CHIBIOS}/os/hal/platforms/STM32/stm32_dma.c + ${CHIBIOS}/os/hal/platforms/STM32/stm32_dma.c \ + ${CHIBIOS}/os/hal/platforms/STM32/i2c_lld.c # Required include directories PLATFORMINC = ${CHIBIOS}/os/hal/platforms/STM32 diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 2b5971b6f..273bb5933 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -54,7 +54,6 @@ * @init */ void i2cInit(void) { - i2c_lld_init(); } @@ -67,8 +66,9 @@ void i2cInit(void) { */ void i2cObjectInit(I2CDriver *i2cp) { - i2cp->i2c_state = I2C_STOP; - i2cp->i2c_config = NULL; + i2cp->id_state = I2C_STOP; + i2cp->id_config = NULL; + i2cp->id_slave_config = NULL; #if defined(I2C_DRIVER_EXT_INIT_HOOK) I2C_DRIVER_EXT_INIT_HOOK(i2cp); #endif @@ -82,17 +82,17 @@ void i2cObjectInit(I2CDriver *i2cp) { * * @api */ -void i2cStart(I2CDriver *i2cp, const I2CConfig *config) { +void i2cStart(I2CDriver *i2cp, I2CConfig *config) { chDbgCheck((i2cp != NULL) && (config != NULL), "i2cStart"); chSysLock(); - chDbgAssert((i2cp->i2c_state == I2C_STOP) || (i2cp->i2c_state == I2C_READY), + chDbgAssert((i2cp->id_state == I2C_STOP) || (i2cp->id_state == I2C_READY), "i2cStart(), #1", "invalid state"); - i2cp->i2c_config = config; + i2cp->id_config = config; i2c_lld_start(i2cp); - i2cp->i2c_state = I2C_READY; + i2cp->id_state = I2C_READY; chSysUnlock(); } @@ -108,13 +108,56 @@ void i2cStop(I2CDriver *i2cp) { chDbgCheck(i2cp != NULL, "i2cStop"); chSysLock(); - chDbgAssert((i2cp->i2c_state == I2C_STOP) || (i2cp->i2c_state == I2C_READY), + chDbgAssert((i2cp->id_state == I2C_STOP) || (i2cp->id_state == I2C_READY), "i2cStop(), #1", "invalid state"); i2c_lld_stop(i2cp); - i2cp->i2c_state = I2C_STOP; + i2cp->id_state = I2C_STOP; chSysUnlock(); } +/** + * @brief Sends data ever the I2C bus. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] slave_addr1 7-bit address of the slave + * @param[in] slave_addr1 used in 10-bit address mode + * @param[in] n number of words to send + * @param[in] txbuf the pointer to the transmit buffer + * + */ +void i2cMasterTransmit(I2CDriver *i2cp, uint8_t slave_addr1, uint8_t slave_addr2, size_t n, const void *txbuf) { + + chDbgCheck((i2cp != NULL) && (n > 0) && (txbuf != NULL), + "i2cSend"); + chDbgAssert(i2cp->id_state == I2C_READY, + "i2cSend(), #1", + "not active"); + + //i2c_lld_master_transmit(i2cp, slave_addr1, slave_addr2, n, txbuf); + +} + +/** + * @brief Receives data from the I2C bus. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] slave_addr1 7-bit address of the slave + * @param[in] slave_addr1 used in 10-bit address mode + * @param[in] n number of words to receive + * @param[out] rxbuf the pointer to the receive buffer + * + */ +void i2cMasterReceive(I2CDriver *i2cp, uint8_t slave_addr1, uint8_t slave_addr2, size_t n, void *rxbuf) { + + chDbgCheck((i2cp != NULL) && (n > 0) && (rxbuf != NULL), + "i2cReceive"); + chDbgAssert(i2cp->id_state == I2C_READY, + "i2cReceive(), #1", + "not active"); + + //i2c_lld_master_receive(i2cp, slave_addr1, slave_addr2, n, rxbuf); + +} /** * @brief Initiates a master bus transaction. @@ -127,17 +170,17 @@ void i2cStop(I2CDriver *i2cp) { * * @iclass */ -void i2cMasterStartI(I2CDriver *i2cp, - uint16_t header, - i2ccallback_t callback) { - - chDbgCheck((i2cp != NULL) && (callback != NULL), "i2cMasterStartI"); - chDbgAssert(i2cp->i2c_state == I2C_READY, - "i2cMasterStartI(), #1", "invalid state"); - - i2cp->id_callback = callback; - i2c_lld_master_start(i2cp, header); -} +//void i2cMasterStartI(I2CDriver *i2cp, +// uint16_t header, +// i2ccallback_t callback) { +// +// chDbgCheck((i2cp != NULL) && (callback != NULL), "i2cMasterStartI"); +// chDbgAssert(i2cp->id_state == I2C_READY, +// "i2cMasterStartI(), #1", "invalid state"); +// +// i2cp->id_callback = callback; +// i2c_lld_master_start(i2cp, header); +//} /** * @brief Terminates a master bus transaction. @@ -147,15 +190,15 @@ void i2cMasterStartI(I2CDriver *i2cp, * * @iclass */ -void i2cMasterStopI(I2CDriver *i2cp, i2ccallback_t callback) { - - chDbgCheck((i2cp != NULL) && (callback != NULL), "i2cMasterStopI"); - chDbgAssert(i2cp->i2c_state == I2C_MREADY, - "i2cMasterStopI(), #1", "invalid state"); - - i2cp->id_callback = callback; - i2c_lld_master_stop(i2cp); -} +//void i2cMasterStopI(I2CDriver *i2cp, i2ccallback_t callback) { +// +// chDbgCheck((i2cp != NULL) && (callback != NULL), "i2cMasterStopI"); +// chDbgAssert(i2cp->id_state == I2C_MREADY, +// "i2cMasterStopI(), #1", "invalid state"); +// +// i2cp->id_callback = callback; +// i2c_lld_master_stop(i2cp); +//} /** @@ -167,15 +210,15 @@ void i2cMasterStopI(I2CDriver *i2cp, i2ccallback_t callback) { * * @iclass */ -void i2cMasterRestartI(I2CDriver *i2cp, i2ccallback_t callback) { - - chDbgCheck((i2cp != NULL) && (callback != NULL), "i2cMasterRestartI"); - chDbgAssert(i2cp->i2c_state == I2C_MREADY, - "i2cMasterRestartI(), #1", "invalid state"); - - i2cp->id_callback = callback; - i2c_lld_master_restart(i2cp); -} +//void i2cMasterRestartI(I2CDriver *i2cp, i2ccallback_t callback) { +// +// chDbgCheck((i2cp != NULL) && (callback != NULL), "i2cMasterRestartI"); +// chDbgAssert(i2cp->id_state == I2C_MREADY, +// "i2cMasterRestartI(), #1", "invalid state"); +// +// i2cp->id_callback = callback; +// i2c_lld_master_restart(i2cp); +//} /** * @brief Master transmission. @@ -187,17 +230,17 @@ void i2cMasterRestartI(I2CDriver *i2cp, i2ccallback_t callback) { * * @iclass */ -void i2cMasterTransmitI(I2CDriver *i2cp, size_t n, const uint8_t *txbuf, - i2ccallback_t callback) { - - chDbgCheck((i2cp != NULL) && (n > 0) && - (txbuf != NULL) && (callback != NULL), "i2cMasterTransmitI"); - chDbgAssert(i2cp->i2c_state == I2C_MREADY, - "i2cMasterTransmitI(), #1", "invalid state"); - - i2cp->id_callback = callback; - i2c_lld_master_transmit(i2cp, n, txbuf); -} +//void i2cMasterTransmitI(I2CDriver *i2cp, size_t n, const uint8_t *txbuf, +// i2ccallback_t callback) { +// +// chDbgCheck((i2cp != NULL) && (n > 0) && +// (txbuf != NULL) && (callback != NULL), "i2cMasterTransmitI"); +// chDbgAssert(i2cp->id_state == I2C_MREADY, +// "i2cMasterTransmitI(), #1", "invalid state"); +// +// i2cp->id_callback = callback; +// i2c_lld_master_transmit(i2cp, n, txbuf); +//} /** * @brief Master receive. @@ -209,17 +252,17 @@ void i2cMasterTransmitI(I2CDriver *i2cp, size_t n, const uint8_t *txbuf, * * @iclass */ -void i2cMasterReceiveI(I2CDriver *i2cp, size_t n, uint8_t *rxbuf, - i2ccallback_t callback) { - - chDbgCheck((i2cp != NULL) && (n > 0) && - (rxbuf != NULL) && (callback != NULL), "i2cMasterReceiveI"); - chDbgAssert(i2cp->i2c_state == I2C_MREADY, - "i2cMasterReceiveI(), #1", "invalid state"); - - i2cp->id_callback = callback; - i2c_lld_master_receive(i2cp, n, rxbuf); -} +//void i2cMasterReceiveI(I2CDriver *i2cp, size_t n, uint8_t *rxbuf, +// i2ccallback_t callback) { +// +// chDbgCheck((i2cp != NULL) && (n > 0) && +// (rxbuf != NULL) && (callback != NULL), "i2cMasterReceiveI"); +// chDbgAssert(i2cp->id_state == I2C_MREADY, +// "i2cMasterReceiveI(), #1", "invalid state"); +// +// i2cp->id_callback = callback; +// i2c_lld_master_receive(i2cp, n, rxbuf); +//} #if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) /** From 9c45802837b9053bbe32a8c8d5688cbf8c5d2706 Mon Sep 17 00:00:00 2001 From: barthess Date: Tue, 25 Jan 2011 21:25:10 +0000 Subject: [PATCH 04/92] I2C. Some hy level functions created and tested. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2686 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 5 +- os/hal/platforms/STM32/i2c_lld.c | 49 ++---------- os/hal/src/i2c.c | 124 +++---------------------------- 3 files changed, 21 insertions(+), 157 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 273c9f57a..73bab57f4 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -120,8 +120,9 @@ extern "C" { void i2cObjectInit(I2CDriver *i2cp); void i2cStart(I2CDriver *i2cp, I2CConfig *config); void i2cStop(I2CDriver *i2cp); - void i2cMasterTransmit(I2CDriver *i2cp, uint8_t slave_addr1, uint8_t slave_addr2, size_t n, const void *txbuf); - void i2cMasterReceive(I2CDriver *i2cp, uint8_t slave_addr1, uint8_t slave_addr2, size_t n, void *rxbuf); + void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); + void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); + void i2cMasterStartI(I2CDriver *i2cp,uint16_t header,i2ccallback_t callback); void i2cMasterStopI(I2CDriver *i2cp, i2ccallback_t callback); void i2cMasterRestartI(I2CDriver *i2cp, i2ccallback_t callback); diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 85ca16b2f..c1b932748 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -227,6 +227,7 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t re while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)){ i++; // wait start bit } + i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | I2C_WRITE; // write slave addres in DR while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){ i++; // wait Address sent @@ -249,6 +250,9 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t re if (restart){ i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate restart condition + while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)){ + i++; // wait start bit + } } else i2cp->id_i2c->CR1 |= I2C_CR1_STOP; // generate stop condition @@ -257,10 +261,8 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t re /** * @brief Receives data from the I2C bus. - * @details To receive data from I2C slave you must sent them some - * control bytes first. Driver takes this data from @p I2CSlaveConfig - * structure (*txbuf and txbytes fields), so you must manually - * fill this fields before invocating receiving function + * @details Before receive data from I2C slave you must manually sent them some + * control bytes first (refer to you device datasheet). * * @param[in] i2cp pointer to the @p I2CDriver object * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object @@ -274,45 +276,6 @@ void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { uint16_t i = 0; uint16_t tmp = 0; - // send control secuence to slave - //i2c_lld_master_transmit(i2cp, i2cscfg, TRUE); - - - - - - i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate start condition - while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)){ - i++; // wait start bit - } - i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | I2C_WRITE; // write slave addres in DR - while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){ - i++; // wait Address sent - } - i = i2cp->id_i2c->SR2; // TODO: check is it need to read this register for I2C to proper functionality - i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit - - // now write data byte by byte in DR register - uint32_t n = 0; - for (n = 0; n < i2cp->id_slave_config->txbytes; n++){ - i2cp->id_i2c->DR = i2cscfg->txbuf[n]; - while (!(i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ - i++; - } - } - - while (!(i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ - i++; - } - - i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate restart condition - while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)){ - i++; // wait start bit - } - - - - // send slave addres with read-bit i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | I2C_READ; while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){ diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 273bb5933..e621c652d 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -115,6 +115,7 @@ void i2cStop(I2CDriver *i2cp) { i2cp->id_state = I2C_STOP; chSysUnlock(); } + /** * @brief Sends data ever the I2C bus. * @@ -125,18 +126,18 @@ void i2cStop(I2CDriver *i2cp) { * @param[in] txbuf the pointer to the transmit buffer * */ -void i2cMasterTransmit(I2CDriver *i2cp, uint8_t slave_addr1, uint8_t slave_addr2, size_t n, const void *txbuf) { +void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart) { - chDbgCheck((i2cp != NULL) && (n > 0) && (txbuf != NULL), - "i2cSend"); + chDbgCheck((i2cp != NULL) && (i2cscfg != NULL), + "i2cMasterTransmit"); chDbgAssert(i2cp->id_state == I2C_READY, - "i2cSend(), #1", + "i2cMasterTransmit(), #1", "not active"); - //i2c_lld_master_transmit(i2cp, slave_addr1, slave_addr2, n, txbuf); - + i2c_lld_master_transmit(i2cp, i2cscfg, restart); } + /** * @brief Receives data from the I2C bus. * @@ -147,122 +148,21 @@ void i2cMasterTransmit(I2CDriver *i2cp, uint8_t slave_addr1, uint8_t slave_addr2 * @param[out] rxbuf the pointer to the receive buffer * */ -void i2cMasterReceive(I2CDriver *i2cp, uint8_t slave_addr1, uint8_t slave_addr2, size_t n, void *rxbuf) { +void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { - chDbgCheck((i2cp != NULL) && (n > 0) && (rxbuf != NULL), - "i2cReceive"); + chDbgCheck((i2cp != NULL) && (i2cscfg != NULL), + "i2cMasterReceive"); chDbgAssert(i2cp->id_state == I2C_READY, - "i2cReceive(), #1", + "i2cMasterReceive(), #1", "not active"); - //i2c_lld_master_receive(i2cp, slave_addr1, slave_addr2, n, rxbuf); - + i2c_lld_master_receive(i2cp, i2cscfg); } -/** - * @brief Initiates a master bus transaction. - * @details This function sends a start bit followed by an one or two bytes - * header. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] header transaction header - * @param[in] callback operation complete callback - * - * @iclass - */ -//void i2cMasterStartI(I2CDriver *i2cp, -// uint16_t header, -// i2ccallback_t callback) { -// -// chDbgCheck((i2cp != NULL) && (callback != NULL), "i2cMasterStartI"); -// chDbgAssert(i2cp->id_state == I2C_READY, -// "i2cMasterStartI(), #1", "invalid state"); -// -// i2cp->id_callback = callback; -// i2c_lld_master_start(i2cp, header); -//} - -/** - * @brief Terminates a master bus transaction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] callback operation complete callback - * - * @iclass - */ -//void i2cMasterStopI(I2CDriver *i2cp, i2ccallback_t callback) { -// -// chDbgCheck((i2cp != NULL) && (callback != NULL), "i2cMasterStopI"); -// chDbgAssert(i2cp->id_state == I2C_MREADY, -// "i2cMasterStopI(), #1", "invalid state"); -// -// i2cp->id_callback = callback; -// i2c_lld_master_stop(i2cp); -//} -/** - * @brief Sends a restart bit. - * @details Restart bits are required by some types of I2C transactions. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] callback operation complete callback - * - * @iclass - */ -//void i2cMasterRestartI(I2CDriver *i2cp, i2ccallback_t callback) { -// -// chDbgCheck((i2cp != NULL) && (callback != NULL), "i2cMasterRestartI"); -// chDbgAssert(i2cp->id_state == I2C_MREADY, -// "i2cMasterRestartI(), #1", "invalid state"); -// -// i2cp->id_callback = callback; -// i2c_lld_master_restart(i2cp); -//} -/** - * @brief Master transmission. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] n number of bytes to be transmitted - * @param[in] txbuf transmit data buffer pointer - * @param[in] callback operation complete callback - * - * @iclass - */ -//void i2cMasterTransmitI(I2CDriver *i2cp, size_t n, const uint8_t *txbuf, -// i2ccallback_t callback) { -// -// chDbgCheck((i2cp != NULL) && (n > 0) && -// (txbuf != NULL) && (callback != NULL), "i2cMasterTransmitI"); -// chDbgAssert(i2cp->id_state == I2C_MREADY, -// "i2cMasterTransmitI(), #1", "invalid state"); -// -// i2cp->id_callback = callback; -// i2c_lld_master_transmit(i2cp, n, txbuf); -//} -/** - * @brief Master receive. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] n number of bytes to be transmitted - * @param[in] rxbuf receive data buffer pointer - * @param[in] callback operation complete callback - * - * @iclass - */ -//void i2cMasterReceiveI(I2CDriver *i2cp, size_t n, uint8_t *rxbuf, -// i2ccallback_t callback) { -// -// chDbgCheck((i2cp != NULL) && (n > 0) && -// (rxbuf != NULL) && (callback != NULL), "i2cMasterReceiveI"); -// chDbgAssert(i2cp->id_state == I2C_MREADY, -// "i2cMasterReceiveI(), #1", "invalid state"); -// -// i2cp->id_callback = callback; -// i2c_lld_master_receive(i2cp, n, rxbuf); -//} #if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) /** From 9babeb847e50141bb378b77e987d8bc25c33a6d1 Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 26 Jan 2011 22:36:12 +0000 Subject: [PATCH 05/92] I2C. Rewriting low level driver to handle IRQs and DMA git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2687 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 11 +++++++---- os/hal/platforms/STM32/i2c_lld.c | 32 ++++++++++++++++++++++++++------ os/hal/platforms/STM32/i2c_lld.h | 4 ++++ 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 73bab57f4..e93f2249c 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -61,10 +61,13 @@ typedef enum { I2C_UNINIT = 0, /**< Not initialized. */ I2C_STOP = 1, /**< Stopped. */ I2C_READY = 2, /**< Ready. */ - I2C_MREADY = 3, /**< START and address sent. */ - I2C_MTRANSMIT = 4, /**< Master transmitting. */ - I2C_MRECEIVE = 5, /**< Master receiving. */ - I2C_MERROR = 6 /**< Error condition. */ + + I2C_MACTIVE = 3, /**< START condition sent. */ + I2C_MTXREADY = 4, /**< address sent when tx-flag set. */ + I2C_MTRANSMIT = 5, /**< Master transmitting. */ + + I2C_MRECEIVE = 6, /**< Master receiving. */ + I2C_MERROR = 7 /**< Error condition. */ } i2cstate_t; #include "i2c_lld.h" diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index c1b932748..8802d5af4 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -63,9 +63,30 @@ static i2cflags_t translate_errors(uint16_t sr) { static void i2c_serve_event_interrupt(I2CDriver *i2cp) { + // TODO: enable interrupts in config registers + if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent + i2cp->id_state = I2C_MACTIVE; + i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | + i2cp->id_slave_config->rw_bit; // write slave address in DR + } + + // now wait interrupt with ADDR flag + // TODO: 10 bit address handling here + if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address successfully sent + if(i2cp->id_slave_config->rw_bit == I2C_WRITE){ + i2cp->id_state = I2C_MTRANSMIT; + // TODO: setup here transmission via DMA like in ADC + } + else { + i2cp->id_state = I2C_MRECEIVE; + // TODO: setup here transmission via DMA like in ADC + } + } } + + static void i2c_serve_error_interrupt(I2CDriver *i2cp) { } @@ -218,15 +239,14 @@ void i2c_lld_stop(I2CDriver *i2cp) { void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart) { //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hylevel API - chSysLock(); - int i = 0; i2cp->id_slave_config = i2cscfg; + i2cp->id_slave_config->rw_bit = I2C_WRITE; + + //TODO: setup DMA channel here i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate start condition - while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)){ - i++; // wait start bit - } + i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | I2C_WRITE; // write slave addres in DR while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){ @@ -256,7 +276,7 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t re } else i2cp->id_i2c->CR1 |= I2C_CR1_STOP; // generate stop condition - chSysUnlock(); + } /** diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 427e72896..0179ba0e8 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -150,6 +150,10 @@ typedef struct { uint16_t error_flags; + uint8_t rw_bit; // this flag contain R/W bit + + bool_t restart; // send restart or stop event after complete data tx/rx + }I2CSlaveConfig; From 7ebdd9c7306b46193f88c990a37c4b597911f5f7 Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 27 Jan 2011 22:32:14 +0000 Subject: [PATCH 06/92] git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2688 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 14 +++++++++++++- os/hal/platforms/STM32/i2c_lld.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 8802d5af4..a6e03d010 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -228,6 +228,13 @@ void i2c_lld_stop(I2CDriver *i2cp) { i2cp->id_state = I2C_STOP; } + + +void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart){ + ; +} + + /** * @brief Transmits data ever the I2C bus as master. * TODO:@details @@ -245,8 +252,13 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t re i2cp->id_slave_config->rw_bit = I2C_WRITE; //TODO: setup DMA channel here - i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate start condition + // + // + i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate start condition + while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)){ + i++; // wait Address sent + } i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | I2C_WRITE; // write slave addres in DR while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){ diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 0179ba0e8..72b190eba 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -225,6 +225,7 @@ void i2c_lld_stop(I2CDriver *i2cp); void i2c_lld_master_start(I2CDriver *i2cp, uint16_t header); void i2c_lld_master_stop(I2CDriver *i2cp); void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); +void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); //static i2cflags_t translate_errors(uint16_t sr); From f4bdefbd11466c09dbf47f3eb680c33987a12172 Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 30 Jan 2011 21:19:51 +0000 Subject: [PATCH 07/92] I2C. Async transmit done. Need much of testing. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2697 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 20 +++-- os/hal/platforms/STM32/i2c_lld.c | 132 +++++++++++++++++++++++++++---- os/hal/platforms/STM32/i2c_lld.h | 57 +++++++++---- os/hal/src/i2c.c | 6 +- 4 files changed, 169 insertions(+), 46 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index e93f2249c..66019ccbf 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -61,12 +61,10 @@ typedef enum { I2C_UNINIT = 0, /**< Not initialized. */ I2C_STOP = 1, /**< Stopped. */ I2C_READY = 2, /**< Ready. */ - I2C_MACTIVE = 3, /**< START condition sent. */ - I2C_MTXREADY = 4, /**< address sent when tx-flag set. */ - I2C_MTRANSMIT = 5, /**< Master transmitting. */ - - I2C_MRECEIVE = 6, /**< Master receiving. */ + I2C_MTRANSMIT = 4, /**< Master transmitting. */ + I2C_MRECEIVE = 5, /**< Master receiving. */ + I2C_MWAIT_TF = 6, /**< Master wait Transmission Finished */ I2C_MERROR = 7 /**< Error condition. */ } i2cstate_t; @@ -123,14 +121,14 @@ extern "C" { void i2cObjectInit(I2CDriver *i2cp); void i2cStart(I2CDriver *i2cp, I2CConfig *config); void i2cStop(I2CDriver *i2cp); - void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); + void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); - void i2cMasterStartI(I2CDriver *i2cp,uint16_t header,i2ccallback_t callback); - void i2cMasterStopI(I2CDriver *i2cp, i2ccallback_t callback); - void i2cMasterRestartI(I2CDriver *i2cp, i2ccallback_t callback); - void i2cMasterTransmitI(I2CDriver *i2cp, size_t n, const uint8_t *txbuf, i2ccallback_t callback); - void i2cMasterReceiveI(I2CDriver *i2cp, size_t n, uint8_t *rxbuf, i2ccallback_t callback); + void i2cMasterStartI(I2CDriver *i2cp,uint16_t header); + void i2cMasterStopI(I2CDriver *i2cp); + void i2cMasterRestartI(I2CDriver *i2cp); + void i2cMasterTransmitI(I2CDriver *i2cp, size_t n, const uint8_t *txbuf); + void i2cMasterReceiveI(I2CDriver *i2cp, size_t n, uint8_t *rxbuf); #if I2C_USE_MUTUAL_EXCLUSION void i2cAcquireBus(I2CDriver *i2cp); void i2cReleaseBus(I2CDriver *i2cp); diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index a6e03d010..5efa5c082 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -61,9 +61,10 @@ static i2cflags_t translate_errors(uint16_t sr) { - +/* This function handle all regular interrupt conditions + * + */ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { - // TODO: enable interrupts in config registers if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent i2cp->id_state = I2C_MACTIVE; @@ -71,24 +72,104 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { i2cp->id_slave_config->rw_bit; // write slave address in DR } - // now wait interrupt with ADDR flag + // now "wait" interrupt with ADDR flag // TODO: 10 bit address handling here + // TODO: setup here transmission via DMA like in ADC if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address successfully sent if(i2cp->id_slave_config->rw_bit == I2C_WRITE){ - i2cp->id_state = I2C_MTRANSMIT; - // TODO: setup here transmission via DMA like in ADC + i2c_lld_txbyte(i2cp); // send first byte + i2cp->id_state = I2C_MTRANSMIT; // change state } else { - i2cp->id_state = I2C_MRECEIVE; - // TODO: setup here transmission via DMA like in ADC + i2c_lld_rxbyte(i2cp); // read first byte + i2cp->id_state = I2C_MRECEIVE; // change stat } } + + // transmitting bytes one by one + if ((i2cp->id_state == I2C_MTRANSMIT) && (i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ + if (i2c_lld_txbyte(i2cp)) + i2cp->id_state = I2C_MWAIT_TF; // last byte written + } + + //receiving bytes one by one + if ((i2cp->id_state == I2C_MRECEIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ + if (i2c_lld_txbyte(i2cp)) + i2cp->id_state = I2C_MWAIT_TF; // last byte read + } + + // "wait" BTF bit in status register + if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ + if (i2cp->id_slave_config->restart){ // restart need + i2cp->id_state = I2C_MACTIVE; + //i2cp->id_i2c->CR1 |= I2C_CR1_START; // send restart + i2cp->id_slave_config->id_restart_callback(i2cp, i2cp->id_slave_config); // callback call + } + else { + i2cp->id_state = I2C_READY; + i2cp->id_i2c->CR1 |= I2C_CR1_STOP; // stop communication + i2cp->id_slave_config->id_stop_callback(i2cp, i2cp->id_slave_config); // callback call + } + } +} + +/* helper function, not API + * write bytes in DR register + * return TRUE if last byte written + */ +bool_t i2c_lld_txbyte(I2CDriver *i2cp) { + // temporal variables + #define txbuf i2cp->id_slave_config->txbuf + #define txbufhead i2cp->id_slave_config->txbufhead + #define txdepth i2cp->id_slave_config->txdepth + + if (txbufhead < txdepth){ + i2cp->id_i2c->DR = txbuf[txbufhead]; + txbufhead++; + return(FALSE); + } + + txbufhead = 0; + #undef txbuf + #undef txbufhead + #undef txdepth + + return(TRUE); // last byte written +} + + +/* helper function, not API + * read bytes from DR register + * return TRUE if last byte read + */ +bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { + // temporal variables + #define rxbuf i2cp->id_slave_config->rxbuf + #define rxbufhead i2cp->id_slave_config->rxbufhead + #define rxdepth i2cp->id_slave_config->rxdepth + + if (rxbufhead < rxdepth){ + rxbuf[rxbufhead] = i2cp->id_i2c->DR; + rxbufhead++; + return(FALSE); + } + + rxbufhead = 0; + #undef rxbuf + #undef rxbufhead + #undef rxdepth + + return(TRUE); // last byte read } static void i2c_serve_error_interrupt(I2CDriver *i2cp) { - + // TODO:remove this stub + //simply trap for errors + while TRUE{ + translate_errors(i2cp->id_i2c->SR1); + } } #if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) @@ -186,9 +267,9 @@ void i2c_lld_start(I2CDriver *i2cp) { i2cp->id_i2c->CR1 = i2cp->id_config->i2cc_cr1; i2cp->id_i2c->CR2 = i2cp->id_config->i2cc_cr2 | - //I2C_CR2_ITERREN | - //I2C_CR2_ITEVTEN | - //I2C_CR2_ITBUFEN | + I2C_CR2_ITERREN | + I2C_CR2_ITEVTEN | + I2C_CR2_ITBUFEN | 36; //TODO: replace this by macro calculation /* TODO: * 1. macro timing calculator @@ -230,10 +311,32 @@ void i2c_lld_stop(I2CDriver *i2cp) { -void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart){ - ; +void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ + //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hylevel API + + i2cp->id_slave_config = i2cscfg; + i2cp->id_slave_config->rw_bit = I2C_WRITE; + + + // generate start condition. Later transmission goes asynchronously + i2cp->id_i2c->CR1 |= I2C_CR1_START; } +void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ + //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hylevel API + + i2cp->id_slave_config = i2cscfg; + i2cp->id_slave_config->rw_bit = I2C_READ; + + // reset restart flag + i2cp->id_slave_config->restart = FALSE; + + // generate (re)start condition. Later connection goes asynchronously + i2cp->id_i2c->CR1 |= I2C_CR1_START; + // TODO: need to clear ACK bit somewhere +} + + /** * @brief Transmits data ever the I2C bus as master. @@ -251,9 +354,6 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t re i2cp->id_slave_config = i2cscfg; i2cp->id_slave_config->rw_bit = I2C_WRITE; - //TODO: setup DMA channel here - // - // i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate start condition while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)){ diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 72b190eba..1b684a167 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -77,13 +77,25 @@ /* Driver data structures and types. */ /*===========================================================================*/ +/** + * @brief Type of a structure representing an I2C driver. + */ +typedef struct I2CDriver I2CDriver; + +/** + * @brief Type of a structure representing an I2C driver. + */ +typedef struct I2CSlaveConfig I2CSlaveConfig; + + /** * @brief I2C notification callback type. * * @param[in] i2cp FIXME: pointer to the @p I2CDriver object triggering the * callback */ -typedef void (*i2ccallback_t)(void); +typedef void (*i2ccallback_t)(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); +//typedef void (*i2ccallback_t)(void); /** * @brief I2C error notification callback type. @@ -93,6 +105,7 @@ typedef void (*i2ccallback_t)(void); */ typedef void (*i2cerrorcallback_t)(void); + /** * @brief Driver configuration structure. */ @@ -123,27 +136,31 @@ typedef uint8_t i2cblock_t; * @brief Structure representing an I2C slave configuration. * @details Each slave has its own data buffers, adress, and error flags. */ -typedef struct { +struct I2CSlaveConfig{ + /** + * @brief Callback pointer. + * @note Transfer finished callback. Invoke when all data transferred, or + * by DMA buffer events + * @p NULL then the callback is disabled. + */ + i2ccallback_t id_stop_callback; + i2ccallback_t id_restart_callback; /** * @brief Callback pointer. * @note TODO: I don't know, when this callback is inwoked * @p NULL then the callback is disabled. */ - i2ccallback_t id_callback; - /** - * @brief Callback pointer. - * @note TODO: I don't know, when this callback is inwoked - * @p NULL then the callback is disabled. - */ - i2cerrorcallback_t id_errcallback; + i2cerrorcallback_t id_err_callback; - i2cblock_t *rxbuf; // pointer to buffer - size_t rxdepth;// depth of buffer - size_t rxbytes;// count of bytes to sent in one sending + i2cblock_t *rxbuf; // pointer to buffer + size_t rxdepth; // depth of buffer + size_t rxbytes; // count of bytes to sent in one sending + size_t rxbufhead; // head pointer to current data byte i2cblock_t *txbuf; size_t txdepth; size_t txbytes; + size_t txbufhead; uint8_t slave_addr1; // 7-bit address of the slave uint8_t slave_addr2; // used in 10-bit address mode @@ -154,14 +171,14 @@ typedef struct { bool_t restart; // send restart or stop event after complete data tx/rx -}I2CSlaveConfig; +}; /** * @brief Structure representing an I2C driver. */ -typedef struct { +struct I2CDriver{ /** * @brief Driver state. */ @@ -195,7 +212,10 @@ typedef struct { */ I2C_TypeDef *id_i2c; -} I2CDriver; +} ; + + + /*===========================================================================*/ @@ -224,9 +244,14 @@ void i2c_lld_start(I2CDriver *i2cp); void i2c_lld_stop(I2CDriver *i2cp); void i2c_lld_master_start(I2CDriver *i2cp, uint16_t header); void i2c_lld_master_stop(I2CDriver *i2cp); + void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); -void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); +bool_t i2c_lld_txbyte(I2CDriver *i2cp); // helper function +void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); + void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); +void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); +bool_t i2c_lld_rxbyte(I2CDriver *i2cp); //static i2cflags_t translate_errors(uint16_t sr); #ifdef __cplusplus diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index e621c652d..5a0471e0f 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -126,7 +126,7 @@ void i2cStop(I2CDriver *i2cp) { * @param[in] txbuf the pointer to the transmit buffer * */ -void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart) { +void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { chDbgCheck((i2cp != NULL) && (i2cscfg != NULL), "i2cMasterTransmit"); @@ -134,7 +134,7 @@ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart) "i2cMasterTransmit(), #1", "not active"); - i2c_lld_master_transmit(i2cp, i2cscfg, restart); + i2c_lld_master_transmitI(i2cp, i2cscfg); } @@ -156,7 +156,7 @@ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { "i2cMasterReceive(), #1", "not active"); - i2c_lld_master_receive(i2cp, i2cscfg); + i2c_lld_master_receiveI(i2cp, i2cscfg); } From 47cd88dcc6eba547ffadbea2981ddc8a6729a15a Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 30 Jan 2011 21:24:45 +0000 Subject: [PATCH 08/92] I2C. Function movement in source file git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2698 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 211 +++++++++++++++---------------- 1 file changed, 104 insertions(+), 107 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 5efa5c082..d092d66d4 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -57,113 +57,6 @@ static i2cflags_t translate_errors(uint16_t sr) { } - - - - -/* This function handle all regular interrupt conditions - * - */ -static void i2c_serve_event_interrupt(I2CDriver *i2cp) { - - if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent - i2cp->id_state = I2C_MACTIVE; - i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | - i2cp->id_slave_config->rw_bit; // write slave address in DR - } - - // now "wait" interrupt with ADDR flag - // TODO: 10 bit address handling here - // TODO: setup here transmission via DMA like in ADC - if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address successfully sent - if(i2cp->id_slave_config->rw_bit == I2C_WRITE){ - i2c_lld_txbyte(i2cp); // send first byte - i2cp->id_state = I2C_MTRANSMIT; // change state - } - else { - i2c_lld_rxbyte(i2cp); // read first byte - i2cp->id_state = I2C_MRECEIVE; // change stat - } - } - - // transmitting bytes one by one - if ((i2cp->id_state == I2C_MTRANSMIT) && (i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ - if (i2c_lld_txbyte(i2cp)) - i2cp->id_state = I2C_MWAIT_TF; // last byte written - } - - //receiving bytes one by one - if ((i2cp->id_state == I2C_MRECEIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ - if (i2c_lld_txbyte(i2cp)) - i2cp->id_state = I2C_MWAIT_TF; // last byte read - } - - // "wait" BTF bit in status register - if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ - if (i2cp->id_slave_config->restart){ // restart need - i2cp->id_state = I2C_MACTIVE; - //i2cp->id_i2c->CR1 |= I2C_CR1_START; // send restart - i2cp->id_slave_config->id_restart_callback(i2cp, i2cp->id_slave_config); // callback call - } - else { - i2cp->id_state = I2C_READY; - i2cp->id_i2c->CR1 |= I2C_CR1_STOP; // stop communication - i2cp->id_slave_config->id_stop_callback(i2cp, i2cp->id_slave_config); // callback call - } - } -} - -/* helper function, not API - * write bytes in DR register - * return TRUE if last byte written - */ -bool_t i2c_lld_txbyte(I2CDriver *i2cp) { - // temporal variables - #define txbuf i2cp->id_slave_config->txbuf - #define txbufhead i2cp->id_slave_config->txbufhead - #define txdepth i2cp->id_slave_config->txdepth - - if (txbufhead < txdepth){ - i2cp->id_i2c->DR = txbuf[txbufhead]; - txbufhead++; - return(FALSE); - } - - txbufhead = 0; - #undef txbuf - #undef txbufhead - #undef txdepth - - return(TRUE); // last byte written -} - - -/* helper function, not API - * read bytes from DR register - * return TRUE if last byte read - */ -bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { - // temporal variables - #define rxbuf i2cp->id_slave_config->rxbuf - #define rxbufhead i2cp->id_slave_config->rxbufhead - #define rxdepth i2cp->id_slave_config->rxdepth - - if (rxbufhead < rxdepth){ - rxbuf[rxbufhead] = i2cp->id_i2c->DR; - rxbufhead++; - return(FALSE); - } - - rxbufhead = 0; - #undef rxbuf - #undef rxbufhead - #undef rxdepth - - return(TRUE); // last byte read -} - - - static void i2c_serve_error_interrupt(I2CDriver *i2cp) { // TODO:remove this stub //simply trap for errors @@ -172,6 +65,8 @@ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { } } + + #if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) /** * @brief I2C1 event interrupt handler. @@ -310,6 +205,108 @@ void i2c_lld_stop(I2CDriver *i2cp) { } +/* helper function, not API + * write bytes in DR register + * return TRUE if last byte written + */ +bool_t i2c_lld_txbyte(I2CDriver *i2cp) { + // temporal variables + #define txbuf i2cp->id_slave_config->txbuf + #define txbufhead i2cp->id_slave_config->txbufhead + #define txdepth i2cp->id_slave_config->txdepth + + if (txbufhead < txdepth){ + i2cp->id_i2c->DR = txbuf[txbufhead]; + txbufhead++; + return(FALSE); + } + + txbufhead = 0; + #undef txbuf + #undef txbufhead + #undef txdepth + + return(TRUE); // last byte written +} + + +/* helper function, not API + * read bytes from DR register + * return TRUE if last byte read + */ +bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { + // temporal variables + #define rxbuf i2cp->id_slave_config->rxbuf + #define rxbufhead i2cp->id_slave_config->rxbufhead + #define rxdepth i2cp->id_slave_config->rxdepth + + if (rxbufhead < rxdepth){ + rxbuf[rxbufhead] = i2cp->id_i2c->DR; + rxbufhead++; + return(FALSE); + } + + rxbufhead = 0; + #undef rxbuf + #undef rxbufhead + #undef rxdepth + + return(TRUE); // last byte read +} + + +/* This function handle all regular interrupt conditions + * + */ +static void i2c_serve_event_interrupt(I2CDriver *i2cp) { + + if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent + i2cp->id_state = I2C_MACTIVE; + i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | + i2cp->id_slave_config->rw_bit; // write slave address in DR + } + + // now "wait" interrupt with ADDR flag + // TODO: 10 bit address handling here + // TODO: setup here transmission via DMA like in ADC + if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address successfully sent + if(i2cp->id_slave_config->rw_bit == I2C_WRITE){ + i2c_lld_txbyte(i2cp); // send first byte + i2cp->id_state = I2C_MTRANSMIT; // change state + } + else { + i2c_lld_rxbyte(i2cp); // read first byte + i2cp->id_state = I2C_MRECEIVE; // change stat + } + } + + // transmitting bytes one by one + if ((i2cp->id_state == I2C_MTRANSMIT) && (i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ + if (i2c_lld_txbyte(i2cp)) + i2cp->id_state = I2C_MWAIT_TF; // last byte written + } + + //receiving bytes one by one + if ((i2cp->id_state == I2C_MRECEIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ + if (i2c_lld_txbyte(i2cp)) + i2cp->id_state = I2C_MWAIT_TF; // last byte read + } + + // "wait" BTF bit in status register + if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ + if (i2cp->id_slave_config->restart){ // restart need + i2cp->id_state = I2C_MACTIVE; + //i2cp->id_i2c->CR1 |= I2C_CR1_START; // send restart + i2cp->id_slave_config->id_restart_callback(i2cp, i2cp->id_slave_config); // callback call + } + else { + i2cp->id_state = I2C_READY; + i2cp->id_i2c->CR1 |= I2C_CR1_STOP; // stop communication + i2cp->id_slave_config->id_stop_callback(i2cp, i2cp->id_slave_config); // callback call + } + } +} + void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hylevel API From 25d42f8b9061f28f553e42afd0d7835a47bbb9c3 Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 30 Jan 2011 23:28:02 +0000 Subject: [PATCH 09/92] I2C. Master receiving and master trasmitting written. Needs testing and debugging. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2699 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 127 +++++++++++++++---------------- os/hal/platforms/STM32/i2c_lld.h | 19 +++-- 2 files changed, 73 insertions(+), 73 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index d092d66d4..9d655c68d 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -40,7 +40,7 @@ I2CDriver I2CD2; * * @return The error flags. */ -static i2cflags_t translate_errors(uint16_t sr) { +static i2cflags_t translate_i2c_errors(uint16_t sr) { i2cflags_t sts = 0; if (sr & USART_SR_ORE) @@ -58,13 +58,54 @@ static i2cflags_t translate_errors(uint16_t sr) { static void i2c_serve_error_interrupt(I2CDriver *i2cp) { - // TODO:remove this stub - //simply trap for errors + // TODO:remove this stub and write normal handler + // this is simply trap for errors while TRUE{ - translate_errors(i2cp->id_i2c->SR1); + translate_i2c_errors(i2cp->id_i2c->SR1); } } +/* This function handle all regular interrupt conditions + * + */ +static void i2c_serve_event_interrupt(I2CDriver *i2cp) { + + if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent + i2cp->id_state = I2C_MACTIVE; + i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | + i2cp->id_slave_config->rw_bit; // write slave address in DR + } + + // now "wait" interrupt with ADDR flag + // TODO: 10 bit address handling here + if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address successfully sent + if(i2cp->id_slave_config->rw_bit == I2C_WRITE){ + i2c_lld_txbyte(i2cp); // send first byte + i2cp->id_state = I2C_MTRANSMIT; // change state + } + else { + i2c_lld_rxbyte(i2cp); // read first byte + i2cp->id_state = I2C_MRECEIVE; // change status + } + } + + // transmitting bytes one by one + if ((i2cp->id_state == I2C_MTRANSMIT) && (i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ + if (i2c_lld_txbyte(i2cp)) + i2cp->id_state = I2C_MWAIT_TF; // last byte written + } + + //receiving bytes one by one + if ((i2cp->id_state == I2C_MRECEIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ + if (i2c_lld_txbyte(i2cp)) + i2cp->id_state = I2C_MWAIT_TF; // last byte read + } + + // "wait" BTF bit in status register + if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ + i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); + } +} #if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) @@ -239,10 +280,14 @@ bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { #define rxbuf i2cp->id_slave_config->rxbuf #define rxbufhead i2cp->id_slave_config->rxbufhead #define rxdepth i2cp->id_slave_config->rxdepth + #define rxbytes i2cp->id_slave_config->rxbytes if (rxbufhead < rxdepth){ rxbuf[rxbufhead] = i2cp->id_i2c->DR; rxbufhead++; + if ((rxbytes - rxbufhead) == 1) + // clear ACK bit for automatically send NACK + i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK); return(FALSE); } @@ -250,61 +295,18 @@ bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { #undef rxbuf #undef rxbufhead #undef rxdepth + #undef rxbytes return(TRUE); // last byte read } -/* This function handle all regular interrupt conditions - * - */ -static void i2c_serve_event_interrupt(I2CDriver *i2cp) { +void i2c_lld_master_start(I2CDriver *i2cp){ + i2cp->id_i2c->CR1 |= I2C_CR1_START; +} - if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent - i2cp->id_state = I2C_MACTIVE; - i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | - i2cp->id_slave_config->rw_bit; // write slave address in DR - } - - // now "wait" interrupt with ADDR flag - // TODO: 10 bit address handling here - // TODO: setup here transmission via DMA like in ADC - if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address successfully sent - if(i2cp->id_slave_config->rw_bit == I2C_WRITE){ - i2c_lld_txbyte(i2cp); // send first byte - i2cp->id_state = I2C_MTRANSMIT; // change state - } - else { - i2c_lld_rxbyte(i2cp); // read first byte - i2cp->id_state = I2C_MRECEIVE; // change stat - } - } - - // transmitting bytes one by one - if ((i2cp->id_state == I2C_MTRANSMIT) && (i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ - if (i2c_lld_txbyte(i2cp)) - i2cp->id_state = I2C_MWAIT_TF; // last byte written - } - - //receiving bytes one by one - if ((i2cp->id_state == I2C_MRECEIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ - if (i2c_lld_txbyte(i2cp)) - i2cp->id_state = I2C_MWAIT_TF; // last byte read - } - - // "wait" BTF bit in status register - if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ - if (i2cp->id_slave_config->restart){ // restart need - i2cp->id_state = I2C_MACTIVE; - //i2cp->id_i2c->CR1 |= I2C_CR1_START; // send restart - i2cp->id_slave_config->id_restart_callback(i2cp, i2cp->id_slave_config); // callback call - } - else { - i2cp->id_state = I2C_READY; - i2cp->id_i2c->CR1 |= I2C_CR1_STOP; // stop communication - i2cp->id_slave_config->id_stop_callback(i2cp, i2cp->id_slave_config); // callback call - } - } +void i2c_lld_master_stop(I2CDriver *i2cp){ + i2cp->id_i2c->CR1 |= I2C_CR1_STOP; } @@ -314,9 +316,8 @@ void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ i2cp->id_slave_config = i2cscfg; i2cp->id_slave_config->rw_bit = I2C_WRITE; - - // generate start condition. Later transmission goes asynchronously - i2cp->id_i2c->CR1 |= I2C_CR1_START; + // generate start condition. Later transmission goes in background + i2c_lld_master_start(i2cp); } void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ @@ -325,19 +326,14 @@ void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ i2cp->id_slave_config = i2cscfg; i2cp->id_slave_config->rw_bit = I2C_READ; - // reset restart flag - i2cp->id_slave_config->restart = FALSE; - // generate (re)start condition. Later connection goes asynchronously - i2cp->id_i2c->CR1 |= I2C_CR1_START; - // TODO: need to clear ACK bit somewhere + i2c_lld_master_start(i2cp); } /** - * @brief Transmits data ever the I2C bus as master. - * TODO:@details + * @brief Transmits data ever the I2C bus as masteri2cp. * * @param[in] i2cp pointer to the @p I2CDriver object * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object @@ -384,10 +380,9 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t re } } else i2cp->id_i2c->CR1 |= I2C_CR1_STOP; // generate stop condition - - } + /** * @brief Receives data from the I2C bus. * @details Before receive data from I2C slave you must manually sent them some @@ -432,4 +427,6 @@ void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { chSysUnlock(); } + + #endif // HAL_USE_I2C diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 1b684a167..bac1dfff0 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -90,17 +90,21 @@ typedef struct I2CSlaveConfig I2CSlaveConfig; /** * @brief I2C notification callback type. + * @details This function must be used to send start or stop events to I2C bus, + * and change states of I2CDriver. * - * @param[in] i2cp FIXME: pointer to the @p I2CDriver object triggering the + * @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, I2CSlaveConfig *i2cscfg); -//typedef void (*i2ccallback_t)(void); + /** * @brief I2C error notification callback type. * - * @param[in] i2cp FIXME: pointer to the @p I2CDriver object triggering the + * @param[in] i2cp TODO: pointer to the @p I2CDriver object triggering the * callback */ typedef void (*i2cerrorcallback_t)(void); @@ -143,8 +147,7 @@ struct I2CSlaveConfig{ * by DMA buffer events * @p NULL then the callback is disabled. */ - i2ccallback_t id_stop_callback; - i2ccallback_t id_restart_callback; + i2ccallback_t id_callback; /** * @brief Callback pointer. * @note TODO: I don't know, when this callback is inwoked @@ -242,17 +245,17 @@ extern "C" { void i2c_lld_init(void); void i2c_lld_start(I2CDriver *i2cp); void i2c_lld_stop(I2CDriver *i2cp); -void i2c_lld_master_start(I2CDriver *i2cp, uint16_t header); + +void i2c_lld_master_start(I2CDriver *i2cp); void i2c_lld_master_stop(I2CDriver *i2cp); void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); -bool_t i2c_lld_txbyte(I2CDriver *i2cp); // helper function void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); +bool_t i2c_lld_txbyte(I2CDriver *i2cp); // helper function void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); bool_t i2c_lld_rxbyte(I2CDriver *i2cp); -//static i2cflags_t translate_errors(uint16_t sr); #ifdef __cplusplus } From 30ba99b968c94b96fd5e9c88bd52a9f5e70cc2e0 Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 2 Feb 2011 21:01:22 +0000 Subject: [PATCH 10/92] I2C. Nop. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2701 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 2 ++ os/hal/platforms/STM32/i2c_lld.c | 45 ++++++++++++++++++-------------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 66019ccbf..64816186b 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -124,6 +124,8 @@ extern "C" { void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); + + void i2cMasterStartI(I2CDriver *i2cp,uint16_t header); void i2cMasterStopI(I2CDriver *i2cp); void i2cMasterRestartI(I2CDriver *i2cp); diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 9d655c68d..8aaf3f646 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -69,23 +69,31 @@ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { * */ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { + // TODO: 10 bit address handling here + if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ + i2cp->id_i2c->SR1 &= (~I2C_SR1_BTF); + i2cp->id_state = I2C_READY; + return; + } if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent i2cp->id_state = I2C_MACTIVE; i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | i2cp->id_slave_config->rw_bit; // write slave address in DR + return; } // now "wait" interrupt with ADDR flag - // TODO: 10 bit address handling here if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address successfully sent - if(i2cp->id_slave_config->rw_bit == I2C_WRITE){ + if(i2cp->id_i2c->SR2 & I2C_SR2_TRA){ i2c_lld_txbyte(i2cp); // send first byte i2cp->id_state = I2C_MTRANSMIT; // change state + return; } else { - i2c_lld_rxbyte(i2cp); // read first byte + //i2c_lld_rxbyte(i2cp); // read first byte i2cp->id_state = I2C_MRECEIVE; // change status + return; } } @@ -93,17 +101,20 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { if ((i2cp->id_state == I2C_MTRANSMIT) && (i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ if (i2c_lld_txbyte(i2cp)) i2cp->id_state = I2C_MWAIT_TF; // last byte written + return; } //receiving bytes one by one if ((i2cp->id_state == I2C_MRECEIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ - if (i2c_lld_txbyte(i2cp)) + if (i2c_lld_rxbyte(i2cp)) i2cp->id_state = I2C_MWAIT_TF; // last byte read + return; } // "wait" BTF bit in status register if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); + return; } } @@ -251,22 +262,12 @@ void i2c_lld_stop(I2CDriver *i2cp) { * return TRUE if last byte written */ bool_t i2c_lld_txbyte(I2CDriver *i2cp) { - // temporal variables - #define txbuf i2cp->id_slave_config->txbuf - #define txbufhead i2cp->id_slave_config->txbufhead - #define txdepth i2cp->id_slave_config->txdepth - - if (txbufhead < txdepth){ - i2cp->id_i2c->DR = txbuf[txbufhead]; - txbufhead++; + if (i2cp->id_slave_config->txbufhead < i2cp->id_slave_config->txbytes){ + i2cp->id_i2c->DR = i2cp->id_slave_config->txbuf[i2cp->id_slave_config->txbufhead]; + (i2cp->id_slave_config->txbufhead)++; return(FALSE); } - - txbufhead = 0; - #undef txbuf - #undef txbufhead - #undef txdepth - + i2cp->id_slave_config->txbufhead = 0; return(TRUE); // last byte written } @@ -282,12 +283,13 @@ bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { #define rxdepth i2cp->id_slave_config->rxdepth #define rxbytes i2cp->id_slave_config->rxbytes - if (rxbufhead < rxdepth){ + if (rxbufhead < rxbytes){ rxbuf[rxbufhead] = i2cp->id_i2c->DR; rxbufhead++; - if ((rxbytes - rxbufhead) == 1) + if ((rxbytes - rxbufhead) == 1){ // clear ACK bit for automatically send NACK i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK); + } return(FALSE); } @@ -307,6 +309,9 @@ void i2c_lld_master_start(I2CDriver *i2cp){ void i2c_lld_master_stop(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_STOP; + chSysLock(); + while (i2cp->id_i2c->CR1 & I2C_CR1_STOP); + chSysUnlock(); } From cb7d5725fbd1a9c164934ab56933bc449c49ccfe Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 2 Feb 2011 22:34:03 +0000 Subject: [PATCH 11/92] I2C. Nop. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2702 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 8aaf3f646..dda47fb45 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -113,6 +113,8 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { // "wait" BTF bit in status register if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ + //if ((i2cp->id_state == I2C_MWAIT_TF) && ((i2cp->id_i2c->SR1 & I2C_SR1_RXNE) || (i2cp->id_i2c->SR1 & I2C_SR1_TXE))){ + i2cp->id_i2c->SR1 &= (~I2C_SR1_BTF); i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); return; } From 0f5f6dd222ffa0571e63cdfba6e6e8c1bddc4beb Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 3 Feb 2011 14:02:02 +0000 Subject: [PATCH 12/92] I2C. Nop. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2703 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 37 ++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index dda47fb45..e362284e4 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -66,17 +66,15 @@ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { } /* This function handle all regular interrupt conditions - * + * TODO: 10 bit address handling here */ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { - // TODO: 10 bit address handling here - if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ - i2cp->id_i2c->SR1 &= (~I2C_SR1_BTF); - i2cp->id_state = I2C_READY; - return; - } + int i = 0; + int n = 0; + int m = 0; if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent + //i = i2cp->id_i2c->SR1; i2cp->id_state = I2C_MACTIVE; i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | i2cp->id_slave_config->rw_bit; // write slave address in DR @@ -106,16 +104,27 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { //receiving bytes one by one if ((i2cp->id_state == I2C_MRECEIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ +// i = i2cp->id_i2c->SR1; +// n = i2cp->id_i2c->SR2; if (i2c_lld_rxbyte(i2cp)) i2cp->id_state = I2C_MWAIT_TF; // last byte read +// i = i2cp->id_i2c->SR1; +// n = i2cp->id_i2c->SR2; return; } // "wait" BTF bit in status register - if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ - //if ((i2cp->id_state == I2C_MWAIT_TF) && ((i2cp->id_i2c->SR1 & I2C_SR1_RXNE) || (i2cp->id_i2c->SR1 & I2C_SR1_TXE))){ - i2cp->id_i2c->SR1 &= (~I2C_SR1_BTF); +// if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ + if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE | I2C_SR1_BTF | I2C_SR1_TXE)){ + chSysLockFromIsr(); i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); + chSysUnlockFromIsr(); + return; + } + else{ // trap + i = i2cp->id_i2c->SR1; + n = i2cp->id_i2c->SR2; + m = i2cp->id_i2c->CR1; return; } } @@ -286,15 +295,15 @@ bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { #define rxbytes i2cp->id_slave_config->rxbytes if (rxbufhead < rxbytes){ + if ((rxbytes - rxbufhead) == 1){ + i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);// clear ACK bit for automatically send NACK + } rxbuf[rxbufhead] = i2cp->id_i2c->DR; rxbufhead++; - if ((rxbytes - rxbufhead) == 1){ - // clear ACK bit for automatically send NACK - i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK); - } return(FALSE); } + rxbuf[rxbufhead] = i2cp->id_i2c->DR; // read last byte rxbufhead = 0; #undef rxbuf #undef rxbufhead From 6034aab6e6c48c4de3f8488957350c8824c60adb Mon Sep 17 00:00:00 2001 From: barthess Date: Fri, 4 Feb 2011 09:55:51 +0000 Subject: [PATCH 13/92] I2C. Nop. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2704 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index e362284e4..9e519d412 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -89,7 +89,12 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { return; } else { - //i2c_lld_rxbyte(i2cp); // read first byte + /* In order to generate the non-acknowledge pulse after the last received + * data byte, the ACK bit must be cleared just after reading the second + * last data byte (after second last RxNE event). + */ + if (i2cp->id_slave_config->rxbytes > 1) + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // set ACK bit i2cp->id_state = I2C_MRECEIVE; // change status return; } @@ -118,6 +123,11 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE | I2C_SR1_BTF | I2C_SR1_TXE)){ chSysLockFromIsr(); i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); + + i = i2cp->id_i2c->SR1; + n = i2cp->id_i2c->SR2; + m = i2cp->id_i2c->CR1; + chSysUnlockFromIsr(); return; } @@ -294,11 +304,15 @@ bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { #define rxdepth i2cp->id_slave_config->rxdepth #define rxbytes i2cp->id_slave_config->rxbytes + /* In order to generate the non-acknowledge pulse after the last received + * data byte, the ACK bit must be cleared just after reading the second + * last data byte (after second last RxNE event). + */ if (rxbufhead < rxbytes){ - if ((rxbytes - rxbufhead) == 1){ + rxbuf[rxbufhead] = i2cp->id_i2c->DR; + if ((rxbytes - rxbufhead) <= 2){ i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);// clear ACK bit for automatically send NACK } - rxbuf[rxbufhead] = i2cp->id_i2c->DR; rxbufhead++; return(FALSE); } From 34f9fdfb6260e91ae827a4b6edd49631c116576a Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 5 Feb 2011 14:53:42 +0000 Subject: [PATCH 14/92] I2C. Move barthess driver to backup files. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2709 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/{i2c.h => i2c_brts.h} | 0 os/hal/platforms/STM32/{i2c_lld.c => i2c_lld_brts.c} | 0 os/hal/platforms/STM32/{i2c_lld.h => i2c_lld_brts.h} | 0 os/hal/src/{i2c.c => i2c_brts.c} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename os/hal/include/{i2c.h => i2c_brts.h} (100%) rename os/hal/platforms/STM32/{i2c_lld.c => i2c_lld_brts.c} (100%) rename os/hal/platforms/STM32/{i2c_lld.h => i2c_lld_brts.h} (100%) rename os/hal/src/{i2c.c => i2c_brts.c} (100%) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c_brts.h similarity index 100% rename from os/hal/include/i2c.h rename to os/hal/include/i2c_brts.h diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld_brts.c similarity index 100% rename from os/hal/platforms/STM32/i2c_lld.c rename to os/hal/platforms/STM32/i2c_lld_brts.c diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld_brts.h similarity index 100% rename from os/hal/platforms/STM32/i2c_lld.h rename to os/hal/platforms/STM32/i2c_lld_brts.h diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c_brts.c similarity index 100% rename from os/hal/src/i2c.c rename to os/hal/src/i2c_brts.c From aad95ce0637a96ee81e60c5251a1a5851b6dfb7d Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 5 Feb 2011 14:55:56 +0000 Subject: [PATCH 15/92] I2C. Added driver from albi. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2710 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 185 ++++++++++ os/hal/platforms/STM32/i2c_lld.c | 574 +++++++++++++++++++++++++++++++ os/hal/platforms/STM32/i2c_lld.h | 263 ++++++++++++++ os/hal/src/i2c.c | 268 +++++++++++++++ 4 files changed, 1290 insertions(+) create mode 100644 os/hal/include/i2c.h create mode 100644 os/hal/platforms/STM32/i2c_lld.c create mode 100644 os/hal/platforms/STM32/i2c_lld.h create mode 100644 os/hal/src/i2c.c diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h new file mode 100644 index 000000000..30ec38548 --- /dev/null +++ b/os/hal/include/i2c.h @@ -0,0 +1,185 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . +*/ + +/** + * @file i2c.h + * @brief I2C Driver macros and structures. + * + * @addtogroup I2C + * @{ + */ + +#ifndef I2C_H_ +#define I2C_H_ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ +#define I2CD_NO_ERROR 0 +/** @brief Bus Error.*/ +#define I2CD_BUS_ERROR 0x01 +/** @brief Arbitration Lost (master mode).*/ +#define I2CD_ARBITRATION_LOST 0x02 +/** @brief Acknowledge Failure.*/ +#define I2CD_ACK_FAILURE 0x04 +/** @brief Overrun/Underrun.*/ +#define I2CD_OVERRUN 0x08 +/** @brief PEC Error in reception.*/ +#define I2CD_PEC_ERROR 0x10 +/** @brief Timeout or Tlow Error.*/ +#define I2CD_TIMEOUT 0x20 +/** @brief SMBus Alert.*/ +#define I2CD_SMB_ALERT 0x40 + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(I2C_USE_WAIT) || defined(__DOXYGEN__) +#define I2C_USE_WAIT TRUE +#endif + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if I2C_USE_MUTUAL_EXCLUSION && !CH_USE_MUTEXES && !CH_USE_SEMAPHORES +#error "I2C_USE_MUTUAL_EXCLUSION requires CH_USE_MUTEXES and/or CH_USE_SEMAPHORES" +#endif + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + I2C_UNINIT = 0, /**< @brief Not initialized. */ + I2C_STOP = 1, /**< @brief Stopped. */ + I2C_READY = 2, /**< @brief Ready. */ + I2C_ACTIVE = 3, /**< @brief In communication. */ + I2C_COMPLETE = 4 /**< @brief Asynchronous operation complete. */ +} i2cstate_t; + +#include "i2c_lld.h" + +#if I2C_USE_WAIT || defined(__DOXYGEN__) +/** + * @brief Waits for operation completion. + * @details This function waits for the driver to complete the current + * operation. + * @pre An operation must be running while the function is invoked. + * @note No more than one thread can wait on a I2C driver using + * this function. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define _i2c_wait_s(i2cp) { \ + chDbgAssert((i2cp)->thread == NULL, \ + "_i2c_wait(), #1", "already waiting"); \ + (i2cp)->thread = chThdSelf(); \ + chSchGoSleepS(THD_STATE_SUSPENDED); \ +} + +/** + * @brief Wakes up the waiting thread. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define _i2c_wakeup_isr(i2cp) { \ + if ((i2cp)->thread != NULL) { \ + Thread *tp = (i2cp)->thread; \ + (i2cp)->thread = NULL; \ + chSysLockFromIsr(); \ + chSchReadyI(tp); \ + chSysUnlockFromIsr(); \ + } \ +} +#else /* !I2C_USE_WAIT */ +#define _i2c_wait_s(i2cp) +#define _i2c_wakeup_isr(i2cp) +#endif /* !I2C_USE_WAIT */ + +/** + * @brief Common ISR code. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * - Waiting thread wakeup, if any. + * - Driver state transitions. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define _i2c_isr_code(i2cp) { \ + (i2cp)->state = I2C_COMPLETE; \ + if((i2cp)->endcb) { \ + (i2cp)->endcb(i2cp); \ + } \ + _i2c_wakeup_isr(i2cp); \ +} + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void i2cInit(void); + void i2cObjectInit(I2CDriver *i2cp); + void i2cStart(I2CDriver *i2cp, const I2CConfig *config); + void i2cStop(I2CDriver *i2cp); + void i2cMasterTransmit(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *txbuf); + void i2cMasterReceive(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *rxbuf); + void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask); + i2cflags_t i2cGetAndClearFlags(I2CDriver *i2cp); + uint16_t i2cSMBusAlertResponse(I2CDriver *i2cp); + +#if I2C_USE_MUTUAL_EXCLUSION + void i2cAcquireBus(I2CDriver *i2cp); + void i2cReleaseBus(I2CDriver *i2cp); +#endif /* I2C_USE_MUTUAL_EXCLUSION */ +#ifdef __cplusplus +} +#endif + + +#endif /* CH_HAL_USE_I2C */ + +#endif /* I2C_H_ */ diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c new file mode 100644 index 000000000..cd6a851db --- /dev/null +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -0,0 +1,574 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . +*/ + +/** + * @file STM32/i2c_lld.c + * @brief STM32 I2C subsystem low level driver source. Slave mode not implemented. + * @addtogroup STM32_I2C + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief I2C1 driver identifier.*/ +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +I2CDriver I2CD1; +#endif + +/** @brief I2C2 driver identifier.*/ +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +I2CDriver I2CD2; +#endif + + +static uint32_t i2c_get_event(I2CDriver *i2cp){ + uint32_t regSR1 = i2cp->i2c_register->SR1; + uint32_t regSR2 = i2cp->i2c_register->SR2; + /* return the last event value from I2C status registers */ + return (I2C_EV_MASK & (regSR1 | (regSR2 << 16))); +} + +static void i2c_serve_event_interrupt(I2CDriver *i2cp) { + static __IO uint8_t *txBuffp, *rxBuffp, *datap; + + I2C_TypeDef *dp = i2cp->i2c_register; + + switch(i2c_get_event(i2cp)) { + case I2C_EV5_MASTER_MODE_SELECT: + i2cp->flags &= ~I2C_FLG_HEADER_SENT; + dp->DR = i2cp->slave_addr1; + break; + case I2C_EV9_MASTER_ADDR_10BIT: + if(i2cp->flags & I2C_FLG_MASTER_RECEIVER) { + i2cp->slave_addr1 |= 0x01; + i2cp->flags |= I2C_FLG_HEADER_SENT; + } + dp->DR = i2cp->slave_addr2; + break; + //------------------------------------------------------------------------ + // Master Transmitter ---------------------------------------------------- + //------------------------------------------------------------------------ + case I2C_EV6_MASTER_TRA_MODE_SELECTED: + if(i2cp->flags & I2C_FLG_HEADER_SENT){ + dp->CR1 |= I2C_CR1_START; // re-send the start in 10-Bit address mode + break; + } + //Initialize the transmit buffer pointer + txBuffp = (uint8_t*)i2cp->txbuf; + datap = txBuffp; + txBuffp++; + i2cp->remaining_bytes--; + /* If no further data to be sent, disable the I2C ITBUF in order to not have a TxE interrupt */ + if(i2cp->remaining_bytes == 0) { + dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + } + //EV8_1 write the first data + dp->DR = *datap; + break; + case I2C_EV8_MASTER_BYTE_TRANSMITTING: + if(i2cp->remaining_bytes > 0) { + datap = txBuffp; + txBuffp++; + i2cp->remaining_bytes--; + if(i2cp->remaining_bytes == 0) { + /* If no further data to be sent, disable the ITBUF in order to not have a TxE interrupt */ + dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + } + dp->DR = *datap; + } + break; + case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: + dp->CR1 |= I2C_CR1_STOP; // stop generation + /* Disable ITEVT In order to not have again a BTF IT */ + dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; + /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ + _i2c_isr_code(i2cp); + break; + //------------------------------------------------------------------------ + // Master Receiver ------------------------------------------------------- + //------------------------------------------------------------------------ + case I2C_EV6_MASTER_REC_MODE_SELECTED: + chSysLockFromIsr(); + switch(i2cp->flags & EV6_SUBEV_MASK) { + case I2C_EV6_3_MASTER_REC_1BTR_MODE_SELECTED: // only an single byte to receive + /* Clear ACK */ + dp->CR1 &= (uint16_t)~I2C_CR1_ACK; + /* Program the STOP */ + dp->CR1 |= I2C_CR1_STOP; + break; + case I2C_EV6_1_MASTER_REC_2BTR_MODE_SELECTED: // only two bytes to receive + /* Clear ACK */ + dp->CR1 &= (uint16_t)~I2C_CR1_ACK; + /* Disable the ITBUF in order to have only the BTF interrupt */ + dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + break; + } + chSysUnlockFromIsr(); + /* Initialize receive buffer pointer */ + rxBuffp = i2cp->rxbuf; + break; + case I2C_EV7_MASTER_REC_BYTE_RECEIVED: + if(i2cp->remaining_bytes != 3) { + /* Read the data register */ + *rxBuffp = dp->DR; + rxBuffp++; + i2cp->remaining_bytes--; + switch(i2cp->remaining_bytes){ + case 3: + /* Disable the ITBUF in order to have only the BTF interrupt */ + dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + i2cp->flags |= I2C_FLG_3BTR; + break; + case 0: + /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ + _i2c_isr_code(i2cp); + break; + } + } + // when remaining 3 bytes do nothing, wait until RXNE and BTF are set (until 2 bytes are received) + break; + case I2C_EV7_MASTER_REC_BYTE_QUEUED: + switch(i2cp->flags & EV7_SUBEV_MASK) { + case I2C_EV7_2_MASTER_REC_3BYTES_TO_PROCESS: + // DataN-2 and DataN-1 are received + chSysLockFromIsr(); + dp->CR2 |= I2C_CR2_ITBUFEN; + /* Clear ACK */ + dp->CR1 &= (uint16_t)~I2C_CR1_ACK; + /* Read the DataN-2*/ + *rxBuffp = dp->DR; //This clear the RXE & BFT flags and launch the DataN reception in the shift register (ending the SCL stretch) + rxBuffp++; + /* Program the STOP */ + dp->CR1 |= I2C_CR1_STOP; + /* Read the DataN-1 */ + *rxBuffp = dp->DR; + chSysUnlockFromIsr(); + rxBuffp++; + /* Decrement the number of readed bytes */ + i2cp->remaining_bytes -= 2; + i2cp->flags = 0; + // ready for read DataN on the next EV7 + break; + case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: // only for case of two bytes to be received + // DataN-1 and DataN are received + chSysLockFromIsr(); + /* Program the STOP */ + dp->CR1 |= I2C_CR1_STOP; + /* Read the DataN-1*/ + *rxBuffp = dp->DR; + chSysUnlockFromIsr(); + rxBuffp++; + /* Read the DataN*/ + *rxBuffp = dp->DR; + i2cp->remaining_bytes = 0; + i2cp->flags = 0; + /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ + _i2c_isr_code(i2cp); + break; + } + break; + } +} + +static void i2c_serve_error_interrupt(I2CDriver *i2cp) { + i2cflags_t flags; + I2C_TypeDef *reg; + + reg = i2cp->i2c_register; + flags = I2CD_NO_ERROR; + + if(reg->SR1 & I2C_SR1_BERR) { // Bus error + reg->SR1 &= ~I2C_SR1_BERR; + flags |= I2CD_BUS_ERROR; + } + if(reg->SR1 & I2C_SR1_ARLO) { // Arbitration lost + reg->SR1 &= ~I2C_SR1_ARLO; + flags |= I2CD_ARBITRATION_LOST; + } + if(reg->SR1 & I2C_SR1_AF) { // Acknowledge fail + reg->SR1 &= ~I2C_SR1_AF; + reg->CR1 |= I2C_CR1_STOP; // setting stop bit + flags |= I2CD_ACK_FAILURE; + } + if(reg->SR1 & I2C_SR1_OVR) { // Overrun + reg->SR1 &= ~I2C_SR1_OVR; + flags |= I2CD_OVERRUN; + } + if(reg->SR1 & I2C_SR1_PECERR) { // PEC error + reg->SR1 &= ~I2C_SR1_PECERR; + flags |= I2CD_PEC_ERROR; + } + if(reg->SR1 & I2C_SR1_TIMEOUT) { // SMBus Timeout + reg->SR1 &= ~I2C_SR1_TIMEOUT; + flags |= I2CD_TIMEOUT; + } + if(reg->SR1 & I2C_SR1_SMBALERT) { // SMBus alert + reg->SR1 &= ~I2C_SR1_SMBALERT; + flags |= I2CD_SMB_ALERT; + } + + if(flags != I2CD_NO_ERROR) { + // send communication end signal + _i2c_isr_code(i2cp); + chSysLockFromIsr(); + i2cAddFlagsI(i2cp, flags); + chSysUnlockFromIsr(); + } +} + +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +/** + * @brief I2C1 event interrupt handler. + */ +CH_IRQ_HANDLER(I2C1_EV_IRQHandler) { + + CH_IRQ_PROLOGUE(); + i2c_serve_event_interrupt(&I2CD1); + CH_IRQ_EPILOGUE(); +} + +/** + * @brief I2C1 error interrupt handler. + */ +CH_IRQ_HANDLER(I2C1_ER_IRQHandler) { + + CH_IRQ_PROLOGUE(); + i2c_serve_error_interrupt(&I2CD1); + CH_IRQ_EPILOGUE(); +} +#endif + +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +/** + * @brief I2C2 event interrupt handler. + */ +CH_IRQ_HANDLER(I2C2_EV_IRQHandler) { + + CH_IRQ_PROLOGUE(); + i2c_serve_event_interrupt(&I2CD2); + CH_IRQ_EPILOGUE(); +} + +/** + * @brief I2C2 error interrupt handler. + */ +CH_IRQ_HANDLER(I2C2_ER_IRQHandler) { + + CH_IRQ_PROLOGUE(); + i2c_serve_error_interrupt(&I2CD2); + CH_IRQ_EPILOGUE(); +} +#endif + +void i2c_lld_reset(I2CDriver *i2cp){ + chDbgCheck((i2cp->state == I2C_STOP)||(i2cp->state == I2C_READY), + "i2c_lld_reset: invalid state"); + + RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; // reset I2C 1 + RCC->APB1RSTR = 0; +} + +void i2c_lld_set_clock(I2CDriver *i2cp, int32_t clock_speed, I2C_DutyCycle_t duty) { + volatile uint16_t regCCR, regCR2, freq, clock_div; + volatile uint16_t pe_bit_saved; + + chDbgCheck((i2cp != NULL) && (clock_speed > 0) && (clock_speed <= 4000000), + "i2c_lld_set_clock"); + + /*---------------------------- CR2 Configuration ------------------------*/ + /* Get the I2Cx CR2 value */ + regCR2 = i2cp->i2c_register->CR2; + /* Clear frequency FREQ[5:0] bits */ + regCR2 &= (uint16_t)~I2C_CR2_FREQ; + /* Set frequency bits depending on pclk1 value */ + freq = (uint16_t)(STM32_PCLK1 / 1000000); + chDbgCheck((freq >= 2) && (freq <= 36), + "i2c_lld_set_clock() : Peripheral clock freq. out of range"); + regCR2 |= freq; + i2cp->i2c_register->CR2 = regCR2; + + /*---------------------------- CCR Configuration ------------------------*/ + pe_bit_saved = (i2cp->i2c_register->CR1 & I2C_CR1_PE); + /* Disable the selected I2C peripheral to configure TRISE */ + i2cp->i2c_register->CR1 &= (uint16_t)~I2C_CR1_PE; + + /* Clear F/S, DUTY and CCR[11:0] bits */ + regCCR = 0; + clock_div = I2C_CCR_CCR; + /* Configure clock_div in standard mode */ + if (clock_speed <= 100000) { + chDbgAssert(duty == stdDutyCycle, + "i2c_lld_set_clock(), #3", "Invalid standard mode duty cycle"); + /* Standard mode clock_div calculate: Tlow/Thigh = 1/1 */ + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2)); + /* Test if CCR value is under 0x4, and set the minimum allowed value */ + if (clock_div < 0x04) clock_div = 0x04; + /* Set clock_div value for standard mode */ + regCCR |= (clock_div & I2C_CCR_CCR); + /* Set Maximum Rise Time for standard mode */ + i2cp->i2c_register->TRISE = freq + 1; + } + /* Configure clock_div in fast mode */ + else if(clock_speed <= 400000) { + chDbgAssert((duty == fastDutyCycle_2) || (duty == fastDutyCycle_16_9), + "i2c_lld_set_clock(), #3", "Invalid fast mode duty cycle"); + if(duty == fastDutyCycle_2) { + /* Fast mode clock_div calculate: Tlow/Thigh = 2/1 */ + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3)); + } + else if(duty == fastDutyCycle_16_9) { + /* Fast mode clock_div calculate: Tlow/Thigh = 16/9 */ + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 25)); + /* Set DUTY bit */ + regCCR |= I2C_CCR_DUTY; + } + /* Test if CCR value is under 0x1, and set the minimum allowed value */ + if(clock_div < 0x01) clock_div = 0x01; + /* Set clock_div value and F/S bit for fast mode*/ + regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR)); + /* Set Maximum Rise Time for fast mode */ + i2cp->i2c_register->TRISE = (freq * 300 / 1000) + 1; + } + chDbgAssert((clock_div <= I2C_CCR_CCR), + "i2c_lld_set_clock(), #2", "Too low clock clock speed selected"); + + /* Write to I2Cx CCR */ + i2cp->i2c_register->CCR = regCCR; + + /* restore the I2C peripheral enabled state */ + i2cp->i2c_register->CR1 |= pe_bit_saved; +} + +void i2c_lld_set_opmode(I2CDriver *i2cp, I2C_opMode_t opmode) { + uint16_t regCR1; + + /*---------------------------- CR1 Configuration ------------------------*/ + /* Get the I2Cx CR1 value */ + regCR1 = i2cp->i2c_register->CR1; + switch(opmode){ + case opmodeI2C: + regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); + break; + case opmodeSMBusDevice: + regCR1 |= I2C_CR1_SMBUS; + regCR1 &= (uint16_t)~(I2C_CR1_SMBTYPE); + break; + case opmodeSMBusHost: + regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); + break; + } + /* Write to I2Cx CR1 */ + i2cp->i2c_register->CR1 = regCR1; +} + +void i2c_lld_set_own_address(I2CDriver *i2cp, int16_t address, int8_t nbit_addr) { + /*---------------------------- OAR1 Configuration -----------------------*/ + /* Set the Own Address1 and bit number address acknowledged */ + i2cp->i2c_register->OAR1 = address & I2C_OAR1_ADD0_9; + switch(nbit_addr) { + case 10: + i2cp->i2c_register->OAR1 |= I2C_OAR1_ADDMODE; // set ADDMODE bit and bit 14. + case 7: + i2cp->i2c_register->OAR1 |= I2C_OAR1_BIT14; // set only bit 14. + } +} + +/** + * @brief Low level I2C driver initialization. + */ +void i2c_lld_init(void) { + +#if STM32_I2C_USE_I2C1 + RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; // reset I2C 1 + RCC->APB1RSTR = 0; + i2cObjectInit(&I2CD1); + I2CD1.i2c_register = I2C1; +#endif +#if STM32_I2C_USE_I2C2 + RCC->APB1RSTR = RCC_APB1RSTR_I2C2RST; // reset I2C 2 + RCC->APB1RSTR = 0; + i2cObjectInit(&I2CD2); + I2CD2.i2c_register = I2C2; +#endif +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2c_lld_start(I2CDriver *i2cp) { + chDbgCheck((i2cp->state == I2C_STOP)||(i2cp->state == I2C_READY), + "i2c_lld_start: invalid state"); + + /* If in stopped state then enables the I2C clock.*/ + if (i2cp->state == I2C_STOP) { +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + NVICEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); + NVICEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); + RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // I2C 1 clock enable + } +#endif +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + NVICEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); + NVICEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); + RCC->APB1ENR |= RCC_APB1ENR_I2C2EN; // I2C 2 clock enable + } +#endif + i2cp->i2c_register->CR1 |= I2C_CR1_PE; // enable I2C peripheral + } +} + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2c_lld_stop(I2CDriver *i2cp) { + + chDbgCheck((i2cp->state == I2C_READY), + "i2c_lld_stop: invalid state"); + + /* I2C disable.*/ + i2cp->i2c_register->CR1 = 0; + + /* If in ready state then disables the I2C clock.*/ + if (i2cp->state == I2C_READY) { +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + NVICDisableVector(I2C1_EV_IRQn); + NVICDisableVector(I2C1_ER_IRQn); + RCC->APB1ENR &= ~RCC_APB1ENR_I2C1EN; + } +#endif +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + NVICDisableVector(I2C2_EV_IRQn); + NVICDisableVector(I2C2_ER_IRQn); + RCC->APB1ENR &= ~RCC_APB1ENR_I2C2EN; + } +#endif + } +} + +/** + * @brief Transmits data ever the I2C bus as master. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] n number of words to send + * @param[in] slave_addr1 the 7-bit address of the slave (should be aligned to left) + * @param[in] slave_addr2 used in 10 bit address mode + * @param[in] txbuf the pointer to the transmit buffer + * + */ +void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *txbuf) { + + // enable ERR, EVT & BUF ITs + i2cp->i2c_register->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + i2cp->i2c_register->CR1 &= ~I2C_CR1_POS; + + switch(i2cp->nbit_address){ + case 7: + i2cp->slave_addr1 = ((slave_addr <<1) & 0x00FE); // LSB = 0 -> write + break; + case 10: + i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); // add the two msb of 10-bit address to the header + i2cp->slave_addr1 |= 0xF0; // add the header bits with LSB = 0 -> write + i2cp->slave_addr2 = slave_addr & 0x00FF; // the remaining 8 bit of 10-bit address + break; + } + + i2cp->txbuf = txbuf; + i2cp->remaining_bytes = n; + i2cp->flags = 0; + i2cp->errors = 0; + + i2cp->i2c_register->CR1 |= I2C_CR1_START; // send start bit + +#if !I2C_USE_WAIT + /* Wait until the START condition is generated on the bus: the START bit is cleared by hardware */ + uint32_t tmo = 0xfffff; + while((i2cp->i2c_register->CR1 & I2C_CR1_START) && tmo--) + ; +#endif /* I2C_USE_WAIT */ +} + +/** + * @brief Receives data from the I2C bus. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] slave_addr1 7-bit address of he slave + * @param[in] slave_addr2 used in 10-bit address mode + * @param[in] n number of words to receive + * @param[out] rxbuf the pointer to the receive buffer + * + */ +void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *rxbuf) { + // enable ERR, EVT & BUF ITs + i2cp->i2c_register->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + i2cp->i2c_register->CR1 |= I2C_CR1_ACK; // acknowledge returned + i2cp->i2c_register->CR1 &= ~I2C_CR1_POS; + + switch(i2cp->nbit_address){ + case 7: + i2cp->slave_addr1 = ((slave_addr <<1) | 0x01); // LSB = 1 -> receive + break; + case 10: + i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); // add the two msb of 10-bit address to the header + i2cp->slave_addr1 |= 0xF0; // add the header bits (the LSB -> 1 will be add to second + i2cp->slave_addr2 = slave_addr & 0x00FF; // the remaining 8 bit of 10-bit address + break; + } + + i2cp->rxbuf = rxbuf; + i2cp->remaining_bytes = n; + i2cp->flags = I2C_FLG_MASTER_RECEIVER; + i2cp->errors = 0; + + // Only one byte to be received + if(i2cp->remaining_bytes == 1) { + i2cp->flags |= I2C_FLG_1BTR; + } + // Only two bytes to be received + else if(i2cp->remaining_bytes == 2) { + i2cp->flags |= I2C_FLG_2BTR; + i2cp->i2c_register->CR1 |= I2C_CR1_POS; // Acknowledge Position + } + + i2cp->i2c_register->CR1 |= I2C_CR1_START; // send start bit + +#if !I2C_USE_WAIT + /* Wait until the START condition is generated on the bus: the START bit is cleared by hardware */ + uint32_t tmo = 0xfffff; + while((i2cp->i2c_register->CR1 & I2C_CR1_START) && tmo--) + ; +#endif /* I2C_USE_WAIT */ +} + +#endif // HAL_USE_I2C + diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h new file mode 100644 index 000000000..2b63afec9 --- /dev/null +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -0,0 +1,263 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . +*/ + + +/** + * @file STM32/i2c_lld.h + * @brief STM32 I2C subsystem low level driver header. + * @addtogroup STM32_I2C + * @{ + */ + +#ifndef _I2C_LLD_H_ +#define _I2C_LLD_H_ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ +#define I2C_OAR1_ADD0_9 ((uint16_t)0x03FF) /*!= @p STM32_I2C1_IRQ_PRIORITY > @p PRIORITY_PENDSV. + */ +#if !defined(STM32_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C1_IRQ_PRIORITY 0xA0 +#endif + +/** + * @brief I2C2 interrupt priority level setting. + * @note @p BASEPRI_KERNEL >= @p STM32_I2C2_IRQ_PRIORITY > @p PRIORITY_PENDSV. + */ +#if !defined(STM32_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_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 + +#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 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 Serial Driver condition flags type. + */ +typedef uint32_t i2cflags_t; + +typedef enum { + opmodeI2C, + opmodeSMBusDevice, + opmodeSMBusHost, +} I2C_opMode_t; + +typedef enum { + stdDutyCycle, + fastDutyCycle_2, + fastDutyCycle_16_9, +} I2C_DutyCycle_t; + +/** + * @brief Type of a structure representing an SPI driver. + */ +typedef struct I2CDriver I2CDriver; + +/** + * @brief I2C notification callback type. + * + * @param[in] i2cp pointer to the @p I2CDriver object triggering the + * callback + */ +typedef void (*i2ccallback_t)(I2CDriver *i2cp); + +/** + * @brief Driver configuration structure. + */ +typedef struct { + I2C_opMode_t opMode; /*!< Specifies the I2C mode.*/ + + uint32_t ClockSpeed; /*!< Specifies the clock frequency. Must be set to a value lower than 400kHz */ + + I2C_DutyCycle_t FastModeDutyCycle; /*!< Specifies the I2C fast mode duty cycle */ + + uint16_t OwnAddress1; /*!< Specifies the first device own address. Can be a 7-bit or 10-bit address. */ + + uint16_t Ack; /*!< Enables or disables the acknowledgement. */ + + uint8_t nBitAddress; /*!< Specifies if 7-bit or 10-bit address is acknowledged */ + +} I2CConfig; + +/** + * @brief Structure representing an I2C driver. + */ +struct I2CDriver { + /** + * @brief Driver state. + */ + i2cstate_t state; + /** + * @brief Operation complete callback or @p NULL. + */ + i2ccallback_t endcb; +#if I2C_USE_WAIT + /** + * @brief Thread waiting for I/O completion. + */ + Thread *thread; +#endif /* I2C_USE_WAIT */ +#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) +#if CH_USE_MUTEXES || defined(__DOXYGEN__) + /** + * @brief Mutex protecting the bus. + */ + Mutex mutex; +#elif CH_USE_SEMAPHORES + Semaphore semaphore; +#endif +#endif /* I2C_USE_MUTUAL_EXCLUSION */ + + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the I2Cx registers block. + */ + I2C_TypeDef *i2c_register; + size_t remaining_bytes; + uint8_t *rxbuf; + uint8_t *txbuf; + uint8_t slave_addr1; // 7-bit address of the slave + uint8_t slave_addr2; // used in 10-bit address mode + uint8_t nbit_address; + i2cflags_t errors; + i2cflags_t flags; + /* Status Change @p EventSource.*/ + EventSource sevent; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +#define i2c_lld_bus_is_busy(i2cp) \ + (i2cp->i2c_register->SR2 & I2C_SR2_BUSY) + + +/* Wait until BUSY flag is reset: a STOP has been generated on the bus + * signaling the end of transmission + */ +#define i2c_lld_wait_bus_free(i2cp) { \ + uint32_t tmo = 0xffff; \ + while((i2cp->i2c_register->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, int32_t clock_speed, I2C_DutyCycle_t duty); +void i2c_lld_set_opmode(I2CDriver *i2cp, I2C_opMode_t opmode); +void i2c_lld_set_own_address(I2CDriver *i2cp, int16_t address, int8_t nr_bit); +void i2c_lld_start(I2CDriver *i2cp); +void i2c_lld_stop(I2CDriver *i2cp); +void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *txbuf); +void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *rxbuf); + +#ifdef __cplusplus +} +#endif +/** @endcond*/ + +#endif // CH_HAL_USE_I2C + +#endif // _I2C_LLD_H_ diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c new file mode 100644 index 000000000..64bed78eb --- /dev/null +++ b/os/hal/src/i2c.c @@ -0,0 +1,268 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . +*/ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/** + * @brief I2C Driver initialization. + */ +void i2cInit(void) { + + i2c_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p I2CDriver structure. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2cObjectInit(I2CDriver *i2cp) { + chEvtInit(&i2cp->sevent); + i2cp->errors = I2CD_NO_ERROR; + i2cp->state = I2C_STOP; +// i2cp->i2cd_config = NULL; +#if I2C_USE_WAIT + i2cp->thread = NULL; +#endif /* I2C_USE_WAIT */ +#if I2C_USE_MUTUAL_EXCLUSION +#if CH_USE_MUTEXES + chMtxInit(&i2cp->mutex); +#elif CH_USE_SEMAPHORES + chSemInit(&i2cp->semaphore, 1); +#endif +#endif /* I2C_USE_MUTUAL_EXCLUSION */ +#if defined(I2C_DRIVER_EXT_INIT_HOOK) + I2C_DRIVER_EXT_INIT_HOOK(i2cp); +#endif +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] config pointer to the @p I2CConfig object + */ +void i2cStart(I2CDriver *i2cp, const I2CConfig *config) { + + chDbgCheck((i2cp != NULL) && (config != NULL), "i2cStart"); + + chSysLock(); + chDbgAssert((i2cp->state == I2C_STOP)||(i2cp->state == I2C_READY), + "i2cStart(), #1", "invalid state"); + + i2cp->nbit_address = config->nBitAddress; + i2c_lld_start(i2cp); + i2c_lld_set_clock(i2cp, config->ClockSpeed, config->FastModeDutyCycle); + i2c_lld_set_opmode(i2cp, config->opMode); + i2c_lld_set_own_address(i2cp, config->OwnAddress1, config->nBitAddress); + i2cp->state = I2C_READY; + chSysUnlock(); +} + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2cStop(I2CDriver *i2cp) { + + chDbgCheck(i2cp != NULL, "i2cStop"); + + chSysLock(); + chDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY), + "i2cStop(), #1", "invalid state"); + i2c_lld_stop(i2cp); + i2cp->state = I2C_STOP; + chSysUnlock(); +} + +/** + * @brief Sends data ever the I2C bus. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] slave_addr 7-bit or 10-bit address of the slave + * @param[in] n number of words to send + * @param[in] txbuf the pointer to the transmit buffer + * + */ +void i2cMasterTransmit(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *txbuf) { + + chDbgCheck((i2cp != NULL) && (n > 0) && (txbuf != NULL), + "i2cMasterTransmit"); + +#if I2C_USE_WAIT + i2c_lld_wait_bus_free(i2cp); + if(i2c_lld_bus_is_busy(i2cp)) { +#ifdef PRINTTRACE + print("I2C Bus busy!\n"); +#endif + return; + }; +#endif + + chSysLock(); + chDbgAssert(i2cp->state == I2C_READY, + "i2cMasterTransmit(), #1", "not ready"); + + i2cp->state = I2C_ACTIVE; + i2c_lld_master_transmit(i2cp, slave_addr, n, txbuf); + _i2c_wait_s(i2cp); +#if !I2C_USE_WAIT + i2c_lld_wait_bus_free(i2cp); +#endif + if (i2cp->state == I2C_COMPLETE) + i2cp->state = I2C_READY; + chSysUnlock(); +} + +/** + * @brief Receives data from the I2C bus. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] slave_addr 7-bit or 10-bit address of the slave + * @param[in] n number of bytes to receive + * @param[out] rxbuf the pointer to the receive buffer + * + */ +void i2cMasterReceive(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *rxbuf) { + + chDbgCheck((i2cp != NULL) && (n > 0) && (rxbuf != NULL), + "i2cMasterReceive"); + +#if I2C_USE_WAIT + i2c_lld_wait_bus_free(i2cp); + if(i2c_lld_bus_is_busy(i2cp)) { +#ifdef PRINTTRACE + print("I2C Bus busy!\n"); +#endif + return; + }; +#endif + + chSysLock(); + chDbgAssert(i2cp->state == I2C_READY, + "i2cMasterReceive(), #1", "not ready"); + + i2cp->state = I2C_ACTIVE; + i2c_lld_master_receive(i2cp, slave_addr, n, rxbuf); + _i2c_wait_s(i2cp); +#if !I2C_USE_WAIT + i2c_lld_wait_bus_free(i2cp); +#endif + if (i2cp->state == I2C_COMPLETE) + i2cp->state = I2C_READY; + chSysUnlock(); +} + +uint16_t i2cSMBusAlertResponse(I2CDriver *i2cp) { + uint16_t slv_addr; + + i2cMasterReceive(i2cp, 0x0C, 2, &slv_addr); + return slv_addr; +} + + +/** + * @brief Handles communication events/errors. + * @details Must be called from the I/O interrupt service routine in order to + * notify I/O conditions as errors, signals change etc. + * + * @param[in] i2cp pointer to a @p I2CDriver structure + * @param[in] mask condition flags to be added to the mask + * + * @iclass + */ +void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask) { + + chDbgCheck(i2cp != NULL, "i2cAddFlagsI"); + + i2cp->errors |= mask; + chEvtBroadcastI(&i2cp->sevent); +} + +/** + * @brief Returns and clears the errors mask associated to the driver. + * + * @param[in] i2cp pointer to a @p I2CDriver structure + * @return The condition flags modified since last time this + * function was invoked. + * + * @api + */ +i2cflags_t i2cGetAndClearFlags(I2CDriver *i2cp) { + i2cflags_t mask; + + chDbgCheck(i2cp != NULL, "i2cGetAndClearFlags"); + + chSysLock(); + mask = i2cp->errors; + i2cp->errors = I2CD_NO_ERROR; + chSysUnlock(); + return mask; +} + + + +#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) +/** + * @brief Gains exclusive access to the I2C bus. + * @details This function tries to gain ownership to the I2C bus, if the bus + * is already being used then the invoking thread is queued. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @note This function is only available when the @p I2C_USE_MUTUAL_EXCLUSION + * option is set to @p TRUE. + */ +void i2cAcquireBus(I2CDriver *i2cp) { + + chDbgCheck(i2cp != NULL, "i2cAcquireBus"); + +#if CH_USE_MUTEXES + chMtxLock(&i2cp->mutex); +#elif CH_USE_SEMAPHORES + chSemWait(&i2cp->semaphore); +#endif +} + +/** + * @brief Releases exclusive access to the I2C bus. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @note This function is only available when the @p I2C_USE_MUTUAL_EXCLUSION + * option is set to @p TRUE. + */ +void i2cReleaseBus(I2CDriver *i2cp) { + + chDbgCheck(i2cp != NULL, "i2cReleaseBus"); + +#if CH_USE_MUTEXES + (void)i2cp; + chMtxUnlock(); +#elif CH_USE_SEMAPHORES + chSemSignal(&i2cp->semaphore); +#endif +} +#endif /* I2C_USE_MUTUAL_EXCLUSION */ + +#endif /* CH_HAL_USE_I2C */ From a74dd37c2cad661eee2070888a55a99e49745b6b Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 5 Feb 2011 18:10:23 +0000 Subject: [PATCH 16/92] I2C. Moved Alberto drivers to backup. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2711 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/{i2c.h => i2c_albi.h} | 0 os/hal/platforms/STM32/{i2c_lld.c => i2c_lld_albi.c} | 0 os/hal/platforms/STM32/{i2c_lld.h => i2c_lld_albi.h} | 0 os/hal/src/{i2c.c => i2c_albi.c} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename os/hal/include/{i2c.h => i2c_albi.h} (100%) rename os/hal/platforms/STM32/{i2c_lld.c => i2c_lld_albi.c} (100%) rename os/hal/platforms/STM32/{i2c_lld.h => i2c_lld_albi.h} (100%) rename os/hal/src/{i2c.c => i2c_albi.c} (100%) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c_albi.h similarity index 100% rename from os/hal/include/i2c.h rename to os/hal/include/i2c_albi.h diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld_albi.c similarity index 100% rename from os/hal/platforms/STM32/i2c_lld.c rename to os/hal/platforms/STM32/i2c_lld_albi.c diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld_albi.h similarity index 100% rename from os/hal/platforms/STM32/i2c_lld.h rename to os/hal/platforms/STM32/i2c_lld_albi.h diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c_albi.c similarity index 100% rename from os/hal/src/i2c.c rename to os/hal/src/i2c_albi.c From d6f77c1ef14cc6b4636fde34d2025e5f23bc9e36 Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 5 Feb 2011 18:22:45 +0000 Subject: [PATCH 17/92] I2C. After comparing of two drivers decided to start of importing features from Alberto driver to mine. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2712 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 146 ++++++++++ os/hal/platforms/STM32/i2c_lld.c | 462 +++++++++++++++++++++++++++++++ os/hal/platforms/STM32/i2c_lld.h | 267 ++++++++++++++++++ os/hal/src/i2c.c | 215 ++++++++++++++ 4 files changed, 1090 insertions(+) create mode 100644 os/hal/include/i2c.h create mode 100644 os/hal/platforms/STM32/i2c_lld.c create mode 100644 os/hal/platforms/STM32/i2c_lld.h create mode 100644 os/hal/src/i2c.c diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h new file mode 100644 index 000000000..64816186b --- /dev/null +++ b/os/hal/include/i2c.h @@ -0,0 +1,146 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . +*/ + +/** + * @file i2c.h + * @brief I2C Driver macros and structures. + * + * @addtogroup I2C + * @{ + */ + +#ifndef _I2C_H_ +#define _I2C_H_ + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + I2C_UNINIT = 0, /**< Not initialized. */ + I2C_STOP = 1, /**< Stopped. */ + I2C_READY = 2, /**< Ready. */ + I2C_MACTIVE = 3, /**< START condition sent. */ + I2C_MTRANSMIT = 4, /**< Master transmitting. */ + I2C_MRECEIVE = 5, /**< Master receiving. */ + I2C_MWAIT_TF = 6, /**< Master wait Transmission Finished */ + I2C_MERROR = 7 /**< Error condition. */ +} i2cstate_t; + +#include "i2c_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Read mode. + */ +#define I2C_READ 1 + +/** + * @brief Write mode. + */ +#define I2C_WRITE 0 + +/** + * @brief Seven bits addresses header builder. + * + * @param[in] addr seven bits address value + * @param[in] rw read/write flag + * + * @return A 16 bit value representing the header, the most + * significant byte is always zero. + */ +#define I2C_ADDR7(addr, rw) (uint16_t)((addr) << 1 | (rw)) + + +/** + * @brief Ten bits addresses header builder. + * + * @param[in] addr ten bits address value + * @param[in] rw read/write flag + * + * @return A 16 bit value representing the header, the most + * significant byte is the first one to be transmitted. + */ +#define I2C_ADDR10(addr, rw) \ + (uint16_t)(0xF000 | \ + (((addr) & 0x0300) << 1) | \ + (((rw) << 8)) | \ + ((addr) & 0x00FF)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ +#ifdef __cplusplus +extern "C" { +#endif + void i2cInit(void); + void i2cObjectInit(I2CDriver *i2cp); + void i2cStart(I2CDriver *i2cp, I2CConfig *config); + void i2cStop(I2CDriver *i2cp); + void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); + void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); + + + + void i2cMasterStartI(I2CDriver *i2cp,uint16_t header); + void i2cMasterStopI(I2CDriver *i2cp); + void i2cMasterRestartI(I2CDriver *i2cp); + void i2cMasterTransmitI(I2CDriver *i2cp, size_t n, const uint8_t *txbuf); + void i2cMasterReceiveI(I2CDriver *i2cp, size_t n, uint8_t *rxbuf); +#if I2C_USE_MUTUAL_EXCLUSION + void i2cAcquireBus(I2CDriver *i2cp); + void i2cReleaseBus(I2CDriver *i2cp); +#endif /* I2C_USE_MUTUAL_EXCLUSION */ +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2C */ + +#endif /* _I2C_H_ */ + +/** @} */ diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c new file mode 100644 index 000000000..9e519d412 --- /dev/null +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -0,0 +1,462 @@ +/** + * @file STM32/i2c_lld.c + * @brief STM32 I2C subsystem low level driver source. Slave mode not implemented. + * @addtogroup STM32_I2C + * @{ + */ + +#include "ch.h" +#include "hal.h" +#include "i2c_lld.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief I2C1 driver identifier.*/ +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +I2CDriver I2CD1; +#endif + +/** @brief I2C2 driver identifier.*/ +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +I2CDriver I2CD2; +#endif + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief TODO: Status bits translation. + * + * @param[in] sr USART SR register value + * + * @return The error flags. + */ +static i2cflags_t translate_i2c_errors(uint16_t sr) { + i2cflags_t sts = 0; + + if (sr & USART_SR_ORE) + sts |= UART_OVERRUN_ERROR; + if (sr & USART_SR_PE) + sts |= UART_PARITY_ERROR; + if (sr & USART_SR_FE) + sts |= UART_FRAMING_ERROR; + if (sr & USART_SR_NE) + sts |= UART_NOISE_ERROR; + if (sr & USART_SR_LBD) + sts |= UART_BREAK_DETECTED; + return sts; +} + + +static void i2c_serve_error_interrupt(I2CDriver *i2cp) { + // TODO:remove this stub and write normal handler + // this is simply trap for errors + while TRUE{ + translate_i2c_errors(i2cp->id_i2c->SR1); + } +} + +/* This function handle all regular interrupt conditions + * TODO: 10 bit address handling here + */ +static void i2c_serve_event_interrupt(I2CDriver *i2cp) { + int i = 0; + int n = 0; + int m = 0; + + if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent + //i = i2cp->id_i2c->SR1; + i2cp->id_state = I2C_MACTIVE; + i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | + i2cp->id_slave_config->rw_bit; // write slave address in DR + return; + } + + // now "wait" interrupt with ADDR flag + if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address successfully sent + if(i2cp->id_i2c->SR2 & I2C_SR2_TRA){ + i2c_lld_txbyte(i2cp); // send first byte + i2cp->id_state = I2C_MTRANSMIT; // change state + return; + } + else { + /* In order to generate the non-acknowledge pulse after the last received + * data byte, the ACK bit must be cleared just after reading the second + * last data byte (after second last RxNE event). + */ + if (i2cp->id_slave_config->rxbytes > 1) + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // set ACK bit + i2cp->id_state = I2C_MRECEIVE; // change status + return; + } + } + + // transmitting bytes one by one + if ((i2cp->id_state == I2C_MTRANSMIT) && (i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ + if (i2c_lld_txbyte(i2cp)) + i2cp->id_state = I2C_MWAIT_TF; // last byte written + return; + } + + //receiving bytes one by one + if ((i2cp->id_state == I2C_MRECEIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ +// i = i2cp->id_i2c->SR1; +// n = i2cp->id_i2c->SR2; + if (i2c_lld_rxbyte(i2cp)) + i2cp->id_state = I2C_MWAIT_TF; // last byte read +// i = i2cp->id_i2c->SR1; +// n = i2cp->id_i2c->SR2; + return; + } + + // "wait" BTF bit in status register +// if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ + if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE | I2C_SR1_BTF | I2C_SR1_TXE)){ + chSysLockFromIsr(); + i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); + + i = i2cp->id_i2c->SR1; + n = i2cp->id_i2c->SR2; + m = i2cp->id_i2c->CR1; + + chSysUnlockFromIsr(); + return; + } + else{ // trap + i = i2cp->id_i2c->SR1; + n = i2cp->id_i2c->SR2; + m = i2cp->id_i2c->CR1; + return; + } +} + + +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +/** + * @brief I2C1 event interrupt handler. + */ +CH_IRQ_HANDLER(VectorBC) { + + CH_IRQ_PROLOGUE(); + i2c_serve_event_interrupt(&I2CD1); + CH_IRQ_EPILOGUE(); +} + +/** + * @brief I2C1 error interrupt handler. + */ +CH_IRQ_HANDLER(VectorC0) { + + CH_IRQ_PROLOGUE(); + i2c_serve_error_interrupt(&I2CD1); + CH_IRQ_EPILOGUE(); +} +#endif + +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +/** + * @brief I2C2 event interrupt handler. + */ +CH_IRQ_HANDLER(VectorC4) { + + CH_IRQ_PROLOGUE(); + i2c_serve_event_interrupt(&I2CD2); + CH_IRQ_EPILOGUE(); +} + +/** + * @brief I2C2 error interrupt handler. + */ +CH_IRQ_HANDLER(VectorC8) { + + CH_IRQ_PROLOGUE(); + i2c_serve_error_interrupt(&I2CD2); + CH_IRQ_EPILOGUE(); +} +#endif + +/** + * @brief Low level I2C driver initialization. + */ +void i2c_lld_init(void) { + +#if STM32_I2C_USE_I2C1 + RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; // reset I2C 1 + RCC->APB1RSTR = 0; + i2cObjectInit(&I2CD1); + I2CD1.id_i2c = I2C1; +#endif + +#if STM32_I2C_USE_I2C2 + RCC->APB1RSTR = RCC_APB1RSTR_I2C2RST; // reset I2C 2 + RCC->APB1RSTR = 0; + i2cObjectInit(&I2CD2); + I2CD2.id_i2c = I2C2; +#endif +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2c_lld_start(I2CDriver *i2cp) { + + /* If in stopped state then enables the I2C clock.*/ + if (i2cp->id_state == I2C_STOP) { +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + NVICEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); + NVICEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); + RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // I2C 1 clock enable + } +#endif +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + NVICEnableVector(I2C2_EV_IRQn, STM32_I2C2_IRQ_PRIORITY); + NVICEnableVector(I2C2_ER_IRQn, STM32_I2C2_IRQ_PRIORITY); + RCC->APB1ENR |= RCC_APB1ENR_I2C2EN; // I2C 2 clock enable + } +#endif + } + + /* I2C setup.*/ + i2cp->id_i2c->CR1 = I2C_CR1_SWRST; // reset i2c peripherial + i2cp->id_i2c->CR1 = 0; + + i2cp->id_i2c->CR1 = i2cp->id_config->i2cc_cr1; + i2cp->id_i2c->CR2 = i2cp->id_config->i2cc_cr2 | + I2C_CR2_ITERREN | + I2C_CR2_ITEVTEN | + I2C_CR2_ITBUFEN | + 36; //TODO: replace this by macro calculation + /* TODO: + * 1. macro timing calculator + * 2. parameter checker + * 3. definitions in halconf.h: i2c-freq, i2c_mode, etc + * 4. trise time calculator/checker + */ + i2cp->id_i2c->CCR = i2cp->id_config->i2cc_ccr | 180; + i2cp->id_i2c->TRISE = i2cp->id_config->i2cc_trise | 37; + i2cp->id_i2c->CR1 |= 1; // enable interface +} + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2c_lld_stop(I2CDriver *i2cp) { + + /* If in ready state then disables the I2C clock.*/ + if (i2cp->id_state == I2C_READY) { +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + NVICDisableVector(I2C1_EV_IRQn); + NVICDisableVector(I2C1_ER_IRQn); + RCC->APB1ENR &= ~RCC_APB1ENR_I2C1EN; + } +#endif +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + NVICDisableVector(I2C2_EV_IRQn); + NVICDisableVector(I2C2_ER_IRQn); + RCC->APB1ENR &= ~RCC_APB1ENR_I2C2EN; + } +#endif + } + i2cp->id_state = I2C_STOP; +} + + +/* helper function, not API + * write bytes in DR register + * return TRUE if last byte written + */ +bool_t i2c_lld_txbyte(I2CDriver *i2cp) { + if (i2cp->id_slave_config->txbufhead < i2cp->id_slave_config->txbytes){ + i2cp->id_i2c->DR = i2cp->id_slave_config->txbuf[i2cp->id_slave_config->txbufhead]; + (i2cp->id_slave_config->txbufhead)++; + return(FALSE); + } + i2cp->id_slave_config->txbufhead = 0; + return(TRUE); // last byte written +} + + +/* helper function, not API + * read bytes from DR register + * return TRUE if last byte read + */ +bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { + // temporal variables + #define rxbuf i2cp->id_slave_config->rxbuf + #define rxbufhead i2cp->id_slave_config->rxbufhead + #define rxdepth i2cp->id_slave_config->rxdepth + #define rxbytes i2cp->id_slave_config->rxbytes + + /* In order to generate the non-acknowledge pulse after the last received + * data byte, the ACK bit must be cleared just after reading the second + * last data byte (after second last RxNE event). + */ + if (rxbufhead < rxbytes){ + rxbuf[rxbufhead] = i2cp->id_i2c->DR; + if ((rxbytes - rxbufhead) <= 2){ + i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);// clear ACK bit for automatically send NACK + } + rxbufhead++; + return(FALSE); + } + + rxbuf[rxbufhead] = i2cp->id_i2c->DR; // read last byte + rxbufhead = 0; + #undef rxbuf + #undef rxbufhead + #undef rxdepth + #undef rxbytes + + return(TRUE); // last byte read +} + + +void i2c_lld_master_start(I2CDriver *i2cp){ + i2cp->id_i2c->CR1 |= I2C_CR1_START; +} + +void i2c_lld_master_stop(I2CDriver *i2cp){ + i2cp->id_i2c->CR1 |= I2C_CR1_STOP; + chSysLock(); + while (i2cp->id_i2c->CR1 & I2C_CR1_STOP); + chSysUnlock(); +} + + +void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ + //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hylevel API + + i2cp->id_slave_config = i2cscfg; + i2cp->id_slave_config->rw_bit = I2C_WRITE; + + // generate start condition. Later transmission goes in background + i2c_lld_master_start(i2cp); +} + +void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ + //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hylevel API + + i2cp->id_slave_config = i2cscfg; + i2cp->id_slave_config->rw_bit = I2C_READ; + + // generate (re)start condition. Later connection goes asynchronously + i2c_lld_master_start(i2cp); +} + + + +/** + * @brief Transmits data ever the I2C bus as masteri2cp. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object + * @param[in] restart bool. If TRUE then generate restart condition insted of stop + */ +void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart) { + //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hylevel API + + int i = 0; + + i2cp->id_slave_config = i2cscfg; + i2cp->id_slave_config->rw_bit = I2C_WRITE; + + + i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate start condition + while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)){ + i++; // wait Address sent + } + + i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | I2C_WRITE; // write slave addres in DR + while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){ + i++; // wait Address sent + } + i = i2cp->id_i2c->SR2; // TODO: check is it need to read this register for I2C to proper functionality + i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit + + // now write data byte by byte in DR register + uint32_t n = 0; + for (n = 0; n < i2cp->id_slave_config->txbytes; n++){ + i2cp->id_i2c->DR = i2cscfg->txbuf[n]; + while (!(i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ + i++; + } + } + + while (!(i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ + i++; + } + + if (restart){ + i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate restart condition + while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)){ + i++; // wait start bit + } + } + else i2cp->id_i2c->CR1 |= I2C_CR1_STOP; // generate stop condition +} + + +/** + * @brief Receives data from the I2C bus. + * @details Before receive data from I2C slave you must manually sent them some + * control bytes first (refer to you device datasheet). + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object + */ +void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { + + chSysLock(); + + i2cp->id_slave_config = i2cscfg; + + uint16_t i = 0; + uint16_t tmp = 0; + + // send slave addres with read-bit + i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | I2C_READ; + while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){ + i++; // wait Address sent + } + i = i2cp->id_i2c->SR2; // TODO: check is it need to read this register for I2C to proper functionality + i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit + + // set ACK bit + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; + + // collect data from slave + for (i = 0; i < i2cp->id_slave_config->rxbytes; i++){ + if ((i2cp->id_slave_config->rxbytes - i) == 1){ // TODO: is it better <= in place of == ? + // clear ACK bit for automatically send NACK + i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);} + while (!(i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ + tmp++; + } + i2cp->id_slave_config->rxbuf[i] = i2cp->id_i2c->DR; + } + // generate STOP + i2cp->id_i2c->CR1 |= I2C_CR1_STOP; + + chSysUnlock(); +} + + + +#endif // HAL_USE_I2C diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h new file mode 100644 index 000000000..bac1dfff0 --- /dev/null +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -0,0 +1,267 @@ +/** + * @file STM32/i2c_lld.h + * @brief STM32 I2C subsystem low level driver header. + * @addtogroup STM32_I2C + * @{ + */ + +#ifndef _I2C_LLD_H_ +#define _I2C_LLD_H_ + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @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 No pending conditions.*/ +#define I2C_NO_ERROR 0 +/*@brief external Stop or Start condition during an address or a data transfer*/ +#define I2C_BUS_ERROR 1 +/** @brief */ +#define I2C_ARBITRATION_LOSS 2 +/** @brief */ +#define I2C_ACK_FAIL 4 +/** @brief */ +#define I2C_OVERRUN_UNDERRUN 8 +/** @brief */ +#define I2C_PEC_ERROR 16 +/** @brief */ +#define I2C_TIMEOUT 32 +/** @brief */ +#define I2C_SMBUS_ALERT 64 + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a structure representing an I2C driver. + */ +typedef struct I2CDriver I2CDriver; + +/** + * @brief Type of a structure representing an I2C driver. + */ +typedef struct I2CSlaveConfig I2CSlaveConfig; + + +/** + * @brief I2C notification callback type. + * @details This function must be used to send start or stop events to I2C bus, + * and change states of I2CDriver. + * + * @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, I2CSlaveConfig *i2cscfg); + + +/** + * @brief I2C error notification callback type. + * + * @param[in] i2cp TODO: pointer to the @p I2CDriver object triggering the + * callback + */ +typedef void (*i2cerrorcallback_t)(void); + + +/** + * @brief Driver configuration structure. + */ +typedef struct { + /** + * @brief I2C initialization data. + */ + uint16_t i2cc_cr1; + uint16_t i2cc_cr2; + uint16_t i2cc_ccr; + uint16_t i2cc_trise; + +} I2CConfig; + + +/** + * @brief TODO: + */ +typedef uint32_t i2cflags_t; + +/** + * @brief TODO: + */ +typedef uint8_t i2cblock_t; + + +/** + * @brief Structure representing an I2C slave configuration. + * @details Each slave has its own data buffers, adress, and error flags. + */ +struct I2CSlaveConfig{ + /** + * @brief Callback pointer. + * @note Transfer finished callback. Invoke when all data transferred, or + * by DMA buffer events + * @p NULL then the callback is disabled. + */ + i2ccallback_t id_callback; + /** + * @brief Callback pointer. + * @note TODO: I don't know, when this callback is inwoked + * @p NULL then the callback is disabled. + */ + i2cerrorcallback_t id_err_callback; + + i2cblock_t *rxbuf; // pointer to buffer + size_t rxdepth; // depth of buffer + size_t rxbytes; // count of bytes to sent in one sending + size_t rxbufhead; // head pointer to current data byte + + i2cblock_t *txbuf; + size_t txdepth; + size_t txbytes; + size_t txbufhead; + + uint8_t slave_addr1; // 7-bit address of the slave + uint8_t slave_addr2; // used in 10-bit address mode + + uint16_t error_flags; + + uint8_t rw_bit; // this flag contain R/W bit + + bool_t restart; // send restart or stop event after complete data tx/rx + +}; + + + +/** + * @brief Structure representing an I2C driver. + */ +struct I2CDriver{ + /** + * @brief Driver state. + */ + i2cstate_t id_state; +#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. + */ + I2CConfig *id_config; + /** + * @brief Current slave configuration data. + */ + I2CSlaveConfig *id_slave_config; + + /* End of the mandatory fields.*/ + /** + * @brief Thread waiting for I/O completion. + */ + Thread *id_thread; + /** + * @brief Pointer to the I2Cx registers block. + */ + I2C_TypeDef *id_i2c; + +} ; + + + + + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* 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_start(I2CDriver *i2cp); +void i2c_lld_stop(I2CDriver *i2cp); + +void i2c_lld_master_start(I2CDriver *i2cp); +void i2c_lld_master_stop(I2CDriver *i2cp); + +void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); +void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); +bool_t i2c_lld_txbyte(I2CDriver *i2cp); // helper function + +void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); +void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); +bool_t i2c_lld_rxbyte(I2CDriver *i2cp); + +#ifdef __cplusplus +} +#endif +/** @endcond*/ + +#endif // CH_HAL_USE_I2C + +#endif // _I2C_LLD_H_ diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c new file mode 100644 index 000000000..5a0471e0f --- /dev/null +++ b/os/hal/src/i2c.c @@ -0,0 +1,215 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . +*/ + +/** + * @file i2c.c + * @brief I2C Driver code. + * + * @addtogroup I2C + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief I2C Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void i2cInit(void) { + i2c_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p I2CDriver structure. + * + * @param[out] i2cp pointer to the @p I2CDriver object + * + * @init + */ +void i2cObjectInit(I2CDriver *i2cp) { + + i2cp->id_state = I2C_STOP; + i2cp->id_config = NULL; + i2cp->id_slave_config = NULL; +#if defined(I2C_DRIVER_EXT_INIT_HOOK) + I2C_DRIVER_EXT_INIT_HOOK(i2cp); +#endif +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] config pointer to the @p I2CConfig object + * + * @api + */ +void i2cStart(I2CDriver *i2cp, I2CConfig *config) { + + chDbgCheck((i2cp != NULL) && (config != NULL), "i2cStart"); + + chSysLock(); + chDbgAssert((i2cp->id_state == I2C_STOP) || (i2cp->id_state == I2C_READY), + "i2cStart(), #1", + "invalid state"); + i2cp->id_config = config; + i2c_lld_start(i2cp); + i2cp->id_state = I2C_READY; + chSysUnlock(); +} + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @api + */ +void i2cStop(I2CDriver *i2cp) { + + chDbgCheck(i2cp != NULL, "i2cStop"); + + chSysLock(); + chDbgAssert((i2cp->id_state == I2C_STOP) || (i2cp->id_state == I2C_READY), + "i2cStop(), #1", + "invalid state"); + i2c_lld_stop(i2cp); + i2cp->id_state = I2C_STOP; + chSysUnlock(); +} + +/** + * @brief Sends data ever the I2C bus. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] slave_addr1 7-bit address of the slave + * @param[in] slave_addr1 used in 10-bit address mode + * @param[in] n number of words to send + * @param[in] txbuf the pointer to the transmit buffer + * + */ +void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { + + chDbgCheck((i2cp != NULL) && (i2cscfg != NULL), + "i2cMasterTransmit"); + chDbgAssert(i2cp->id_state == I2C_READY, + "i2cMasterTransmit(), #1", + "not active"); + + i2c_lld_master_transmitI(i2cp, i2cscfg); +} + + +/** + * @brief Receives data from the I2C bus. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] slave_addr1 7-bit address of the slave + * @param[in] slave_addr1 used in 10-bit address mode + * @param[in] n number of words to receive + * @param[out] rxbuf the pointer to the receive buffer + * + */ +void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { + + chDbgCheck((i2cp != NULL) && (i2cscfg != NULL), + "i2cMasterReceive"); + chDbgAssert(i2cp->id_state == I2C_READY, + "i2cMasterReceive(), #1", + "not active"); + + i2c_lld_master_receiveI(i2cp, i2cscfg); +} + + + + + + +#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) +/** + * @brief Gains exclusive access to the I2C bus. + * @details This function tries to gain ownership to the I2C bus, if the bus + * is already being used then the invoking thread is queued. + * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @api + * + */ +void i2cAcquireBus(I2CDriver *i2cp) { + + chDbgCheck(i2cp != NULL, "i2cAcquireBus"); + +#if CH_USE_MUTEXES + chMtxLock(&i2cp->id_mutex); +#elif CH_USE_SEMAPHORES + chSemWait(&i2cp->id_semaphore); +#endif +} + +/** + * @brief Releases exclusive access to the I2C bus. + * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @api + */ +void i2cReleaseBus(I2CDriver *i2cp) { + + chDbgCheck(i2cp != NULL, "i2cReleaseBus"); + +#if CH_USE_MUTEXES + (void)i2cp; + chMtxUnlock(); +#elif CH_USE_SEMAPHORES + chSemSignal(&i2cp->id_semaphore); +#endif +} +#endif /* I2C_USE_MUTUAL_EXCLUSION */ + +#endif /* HAL_USE_I2C */ + +/** @} */ From 00800dd8ed98bfc23cfb9d4c50fa84ef0e2e0898 Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 6 Feb 2011 13:36:29 +0000 Subject: [PATCH 18/92] I2C. Async transfer complete. Needs testing. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2716 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 59 +++++++++++++++++++------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 71873be05..7a7a071ec 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -122,6 +122,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { // if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ chSysLockFromIsr(); + i2cp->id_i2c->CR2 &= (~I2C_CR2_ITEVTEN); // disable BTF interrupt i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); i = i2cp->id_i2c->SR1; @@ -283,16 +284,23 @@ void i2c_lld_stop(I2CDriver *i2cp) { * return TRUE if last byte written */ bool_t i2c_lld_txbyte(I2CDriver *i2cp) { - void *txbufhead = i2cp->id_slave_config->txbufhead; - void *txbytes = i2cp->id_slave_config->txbytes; +#define _txbufhead (i2cp->id_slave_config->txbufhead) +#define _txbytes (i2cp->id_slave_config->txbytes) +#define _txbuf (i2cp->id_slave_config->txbuf) - if (i2cp->id_slave_config->txbufhead < i2cp->id_slave_config->txbytes){ - i2cp->id_i2c->DR = i2cp->id_slave_config->txbuf[i2cp->id_slave_config->txbufhead]; - (i2cp->id_slave_config->txbufhead)++; + if (_txbufhead < _txbytes){ + /* disable interrupt to avoid jumping to ISR */ + if ( _txbytes - _txbufhead == 1) + i2cp->id_i2c->CR2 &= (~I2C_CR2_ITBUFEN); + i2cp->id_i2c->DR = _txbuf[_txbufhead]; + (_txbufhead)++; return(FALSE); } - i2cp->id_slave_config->txbufhead = 0; + _txbufhead = 0; return(TRUE); // last byte written +#undef _txbufhead +#undef _txbytes +#undef _txbuf } @@ -302,44 +310,49 @@ bool_t i2c_lld_txbyte(I2CDriver *i2cp) { */ bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { // temporal variables - #define rxbuf i2cp->id_slave_config->rxbuf - #define rxbufhead i2cp->id_slave_config->rxbufhead - #define rxdepth i2cp->id_slave_config->rxdepth - #define rxbytes i2cp->id_slave_config->rxbytes +#define _rxbuf (i2cp->id_slave_config->rxbuf) +#define _rxbufhead (i2cp->id_slave_config->rxbufhead) +#define _rxdepth (i2cp->id_slave_config->rxdepth) +#define _rxbytes (i2cp->id_slave_config->rxbytes) /* In order to generate the non-acknowledge pulse after the last received * data byte, the ACK bit must be cleared just after reading the second * last data byte (after second last RxNE event). */ - if (rxbufhead < rxbytes){ - rxbuf[rxbufhead] = i2cp->id_i2c->DR; - if ((rxbytes - rxbufhead) <= 2){ + if (_rxbufhead < _rxbytes){ + _rxbuf[_rxbufhead] = i2cp->id_i2c->DR; + if ((_rxbytes - _rxbufhead) <= 2){ i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);// clear ACK bit for automatically send NACK } - rxbufhead++; + (_rxbufhead)++; return(FALSE); } - i2cp->id_i2c->CR2 &= (~I2C_CR2_ITBUFEN); // disable interrupt - rxbuf[rxbufhead] = i2cp->id_i2c->DR; // read last byte - rxbufhead = 0; - #undef rxbuf - #undef rxbufhead - #undef rxdepth - #undef rxbytes + /* disable interrupt to avoid jumping to ISR */ + i2cp->id_i2c->CR2 &= (~I2C_CR2_ITBUFEN); + _rxbuf[_rxbufhead] = i2cp->id_i2c->DR; // read last byte + _rxbufhead = 0; return(TRUE); // last byte read + +#undef _rxbuf +#undef _rxbufhead +#undef _rxdepth +#undef _rxbytes } void i2c_lld_master_start(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_START; + while (i2cp->id_i2c->CR1 & I2C_CR1_START); + + // enable interrupts + i2cp->id_i2c->CR2 |= I2C_CR2_ITEVTEN; + i2cp->id_i2c->CR2 |= I2C_CR2_ITBUFEN; } void i2c_lld_master_stop(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_STOP; - chSysLock(); while (i2cp->id_i2c->CR1 & I2C_CR1_STOP); - chSysUnlock(); } From 918ff6d6b67e49410f01d5e3578b29d135d72de0 Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 9 Feb 2011 13:31:34 +0000 Subject: [PATCH 19/92] I2C. Merged Alberto's clock setting code. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2720 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 123 ++++++++++++++++++++++--------- os/hal/platforms/STM32/i2c_lld.h | 42 ++++++----- 2 files changed, 114 insertions(+), 51 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 7a7a071ec..34b8d377e 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -66,17 +66,17 @@ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { } /* This function handle all regular interrupt conditions - * TODO: 10 bit address handling here + * TODO: 10 bit address handling */ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { + // debug variables int i = 0; int n = 0; int m = 0; if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent - //i = i2cp->id_i2c->SR1; i2cp->id_state = I2C_MACTIVE; - i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | + i2cp->id_i2c->DR = (i2cp->id_slave_config->addr7 << 1) | i2cp->id_slave_config->rw_bit; // write slave address in DR return; } @@ -109,30 +109,20 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { //receiving bytes one by one if ((i2cp->id_state == I2C_MRECEIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ -// i = i2cp->id_i2c->SR1; -// n = i2cp->id_i2c->SR2; if (i2c_lld_rxbyte(i2cp)) i2cp->id_state = I2C_MWAIT_TF; // last byte read -// i = i2cp->id_i2c->SR1; -// n = i2cp->id_i2c->SR2; return; } // "wait" BTF bit in status register -// if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ chSysLockFromIsr(); i2cp->id_i2c->CR2 &= (~I2C_CR2_ITEVTEN); // disable BTF interrupt i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); - - i = i2cp->id_i2c->SR1; - n = i2cp->id_i2c->SR2; - m = i2cp->id_i2c->CR1; - chSysUnlockFromIsr(); return; } - else{ // trap + else{ // debugging trap i = i2cp->id_i2c->SR1; n = i2cp->id_i2c->SR2; m = i2cp->id_i2c->CR1; @@ -234,23 +224,90 @@ void i2c_lld_start(I2CDriver *i2cp) { i2cp->id_i2c->CR1 = I2C_CR1_SWRST; // reset i2c peripherial i2cp->id_i2c->CR1 = 0; - i2cp->id_i2c->CR1 = i2cp->id_config->i2cc_cr1; - i2cp->id_i2c->CR2 = i2cp->id_config->i2cc_cr2 | - I2C_CR2_ITERREN | - I2C_CR2_ITEVTEN | - I2C_CR2_ITBUFEN | - 36; //TODO: replace this by macro calculation - /* TODO: - * 1. macro timing calculator - * 2. parameter checker - * 3. definitions in halconf.h: i2c-freq, i2c_mode, etc - * 4. trise time calculator/checker - */ - i2cp->id_i2c->CCR = i2cp->id_config->i2cc_ccr | 180; - i2cp->id_i2c->TRISE = i2cp->id_config->i2cc_trise | 37; + i2c_lld_set_clock(i2cp); + i2cp->id_i2c->CR1 |= 1; // enable interface } + + +// int32_t clock_speed, I2C_DutyCycle_t duty + +void i2c_lld_set_clock(I2CDriver *i2cp) { + volatile uint16_t regCCR, regCR2, freq, clock_div; + volatile uint16_t pe_bit_saved; + int32_t clock_speed = i2cp->id_config->ClockSpeed; + I2C_DutyCycle_t duty = i2cp->id_config->FastModeDutyCycle; + + chDbgCheck((i2cp != NULL) && (clock_speed > 0) && (clock_speed <= 4000000), + "i2c_lld_set_clock"); + + /*---------------------------- CR2 Configuration ------------------------*/ + /* Get the I2Cx CR2 value */ + regCR2 = i2cp->id_i2c->CR2; + + /* Clear frequency FREQ[5:0] bits */ + regCR2 &= (uint16_t)~I2C_CR2_FREQ; + /* Set frequency bits depending on pclk1 value */ + freq = (uint16_t)(STM32_PCLK1 / 1000000); + chDbgCheck((freq >= 2) && (freq <= 36), + "i2c_lld_set_clock() : Peripheral clock freq. out of range"); + regCR2 |= freq; + i2cp->id_i2c->CR2 = regCR2; + + /*---------------------------- CCR Configuration ------------------------*/ + pe_bit_saved = (i2cp->id_i2c->CR1 & I2C_CR1_PE); + /* Disable the selected I2C peripheral to configure TRISE */ + i2cp->id_i2c->CR1 &= (uint16_t)~I2C_CR1_PE; + + /* Clear F/S, DUTY and CCR[11:0] bits */ + regCCR = 0; + clock_div = I2C_CCR_CCR; + /* Configure clock_div in standard mode */ + if (clock_speed <= 100000) { + chDbgAssert(duty == stdDutyCycle, + "i2c_lld_set_clock(), #3", "Invalid standard mode duty cycle"); + /* Standard mode clock_div calculate: Tlow/Thigh = 1/1 */ + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2)); + /* Test if CCR value is under 0x4, and set the minimum allowed value */ + if (clock_div < 0x04) clock_div = 0x04; + /* Set clock_div value for standard mode */ + regCCR |= (clock_div & I2C_CCR_CCR); + /* Set Maximum Rise Time for standard mode */ + i2cp->id_i2c->TRISE = freq + 1; + } + /* Configure clock_div in fast mode */ + else if(clock_speed <= 400000) { + chDbgAssert((duty == fastDutyCycle_2) || (duty == fastDutyCycle_16_9), + "i2c_lld_set_clock(), #3", "Invalid fast mode duty cycle"); + if(duty == fastDutyCycle_2) { + /* Fast mode clock_div calculate: Tlow/Thigh = 2/1 */ + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3)); + } + else if(duty == fastDutyCycle_16_9) { + /* Fast mode clock_div calculate: Tlow/Thigh = 16/9 */ + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 25)); + /* Set DUTY bit */ + regCCR |= I2C_CCR_DUTY; + } + /* Test if CCR value is under 0x1, and set the minimum allowed value */ + if(clock_div < 0x01) clock_div = 0x01; + /* Set clock_div value and F/S bit for fast mode*/ + regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR)); + /* Set Maximum Rise Time for fast mode */ + i2cp->id_i2c->TRISE = (freq * 300 / 1000) + 1; + } + chDbgAssert((clock_div <= I2C_CCR_CCR), + "i2c_lld_set_clock(), #2", "Too low clock clock speed selected"); + + /* Write to I2Cx CCR */ + i2cp->id_i2c->CCR = regCCR; + + /* restore the I2C peripheral enabled state */ + i2cp->id_i2c->CR1 |= pe_bit_saved; +} + + /** * @brief Deactivates the I2C peripheral. * @@ -283,7 +340,7 @@ void i2c_lld_stop(I2CDriver *i2cp) { * write bytes in DR register * return TRUE if last byte written */ -bool_t i2c_lld_txbyte(I2CDriver *i2cp) { +inline bool_t i2c_lld_txbyte(I2CDriver *i2cp) { #define _txbufhead (i2cp->id_slave_config->txbufhead) #define _txbytes (i2cp->id_slave_config->txbytes) #define _txbuf (i2cp->id_slave_config->txbuf) @@ -308,7 +365,7 @@ bool_t i2c_lld_txbyte(I2CDriver *i2cp) { * read bytes from DR register * return TRUE if last byte read */ -bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { +inline bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { // temporal variables #define _rxbuf (i2cp->id_slave_config->rxbuf) #define _rxbufhead (i2cp->id_slave_config->rxbufhead) @@ -319,7 +376,7 @@ bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { * data byte, the ACK bit must be cleared just after reading the second * last data byte (after second last RxNE event). */ - if (_rxbufhead < _rxbytes){ + if (_rxbufhead < (_rxbytes - 1)){ _rxbuf[_rxbufhead] = i2cp->id_i2c->DR; if ((_rxbytes - _rxbufhead) <= 2){ i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);// clear ACK bit for automatically send NACK @@ -399,7 +456,7 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t re i++; // wait Address sent } - i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | I2C_WRITE; // write slave addres in DR + i2cp->id_i2c->DR = (i2cp->id_slave_config->addr7 << 1) | I2C_WRITE; // write slave addres in DR while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){ i++; // wait Address sent } @@ -447,7 +504,7 @@ void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { uint16_t tmp = 0; // send slave addres with read-bit - i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | I2C_READ; + i2cp->id_i2c->DR = (i2cp->id_slave_config->addr7 << 1) | I2C_READ; while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){ i++; // wait Address sent } diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 7a8f468eb..82333b0f7 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -109,19 +109,27 @@ typedef void (*i2ccallback_t)(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); */ typedef void (*i2cerrorcallback_t)(void); +typedef enum { + opmodeI2C, + opmodeSMBusDevice, + opmodeSMBusHost, +} I2C_opMode_t; + +typedef enum { + stdDutyCycle, + fastDutyCycle_2, + fastDutyCycle_16_9, +} I2C_DutyCycle_t; /** * @brief Driver configuration structure. */ typedef struct { - /** - * @brief I2C initialization data. - */ - uint16_t i2cc_cr1; - uint16_t i2cc_cr2; - uint16_t i2cc_ccr; - uint16_t i2cc_trise; - + I2C_opMode_t opMode; /*!< Specifies the I2C mode.*/ + uint32_t ClockSpeed; /*!< Specifies the clock frequency. Must be set to a value lower than 400kHz */ + I2C_DutyCycle_t FastModeDutyCycle;/*!< Specifies the I2C fast mode duty cycle */ + uint8_t OwnAddress7; /*!< Specifies the first device 7-bit own address. */ + uint8_t OwnAddress10; /*!< Specifies the second part of device own address in 10-bit mode. */ } I2CConfig; @@ -165,14 +173,13 @@ struct I2CSlaveConfig{ size_t txbytes; size_t txbufhead; - uint8_t slave_addr1; // 7-bit address of the slave - uint8_t slave_addr2; // used in 10-bit address mode + uint8_t addr7; // 7-bit address of the slave + uint8_t addr10; // used in 10-bit address mode. Set to NULL if not used uint16_t error_flags; - - uint8_t rw_bit; // this flag contain R/W bit - - bool_t restart; // send restart or stop event after complete data tx/rx + uint8_t rw_bit; // this flag contain R/W bit + bool_t restart; // send restart or stop event after complete data tx/rx + //TODO: join error_flags, rw_bit, restart in one word. #if I2C_USE_WAIT /** @@ -212,10 +219,7 @@ struct I2CDriver{ I2CSlaveConfig *id_slave_config; /* End of the mandatory fields.*/ - /** - * @brief Thread waiting for I/O completion. - */ - Thread *id_thread; + /** * @brief Pointer to the I2Cx registers block. */ @@ -252,6 +256,8 @@ void i2c_lld_init(void); void i2c_lld_start(I2CDriver *i2cp); void i2c_lld_stop(I2CDriver *i2cp); +void i2c_lld_set_clock(I2CDriver *i2cp); + void i2c_lld_master_start(I2CDriver *i2cp); void i2c_lld_master_stop(I2CDriver *i2cp); From eddd171ec8a54080dbd354f9e90baf60a3436266 Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 9 Feb 2011 15:00:08 +0000 Subject: [PATCH 20/92] I2C. Alberto's clock setting code tested. Minor changes. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2721 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 34b8d377e..df2685387 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -225,14 +225,11 @@ void i2c_lld_start(I2CDriver *i2cp) { i2cp->id_i2c->CR1 = 0; i2c_lld_set_clock(i2cp); - + i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN | I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; i2cp->id_i2c->CR1 |= 1; // enable interface } - - -// int32_t clock_speed, I2C_DutyCycle_t duty - +//TODO: dox here void i2c_lld_set_clock(I2CDriver *i2cp) { volatile uint16_t regCCR, regCR2, freq, clock_div; volatile uint16_t pe_bit_saved; @@ -403,8 +400,7 @@ void i2c_lld_master_start(I2CDriver *i2cp){ while (i2cp->id_i2c->CR1 & I2C_CR1_START); // enable interrupts - i2cp->id_i2c->CR2 |= I2C_CR2_ITEVTEN; - i2cp->id_i2c->CR2 |= I2C_CR2_ITBUFEN; + i2cp->id_i2c->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; } void i2c_lld_master_stop(I2CDriver *i2cp){ From 76bac6bb8704e039a7f9e4b34da7af3bd909c2bd Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 9 Feb 2011 19:33:19 +0000 Subject: [PATCH 21/92] I2C. Added own slave address handling and error callback. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2723 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 18 ++- os/hal/platforms/STM32/i2c_lld.c | 251 ++++++++++++++++--------------- os/hal/platforms/STM32/i2c_lld.h | 42 ++---- os/hal/src/i2c.c | 3 - 4 files changed, 151 insertions(+), 163 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 64816186b..5a85ed5f7 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -33,8 +33,21 @@ /*===========================================================================*/ /* Driver constants. */ /*===========================================================================*/ - - +#define I2CD_NO_ERROR 0 +/** @brief Bus Error.*/ +#define I2CD_BUS_ERROR 0x01 +/** @brief Arbitration Lost (master mode).*/ +#define I2CD_ARBITRATION_LOST 0x02 +/** @brief Acknowledge Failure.*/ +#define I2CD_ACK_FAILURE 0x04 +/** @brief Overrun/Underrun.*/ +#define I2CD_OVERRUN 0x08 +/** @brief PEC Error in reception.*/ +#define I2CD_PEC_ERROR 0x10 +/** @brief Timeout or Tlow Error.*/ +#define I2CD_TIMEOUT 0x20 +/** @brief SMBus Alert.*/ +#define I2CD_SMB_ALERT 0x40 /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ @@ -125,7 +138,6 @@ extern "C" { void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); - void i2cMasterStartI(I2CDriver *i2cp,uint16_t header); void i2cMasterStopI(I2CDriver *i2cp); void i2cMasterRestartI(I2CDriver *i2cp); diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index df2685387..65cdec1b3 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -33,40 +33,76 @@ I2CDriver I2CD2; /* Driver local functions. */ /*===========================================================================*/ -/** - * @brief TODO: Status bits translation. - * - * @param[in] sr USART SR register value - * - * @return The error flags. - */ -static i2cflags_t translate_i2c_errors(uint16_t sr) { - i2cflags_t sts = 0; - - if (sr & USART_SR_ORE) - sts |= UART_OVERRUN_ERROR; - if (sr & USART_SR_PE) - sts |= UART_PARITY_ERROR; - if (sr & USART_SR_FE) - sts |= UART_FRAMING_ERROR; - if (sr & USART_SR_NE) - sts |= UART_NOISE_ERROR; - if (sr & USART_SR_LBD) - sts |= UART_BREAK_DETECTED; - return sts; -} - - static void i2c_serve_error_interrupt(I2CDriver *i2cp) { - // TODO:remove this stub and write normal handler - // this is simply trap for errors - while TRUE{ - translate_i2c_errors(i2cp->id_i2c->SR1); - } + chSysLockFromIsr(); + i2cp->id_slave_config->id_err_callback(i2cp, i2cp->id_slave_config); + chSysUnlockFromIsr(); } -/* This function handle all regular interrupt conditions - * TODO: 10 bit address handling +/* helper function, not API + * write bytes in DR register + * return TRUE if last byte written + */ +inline bool_t i2c_lld_txbyte(I2CDriver *i2cp) { +#define _txbufhead (i2cp->id_slave_config->txbufhead) +#define _txbytes (i2cp->id_slave_config->txbytes) +#define _txbuf (i2cp->id_slave_config->txbuf) + + if (_txbufhead < _txbytes){ + /* disable interrupt to avoid jumping to ISR */ + if ( _txbytes - _txbufhead == 1) + i2cp->id_i2c->CR2 &= (~I2C_CR2_ITBUFEN); + i2cp->id_i2c->DR = _txbuf[_txbufhead]; + (_txbufhead)++; + return(FALSE); + } + _txbufhead = 0; + return(TRUE); // last byte written +#undef _txbufhead +#undef _txbytes +#undef _txbuf +} + + +/* helper function, not API + * read bytes from DR register + * return TRUE if last byte read + */ +inline bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { + // temporal variables +#define _rxbuf (i2cp->id_slave_config->rxbuf) +#define _rxbufhead (i2cp->id_slave_config->rxbufhead) +#define _rxdepth (i2cp->id_slave_config->rxdepth) +#define _rxbytes (i2cp->id_slave_config->rxbytes) + + /* In order to generate the non-acknowledge pulse after the last received + * data byte, the ACK bit must be cleared just after reading the second + * last data byte (after second last RxNE event). + */ + if (_rxbufhead < (_rxbytes - 1)){ + _rxbuf[_rxbufhead] = i2cp->id_i2c->DR; + if ((_rxbytes - _rxbufhead) <= 2){ + i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);// clear ACK bit for automatically send NACK + } + (_rxbufhead)++; + return(FALSE); + } + /* disable interrupt to avoid jumping to ISR */ + i2cp->id_i2c->CR2 &= (~I2C_CR2_ITBUFEN); + + _rxbuf[_rxbufhead] = i2cp->id_i2c->DR; // read last byte + _rxbufhead = 0; + return(TRUE); // last byte read + +#undef _rxbuf +#undef _rxbufhead +#undef _rxdepth +#undef _rxbytes +} + + +/* + * This function handle all regular interrupt conditions */ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { // debug variables @@ -76,12 +112,13 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent i2cp->id_state = I2C_MACTIVE; + //TODO: 10 bit address handling i2cp->id_i2c->DR = (i2cp->id_slave_config->addr7 << 1) | i2cp->id_slave_config->rw_bit; // write slave address in DR return; } - // now "wait" interrupt with ADDR flag + // "wait" interrupt with ADDR flag if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address successfully sent if(i2cp->id_i2c->SR2 & I2C_SR2_TRA){ i2c_lld_txbyte(i2cp); // send first byte @@ -130,7 +167,6 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { } } - #if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) /** * @brief I2C1 event interrupt handler. @@ -225,6 +261,7 @@ void i2c_lld_start(I2CDriver *i2cp) { i2cp->id_i2c->CR1 = 0; i2c_lld_set_clock(i2cp); + i2c_lld_set_opmode(i2cp); i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN | I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; i2cp->id_i2c->CR1 |= 1; // enable interface } @@ -263,7 +300,7 @@ void i2c_lld_set_clock(I2CDriver *i2cp) { /* Configure clock_div in standard mode */ if (clock_speed <= 100000) { chDbgAssert(duty == stdDutyCycle, - "i2c_lld_set_clock(), #3", "Invalid standard mode duty cycle"); + "i2c_lld_set_clock(), #1", "Invalid standard mode duty cycle"); /* Standard mode clock_div calculate: Tlow/Thigh = 1/1 */ clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2)); /* Test if CCR value is under 0x4, and set the minimum allowed value */ @@ -276,7 +313,7 @@ void i2c_lld_set_clock(I2CDriver *i2cp) { /* Configure clock_div in fast mode */ else if(clock_speed <= 400000) { chDbgAssert((duty == fastDutyCycle_2) || (duty == fastDutyCycle_16_9), - "i2c_lld_set_clock(), #3", "Invalid fast mode duty cycle"); + "i2c_lld_set_clock(), #2", "Invalid fast mode duty cycle"); if(duty == fastDutyCycle_2) { /* Fast mode clock_div calculate: Tlow/Thigh = 2/1 */ clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3)); @@ -295,7 +332,7 @@ void i2c_lld_set_clock(I2CDriver *i2cp) { i2cp->id_i2c->TRISE = (freq * 300 / 1000) + 1; } chDbgAssert((clock_div <= I2C_CCR_CCR), - "i2c_lld_set_clock(), #2", "Too low clock clock speed selected"); + "i2c_lld_set_clock(), #3", "Too low clock clock speed selected"); /* Write to I2Cx CCR */ i2cp->id_i2c->CCR = regCCR; @@ -304,6 +341,47 @@ void i2c_lld_set_clock(I2CDriver *i2cp) { i2cp->id_i2c->CR1 |= pe_bit_saved; } +void i2c_lld_set_opmode(I2CDriver *i2cp) { + I2C_opMode_t opmode = i2cp->id_config->opMode; + uint16_t regCR1; + + /*---------------------------- CR1 Configuration ------------------------*/ + /* Get the I2Cx CR1 value */ + regCR1 = i2cp->id_i2c->CR1; + switch(opmode){ + case opmodeI2C: + regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); + break; + case opmodeSMBusDevice: + regCR1 |= I2C_CR1_SMBUS; + regCR1 &= (uint16_t)~(I2C_CR1_SMBTYPE); + break; + case opmodeSMBusHost: + regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); + break; + } + /* Write to I2Cx CR1 */ + i2cp->id_i2c->CR1 = regCR1; +} + +void i2c_lld_set_own_address(I2CDriver *i2cp) { + //TODO: dual address mode + + /*---------------------------- OAR1 Configuration -----------------------*/ + i2cp->id_i2c->OAR1 |= 1 << 14; + + if (&(i2cp->id_config->OwnAddress10) == NULL){// only 7-bit address + i2cp->id_i2c->OAR1 &= (~I2C_OAR1_ADDMODE); + i2cp->id_i2c->OAR1 |= i2cp->id_config->OwnAddress7 << 1; + } + else { + chDbgAssert((i2cp->id_config->OwnAddress10 < 1024), + "i2c_lld_set_own_address(), #1", "10-bit address longer then 10 bit") + i2cp->id_i2c->OAR1 |= I2C_OAR1_ADDMODE; + i2cp->id_i2c->OAR1 |= i2cp->id_config->OwnAddress10; + } +} + /** * @brief Deactivates the I2C peripheral. @@ -333,66 +411,6 @@ void i2c_lld_stop(I2CDriver *i2cp) { } -/* helper function, not API - * write bytes in DR register - * return TRUE if last byte written - */ -inline bool_t i2c_lld_txbyte(I2CDriver *i2cp) { -#define _txbufhead (i2cp->id_slave_config->txbufhead) -#define _txbytes (i2cp->id_slave_config->txbytes) -#define _txbuf (i2cp->id_slave_config->txbuf) - - if (_txbufhead < _txbytes){ - /* disable interrupt to avoid jumping to ISR */ - if ( _txbytes - _txbufhead == 1) - i2cp->id_i2c->CR2 &= (~I2C_CR2_ITBUFEN); - i2cp->id_i2c->DR = _txbuf[_txbufhead]; - (_txbufhead)++; - return(FALSE); - } - _txbufhead = 0; - return(TRUE); // last byte written -#undef _txbufhead -#undef _txbytes -#undef _txbuf -} - - -/* helper function, not API - * read bytes from DR register - * return TRUE if last byte read - */ -inline bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { - // temporal variables -#define _rxbuf (i2cp->id_slave_config->rxbuf) -#define _rxbufhead (i2cp->id_slave_config->rxbufhead) -#define _rxdepth (i2cp->id_slave_config->rxdepth) -#define _rxbytes (i2cp->id_slave_config->rxbytes) - - /* In order to generate the non-acknowledge pulse after the last received - * data byte, the ACK bit must be cleared just after reading the second - * last data byte (after second last RxNE event). - */ - if (_rxbufhead < (_rxbytes - 1)){ - _rxbuf[_rxbufhead] = i2cp->id_i2c->DR; - if ((_rxbytes - _rxbufhead) <= 2){ - i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);// clear ACK bit for automatically send NACK - } - (_rxbufhead)++; - return(FALSE); - } - /* disable interrupt to avoid jumping to ISR */ - i2cp->id_i2c->CR2 &= (~I2C_CR2_ITBUFEN); - - _rxbuf[_rxbufhead] = i2cp->id_i2c->DR; // read last byte - _rxbufhead = 0; - return(TRUE); // last byte read - -#undef _rxbuf -#undef _rxbufhead -#undef _rxdepth -#undef _rxbytes -} void i2c_lld_master_start(I2CDriver *i2cp){ @@ -448,35 +466,25 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t re i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate start condition - while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)){ - i++; // wait Address sent - } + while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)); // wait Address sent i2cp->id_i2c->DR = (i2cp->id_slave_config->addr7 << 1) | I2C_WRITE; // write slave addres in DR - while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){ - i++; // wait Address sent - } - i = i2cp->id_i2c->SR2; // TODO: check is it need to read this register for I2C to proper functionality + while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)); // wait Address sent + i = i2cp->id_i2c->SR2; i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit // now write data byte by byte in DR register uint32_t n = 0; for (n = 0; n < i2cp->id_slave_config->txbytes; n++){ i2cp->id_i2c->DR = i2cscfg->txbuf[n]; - while (!(i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ - i++; - } + while (!(i2cp->id_i2c->SR1 & I2C_SR1_TXE)); } - while (!(i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ - i++; - } + while (!(i2cp->id_i2c->SR1 & I2C_SR1_BTF)); if (restart){ i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate restart condition - while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)){ - i++; // wait start bit - } + while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)); // wait start bit } else i2cp->id_i2c->CR1 |= I2C_CR1_STOP; // generate stop condition } @@ -492,19 +500,15 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t re */ void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { - chSysLock(); - i2cp->id_slave_config = i2cscfg; uint16_t i = 0; - uint16_t tmp = 0; // send slave addres with read-bit i2cp->id_i2c->DR = (i2cp->id_slave_config->addr7 << 1) | I2C_READ; - while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){ - i++; // wait Address sent - } - i = i2cp->id_i2c->SR2; // TODO: check is it need to read this register for I2C to proper functionality + while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)); // wait Address sent + + i = i2cp->id_i2c->SR2; i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit // set ACK bit @@ -512,18 +516,15 @@ void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { // collect data from slave for (i = 0; i < i2cp->id_slave_config->rxbytes; i++){ - if ((i2cp->id_slave_config->rxbytes - i) == 1){ // TODO: is it better <= in place of == ? + if ((i2cp->id_slave_config->rxbytes - i) == 1){ // clear ACK bit for automatically send NACK i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);} - while (!(i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ - tmp++; - } + while (!(i2cp->id_i2c->SR1 & I2C_SR1_RXNE)); + i2cp->id_slave_config->rxbuf[i] = i2cp->id_i2c->DR; } // generate STOP i2cp->id_i2c->CR1 |= I2C_CR1_STOP; - - chSysUnlock(); } diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 82333b0f7..25e451962 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -56,23 +56,6 @@ /* Derived constants and error checks. */ /*===========================================================================*/ -/** @brief No pending conditions.*/ -#define I2C_NO_ERROR 0 -/*@brief external Stop or Start condition during an address or a data transfer*/ -#define I2C_BUS_ERROR 1 -/** @brief */ -#define I2C_ARBITRATION_LOSS 2 -/** @brief */ -#define I2C_ACK_FAIL 4 -/** @brief */ -#define I2C_OVERRUN_UNDERRUN 8 -/** @brief */ -#define I2C_PEC_ERROR 16 -/** @brief */ -#define I2C_TIMEOUT 32 -/** @brief */ -#define I2C_SMBUS_ALERT 64 - /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ @@ -104,10 +87,12 @@ typedef void (*i2ccallback_t)(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); /** * @brief I2C error notification callback type. * - * @param[in] i2cp TODO: pointer to the @p I2CDriver object triggering the + * @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)(void); +typedef void (*i2cerrorcallback_t)(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); typedef enum { opmodeI2C, @@ -129,7 +114,7 @@ typedef struct { uint32_t ClockSpeed; /*!< Specifies the clock frequency. Must be set to a value lower than 400kHz */ I2C_DutyCycle_t FastModeDutyCycle;/*!< Specifies the I2C fast mode duty cycle */ uint8_t OwnAddress7; /*!< Specifies the first device 7-bit own address. */ - uint8_t OwnAddress10; /*!< Specifies the second part of device own address in 10-bit mode. */ + uint16_t OwnAddress10; /*!< Specifies the second part of device own address in 10-bit mode. Set to NULL if not used. */ } I2CConfig; @@ -174,12 +159,11 @@ struct I2CSlaveConfig{ size_t txbufhead; uint8_t addr7; // 7-bit address of the slave - uint8_t addr10; // used in 10-bit address mode. Set to NULL if not used + uint16_t addr10; // used in 10-bit address mode. Set to NULL if not used - uint16_t error_flags; uint8_t rw_bit; // this flag contain R/W bit bool_t restart; // send restart or stop event after complete data tx/rx - //TODO: join error_flags, rw_bit, restart in one word. + //TODO: join rw_bit, restart in one word. #if I2C_USE_WAIT /** @@ -224,13 +208,9 @@ struct I2CDriver{ * @brief Pointer to the I2Cx registers block. */ I2C_TypeDef *id_i2c; - } ; - - - /*===========================================================================*/ /* Driver macros. */ /*===========================================================================*/ @@ -255,20 +235,18 @@ extern "C" { void i2c_lld_init(void); void i2c_lld_start(I2CDriver *i2cp); void i2c_lld_stop(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_master_start(I2CDriver *i2cp); void i2c_lld_master_stop(I2CDriver *i2cp); + void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); -bool_t i2c_lld_txbyte(I2CDriver *i2cp); // helper function - void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); -bool_t i2c_lld_rxbyte(I2CDriver *i2cp); - #ifdef __cplusplus } #endif diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 5a0471e0f..04af9a6c2 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -161,9 +161,6 @@ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { - - - #if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) /** * @brief Gains exclusive access to the I2C bus. From c2d458110ccf32fd9c28850f5c953e12e4ef9b2c Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 9 Feb 2011 23:02:49 +0000 Subject: [PATCH 22/92] I2C. Begin of 10-bit slave address realization. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2727 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 21 +++++++++++++++++---- os/hal/platforms/STM32/i2c_lld.h | 21 ++++++++++++++------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 65cdec1b3..68e42972c 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -112,12 +112,25 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent i2cp->id_state = I2C_MACTIVE; - //TODO: 10 bit address handling - i2cp->id_i2c->DR = (i2cp->id_slave_config->addr7 << 1) | + /*TODO: 10 bit address handling + In 10-bit addressing mode, + – To enter Transmitter mode, a master sends the header (11110xx0) and then the + slave address, (where xx denotes the two most significant bits of the address). + – To enter Receiver mode, a master sends the header (11110xx0) and then the + slave address. Then it should send a repeated Start condition followed by the + header (11110xx1), (where xx denotes the two most significant bits of the + address). + The TRA bit indicates whether the master is in Receiver or Transmitter mode.*/ + + i2cp->id_i2c->DR = (i2cp->id_slave_config->address << 1) | i2cp->id_slave_config->rw_bit; // write slave address in DR return; } + if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADD10)){// header sent + + } + // "wait" interrupt with ADDR flag if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address successfully sent if(i2cp->id_i2c->SR2 & I2C_SR2_TRA){ @@ -468,7 +481,7 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t re i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate start condition while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)); // wait Address sent - i2cp->id_i2c->DR = (i2cp->id_slave_config->addr7 << 1) | I2C_WRITE; // write slave addres in DR + i2cp->id_i2c->DR = (i2cp->id_slave_config->address << 1) | I2C_WRITE; // write slave addres in DR while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)); // wait Address sent i = i2cp->id_i2c->SR2; i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit @@ -505,7 +518,7 @@ void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { uint16_t i = 0; // send slave addres with read-bit - i2cp->id_i2c->DR = (i2cp->id_slave_config->addr7 << 1) | I2C_READ; + i2cp->id_i2c->DR = (i2cp->id_slave_config->address << 1) | I2C_READ; while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)); // wait Address sent i = i2cp->id_i2c->SR2; diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 25e451962..5f7098d50 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -138,19 +138,19 @@ struct I2CSlaveConfig{ * @brief Callback pointer. * @note Transfer finished callback. Invoke when all data transferred, or * by DMA buffer events - * @p NULL then the callback is disabled. + * If set to @p NULL then the callback is disabled. */ i2ccallback_t id_callback; /** * @brief Callback pointer. - * @note TODO: I don't know, when this callback is inwoked - * @p NULL then the callback is disabled. + * @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; i2cblock_t *rxbuf; // pointer to buffer size_t rxdepth; // depth of buffer - size_t rxbytes; // count of bytes to sent in one sending + size_t rxbytes; // count of bytes to sent in one transmission size_t rxbufhead; // head pointer to current data byte i2cblock_t *txbuf; @@ -158,12 +158,19 @@ struct I2CSlaveConfig{ size_t txbytes; size_t txbufhead; - uint8_t addr7; // 7-bit address of the slave - uint16_t addr10; // used in 10-bit address mode. Set to NULL if not used + /** + * @brief Address word. + * @details The MSB used to switch between 10-bit and 7-bit modes + * (0 denotes 7-bit mode). Bits 0..9 contain slave address. + * Bits 10..14 ignores in 10-bit mode. + * Bits 7..14 ignores in 7-bot mode. + */ + uint16_t address; + //TODO: join rw_bit, restart in one word. uint8_t rw_bit; // this flag contain R/W bit bool_t restart; // send restart or stop event after complete data tx/rx - //TODO: join rw_bit, restart in one word. + #if I2C_USE_WAIT /** From eafaa7d6cfafb767ddf58caba640d63f418c5af6 Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 10 Feb 2011 16:35:28 +0000 Subject: [PATCH 23/92] I2C. 10-bit slave addressing done. Not tested at all. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2729 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 18 +++++---- os/hal/platforms/STM32/i2c_lld.c | 63 +++++++++++++++++++++++--------- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 5a85ed5f7..5f4b2cc6f 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -71,14 +71,16 @@ * @brief Driver state machine possible states. */ typedef enum { - I2C_UNINIT = 0, /**< Not initialized. */ - I2C_STOP = 1, /**< Stopped. */ - I2C_READY = 2, /**< Ready. */ - I2C_MACTIVE = 3, /**< START condition sent. */ - I2C_MTRANSMIT = 4, /**< Master transmitting. */ - I2C_MRECEIVE = 5, /**< Master receiving. */ - I2C_MWAIT_TF = 6, /**< Master wait Transmission Finished */ - I2C_MERROR = 7 /**< Error condition. */ + I2C_UNINIT = 0, /**< Not initialized. */ + I2C_STOP = 1, /**< Stopped. */ + I2C_READY = 2, /**< Ready. Start condition generated. */ + I2C_MACTIVE = 3, /**< I2C configured and waiting start cond. */ + I2C_10BIT_HANDSHAKE = 4, /**< 10-bit address sending */ + I2C_MWAIT_ADDR_ACK = 5, /**< Waiting ACK on address sending. */ + I2C_MTRANSMIT = 6, /**< Master transmitting. */ + I2C_MRECEIVE = 7, /**< Master receiving. */ + I2C_MWAIT_TF = 8, /**< Master wait Transmission Finished */ + I2C_MERROR = 9 /**< Error condition. */ } i2cstate_t; #include "i2c_lld.h" diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 68e42972c..aecb1d24d 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -110,32 +110,59 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { int n = 0; int m = 0; + /* In 10-bit addressing mode, + – To enter Transmitter mode, a master sends the header (11110xx0) and then the + slave address, (where xx denotes the two most significant bits of the address). + – To enter Receiver mode, a master sends the header (11110xx0) and then the + slave address. Then it should send a repeated Start condition followed by the + header (11110xx1), (where xx denotes the two most significant bits of the + address). + The TRA bit indicates whether the master is in Receiver or Transmitter mode.*/ + if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent i2cp->id_state = I2C_MACTIVE; - /*TODO: 10 bit address handling - In 10-bit addressing mode, - – To enter Transmitter mode, a master sends the header (11110xx0) and then the - slave address, (where xx denotes the two most significant bits of the address). - – To enter Receiver mode, a master sends the header (11110xx0) and then the - slave address. Then it should send a repeated Start condition followed by the - header (11110xx1), (where xx denotes the two most significant bits of the - address). - The TRA bit indicates whether the master is in Receiver or Transmitter mode.*/ - i2cp->id_i2c->DR = (i2cp->id_slave_config->address << 1) | - i2cp->id_slave_config->rw_bit; // write slave address in DR + if(!(i2cp->id_slave_config->address & 0x8000)){ // slave address is 7-bit + i2cp->id_i2c->DR = ((i2cp->id_slave_config->address & 0x7F) << 1) | + i2cp->id_slave_config->rw_bit; + i2cp->id_state = I2C_MWAIT_ADDR_ACK; + return; + } + else{ // slave address is 10-bit + i2cp->id_state = I2C_10BIT_HANDSHAKE; + // send MSB with header. LSB = 0. + i2cp->id_i2c->DR = ((i2cp->id_slave_config->address >> 7) & 0x6) | 0xF0; + return; + } + } + + // "wait" interrupt with ADD10 flag + if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADD10)){ + i2cp->id_i2c->DR = i2cp->id_slave_config->address & 0x00FF; // send remaining bits of address + if (!(i2cp->id_slave_config->rw_bit)) + // in transmit mode there is nothing to do with 10-bit handshaking + i2cp->id_state = I2C_MWAIT_ADDR_ACK; return; } - if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADD10)){// header sent - + // "wait" interrupt with ADDR + if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address ACKed + i2cp->id_i2c->CR1 |= I2C_CR1_START; + return; } - // "wait" interrupt with ADDR flag - if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address successfully sent - if(i2cp->id_i2c->SR2 & I2C_SR2_TRA){ - i2c_lld_txbyte(i2cp); // send first byte + if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// restart generated + // send MSB with header. LSB = 1 + i2cp->id_i2c->DR = ((i2cp->id_slave_config->address >> 7) & 0x6) | 0xF1; + i2cp->id_state = I2C_MWAIT_ADDR_ACK; + return; + } + + // "wait" interrupt with ADDR (ADD10 in 10-bit receiver mode) flag + if ((i2cp->id_state == I2C_MWAIT_ADDR_ACK) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR & I2C_SR1_ADD10)){// address ACKed + if(i2cp->id_i2c->SR2 & I2C_SR2_TRA){// I2C is transmitting data i2cp->id_state = I2C_MTRANSMIT; // change state + i2c_lld_txbyte(i2cp); // send first byte return; } else { @@ -145,7 +172,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { */ if (i2cp->id_slave_config->rxbytes > 1) i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // set ACK bit - i2cp->id_state = I2C_MRECEIVE; // change status + i2cp->id_state = I2C_MRECEIVE; // change state return; } } From 12778b0075823d399f0ac911bc9725fe8c8312c1 Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 10 Feb 2011 17:21:20 +0000 Subject: [PATCH 24/92] I2C. Cleanups. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2730 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 7 ++++++- os/hal/platforms/STM32/i2c_lld.c | 18 ++++++++++-------- os/hal/platforms/STM32/i2c_lld.h | 4 ++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 5f4b2cc6f..8b057f527 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -80,7 +80,12 @@ typedef enum { I2C_MTRANSMIT = 6, /**< Master transmitting. */ I2C_MRECEIVE = 7, /**< Master receiving. */ I2C_MWAIT_TF = 8, /**< Master wait Transmission Finished */ - I2C_MERROR = 9 /**< Error condition. */ + I2C_MERROR = 9, /**< Error condition. */ + + // slave part + I2C_SACTIVE = 10, + I2C_STRANSMIT = 11, + I2C_SRECEIVE = 12, } i2cstate_t; #include "i2c_lld.h" diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index aecb1d24d..ea535f246 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -82,7 +82,8 @@ inline bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { if (_rxbufhead < (_rxbytes - 1)){ _rxbuf[_rxbufhead] = i2cp->id_i2c->DR; if ((_rxbytes - _rxbufhead) <= 2){ - i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);// clear ACK bit for automatically send NACK + // clear ACK bit for automatically send NACK + i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK); } (_rxbufhead)++; return(FALSE); @@ -145,7 +146,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { return; } - // "wait" interrupt with ADDR + // "wait" interrupt with ADDR flag if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address ACKed i2cp->id_i2c->CR1 |= I2C_CR1_START; return; @@ -306,7 +307,7 @@ void i2c_lld_start(I2CDriver *i2cp) { i2cp->id_i2c->CR1 |= 1; // enable interface } -//TODO: dox here + void i2c_lld_set_clock(I2CDriver *i2cp) { volatile uint16_t regCCR, regCR2, freq, clock_div; volatile uint16_t pe_bit_saved; @@ -492,11 +493,13 @@ void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ /** * @brief Transmits data ever the I2C bus as masteri2cp. * + * @note This function does not use interrupts + * * @param[in] i2cp pointer to the @p I2CDriver object * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object - * @param[in] restart bool. If TRUE then generate restart condition insted of stop + * @param[in] restart bool. If TRUE then generate restart condition instead of stop */ -void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart) { +void i2c_lld_master_transmit_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart) { //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hylevel API int i = 0; @@ -532,13 +535,12 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t re /** * @brief Receives data from the I2C bus. - * @details Before receive data from I2C slave you must manually sent them some - * control bytes first (refer to you device datasheet). + * @note This function does not use interrupts * * @param[in] i2cp pointer to the @p I2CDriver object * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object */ -void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { +void i2c_lld_master_receive_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { i2cp->id_slave_config = i2cscfg; diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 5f7098d50..103e454f2 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -250,9 +250,9 @@ void i2c_lld_master_start(I2CDriver *i2cp); void i2c_lld_master_stop(I2CDriver *i2cp); -void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); +void i2c_lld_master_transmit_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); -void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); +void i2c_lld_master_receive_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); #ifdef __cplusplus } From e96e10761e38f07f884553c8ec6bcbaa06f42dd4 Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 10 Feb 2011 17:36:37 +0000 Subject: [PATCH 25/92] I2C. Small bugfix. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2731 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index ea535f246..ebfe9b423 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -160,7 +160,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { } // "wait" interrupt with ADDR (ADD10 in 10-bit receiver mode) flag - if ((i2cp->id_state == I2C_MWAIT_ADDR_ACK) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR & I2C_SR1_ADD10)){// address ACKed + if ((i2cp->id_state == I2C_MWAIT_ADDR_ACK) && (i2cp->id_i2c->SR1 & (I2C_SR1_ADDR | I2C_SR1_ADD10))){// address ACKed if(i2cp->id_i2c->SR2 & I2C_SR2_TRA){// I2C is transmitting data i2cp->id_state = I2C_MTRANSMIT; // change state i2c_lld_txbyte(i2cp); // send first byte From 4f827c235aa25d0c0b45eca7ccd06ce2c1740a24 Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 27 Feb 2011 15:22:18 +0000 Subject: [PATCH 26/92] I2C. Code cleanups. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2776 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 8 ++---- os/hal/platforms/STM32/i2c_lld.c | 10 +++----- os/hal/platforms/STM32/i2c_lld.h | 42 +++++++++++++++++--------------- os/hal/src/i2c.c | 41 ++++++++++++++++++++++--------- 4 files changed, 57 insertions(+), 44 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 8b057f527..5b7046627 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -143,13 +143,9 @@ extern "C" { void i2cStop(I2CDriver *i2cp); void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); + void i2cMasterStart(I2CDriver *i2cp); + void i2cMasterStop(I2CDriver *i2cp); - - void i2cMasterStartI(I2CDriver *i2cp,uint16_t header); - void i2cMasterStopI(I2CDriver *i2cp); - void i2cMasterRestartI(I2CDriver *i2cp); - void i2cMasterTransmitI(I2CDriver *i2cp, size_t n, const uint8_t *txbuf); - void i2cMasterReceiveI(I2CDriver *i2cp, size_t n, uint8_t *rxbuf); #if I2C_USE_MUTUAL_EXCLUSION void i2cAcquireBus(I2CDriver *i2cp); void i2cReleaseBus(I2CDriver *i2cp); diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index ebfe9b423..53c070e7b 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -452,8 +452,6 @@ void i2c_lld_stop(I2CDriver *i2cp) { } - - void i2c_lld_master_start(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_START; while (i2cp->id_i2c->CR1 & I2C_CR1_START); @@ -468,8 +466,8 @@ void i2c_lld_master_stop(I2CDriver *i2cp){ } -void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ - //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hylevel API +void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ + //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hi level API i2cp->id_slave_config = i2cscfg; i2cp->id_slave_config->rw_bit = I2C_WRITE; @@ -478,8 +476,8 @@ void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ i2c_lld_master_start(i2cp); } -void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ - //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hylevel API +void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ + //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hi level API i2cp->id_slave_config = i2cscfg; i2cp->id_slave_config->rw_bit = I2C_READ; diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 103e454f2..5d6f3c685 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -110,28 +110,23 @@ typedef enum { * @brief Driver configuration structure. */ typedef struct { - I2C_opMode_t opMode; /*!< Specifies the I2C mode.*/ - uint32_t ClockSpeed; /*!< Specifies the clock frequency. Must be set to a value lower than 400kHz */ + I2C_opMode_t opMode; /*!< Specifies the I2C mode.*/ + uint32_t ClockSpeed; /*!< Specifies the clock frequency. Must be set to a value lower than 400kHz */ I2C_DutyCycle_t FastModeDutyCycle;/*!< Specifies the I2C fast mode duty cycle */ - uint8_t OwnAddress7; /*!< Specifies the first device 7-bit own address. */ - uint16_t OwnAddress10; /*!< Specifies the second part of device own address in 10-bit mode. Set to NULL if not used. */ + uint8_t OwnAddress7; /*!< Specifies the first device 7-bit own address. */ + uint16_t OwnAddress10; /*!< Specifies the second part of device own address in 10-bit mode. Set to NULL if not used. */ } I2CConfig; -/** - * @brief TODO: - */ -typedef uint32_t i2cflags_t; /** - * @brief TODO: + * @brief I2C transmission data block size. */ typedef uint8_t i2cblock_t; /** * @brief Structure representing an I2C slave configuration. - * @details Each slave has its own data buffers, adress, and error flags. */ struct I2CSlaveConfig{ /** @@ -141,6 +136,7 @@ struct I2CSlaveConfig{ * 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. @@ -159,17 +155,22 @@ struct I2CSlaveConfig{ size_t txbufhead; /** - * @brief Address word. - * @details The MSB used to switch between 10-bit and 7-bit modes - * (0 denotes 7-bit mode). Bits 0..9 contain slave address. - * Bits 10..14 ignores in 10-bit mode. - * Bits 7..14 ignores in 7-bot mode. + * @brief Contain slave address and some flags. + * @details Bits 0..9 contain slave address in 10-bit mode. + * + * Bits 0..6 contain slave address in 7-bit mode. + * + * Bits 10..14 are not used in 10-bit mode. + * Bits 7..14 are not used in 7-bit mode. + * + * Bit 15 is used to switch between 10-bit and 7-bit modes + * (0 denotes 7-bit mode). */ uint16_t address; - //TODO: join rw_bit, restart in one word. - uint8_t rw_bit; // this flag contain R/W bit - bool_t restart; // send restart or stop event after complete data tx/rx + //TODO: merge rw_bit, restart and address in one 16-bit variable. + uint8_t rw_bit; + bool_t restart; // send restart if TRUE. Else sent stop event after complete data tx/rx #if I2C_USE_WAIT @@ -249,11 +250,12 @@ void i2c_lld_set_own_address(I2CDriver *i2cp); void i2c_lld_master_start(I2CDriver *i2cp); void i2c_lld_master_stop(I2CDriver *i2cp); +void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); +void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); void i2c_lld_master_transmit_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); -void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); void i2c_lld_master_receive_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); -void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); + #ifdef __cplusplus } #endif diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 04af9a6c2..7dede9f86 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -116,14 +116,35 @@ void i2cStop(I2CDriver *i2cp) { chSysUnlock(); } +/** + * @brief Generate (re)start on the bus. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2cMasterStart(I2CDriver *i2cp){ + + chDbgCheck((i2cp != NULL), "i2cMasterTransmit"); + + i2c_lld_master_start(i2cp); +} + +/** + * @brief Generate stop on the bus. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2cMasterStop(I2CDriver *i2cp){ + + chDbgCheck((i2cp != NULL), "i2cMasterTransmit"); + + i2c_lld_master_stop(i2cp); +} + /** * @brief Sends data ever the I2C bus. * * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] slave_addr1 7-bit address of the slave - * @param[in] slave_addr1 used in 10-bit address mode - * @param[in] n number of words to send - * @param[in] txbuf the pointer to the transmit buffer + * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object * */ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { @@ -134,19 +155,15 @@ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { "i2cMasterTransmit(), #1", "not active"); - i2c_lld_master_transmitI(i2cp, i2cscfg); + i2c_lld_master_transmit(i2cp, i2cscfg); } /** * @brief Receives data from the I2C bus. * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] slave_addr1 7-bit address of the slave - * @param[in] slave_addr1 used in 10-bit address mode - * @param[in] n number of words to receive - * @param[out] rxbuf the pointer to the receive buffer - * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object */ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { @@ -156,7 +173,7 @@ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { "i2cMasterReceive(), #1", "not active"); - i2c_lld_master_receiveI(i2cp, i2cscfg); + i2c_lld_master_receive(i2cp, i2cscfg); } From 4e4d882c04eecbe2e550ab6718016a7799ddd443 Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 27 Feb 2011 19:35:04 +0000 Subject: [PATCH 27/92] I2C. Cleanups. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2777 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c_brts.h | 146 -------- os/hal/platforms/STM32/i2c_lld.c | 15 +- os/hal/platforms/STM32/i2c_lld.h | 2 +- os/hal/platforms/STM32/i2c_lld_brts.c | 462 -------------------------- os/hal/platforms/STM32/i2c_lld_brts.h | 267 --------------- 5 files changed, 6 insertions(+), 886 deletions(-) delete mode 100644 os/hal/include/i2c_brts.h delete mode 100644 os/hal/platforms/STM32/i2c_lld_brts.c delete mode 100644 os/hal/platforms/STM32/i2c_lld_brts.h diff --git a/os/hal/include/i2c_brts.h b/os/hal/include/i2c_brts.h deleted file mode 100644 index 64816186b..000000000 --- a/os/hal/include/i2c_brts.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . -*/ - -/** - * @file i2c.h - * @brief I2C Driver macros and structures. - * - * @addtogroup I2C - * @{ - */ - -#ifndef _I2C_H_ -#define _I2C_H_ - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief Enables the mutual exclusion APIs on the I2C bus. - */ -#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define I2C_USE_MUTUAL_EXCLUSION TRUE -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - I2C_UNINIT = 0, /**< Not initialized. */ - I2C_STOP = 1, /**< Stopped. */ - I2C_READY = 2, /**< Ready. */ - I2C_MACTIVE = 3, /**< START condition sent. */ - I2C_MTRANSMIT = 4, /**< Master transmitting. */ - I2C_MRECEIVE = 5, /**< Master receiving. */ - I2C_MWAIT_TF = 6, /**< Master wait Transmission Finished */ - I2C_MERROR = 7 /**< Error condition. */ -} i2cstate_t; - -#include "i2c_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Read mode. - */ -#define I2C_READ 1 - -/** - * @brief Write mode. - */ -#define I2C_WRITE 0 - -/** - * @brief Seven bits addresses header builder. - * - * @param[in] addr seven bits address value - * @param[in] rw read/write flag - * - * @return A 16 bit value representing the header, the most - * significant byte is always zero. - */ -#define I2C_ADDR7(addr, rw) (uint16_t)((addr) << 1 | (rw)) - - -/** - * @brief Ten bits addresses header builder. - * - * @param[in] addr ten bits address value - * @param[in] rw read/write flag - * - * @return A 16 bit value representing the header, the most - * significant byte is the first one to be transmitted. - */ -#define I2C_ADDR10(addr, rw) \ - (uint16_t)(0xF000 | \ - (((addr) & 0x0300) << 1) | \ - (((rw) << 8)) | \ - ((addr) & 0x00FF)) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ -#ifdef __cplusplus -extern "C" { -#endif - void i2cInit(void); - void i2cObjectInit(I2CDriver *i2cp); - void i2cStart(I2CDriver *i2cp, I2CConfig *config); - void i2cStop(I2CDriver *i2cp); - void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); - void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); - - - - void i2cMasterStartI(I2CDriver *i2cp,uint16_t header); - void i2cMasterStopI(I2CDriver *i2cp); - void i2cMasterRestartI(I2CDriver *i2cp); - void i2cMasterTransmitI(I2CDriver *i2cp, size_t n, const uint8_t *txbuf); - void i2cMasterReceiveI(I2CDriver *i2cp, size_t n, uint8_t *rxbuf); -#if I2C_USE_MUTUAL_EXCLUSION - void i2cAcquireBus(I2CDriver *i2cp); - void i2cReleaseBus(I2CDriver *i2cp); -#endif /* I2C_USE_MUTUAL_EXCLUSION */ -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_I2C */ - -#endif /* _I2C_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 53c070e7b..154a735fa 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -34,9 +34,10 @@ I2CDriver I2CD2; /*===========================================================================*/ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { - chSysLockFromIsr(); - i2cp->id_slave_config->id_err_callback(i2cp, i2cp->id_slave_config); - chSysUnlockFromIsr(); + //TODO: more robust error handling + chSysLockFromIsr(); + i2cp->id_slave_config->id_err_callback(i2cp, i2cp->id_slave_config); + chSysUnlockFromIsr(); } /* helper function, not API @@ -72,7 +73,6 @@ inline bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { // temporal variables #define _rxbuf (i2cp->id_slave_config->rxbuf) #define _rxbufhead (i2cp->id_slave_config->rxbufhead) -#define _rxdepth (i2cp->id_slave_config->rxdepth) #define _rxbytes (i2cp->id_slave_config->rxbytes) /* In order to generate the non-acknowledge pulse after the last received @@ -97,7 +97,6 @@ inline bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { #undef _rxbuf #undef _rxbufhead -#undef _rxdepth #undef _rxbytes } @@ -456,8 +455,7 @@ void i2c_lld_master_start(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_START; while (i2cp->id_i2c->CR1 & I2C_CR1_START); - // enable interrupts - i2cp->id_i2c->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; + i2cp->id_i2c->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; // enable interrupts } void i2c_lld_master_stop(I2CDriver *i2cp){ @@ -467,7 +465,6 @@ void i2c_lld_master_stop(I2CDriver *i2cp){ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ - //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hi level API i2cp->id_slave_config = i2cscfg; i2cp->id_slave_config->rw_bit = I2C_WRITE; @@ -477,7 +474,6 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ } void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ - //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hi level API i2cp->id_slave_config = i2cscfg; i2cp->id_slave_config->rw_bit = I2C_READ; @@ -498,7 +494,6 @@ void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ * @param[in] restart bool. If TRUE then generate restart condition instead of stop */ void i2c_lld_master_transmit_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart) { - //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hylevel API int i = 0; diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 5d6f3c685..1f5356bca 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -168,7 +168,7 @@ struct I2CSlaveConfig{ */ uint16_t address; - //TODO: merge rw_bit, restart and address in one 16-bit variable. + //TODO: (is it need?) merge rw_bit, restart and address in one 16-bit variable. uint8_t rw_bit; bool_t restart; // send restart if TRUE. Else sent stop event after complete data tx/rx diff --git a/os/hal/platforms/STM32/i2c_lld_brts.c b/os/hal/platforms/STM32/i2c_lld_brts.c deleted file mode 100644 index 9e519d412..000000000 --- a/os/hal/platforms/STM32/i2c_lld_brts.c +++ /dev/null @@ -1,462 +0,0 @@ -/** - * @file STM32/i2c_lld.c - * @brief STM32 I2C subsystem low level driver source. Slave mode not implemented. - * @addtogroup STM32_I2C - * @{ - */ - -#include "ch.h" -#include "hal.h" -#include "i2c_lld.h" - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief I2C1 driver identifier.*/ -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -I2CDriver I2CD1; -#endif - -/** @brief I2C2 driver identifier.*/ -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -I2CDriver I2CD2; -#endif - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief TODO: Status bits translation. - * - * @param[in] sr USART SR register value - * - * @return The error flags. - */ -static i2cflags_t translate_i2c_errors(uint16_t sr) { - i2cflags_t sts = 0; - - if (sr & USART_SR_ORE) - sts |= UART_OVERRUN_ERROR; - if (sr & USART_SR_PE) - sts |= UART_PARITY_ERROR; - if (sr & USART_SR_FE) - sts |= UART_FRAMING_ERROR; - if (sr & USART_SR_NE) - sts |= UART_NOISE_ERROR; - if (sr & USART_SR_LBD) - sts |= UART_BREAK_DETECTED; - return sts; -} - - -static void i2c_serve_error_interrupt(I2CDriver *i2cp) { - // TODO:remove this stub and write normal handler - // this is simply trap for errors - while TRUE{ - translate_i2c_errors(i2cp->id_i2c->SR1); - } -} - -/* This function handle all regular interrupt conditions - * TODO: 10 bit address handling here - */ -static void i2c_serve_event_interrupt(I2CDriver *i2cp) { - int i = 0; - int n = 0; - int m = 0; - - if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent - //i = i2cp->id_i2c->SR1; - i2cp->id_state = I2C_MACTIVE; - i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | - i2cp->id_slave_config->rw_bit; // write slave address in DR - return; - } - - // now "wait" interrupt with ADDR flag - if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address successfully sent - if(i2cp->id_i2c->SR2 & I2C_SR2_TRA){ - i2c_lld_txbyte(i2cp); // send first byte - i2cp->id_state = I2C_MTRANSMIT; // change state - return; - } - else { - /* In order to generate the non-acknowledge pulse after the last received - * data byte, the ACK bit must be cleared just after reading the second - * last data byte (after second last RxNE event). - */ - if (i2cp->id_slave_config->rxbytes > 1) - i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // set ACK bit - i2cp->id_state = I2C_MRECEIVE; // change status - return; - } - } - - // transmitting bytes one by one - if ((i2cp->id_state == I2C_MTRANSMIT) && (i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ - if (i2c_lld_txbyte(i2cp)) - i2cp->id_state = I2C_MWAIT_TF; // last byte written - return; - } - - //receiving bytes one by one - if ((i2cp->id_state == I2C_MRECEIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ -// i = i2cp->id_i2c->SR1; -// n = i2cp->id_i2c->SR2; - if (i2c_lld_rxbyte(i2cp)) - i2cp->id_state = I2C_MWAIT_TF; // last byte read -// i = i2cp->id_i2c->SR1; -// n = i2cp->id_i2c->SR2; - return; - } - - // "wait" BTF bit in status register -// if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ - if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE | I2C_SR1_BTF | I2C_SR1_TXE)){ - chSysLockFromIsr(); - i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); - - i = i2cp->id_i2c->SR1; - n = i2cp->id_i2c->SR2; - m = i2cp->id_i2c->CR1; - - chSysUnlockFromIsr(); - return; - } - else{ // trap - i = i2cp->id_i2c->SR1; - n = i2cp->id_i2c->SR2; - m = i2cp->id_i2c->CR1; - return; - } -} - - -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -/** - * @brief I2C1 event interrupt handler. - */ -CH_IRQ_HANDLER(VectorBC) { - - CH_IRQ_PROLOGUE(); - i2c_serve_event_interrupt(&I2CD1); - CH_IRQ_EPILOGUE(); -} - -/** - * @brief I2C1 error interrupt handler. - */ -CH_IRQ_HANDLER(VectorC0) { - - CH_IRQ_PROLOGUE(); - i2c_serve_error_interrupt(&I2CD1); - CH_IRQ_EPILOGUE(); -} -#endif - -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -/** - * @brief I2C2 event interrupt handler. - */ -CH_IRQ_HANDLER(VectorC4) { - - CH_IRQ_PROLOGUE(); - i2c_serve_event_interrupt(&I2CD2); - CH_IRQ_EPILOGUE(); -} - -/** - * @brief I2C2 error interrupt handler. - */ -CH_IRQ_HANDLER(VectorC8) { - - CH_IRQ_PROLOGUE(); - i2c_serve_error_interrupt(&I2CD2); - CH_IRQ_EPILOGUE(); -} -#endif - -/** - * @brief Low level I2C driver initialization. - */ -void i2c_lld_init(void) { - -#if STM32_I2C_USE_I2C1 - RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; // reset I2C 1 - RCC->APB1RSTR = 0; - i2cObjectInit(&I2CD1); - I2CD1.id_i2c = I2C1; -#endif - -#if STM32_I2C_USE_I2C2 - RCC->APB1RSTR = RCC_APB1RSTR_I2C2RST; // reset I2C 2 - RCC->APB1RSTR = 0; - i2cObjectInit(&I2CD2); - I2CD2.id_i2c = I2C2; -#endif -} - -/** - * @brief Configures and activates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2c_lld_start(I2CDriver *i2cp) { - - /* If in stopped state then enables the I2C clock.*/ - if (i2cp->id_state == I2C_STOP) { -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - NVICEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); - NVICEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); - RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // I2C 1 clock enable - } -#endif -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - NVICEnableVector(I2C2_EV_IRQn, STM32_I2C2_IRQ_PRIORITY); - NVICEnableVector(I2C2_ER_IRQn, STM32_I2C2_IRQ_PRIORITY); - RCC->APB1ENR |= RCC_APB1ENR_I2C2EN; // I2C 2 clock enable - } -#endif - } - - /* I2C setup.*/ - i2cp->id_i2c->CR1 = I2C_CR1_SWRST; // reset i2c peripherial - i2cp->id_i2c->CR1 = 0; - - i2cp->id_i2c->CR1 = i2cp->id_config->i2cc_cr1; - i2cp->id_i2c->CR2 = i2cp->id_config->i2cc_cr2 | - I2C_CR2_ITERREN | - I2C_CR2_ITEVTEN | - I2C_CR2_ITBUFEN | - 36; //TODO: replace this by macro calculation - /* TODO: - * 1. macro timing calculator - * 2. parameter checker - * 3. definitions in halconf.h: i2c-freq, i2c_mode, etc - * 4. trise time calculator/checker - */ - i2cp->id_i2c->CCR = i2cp->id_config->i2cc_ccr | 180; - i2cp->id_i2c->TRISE = i2cp->id_config->i2cc_trise | 37; - i2cp->id_i2c->CR1 |= 1; // enable interface -} - -/** - * @brief Deactivates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2c_lld_stop(I2CDriver *i2cp) { - - /* If in ready state then disables the I2C clock.*/ - if (i2cp->id_state == I2C_READY) { -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - NVICDisableVector(I2C1_EV_IRQn); - NVICDisableVector(I2C1_ER_IRQn); - RCC->APB1ENR &= ~RCC_APB1ENR_I2C1EN; - } -#endif -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - NVICDisableVector(I2C2_EV_IRQn); - NVICDisableVector(I2C2_ER_IRQn); - RCC->APB1ENR &= ~RCC_APB1ENR_I2C2EN; - } -#endif - } - i2cp->id_state = I2C_STOP; -} - - -/* helper function, not API - * write bytes in DR register - * return TRUE if last byte written - */ -bool_t i2c_lld_txbyte(I2CDriver *i2cp) { - if (i2cp->id_slave_config->txbufhead < i2cp->id_slave_config->txbytes){ - i2cp->id_i2c->DR = i2cp->id_slave_config->txbuf[i2cp->id_slave_config->txbufhead]; - (i2cp->id_slave_config->txbufhead)++; - return(FALSE); - } - i2cp->id_slave_config->txbufhead = 0; - return(TRUE); // last byte written -} - - -/* helper function, not API - * read bytes from DR register - * return TRUE if last byte read - */ -bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { - // temporal variables - #define rxbuf i2cp->id_slave_config->rxbuf - #define rxbufhead i2cp->id_slave_config->rxbufhead - #define rxdepth i2cp->id_slave_config->rxdepth - #define rxbytes i2cp->id_slave_config->rxbytes - - /* In order to generate the non-acknowledge pulse after the last received - * data byte, the ACK bit must be cleared just after reading the second - * last data byte (after second last RxNE event). - */ - if (rxbufhead < rxbytes){ - rxbuf[rxbufhead] = i2cp->id_i2c->DR; - if ((rxbytes - rxbufhead) <= 2){ - i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);// clear ACK bit for automatically send NACK - } - rxbufhead++; - return(FALSE); - } - - rxbuf[rxbufhead] = i2cp->id_i2c->DR; // read last byte - rxbufhead = 0; - #undef rxbuf - #undef rxbufhead - #undef rxdepth - #undef rxbytes - - return(TRUE); // last byte read -} - - -void i2c_lld_master_start(I2CDriver *i2cp){ - i2cp->id_i2c->CR1 |= I2C_CR1_START; -} - -void i2c_lld_master_stop(I2CDriver *i2cp){ - i2cp->id_i2c->CR1 |= I2C_CR1_STOP; - chSysLock(); - while (i2cp->id_i2c->CR1 & I2C_CR1_STOP); - chSysUnlock(); -} - - -void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ - //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hylevel API - - i2cp->id_slave_config = i2cscfg; - i2cp->id_slave_config->rw_bit = I2C_WRITE; - - // generate start condition. Later transmission goes in background - i2c_lld_master_start(i2cp); -} - -void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ - //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hylevel API - - i2cp->id_slave_config = i2cscfg; - i2cp->id_slave_config->rw_bit = I2C_READ; - - // generate (re)start condition. Later connection goes asynchronously - i2c_lld_master_start(i2cp); -} - - - -/** - * @brief Transmits data ever the I2C bus as masteri2cp. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object - * @param[in] restart bool. If TRUE then generate restart condition insted of stop - */ -void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart) { - //TODO: check txbytes <= sizeof(i2cscfg->txbuf) here, or in hylevel API - - int i = 0; - - i2cp->id_slave_config = i2cscfg; - i2cp->id_slave_config->rw_bit = I2C_WRITE; - - - i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate start condition - while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)){ - i++; // wait Address sent - } - - i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | I2C_WRITE; // write slave addres in DR - while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){ - i++; // wait Address sent - } - i = i2cp->id_i2c->SR2; // TODO: check is it need to read this register for I2C to proper functionality - i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit - - // now write data byte by byte in DR register - uint32_t n = 0; - for (n = 0; n < i2cp->id_slave_config->txbytes; n++){ - i2cp->id_i2c->DR = i2cscfg->txbuf[n]; - while (!(i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ - i++; - } - } - - while (!(i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ - i++; - } - - if (restart){ - i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate restart condition - while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)){ - i++; // wait start bit - } - } - else i2cp->id_i2c->CR1 |= I2C_CR1_STOP; // generate stop condition -} - - -/** - * @brief Receives data from the I2C bus. - * @details Before receive data from I2C slave you must manually sent them some - * control bytes first (refer to you device datasheet). - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object - */ -void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { - - chSysLock(); - - i2cp->id_slave_config = i2cscfg; - - uint16_t i = 0; - uint16_t tmp = 0; - - // send slave addres with read-bit - i2cp->id_i2c->DR = (i2cp->id_slave_config->slave_addr1 << 1) | I2C_READ; - while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){ - i++; // wait Address sent - } - i = i2cp->id_i2c->SR2; // TODO: check is it need to read this register for I2C to proper functionality - i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit - - // set ACK bit - i2cp->id_i2c->CR1 |= I2C_CR1_ACK; - - // collect data from slave - for (i = 0; i < i2cp->id_slave_config->rxbytes; i++){ - if ((i2cp->id_slave_config->rxbytes - i) == 1){ // TODO: is it better <= in place of == ? - // clear ACK bit for automatically send NACK - i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);} - while (!(i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ - tmp++; - } - i2cp->id_slave_config->rxbuf[i] = i2cp->id_i2c->DR; - } - // generate STOP - i2cp->id_i2c->CR1 |= I2C_CR1_STOP; - - chSysUnlock(); -} - - - -#endif // HAL_USE_I2C diff --git a/os/hal/platforms/STM32/i2c_lld_brts.h b/os/hal/platforms/STM32/i2c_lld_brts.h deleted file mode 100644 index bac1dfff0..000000000 --- a/os/hal/platforms/STM32/i2c_lld_brts.h +++ /dev/null @@ -1,267 +0,0 @@ -/** - * @file STM32/i2c_lld.h - * @brief STM32 I2C subsystem low level driver header. - * @addtogroup STM32_I2C - * @{ - */ - -#ifndef _I2C_LLD_H_ -#define _I2C_LLD_H_ - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @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 No pending conditions.*/ -#define I2C_NO_ERROR 0 -/*@brief external Stop or Start condition during an address or a data transfer*/ -#define I2C_BUS_ERROR 1 -/** @brief */ -#define I2C_ARBITRATION_LOSS 2 -/** @brief */ -#define I2C_ACK_FAIL 4 -/** @brief */ -#define I2C_OVERRUN_UNDERRUN 8 -/** @brief */ -#define I2C_PEC_ERROR 16 -/** @brief */ -#define I2C_TIMEOUT 32 -/** @brief */ -#define I2C_SMBUS_ALERT 64 - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a structure representing an I2C driver. - */ -typedef struct I2CDriver I2CDriver; - -/** - * @brief Type of a structure representing an I2C driver. - */ -typedef struct I2CSlaveConfig I2CSlaveConfig; - - -/** - * @brief I2C notification callback type. - * @details This function must be used to send start or stop events to I2C bus, - * and change states of I2CDriver. - * - * @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, I2CSlaveConfig *i2cscfg); - - -/** - * @brief I2C error notification callback type. - * - * @param[in] i2cp TODO: pointer to the @p I2CDriver object triggering the - * callback - */ -typedef void (*i2cerrorcallback_t)(void); - - -/** - * @brief Driver configuration structure. - */ -typedef struct { - /** - * @brief I2C initialization data. - */ - uint16_t i2cc_cr1; - uint16_t i2cc_cr2; - uint16_t i2cc_ccr; - uint16_t i2cc_trise; - -} I2CConfig; - - -/** - * @brief TODO: - */ -typedef uint32_t i2cflags_t; - -/** - * @brief TODO: - */ -typedef uint8_t i2cblock_t; - - -/** - * @brief Structure representing an I2C slave configuration. - * @details Each slave has its own data buffers, adress, and error flags. - */ -struct I2CSlaveConfig{ - /** - * @brief Callback pointer. - * @note Transfer finished callback. Invoke when all data transferred, or - * by DMA buffer events - * @p NULL then the callback is disabled. - */ - i2ccallback_t id_callback; - /** - * @brief Callback pointer. - * @note TODO: I don't know, when this callback is inwoked - * @p NULL then the callback is disabled. - */ - i2cerrorcallback_t id_err_callback; - - i2cblock_t *rxbuf; // pointer to buffer - size_t rxdepth; // depth of buffer - size_t rxbytes; // count of bytes to sent in one sending - size_t rxbufhead; // head pointer to current data byte - - i2cblock_t *txbuf; - size_t txdepth; - size_t txbytes; - size_t txbufhead; - - uint8_t slave_addr1; // 7-bit address of the slave - uint8_t slave_addr2; // used in 10-bit address mode - - uint16_t error_flags; - - uint8_t rw_bit; // this flag contain R/W bit - - bool_t restart; // send restart or stop event after complete data tx/rx - -}; - - - -/** - * @brief Structure representing an I2C driver. - */ -struct I2CDriver{ - /** - * @brief Driver state. - */ - i2cstate_t id_state; -#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. - */ - I2CConfig *id_config; - /** - * @brief Current slave configuration data. - */ - I2CSlaveConfig *id_slave_config; - - /* End of the mandatory fields.*/ - /** - * @brief Thread waiting for I/O completion. - */ - Thread *id_thread; - /** - * @brief Pointer to the I2Cx registers block. - */ - I2C_TypeDef *id_i2c; - -} ; - - - - - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* 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_start(I2CDriver *i2cp); -void i2c_lld_stop(I2CDriver *i2cp); - -void i2c_lld_master_start(I2CDriver *i2cp); -void i2c_lld_master_stop(I2CDriver *i2cp); - -void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); -void i2c_lld_master_transmitI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); -bool_t i2c_lld_txbyte(I2CDriver *i2cp); // helper function - -void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); -void i2c_lld_master_receiveI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); -bool_t i2c_lld_rxbyte(I2CDriver *i2cp); - -#ifdef __cplusplus -} -#endif -/** @endcond*/ - -#endif // CH_HAL_USE_I2C - -#endif // _I2C_LLD_H_ From b2f4a22581819dfa9c7608d764d563f9146a4755 Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 27 Feb 2011 20:11:34 +0000 Subject: [PATCH 28/92] I2C. Platform independent I2CSlaveConfig structure moved to i2c.h. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2778 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 104 +++++++++++++++++++++++---- os/hal/platforms/STM32/i2c_lld.h | 117 ++++++------------------------- 2 files changed, 110 insertions(+), 111 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 5b7046627..2d07ae8f2 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -33,21 +33,7 @@ /*===========================================================================*/ /* Driver constants. */ /*===========================================================================*/ -#define I2CD_NO_ERROR 0 -/** @brief Bus Error.*/ -#define I2CD_BUS_ERROR 0x01 -/** @brief Arbitration Lost (master mode).*/ -#define I2CD_ARBITRATION_LOST 0x02 -/** @brief Acknowledge Failure.*/ -#define I2CD_ACK_FAILURE 0x04 -/** @brief Overrun/Underrun.*/ -#define I2CD_OVERRUN 0x08 -/** @brief PEC Error in reception.*/ -#define I2CD_PEC_ERROR 0x10 -/** @brief Timeout or Tlow Error.*/ -#define I2CD_TIMEOUT 0x20 -/** @brief SMBus Alert.*/ -#define I2CD_SMB_ALERT 0x40 + /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ @@ -88,8 +74,96 @@ typedef enum { I2C_SRECEIVE = 12, } i2cstate_t; + #include "i2c_lld.h" +/** + * @brief I2C notification callback type. + * @details This function must be used to send start or stop events to I2C bus, + * and change states of I2CDriver. + * + * @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, 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, I2CSlaveConfig *i2cscfg); + + +/** + * @brief I2C transmission data block size. + */ +typedef uint8_t i2cblock_t; + + +/** + * @brief Structure representing an I2C slave configuration. + */ +struct I2CSlaveConfig{ + /** + * @brief Callback pointer. + * @note Transfer finished callback. Invoke when all data transferred, or + * by DMA buffer events + * 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; + + i2cblock_t *rxbuf; // pointer to buffer + size_t rxdepth; // depth of buffer + size_t rxbytes; // count of bytes to sent in one transmission + size_t rxbufhead; // head pointer to current data byte + + i2cblock_t *txbuf; + size_t txdepth; + size_t txbytes; + size_t txbufhead; + + /** + * @brief Contain slave address and some flags. + * @details Bits 0..9 contain slave address in 10-bit mode. + * + * Bits 0..6 contain slave address in 7-bit mode. + * + * Bits 10..14 are not used in 10-bit mode. + * Bits 7..14 are not used in 7-bit mode. + * + * Bit 15 is used to switch between 10-bit and 7-bit modes + * (0 denotes 7-bit mode). + */ + uint16_t address; + + //TODO: (is it need?) merge rw_bit, restart and address in one 16-bit variable. + uint8_t rw_bit; + bool_t restart; // send restart if TRUE. Else sent stop event after complete data tx/rx + + +#if I2C_USE_WAIT + /** + * @brief Thread waiting for I/O completion. + */ + Thread *thread; +#endif /* I2C_USE_WAIT */ +}; + + /*===========================================================================*/ /* Driver macros. */ /*===========================================================================*/ diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 1f5356bca..9787360fd 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -55,45 +55,25 @@ /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ - +#define I2CD_NO_ERROR 0 +/** @brief Bus Error.*/ +#define I2CD_BUS_ERROR 0x01 +/** @brief Arbitration Lost (master mode).*/ +#define I2CD_ARBITRATION_LOST 0x02 +/** @brief Acknowledge Failure.*/ +#define I2CD_ACK_FAILURE 0x04 +/** @brief Overrun/Underrun.*/ +#define I2CD_OVERRUN 0x08 +/** @brief PEC Error in reception.*/ +#define I2CD_PEC_ERROR 0x10 +/** @brief Timeout or Tlow Error.*/ +#define I2CD_TIMEOUT 0x20 +/** @brief SMBus Alert.*/ +#define I2CD_SMB_ALERT 0x40 /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ -/** - * @brief Type of a structure representing an I2C driver. - */ -typedef struct I2CDriver I2CDriver; - -/** - * @brief Type of a structure representing an I2C driver. - */ -typedef struct I2CSlaveConfig I2CSlaveConfig; - - -/** - * @brief I2C notification callback type. - * @details This function must be used to send start or stop events to I2C bus, - * and change states of I2CDriver. - * - * @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, 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, I2CSlaveConfig *i2cscfg); - typedef enum { opmodeI2C, opmodeSMBusDevice, @@ -118,70 +98,15 @@ typedef struct { } I2CConfig; +/** + * @brief Type of a structure representing an I2C driver. + */ +typedef struct I2CDriver I2CDriver; /** - * @brief I2C transmission data block size. + * @brief Type of a structure representing an I2C slave config. */ -typedef uint8_t i2cblock_t; - - -/** - * @brief Structure representing an I2C slave configuration. - */ -struct I2CSlaveConfig{ - /** - * @brief Callback pointer. - * @note Transfer finished callback. Invoke when all data transferred, or - * by DMA buffer events - * 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; - - i2cblock_t *rxbuf; // pointer to buffer - size_t rxdepth; // depth of buffer - size_t rxbytes; // count of bytes to sent in one transmission - size_t rxbufhead; // head pointer to current data byte - - i2cblock_t *txbuf; - size_t txdepth; - size_t txbytes; - size_t txbufhead; - - /** - * @brief Contain slave address and some flags. - * @details Bits 0..9 contain slave address in 10-bit mode. - * - * Bits 0..6 contain slave address in 7-bit mode. - * - * Bits 10..14 are not used in 10-bit mode. - * Bits 7..14 are not used in 7-bit mode. - * - * Bit 15 is used to switch between 10-bit and 7-bit modes - * (0 denotes 7-bit mode). - */ - uint16_t address; - - //TODO: (is it need?) merge rw_bit, restart and address in one 16-bit variable. - uint8_t rw_bit; - bool_t restart; // send restart if TRUE. Else sent stop event after complete data tx/rx - - -#if I2C_USE_WAIT - /** - * @brief Thread waiting for I/O completion. - */ - Thread *thread; -#endif /* I2C_USE_WAIT */ -}; - - +typedef struct I2CSlaveConfig I2CSlaveConfig; /** * @brief Structure representing an I2C driver. From 44578159320d9d9bf89e8ac3b4d21635e8a45f10 Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 26 Mar 2011 14:28:52 +0000 Subject: [PATCH 29/92] I2C. Some improvements. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2841 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 11 +++++++++-- os/hal/platforms/STM32/i2c_lld.c | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 2d07ae8f2..c2f717432 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -79,8 +79,15 @@ typedef enum { /** * @brief I2C notification callback type. - * @details This function must be used to send start or stop events to I2C bus, - * and change states of I2CDriver. + * @details This callback invoked when byte transfer finish event generated, + * No matter sending or reading. This function designed + * for sending (re)start or stop events to I2C bus. + * Use "restart" boolean flag + * in I2CSlaveConfig structure for this needs. + * Each slave can (must?) have its own callback function. + * + * If callback function is set to NULL - driver generate stop + * condition on the bus after the transfer finish. * * @param[in] i2cp pointer to the @p I2CDriver object triggering the * callback diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 154a735fa..cb75b6da2 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -195,8 +195,16 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ chSysLockFromIsr(); i2cp->id_i2c->CR2 &= (~I2C_CR2_ITEVTEN); // disable BTF interrupt - i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); chSysUnlockFromIsr(); + /* now driver is ready to generate (re)start/stop condition. + * Callback function is good place to do that.*/ + i2cp->id_state = I2C_READY; + + if (i2cp->id_slave_config->id_callback != NULL) + i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); + else /* If no callback function set - generate stop */ + i2c_lld_master_stop(i2cp); + return; } else{ // debugging trap @@ -455,7 +463,9 @@ void i2c_lld_master_start(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_START; while (i2cp->id_i2c->CR1 & I2C_CR1_START); - i2cp->id_i2c->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; // enable interrupts + /* enable interrupts from I2C hardware. They will disable in driver state + machine after the tranafer finish.*/ + i2cp->id_i2c->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; } void i2c_lld_master_stop(I2CDriver *i2cp){ From d0397838aeed91201230290ec052fe2f94840b56 Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 26 Mar 2011 21:28:14 +0000 Subject: [PATCH 30/92] I2C. Small bugfix. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2844 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 4 ++++ os/hal/platforms/STM32/i2c_lld.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index c2f717432..53f4cd86a 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -116,6 +116,7 @@ typedef uint8_t i2cblock_t; /** * @brief Structure representing an I2C slave configuration. + * @details TODO: write about befers */ struct I2CSlaveConfig{ /** @@ -133,6 +134,9 @@ struct I2CSlaveConfig{ */ i2cerrorcallback_t id_err_callback; + /** + * @brief Pointer to input buffer. + */ i2cblock_t *rxbuf; // pointer to buffer size_t rxdepth; // depth of buffer size_t rxbytes; // count of bytes to sent in one transmission diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index cb75b6da2..804246b2d 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -297,8 +297,8 @@ void i2c_lld_start(I2CDriver *i2cp) { #endif #if STM32_I2C_USE_I2C2 if (&I2CD2 == i2cp) { - NVICEnableVector(I2C2_EV_IRQn, STM32_I2C2_IRQ_PRIORITY); - NVICEnableVector(I2C2_ER_IRQn, STM32_I2C2_IRQ_PRIORITY); + NVICEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); + NVICEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); RCC->APB1ENR |= RCC_APB1ENR_I2C2EN; // I2C 2 clock enable } #endif From d16a6e24d95bdd9b2596e9494e2f7294d56fa070 Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 27 Mar 2011 14:57:47 +0000 Subject: [PATCH 31/92] I2C. API changes. rw_bit field moved from slave config ctructure to the driver structure. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2845 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 2 -- os/hal/platforms/STM32/i2c_lld.c | 14 +++++++------- os/hal/platforms/STM32/i2c_lld.h | 12 +++++++++++- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 53f4cd86a..3f9186125 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -161,8 +161,6 @@ struct I2CSlaveConfig{ */ uint16_t address; - //TODO: (is it need?) merge rw_bit, restart and address in one 16-bit variable. - uint8_t rw_bit; bool_t restart; // send restart if TRUE. Else sent stop event after complete data tx/rx diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 804246b2d..94c3c0da3 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -124,7 +124,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { if(!(i2cp->id_slave_config->address & 0x8000)){ // slave address is 7-bit i2cp->id_i2c->DR = ((i2cp->id_slave_config->address & 0x7F) << 1) | - i2cp->id_slave_config->rw_bit; + i2cp->rw_bit; i2cp->id_state = I2C_MWAIT_ADDR_ACK; return; } @@ -139,7 +139,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { // "wait" interrupt with ADD10 flag if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADD10)){ i2cp->id_i2c->DR = i2cp->id_slave_config->address & 0x00FF; // send remaining bits of address - if (!(i2cp->id_slave_config->rw_bit)) + if (!(i2cp->rw_bit)) // in transmit mode there is nothing to do with 10-bit handshaking i2cp->id_state = I2C_MWAIT_ADDR_ACK; return; @@ -310,7 +310,7 @@ void i2c_lld_start(I2CDriver *i2cp) { i2c_lld_set_clock(i2cp); i2c_lld_set_opmode(i2cp); - i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN | I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; + i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN | I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN;// enable interrupts i2cp->id_i2c->CR1 |= 1; // enable interface } @@ -477,7 +477,7 @@ void i2c_lld_master_stop(I2CDriver *i2cp){ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ i2cp->id_slave_config = i2cscfg; - i2cp->id_slave_config->rw_bit = I2C_WRITE; + i2cp->rw_bit = I2C_WRITE; // generate start condition. Later transmission goes in background i2c_lld_master_start(i2cp); @@ -486,7 +486,7 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ i2cp->id_slave_config = i2cscfg; - i2cp->id_slave_config->rw_bit = I2C_READ; + i2cp->rw_bit = I2C_READ; // generate (re)start condition. Later connection goes asynchronously i2c_lld_master_start(i2cp); @@ -495,7 +495,7 @@ void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ /** - * @brief Transmits data ever the I2C bus as masteri2cp. + * @brief Transmits data via I2C bus. * * @note This function does not use interrupts * @@ -508,7 +508,7 @@ void i2c_lld_master_transmit_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t int i = 0; i2cp->id_slave_config = i2cscfg; - i2cp->id_slave_config->rw_bit = I2C_WRITE; + i2cp->rw_bit = I2C_WRITE; i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate start condition diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 9787360fd..76f7068e2 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -116,6 +116,12 @@ struct I2CDriver{ * @brief Driver state. */ i2cstate_t id_state; +#if I2C_USE_WAIT + /** + * @brief Thread waiting for I/O completion. + */ + Thread *thread; +#endif /* I2C_USE_WAIT */ #if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) #if CH_USE_MUTEXES || defined(__DOXYGEN__) /** @@ -134,8 +140,12 @@ struct I2CDriver{ * @brief Current slave configuration data. */ I2CSlaveConfig *id_slave_config; + /** + * @brief RW-bit sent to slave. + */ + uint8_t rw_bit; - /* End of the mandatory fields.*/ + /*********** End of the mandatory fields. **********************************/ /** * @brief Pointer to the I2Cx registers block. From 1ab46c6fb9e7a6f8283886b0d9de5357a08b3740 Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 27 Mar 2011 15:58:39 +0000 Subject: [PATCH 32/92] I2C. Doxy comments improvement. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2846 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 42 +++++++++++--------- os/hal/platforms/STM32/i2c_lld.c | 67 +++++++++++++++++++++++++++----- 2 files changed, 81 insertions(+), 28 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 3f9186125..a01606a18 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -79,15 +79,12 @@ typedef enum { /** * @brief I2C notification callback type. - * @details This callback invoked when byte transfer finish event generated, + * @details This callback invoked when byte transfer finish event occurs, * No matter sending or reading. This function designed - * for sending (re)start or stop events to I2C bus. - * Use "restart" boolean flag - * in I2CSlaveConfig structure for this needs. - * Each slave can (must?) have its own callback function. + * for sending (re)start or stop events to I2C bus from user level. * - * If callback function is set to NULL - driver generate stop - * condition on the bus after the transfer finish. + * If callback function is set to NULL - driver atomaticcaly + * generate stop condition after the transfer finish. * * @param[in] i2cp pointer to the @p I2CDriver object triggering the * callback @@ -115,8 +112,9 @@ typedef uint8_t i2cblock_t; /** - * @brief Structure representing an I2C slave configuration. - * @details TODO: write about befers + * @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{ /** @@ -135,17 +133,17 @@ struct I2CSlaveConfig{ i2cerrorcallback_t id_err_callback; /** - * @brief Pointer to input buffer. + * @brief Receive and transmit buffers. */ - i2cblock_t *rxbuf; // pointer to buffer - size_t rxdepth; // depth of buffer - size_t rxbytes; // count of bytes to sent in one transmission - size_t rxbufhead; // head pointer to current data byte + i2cblock_t *rxbuf; /*!< Pointer to receive buffer. */ + size_t rxdepth; /*!< Depth of buffer. */ + size_t rxbytes; /*!< Number of bytes to be receive in one transmission. */ + size_t rxbufhead; /*!< Pointer to current data byte. */ - i2cblock_t *txbuf; - size_t txdepth; - size_t txbytes; - size_t txbufhead; + i2cblock_t *txbuf; /*!< Pointer to transmit buffer.*/ + size_t txdepth; /*!< Depth of buffer. */ + size_t txbytes; /*!< Number of bytes to be transmit in one transmission. */ + size_t txbufhead; /*!< Pointer to current data byte. */ /** * @brief Contain slave address and some flags. @@ -161,7 +159,13 @@ struct I2CSlaveConfig{ */ uint16_t address; - bool_t restart; // send restart if TRUE. Else sent stop event after complete data tx/rx + /** + * @brief Boolean flag for dealing with start/stop conditions. + * @note This flag destined to use in callback functions. It place here + * for convenience and flexibility reasons, but you can use your + * own variable from user level code. + */ + bool_t restart; #if I2C_USE_WAIT diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 94c3c0da3..9dc3a66bc 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -33,6 +33,12 @@ I2CDriver I2CD2; /* Driver local functions. */ /*===========================================================================*/ +/** + * @brief Interrupt service routine. + * @details This function handle all ERROR interrupt conditions. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { //TODO: more robust error handling chSysLockFromIsr(); @@ -101,14 +107,20 @@ inline bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { } -/* - * This function handle all regular interrupt conditions +/** + * @brief Interrupt service routine. + * @details This function handle all regular interrupt conditions. + * + * @param[in] i2cp pointer to the @p I2CDriver object */ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { + +#if CH_DBG_ENABLE_CHECKS // debug variables int i = 0; int n = 0; int m = 0; +#endif /* In 10-bit addressing mode, – To enter Transmitter mode, a master sends the header (11110xx0) and then the @@ -165,7 +177,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { i2c_lld_txbyte(i2cp); // send first byte return; } - else { + else {// I2C is receiving data /* In order to generate the non-acknowledge pulse after the last received * data byte, the ACK bit must be cleared just after reading the second * last data byte (after second last RxNE event). @@ -197,22 +209,25 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { i2cp->id_i2c->CR2 &= (~I2C_CR2_ITEVTEN); // disable BTF interrupt chSysUnlockFromIsr(); /* now driver is ready to generate (re)start/stop condition. - * Callback function is good place to do that.*/ + * Callback function is good place to do that. If not callback was + * set - driver only generate stop condition. */ i2cp->id_state = I2C_READY; if (i2cp->id_slave_config->id_callback != NULL) i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); - else /* If no callback function set - generate stop */ + else /* No callback function set - generate stop */ i2c_lld_master_stop(i2cp); return; } +#if CH_DBG_ENABLE_CHECKS else{ // debugging trap i = i2cp->id_i2c->SR1; n = i2cp->id_i2c->SR2; m = i2cp->id_i2c->CR1; - return; + while(TRUE); } +#endif /* CH_DBG_ENABLE_CHECKS */ } #if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) @@ -314,7 +329,11 @@ void i2c_lld_start(I2CDriver *i2cp) { i2cp->id_i2c->CR1 |= 1; // enable interface } - +/** + * @brief Set clock speed. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ void i2c_lld_set_clock(I2CDriver *i2cp) { volatile uint16_t regCCR, regCR2, freq, clock_div; volatile uint16_t pe_bit_saved; @@ -389,6 +408,11 @@ void i2c_lld_set_clock(I2CDriver *i2cp) { i2cp->id_i2c->CR1 |= pe_bit_saved; } +/** + * @brief Set operation mode of I2C hardware. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ void i2c_lld_set_opmode(I2CDriver *i2cp) { I2C_opMode_t opmode = i2cp->id_config->opMode; uint16_t regCR1; @@ -412,6 +436,11 @@ void i2c_lld_set_opmode(I2CDriver *i2cp) { i2cp->id_i2c->CR1 = regCR1; } +/** + * @brief Set own address. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ void i2c_lld_set_own_address(I2CDriver *i2cp) { //TODO: dual address mode @@ -458,7 +487,11 @@ void i2c_lld_stop(I2CDriver *i2cp) { i2cp->id_state = I2C_STOP; } - +/** + * @brief Generate start condition. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ void i2c_lld_master_start(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_START; while (i2cp->id_i2c->CR1 & I2C_CR1_START); @@ -468,12 +501,22 @@ void i2c_lld_master_start(I2CDriver *i2cp){ i2cp->id_i2c->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; } +/** + * @brief Generate stop condition. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ void i2c_lld_master_stop(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_STOP; while (i2cp->id_i2c->CR1 & I2C_CR1_STOP); } - +/** + * @brief Begin data transmitting. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object + */ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ i2cp->id_slave_config = i2cscfg; @@ -483,6 +526,12 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ i2c_lld_master_start(i2cp); } +/** + * @brief Begin data receiving. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object + */ void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ i2cp->id_slave_config = i2cscfg; From 7a694b4402e8d47ef0fdc651492ee09084ebcad0 Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 27 Mar 2011 21:12:43 +0000 Subject: [PATCH 33/92] I2C. Mutual exclusion support added. Need testing. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2847 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/i2c.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 7dede9f86..11d4fccfa 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -69,6 +69,19 @@ void i2cObjectInit(I2CDriver *i2cp) { i2cp->id_state = I2C_STOP; i2cp->id_config = NULL; i2cp->id_slave_config = NULL; + +#if I2C_USE_WAIT + i2cp->id_thread = NULL; +#endif /* I2C_USE_WAIT */ + +#if I2C_USE_MUTUAL_EXCLUSION +#if CH_USE_MUTEXES + chMtxInit(&i2cp->id_mutex); +#else + chSemInit(&i2cp->id_semaphore, 1); +#endif /* CH_USE_MUTEXES */ +#endif /* I2C_USE_MUTUAL_EXCLUSION */ + #if defined(I2C_DRIVER_EXT_INIT_HOOK) I2C_DRIVER_EXT_INIT_HOOK(i2cp); #endif From 573b5e875bd8431963fc3a40885020f7e3310640 Mon Sep 17 00:00:00 2001 From: barthess Date: Fri, 1 Apr 2011 18:23:35 +0000 Subject: [PATCH 34/92] I2C. Usage example added. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2864 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- testhal/STM32/I2C/Makefile | 213 +++++++++++++++ testhal/STM32/I2C/ch.ld | 113 ++++++++ testhal/STM32/I2C/chconf.h | 507 ++++++++++++++++++++++++++++++++++++ testhal/STM32/I2C/halconf.h | 259 ++++++++++++++++++ testhal/STM32/I2C/i2c_pns.c | 61 +++++ testhal/STM32/I2C/i2c_pns.h | 8 + testhal/STM32/I2C/lis3.c | 170 ++++++++++++ testhal/STM32/I2C/lis3.h | 28 ++ testhal/STM32/I2C/main.c | 120 +++++++++ testhal/STM32/I2C/main.h | 19 ++ testhal/STM32/I2C/max1236.c | 106 ++++++++ testhal/STM32/I2C/max1236.h | 14 + testhal/STM32/I2C/mcuconf.h | 131 ++++++++++ testhal/STM32/I2C/tmp75.c | 72 +++++ testhal/STM32/I2C/tmp75.h | 13 + 15 files changed, 1834 insertions(+) create mode 100644 testhal/STM32/I2C/Makefile create mode 100644 testhal/STM32/I2C/ch.ld create mode 100644 testhal/STM32/I2C/chconf.h create mode 100644 testhal/STM32/I2C/halconf.h create mode 100644 testhal/STM32/I2C/i2c_pns.c create mode 100644 testhal/STM32/I2C/i2c_pns.h create mode 100644 testhal/STM32/I2C/lis3.c create mode 100644 testhal/STM32/I2C/lis3.h create mode 100644 testhal/STM32/I2C/main.c create mode 100644 testhal/STM32/I2C/main.h create mode 100644 testhal/STM32/I2C/max1236.c create mode 100644 testhal/STM32/I2C/max1236.h create mode 100644 testhal/STM32/I2C/mcuconf.h create mode 100644 testhal/STM32/I2C/tmp75.c create mode 100644 testhal/STM32/I2C/tmp75.h diff --git a/testhal/STM32/I2C/Makefile b/testhal/STM32/I2C/Makefile new file mode 100644 index 000000000..888e33eb2 --- /dev/null +++ b/testhal/STM32/I2C/Makefile @@ -0,0 +1,213 @@ +############################################################################## +# Build global options +# NOTE: Can be overridden externally. +# + +# Compiler options here. +ifeq ($(USE_OPT),) + USE_OPT = -O0 -ggdb -fomit-frame-pointer -falign-functions=16 -Wall -Wextra + #USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16 -Wall -Wextra +endif + +# C++ specific options here (added to USE_OPT). +ifeq ($(USE_CPPOPT),) + USE_CPPOPT = -fno-rtti +endif + +# Enable this if you want the linker to remove unused code and data +ifeq ($(USE_LINK_GC),) + USE_LINK_GC = yes +endif + +# If enabled, this option allows to compile the application in THUMB mode. +ifeq ($(USE_THUMB),) + USE_THUMB = yes +endif + +# Enable register caching optimization (read documentation). +ifeq ($(USE_CURRP_CACHING),) + USE_CURRP_CACHING = no +endif + +# +# Build global options +############################################################################## + +############################################################################## +# Architecture or project specific options +# + +# Enable this if you really want to use the STM FWLib. +ifeq ($(USE_FWLIB),) + USE_FWLIB = no +endif + +# +# Architecture or project specific options +############################################################################## + +############################################################################## +# Project, sources and paths +# + +# Define project name here +PROJECT = ch + +# Define linker script file here +LDSCRIPT= ch.ld + +# Imported source files +CHIBIOS = ../../.. +include $(CHIBIOS)/boards/OLIMEX_STM32_P103/board.mk +include $(CHIBIOS)/os/hal/platforms/STM32/platform.mk +include $(CHIBIOS)/os/hal/hal.mk +include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32/port.mk +include $(CHIBIOS)/os/kernel/kernel.mk +include $(CHIBIOS)/test/test.mk + +# C sources that can be compiled in ARM or THUMB mode depending on the global +# setting. +CSRC = $(PORTSRC) \ + $(KERNSRC) \ + $(TESTSRC) \ + $(HALSRC) \ + $(PLATFORMSRC) \ + $(BOARDSRC) \ + $(CHIBIOS)/os/various/evtimer.c \ + $(CHIBIOS)/os/various/syscalls.c \ + main.c \ + i2c_pns.c \ + lis3.c\ + tmp75.c\ + max1236.c\ + +# C++ sources that can be compiled in ARM or THUMB mode depending on the global +# setting. +CPPSRC = + +# C sources to be compiled in ARM mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +ACSRC = + +# C++ sources to be compiled in ARM mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +ACPPSRC = + +# C sources to be compiled in THUMB mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +TCSRC = + +# C sources to be compiled in THUMB mode regardless of the global setting. +# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler +# option that results in lower performance and larger code size. +TCPPSRC = + +# List ASM source files here +ASMSRC = $(PORTASM) + +INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \ + $(HALINC) $(PLATFORMINC) $(BOARDINC) \ + $(CHIBIOS)/os/various + +# +# Project, sources and paths +############################################################################## + +############################################################################## +# Compiler settings +# + +# -lm äîáàâëåí èìåííî çäåñü, ïîòîìó ÷òî áîëüøå íåêóäà +MCU = cortex-m3 + +#TRGT = arm-elf- +TRGT = arm-none-eabi- +CC = $(TRGT)gcc +CPPC = $(TRGT)g++ +# Enable loading with g++ only if you need C++ runtime support. +# NOTE: You can use C++ even without C++ support if you are careful. C++ +# runtime support makes code size explode. + +LD = $(TRGT)gcc +#LD = $(TRGT)g++ +CP = $(TRGT)objcopy +AS = $(TRGT)gcc -x assembler-with-cpp +OD = $(TRGT)objdump +HEX = $(CP) -O ihex +BIN = $(CP) -O binary + +# ARM-specific options here +AOPT = + +# THUMB-specific options here +TOPT = -mthumb -DTHUMB + +# Define C warning options here +CWARN = -Wall -Wextra -Wstrict-prototypes + +# Define C++ warning options here +CPPWARN = -Wall -Wextra + +# +# Compiler settings +############################################################################## + +############################################################################## +# Start of default section +# + +# List all default C defines here, like -D_DEBUG=1 +DDEFS = + +# List all default ASM defines here, like -D_DEBUG=1 +DADEFS = + +# List all default directories to look for include files here +DINCDIR = + +# List the default directory to look for the libraries here +DLIBDIR = + +# List all default libraries here +DLIBS = + +# +# End of default section +############################################################################## + +############################################################################## +# Start of user section +# + +# List all user C define here, like -D_DEBUG=1 +UDEFS = + +# Define ASM defines here +UADEFS = + +# List all user directories here +UINCDIR = + +# List the user directory to look for the libraries here +ULIBDIR = + +# List all user libraries here +ULIBS = + +# +# End of user defines +############################################################################## + +ifeq ($(USE_FWLIB),yes) + include $(CHIBIOS)/ext/stm32lib/stm32lib.mk + CSRC += $(STM32SRC) + INCDIR += $(STM32INC) + USE_OPT += -DUSE_STDPERIPH_DRIVER +endif + +include $(CHIBIOS)/os/ports/GCC/ARMCMx/rules.mk + + diff --git a/testhal/STM32/I2C/ch.ld b/testhal/STM32/I2C/ch.ld new file mode 100644 index 000000000..44f494121 --- /dev/null +++ b/testhal/STM32/I2C/ch.ld @@ -0,0 +1,113 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . +*/ + +/* + * ST32F103 memory setup. + */ +__main_stack_size__ = 0x0400; +__process_stack_size__ = 0x0400; +__stacks_total_size__ = __main_stack_size__ + __process_stack_size__; + +MEMORY +{ + flash : org = 0x08000000, len = 128k + ram : org = 0x20000000, len = 20k +} + +__ram_start__ = ORIGIN(ram); +__ram_size__ = LENGTH(ram); +__ram_end__ = __ram_start__ + __ram_size__; + +SECTIONS +{ + . = 0; + + .text : ALIGN(16) SUBALIGN(16) + { + _text = .; + KEEP(*(vectors)) + *(.text) + *(.text.*) + *(.rodata) + *(.rodata.*) + *(.glue_7t) + *(.glue_7) + *(.gcc*) + } > flash + + .ctors : + { + PROVIDE(_ctors_start_ = .); + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + PROVIDE(_ctors_end_ = .); + } > flash + + .dtors : + { + PROVIDE(_dtors_start_ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(_dtors_end_ = .); + } > flash + + .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} + + __exidx_start = .; + .ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > flash + __exidx_end = .; + + .eh_frame_hdr : {*(.eh_frame_hdr)} + + .eh_frame : ONLY_IF_RO {*(.eh_frame)} + + . = ALIGN(4); + _etext = .; + _textdata = _etext; + + .data : + { + _data = .; + *(.data) + . = ALIGN(4); + *(.data.*) + . = ALIGN(4); + *(.ramtext) + . = ALIGN(4); + _edata = .; + } > ram AT > flash + + .bss : + { + _bss_start = .; + *(.bss) + . = ALIGN(4); + *(.bss.*) + . = ALIGN(4); + *(COMMON) + . = ALIGN(4); + _bss_end = .; + } > ram +} + +PROVIDE(end = .); +_end = .; + +__heap_base__ = _end; +__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/testhal/STM32/I2C/chconf.h b/testhal/STM32/I2C/chconf.h new file mode 100644 index 000000000..657ddf887 --- /dev/null +++ b/testhal/STM32/I2C/chconf.h @@ -0,0 +1,507 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . +*/ + +/** + * @file templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef _CHCONF_H_ +#define _CHCONF_H_ + +/*===========================================================================*/ +/* Kernel parameters. */ +/*===========================================================================*/ + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#if !defined(CH_FREQUENCY) || defined(__DOXYGEN__) +#define CH_FREQUENCY 1000 +#endif + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + */ +#if !defined(CH_TIME_QUANTUM) || defined(__DOXYGEN__) +#define CH_TIME_QUANTUM 20 +#endif + +/** + * @brief Nested locks. + * @details If enabled then the use of nested @p chSysLock() / @p chSysUnlock() + * operations is allowed.
+ * For performance and code size reasons the recommended setting + * is to leave this option disabled.
+ * You may use this option if you need to merge ChibiOS/RT with + * external libraries that require nested lock/unlock operations. + * + * @note T he default is @p FALSE. + */ +#if !defined(CH_USE_NESTED_LOCKS) || defined(__DOXYGEN__) +#define CH_USE_NESTED_LOCKS TRUE +#endif + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_USE_COREMEM. + */ +#if !defined(CH_MEMCORE_SIZE) || defined(__DOXYGEN__) +#define CH_MEMCORE_SIZE 0 +#endif + +/*===========================================================================*/ +/* Performance options. */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#if !defined(CH_OPTIMIZE_SPEED) || defined(__DOXYGEN__) +#define CH_OPTIMIZE_SPEED FALSE +#endif + +/** + * @brief Exotic optimization. + * @details If defined then a CPU register is used as storage for the global + * @p currp variable. Caching this variable in a register greatly + * improves both space and time OS efficiency. A side effect is that + * one less register has to be saved during the context switch + * resulting in lower RAM usage and faster context switch. + * + * @note This option is only usable with the GCC compiler and is only useful + * on processors with many registers like ARM cores. + * @note If this option is enabled then ALL the libraries linked to the + * ChibiOS/RT code must be recompiled with the GCC option @p + * -ffixed-@. + * @note This option must be enabled in the Makefile, it is listed here for + * documentation only. + */ +#if defined(__DOXYGEN__) +#define CH_CURRP_REGISTER_CACHE "reg" +#endif + +/*===========================================================================*/ +/* Subsystem options. */ +/*===========================================================================*/ + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_USE_REGISTRY) || defined(__DOXYGEN__) +#define CH_USE_REGISTRY TRUE +#endif + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__) +#define CH_USE_WAITEXIT TRUE +#endif + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__) +#define CH_USE_SEMAPHORES TRUE +#endif + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special requirements. + * @note Requires @p CH_USE_SEMAPHORES. + */ +#if !defined(CH_USE_SEMAPHORES_PRIORITY) || defined(__DOXYGEN__) +#define CH_USE_SEMAPHORES_PRIORITY FALSE +#endif + +/** + * @brief Atomic semaphore API. + * @details If enabled then the semaphores the @p chSemSignalWait() API + * is included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_USE_SEMAPHORES. + */ +#if !defined(CH_USE_SEMSW) || defined(__DOXYGEN__) +#define CH_USE_SEMSW TRUE +#endif + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__) +#define CH_USE_MUTEXES FALSE +#endif + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_USE_MUTEXES. + */ +#if !defined(CH_USE_CONDVARS) || defined(__DOXYGEN__) +#define CH_USE_CONDVARS FALSE +#endif + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_USE_CONDVARS. + */ +#if !defined(CH_USE_CONDVARS_TIMEOUT) || defined(__DOXYGEN__) +#define CH_USE_CONDVARS_TIMEOUT TRUE +#endif + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__) +#define CH_USE_EVENTS TRUE +#endif + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_USE_EVENTS. + */ +#if !defined(CH_USE_EVENTS_TIMEOUT) || defined(__DOXYGEN__) +#define CH_USE_EVENTS_TIMEOUT TRUE +#endif + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__) +#define CH_USE_MESSAGES TRUE +#endif + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special requirements. + * @note Requires @p CH_USE_MESSAGES. + */ +#if !defined(CH_USE_MESSAGES_PRIORITY) || defined(__DOXYGEN__) +#define CH_USE_MESSAGES_PRIORITY FALSE +#endif + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_USE_SEMAPHORES. + */ +#if !defined(CH_USE_MAILBOXES) || defined(__DOXYGEN__) +#define CH_USE_MAILBOXES TRUE +#endif + +/** + * @brief I/O Queues APIs. + * @details If enabled then the I/O queues APIs are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_USE_SEMAPHORES. + */ +#if !defined(CH_USE_QUEUES) || defined(__DOXYGEN__) +#define CH_USE_QUEUES TRUE +#endif + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_USE_MEMCORE) || defined(__DOXYGEN__) +#define CH_USE_MEMCORE TRUE +#endif + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_USE_COREMEM and either @p CH_USE_MUTEXES or + * @p CH_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#if !defined(CH_USE_HEAP) || defined(__DOXYGEN__) +#define CH_USE_HEAP FALSE +#endif + +/** + * @brief C-runtime allocator. + * @details If enabled the the heap allocator APIs just wrap the C-runtime + * @p malloc() and @p free() functions. + * + * @note The default is @p FALSE. + * @note Requires @p CH_USE_HEAP. + * @note The C-runtime may or may not require @p CH_USE_COREMEM, see the + * appropriate documentation. + */ +#if !defined(CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__) +#define CH_USE_MALLOC_HEAP FALSE +#endif + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__) +#define CH_USE_MEMPOOLS FALSE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_USE_WAITEXIT. + * @note Requires @p CH_USE_HEAP and/or @p CH_USE_MEMPOOLS. + */ +#if !defined(CH_USE_DYNAMIC) || defined(__DOXYGEN__) +#define CH_USE_DYNAMIC FALSE +#endif + +/*===========================================================================*/ +/* Debug options. */ +/*===========================================================================*/ + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__) +#define CH_DBG_ENABLE_CHECKS TRUE +#endif + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__) +#define CH_DBG_ENABLE_ASSERTS TRUE +#endif + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the context switch circular trace buffer is + * activated. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__) +#define CH_DBG_ENABLE_TRACE TRUE +#endif + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__) +#define CH_DBG_ENABLE_STACK_CHECK TRUE +#endif + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_FILL_THREADS) || defined(__DOXYGEN__) +#define CH_DBG_FILL_THREADS TRUE +#endif + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p Thread structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p TRUE. + * @note This debug option is defaulted to TRUE because it is required by + * some test cases into the test suite. + */ +#if !defined(CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__) +#define CH_DBG_THREADS_PROFILING FALSE +#endif + +/*===========================================================================*/ +/* Kernel hooks. */ +/*===========================================================================*/ + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p Thread structure. + */ +#if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__) +#define THREAD_EXT_FIELDS \ + /* Add threads custom fields here.*/ +#endif + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p chThdInit() API. + * + * @note It is invoked from within @p chThdInit() and implicitily from all + * the threads creation APIs. + */ +#if !defined(THREAD_EXT_INIT_HOOK) || defined(__DOXYGEN__) +#define THREAD_EXT_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} +#endif + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + * + * @note It is inserted into lock zone. + * @note It is also invoked when the threads simply return in order to + * terminate. + */ +#if !defined(THREAD_EXT_EXIT_HOOK) || defined(__DOXYGEN__) +#define THREAD_EXT_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} +#endif + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__) +#define IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} +#endif + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#if !defined(SYSTEM_TICK_EVENT_HOOK) || defined(__DOXYGEN__) +#define SYSTEM_TICK_EVENT_HOOK() { \ + /* System tick event code here.*/ \ +} +#endif + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#if !defined(SYSTEM_HALT_HOOK) || defined(__DOXYGEN__) +#define SYSTEM_HALT_HOOK() { \ + /* System halt code here.*/ \ +} +#endif + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* _CHCONF_H_ */ + +/** @} */ diff --git a/testhal/STM32/I2C/halconf.h b/testhal/STM32/I2C/halconf.h new file mode 100644 index 000000000..9a7979cc9 --- /dev/null +++ b/testhal/STM32/I2C/halconf.h @@ -0,0 +1,259 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . +*/ + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef _HALCONF_H_ +#define _HALCONF_H_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC TRUE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C TRUE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM TRUE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART TRUE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Block size for MMC transfers. + */ +#if !defined(MMC_SECTOR_SIZE) || defined(__DOXYGEN__) +#define MMC_SECTOR_SIZE 512 +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/** + * @brief Number of positive insertion queries before generating the + * insertion event. + */ +#if !defined(MMC_POLLING_INTERVAL) || defined(__DOXYGEN__) +#define MMC_POLLING_INTERVAL 10 +#endif + +/** + * @brief Interval, in milliseconds, between insertion queries. + */ +#if !defined(MMC_POLLING_DELAY) || defined(__DOXYGEN__) +#define MMC_POLLING_DELAY 10 +#endif + +/** + * @brief Uses the SPI polled API for small data transfers. + * @details Polled transfers usually improve performance because it + * saves two context switches and interrupt servicing. Note + * that this option has no effect on large transfers which + * are always performed using DMAs/IRQs. + */ +#if !defined(MMC_USE_SPI_POLLING) || defined(__DOXYGEN__) +#define MMC_USE_SPI_POLLING TRUE +#endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* PWM driver related settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 38400 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 64 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +#endif /* _HALCONF_H_ */ + +/** @} */ diff --git a/testhal/STM32/I2C/i2c_pns.c b/testhal/STM32/I2C/i2c_pns.c new file mode 100644 index 000000000..11982d0a7 --- /dev/null +++ b/testhal/STM32/I2C/i2c_pns.c @@ -0,0 +1,61 @@ +#include "ch.h" +#include "hal.h" + +#include "i2c_pns.h" + +#include "lis3.h" +#include "tmp75.h" +#include "max1236.h" + +/* I2C1 */ +static I2CConfig i2cfg1 = { + opmodeI2C, + 100000, + stdDutyCycle, + 0, + 0, +}; + +/* I2C2 */ +static I2CConfig i2cfg2 = { + opmodeI2C, + 100000, + stdDutyCycle, + 0, + 0, +}; + + + +void I2CInit_pns(void){ + + i2cInit(); + + i2cStart(&I2CD1, &i2cfg1); + while(I2CD1.id_state != I2C_READY){ // wait ready status + chThdSleepMilliseconds(1); + } + + i2cStart(&I2CD2, &i2cfg2); + while(I2CD2.id_state != I2C_READY){ // wait ready status + chThdSleepMilliseconds(1); + } + + /* tune ports for I2C1*/ + palSetPadMode(IOPORT2, 6, 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 */ + init_max1236(); + chThdSleepMilliseconds(100); + + init_lis3(); + chThdSleepMilliseconds(100); +} + + diff --git a/testhal/STM32/I2C/i2c_pns.h b/testhal/STM32/I2C/i2c_pns.h new file mode 100644 index 000000000..4dfdf320e --- /dev/null +++ b/testhal/STM32/I2C/i2c_pns.h @@ -0,0 +1,8 @@ +#ifndef I2C_PNS_H_ +#define I2C_PNS_H_ + + +void I2CInit_pns(void); + + +#endif /* I2C_PNS_H_ */ diff --git a/testhal/STM32/I2C/lis3.c b/testhal/STM32/I2C/lis3.c new file mode 100644 index 000000000..06f6da1d0 --- /dev/null +++ b/testhal/STM32/I2C/lis3.c @@ -0,0 +1,170 @@ +/** + * This is most complex and difficult device. + * It realize "read through write" paradigm. This is not standard, but + * most of I2C devices use this paradigm. + * You must write to device reading address, send restart to bus, + * and then begin reading process. + */ + +#include + +#include "ch.h" +#include "hal.h" + +#include "lis3.h" + + +// buffers +static i2cblock_t accel_rx_data[ACCEL_RX_DEPTH]; +static i2cblock_t accel_tx_data[ACCEL_TX_DEPTH]; + +/* Error trap */ +static void i2c_lis3_error_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ + (void)i2cscfg; + int status = 0; + status = i2cp->id_i2c->SR1; + while(TRUE); +} + +// Accelerometer lis3lv02dq config +static I2CSlaveConfig lis3 = { + NULL, + i2c_lis3_error_cb, + accel_rx_data, + ACCEL_RX_DEPTH, + 0, + 0, + accel_tx_data, + ACCEL_TX_DEPTH, + 0, + 0, + 0b0011101, + FALSE, +}; + + +/** + * This treading need for convenient realize + * "read through write" process. + */ +static WORKING_AREA(I2CAccelThreadWA, 128); +static Thread *i2c_accel_tp = NULL; +static msg_t I2CAccelThread(void *arg) { + (void)arg; + + int16_t acceleration_x = 0; + int16_t acceleration_y = 0; + int16_t acceleration_z = 0; + + I2CDriver *i2cp; + msg_t msg; + + while (TRUE) { + /* Waiting for wake up */ + chSysLock(); + i2c_accel_tp = chThdSelf(); + chSchGoSleepS(THD_STATE_SUSPENDED); + msg = chThdSelf()->p_msg; /* Retrieving the message, optional.*/ + chSysUnlock(); + + /***************** Perform processing here. ***************************/ + i2cp = (I2CDriver *)msg; + + /* collect measured data */ + acceleration_x = lis3.rxbuf[0] + (lis3.rxbuf[1] << 8); + acceleration_y = lis3.rxbuf[2] + (lis3.rxbuf[3] << 8); + acceleration_z = lis3.rxbuf[4] + (lis3.rxbuf[5] << 8); + } + return 0; +} + + + +/* This callback raise up when transfer finished */ +static void i2c_lis3_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ + + if (i2cp->id_slave_config->restart){ // is it restart flag set to TRUE + /* reset restart flag */ + i2cp->id_slave_config->restart = FALSE; + /* now send restart and read acceleration data. + * Function i2cMasterReceive() send restart implicitly. */ + i2cMasterReceive(i2cp, i2cscfg); + } + else{ + /* If jump here than requested data have been read. + * Stop communication, release bus and wake up processing thread */ + i2cMasterStop(i2cp); + i2cReleaseBus(&I2CD1); + + // wake up heavy thread for data processing + if (i2c_accel_tp != NULL) { + i2c_accel_tp->p_msg = (msg_t)i2cp; + chSchReadyI(i2c_accel_tp); + i2c_accel_tp = NULL; + } + } +} + +/** + * Init function. Here we will also start personal serving thread. + */ +int init_lis3(void){ + + /* Starting the accelerometer serving thread.*/ + i2c_accel_tp = chThdCreateStatic(I2CAccelThreadWA, + sizeof(I2CAccelThreadWA), + HIGHPRIO, + I2CAccelThread, + NULL); + + /* wait thread statup */ + while (i2c_accel_tp == NULL) + chThdSleepMilliseconds(1); + + lis3.txbufhead = 0; + lis3.rxbufhead = 0; + + + /* Write configuration data */ + lis3.txbytes = 4; + /* fill transmit buffer. See datasheet to understand what we write */ + lis3.txbuf[0] = ACCEL_CTRL_REG1 | AUTO_INCREMENT_BIT; + lis3.txbuf[1] = 0b11100111; + lis3.txbuf[2] = 0b01000001; + lis3.txbuf[3] = 0b00000000; + + /* setting callback */ + lis3.id_callback = i2c_lis3_cb; + + i2cAcquireBus(&I2CD1); + + /* sending */ + i2cMasterTransmit(&I2CD1, &lis3); + + return 0; +} + +/** + * + */ +void request_acceleration_data(void){ + + /* fill transmit buffer with address of register that we want to read */ + lis3.txbufhead = 0; + lis3.txbuf[0] = ACCEL_OUT_DATA | AUTO_INCREMENT_BIT; // register address + lis3.txbytes = 1; + + /* tune receive structures */ + lis3.rxbufhead = 0; + lis3.rxbytes = 6; + + /* Now it is most important action. We must set restart flag to TRUE. + * And in callback function we must reset it to FALSE after sending + * of register address. In TMP75 and MAX1236 this flag does not use. */ + lis3.restart = TRUE; + + /* talk to slave what we want from it */ + i2cAcquireBus(&I2CD1); + i2cMasterTransmit(&I2CD1, &lis3); +} + diff --git a/testhal/STM32/I2C/lis3.h b/testhal/STM32/I2C/lis3.h new file mode 100644 index 000000000..e50359bde --- /dev/null +++ b/testhal/STM32/I2C/lis3.h @@ -0,0 +1,28 @@ +#include +#include "ch.h" + +#ifndef LIS3_H_ +#define LIS3_H_ + + + +/* buffers depth */ +#define ACCEL_RX_DEPTH 8 +#define ACCEL_TX_DEPTH 8 + +/* autoincrement bit position. This bit needs to perform reading of + * multiple bytes at one request */ +#define AUTO_INCREMENT_BIT (1<<7) + +/* slave specific addresses */ +#define ACCEL_STATUS_REG 0x27 +#define ACCEL_CTRL_REG1 0x20 +#define ACCEL_OUT_DATA 0x28 + + + +inline int init_lis3(void); +inline void request_acceleration_data(void); + + +#endif /* LIS3_H_ */ diff --git a/testhal/STM32/I2C/main.c b/testhal/STM32/I2C/main.c new file mode 100644 index 000000000..860e179d4 --- /dev/null +++ b/testhal/STM32/I2C/main.c @@ -0,0 +1,120 @@ +/** + * Lets imagine that we have board with LIS3LV02DL accelerometer on channel #1 + * and MAX1236 ADC, TMP75 thermometer on channel #2. + * + * NOTE: I assume, that you have datasheets on all this stuff. + * + * NOTE: Also, I assume, that you know how to I2C works. + * + * In order from simplicity to complexity: + * TMP75 + * MAX1236 + * LIS3LV02DL + * + * Project splitted to separate source files for each device. + * + * Data from sensors we will be read from different thread sleeping different + * amount of time. + */ + +#include + +#include "ch.h" +#include "hal.h" + +#include "i2c_pns.h" +#include "tmp75.h" +#include "max1236.h" +#include "lis3.h" + + + +/* Temperature polling thread */ +static WORKING_AREA(PollTmp75ThreadWA, 128); +static msg_t PollTmp75Thread(void *arg) { + (void)arg; + systime_t time = chTimeNow(); + + while (TRUE) { + time += MS2ST(1000); + /* Call reading function */ + request_temperature(); + chThdSleepUntil(time); + } + return 0; +} + +/* MAX1236 polling thread */ +static WORKING_AREA(PollMax1236ThreadWA, 128); +static msg_t PollMax1236Thread(void *arg) { + (void)arg; + systime_t time = chTimeNow(); + + while (TRUE) { + time += MS2ST(20); + /* Call reading function */ + read_max1236(); + chThdSleepUntil(time); + } + return 0; +} + + +static WORKING_AREA(PollAccelThreadWA, 128); +static msg_t PollAccelThread(void *arg) { + (void)arg; + systime_t time = chTimeNow(); + + while (TRUE) { + time += MS2ST(2); + request_acceleration_data(); + chThdSleepUntil(time); + } + return 0; +} + + + + +/* + * Entry point, note, the main() function is already a thread in the system + * on entry. + */ +int main(void) { + + halInit(); + chSysInit(); + + I2CInit_pns(); + + /* Create temperature thread */ + chThdCreateStatic(PollTmp75ThreadWA, + sizeof(PollTmp75ThreadWA), + NORMALPRIO, + PollTmp75Thread, + NULL); + + + /* Create max1236 thread */ + chThdCreateStatic(PollMax1236ThreadWA, + sizeof(PollMax1236ThreadWA), + NORMALPRIO, + PollMax1236Thread, + NULL); + + + /* Create accelerometer thread */ + chThdCreateStatic(PollAccelThreadWA, + sizeof(PollAccelThreadWA), + HIGHPRIO, + PollAccelThread, + NULL); + + + /* main loop that do nothing */ + while (TRUE) { + chThdSleepMilliseconds(500); + } + + return 0; +} diff --git a/testhal/STM32/I2C/main.h b/testhal/STM32/I2C/main.h new file mode 100644 index 000000000..1435a05e5 --- /dev/null +++ b/testhal/STM32/I2C/main.h @@ -0,0 +1,19 @@ +/* + * 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_ */ diff --git a/testhal/STM32/I2C/max1236.c b/testhal/STM32/I2C/max1236.c new file mode 100644 index 000000000..e7e253916 --- /dev/null +++ b/testhal/STM32/I2C/max1236.c @@ -0,0 +1,106 @@ +/** + * Maxim ADC has not so suitable default settings after startup. + * So we will create init function to tune this ADC. + */ + +#include + +#include "ch.h" +#include "hal.h" + +#include "max1236.h" + +// Data buffers +static i2cblock_t max1236_rx_data[MAX1236_RX_DEPTH]; +static i2cblock_t max1236_tx_data[MAX1236_TX_DEPTH]; + +/* Error trap */ +static void i2c_max1236_error_cb(I2CDriver *i2cp, 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, I2CSlaveConfig *i2cscfg){ + uint16_t ch1 = 0; + uint16_t ch2 = 0; + uint16_t ch3 = 0; + uint16_t ch4 = 0; + + /* send stop */ + i2cMasterStop(i2cp); + + /* unlock bus */ + i2cReleaseBus(&I2CD2); + + /* get ADC data */ + ch1 = ((i2cscfg->rxbuf[0] & 0xF) << 8) + i2cscfg->rxbuf[1]; + ch2 = ((i2cscfg->rxbuf[2] & 0xF) << 8) + i2cscfg->rxbuf[3]; + ch3 = ((i2cscfg->rxbuf[4] & 0xF) << 8) + i2cscfg->rxbuf[5]; + ch4 = ((i2cscfg->rxbuf[6] & 0xF) << 8) + i2cscfg->rxbuf[7]; +} + + +// ADC maxim MAX1236 config +static I2CSlaveConfig max1236 = { + NULL, // first set to NULL. We will set this pointer to the function later. + i2c_max1236_error_cb, + max1236_rx_data, + MAX1236_RX_DEPTH, + 0, + 0, + max1236_tx_data, + MAX1236_TX_DEPTH, + 0, + 0, + 0b0110100, + FALSE, +}; + + +/** + * Initilization routine. See datasheet on page 13 to understand + * how to initialize ADC. + */ +void init_max1236(void){ + /* lock bus */ + i2cAcquireBus(&I2CD2); + + /* this data we must send to IC to setup ADC settings */ + max1236.txbufhead = 0; + max1236.txbytes = 2; // total 2 bytes to be sent + max1236.txbuf[0] = 0b10000011; // config register content. Consult datasheet + max1236.txbuf[1] = 0b00000111; // config register content. Consult datasheet + + // transmit out 2 bytes + i2cMasterTransmit(&I2CD2, &max1236); + while(I2CD2.id_state != I2C_READY) // wait + chThdSleepMilliseconds(1); + + /* now add pointer to callback function */ + max1236.id_callback = i2c_max1236_cb; + + /*clear transmitting structures */ + max1236.txbytes = 0; + max1236.txbufhead = 0; + + /* unlock bus */ + i2cReleaseBus(&I2CD2); +} + + +/* Now simply read 8 bytes to get all 4 ADC channels */ +void read_max1236(void){ + /* tune receive buffer */ + max1236.rxbufhead = 0; + max1236.rxbytes = 8; + + /* lock bus */ + i2cAcquireBus(&I2CD2); + + /* start reading */ + i2cMasterReceive(&I2CD2, &max1236); +} diff --git a/testhal/STM32/I2C/max1236.h b/testhal/STM32/I2C/max1236.h new file mode 100644 index 000000000..aff466cf4 --- /dev/null +++ b/testhal/STM32/I2C/max1236.h @@ -0,0 +1,14 @@ +#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_ */ diff --git a/testhal/STM32/I2C/mcuconf.h b/testhal/STM32/I2C/mcuconf.h new file mode 100644 index 000000000..92f8e17d8 --- /dev/null +++ b/testhal/STM32/I2C/mcuconf.h @@ -0,0 +1,131 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . +*/ + +/* + * STM32 drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +/* + * HAL driver system settings. + */ +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1 +#define STM32_PLLMUL_VALUE 9 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV2 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_ADCPRE STM32_ADCPRE_DIV4 +#define STM32_MCO STM32_MCO_NOCLOCK + +/* + * ADC driver system settings. + */ +#define STM32_ADC_USE_ADC1 TRUE +#define STM32_ADC_ADC1_DMA_PRIORITY 3 +#define STM32_ADC_ADC1_IRQ_PRIORITY 5 +#define STM32_ADC_ADC1_DMA_ERROR_HOOK() chSysHalt() + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM4 TRUE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_DMA_PRIORITY 2 +#define STM32_SPI_SPI2_DMA_PRIORITY 2 +#define STM32_SPI_SPI3_DMA_PRIORITY 2 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_SPI1_DMA_ERROR_HOOK() chSysHalt() +#define STM32_SPI_SPI2_DMA_ERROR_HOOK() chSysHalt() +#define STM32_SPI_SPI3_DMA_ERROR_HOOK() chSysHalt() + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 TRUE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_USART1_DMA_ERROR_HOOK() chSysHalt() +#define STM32_UART_USART2_DMA_ERROR_HOOK() chSysHalt() +#define STM32_UART_USART3_DMA_ERROR_HOOK() chSysHalt() + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 TRUE +#define STM32_I2C_I2C1_IRQ_PRIORITY 11 +#define STM32_I2C_I2C2_IRQ_PRIORITY 11 +#define STM32_I2C_I2C1_DMA_PRIORITY 4 +#define STM32_I2C_I2C2_DMA_PRIORITY 4 +#define STM32_I2C_I2C1_DMA_ERROR_HOOK() chSysHalt() +#define STM32_I2C_I2C2_DMA_ERROR_HOOK() chSysHalt() diff --git a/testhal/STM32/I2C/tmp75.c b/testhal/STM32/I2C/tmp75.c new file mode 100644 index 000000000..4d9923881 --- /dev/null +++ b/testhal/STM32/I2C/tmp75.c @@ -0,0 +1,72 @@ +/** + * TMP75 is most simple I2C device in our case. It is already useful with + * default settings after powerup. + * You only must read 2 sequential bytes from it. + */ + +#include + +#include "ch.h" +#include "hal.h" + +#include "tmp75.h" + + +// input buffer +static i2cblock_t tmp75_rx_data[TMP75_RX_DEPTH]; +static i2cblock_t tmp75_tx_data[TMP75_TX_DEPTH]; + +// Simple error trap +static void i2c_tmp75_error_cb(I2CDriver *i2cp, 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, I2CSlaveConfig *i2cscfg){ + int16_t temperature = 0; + + /* Manually send stop signal to the bus. This is important! */ + i2cMasterStop(i2cp); + /* unlock bus */ + i2cReleaseBus(&I2CD2); + + /* store temperature value */ + temperature = (i2cscfg->rxbuf[0] << 8) + i2cscfg->rxbuf[1]; + +} + +// Fill TMP75 config. +static I2CSlaveConfig tmp75 = { + i2c_tmp75_cb, + i2c_tmp75_error_cb, + tmp75_rx_data, + TMP75_RX_DEPTH, + 0, + 0, + tmp75_tx_data, + TMP75_TX_DEPTH, + 0, + 0, + 0b1001000, + FALSE, +}; + +/* This is main function. */ +void request_temperature(void){ + tmp75.txbytes = 0; // set to zero just to be safe + + /* tune receiving buffer */ + tmp75.rxbufhead = 0;// point to beginig of buffer + tmp75.rxbytes = 2; // we need read 2 bytes + + /* get exclusive access to the bus */ + i2cAcquireBus(&I2CD2); + + /* start receiving process in background and return */ + i2cMasterReceive(&I2CD2, &tmp75); +} + + diff --git a/testhal/STM32/I2C/tmp75.h b/testhal/STM32/I2C/tmp75.h new file mode 100644 index 000000000..ab4b5fa9b --- /dev/null +++ b/testhal/STM32/I2C/tmp75.h @@ -0,0 +1,13 @@ +#ifndef TMP75_H_ +#define TMP75_H_ + + + +/* buffers depth */ +#define TMP75_RX_DEPTH 2 +#define TMP75_TX_DEPTH 2 + +void init_tmp75(void); +void request_temperature(void); + +#endif /* TMP75_H_ */ From 57fb5e703ba8ab824d1849d7436abd64684caf20 Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 2 Apr 2011 09:33:46 +0000 Subject: [PATCH 35/92] I2C. Additional locks added to avoiding system hangups. Some mistypes in comments fixed. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2865 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 4 ++-- os/hal/src/i2c.c | 9 ++++++++- testhal/STM32/I2C/main.c | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 9dc3a66bc..1ac7e4309 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -215,7 +215,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { if (i2cp->id_slave_config->id_callback != NULL) i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); - else /* No callback function set - generate stop */ + else /* No callback function set. Generate stop */ i2c_lld_master_stop(i2cp); return; @@ -497,7 +497,7 @@ void i2c_lld_master_start(I2CDriver *i2cp){ while (i2cp->id_i2c->CR1 & I2C_CR1_START); /* enable interrupts from I2C hardware. They will disable in driver state - machine after the tranafer finish.*/ + machine after the transfer finish.*/ i2cp->id_i2c->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; } diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 11d4fccfa..ad9a5d0ac 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -138,7 +138,9 @@ void i2cMasterStart(I2CDriver *i2cp){ chDbgCheck((i2cp != NULL), "i2cMasterTransmit"); + chSysLock(); i2c_lld_master_start(i2cp); + chSysUnlock(); } /** @@ -149,8 +151,9 @@ void i2cMasterStart(I2CDriver *i2cp){ void i2cMasterStop(I2CDriver *i2cp){ chDbgCheck((i2cp != NULL), "i2cMasterTransmit"); - + chSysLock(); i2c_lld_master_stop(i2cp); + chSysUnlock(); } /** @@ -168,7 +171,9 @@ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { "i2cMasterTransmit(), #1", "not active"); + chSysLock(); i2c_lld_master_transmit(i2cp, i2cscfg); + chSysUnlock(); } @@ -186,7 +191,9 @@ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { "i2cMasterReceive(), #1", "not active"); + chSysLock(); i2c_lld_master_receive(i2cp, i2cscfg); + chSysUnlock(); } diff --git a/testhal/STM32/I2C/main.c b/testhal/STM32/I2C/main.c index 860e179d4..793f73f49 100644 --- a/testhal/STM32/I2C/main.c +++ b/testhal/STM32/I2C/main.c @@ -36,7 +36,7 @@ static msg_t PollTmp75Thread(void *arg) { systime_t time = chTimeNow(); while (TRUE) { - time += MS2ST(1000); + time += MS2ST(1001); /* Call reading function */ request_temperature(); chThdSleepUntil(time); From 2459b2beb0af669675d93c57fc132c734981667c Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 4 May 2011 13:12:34 +0000 Subject: [PATCH 36/92] I2C. My driver really sucks. I'll try to use alberto driver with my improvements git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2918 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c_brts.h | 248 ++++++++++ os/hal/platforms/STM32/i2c_lld_brts.c | 626 +++++++++++++++++++++++++ os/hal/platforms/STM32/i2c_lld_btrts.h | 201 ++++++++ os/hal/src/i2c_brts.c | 64 ++- 4 files changed, 1124 insertions(+), 15 deletions(-) create mode 100644 os/hal/include/i2c_brts.h create mode 100644 os/hal/platforms/STM32/i2c_lld_brts.c create mode 100644 os/hal/platforms/STM32/i2c_lld_btrts.h diff --git a/os/hal/include/i2c_brts.h b/os/hal/include/i2c_brts.h new file mode 100644 index 000000000..a01606a18 --- /dev/null +++ b/os/hal/include/i2c_brts.h @@ -0,0 +1,248 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . +*/ + +/** + * @file i2c.h + * @brief I2C Driver macros and structures. + * + * @addtogroup I2C + * @{ + */ + +#ifndef _I2C_H_ +#define _I2C_H_ + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + I2C_UNINIT = 0, /**< Not initialized. */ + I2C_STOP = 1, /**< Stopped. */ + I2C_READY = 2, /**< Ready. Start condition generated. */ + I2C_MACTIVE = 3, /**< I2C configured and waiting start cond. */ + I2C_10BIT_HANDSHAKE = 4, /**< 10-bit address sending */ + I2C_MWAIT_ADDR_ACK = 5, /**< Waiting ACK on address sending. */ + I2C_MTRANSMIT = 6, /**< Master transmitting. */ + I2C_MRECEIVE = 7, /**< Master receiving. */ + I2C_MWAIT_TF = 8, /**< Master wait Transmission Finished */ + I2C_MERROR = 9, /**< Error condition. */ + + // slave part + I2C_SACTIVE = 10, + I2C_STRANSMIT = 11, + I2C_SRECEIVE = 12, +} i2cstate_t; + + +#include "i2c_lld.h" + +/** + * @brief I2C notification callback type. + * @details This callback invoked when byte transfer finish event occurs, + * No matter sending or reading. This function designed + * for sending (re)start or stop events to I2C bus from user level. + * + * If callback function is set to NULL - driver atomaticcaly + * generate stop condition after the transfer finish. + * + * @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, 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, 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, or + * by DMA buffer events + * 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; + + /** + * @brief Receive and transmit buffers. + */ + i2cblock_t *rxbuf; /*!< Pointer to receive buffer. */ + size_t rxdepth; /*!< Depth of buffer. */ + size_t rxbytes; /*!< Number of bytes to be receive in one transmission. */ + size_t rxbufhead; /*!< Pointer to current data byte. */ + + i2cblock_t *txbuf; /*!< Pointer to transmit buffer.*/ + size_t txdepth; /*!< Depth of buffer. */ + size_t txbytes; /*!< Number of bytes to be transmit in one transmission. */ + size_t txbufhead; /*!< Pointer to current data byte. */ + + /** + * @brief Contain slave address and some flags. + * @details Bits 0..9 contain slave address in 10-bit mode. + * + * Bits 0..6 contain slave address in 7-bit mode. + * + * Bits 10..14 are not used in 10-bit mode. + * Bits 7..14 are not used in 7-bit mode. + * + * Bit 15 is used to switch between 10-bit and 7-bit modes + * (0 denotes 7-bit mode). + */ + uint16_t address; + + /** + * @brief Boolean flag for dealing with start/stop conditions. + * @note This flag destined to use in callback functions. It place here + * for convenience and flexibility reasons, but you can use your + * own variable from user level code. + */ + bool_t restart; + + +#if I2C_USE_WAIT + /** + * @brief Thread waiting for I/O completion. + */ + Thread *thread; +#endif /* I2C_USE_WAIT */ +}; + + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Read mode. + */ +#define I2C_READ 1 + +/** + * @brief Write mode. + */ +#define I2C_WRITE 0 + +/** + * @brief Seven bits addresses header builder. + * + * @param[in] addr seven bits address value + * @param[in] rw read/write flag + * + * @return A 16 bit value representing the header, the most + * significant byte is always zero. + */ +#define I2C_ADDR7(addr, rw) (uint16_t)((addr) << 1 | (rw)) + + +/** + * @brief Ten bits addresses header builder. + * + * @param[in] addr ten bits address value + * @param[in] rw read/write flag + * + * @return A 16 bit value representing the header, the most + * significant byte is the first one to be transmitted. + */ +#define I2C_ADDR10(addr, rw) \ + (uint16_t)(0xF000 | \ + (((addr) & 0x0300) << 1) | \ + (((rw) << 8)) | \ + ((addr) & 0x00FF)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ +#ifdef __cplusplus +extern "C" { +#endif + void i2cInit(void); + void i2cObjectInit(I2CDriver *i2cp); + void i2cStart(I2CDriver *i2cp, I2CConfig *config); + void i2cStop(I2CDriver *i2cp); + void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); + void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); + void i2cMasterStart(I2CDriver *i2cp); + void i2cMasterStop(I2CDriver *i2cp); + +#if I2C_USE_MUTUAL_EXCLUSION + void i2cAcquireBus(I2CDriver *i2cp); + void i2cReleaseBus(I2CDriver *i2cp); +#endif /* I2C_USE_MUTUAL_EXCLUSION */ +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2C */ + +#endif /* _I2C_H_ */ + +/** @} */ diff --git a/os/hal/platforms/STM32/i2c_lld_brts.c b/os/hal/platforms/STM32/i2c_lld_brts.c new file mode 100644 index 000000000..1ac7e4309 --- /dev/null +++ b/os/hal/platforms/STM32/i2c_lld_brts.c @@ -0,0 +1,626 @@ +/** + * @file STM32/i2c_lld.c + * @brief STM32 I2C subsystem low level driver source. Slave mode not implemented. + * @addtogroup STM32_I2C + * @{ + */ + +#include "ch.h" +#include "hal.h" +#include "i2c_lld.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief I2C1 driver identifier.*/ +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +I2CDriver I2CD1; +#endif + +/** @brief I2C2 driver identifier.*/ +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +I2CDriver I2CD2; +#endif + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Interrupt service routine. + * @details This function handle all ERROR interrupt conditions. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +static void i2c_serve_error_interrupt(I2CDriver *i2cp) { + //TODO: more robust error handling + chSysLockFromIsr(); + i2cp->id_slave_config->id_err_callback(i2cp, i2cp->id_slave_config); + chSysUnlockFromIsr(); +} + +/* helper function, not API + * write bytes in DR register + * return TRUE if last byte written + */ +inline bool_t i2c_lld_txbyte(I2CDriver *i2cp) { +#define _txbufhead (i2cp->id_slave_config->txbufhead) +#define _txbytes (i2cp->id_slave_config->txbytes) +#define _txbuf (i2cp->id_slave_config->txbuf) + + if (_txbufhead < _txbytes){ + /* disable interrupt to avoid jumping to ISR */ + if ( _txbytes - _txbufhead == 1) + i2cp->id_i2c->CR2 &= (~I2C_CR2_ITBUFEN); + i2cp->id_i2c->DR = _txbuf[_txbufhead]; + (_txbufhead)++; + return(FALSE); + } + _txbufhead = 0; + return(TRUE); // last byte written +#undef _txbufhead +#undef _txbytes +#undef _txbuf +} + + +/* helper function, not API + * read bytes from DR register + * return TRUE if last byte read + */ +inline bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { + // temporal variables +#define _rxbuf (i2cp->id_slave_config->rxbuf) +#define _rxbufhead (i2cp->id_slave_config->rxbufhead) +#define _rxbytes (i2cp->id_slave_config->rxbytes) + + /* In order to generate the non-acknowledge pulse after the last received + * data byte, the ACK bit must be cleared just after reading the second + * last data byte (after second last RxNE event). + */ + if (_rxbufhead < (_rxbytes - 1)){ + _rxbuf[_rxbufhead] = i2cp->id_i2c->DR; + if ((_rxbytes - _rxbufhead) <= 2){ + // clear ACK bit for automatically send NACK + i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK); + } + (_rxbufhead)++; + return(FALSE); + } + /* disable interrupt to avoid jumping to ISR */ + i2cp->id_i2c->CR2 &= (~I2C_CR2_ITBUFEN); + + _rxbuf[_rxbufhead] = i2cp->id_i2c->DR; // read last byte + _rxbufhead = 0; + return(TRUE); // last byte read + +#undef _rxbuf +#undef _rxbufhead +#undef _rxbytes +} + + +/** + * @brief Interrupt service routine. + * @details This function handle all regular interrupt conditions. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +static void i2c_serve_event_interrupt(I2CDriver *i2cp) { + +#if CH_DBG_ENABLE_CHECKS + // debug variables + int i = 0; + int n = 0; + int m = 0; +#endif + + /* In 10-bit addressing mode, + – To enter Transmitter mode, a master sends the header (11110xx0) and then the + slave address, (where xx denotes the two most significant bits of the address). + – To enter Receiver mode, a master sends the header (11110xx0) and then the + slave address. Then it should send a repeated Start condition followed by the + header (11110xx1), (where xx denotes the two most significant bits of the + address). + The TRA bit indicates whether the master is in Receiver or Transmitter mode.*/ + + if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent + i2cp->id_state = I2C_MACTIVE; + + if(!(i2cp->id_slave_config->address & 0x8000)){ // slave address is 7-bit + i2cp->id_i2c->DR = ((i2cp->id_slave_config->address & 0x7F) << 1) | + i2cp->rw_bit; + i2cp->id_state = I2C_MWAIT_ADDR_ACK; + return; + } + else{ // slave address is 10-bit + i2cp->id_state = I2C_10BIT_HANDSHAKE; + // send MSB with header. LSB = 0. + i2cp->id_i2c->DR = ((i2cp->id_slave_config->address >> 7) & 0x6) | 0xF0; + return; + } + } + + // "wait" interrupt with ADD10 flag + if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADD10)){ + i2cp->id_i2c->DR = i2cp->id_slave_config->address & 0x00FF; // send remaining bits of address + if (!(i2cp->rw_bit)) + // in transmit mode there is nothing to do with 10-bit handshaking + i2cp->id_state = I2C_MWAIT_ADDR_ACK; + return; + } + + // "wait" interrupt with ADDR flag + if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address ACKed + i2cp->id_i2c->CR1 |= I2C_CR1_START; + return; + } + + if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// restart generated + // send MSB with header. LSB = 1 + i2cp->id_i2c->DR = ((i2cp->id_slave_config->address >> 7) & 0x6) | 0xF1; + i2cp->id_state = I2C_MWAIT_ADDR_ACK; + return; + } + + // "wait" interrupt with ADDR (ADD10 in 10-bit receiver mode) flag + if ((i2cp->id_state == I2C_MWAIT_ADDR_ACK) && (i2cp->id_i2c->SR1 & (I2C_SR1_ADDR | I2C_SR1_ADD10))){// address ACKed + if(i2cp->id_i2c->SR2 & I2C_SR2_TRA){// I2C is transmitting data + i2cp->id_state = I2C_MTRANSMIT; // change state + i2c_lld_txbyte(i2cp); // send first byte + return; + } + else {// I2C is receiving data + /* In order to generate the non-acknowledge pulse after the last received + * data byte, the ACK bit must be cleared just after reading the second + * last data byte (after second last RxNE event). + */ + if (i2cp->id_slave_config->rxbytes > 1) + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // set ACK bit + i2cp->id_state = I2C_MRECEIVE; // change state + return; + } + } + + // transmitting bytes one by one + if ((i2cp->id_state == I2C_MTRANSMIT) && (i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ + if (i2c_lld_txbyte(i2cp)) + i2cp->id_state = I2C_MWAIT_TF; // last byte written + return; + } + + //receiving bytes one by one + if ((i2cp->id_state == I2C_MRECEIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ + if (i2c_lld_rxbyte(i2cp)) + i2cp->id_state = I2C_MWAIT_TF; // last byte read + return; + } + + // "wait" BTF bit in status register + if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ + chSysLockFromIsr(); + i2cp->id_i2c->CR2 &= (~I2C_CR2_ITEVTEN); // disable BTF interrupt + chSysUnlockFromIsr(); + /* now driver is ready to generate (re)start/stop condition. + * Callback function is good place to do that. If not callback was + * set - driver only generate stop condition. */ + i2cp->id_state = I2C_READY; + + if (i2cp->id_slave_config->id_callback != NULL) + i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); + else /* No callback function set. Generate stop */ + i2c_lld_master_stop(i2cp); + + return; + } +#if CH_DBG_ENABLE_CHECKS + else{ // debugging trap + i = i2cp->id_i2c->SR1; + n = i2cp->id_i2c->SR2; + m = i2cp->id_i2c->CR1; + while(TRUE); + } +#endif /* CH_DBG_ENABLE_CHECKS */ +} + +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +/** + * @brief I2C1 event interrupt handler. + */ +CH_IRQ_HANDLER(VectorBC) { + + CH_IRQ_PROLOGUE(); + i2c_serve_event_interrupt(&I2CD1); + CH_IRQ_EPILOGUE(); +} + +/** + * @brief I2C1 error interrupt handler. + */ +CH_IRQ_HANDLER(VectorC0) { + + CH_IRQ_PROLOGUE(); + i2c_serve_error_interrupt(&I2CD1); + CH_IRQ_EPILOGUE(); +} +#endif + +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +/** + * @brief I2C2 event interrupt handler. + */ +CH_IRQ_HANDLER(VectorC4) { + + CH_IRQ_PROLOGUE(); + i2c_serve_event_interrupt(&I2CD2); + CH_IRQ_EPILOGUE(); +} + +/** + * @brief I2C2 error interrupt handler. + */ +CH_IRQ_HANDLER(VectorC8) { + + CH_IRQ_PROLOGUE(); + i2c_serve_error_interrupt(&I2CD2); + CH_IRQ_EPILOGUE(); +} +#endif + +/** + * @brief Low level I2C driver initialization. + */ +void i2c_lld_init(void) { + +#if STM32_I2C_USE_I2C1 + RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; // reset I2C 1 + RCC->APB1RSTR = 0; + i2cObjectInit(&I2CD1); + I2CD1.id_i2c = I2C1; +#endif + +#if STM32_I2C_USE_I2C2 + RCC->APB1RSTR = RCC_APB1RSTR_I2C2RST; // reset I2C 2 + RCC->APB1RSTR = 0; + i2cObjectInit(&I2CD2); + I2CD2.id_i2c = I2C2; +#endif +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2c_lld_start(I2CDriver *i2cp) { + + /* If in stopped state then enables the I2C clock.*/ + if (i2cp->id_state == I2C_STOP) { +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + NVICEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); + NVICEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); + RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // I2C 1 clock enable + } +#endif +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + NVICEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); + NVICEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); + RCC->APB1ENR |= RCC_APB1ENR_I2C2EN; // I2C 2 clock enable + } +#endif + } + + /* I2C setup.*/ + i2cp->id_i2c->CR1 = I2C_CR1_SWRST; // reset i2c peripherial + i2cp->id_i2c->CR1 = 0; + + i2c_lld_set_clock(i2cp); + i2c_lld_set_opmode(i2cp); + i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN | I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN;// enable interrupts + i2cp->id_i2c->CR1 |= 1; // enable interface +} + +/** + * @brief Set clock speed. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2c_lld_set_clock(I2CDriver *i2cp) { + volatile uint16_t regCCR, regCR2, freq, clock_div; + volatile uint16_t pe_bit_saved; + int32_t clock_speed = i2cp->id_config->ClockSpeed; + I2C_DutyCycle_t duty = i2cp->id_config->FastModeDutyCycle; + + chDbgCheck((i2cp != NULL) && (clock_speed > 0) && (clock_speed <= 4000000), + "i2c_lld_set_clock"); + + /*---------------------------- CR2 Configuration ------------------------*/ + /* Get the I2Cx CR2 value */ + regCR2 = i2cp->id_i2c->CR2; + + /* Clear frequency FREQ[5:0] bits */ + regCR2 &= (uint16_t)~I2C_CR2_FREQ; + /* Set frequency bits depending on pclk1 value */ + freq = (uint16_t)(STM32_PCLK1 / 1000000); + chDbgCheck((freq >= 2) && (freq <= 36), + "i2c_lld_set_clock() : Peripheral clock freq. out of range"); + regCR2 |= freq; + i2cp->id_i2c->CR2 = regCR2; + + /*---------------------------- CCR Configuration ------------------------*/ + pe_bit_saved = (i2cp->id_i2c->CR1 & I2C_CR1_PE); + /* Disable the selected I2C peripheral to configure TRISE */ + i2cp->id_i2c->CR1 &= (uint16_t)~I2C_CR1_PE; + + /* Clear F/S, DUTY and CCR[11:0] bits */ + regCCR = 0; + clock_div = I2C_CCR_CCR; + /* Configure clock_div in standard mode */ + if (clock_speed <= 100000) { + chDbgAssert(duty == stdDutyCycle, + "i2c_lld_set_clock(), #1", "Invalid standard mode duty cycle"); + /* Standard mode clock_div calculate: Tlow/Thigh = 1/1 */ + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2)); + /* Test if CCR value is under 0x4, and set the minimum allowed value */ + if (clock_div < 0x04) clock_div = 0x04; + /* Set clock_div value for standard mode */ + regCCR |= (clock_div & I2C_CCR_CCR); + /* Set Maximum Rise Time for standard mode */ + i2cp->id_i2c->TRISE = freq + 1; + } + /* Configure clock_div in fast mode */ + else if(clock_speed <= 400000) { + chDbgAssert((duty == fastDutyCycle_2) || (duty == fastDutyCycle_16_9), + "i2c_lld_set_clock(), #2", "Invalid fast mode duty cycle"); + if(duty == fastDutyCycle_2) { + /* Fast mode clock_div calculate: Tlow/Thigh = 2/1 */ + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3)); + } + else if(duty == fastDutyCycle_16_9) { + /* Fast mode clock_div calculate: Tlow/Thigh = 16/9 */ + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 25)); + /* Set DUTY bit */ + regCCR |= I2C_CCR_DUTY; + } + /* Test if CCR value is under 0x1, and set the minimum allowed value */ + if(clock_div < 0x01) clock_div = 0x01; + /* Set clock_div value and F/S bit for fast mode*/ + regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR)); + /* Set Maximum Rise Time for fast mode */ + i2cp->id_i2c->TRISE = (freq * 300 / 1000) + 1; + } + chDbgAssert((clock_div <= I2C_CCR_CCR), + "i2c_lld_set_clock(), #3", "Too low clock clock speed selected"); + + /* Write to I2Cx CCR */ + i2cp->id_i2c->CCR = regCCR; + + /* restore the I2C peripheral enabled state */ + i2cp->id_i2c->CR1 |= pe_bit_saved; +} + +/** + * @brief Set operation mode of I2C hardware. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2c_lld_set_opmode(I2CDriver *i2cp) { + I2C_opMode_t opmode = i2cp->id_config->opMode; + uint16_t regCR1; + + /*---------------------------- CR1 Configuration ------------------------*/ + /* Get the I2Cx CR1 value */ + regCR1 = i2cp->id_i2c->CR1; + switch(opmode){ + case opmodeI2C: + regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); + break; + case opmodeSMBusDevice: + regCR1 |= I2C_CR1_SMBUS; + regCR1 &= (uint16_t)~(I2C_CR1_SMBTYPE); + break; + case opmodeSMBusHost: + regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); + break; + } + /* Write to I2Cx CR1 */ + i2cp->id_i2c->CR1 = regCR1; +} + +/** + * @brief Set own address. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2c_lld_set_own_address(I2CDriver *i2cp) { + //TODO: dual address mode + + /*---------------------------- OAR1 Configuration -----------------------*/ + i2cp->id_i2c->OAR1 |= 1 << 14; + + if (&(i2cp->id_config->OwnAddress10) == NULL){// only 7-bit address + i2cp->id_i2c->OAR1 &= (~I2C_OAR1_ADDMODE); + i2cp->id_i2c->OAR1 |= i2cp->id_config->OwnAddress7 << 1; + } + else { + chDbgAssert((i2cp->id_config->OwnAddress10 < 1024), + "i2c_lld_set_own_address(), #1", "10-bit address longer then 10 bit") + i2cp->id_i2c->OAR1 |= I2C_OAR1_ADDMODE; + i2cp->id_i2c->OAR1 |= i2cp->id_config->OwnAddress10; + } +} + + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2c_lld_stop(I2CDriver *i2cp) { + + /* If in ready state then disables the I2C clock.*/ + if (i2cp->id_state == I2C_READY) { +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + NVICDisableVector(I2C1_EV_IRQn); + NVICDisableVector(I2C1_ER_IRQn); + RCC->APB1ENR &= ~RCC_APB1ENR_I2C1EN; + } +#endif +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + NVICDisableVector(I2C2_EV_IRQn); + NVICDisableVector(I2C2_ER_IRQn); + RCC->APB1ENR &= ~RCC_APB1ENR_I2C2EN; + } +#endif + } + i2cp->id_state = I2C_STOP; +} + +/** + * @brief Generate start condition. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2c_lld_master_start(I2CDriver *i2cp){ + i2cp->id_i2c->CR1 |= I2C_CR1_START; + while (i2cp->id_i2c->CR1 & I2C_CR1_START); + + /* enable interrupts from I2C hardware. They will disable in driver state + machine after the transfer finish.*/ + i2cp->id_i2c->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; +} + +/** + * @brief Generate stop condition. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2c_lld_master_stop(I2CDriver *i2cp){ + i2cp->id_i2c->CR1 |= I2C_CR1_STOP; + while (i2cp->id_i2c->CR1 & I2C_CR1_STOP); +} + +/** + * @brief Begin data transmitting. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object + */ +void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ + + i2cp->id_slave_config = i2cscfg; + i2cp->rw_bit = I2C_WRITE; + + // generate start condition. Later transmission goes in background + i2c_lld_master_start(i2cp); +} + +/** + * @brief Begin data receiving. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object + */ +void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ + + i2cp->id_slave_config = i2cscfg; + i2cp->rw_bit = I2C_READ; + + // generate (re)start condition. Later connection goes asynchronously + i2c_lld_master_start(i2cp); +} + + + +/** + * @brief Transmits data via I2C bus. + * + * @note This function does not use interrupts + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object + * @param[in] restart bool. If TRUE then generate restart condition instead of stop + */ +void i2c_lld_master_transmit_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart) { + + int i = 0; + + i2cp->id_slave_config = i2cscfg; + i2cp->rw_bit = I2C_WRITE; + + + i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate start condition + while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)); // wait Address sent + + i2cp->id_i2c->DR = (i2cp->id_slave_config->address << 1) | I2C_WRITE; // write slave addres in DR + while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)); // wait Address sent + i = i2cp->id_i2c->SR2; + i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit + + // now write data byte by byte in DR register + uint32_t n = 0; + for (n = 0; n < i2cp->id_slave_config->txbytes; n++){ + i2cp->id_i2c->DR = i2cscfg->txbuf[n]; + while (!(i2cp->id_i2c->SR1 & I2C_SR1_TXE)); + } + + while (!(i2cp->id_i2c->SR1 & I2C_SR1_BTF)); + + if (restart){ + i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate restart condition + while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)); // wait start bit + } + else i2cp->id_i2c->CR1 |= I2C_CR1_STOP; // generate stop condition +} + + +/** + * @brief Receives data from the I2C bus. + * @note This function does not use interrupts + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object + */ +void i2c_lld_master_receive_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { + + i2cp->id_slave_config = i2cscfg; + + uint16_t i = 0; + + // send slave addres with read-bit + i2cp->id_i2c->DR = (i2cp->id_slave_config->address << 1) | I2C_READ; + while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)); // wait Address sent + + i = i2cp->id_i2c->SR2; + i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit + + // set ACK bit + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; + + // collect data from slave + for (i = 0; i < i2cp->id_slave_config->rxbytes; i++){ + if ((i2cp->id_slave_config->rxbytes - i) == 1){ + // clear ACK bit for automatically send NACK + i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);} + while (!(i2cp->id_i2c->SR1 & I2C_SR1_RXNE)); + + i2cp->id_slave_config->rxbuf[i] = i2cp->id_i2c->DR; + } + // generate STOP + i2cp->id_i2c->CR1 |= I2C_CR1_STOP; +} + + + +#endif // HAL_USE_I2C diff --git a/os/hal/platforms/STM32/i2c_lld_btrts.h b/os/hal/platforms/STM32/i2c_lld_btrts.h new file mode 100644 index 000000000..76f7068e2 --- /dev/null +++ b/os/hal/platforms/STM32/i2c_lld_btrts.h @@ -0,0 +1,201 @@ +/** + * @file STM32/i2c_lld.h + * @brief STM32 I2C subsystem low level driver header. + * @addtogroup STM32_I2C + * @{ + */ + +#ifndef _I2C_LLD_H_ +#define _I2C_LLD_H_ + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @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. */ +/*===========================================================================*/ +#define I2CD_NO_ERROR 0 +/** @brief Bus Error.*/ +#define I2CD_BUS_ERROR 0x01 +/** @brief Arbitration Lost (master mode).*/ +#define I2CD_ARBITRATION_LOST 0x02 +/** @brief Acknowledge Failure.*/ +#define I2CD_ACK_FAILURE 0x04 +/** @brief Overrun/Underrun.*/ +#define I2CD_OVERRUN 0x08 +/** @brief PEC Error in reception.*/ +#define I2CD_PEC_ERROR 0x10 +/** @brief Timeout or Tlow Error.*/ +#define I2CD_TIMEOUT 0x20 +/** @brief SMBus Alert.*/ +#define I2CD_SMB_ALERT 0x40 +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +typedef enum { + opmodeI2C, + opmodeSMBusDevice, + opmodeSMBusHost, +} I2C_opMode_t; + +typedef enum { + stdDutyCycle, + fastDutyCycle_2, + fastDutyCycle_16_9, +} I2C_DutyCycle_t; + +/** + * @brief Driver configuration structure. + */ +typedef struct { + I2C_opMode_t opMode; /*!< Specifies the I2C mode.*/ + uint32_t ClockSpeed; /*!< Specifies the clock frequency. Must be set to a value lower than 400kHz */ + I2C_DutyCycle_t FastModeDutyCycle;/*!< Specifies the I2C fast mode duty cycle */ + uint8_t OwnAddress7; /*!< Specifies the first device 7-bit own address. */ + uint16_t OwnAddress10; /*!< Specifies the second part of device own address in 10-bit mode. Set to NULL if not used. */ +} 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 *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. + */ + I2CConfig *id_config; + /** + * @brief Current slave configuration data. + */ + I2CSlaveConfig *id_slave_config; + /** + * @brief RW-bit sent to slave. + */ + uint8_t rw_bit; + + /*********** End of the mandatory fields. **********************************/ + + /** + * @brief Pointer to the I2Cx registers block. + */ + I2C_TypeDef *id_i2c; +} ; + + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* 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_start(I2CDriver *i2cp); +void i2c_lld_stop(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_master_start(I2CDriver *i2cp); +void i2c_lld_master_stop(I2CDriver *i2cp); + +void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); +void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); + +void i2c_lld_master_transmit_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); +void i2c_lld_master_receive_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); + +#ifdef __cplusplus +} +#endif +/** @endcond*/ + +#endif // CH_HAL_USE_I2C + +#endif // _I2C_LLD_H_ diff --git a/os/hal/src/i2c_brts.c b/os/hal/src/i2c_brts.c index 5a0471e0f..ad9a5d0ac 100644 --- a/os/hal/src/i2c_brts.c +++ b/os/hal/src/i2c_brts.c @@ -69,6 +69,19 @@ void i2cObjectInit(I2CDriver *i2cp) { i2cp->id_state = I2C_STOP; i2cp->id_config = NULL; i2cp->id_slave_config = NULL; + +#if I2C_USE_WAIT + i2cp->id_thread = NULL; +#endif /* I2C_USE_WAIT */ + +#if I2C_USE_MUTUAL_EXCLUSION +#if CH_USE_MUTEXES + chMtxInit(&i2cp->id_mutex); +#else + chSemInit(&i2cp->id_semaphore, 1); +#endif /* CH_USE_MUTEXES */ +#endif /* I2C_USE_MUTUAL_EXCLUSION */ + #if defined(I2C_DRIVER_EXT_INIT_HOOK) I2C_DRIVER_EXT_INIT_HOOK(i2cp); #endif @@ -116,14 +129,38 @@ void i2cStop(I2CDriver *i2cp) { chSysUnlock(); } +/** + * @brief Generate (re)start on the bus. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2cMasterStart(I2CDriver *i2cp){ + + chDbgCheck((i2cp != NULL), "i2cMasterTransmit"); + + chSysLock(); + i2c_lld_master_start(i2cp); + chSysUnlock(); +} + +/** + * @brief Generate stop on the bus. + * + * @param[in] i2cp pointer to the @p I2CDriver object + */ +void i2cMasterStop(I2CDriver *i2cp){ + + chDbgCheck((i2cp != NULL), "i2cMasterTransmit"); + chSysLock(); + i2c_lld_master_stop(i2cp); + chSysUnlock(); +} + /** * @brief Sends data ever the I2C bus. * * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] slave_addr1 7-bit address of the slave - * @param[in] slave_addr1 used in 10-bit address mode - * @param[in] n number of words to send - * @param[in] txbuf the pointer to the transmit buffer + * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object * */ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { @@ -134,19 +171,17 @@ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { "i2cMasterTransmit(), #1", "not active"); - i2c_lld_master_transmitI(i2cp, i2cscfg); + chSysLock(); + i2c_lld_master_transmit(i2cp, i2cscfg); + chSysUnlock(); } /** * @brief Receives data from the I2C bus. * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] slave_addr1 7-bit address of the slave - * @param[in] slave_addr1 used in 10-bit address mode - * @param[in] n number of words to receive - * @param[out] rxbuf the pointer to the receive buffer - * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object */ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { @@ -156,14 +191,13 @@ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { "i2cMasterReceive(), #1", "not active"); - i2c_lld_master_receiveI(i2cp, i2cscfg); + chSysLock(); + i2c_lld_master_receive(i2cp, i2cscfg); + chSysUnlock(); } - - - #if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) /** * @brief Gains exclusive access to the I2C bus. From 5387a1b39fdefec625c0a285ed8fd63c9baf827f Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 4 May 2011 14:34:49 +0000 Subject: [PATCH 37/92] I2C. All is broken. Need rewrite. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2919 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 37 +- os/hal/platforms/STM32/i2c_lld.c | 563 +++++++++++++++---------------- os/hal/platforms/STM32/i2c_lld.h | 68 ++-- 3 files changed, 333 insertions(+), 335 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index a01606a18..203de769c 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -33,7 +33,24 @@ /*===========================================================================*/ /* Driver constants. */ /*===========================================================================*/ - +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ +#define I2CD_NO_ERROR 0 +/** @brief Bus Error.*/ +#define I2CD_BUS_ERROR 0x01 +/** @brief Arbitration Lost (master mode).*/ +#define I2CD_ARBITRATION_LOST 0x02 +/** @brief Acknowledge Failure.*/ +#define I2CD_ACK_FAILURE 0x04 +/** @brief Overrun/Underrun.*/ +#define I2CD_OVERRUN 0x08 +/** @brief PEC Error in reception.*/ +#define I2CD_PEC_ERROR 0x10 +/** @brief Timeout or Tlow Error.*/ +#define I2CD_TIMEOUT 0x20 +/** @brief SMBus Alert.*/ +#define I2CD_SMB_ALERT 0x40 /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ @@ -48,6 +65,9 @@ /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ +#if I2C_USE_MUTUAL_EXCLUSION && !CH_USE_MUTEXES && !CH_USE_SEMAPHORES +#error "I2C_USE_MUTUAL_EXCLUSION requires CH_USE_MUTEXES and/or CH_USE_SEMAPHORES" +#endif /*===========================================================================*/ /* Driver data structures and types. */ @@ -57,16 +77,11 @@ * @brief Driver state machine possible states. */ typedef enum { - I2C_UNINIT = 0, /**< Not initialized. */ - I2C_STOP = 1, /**< Stopped. */ - I2C_READY = 2, /**< Ready. Start condition generated. */ - I2C_MACTIVE = 3, /**< I2C configured and waiting start cond. */ - I2C_10BIT_HANDSHAKE = 4, /**< 10-bit address sending */ - I2C_MWAIT_ADDR_ACK = 5, /**< Waiting ACK on address sending. */ - I2C_MTRANSMIT = 6, /**< Master transmitting. */ - I2C_MRECEIVE = 7, /**< Master receiving. */ - I2C_MWAIT_TF = 8, /**< Master wait Transmission Finished */ - I2C_MERROR = 9, /**< Error condition. */ + I2C_UNINIT = 0, /**< @brief Not initialized. */ + I2C_STOP = 1, /**< @brief Stopped. */ + I2C_READY = 2, /**< @brief Ready. */ + I2C_ACTIVE = 3, /**< @brief In communication. */ + I2C_COMPLETE = 4, /**< @brief Asynchronous operation complete. */ // slave part I2C_SACTIVE = 10, diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 1ac7e4309..4a54632f6 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -33,203 +33,203 @@ I2CDriver I2CD2; /* Driver local functions. */ /*===========================================================================*/ -/** - * @brief Interrupt service routine. - * @details This function handle all ERROR interrupt conditions. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -static void i2c_serve_error_interrupt(I2CDriver *i2cp) { - //TODO: more robust error handling - chSysLockFromIsr(); - i2cp->id_slave_config->id_err_callback(i2cp, i2cp->id_slave_config); - chSysUnlockFromIsr(); + +static uint32_t i2c_get_event(I2CDriver *i2cp){ + uint32_t regSR1 = i2cp->i2c_register->SR1; + uint32_t regSR2 = i2cp->i2c_register->SR2; + /* return the last event value from I2C status registers */ + return (I2C_EV_MASK & (regSR1 | (regSR2 << 16))); } -/* helper function, not API - * write bytes in DR register - * return TRUE if last byte written - */ -inline bool_t i2c_lld_txbyte(I2CDriver *i2cp) { -#define _txbufhead (i2cp->id_slave_config->txbufhead) -#define _txbytes (i2cp->id_slave_config->txbytes) -#define _txbuf (i2cp->id_slave_config->txbuf) - - if (_txbufhead < _txbytes){ - /* disable interrupt to avoid jumping to ISR */ - if ( _txbytes - _txbufhead == 1) - i2cp->id_i2c->CR2 &= (~I2C_CR2_ITBUFEN); - i2cp->id_i2c->DR = _txbuf[_txbufhead]; - (_txbufhead)++; - return(FALSE); - } - _txbufhead = 0; - return(TRUE); // last byte written -#undef _txbufhead -#undef _txbytes -#undef _txbuf -} - - -/* helper function, not API - * read bytes from DR register - * return TRUE if last byte read - */ -inline bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { - // temporal variables -#define _rxbuf (i2cp->id_slave_config->rxbuf) -#define _rxbufhead (i2cp->id_slave_config->rxbufhead) -#define _rxbytes (i2cp->id_slave_config->rxbytes) - - /* In order to generate the non-acknowledge pulse after the last received - * data byte, the ACK bit must be cleared just after reading the second - * last data byte (after second last RxNE event). - */ - if (_rxbufhead < (_rxbytes - 1)){ - _rxbuf[_rxbufhead] = i2cp->id_i2c->DR; - if ((_rxbytes - _rxbufhead) <= 2){ - // clear ACK bit for automatically send NACK - i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK); - } - (_rxbufhead)++; - return(FALSE); - } - /* disable interrupt to avoid jumping to ISR */ - i2cp->id_i2c->CR2 &= (~I2C_CR2_ITBUFEN); - - _rxbuf[_rxbufhead] = i2cp->id_i2c->DR; // read last byte - _rxbufhead = 0; - return(TRUE); // last byte read - -#undef _rxbuf -#undef _rxbufhead -#undef _rxbytes -} - - -/** - * @brief Interrupt service routine. - * @details This function handle all regular interrupt conditions. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { + static __IO uint8_t *txBuffp, *rxBuffp, *datap; -#if CH_DBG_ENABLE_CHECKS - // debug variables - int i = 0; - int n = 0; - int m = 0; -#endif + I2C_TypeDef *dp = i2cp->i2c_register; - /* In 10-bit addressing mode, - – To enter Transmitter mode, a master sends the header (11110xx0) and then the - slave address, (where xx denotes the two most significant bits of the address). - – To enter Receiver mode, a master sends the header (11110xx0) and then the - slave address. Then it should send a repeated Start condition followed by the - header (11110xx1), (where xx denotes the two most significant bits of the - address). - The TRA bit indicates whether the master is in Receiver or Transmitter mode.*/ - - if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent - i2cp->id_state = I2C_MACTIVE; - - if(!(i2cp->id_slave_config->address & 0x8000)){ // slave address is 7-bit - i2cp->id_i2c->DR = ((i2cp->id_slave_config->address & 0x7F) << 1) | - i2cp->rw_bit; - i2cp->id_state = I2C_MWAIT_ADDR_ACK; - return; + switch(i2c_get_event(i2cp)) { + case I2C_EV5_MASTER_MODE_SELECT: + i2cp->flags &= ~I2C_FLG_HEADER_SENT; + dp->DR = i2cp->slave_addr1; + break; + case I2C_EV9_MASTER_ADDR_10BIT: + if(i2cp->flags & I2C_FLG_MASTER_RECEIVER) { + i2cp->slave_addr1 |= 0x01; + i2cp->flags |= I2C_FLG_HEADER_SENT; } - else{ // slave address is 10-bit - i2cp->id_state = I2C_10BIT_HANDSHAKE; - // send MSB with header. LSB = 0. - i2cp->id_i2c->DR = ((i2cp->id_slave_config->address >> 7) & 0x6) | 0xF0; - return; + dp->DR = i2cp->slave_addr2; + break; + //------------------------------------------------------------------------ + // Master Transmitter ---------------------------------------------------- + //------------------------------------------------------------------------ + case I2C_EV6_MASTER_TRA_MODE_SELECTED: + if(i2cp->flags & I2C_FLG_HEADER_SENT){ + dp->CR1 |= I2C_CR1_START; // re-send the start in 10-Bit address mode + break; } - } - - // "wait" interrupt with ADD10 flag - if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADD10)){ - i2cp->id_i2c->DR = i2cp->id_slave_config->address & 0x00FF; // send remaining bits of address - if (!(i2cp->rw_bit)) - // in transmit mode there is nothing to do with 10-bit handshaking - i2cp->id_state = I2C_MWAIT_ADDR_ACK; - return; - } - - // "wait" interrupt with ADDR flag - if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address ACKed - i2cp->id_i2c->CR1 |= I2C_CR1_START; - return; - } - - if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// restart generated - // send MSB with header. LSB = 1 - i2cp->id_i2c->DR = ((i2cp->id_slave_config->address >> 7) & 0x6) | 0xF1; - i2cp->id_state = I2C_MWAIT_ADDR_ACK; - return; - } - - // "wait" interrupt with ADDR (ADD10 in 10-bit receiver mode) flag - if ((i2cp->id_state == I2C_MWAIT_ADDR_ACK) && (i2cp->id_i2c->SR1 & (I2C_SR1_ADDR | I2C_SR1_ADD10))){// address ACKed - if(i2cp->id_i2c->SR2 & I2C_SR2_TRA){// I2C is transmitting data - i2cp->id_state = I2C_MTRANSMIT; // change state - i2c_lld_txbyte(i2cp); // send first byte - return; + //Initialize the transmit buffer pointer + txBuffp = (uint8_t*)i2cp->txbuf; + datap = txBuffp; + txBuffp++; + i2cp->remaining_bytes--; + /* If no further data to be sent, disable the I2C ITBUF in order to not have a TxE interrupt */ + if(i2cp->remaining_bytes == 0) { + dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; } - else {// I2C is receiving data - /* In order to generate the non-acknowledge pulse after the last received - * data byte, the ACK bit must be cleared just after reading the second - * last data byte (after second last RxNE event). - */ - if (i2cp->id_slave_config->rxbytes > 1) - i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // set ACK bit - i2cp->id_state = I2C_MRECEIVE; // change state - return; + //EV8_1 write the first data + dp->DR = *datap; + break; + case I2C_EV8_MASTER_BYTE_TRANSMITTING: + if(i2cp->remaining_bytes > 0) { + datap = txBuffp; + txBuffp++; + i2cp->remaining_bytes--; + if(i2cp->remaining_bytes == 0) { + /* If no further data to be sent, disable the ITBUF in order to not have a TxE interrupt */ + dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + } + dp->DR = *datap; } - } - - // transmitting bytes one by one - if ((i2cp->id_state == I2C_MTRANSMIT) && (i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ - if (i2c_lld_txbyte(i2cp)) - i2cp->id_state = I2C_MWAIT_TF; // last byte written - return; - } - - //receiving bytes one by one - if ((i2cp->id_state == I2C_MRECEIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ - if (i2c_lld_rxbyte(i2cp)) - i2cp->id_state = I2C_MWAIT_TF; // last byte read - return; - } - - // "wait" BTF bit in status register - if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ + break; + case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: + dp->CR1 |= I2C_CR1_STOP; // stop generation + /* Disable ITEVT In order to not have again a BTF IT */ + dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; + /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ + _i2c_isr_code(i2cp); + break; + //------------------------------------------------------------------------ + // Master Receiver ------------------------------------------------------- + //------------------------------------------------------------------------ + case I2C_EV6_MASTER_REC_MODE_SELECTED: chSysLockFromIsr(); - i2cp->id_i2c->CR2 &= (~I2C_CR2_ITEVTEN); // disable BTF interrupt + switch(i2cp->flags & EV6_SUBEV_MASK) { + case I2C_EV6_3_MASTER_REC_1BTR_MODE_SELECTED: // only an single byte to receive + /* Clear ACK */ + dp->CR1 &= (uint16_t)~I2C_CR1_ACK; + /* Program the STOP */ + dp->CR1 |= I2C_CR1_STOP; + break; + case I2C_EV6_1_MASTER_REC_2BTR_MODE_SELECTED: // only two bytes to receive + /* Clear ACK */ + dp->CR1 &= (uint16_t)~I2C_CR1_ACK; + /* Disable the ITBUF in order to have only the BTF interrupt */ + dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + break; + } chSysUnlockFromIsr(); - /* now driver is ready to generate (re)start/stop condition. - * Callback function is good place to do that. If not callback was - * set - driver only generate stop condition. */ - i2cp->id_state = I2C_READY; - - if (i2cp->id_slave_config->id_callback != NULL) - i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); - else /* No callback function set. Generate stop */ - i2c_lld_master_stop(i2cp); - - return; + /* Initialize receive buffer pointer */ + rxBuffp = i2cp->rxbuf; + break; + case I2C_EV7_MASTER_REC_BYTE_RECEIVED: + if(i2cp->remaining_bytes != 3) { + /* Read the data register */ + *rxBuffp = dp->DR; + rxBuffp++; + i2cp->remaining_bytes--; + switch(i2cp->remaining_bytes){ + case 3: + /* Disable the ITBUF in order to have only the BTF interrupt */ + dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + i2cp->flags |= I2C_FLG_3BTR; + break; + case 0: + /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ + _i2c_isr_code(i2cp); + break; + } + } + // when remaining 3 bytes do nothing, wait until RXNE and BTF are set (until 2 bytes are received) + break; + case I2C_EV7_MASTER_REC_BYTE_QUEUED: + switch(i2cp->flags & EV7_SUBEV_MASK) { + case I2C_EV7_2_MASTER_REC_3BYTES_TO_PROCESS: + // DataN-2 and DataN-1 are received + chSysLockFromIsr(); + dp->CR2 |= I2C_CR2_ITBUFEN; + /* Clear ACK */ + dp->CR1 &= (uint16_t)~I2C_CR1_ACK; + /* Read the DataN-2*/ + *rxBuffp = dp->DR; //This clear the RXE & BFT flags and launch the DataN reception in the shift register (ending the SCL stretch) + rxBuffp++; + /* Program the STOP */ + dp->CR1 |= I2C_CR1_STOP; + /* Read the DataN-1 */ + *rxBuffp = dp->DR; + chSysUnlockFromIsr(); + rxBuffp++; + /* Decrement the number of readed bytes */ + i2cp->remaining_bytes -= 2; + i2cp->flags = 0; + // ready for read DataN on the next EV7 + break; + case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: // only for case of two bytes to be received + // DataN-1 and DataN are received + chSysLockFromIsr(); + /* Program the STOP */ + dp->CR1 |= I2C_CR1_STOP; + /* Read the DataN-1*/ + *rxBuffp = dp->DR; + chSysUnlockFromIsr(); + rxBuffp++; + /* Read the DataN*/ + *rxBuffp = dp->DR; + i2cp->remaining_bytes = 0; + i2cp->flags = 0; + /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ + _i2c_isr_code(i2cp); + break; + } + break; } -#if CH_DBG_ENABLE_CHECKS - else{ // debugging trap - i = i2cp->id_i2c->SR1; - n = i2cp->id_i2c->SR2; - m = i2cp->id_i2c->CR1; - while(TRUE); - } -#endif /* CH_DBG_ENABLE_CHECKS */ } +static void i2c_serve_error_interrupt(I2CDriver *i2cp) { + i2cflags_t flags; + I2C_TypeDef *reg; + + reg = i2cp->i2c_register; + flags = I2CD_NO_ERROR; + + if(reg->SR1 & I2C_SR1_BERR) { // Bus error + reg->SR1 &= ~I2C_SR1_BERR; + flags |= I2CD_BUS_ERROR; + } + if(reg->SR1 & I2C_SR1_ARLO) { // Arbitration lost + reg->SR1 &= ~I2C_SR1_ARLO; + flags |= I2CD_ARBITRATION_LOST; + } + if(reg->SR1 & I2C_SR1_AF) { // Acknowledge fail + reg->SR1 &= ~I2C_SR1_AF; + reg->CR1 |= I2C_CR1_STOP; // setting stop bit + flags |= I2CD_ACK_FAILURE; + } + if(reg->SR1 & I2C_SR1_OVR) { // Overrun + reg->SR1 &= ~I2C_SR1_OVR; + flags |= I2CD_OVERRUN; + } + if(reg->SR1 & I2C_SR1_PECERR) { // PEC error + reg->SR1 &= ~I2C_SR1_PECERR; + flags |= I2CD_PEC_ERROR; + } + if(reg->SR1 & I2C_SR1_TIMEOUT) { // SMBus Timeout + reg->SR1 &= ~I2C_SR1_TIMEOUT; + flags |= I2CD_TIMEOUT; + } + if(reg->SR1 & I2C_SR1_SMBALERT) { // SMBus alert + reg->SR1 &= ~I2C_SR1_SMBALERT; + flags |= I2CD_SMB_ALERT; + } + + if(flags != I2CD_NO_ERROR) { + // send communication end signal + _i2c_isr_code(i2cp); + chSysLockFromIsr(); + i2cAddFlagsI(i2cp, flags); + chSysUnlockFromIsr(); + } +} + + #if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) /** * @brief I2C1 event interrupt handler. @@ -329,6 +329,15 @@ void i2c_lld_start(I2CDriver *i2cp) { i2cp->id_i2c->CR1 |= 1; // enable interface } +void i2c_lld_reset(I2CDriver *i2cp){ + chDbgCheck((i2cp->state == I2C_STOP)||(i2cp->state == I2C_READY), + "i2c_lld_reset: invalid state"); + + RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; // reset I2C 1 + RCC->APB1RSTR = 0; +} + + /** * @brief Set clock speed. * @@ -488,137 +497,97 @@ void i2c_lld_stop(I2CDriver *i2cp) { } /** - * @brief Generate start condition. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2c_lld_master_start(I2CDriver *i2cp){ - i2cp->id_i2c->CR1 |= I2C_CR1_START; - while (i2cp->id_i2c->CR1 & I2C_CR1_START); - - /* enable interrupts from I2C hardware. They will disable in driver state - machine after the transfer finish.*/ - i2cp->id_i2c->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; -} - -/** - * @brief Generate stop condition. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2c_lld_master_stop(I2CDriver *i2cp){ - i2cp->id_i2c->CR1 |= I2C_CR1_STOP; - while (i2cp->id_i2c->CR1 & I2C_CR1_STOP); -} - -/** - * @brief Begin data transmitting. + * @brief Transmits data ever the I2C bus as master. * * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object - */ -void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ - - i2cp->id_slave_config = i2cscfg; - i2cp->rw_bit = I2C_WRITE; - - // generate start condition. Later transmission goes in background - i2c_lld_master_start(i2cp); -} - -/** - * @brief Begin data receiving. + * @param[in] n number of words to send + * @param[in] slave_addr1 the 7-bit address of the slave (should be aligned to left) + * @param[in] slave_addr2 used in 10 bit address mode + * @param[in] txbuf the pointer to the transmit buffer * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object */ -void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ +void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *txbuf) { - i2cp->id_slave_config = i2cscfg; - i2cp->rw_bit = I2C_READ; + // enable ERR, EVT & BUF ITs + i2cp->i2c_register->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + i2cp->i2c_register->CR1 &= ~I2C_CR1_POS; - // generate (re)start condition. Later connection goes asynchronously - i2c_lld_master_start(i2cp); -} - - - -/** - * @brief Transmits data via I2C bus. - * - * @note This function does not use interrupts - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object - * @param[in] restart bool. If TRUE then generate restart condition instead of stop - */ -void i2c_lld_master_transmit_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart) { - - int i = 0; - - i2cp->id_slave_config = i2cscfg; - i2cp->rw_bit = I2C_WRITE; - - - i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate start condition - while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)); // wait Address sent - - i2cp->id_i2c->DR = (i2cp->id_slave_config->address << 1) | I2C_WRITE; // write slave addres in DR - while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)); // wait Address sent - i = i2cp->id_i2c->SR2; - i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit - - // now write data byte by byte in DR register - uint32_t n = 0; - for (n = 0; n < i2cp->id_slave_config->txbytes; n++){ - i2cp->id_i2c->DR = i2cscfg->txbuf[n]; - while (!(i2cp->id_i2c->SR1 & I2C_SR1_TXE)); + switch(i2cp->nbit_address){ + case 7: + i2cp->slave_addr1 = ((slave_addr <<1) & 0x00FE); // LSB = 0 -> write + break; + case 10: + i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); // add the two msb of 10-bit address to the header + i2cp->slave_addr1 |= 0xF0; // add the header bits with LSB = 0 -> write + i2cp->slave_addr2 = slave_addr & 0x00FF; // the remaining 8 bit of 10-bit address + break; } - while (!(i2cp->id_i2c->SR1 & I2C_SR1_BTF)); + i2cp->txbuf = txbuf; + i2cp->remaining_bytes = n; + i2cp->flags = 0; + i2cp->errors = 0; - if (restart){ - i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate restart condition - while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)); // wait start bit - } - else i2cp->id_i2c->CR1 |= I2C_CR1_STOP; // generate stop condition + i2cp->i2c_register->CR1 |= I2C_CR1_START; // send start bit + +#if !I2C_USE_WAIT + /* Wait until the START condition is generated on the bus: the START bit is cleared by hardware */ + uint32_t tmo = 0xfffff; + while((i2cp->i2c_register->CR1 & I2C_CR1_START) && tmo--) + ; +#endif /* I2C_USE_WAIT */ } - /** - * @brief Receives data from the I2C bus. - * @note This function does not use interrupts + * @brief Receives data from the I2C bus. * * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object + * @param[in] slave_addr1 7-bit address of he slave + * @param[in] slave_addr2 used in 10-bit address mode + * @param[in] n number of words to receive + * @param[out] rxbuf the pointer to the receive buffer + * */ -void i2c_lld_master_receive_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { +void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *rxbuf) { + // enable ERR, EVT & BUF ITs + i2cp->i2c_register->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + i2cp->i2c_register->CR1 |= I2C_CR1_ACK; // acknowledge returned + i2cp->i2c_register->CR1 &= ~I2C_CR1_POS; - i2cp->id_slave_config = i2cscfg; - - uint16_t i = 0; - - // send slave addres with read-bit - i2cp->id_i2c->DR = (i2cp->id_slave_config->address << 1) | I2C_READ; - while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)); // wait Address sent - - i = i2cp->id_i2c->SR2; - i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit - - // set ACK bit - i2cp->id_i2c->CR1 |= I2C_CR1_ACK; - - // collect data from slave - for (i = 0; i < i2cp->id_slave_config->rxbytes; i++){ - if ((i2cp->id_slave_config->rxbytes - i) == 1){ - // clear ACK bit for automatically send NACK - i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);} - while (!(i2cp->id_i2c->SR1 & I2C_SR1_RXNE)); - - i2cp->id_slave_config->rxbuf[i] = i2cp->id_i2c->DR; + switch(i2cp->nbit_address){ + case 7: + i2cp->slave_addr1 = ((slave_addr <<1) | 0x01); // LSB = 1 -> receive + break; + case 10: + i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); // add the two msb of 10-bit address to the header + i2cp->slave_addr1 |= 0xF0; // add the header bits (the LSB -> 1 will be add to second + i2cp->slave_addr2 = slave_addr & 0x00FF; // the remaining 8 bit of 10-bit address + break; } - // generate STOP - i2cp->id_i2c->CR1 |= I2C_CR1_STOP; + + i2cp->rxbuf = rxbuf; + i2cp->remaining_bytes = n; + i2cp->flags = I2C_FLG_MASTER_RECEIVER; + i2cp->errors = 0; + + // Only one byte to be received + if(i2cp->remaining_bytes == 1) { + i2cp->flags |= I2C_FLG_1BTR; + } + // Only two bytes to be received + else if(i2cp->remaining_bytes == 2) { + i2cp->flags |= I2C_FLG_2BTR; + i2cp->i2c_register->CR1 |= I2C_CR1_POS; // Acknowledge Position + } + + i2cp->i2c_register->CR1 |= I2C_CR1_START; // send start bit + +#if !I2C_USE_WAIT + /* Wait until the START condition is generated on the bus: the START bit is cleared by hardware */ + uint32_t tmo = 0xfffff; + while((i2cp->i2c_register->CR1 & I2C_CR1_START) && tmo--) + ; +#endif /* I2C_USE_WAIT */ } diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 76f7068e2..2c926b1dd 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -55,25 +55,45 @@ /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ -#define I2CD_NO_ERROR 0 -/** @brief Bus Error.*/ -#define I2CD_BUS_ERROR 0x01 -/** @brief Arbitration Lost (master mode).*/ -#define I2CD_ARBITRATION_LOST 0x02 -/** @brief Acknowledge Failure.*/ -#define I2CD_ACK_FAILURE 0x04 -/** @brief Overrun/Underrun.*/ -#define I2CD_OVERRUN 0x08 -/** @brief PEC Error in reception.*/ -#define I2CD_PEC_ERROR 0x10 -/** @brief Timeout or Tlow Error.*/ -#define I2CD_TIMEOUT 0x20 -/** @brief SMBus Alert.*/ -#define I2CD_SMB_ALERT 0x40 + +/** @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 + +#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 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 Serial Driver condition flags type. + */ +typedef uint32_t i2cflags_t; + typedef enum { opmodeI2C, opmodeSMBusDevice, @@ -176,20 +196,14 @@ extern "C" { #endif void i2c_lld_init(void); +void i2c_lld_reset(I2CDriver *i2cp); +void i2c_lld_set_clock(I2CDriver *i2cp, int32_t clock_speed, I2C_DutyCycle_t duty); +void i2c_lld_set_opmode(I2CDriver *i2cp, I2C_opMode_t opmode); +void i2c_lld_set_own_address(I2CDriver *i2cp, int16_t address, int8_t nr_bit); void i2c_lld_start(I2CDriver *i2cp); void i2c_lld_stop(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_master_start(I2CDriver *i2cp); -void i2c_lld_master_stop(I2CDriver *i2cp); - -void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); -void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); - -void i2c_lld_master_transmit_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); -void i2c_lld_master_receive_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); +void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *txbuf); +void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *rxbuf); #ifdef __cplusplus } From 4fda4dc84fcfcfa483f10a8b5043d124ad551ba0 Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 5 May 2011 17:43:54 +0000 Subject: [PATCH 38/92] I2C. Code compiles successfully, but totally not tested. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2921 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 129 ++++++++++++----------- os/hal/platforms/STM32/i2c_lld.c | 136 ++++++++++++------------- os/hal/platforms/STM32/i2c_lld.h | 17 +++- os/hal/src/i2c.c | 170 +++++++++++++++++++++---------- 4 files changed, 260 insertions(+), 192 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 203de769c..39ba313fd 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -150,45 +150,16 @@ struct I2CSlaveConfig{ /** * @brief Receive and transmit buffers. */ - i2cblock_t *rxbuf; /*!< Pointer to receive buffer. */ - size_t rxdepth; /*!< Depth of buffer. */ - size_t rxbytes; /*!< Number of bytes to be receive in one transmission. */ - size_t rxbufhead; /*!< Pointer to current data byte. */ - - i2cblock_t *txbuf; /*!< Pointer to transmit buffer.*/ - size_t txdepth; /*!< Depth of buffer. */ - size_t txbytes; /*!< Number of bytes to be transmit in one transmission. */ - size_t txbufhead; /*!< Pointer to current data byte. */ - - /** - * @brief Contain slave address and some flags. - * @details Bits 0..9 contain slave address in 10-bit mode. - * - * Bits 0..6 contain slave address in 7-bit mode. - * - * Bits 10..14 are not used in 10-bit mode. - * Bits 7..14 are not used in 7-bit mode. - * - * Bit 15 is used to switch between 10-bit and 7-bit modes - * (0 denotes 7-bit mode). - */ - uint16_t address; - - /** - * @brief Boolean flag for dealing with start/stop conditions. - * @note This flag destined to use in callback functions. It place here - * for convenience and flexibility reasons, but you can use your - * own variable from user level code. - */ - bool_t restart; - - -#if I2C_USE_WAIT - /** - * @brief Thread waiting for I/O completion. - */ - Thread *thread; -#endif /* I2C_USE_WAIT */ + size_t tx_remaining_bytes; + size_t rx_remaining_bytes; + i2cblock_t *rxbuf;/*!< Pointer to receive buffer. */ + i2cblock_t *txbuf;/*!< Pointer to transmit buffer.*/ + uint16_t slave_addr; + uint8_t nbit_address; + i2cflags_t errors; + i2cflags_t flags; + /* Status Change @p EventSource.*/ + EventSource sevent; }; @@ -196,42 +167,69 @@ struct I2CSlaveConfig{ /* Driver macros. */ /*===========================================================================*/ +#if I2C_USE_WAIT || defined(__DOXYGEN__) /** - * @brief Read mode. + * @brief Waits for operation completion. + * @details This function waits for the driver to complete the current + * operation. + * @pre An operation must be running while the function is invoked. + * @note No more than one thread can wait on a I2C driver using + * this function. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi */ -#define I2C_READ 1 +#define _i2c_wait_s(i2cp) { \ + chDbgAssert((i2cp)->thread == NULL, \ + "_i2c_wait(), #1", "already waiting"); \ + (i2cp)->thread = chThdSelf(); \ + chSchGoSleepS(THD_STATE_SUSPENDED); \ +} /** - * @brief Write mode. + * @brief Wakes up the waiting thread. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi */ -#define I2C_WRITE 0 +#define _i2c_wakeup_isr(i2cp) { \ + if ((i2cp)->thread != NULL) { \ + Thread *tp = (i2cp)->thread; \ + (i2cp)->thread = NULL; \ + chSysLockFromIsr(); \ + chSchReadyI(tp); \ + chSysUnlockFromIsr(); \ + } \ +} +#else /* !I2C_USE_WAIT */ +#define i2c_lld_wait_bus_free(i2cp) //TODO: remove this STUB +#define _i2c_wait_s(i2cp) +#define _i2c_wakeup_isr(i2cp) +#endif /* !I2C_USE_WAIT */ /** - * @brief Seven bits addresses header builder. + * @brief Common ISR code. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * - Waiting thread wakeup, if any. + * - Driver state transitions. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. * - * @param[in] addr seven bits address value - * @param[in] rw read/write flag + * @param[in] i2cp pointer to the @p I2CDriver object * - * @return A 16 bit value representing the header, the most - * significant byte is always zero. + * @notapi */ -#define I2C_ADDR7(addr, rw) (uint16_t)((addr) << 1 | (rw)) - - -/** - * @brief Ten bits addresses header builder. - * - * @param[in] addr ten bits address value - * @param[in] rw read/write flag - * - * @return A 16 bit value representing the header, the most - * significant byte is the first one to be transmitted. - */ -#define I2C_ADDR10(addr, rw) \ - (uint16_t)(0xF000 | \ - (((addr) & 0x0300) << 1) | \ - (((rw) << 8)) | \ - ((addr) & 0x00FF)) +#define _i2c_isr_code(i2cp, i2cscfg) { \ + (i2cp)->id_state = I2C_COMPLETE; \ + if(((i2cp)->id_slave_config)->id_callback) { \ + ((i2cp)->id_slave_config)->id_callback(i2cp, i2cscfg); \ + } \ + _i2c_wakeup_isr(i2cp); \ +} /*===========================================================================*/ /* External declarations. */ @@ -247,6 +245,7 @@ extern "C" { void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); void i2cMasterStart(I2CDriver *i2cp); void i2cMasterStop(I2CDriver *i2cp); + void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask); #if I2C_USE_MUTUAL_EXCLUSION void i2cAcquireBus(I2CDriver *i2cp); diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 4a54632f6..6384300f7 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -35,8 +35,8 @@ I2CDriver I2CD2; static uint32_t i2c_get_event(I2CDriver *i2cp){ - uint32_t regSR1 = i2cp->i2c_register->SR1; - uint32_t regSR2 = i2cp->i2c_register->SR2; + uint32_t regSR1 = i2cp->id_i2c->SR1; + uint32_t regSR2 = i2cp->id_i2c->SR2; /* return the last event value from I2C status registers */ return (I2C_EV_MASK & (regSR1 | (regSR2 << 16))); } @@ -44,46 +44,49 @@ static uint32_t i2c_get_event(I2CDriver *i2cp){ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { static __IO uint8_t *txBuffp, *rxBuffp, *datap; - I2C_TypeDef *dp = i2cp->i2c_register; + I2C_TypeDef *dp = i2cp->id_i2c; switch(i2c_get_event(i2cp)) { case I2C_EV5_MASTER_MODE_SELECT: - i2cp->flags &= ~I2C_FLG_HEADER_SENT; + i2cp->id_slave_config->flags &= ~I2C_FLG_HEADER_SENT; dp->DR = i2cp->slave_addr1; break; case I2C_EV9_MASTER_ADDR_10BIT: - if(i2cp->flags & I2C_FLG_MASTER_RECEIVER) { + if(i2cp->id_slave_config->flags & I2C_FLG_MASTER_RECEIVER) { i2cp->slave_addr1 |= 0x01; - i2cp->flags |= I2C_FLG_HEADER_SENT; + i2cp->id_slave_config->flags |= I2C_FLG_HEADER_SENT; +// i2cp->id_i2c->CR1 = (i2cp->id_i2c->CR1 & (~I2C_CR1_ACK)) | I2C_CR1_STOP; } dp->DR = i2cp->slave_addr2; break; + + //------------------------------------------------------------------------ // Master Transmitter ---------------------------------------------------- //------------------------------------------------------------------------ case I2C_EV6_MASTER_TRA_MODE_SELECTED: - if(i2cp->flags & I2C_FLG_HEADER_SENT){ + if(i2cp->id_slave_config->flags & I2C_FLG_HEADER_SENT){ dp->CR1 |= I2C_CR1_START; // re-send the start in 10-Bit address mode break; } //Initialize the transmit buffer pointer - txBuffp = (uint8_t*)i2cp->txbuf; + txBuffp = (uint8_t*)i2cp->id_slave_config->txbuf; datap = txBuffp; txBuffp++; - i2cp->remaining_bytes--; + i2cp->id_slave_config->tx_remaining_bytes--; /* If no further data to be sent, disable the I2C ITBUF in order to not have a TxE interrupt */ - if(i2cp->remaining_bytes == 0) { + if(i2cp->id_slave_config->tx_remaining_bytes == 0) { dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; } //EV8_1 write the first data dp->DR = *datap; break; case I2C_EV8_MASTER_BYTE_TRANSMITTING: - if(i2cp->remaining_bytes > 0) { + if(i2cp->id_slave_config->tx_remaining_bytes > 0) { datap = txBuffp; txBuffp++; - i2cp->remaining_bytes--; - if(i2cp->remaining_bytes == 0) { + i2cp->id_slave_config->tx_remaining_bytes--; + if(i2cp->id_slave_config->tx_remaining_bytes == 0) { /* If no further data to be sent, disable the ITBUF in order to not have a TxE interrupt */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; } @@ -95,14 +98,16 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { /* Disable ITEVT In order to not have again a BTF IT */ dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ - _i2c_isr_code(i2cp); + _i2c_isr_code(i2cp, i2cp->id_slave_config); break; + + //------------------------------------------------------------------------ // Master Receiver ------------------------------------------------------- //------------------------------------------------------------------------ case I2C_EV6_MASTER_REC_MODE_SELECTED: chSysLockFromIsr(); - switch(i2cp->flags & EV6_SUBEV_MASK) { + switch(i2cp->id_slave_config->flags & EV6_SUBEV_MASK) { case I2C_EV6_3_MASTER_REC_1BTR_MODE_SELECTED: // only an single byte to receive /* Clear ACK */ dp->CR1 &= (uint16_t)~I2C_CR1_ACK; @@ -118,30 +123,30 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { } chSysUnlockFromIsr(); /* Initialize receive buffer pointer */ - rxBuffp = i2cp->rxbuf; + rxBuffp = i2cp->id_slave_config->rxbuf; break; case I2C_EV7_MASTER_REC_BYTE_RECEIVED: - if(i2cp->remaining_bytes != 3) { + if(i2cp->id_slave_config->rx_remaining_bytes != 3) { /* Read the data register */ *rxBuffp = dp->DR; rxBuffp++; - i2cp->remaining_bytes--; - switch(i2cp->remaining_bytes){ + i2cp->id_slave_config->rx_remaining_bytes--; + switch(i2cp->id_slave_config->rx_remaining_bytes){ case 3: /* Disable the ITBUF in order to have only the BTF interrupt */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - i2cp->flags |= I2C_FLG_3BTR; + i2cp->id_slave_config->flags |= I2C_FLG_3BTR; break; case 0: /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ - _i2c_isr_code(i2cp); + _i2c_isr_code(i2cp, i2cp->id_slave_config); break; } } // when remaining 3 bytes do nothing, wait until RXNE and BTF are set (until 2 bytes are received) break; case I2C_EV7_MASTER_REC_BYTE_QUEUED: - switch(i2cp->flags & EV7_SUBEV_MASK) { + switch(i2cp->id_slave_config->flags & EV7_SUBEV_MASK) { case I2C_EV7_2_MASTER_REC_3BYTES_TO_PROCESS: // DataN-2 and DataN-1 are received chSysLockFromIsr(); @@ -158,8 +163,8 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { chSysUnlockFromIsr(); rxBuffp++; /* Decrement the number of readed bytes */ - i2cp->remaining_bytes -= 2; - i2cp->flags = 0; + i2cp->id_slave_config->rx_remaining_bytes -= 2; + i2cp->id_slave_config->flags = 0; // ready for read DataN on the next EV7 break; case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: // only for case of two bytes to be received @@ -173,10 +178,10 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { rxBuffp++; /* Read the DataN*/ *rxBuffp = dp->DR; - i2cp->remaining_bytes = 0; - i2cp->flags = 0; + i2cp->id_slave_config->rx_remaining_bytes = 0; + i2cp->id_slave_config->flags = 0; /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ - _i2c_isr_code(i2cp); + _i2c_isr_code(i2cp, i2cp->id_slave_config); break; } break; @@ -187,7 +192,7 @@ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { i2cflags_t flags; I2C_TypeDef *reg; - reg = i2cp->i2c_register; + reg = i2cp->id_i2c; flags = I2CD_NO_ERROR; if(reg->SR1 & I2C_SR1_BERR) { // Bus error @@ -222,7 +227,7 @@ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { if(flags != I2CD_NO_ERROR) { // send communication end signal - _i2c_isr_code(i2cp); + _i2c_isr_code(i2cp, i2cp->id_slave_config); chSysLockFromIsr(); i2cAddFlagsI(i2cp, flags); chSysUnlockFromIsr(); @@ -330,7 +335,7 @@ void i2c_lld_start(I2CDriver *i2cp) { } void i2c_lld_reset(I2CDriver *i2cp){ - chDbgCheck((i2cp->state == I2C_STOP)||(i2cp->state == I2C_READY), + chDbgCheck((i2cp->id_state == I2C_STOP)||(i2cp->id_state == I2C_READY), "i2c_lld_reset: invalid state"); RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; // reset I2C 1 @@ -500,92 +505,81 @@ void i2c_lld_stop(I2CDriver *i2cp) { * @brief Transmits data ever the I2C bus as master. * * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] n number of words to send - * @param[in] slave_addr1 the 7-bit address of the slave (should be aligned to left) - * @param[in] slave_addr2 used in 10 bit address mode - * @param[in] txbuf the pointer to the transmit buffer * */ -void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *txbuf) { +void i2c_lld_master_transmit(I2CDriver *i2cp) { // enable ERR, EVT & BUF ITs - i2cp->i2c_register->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); - i2cp->i2c_register->CR1 &= ~I2C_CR1_POS; + i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - switch(i2cp->nbit_address){ + switch(i2cp->id_slave_config->nbit_address){ case 7: - i2cp->slave_addr1 = ((slave_addr <<1) & 0x00FE); // LSB = 0 -> write + i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) & 0x00FE); // LSB = 0 -> write break; case 10: - i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); // add the two msb of 10-bit address to the header + i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr >>7) & 0x0006); // add the two msb of 10-bit address to the header i2cp->slave_addr1 |= 0xF0; // add the header bits with LSB = 0 -> write - i2cp->slave_addr2 = slave_addr & 0x00FF; // the remaining 8 bit of 10-bit address + i2cp->slave_addr2 = i2cp->id_slave_config->slave_addr & 0x00FF; // the remaining 8 bit of 10-bit address break; } - i2cp->txbuf = txbuf; - i2cp->remaining_bytes = n; - i2cp->flags = 0; - i2cp->errors = 0; + i2cp->id_slave_config->flags = 0; + i2cp->id_slave_config->errors = 0; - i2cp->i2c_register->CR1 |= I2C_CR1_START; // send start bit + i2cp->id_i2c->CR1 |= I2C_CR1_START; // send start bit #if !I2C_USE_WAIT /* Wait until the START condition is generated on the bus: the START bit is cleared by hardware */ - uint32_t tmo = 0xfffff; - while((i2cp->i2c_register->CR1 & I2C_CR1_START) && tmo--) + uint32_t timeout = 0xfffff; + while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) ; #endif /* I2C_USE_WAIT */ } + /** * @brief Receives data from the I2C bus. * * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] slave_addr1 7-bit address of he slave - * @param[in] slave_addr2 used in 10-bit address mode - * @param[in] n number of words to receive - * @param[out] rxbuf the pointer to the receive buffer * */ -void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *rxbuf) { +void i2c_lld_master_receive(I2CDriver *i2cp){ // enable ERR, EVT & BUF ITs - i2cp->i2c_register->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); - i2cp->i2c_register->CR1 |= I2C_CR1_ACK; // acknowledge returned - i2cp->i2c_register->CR1 &= ~I2C_CR1_POS; + i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // acknowledge returned + i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; switch(i2cp->nbit_address){ case 7: - i2cp->slave_addr1 = ((slave_addr <<1) | 0x01); // LSB = 1 -> receive + i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) | 0x01); // LSB = 1 -> receive break; case 10: - i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); // add the two msb of 10-bit address to the header + i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr >>7) & 0x0006); // add the two msb of 10-bit address to the header i2cp->slave_addr1 |= 0xF0; // add the header bits (the LSB -> 1 will be add to second - i2cp->slave_addr2 = slave_addr & 0x00FF; // the remaining 8 bit of 10-bit address + i2cp->slave_addr2 = i2cp->id_slave_config->slave_addr & 0x00FF; // the remaining 8 bit of 10-bit address break; } - i2cp->rxbuf = rxbuf; - i2cp->remaining_bytes = n; - i2cp->flags = I2C_FLG_MASTER_RECEIVER; - i2cp->errors = 0; + i2cp->id_slave_config->flags = I2C_FLG_MASTER_RECEIVER; + i2cp->id_slave_config->errors = 0; // Only one byte to be received - if(i2cp->remaining_bytes == 1) { - i2cp->flags |= I2C_FLG_1BTR; + if(i2cp->id_slave_config->rx_remaining_bytes == 1) { + i2cp->id_slave_config->flags |= I2C_FLG_1BTR; } // Only two bytes to be received - else if(i2cp->remaining_bytes == 2) { - i2cp->flags |= I2C_FLG_2BTR; - i2cp->i2c_register->CR1 |= I2C_CR1_POS; // Acknowledge Position + else if(i2cp->id_slave_config->rx_remaining_bytes == 2) { + i2cp->id_slave_config->flags |= I2C_FLG_2BTR; + i2cp->id_i2c->CR1 |= I2C_CR1_POS; // Acknowledge Position } - i2cp->i2c_register->CR1 |= I2C_CR1_START; // send start bit + i2cp->id_i2c->CR1 |= I2C_CR1_START; // send start bit #if !I2C_USE_WAIT /* Wait until the START condition is generated on the bus: the START bit is cleared by hardware */ - uint32_t tmo = 0xfffff; - while((i2cp->i2c_register->CR1 & I2C_CR1_START) && tmo--) + uint32_t timeout = 0xfffff; + while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) ; #endif /* I2C_USE_WAIT */ } diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 2c926b1dd..268e7264d 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -115,6 +115,8 @@ typedef struct { I2C_DutyCycle_t FastModeDutyCycle;/*!< Specifies the I2C fast mode duty cycle */ uint8_t OwnAddress7; /*!< Specifies the first device 7-bit own address. */ uint16_t OwnAddress10; /*!< Specifies the second part of device own address in 10-bit mode. Set to NULL if not used. */ + uint16_t Ack; /*!< Enables or disables the acknowledgement. */ + uint8_t nBitAddress; /*!< Specifies if 7-bit or 10-bit address is acknowledged */ } I2CConfig; @@ -165,6 +167,11 @@ struct I2CDriver{ */ uint8_t rw_bit; + uint8_t slave_addr1; // 7-bit address of the slave + uint8_t slave_addr2; // used in 10-bit address mode + uint8_t nbit_address; + + /*********** End of the mandatory fields. **********************************/ /** @@ -197,13 +204,13 @@ extern "C" { void i2c_lld_init(void); void i2c_lld_reset(I2CDriver *i2cp); -void i2c_lld_set_clock(I2CDriver *i2cp, int32_t clock_speed, I2C_DutyCycle_t duty); -void i2c_lld_set_opmode(I2CDriver *i2cp, I2C_opMode_t opmode); -void i2c_lld_set_own_address(I2CDriver *i2cp, int16_t address, int8_t nr_bit); +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, size_t n, void *txbuf); -void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *rxbuf); +void i2c_lld_master_transmit(I2CDriver *i2cp); +void i2c_lld_master_receive(I2CDriver *i2cp); #ifdef __cplusplus } diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index ad9a5d0ac..50767b3a9 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -129,107 +129,175 @@ void i2cStop(I2CDriver *i2cp) { chSysUnlock(); } -/** - * @brief Generate (re)start on the bus. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2cMasterStart(I2CDriver *i2cp){ - - chDbgCheck((i2cp != NULL), "i2cMasterTransmit"); - - chSysLock(); - i2c_lld_master_start(i2cp); - chSysUnlock(); -} - -/** - * @brief Generate stop on the bus. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2cMasterStop(I2CDriver *i2cp){ - - chDbgCheck((i2cp != NULL), "i2cMasterTransmit"); - chSysLock(); - i2c_lld_master_stop(i2cp); - chSysUnlock(); -} - /** * @brief Sends data ever the I2C bus. * * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object + * @param[in] i2cscfg pointer to the @p I2C slave config * */ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { - chDbgCheck((i2cp != NULL) && (i2cscfg != NULL), + size_t n; + i2cblock_t *txbuf; + + txbuf = i2cscfg->txbuf; + n = i2cscfg->tx_remaining_bytes; + + chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) && (n > 0) && (txbuf != NULL), "i2cMasterTransmit"); - chDbgAssert(i2cp->id_state == I2C_READY, - "i2cMasterTransmit(), #1", - "not active"); + + // init slave config field in driver + i2cp->id_slave_config = i2cscfg; + +#if I2C_USE_WAIT + i2c_lld_wait_bus_free(i2cp); + if(i2c_lld_bus_is_busy(i2cp)) { +#ifdef PRINTTRACE + print("I2C Bus busy!\n"); +#endif + return; + }; +#endif chSysLock(); - i2c_lld_master_transmit(i2cp, i2cscfg); + chDbgAssert(i2cp->id_state == I2C_READY, + "i2cMasterTransmit(), #1", "not ready"); + + i2cp->id_state = I2C_ACTIVE; + i2c_lld_master_transmit(i2cp); + _i2c_wait_s(i2cp); +#if !I2C_USE_WAIT + i2c_lld_wait_bus_free(i2cp); +#endif + if (i2cp->id_state == I2C_COMPLETE) + i2cp->id_state = I2C_READY; chSysUnlock(); } - /** * @brief Receives data from the I2C bus. * * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object + * @param[in] i2cscfg pointer to the @p I2C slave config + * */ -void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { +void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ - chDbgCheck((i2cp != NULL) && (i2cscfg != NULL), + size_t n; + i2cblock_t *rxbuf; + + rxbuf = i2cscfg->rxbuf; + n = i2cscfg->rx_remaining_bytes; + + chDbgCheck((i2cp != NULL) && (n > 0) && (rxbuf != NULL), "i2cMasterReceive"); - chDbgAssert(i2cp->id_state == I2C_READY, - "i2cMasterReceive(), #1", - "not active"); + + // init slave config field in driver + i2cp->id_slave_config = i2cscfg; + +#if I2C_USE_WAIT + i2c_lld_wait_bus_free(i2cp); + if(i2c_lld_bus_is_busy(i2cp)) { +#ifdef PRINTTRACE + print("I2C Bus busy!\n"); +#endif + return; + }; +#endif chSysLock(); - i2c_lld_master_receive(i2cp, i2cscfg); + chDbgAssert(i2cp->id_state == I2C_READY, + "i2cMasterReceive(), #1", "not ready"); + + i2cp->id_state = I2C_ACTIVE; + i2c_lld_master_receive(i2cp); + _i2c_wait_s(i2cp); +#if !I2C_USE_WAIT + i2c_lld_wait_bus_free(i2cp); +#endif + if (i2cp->id_state == I2C_COMPLETE) + i2cp->id_state = I2C_READY; chSysUnlock(); } +uint16_t i2cSMBusAlertResponse(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { + + i2cMasterReceive(i2cp, i2cscfg); + return i2cp->id_slave_config->slave_addr; +} + + +/** + * @brief Handles communication events/errors. + * @details Must be called from the I/O interrupt service routine in order to + * notify I/O conditions as errors, signals change etc. + * + * @param[in] i2cp pointer to a @p I2CDriver structure + * @param[in] mask condition flags to be added to the mask + * + * @iclass + */ +void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask) { + + chDbgCheck(i2cp != NULL, "i2cAddFlagsI"); + + i2cp->id_slave_config->errors |= mask; + chEvtBroadcastI(&i2cp->id_slave_config->sevent); +} + +/** + * @brief Returns and clears the errors mask associated to the driver. + * + * @param[in] i2cp pointer to a @p I2CDriver structure + * @return The condition flags modified since last time this + * function was invoked. + * + * @api + */ +i2cflags_t i2cGetAndClearFlags(I2CDriver *i2cp) { + i2cflags_t mask; + + chDbgCheck(i2cp != NULL, "i2cGetAndClearFlags"); + + chSysLock(); + mask = i2cp->id_slave_config->errors; + i2cp->id_slave_config->errors = I2CD_NO_ERROR; + chSysUnlock(); + return mask; +} + #if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) /** - * @brief Gains exclusive access to the I2C bus. + * @brief Gains exclusive access to the I2C bus. * @details This function tries to gain ownership to the I2C bus, if the bus * is already being used then the invoking thread is queued. - * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION - * must be enabled. * * @param[in] i2cp pointer to the @p I2CDriver object * - * @api - * + * @note This function is only available when the @p I2C_USE_MUTUAL_EXCLUSION + * option is set to @p TRUE. */ void i2cAcquireBus(I2CDriver *i2cp) { chDbgCheck(i2cp != NULL, "i2cAcquireBus"); #if CH_USE_MUTEXES - chMtxLock(&i2cp->id_mutex); + chMtxLock(&i2cp->mutex); #elif CH_USE_SEMAPHORES chSemWait(&i2cp->id_semaphore); #endif } /** - * @brief Releases exclusive access to the I2C bus. - * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION - * must be enabled. + * @brief Releases exclusive access to the I2C bus. * * @param[in] i2cp pointer to the @p I2CDriver object * - * @api + * @note This function is only available when the @p I2C_USE_MUTUAL_EXCLUSION + * option is set to @p TRUE. */ void i2cReleaseBus(I2CDriver *i2cp) { From 60975ca7fed0e2960bced2fe72239422f8376068 Mon Sep 17 00:00:00 2001 From: barthess Date: Fri, 6 May 2011 15:16:15 +0000 Subject: [PATCH 39/92] I2C. Some fixes. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2922 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 11 +++-- os/hal/platforms/STM32/i2c_lld.c | 69 +++++++++++++++++++++++++++++--- os/hal/platforms/STM32/i2c_lld.h | 14 +++++++ os/hal/src/i2c.c | 11 ++++- 4 files changed, 91 insertions(+), 14 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 39ba313fd..6e740cfa9 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -204,7 +204,6 @@ struct I2CSlaveConfig{ } \ } #else /* !I2C_USE_WAIT */ -#define i2c_lld_wait_bus_free(i2cp) //TODO: remove this STUB #define _i2c_wait_s(i2cp) #define _i2c_wakeup_isr(i2cp) #endif /* !I2C_USE_WAIT */ @@ -223,12 +222,12 @@ struct I2CSlaveConfig{ * * @notapi */ -#define _i2c_isr_code(i2cp, i2cscfg) { \ - (i2cp)->id_state = I2C_COMPLETE; \ +#define _i2c_isr_code(i2cp, i2cscfg) { \ + (i2cp)->id_state = I2C_COMPLETE; \ if(((i2cp)->id_slave_config)->id_callback) { \ - ((i2cp)->id_slave_config)->id_callback(i2cp, i2cscfg); \ - } \ - _i2c_wakeup_isr(i2cp); \ + ((i2cp)->id_slave_config)->id_callback(i2cp, i2cscfg); \ + } \ + _i2c_wakeup_isr(i2cp); \ } /*===========================================================================*/ diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 6384300f7..7d48b01c8 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -94,11 +94,20 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { } break; case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: - dp->CR1 |= I2C_CR1_STOP; // stop generation - /* Disable ITEVT In order to not have again a BTF IT */ - dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; - /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ - _i2c_isr_code(i2cp, i2cp->id_slave_config); + /* if nothing to read then generate stop */ + if (i2cp->id_slave_config->rx_remaining_bytes == 0){ + dp->CR1 |= I2C_CR1_STOP; // stop generation + /* Disable ITEVT In order to not have again a BTF IT */ + dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; + /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ + _i2c_isr_code(i2cp, i2cp->id_slave_config); + } + else{ + /* Disable ITEVT In order to not have again a BTF IT */ + dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; + /* send restart and begin reading operations */ + i2c_lld_master_transceive(i2cp); + } break; @@ -550,7 +559,7 @@ void i2c_lld_master_receive(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // acknowledge returned i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - switch(i2cp->nbit_address){ + switch(i2cp->id_slave_config->nbit_address){ case 7: i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) | 0x01); // LSB = 1 -> receive break; @@ -586,4 +595,52 @@ void i2c_lld_master_receive(I2CDriver *i2cp){ +/** + * @brief + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + */ +void i2c_lld_master_transceive(I2CDriver *i2cp){ + uint32_t a, b; + // enable ERR, EVT & BUF ITs + i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // acknowledge returned + i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; + + switch(i2cp->id_slave_config->nbit_address){ + case 7: + i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) | 0x01); // LSB = 1 -> receive + break; + case 10: + i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr >>7) & 0x0006); // add the two msb of 10-bit address to the header + i2cp->slave_addr1 |= 0xF0; // add the header bits (the LSB -> 1 will be add to second + i2cp->slave_addr2 = i2cp->id_slave_config->slave_addr & 0x00FF; // the remaining 8 bit of 10-bit address + break; + } + + i2cp->id_slave_config->flags = I2C_FLG_MASTER_RECEIVER; + i2cp->id_slave_config->errors = 0; + + // Only one byte to be received + if(i2cp->id_slave_config->rx_remaining_bytes == 1) { + i2cp->id_slave_config->flags |= I2C_FLG_1BTR; + } + // Only two bytes to be received + else if(i2cp->id_slave_config->rx_remaining_bytes == 2) { + i2cp->id_slave_config->flags |= I2C_FLG_2BTR; + i2cp->id_i2c->CR1 |= I2C_CR1_POS; // Acknowledge Position + } + + i2cp->id_i2c->CR1 |= I2C_CR1_START; // send start bit + +#if !I2C_USE_WAIT + /* Wait until the START condition is generated on the bus: the START bit is cleared by hardware */ + uint32_t timeout = 0xfffff; + while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) + ; +#endif /* I2C_USE_WAIT */ +} + + #endif // HAL_USE_I2C diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 268e7264d..00c6410fa 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -185,6 +185,19 @@ struct I2CDriver{ /* 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 + */ +#define i2c_lld_wait_bus_free(i2cp) { \ + uint32_t tmo = 0xffff; \ + while((i2cp->id_i2c->SR2 & I2C_SR2_BUSY) && tmo--) \ + ; \ +} + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ @@ -211,6 +224,7 @@ void i2c_lld_start(I2CDriver *i2cp); void i2c_lld_stop(I2CDriver *i2cp); void i2c_lld_master_transmit(I2CDriver *i2cp); void i2c_lld_master_receive(I2CDriver *i2cp); +void i2c_lld_master_transceive(I2CDriver *i2cp); #ifdef __cplusplus } diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 50767b3a9..1a2873a29 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -140,11 +140,14 @@ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { size_t n; i2cblock_t *txbuf; + uint8_t nbit_addr; txbuf = i2cscfg->txbuf; + nbit_addr = i2cscfg->nbit_address; n = i2cscfg->tx_remaining_bytes; - chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) && (n > 0) && (txbuf != NULL), + chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) && \ + ((nbit_addr == 7) || (nbit_addr == 10)) && (n > 0) && (txbuf != NULL), "i2cMasterTransmit"); // init slave config field in driver @@ -186,11 +189,14 @@ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ size_t n; i2cblock_t *rxbuf; + uint8_t nbit_addr; rxbuf = i2cscfg->rxbuf; n = i2cscfg->rx_remaining_bytes; + nbit_addr = i2cscfg->nbit_address; - chDbgCheck((i2cp != NULL) && (n > 0) && (rxbuf != NULL), + chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) && (n > 0) && \ + ((nbit_addr == 7) || (nbit_addr == 10)) && (rxbuf != NULL), "i2cMasterReceive"); // init slave config field in driver @@ -221,6 +227,7 @@ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ chSysUnlock(); } + uint16_t i2cSMBusAlertResponse(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { i2cMasterReceive(i2cp, i2cscfg); From 732eaa72c18b9bc6ddb9b6c5ac2294420d14552e Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 8 May 2011 13:20:10 +0000 Subject: [PATCH 40/92] I2C. Code cleanups. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2937 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 28 ++++++++++++++-------------- os/hal/platforms/STM32/i2c_lld.c | 30 +++++++++++++++--------------- os/hal/src/i2c.c | 4 ++-- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 6e740cfa9..c3e5c0538 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -77,11 +77,11 @@ * @brief Driver state machine possible states. */ typedef enum { - I2C_UNINIT = 0, /**< @brief Not initialized. */ - I2C_STOP = 1, /**< @brief Stopped. */ - I2C_READY = 2, /**< @brief Ready. */ - I2C_ACTIVE = 3, /**< @brief In communication. */ - I2C_COMPLETE = 4, /**< @brief Asynchronous operation complete. */ + I2C_UNINIT = 0, /**< @brief Not initialized. */ + I2C_STOP = 1, /**< @brief Stopped. */ + I2C_READY = 2, /**< @brief Ready. */ + I2C_ACTIVE = 3, /**< @brief In communication. */ + I2C_COMPLETE = 4, /**< @brief Asynchronous operation complete. */ // slave part I2C_SACTIVE = 10, @@ -150,12 +150,12 @@ struct I2CSlaveConfig{ /** * @brief Receive and transmit buffers. */ - size_t tx_remaining_bytes; - size_t rx_remaining_bytes; - i2cblock_t *rxbuf;/*!< Pointer to receive buffer. */ - i2cblock_t *txbuf;/*!< Pointer to transmit buffer.*/ + size_t tx_bytes; + size_t rx_bytes; + i2cblock_t *rxbuf; /*!< Pointer to receive buffer. */ + i2cblock_t *txbuf; /*!< Pointer to transmit buffer.*/ uint16_t slave_addr; - uint8_t nbit_address; + uint8_t nbit_address; /*!< Length of address (must be 7 or 10).*/ i2cflags_t errors; i2cflags_t flags; /* Status Change @p EventSource.*/ @@ -224,10 +224,10 @@ struct I2CSlaveConfig{ */ #define _i2c_isr_code(i2cp, i2cscfg) { \ (i2cp)->id_state = I2C_COMPLETE; \ - if(((i2cp)->id_slave_config)->id_callback) { \ - ((i2cp)->id_slave_config)->id_callback(i2cp, i2cscfg); \ - } \ - _i2c_wakeup_isr(i2cp); \ + if(((i2cp)->id_slave_config)->id_callback) { \ + ((i2cp)->id_slave_config)->id_callback(i2cp, i2cscfg); \ + } \ + _i2c_wakeup_isr(i2cp); \ } /*===========================================================================*/ diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 7d48b01c8..02f1105de 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -73,20 +73,20 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { txBuffp = (uint8_t*)i2cp->id_slave_config->txbuf; datap = txBuffp; txBuffp++; - i2cp->id_slave_config->tx_remaining_bytes--; + i2cp->id_slave_config->tx_bytes--; /* If no further data to be sent, disable the I2C ITBUF in order to not have a TxE interrupt */ - if(i2cp->id_slave_config->tx_remaining_bytes == 0) { + if(i2cp->id_slave_config->tx_bytes == 0) { dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; } //EV8_1 write the first data dp->DR = *datap; break; case I2C_EV8_MASTER_BYTE_TRANSMITTING: - if(i2cp->id_slave_config->tx_remaining_bytes > 0) { + if(i2cp->id_slave_config->tx_bytes > 0) { datap = txBuffp; txBuffp++; - i2cp->id_slave_config->tx_remaining_bytes--; - if(i2cp->id_slave_config->tx_remaining_bytes == 0) { + i2cp->id_slave_config->tx_bytes--; + if(i2cp->id_slave_config->tx_bytes == 0) { /* If no further data to be sent, disable the ITBUF in order to not have a TxE interrupt */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; } @@ -95,7 +95,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { break; case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: /* if nothing to read then generate stop */ - if (i2cp->id_slave_config->rx_remaining_bytes == 0){ + if (i2cp->id_slave_config->rx_bytes == 0){ dp->CR1 |= I2C_CR1_STOP; // stop generation /* Disable ITEVT In order to not have again a BTF IT */ dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; @@ -135,12 +135,12 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { rxBuffp = i2cp->id_slave_config->rxbuf; break; case I2C_EV7_MASTER_REC_BYTE_RECEIVED: - if(i2cp->id_slave_config->rx_remaining_bytes != 3) { + if(i2cp->id_slave_config->rx_bytes != 3) { /* Read the data register */ *rxBuffp = dp->DR; rxBuffp++; - i2cp->id_slave_config->rx_remaining_bytes--; - switch(i2cp->id_slave_config->rx_remaining_bytes){ + i2cp->id_slave_config->rx_bytes--; + switch(i2cp->id_slave_config->rx_bytes){ case 3: /* Disable the ITBUF in order to have only the BTF interrupt */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; @@ -172,7 +172,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { chSysUnlockFromIsr(); rxBuffp++; /* Decrement the number of readed bytes */ - i2cp->id_slave_config->rx_remaining_bytes -= 2; + i2cp->id_slave_config->rx_bytes -= 2; i2cp->id_slave_config->flags = 0; // ready for read DataN on the next EV7 break; @@ -187,7 +187,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { rxBuffp++; /* Read the DataN*/ *rxBuffp = dp->DR; - i2cp->id_slave_config->rx_remaining_bytes = 0; + i2cp->id_slave_config->rx_bytes = 0; i2cp->id_slave_config->flags = 0; /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ _i2c_isr_code(i2cp, i2cp->id_slave_config); @@ -574,11 +574,11 @@ void i2c_lld_master_receive(I2CDriver *i2cp){ i2cp->id_slave_config->errors = 0; // Only one byte to be received - if(i2cp->id_slave_config->rx_remaining_bytes == 1) { + if(i2cp->id_slave_config->rx_bytes == 1) { i2cp->id_slave_config->flags |= I2C_FLG_1BTR; } // Only two bytes to be received - else if(i2cp->id_slave_config->rx_remaining_bytes == 2) { + else if(i2cp->id_slave_config->rx_bytes == 2) { i2cp->id_slave_config->flags |= I2C_FLG_2BTR; i2cp->id_i2c->CR1 |= I2C_CR1_POS; // Acknowledge Position } @@ -623,11 +623,11 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ i2cp->id_slave_config->errors = 0; // Only one byte to be received - if(i2cp->id_slave_config->rx_remaining_bytes == 1) { + if(i2cp->id_slave_config->rx_bytes == 1) { i2cp->id_slave_config->flags |= I2C_FLG_1BTR; } // Only two bytes to be received - else if(i2cp->id_slave_config->rx_remaining_bytes == 2) { + else if(i2cp->id_slave_config->rx_bytes == 2) { i2cp->id_slave_config->flags |= I2C_FLG_2BTR; i2cp->id_i2c->CR1 |= I2C_CR1_POS; // Acknowledge Position } diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 1a2873a29..18d1d78c0 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -144,7 +144,7 @@ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { txbuf = i2cscfg->txbuf; nbit_addr = i2cscfg->nbit_address; - n = i2cscfg->tx_remaining_bytes; + n = i2cscfg->tx_bytes; chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) && \ ((nbit_addr == 7) || (nbit_addr == 10)) && (n > 0) && (txbuf != NULL), @@ -192,7 +192,7 @@ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ uint8_t nbit_addr; rxbuf = i2cscfg->rxbuf; - n = i2cscfg->rx_remaining_bytes; + n = i2cscfg->rx_bytes; nbit_addr = i2cscfg->nbit_address; chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) && (n > 0) && \ From 07556a2d033a33d1d4e5a1d75b93681851e485c7 Mon Sep 17 00:00:00 2001 From: barthess Date: Fri, 13 May 2011 13:24:32 +0000 Subject: [PATCH 41/92] I2C. Remove dead variable. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2950 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 1 - 1 file changed, 1 deletion(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 02f1105de..388409774 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -602,7 +602,6 @@ void i2c_lld_master_receive(I2CDriver *i2cp){ * */ void i2c_lld_master_transceive(I2CDriver *i2cp){ - uint32_t a, b; // enable ERR, EVT & BUF ITs i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // acknowledge returned From 152f34a80c6ffe5fd17809732272823091b854e8 Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 28 May 2011 12:31:47 +0000 Subject: [PATCH 42/92] I2C. Some refactorings. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3000 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 4 ++-- os/hal/platforms/STM32/i2c_lld.c | 30 +++++++++++++++--------------- os/hal/src/i2c.c | 4 ++-- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index c3e5c0538..1c9238859 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -150,8 +150,8 @@ struct I2CSlaveConfig{ /** * @brief Receive and transmit buffers. */ - size_t tx_bytes; - size_t rx_bytes; + size_t txbytes; + size_t rxbytes; i2cblock_t *rxbuf; /*!< Pointer to receive buffer. */ i2cblock_t *txbuf; /*!< Pointer to transmit buffer.*/ uint16_t slave_addr; diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 388409774..2c535b930 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -73,20 +73,20 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { txBuffp = (uint8_t*)i2cp->id_slave_config->txbuf; datap = txBuffp; txBuffp++; - i2cp->id_slave_config->tx_bytes--; + i2cp->id_slave_config->txbytes--; /* If no further data to be sent, disable the I2C ITBUF in order to not have a TxE interrupt */ - if(i2cp->id_slave_config->tx_bytes == 0) { + if(i2cp->id_slave_config->txbytes == 0) { dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; } //EV8_1 write the first data dp->DR = *datap; break; case I2C_EV8_MASTER_BYTE_TRANSMITTING: - if(i2cp->id_slave_config->tx_bytes > 0) { + if(i2cp->id_slave_config->txbytes > 0) { datap = txBuffp; txBuffp++; - i2cp->id_slave_config->tx_bytes--; - if(i2cp->id_slave_config->tx_bytes == 0) { + i2cp->id_slave_config->txbytes--; + if(i2cp->id_slave_config->txbytes == 0) { /* If no further data to be sent, disable the ITBUF in order to not have a TxE interrupt */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; } @@ -95,7 +95,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { break; case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: /* if nothing to read then generate stop */ - if (i2cp->id_slave_config->rx_bytes == 0){ + if (i2cp->id_slave_config->rxbytes == 0){ dp->CR1 |= I2C_CR1_STOP; // stop generation /* Disable ITEVT In order to not have again a BTF IT */ dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; @@ -135,12 +135,12 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { rxBuffp = i2cp->id_slave_config->rxbuf; break; case I2C_EV7_MASTER_REC_BYTE_RECEIVED: - if(i2cp->id_slave_config->rx_bytes != 3) { + if(i2cp->id_slave_config->rxbytes != 3) { /* Read the data register */ *rxBuffp = dp->DR; rxBuffp++; - i2cp->id_slave_config->rx_bytes--; - switch(i2cp->id_slave_config->rx_bytes){ + i2cp->id_slave_config->rxbytes--; + switch(i2cp->id_slave_config->rxbytes){ case 3: /* Disable the ITBUF in order to have only the BTF interrupt */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; @@ -172,7 +172,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { chSysUnlockFromIsr(); rxBuffp++; /* Decrement the number of readed bytes */ - i2cp->id_slave_config->rx_bytes -= 2; + i2cp->id_slave_config->rxbytes -= 2; i2cp->id_slave_config->flags = 0; // ready for read DataN on the next EV7 break; @@ -187,7 +187,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { rxBuffp++; /* Read the DataN*/ *rxBuffp = dp->DR; - i2cp->id_slave_config->rx_bytes = 0; + i2cp->id_slave_config->rxbytes = 0; i2cp->id_slave_config->flags = 0; /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ _i2c_isr_code(i2cp, i2cp->id_slave_config); @@ -574,11 +574,11 @@ void i2c_lld_master_receive(I2CDriver *i2cp){ i2cp->id_slave_config->errors = 0; // Only one byte to be received - if(i2cp->id_slave_config->rx_bytes == 1) { + if(i2cp->id_slave_config->rxbytes == 1) { i2cp->id_slave_config->flags |= I2C_FLG_1BTR; } // Only two bytes to be received - else if(i2cp->id_slave_config->rx_bytes == 2) { + else if(i2cp->id_slave_config->rxbytes == 2) { i2cp->id_slave_config->flags |= I2C_FLG_2BTR; i2cp->id_i2c->CR1 |= I2C_CR1_POS; // Acknowledge Position } @@ -622,11 +622,11 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ i2cp->id_slave_config->errors = 0; // Only one byte to be received - if(i2cp->id_slave_config->rx_bytes == 1) { + if(i2cp->id_slave_config->rxbytes == 1) { i2cp->id_slave_config->flags |= I2C_FLG_1BTR; } // Only two bytes to be received - else if(i2cp->id_slave_config->rx_bytes == 2) { + else if(i2cp->id_slave_config->rxbytes == 2) { i2cp->id_slave_config->flags |= I2C_FLG_2BTR; i2cp->id_i2c->CR1 |= I2C_CR1_POS; // Acknowledge Position } diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 18d1d78c0..84dfcf958 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -144,7 +144,7 @@ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { txbuf = i2cscfg->txbuf; nbit_addr = i2cscfg->nbit_address; - n = i2cscfg->tx_bytes; + n = i2cscfg->txbytes; chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) && \ ((nbit_addr == 7) || (nbit_addr == 10)) && (n > 0) && (txbuf != NULL), @@ -192,7 +192,7 @@ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ uint8_t nbit_addr; rxbuf = i2cscfg->rxbuf; - n = i2cscfg->rx_bytes; + n = i2cscfg->rxbytes; nbit_addr = i2cscfg->nbit_address; chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) && (n > 0) && \ From 4044f7d30841ccba2ed820f72753aff1d371cc67 Mon Sep 17 00:00:00 2001 From: barthess Date: Fri, 17 Jun 2011 07:10:30 +0000 Subject: [PATCH 43/92] I2C. Examples update. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3051 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- testhal/STM32/I2C/Makefile | 2 +- testhal/STM32/I2C/ch.ld | 69 ++++++++++++++++++----------- testhal/STM32/I2C/chconf.h | 37 +++++++--------- testhal/STM32/I2C/halconf.h | 73 ++++++++++++++++++++++++++++-- testhal/STM32/I2C/lis3.c | 71 +++++++++--------------------- testhal/STM32/I2C/max1236.c | 70 +++++++++++------------------ testhal/STM32/I2C/mcuconf.h | 88 +++++++++++++++++++++++++++---------- testhal/STM32/I2C/tmp75.c | 35 +++++---------- 8 files changed, 255 insertions(+), 190 deletions(-) diff --git a/testhal/STM32/I2C/Makefile b/testhal/STM32/I2C/Makefile index 888e33eb2..62eef3874 100644 --- a/testhal/STM32/I2C/Makefile +++ b/testhal/STM32/I2C/Makefile @@ -78,8 +78,8 @@ CSRC = $(PORTSRC) \ main.c \ i2c_pns.c \ lis3.c\ - tmp75.c\ max1236.c\ + tmp75.c\ # C++ sources that can be compiled in ARM or THUMB mode depending on the global # setting. diff --git a/testhal/STM32/I2C/ch.ld b/testhal/STM32/I2C/ch.ld index 44f494121..4d97e7682 100644 --- a/testhal/STM32/I2C/ch.ld +++ b/testhal/STM32/I2C/ch.ld @@ -1,5 +1,6 @@ /* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -37,11 +38,32 @@ __ram_end__ = __ram_start__ + __ram_size__; SECTIONS { . = 0; + _text = .; + + startup : ALIGN(16) SUBALIGN(16) + { + KEEP(*(vectors)) + } > flash + + constructors : ALIGN(4) SUBALIGN(4) + { + PROVIDE(__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE(__init_array_end = .); + } > flash + + destructors : ALIGN(4) SUBALIGN(4) + { + PROVIDE(__fini_array_start = .); + KEEP(*(.fini_array)) + KEEP(*(SORT(.fini_array.*))) + PROVIDE(__fini_array_end = .); + } > flash .text : ALIGN(16) SUBALIGN(16) { - _text = .; - KEEP(*(vectors)) + *(.text.startup.*) *(.text) *(.text.*) *(.rodata) @@ -51,31 +73,26 @@ SECTIONS *(.gcc*) } > flash - .ctors : + .ARM.extab : { - PROVIDE(_ctors_start_ = .); - KEEP(*(SORT(.ctors.*))) - KEEP(*(.ctors)) - PROVIDE(_ctors_end_ = .); + *(.ARM.extab* .gnu.linkonce.armextab.*) } > flash - .dtors : + .ARM.exidx : { + PROVIDE(__exidx_start = .); + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + PROVIDE(__exidx_end = .); + } > flash + + .eh_frame_hdr : { - PROVIDE(_dtors_start_ = .); - KEEP(*(SORT(.dtors.*))) - KEEP(*(.dtors)) - PROVIDE(_dtors_end_ = .); + *(.eh_frame_hdr) } > flash - .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} - - __exidx_start = .; - .ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > flash - __exidx_end = .; - - .eh_frame_hdr : {*(.eh_frame_hdr)} - - .eh_frame : ONLY_IF_RO {*(.eh_frame)} + .eh_frame : ONLY_IF_RO + { + *(.eh_frame) + } > flash . = ALIGN(4); _etext = .; @@ -83,26 +100,26 @@ SECTIONS .data : { - _data = .; + PROVIDE(_data = .); *(.data) . = ALIGN(4); *(.data.*) . = ALIGN(4); *(.ramtext) . = ALIGN(4); - _edata = .; + PROVIDE(_edata = .); } > ram AT > flash .bss : { - _bss_start = .; + PROVIDE(_bss_start = .); *(.bss) . = ALIGN(4); *(.bss.*) . = ALIGN(4); *(COMMON) . = ALIGN(4); - _bss_end = .; + PROVIDE(_bss_end = .); } > ram } diff --git a/testhal/STM32/I2C/chconf.h b/testhal/STM32/I2C/chconf.h index 657ddf887..9f5273ba5 100644 --- a/testhal/STM32/I2C/chconf.h +++ b/testhal/STM32/I2C/chconf.h @@ -89,6 +89,23 @@ #define CH_MEMCORE_SIZE 0 #endif +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread automatically. The application has + * then the responsibility to do one of the following: + * - Spawn a custom idle thread at priority @p IDLEPRIO. + * - Change the main() thread priority to @p IDLEPRIO then enter + * an endless loop. In this scenario the @p main() thread acts as + * the idle thread. + * . + * @note Unless an idle thread is spawned the @p main() thread must not + * enter a sleep state. + */ +#if !defined(CH_NO_IDLE_THREAD) || defined(__DOXYGEN__) +#define CH_NO_IDLE_THREAD FALSE +#endif + /*===========================================================================*/ /* Performance options. */ /*===========================================================================*/ @@ -105,26 +122,6 @@ #define CH_OPTIMIZE_SPEED FALSE #endif -/** - * @brief Exotic optimization. - * @details If defined then a CPU register is used as storage for the global - * @p currp variable. Caching this variable in a register greatly - * improves both space and time OS efficiency. A side effect is that - * one less register has to be saved during the context switch - * resulting in lower RAM usage and faster context switch. - * - * @note This option is only usable with the GCC compiler and is only useful - * on processors with many registers like ARM cores. - * @note If this option is enabled then ALL the libraries linked to the - * ChibiOS/RT code must be recompiled with the GCC option @p - * -ffixed-@. - * @note This option must be enabled in the Makefile, it is listed here for - * documentation only. - */ -#if defined(__DOXYGEN__) -#define CH_CURRP_REGISTER_CACHE "reg" -#endif - /*===========================================================================*/ /* Subsystem options. */ /*===========================================================================*/ diff --git a/testhal/STM32/I2C/halconf.h b/testhal/STM32/I2C/halconf.h index 9a7979cc9..b128d89cf 100644 --- a/testhal/STM32/I2C/halconf.h +++ b/testhal/STM32/I2C/halconf.h @@ -54,6 +54,13 @@ #define HAL_USE_CAN FALSE #endif +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + /** * @brief Enables the I2C subsystem. */ @@ -61,6 +68,13 @@ #define HAL_USE_I2C TRUE #endif +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + /** * @brief Enables the MAC subsystem. */ @@ -82,11 +96,25 @@ #define HAL_USE_PWM TRUE #endif +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + /** * @brief Enables the SERIAL subsystem. */ #if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) -#define HAL_USE_SERIAL FALSE +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE #endif /** @@ -100,7 +128,14 @@ * @brief Enables the UART subsystem. */ #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) -#define HAL_USE_UART TRUE +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE #endif /*===========================================================================*/ @@ -206,6 +241,36 @@ /* PWM driver related settings. */ /*===========================================================================*/ +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intevals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + /*===========================================================================*/ /* SERIAL driver related settings. */ /*===========================================================================*/ @@ -216,7 +281,7 @@ * default configuration. */ #if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) -#define SERIAL_DEFAULT_BITRATE 38400 +#define SERIAL_DEFAULT_BITRATE 57600 #endif /** @@ -227,7 +292,7 @@ * buffers. */ #if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) -#define SERIAL_BUFFERS_SIZE 16 +#define SERIAL_BUFFERS_SIZE 256 #endif /*===========================================================================*/ diff --git a/testhal/STM32/I2C/lis3.c b/testhal/STM32/I2C/lis3.c index 06f6da1d0..7e7c9d221 100644 --- a/testhal/STM32/I2C/lis3.c +++ b/testhal/STM32/I2C/lis3.c @@ -30,19 +30,21 @@ static void i2c_lis3_error_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ static I2CSlaveConfig lis3 = { NULL, i2c_lis3_error_cb, + 0, + 0, accel_rx_data, - ACCEL_RX_DEPTH, - 0, - 0, accel_tx_data, - ACCEL_TX_DEPTH, - 0, - 0, 0b0011101, - FALSE, + 7, + 0, + 0, + {NULL}, }; + + + /** * This treading need for convenient realize * "read through write" process. @@ -82,26 +84,13 @@ static msg_t I2CAccelThread(void *arg) { /* This callback raise up when transfer finished */ static void i2c_lis3_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ + (void) i2cscfg; - if (i2cp->id_slave_config->restart){ // is it restart flag set to TRUE - /* reset restart flag */ - i2cp->id_slave_config->restart = FALSE; - /* now send restart and read acceleration data. - * Function i2cMasterReceive() send restart implicitly. */ - i2cMasterReceive(i2cp, i2cscfg); - } - else{ - /* If jump here than requested data have been read. - * Stop communication, release bus and wake up processing thread */ - i2cMasterStop(i2cp); - i2cReleaseBus(&I2CD1); - - // wake up heavy thread for data processing - if (i2c_accel_tp != NULL) { - i2c_accel_tp->p_msg = (msg_t)i2cp; - chSchReadyI(i2c_accel_tp); - i2c_accel_tp = NULL; - } + // only wake up processing thread + if (i2c_accel_tp != NULL) { + i2c_accel_tp->p_msg = (msg_t)i2cp; + chSchReadyI(i2c_accel_tp); + i2c_accel_tp = NULL; } } @@ -121,25 +110,19 @@ int init_lis3(void){ while (i2c_accel_tp == NULL) chThdSleepMilliseconds(1); - lis3.txbufhead = 0; - lis3.rxbufhead = 0; + lis3.rxbytes = 0; //set to 0 because we need only transmit - - /* Write configuration data */ + /* configure accelerometer */ lis3.txbytes = 4; - /* fill transmit buffer. See datasheet to understand what we write */ - lis3.txbuf[0] = ACCEL_CTRL_REG1 | AUTO_INCREMENT_BIT; + lis3.txbuf[0] = ACCEL_CTRL_REG1 | AUTO_INCREMENT_BIT; // register address lis3.txbuf[1] = 0b11100111; lis3.txbuf[2] = 0b01000001; lis3.txbuf[3] = 0b00000000; - /* setting callback */ - lis3.id_callback = i2c_lis3_cb; - - i2cAcquireBus(&I2CD1); - /* sending */ i2cMasterTransmit(&I2CD1, &lis3); + chThdSleepMilliseconds(1); + lis3.id_callback = i2c_lis3_cb; return 0; } @@ -148,23 +131,11 @@ int init_lis3(void){ * */ void request_acceleration_data(void){ - - /* fill transmit buffer with address of register that we want to read */ - lis3.txbufhead = 0; lis3.txbuf[0] = ACCEL_OUT_DATA | AUTO_INCREMENT_BIT; // register address lis3.txbytes = 1; - - /* tune receive structures */ - lis3.rxbufhead = 0; lis3.rxbytes = 6; - - /* Now it is most important action. We must set restart flag to TRUE. - * And in callback function we must reset it to FALSE after sending - * of register address. In TMP75 and MAX1236 this flag does not use. */ - lis3.restart = TRUE; - - /* talk to slave what we want from it */ i2cAcquireBus(&I2CD1); i2cMasterTransmit(&I2CD1, &lis3); + i2cReleaseBus(&I2CD1); } diff --git a/testhal/STM32/I2C/max1236.c b/testhal/STM32/I2C/max1236.c index e7e253916..36a77ff03 100644 --- a/testhal/STM32/I2C/max1236.c +++ b/testhal/STM32/I2C/max1236.c @@ -13,6 +13,9 @@ // 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, I2CSlaveConfig *i2cscfg){ @@ -25,17 +28,7 @@ static void i2c_max1236_error_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ /* This callback raise up when transfer finished */ static void i2c_max1236_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ - uint16_t ch1 = 0; - uint16_t ch2 = 0; - uint16_t ch3 = 0; - uint16_t ch4 = 0; - - /* send stop */ - i2cMasterStop(i2cp); - - /* unlock bus */ - i2cReleaseBus(&I2CD2); - + (void)*i2cp; /* get ADC data */ ch1 = ((i2cscfg->rxbuf[0] & 0xF) << 8) + i2cscfg->rxbuf[1]; ch2 = ((i2cscfg->rxbuf[2] & 0xF) << 8) + i2cscfg->rxbuf[3]; @@ -45,19 +38,19 @@ static void i2c_max1236_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ // ADC maxim MAX1236 config + static I2CSlaveConfig max1236 = { - NULL, // first set to NULL. We will set this pointer to the function later. - i2c_max1236_error_cb, - max1236_rx_data, - MAX1236_RX_DEPTH, - 0, - 0, - max1236_tx_data, - MAX1236_TX_DEPTH, - 0, - 0, - 0b0110100, - FALSE, + NULL, + i2c_max1236_error_cb, + 0, + 0, + max1236_rx_data, + max1236_tx_data, + 0b0110100, + 7, + 0, + 0, + {NULL}, }; @@ -66,41 +59,30 @@ static I2CSlaveConfig max1236 = { * how to initialize ADC. */ void init_max1236(void){ - /* lock bus */ - i2cAcquireBus(&I2CD2); - - /* this data we must send to IC to setup ADC settings */ - max1236.txbufhead = 0; + /* this data we must send via IC to setup ADC */ + max1236.rxbytes = 0; max1236.txbytes = 2; // total 2 bytes to be sent max1236.txbuf[0] = 0b10000011; // config register content. Consult datasheet max1236.txbuf[1] = 0b00000111; // config register content. Consult datasheet - // transmit out 2 bytes - i2cMasterTransmit(&I2CD2, &max1236); - while(I2CD2.id_state != I2C_READY) // wait - chThdSleepMilliseconds(1); + // transmit out 2 bytes + i2cAcquireBus(&I2CD2); + i2cMasterTransmit(&I2CD2, &max1236); + while(I2CD2.id_state != I2C_READY){ + chThdSleepMilliseconds(1); + } /* now add pointer to callback function */ max1236.id_callback = i2c_max1236_cb; - - /*clear transmitting structures */ - max1236.txbytes = 0; - max1236.txbufhead = 0; - - /* unlock bus */ i2cReleaseBus(&I2CD2); } /* Now simply read 8 bytes to get all 4 ADC channels */ void read_max1236(void){ - /* tune receive buffer */ - max1236.rxbufhead = 0; + max1236.txbytes = 0; max1236.rxbytes = 8; - - /* lock bus */ i2cAcquireBus(&I2CD2); - - /* start reading */ i2cMasterReceive(&I2CD2, &max1236); + i2cReleaseBus(&I2CD2); } diff --git a/testhal/STM32/I2C/mcuconf.h b/testhal/STM32/I2C/mcuconf.h index 92f8e17d8..465de58b8 100644 --- a/testhal/STM32/I2C/mcuconf.h +++ b/testhal/STM32/I2C/mcuconf.h @@ -58,25 +58,54 @@ #define STM32_CAN_USE_CAN1 FALSE #define STM32_CAN_CAN1_IRQ_PRIORITY 11 +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 TRUE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 + /* * PWM driver system settings. */ +#define STM32_PWM_USE_ADVANCED FALSE #define STM32_PWM_USE_TIM1 FALSE #define STM32_PWM_USE_TIM2 FALSE #define STM32_PWM_USE_TIM3 TRUE #define STM32_PWM_USE_TIM4 TRUE #define STM32_PWM_USE_TIM5 FALSE -#define STM32_PWM_TIM1_IRQ_PRIORITY 7 -#define STM32_PWM_TIM2_IRQ_PRIORITY 7 -#define STM32_PWM_TIM3_IRQ_PRIORITY 7 -#define STM32_PWM_TIM4_IRQ_PRIORITY 7 -#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM1_IRQ_PRIORITY 2 +#define STM32_PWM_TIM2_IRQ_PRIORITY 2 +#define STM32_PWM_TIM3_IRQ_PRIORITY 2 +#define STM32_PWM_TIM4_IRQ_PRIORITY 2 +#define STM32_PWM_TIM5_IRQ_PRIORITY 2 /* * SERIAL driver system settings. */ -#define STM32_SERIAL_USE_USART1 FALSE -#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART1 TRUE +#define STM32_SERIAL_USE_USART2 TRUE #define STM32_SERIAL_USE_USART3 FALSE #define STM32_SERIAL_USE_UART4 FALSE #define STM32_SERIAL_USE_UART5 FALSE @@ -89,24 +118,22 @@ /* * SPI driver system settings. */ -#define STM32_SPI_USE_SPI1 FALSE -#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI1 TRUE +#define STM32_SPI_USE_SPI2 TRUE #define STM32_SPI_USE_SPI3 FALSE -#define STM32_SPI_SPI1_DMA_PRIORITY 2 -#define STM32_SPI_SPI2_DMA_PRIORITY 2 -#define STM32_SPI_SPI3_DMA_PRIORITY 2 +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 #define STM32_SPI_SPI1_IRQ_PRIORITY 10 #define STM32_SPI_SPI2_IRQ_PRIORITY 10 #define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#define STM32_SPI_SPI1_DMA_ERROR_HOOK() chSysHalt() -#define STM32_SPI_SPI2_DMA_ERROR_HOOK() chSysHalt() -#define STM32_SPI_SPI3_DMA_ERROR_HOOK() chSysHalt() +#define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt() /* * UART driver system settings. */ -#define STM32_UART_USE_USART1 TRUE -#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART1 FALSE // RF link +#define STM32_UART_USE_USART2 FALSE //GPS #define STM32_UART_USE_USART3 FALSE #define STM32_UART_USART1_IRQ_PRIORITY 12 #define STM32_UART_USART2_IRQ_PRIORITY 12 @@ -114,18 +141,35 @@ #define STM32_UART_USART1_DMA_PRIORITY 0 #define STM32_UART_USART2_DMA_PRIORITY 0 #define STM32_UART_USART3_DMA_PRIORITY 0 -#define STM32_UART_USART1_DMA_ERROR_HOOK() chSysHalt() -#define STM32_UART_USART2_DMA_ERROR_HOOK() chSysHalt() -#define STM32_UART_USART3_DMA_ERROR_HOOK() chSysHalt() +#define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt() /* * I2C driver system settings. */ #define STM32_I2C_USE_I2C1 TRUE #define STM32_I2C_USE_I2C2 TRUE -#define STM32_I2C_I2C1_IRQ_PRIORITY 11 -#define STM32_I2C_I2C2_IRQ_PRIORITY 11 +#define STM32_I2C_I2C1_IRQ_PRIORITY 10 +#define STM32_I2C_I2C2_IRQ_PRIORITY 10 #define STM32_I2C_I2C1_DMA_PRIORITY 4 #define STM32_I2C_I2C2_DMA_PRIORITY 4 #define STM32_I2C_I2C1_DMA_ERROR_HOOK() chSysHalt() #define STM32_I2C_I2C2_DMA_ERROR_HOOK() chSysHalt() + +/* + * EXTI system settings. + */ +#define STM32_EXTI0_PRIORITY 5 +#define STM32_EXTI1_PRIORITY 5 +#define STM32_EXTI2_PRIORITY 5 +#define STM32_EXTI3_PRIORITY 5 +#define STM32_EXTI4_PRIORITY 5 +#define STM32_EXTI9_5_PRIORITY 5 +#define STM32_EXTI15_10_PRIORITY 5 + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_USB1 TRUE +#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE +#define STM32_USB_USB1_HP_IRQ_PRIORITY 6 +#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 diff --git a/testhal/STM32/I2C/tmp75.c b/testhal/STM32/I2C/tmp75.c index 4d9923881..cc1b2ca7f 100644 --- a/testhal/STM32/I2C/tmp75.c +++ b/testhal/STM32/I2C/tmp75.c @@ -15,6 +15,8 @@ // input buffer static i2cblock_t tmp75_rx_data[TMP75_RX_DEPTH]; static i2cblock_t tmp75_tx_data[TMP75_TX_DEPTH]; +// temperature value +static int16_t temperature = 0; // Simple error trap static void i2c_tmp75_error_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ @@ -26,47 +28,34 @@ static void i2c_tmp75_error_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ /* This callback raise up when transfer finished */ static void i2c_tmp75_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ - int16_t temperature = 0; - - /* Manually send stop signal to the bus. This is important! */ - i2cMasterStop(i2cp); - /* unlock bus */ - i2cReleaseBus(&I2CD2); - + (void)*i2cp; /* store temperature value */ temperature = (i2cscfg->rxbuf[0] << 8) + i2cscfg->rxbuf[1]; - } // Fill TMP75 config. static I2CSlaveConfig tmp75 = { i2c_tmp75_cb, i2c_tmp75_error_cb, + 0, + 0, tmp75_rx_data, - TMP75_RX_DEPTH, - 0, - 0, tmp75_tx_data, - TMP75_TX_DEPTH, - 0, - 0, 0b1001000, - FALSE, + 7, + 0, + 0, + {NULL}, }; /* This is main function. */ void request_temperature(void){ - tmp75.txbytes = 0; // set to zero just to be safe + tmp75.txbytes = 0; // set to zero because we need only reading + tmp75.rxbytes = 2; // we need to read 2 bytes - /* tune receiving buffer */ - tmp75.rxbufhead = 0;// point to beginig of buffer - tmp75.rxbytes = 2; // we need read 2 bytes - - /* get exclusive access to the bus */ i2cAcquireBus(&I2CD2); - - /* start receiving process in background and return */ i2cMasterReceive(&I2CD2, &tmp75); + i2cReleaseBus(&I2CD2); } From 140560ea821683cb52a483eb73ab671e2fc74520 Mon Sep 17 00:00:00 2001 From: barthess Date: Fri, 17 Jun 2011 07:32:57 +0000 Subject: [PATCH 44/92] I2C. Remove duplicate code. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3052 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 80 +++++++++----------------------- 1 file changed, 21 insertions(+), 59 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 2c535b930..4809838b7 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -106,7 +106,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { /* Disable ITEVT In order to not have again a BTF IT */ dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; /* send restart and begin reading operations */ - i2c_lld_master_transceive(i2cp); + i2c_lld_master_receive(i2cp); } break; @@ -524,12 +524,16 @@ void i2c_lld_master_transmit(I2CDriver *i2cp) { switch(i2cp->id_slave_config->nbit_address){ case 7: - i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) & 0x00FE); // LSB = 0 -> write + // LSB = 0 -> write + i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) & 0x00FE); break; case 10: - i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr >>7) & 0x0006); // add the two msb of 10-bit address to the header - i2cp->slave_addr1 |= 0xF0; // add the header bits with LSB = 0 -> write - i2cp->slave_addr2 = i2cp->id_slave_config->slave_addr & 0x00FF; // the remaining 8 bit of 10-bit address + // add the two msb of 10-bit address to the header + i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr >>7) & 0x0006); + // add the header bits with LSB = 0 -> write + i2cp->slave_addr1 |= 0xF0; + // the remaining 8 bit of 10-bit address + i2cp->slave_addr2 = i2cp->id_slave_config->slave_addr & 0x00FF; break; } @@ -539,7 +543,8 @@ void i2c_lld_master_transmit(I2CDriver *i2cp) { i2cp->id_i2c->CR1 |= I2C_CR1_START; // send start bit #if !I2C_USE_WAIT - /* Wait until the START condition is generated on the bus: the START bit is cleared by hardware */ + /* Wait until the START condition is generated on the bus: + * the START bit is cleared by hardware */ uint32_t timeout = 0xfffff; while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) ; @@ -561,12 +566,16 @@ void i2c_lld_master_receive(I2CDriver *i2cp){ switch(i2cp->id_slave_config->nbit_address){ case 7: - i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) | 0x01); // LSB = 1 -> receive + // LSB = 1 -> receive + i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) | 0x01); break; case 10: - i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr >>7) & 0x0006); // add the two msb of 10-bit address to the header - i2cp->slave_addr1 |= 0xF0; // add the header bits (the LSB -> 1 will be add to second - i2cp->slave_addr2 = i2cp->id_slave_config->slave_addr & 0x00FF; // the remaining 8 bit of 10-bit address + // add the two msb of 10-bit address to the header + i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr >>7) & 0x0006); + // add the header bits (the LSB -> 1 will be add to second + i2cp->slave_addr1 |= 0xF0; + // the remaining 8 bit of 10-bit address + i2cp->slave_addr2 = i2cp->id_slave_config->slave_addr & 0x00FF; break; } @@ -586,55 +595,8 @@ void i2c_lld_master_receive(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_START; // send start bit #if !I2C_USE_WAIT - /* Wait until the START condition is generated on the bus: the START bit is cleared by hardware */ - uint32_t timeout = 0xfffff; - while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) - ; -#endif /* I2C_USE_WAIT */ -} - - - -/** - * @brief - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - */ -void i2c_lld_master_transceive(I2CDriver *i2cp){ - // enable ERR, EVT & BUF ITs - i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); - i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // acknowledge returned - i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - - switch(i2cp->id_slave_config->nbit_address){ - case 7: - i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) | 0x01); // LSB = 1 -> receive - break; - case 10: - i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr >>7) & 0x0006); // add the two msb of 10-bit address to the header - i2cp->slave_addr1 |= 0xF0; // add the header bits (the LSB -> 1 will be add to second - i2cp->slave_addr2 = i2cp->id_slave_config->slave_addr & 0x00FF; // the remaining 8 bit of 10-bit address - break; - } - - i2cp->id_slave_config->flags = I2C_FLG_MASTER_RECEIVER; - i2cp->id_slave_config->errors = 0; - - // Only one byte to be received - if(i2cp->id_slave_config->rxbytes == 1) { - i2cp->id_slave_config->flags |= I2C_FLG_1BTR; - } - // Only two bytes to be received - else if(i2cp->id_slave_config->rxbytes == 2) { - i2cp->id_slave_config->flags |= I2C_FLG_2BTR; - i2cp->id_i2c->CR1 |= I2C_CR1_POS; // Acknowledge Position - } - - i2cp->id_i2c->CR1 |= I2C_CR1_START; // send start bit - -#if !I2C_USE_WAIT - /* Wait until the START condition is generated on the bus: the START bit is cleared by hardware */ + /* Wait until the START condition is generated on the bus: + * the START bit is cleared by hardware */ uint32_t timeout = 0xfffff; while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) ; From 9e2d63e9dca04b460e36674dcb681d55f8cea5df Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 18 Jun 2011 10:18:56 +0000 Subject: [PATCH 45/92] I2C. Deleted draft driver files git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3053 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c_albi.h | 185 -------- os/hal/include/i2c_brts.h | 248 ---------- os/hal/platforms/STM32/i2c_lld_albi.c | 574 ----------------------- os/hal/platforms/STM32/i2c_lld_albi.h | 263 ----------- os/hal/platforms/STM32/i2c_lld_brts.c | 626 ------------------------- os/hal/platforms/STM32/i2c_lld_btrts.h | 201 -------- os/hal/src/i2c_albi.c | 268 ----------- os/hal/src/i2c_brts.c | 249 ---------- 8 files changed, 2614 deletions(-) delete mode 100644 os/hal/include/i2c_albi.h delete mode 100644 os/hal/include/i2c_brts.h delete mode 100644 os/hal/platforms/STM32/i2c_lld_albi.c delete mode 100644 os/hal/platforms/STM32/i2c_lld_albi.h delete mode 100644 os/hal/platforms/STM32/i2c_lld_brts.c delete mode 100644 os/hal/platforms/STM32/i2c_lld_btrts.h delete mode 100644 os/hal/src/i2c_albi.c delete mode 100644 os/hal/src/i2c_brts.c diff --git a/os/hal/include/i2c_albi.h b/os/hal/include/i2c_albi.h deleted file mode 100644 index 30ec38548..000000000 --- a/os/hal/include/i2c_albi.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . -*/ - -/** - * @file i2c.h - * @brief I2C Driver macros and structures. - * - * @addtogroup I2C - * @{ - */ - -#ifndef I2C_H_ -#define I2C_H_ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ -#define I2CD_NO_ERROR 0 -/** @brief Bus Error.*/ -#define I2CD_BUS_ERROR 0x01 -/** @brief Arbitration Lost (master mode).*/ -#define I2CD_ARBITRATION_LOST 0x02 -/** @brief Acknowledge Failure.*/ -#define I2CD_ACK_FAILURE 0x04 -/** @brief Overrun/Underrun.*/ -#define I2CD_OVERRUN 0x08 -/** @brief PEC Error in reception.*/ -#define I2CD_PEC_ERROR 0x10 -/** @brief Timeout or Tlow Error.*/ -#define I2CD_TIMEOUT 0x20 -/** @brief SMBus Alert.*/ -#define I2CD_SMB_ALERT 0x40 - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(I2C_USE_WAIT) || defined(__DOXYGEN__) -#define I2C_USE_WAIT TRUE -#endif - -/** - * @brief Enables the mutual exclusion APIs on the I2C bus. - */ -#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define I2C_USE_MUTUAL_EXCLUSION FALSE -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if I2C_USE_MUTUAL_EXCLUSION && !CH_USE_MUTEXES && !CH_USE_SEMAPHORES -#error "I2C_USE_MUTUAL_EXCLUSION requires CH_USE_MUTEXES and/or CH_USE_SEMAPHORES" -#endif - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - I2C_UNINIT = 0, /**< @brief Not initialized. */ - I2C_STOP = 1, /**< @brief Stopped. */ - I2C_READY = 2, /**< @brief Ready. */ - I2C_ACTIVE = 3, /**< @brief In communication. */ - I2C_COMPLETE = 4 /**< @brief Asynchronous operation complete. */ -} i2cstate_t; - -#include "i2c_lld.h" - -#if I2C_USE_WAIT || defined(__DOXYGEN__) -/** - * @brief Waits for operation completion. - * @details This function waits for the driver to complete the current - * operation. - * @pre An operation must be running while the function is invoked. - * @note No more than one thread can wait on a I2C driver using - * this function. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define _i2c_wait_s(i2cp) { \ - chDbgAssert((i2cp)->thread == NULL, \ - "_i2c_wait(), #1", "already waiting"); \ - (i2cp)->thread = chThdSelf(); \ - chSchGoSleepS(THD_STATE_SUSPENDED); \ -} - -/** - * @brief Wakes up the waiting thread. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define _i2c_wakeup_isr(i2cp) { \ - if ((i2cp)->thread != NULL) { \ - Thread *tp = (i2cp)->thread; \ - (i2cp)->thread = NULL; \ - chSysLockFromIsr(); \ - chSchReadyI(tp); \ - chSysUnlockFromIsr(); \ - } \ -} -#else /* !I2C_USE_WAIT */ -#define _i2c_wait_s(i2cp) -#define _i2c_wakeup_isr(i2cp) -#endif /* !I2C_USE_WAIT */ - -/** - * @brief Common ISR code. - * @details This code handles the portable part of the ISR code: - * - Callback invocation. - * - Waiting thread wakeup, if any. - * - Driver state transitions. - * . - * @note This macro is meant to be used in the low level drivers - * implementation only. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define _i2c_isr_code(i2cp) { \ - (i2cp)->state = I2C_COMPLETE; \ - if((i2cp)->endcb) { \ - (i2cp)->endcb(i2cp); \ - } \ - _i2c_wakeup_isr(i2cp); \ -} - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void i2cInit(void); - void i2cObjectInit(I2CDriver *i2cp); - void i2cStart(I2CDriver *i2cp, const I2CConfig *config); - void i2cStop(I2CDriver *i2cp); - void i2cMasterTransmit(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *txbuf); - void i2cMasterReceive(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *rxbuf); - void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask); - i2cflags_t i2cGetAndClearFlags(I2CDriver *i2cp); - uint16_t i2cSMBusAlertResponse(I2CDriver *i2cp); - -#if I2C_USE_MUTUAL_EXCLUSION - void i2cAcquireBus(I2CDriver *i2cp); - void i2cReleaseBus(I2CDriver *i2cp); -#endif /* I2C_USE_MUTUAL_EXCLUSION */ -#ifdef __cplusplus -} -#endif - - -#endif /* CH_HAL_USE_I2C */ - -#endif /* I2C_H_ */ diff --git a/os/hal/include/i2c_brts.h b/os/hal/include/i2c_brts.h deleted file mode 100644 index a01606a18..000000000 --- a/os/hal/include/i2c_brts.h +++ /dev/null @@ -1,248 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . -*/ - -/** - * @file i2c.h - * @brief I2C Driver macros and structures. - * - * @addtogroup I2C - * @{ - */ - -#ifndef _I2C_H_ -#define _I2C_H_ - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief Enables the mutual exclusion APIs on the I2C bus. - */ -#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define I2C_USE_MUTUAL_EXCLUSION TRUE -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - I2C_UNINIT = 0, /**< Not initialized. */ - I2C_STOP = 1, /**< Stopped. */ - I2C_READY = 2, /**< Ready. Start condition generated. */ - I2C_MACTIVE = 3, /**< I2C configured and waiting start cond. */ - I2C_10BIT_HANDSHAKE = 4, /**< 10-bit address sending */ - I2C_MWAIT_ADDR_ACK = 5, /**< Waiting ACK on address sending. */ - I2C_MTRANSMIT = 6, /**< Master transmitting. */ - I2C_MRECEIVE = 7, /**< Master receiving. */ - I2C_MWAIT_TF = 8, /**< Master wait Transmission Finished */ - I2C_MERROR = 9, /**< Error condition. */ - - // slave part - I2C_SACTIVE = 10, - I2C_STRANSMIT = 11, - I2C_SRECEIVE = 12, -} i2cstate_t; - - -#include "i2c_lld.h" - -/** - * @brief I2C notification callback type. - * @details This callback invoked when byte transfer finish event occurs, - * No matter sending or reading. This function designed - * for sending (re)start or stop events to I2C bus from user level. - * - * If callback function is set to NULL - driver atomaticcaly - * generate stop condition after the transfer finish. - * - * @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, 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, 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, or - * by DMA buffer events - * 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; - - /** - * @brief Receive and transmit buffers. - */ - i2cblock_t *rxbuf; /*!< Pointer to receive buffer. */ - size_t rxdepth; /*!< Depth of buffer. */ - size_t rxbytes; /*!< Number of bytes to be receive in one transmission. */ - size_t rxbufhead; /*!< Pointer to current data byte. */ - - i2cblock_t *txbuf; /*!< Pointer to transmit buffer.*/ - size_t txdepth; /*!< Depth of buffer. */ - size_t txbytes; /*!< Number of bytes to be transmit in one transmission. */ - size_t txbufhead; /*!< Pointer to current data byte. */ - - /** - * @brief Contain slave address and some flags. - * @details Bits 0..9 contain slave address in 10-bit mode. - * - * Bits 0..6 contain slave address in 7-bit mode. - * - * Bits 10..14 are not used in 10-bit mode. - * Bits 7..14 are not used in 7-bit mode. - * - * Bit 15 is used to switch between 10-bit and 7-bit modes - * (0 denotes 7-bit mode). - */ - uint16_t address; - - /** - * @brief Boolean flag for dealing with start/stop conditions. - * @note This flag destined to use in callback functions. It place here - * for convenience and flexibility reasons, but you can use your - * own variable from user level code. - */ - bool_t restart; - - -#if I2C_USE_WAIT - /** - * @brief Thread waiting for I/O completion. - */ - Thread *thread; -#endif /* I2C_USE_WAIT */ -}; - - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Read mode. - */ -#define I2C_READ 1 - -/** - * @brief Write mode. - */ -#define I2C_WRITE 0 - -/** - * @brief Seven bits addresses header builder. - * - * @param[in] addr seven bits address value - * @param[in] rw read/write flag - * - * @return A 16 bit value representing the header, the most - * significant byte is always zero. - */ -#define I2C_ADDR7(addr, rw) (uint16_t)((addr) << 1 | (rw)) - - -/** - * @brief Ten bits addresses header builder. - * - * @param[in] addr ten bits address value - * @param[in] rw read/write flag - * - * @return A 16 bit value representing the header, the most - * significant byte is the first one to be transmitted. - */ -#define I2C_ADDR10(addr, rw) \ - (uint16_t)(0xF000 | \ - (((addr) & 0x0300) << 1) | \ - (((rw) << 8)) | \ - ((addr) & 0x00FF)) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ -#ifdef __cplusplus -extern "C" { -#endif - void i2cInit(void); - void i2cObjectInit(I2CDriver *i2cp); - void i2cStart(I2CDriver *i2cp, I2CConfig *config); - void i2cStop(I2CDriver *i2cp); - void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); - void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); - void i2cMasterStart(I2CDriver *i2cp); - void i2cMasterStop(I2CDriver *i2cp); - -#if I2C_USE_MUTUAL_EXCLUSION - void i2cAcquireBus(I2CDriver *i2cp); - void i2cReleaseBus(I2CDriver *i2cp); -#endif /* I2C_USE_MUTUAL_EXCLUSION */ -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_I2C */ - -#endif /* _I2C_H_ */ - -/** @} */ diff --git a/os/hal/platforms/STM32/i2c_lld_albi.c b/os/hal/platforms/STM32/i2c_lld_albi.c deleted file mode 100644 index cd6a851db..000000000 --- a/os/hal/platforms/STM32/i2c_lld_albi.c +++ /dev/null @@ -1,574 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . -*/ - -/** - * @file STM32/i2c_lld.c - * @brief STM32 I2C subsystem low level driver source. Slave mode not implemented. - * @addtogroup STM32_I2C - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief I2C1 driver identifier.*/ -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -I2CDriver I2CD1; -#endif - -/** @brief I2C2 driver identifier.*/ -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -I2CDriver I2CD2; -#endif - - -static uint32_t i2c_get_event(I2CDriver *i2cp){ - uint32_t regSR1 = i2cp->i2c_register->SR1; - uint32_t regSR2 = i2cp->i2c_register->SR2; - /* return the last event value from I2C status registers */ - return (I2C_EV_MASK & (regSR1 | (regSR2 << 16))); -} - -static void i2c_serve_event_interrupt(I2CDriver *i2cp) { - static __IO uint8_t *txBuffp, *rxBuffp, *datap; - - I2C_TypeDef *dp = i2cp->i2c_register; - - switch(i2c_get_event(i2cp)) { - case I2C_EV5_MASTER_MODE_SELECT: - i2cp->flags &= ~I2C_FLG_HEADER_SENT; - dp->DR = i2cp->slave_addr1; - break; - case I2C_EV9_MASTER_ADDR_10BIT: - if(i2cp->flags & I2C_FLG_MASTER_RECEIVER) { - i2cp->slave_addr1 |= 0x01; - i2cp->flags |= I2C_FLG_HEADER_SENT; - } - dp->DR = i2cp->slave_addr2; - break; - //------------------------------------------------------------------------ - // Master Transmitter ---------------------------------------------------- - //------------------------------------------------------------------------ - case I2C_EV6_MASTER_TRA_MODE_SELECTED: - if(i2cp->flags & I2C_FLG_HEADER_SENT){ - dp->CR1 |= I2C_CR1_START; // re-send the start in 10-Bit address mode - break; - } - //Initialize the transmit buffer pointer - txBuffp = (uint8_t*)i2cp->txbuf; - datap = txBuffp; - txBuffp++; - i2cp->remaining_bytes--; - /* If no further data to be sent, disable the I2C ITBUF in order to not have a TxE interrupt */ - if(i2cp->remaining_bytes == 0) { - dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - } - //EV8_1 write the first data - dp->DR = *datap; - break; - case I2C_EV8_MASTER_BYTE_TRANSMITTING: - if(i2cp->remaining_bytes > 0) { - datap = txBuffp; - txBuffp++; - i2cp->remaining_bytes--; - if(i2cp->remaining_bytes == 0) { - /* If no further data to be sent, disable the ITBUF in order to not have a TxE interrupt */ - dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - } - dp->DR = *datap; - } - break; - case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: - dp->CR1 |= I2C_CR1_STOP; // stop generation - /* Disable ITEVT In order to not have again a BTF IT */ - dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; - /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ - _i2c_isr_code(i2cp); - break; - //------------------------------------------------------------------------ - // Master Receiver ------------------------------------------------------- - //------------------------------------------------------------------------ - case I2C_EV6_MASTER_REC_MODE_SELECTED: - chSysLockFromIsr(); - switch(i2cp->flags & EV6_SUBEV_MASK) { - case I2C_EV6_3_MASTER_REC_1BTR_MODE_SELECTED: // only an single byte to receive - /* Clear ACK */ - dp->CR1 &= (uint16_t)~I2C_CR1_ACK; - /* Program the STOP */ - dp->CR1 |= I2C_CR1_STOP; - break; - case I2C_EV6_1_MASTER_REC_2BTR_MODE_SELECTED: // only two bytes to receive - /* Clear ACK */ - dp->CR1 &= (uint16_t)~I2C_CR1_ACK; - /* Disable the ITBUF in order to have only the BTF interrupt */ - dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - break; - } - chSysUnlockFromIsr(); - /* Initialize receive buffer pointer */ - rxBuffp = i2cp->rxbuf; - break; - case I2C_EV7_MASTER_REC_BYTE_RECEIVED: - if(i2cp->remaining_bytes != 3) { - /* Read the data register */ - *rxBuffp = dp->DR; - rxBuffp++; - i2cp->remaining_bytes--; - switch(i2cp->remaining_bytes){ - case 3: - /* Disable the ITBUF in order to have only the BTF interrupt */ - dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - i2cp->flags |= I2C_FLG_3BTR; - break; - case 0: - /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ - _i2c_isr_code(i2cp); - break; - } - } - // when remaining 3 bytes do nothing, wait until RXNE and BTF are set (until 2 bytes are received) - break; - case I2C_EV7_MASTER_REC_BYTE_QUEUED: - switch(i2cp->flags & EV7_SUBEV_MASK) { - case I2C_EV7_2_MASTER_REC_3BYTES_TO_PROCESS: - // DataN-2 and DataN-1 are received - chSysLockFromIsr(); - dp->CR2 |= I2C_CR2_ITBUFEN; - /* Clear ACK */ - dp->CR1 &= (uint16_t)~I2C_CR1_ACK; - /* Read the DataN-2*/ - *rxBuffp = dp->DR; //This clear the RXE & BFT flags and launch the DataN reception in the shift register (ending the SCL stretch) - rxBuffp++; - /* Program the STOP */ - dp->CR1 |= I2C_CR1_STOP; - /* Read the DataN-1 */ - *rxBuffp = dp->DR; - chSysUnlockFromIsr(); - rxBuffp++; - /* Decrement the number of readed bytes */ - i2cp->remaining_bytes -= 2; - i2cp->flags = 0; - // ready for read DataN on the next EV7 - break; - case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: // only for case of two bytes to be received - // DataN-1 and DataN are received - chSysLockFromIsr(); - /* Program the STOP */ - dp->CR1 |= I2C_CR1_STOP; - /* Read the DataN-1*/ - *rxBuffp = dp->DR; - chSysUnlockFromIsr(); - rxBuffp++; - /* Read the DataN*/ - *rxBuffp = dp->DR; - i2cp->remaining_bytes = 0; - i2cp->flags = 0; - /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ - _i2c_isr_code(i2cp); - break; - } - break; - } -} - -static void i2c_serve_error_interrupt(I2CDriver *i2cp) { - i2cflags_t flags; - I2C_TypeDef *reg; - - reg = i2cp->i2c_register; - flags = I2CD_NO_ERROR; - - if(reg->SR1 & I2C_SR1_BERR) { // Bus error - reg->SR1 &= ~I2C_SR1_BERR; - flags |= I2CD_BUS_ERROR; - } - if(reg->SR1 & I2C_SR1_ARLO) { // Arbitration lost - reg->SR1 &= ~I2C_SR1_ARLO; - flags |= I2CD_ARBITRATION_LOST; - } - if(reg->SR1 & I2C_SR1_AF) { // Acknowledge fail - reg->SR1 &= ~I2C_SR1_AF; - reg->CR1 |= I2C_CR1_STOP; // setting stop bit - flags |= I2CD_ACK_FAILURE; - } - if(reg->SR1 & I2C_SR1_OVR) { // Overrun - reg->SR1 &= ~I2C_SR1_OVR; - flags |= I2CD_OVERRUN; - } - if(reg->SR1 & I2C_SR1_PECERR) { // PEC error - reg->SR1 &= ~I2C_SR1_PECERR; - flags |= I2CD_PEC_ERROR; - } - if(reg->SR1 & I2C_SR1_TIMEOUT) { // SMBus Timeout - reg->SR1 &= ~I2C_SR1_TIMEOUT; - flags |= I2CD_TIMEOUT; - } - if(reg->SR1 & I2C_SR1_SMBALERT) { // SMBus alert - reg->SR1 &= ~I2C_SR1_SMBALERT; - flags |= I2CD_SMB_ALERT; - } - - if(flags != I2CD_NO_ERROR) { - // send communication end signal - _i2c_isr_code(i2cp); - chSysLockFromIsr(); - i2cAddFlagsI(i2cp, flags); - chSysUnlockFromIsr(); - } -} - -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -/** - * @brief I2C1 event interrupt handler. - */ -CH_IRQ_HANDLER(I2C1_EV_IRQHandler) { - - CH_IRQ_PROLOGUE(); - i2c_serve_event_interrupt(&I2CD1); - CH_IRQ_EPILOGUE(); -} - -/** - * @brief I2C1 error interrupt handler. - */ -CH_IRQ_HANDLER(I2C1_ER_IRQHandler) { - - CH_IRQ_PROLOGUE(); - i2c_serve_error_interrupt(&I2CD1); - CH_IRQ_EPILOGUE(); -} -#endif - -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -/** - * @brief I2C2 event interrupt handler. - */ -CH_IRQ_HANDLER(I2C2_EV_IRQHandler) { - - CH_IRQ_PROLOGUE(); - i2c_serve_event_interrupt(&I2CD2); - CH_IRQ_EPILOGUE(); -} - -/** - * @brief I2C2 error interrupt handler. - */ -CH_IRQ_HANDLER(I2C2_ER_IRQHandler) { - - CH_IRQ_PROLOGUE(); - i2c_serve_error_interrupt(&I2CD2); - CH_IRQ_EPILOGUE(); -} -#endif - -void i2c_lld_reset(I2CDriver *i2cp){ - chDbgCheck((i2cp->state == I2C_STOP)||(i2cp->state == I2C_READY), - "i2c_lld_reset: invalid state"); - - RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; // reset I2C 1 - RCC->APB1RSTR = 0; -} - -void i2c_lld_set_clock(I2CDriver *i2cp, int32_t clock_speed, I2C_DutyCycle_t duty) { - volatile uint16_t regCCR, regCR2, freq, clock_div; - volatile uint16_t pe_bit_saved; - - chDbgCheck((i2cp != NULL) && (clock_speed > 0) && (clock_speed <= 4000000), - "i2c_lld_set_clock"); - - /*---------------------------- CR2 Configuration ------------------------*/ - /* Get the I2Cx CR2 value */ - regCR2 = i2cp->i2c_register->CR2; - /* Clear frequency FREQ[5:0] bits */ - regCR2 &= (uint16_t)~I2C_CR2_FREQ; - /* Set frequency bits depending on pclk1 value */ - freq = (uint16_t)(STM32_PCLK1 / 1000000); - chDbgCheck((freq >= 2) && (freq <= 36), - "i2c_lld_set_clock() : Peripheral clock freq. out of range"); - regCR2 |= freq; - i2cp->i2c_register->CR2 = regCR2; - - /*---------------------------- CCR Configuration ------------------------*/ - pe_bit_saved = (i2cp->i2c_register->CR1 & I2C_CR1_PE); - /* Disable the selected I2C peripheral to configure TRISE */ - i2cp->i2c_register->CR1 &= (uint16_t)~I2C_CR1_PE; - - /* Clear F/S, DUTY and CCR[11:0] bits */ - regCCR = 0; - clock_div = I2C_CCR_CCR; - /* Configure clock_div in standard mode */ - if (clock_speed <= 100000) { - chDbgAssert(duty == stdDutyCycle, - "i2c_lld_set_clock(), #3", "Invalid standard mode duty cycle"); - /* Standard mode clock_div calculate: Tlow/Thigh = 1/1 */ - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2)); - /* Test if CCR value is under 0x4, and set the minimum allowed value */ - if (clock_div < 0x04) clock_div = 0x04; - /* Set clock_div value for standard mode */ - regCCR |= (clock_div & I2C_CCR_CCR); - /* Set Maximum Rise Time for standard mode */ - i2cp->i2c_register->TRISE = freq + 1; - } - /* Configure clock_div in fast mode */ - else if(clock_speed <= 400000) { - chDbgAssert((duty == fastDutyCycle_2) || (duty == fastDutyCycle_16_9), - "i2c_lld_set_clock(), #3", "Invalid fast mode duty cycle"); - if(duty == fastDutyCycle_2) { - /* Fast mode clock_div calculate: Tlow/Thigh = 2/1 */ - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3)); - } - else if(duty == fastDutyCycle_16_9) { - /* Fast mode clock_div calculate: Tlow/Thigh = 16/9 */ - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 25)); - /* Set DUTY bit */ - regCCR |= I2C_CCR_DUTY; - } - /* Test if CCR value is under 0x1, and set the minimum allowed value */ - if(clock_div < 0x01) clock_div = 0x01; - /* Set clock_div value and F/S bit for fast mode*/ - regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR)); - /* Set Maximum Rise Time for fast mode */ - i2cp->i2c_register->TRISE = (freq * 300 / 1000) + 1; - } - chDbgAssert((clock_div <= I2C_CCR_CCR), - "i2c_lld_set_clock(), #2", "Too low clock clock speed selected"); - - /* Write to I2Cx CCR */ - i2cp->i2c_register->CCR = regCCR; - - /* restore the I2C peripheral enabled state */ - i2cp->i2c_register->CR1 |= pe_bit_saved; -} - -void i2c_lld_set_opmode(I2CDriver *i2cp, I2C_opMode_t opmode) { - uint16_t regCR1; - - /*---------------------------- CR1 Configuration ------------------------*/ - /* Get the I2Cx CR1 value */ - regCR1 = i2cp->i2c_register->CR1; - switch(opmode){ - case opmodeI2C: - regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); - break; - case opmodeSMBusDevice: - regCR1 |= I2C_CR1_SMBUS; - regCR1 &= (uint16_t)~(I2C_CR1_SMBTYPE); - break; - case opmodeSMBusHost: - regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); - break; - } - /* Write to I2Cx CR1 */ - i2cp->i2c_register->CR1 = regCR1; -} - -void i2c_lld_set_own_address(I2CDriver *i2cp, int16_t address, int8_t nbit_addr) { - /*---------------------------- OAR1 Configuration -----------------------*/ - /* Set the Own Address1 and bit number address acknowledged */ - i2cp->i2c_register->OAR1 = address & I2C_OAR1_ADD0_9; - switch(nbit_addr) { - case 10: - i2cp->i2c_register->OAR1 |= I2C_OAR1_ADDMODE; // set ADDMODE bit and bit 14. - case 7: - i2cp->i2c_register->OAR1 |= I2C_OAR1_BIT14; // set only bit 14. - } -} - -/** - * @brief Low level I2C driver initialization. - */ -void i2c_lld_init(void) { - -#if STM32_I2C_USE_I2C1 - RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; // reset I2C 1 - RCC->APB1RSTR = 0; - i2cObjectInit(&I2CD1); - I2CD1.i2c_register = I2C1; -#endif -#if STM32_I2C_USE_I2C2 - RCC->APB1RSTR = RCC_APB1RSTR_I2C2RST; // reset I2C 2 - RCC->APB1RSTR = 0; - i2cObjectInit(&I2CD2); - I2CD2.i2c_register = I2C2; -#endif -} - -/** - * @brief Configures and activates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2c_lld_start(I2CDriver *i2cp) { - chDbgCheck((i2cp->state == I2C_STOP)||(i2cp->state == I2C_READY), - "i2c_lld_start: invalid state"); - - /* If in stopped state then enables the I2C clock.*/ - if (i2cp->state == I2C_STOP) { -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - NVICEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); - NVICEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); - RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // I2C 1 clock enable - } -#endif -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - NVICEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); - NVICEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); - RCC->APB1ENR |= RCC_APB1ENR_I2C2EN; // I2C 2 clock enable - } -#endif - i2cp->i2c_register->CR1 |= I2C_CR1_PE; // enable I2C peripheral - } -} - -/** - * @brief Deactivates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2c_lld_stop(I2CDriver *i2cp) { - - chDbgCheck((i2cp->state == I2C_READY), - "i2c_lld_stop: invalid state"); - - /* I2C disable.*/ - i2cp->i2c_register->CR1 = 0; - - /* If in ready state then disables the I2C clock.*/ - if (i2cp->state == I2C_READY) { -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - NVICDisableVector(I2C1_EV_IRQn); - NVICDisableVector(I2C1_ER_IRQn); - RCC->APB1ENR &= ~RCC_APB1ENR_I2C1EN; - } -#endif -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - NVICDisableVector(I2C2_EV_IRQn); - NVICDisableVector(I2C2_ER_IRQn); - RCC->APB1ENR &= ~RCC_APB1ENR_I2C2EN; - } -#endif - } -} - -/** - * @brief Transmits data ever the I2C bus as master. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] n number of words to send - * @param[in] slave_addr1 the 7-bit address of the slave (should be aligned to left) - * @param[in] slave_addr2 used in 10 bit address mode - * @param[in] txbuf the pointer to the transmit buffer - * - */ -void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *txbuf) { - - // enable ERR, EVT & BUF ITs - i2cp->i2c_register->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); - i2cp->i2c_register->CR1 &= ~I2C_CR1_POS; - - switch(i2cp->nbit_address){ - case 7: - i2cp->slave_addr1 = ((slave_addr <<1) & 0x00FE); // LSB = 0 -> write - break; - case 10: - i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); // add the two msb of 10-bit address to the header - i2cp->slave_addr1 |= 0xF0; // add the header bits with LSB = 0 -> write - i2cp->slave_addr2 = slave_addr & 0x00FF; // the remaining 8 bit of 10-bit address - break; - } - - i2cp->txbuf = txbuf; - i2cp->remaining_bytes = n; - i2cp->flags = 0; - i2cp->errors = 0; - - i2cp->i2c_register->CR1 |= I2C_CR1_START; // send start bit - -#if !I2C_USE_WAIT - /* Wait until the START condition is generated on the bus: the START bit is cleared by hardware */ - uint32_t tmo = 0xfffff; - while((i2cp->i2c_register->CR1 & I2C_CR1_START) && tmo--) - ; -#endif /* I2C_USE_WAIT */ -} - -/** - * @brief Receives data from the I2C bus. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] slave_addr1 7-bit address of he slave - * @param[in] slave_addr2 used in 10-bit address mode - * @param[in] n number of words to receive - * @param[out] rxbuf the pointer to the receive buffer - * - */ -void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *rxbuf) { - // enable ERR, EVT & BUF ITs - i2cp->i2c_register->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); - i2cp->i2c_register->CR1 |= I2C_CR1_ACK; // acknowledge returned - i2cp->i2c_register->CR1 &= ~I2C_CR1_POS; - - switch(i2cp->nbit_address){ - case 7: - i2cp->slave_addr1 = ((slave_addr <<1) | 0x01); // LSB = 1 -> receive - break; - case 10: - i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); // add the two msb of 10-bit address to the header - i2cp->slave_addr1 |= 0xF0; // add the header bits (the LSB -> 1 will be add to second - i2cp->slave_addr2 = slave_addr & 0x00FF; // the remaining 8 bit of 10-bit address - break; - } - - i2cp->rxbuf = rxbuf; - i2cp->remaining_bytes = n; - i2cp->flags = I2C_FLG_MASTER_RECEIVER; - i2cp->errors = 0; - - // Only one byte to be received - if(i2cp->remaining_bytes == 1) { - i2cp->flags |= I2C_FLG_1BTR; - } - // Only two bytes to be received - else if(i2cp->remaining_bytes == 2) { - i2cp->flags |= I2C_FLG_2BTR; - i2cp->i2c_register->CR1 |= I2C_CR1_POS; // Acknowledge Position - } - - i2cp->i2c_register->CR1 |= I2C_CR1_START; // send start bit - -#if !I2C_USE_WAIT - /* Wait until the START condition is generated on the bus: the START bit is cleared by hardware */ - uint32_t tmo = 0xfffff; - while((i2cp->i2c_register->CR1 & I2C_CR1_START) && tmo--) - ; -#endif /* I2C_USE_WAIT */ -} - -#endif // HAL_USE_I2C - diff --git a/os/hal/platforms/STM32/i2c_lld_albi.h b/os/hal/platforms/STM32/i2c_lld_albi.h deleted file mode 100644 index 2b63afec9..000000000 --- a/os/hal/platforms/STM32/i2c_lld_albi.h +++ /dev/null @@ -1,263 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . -*/ - - -/** - * @file STM32/i2c_lld.h - * @brief STM32 I2C subsystem low level driver header. - * @addtogroup STM32_I2C - * @{ - */ - -#ifndef _I2C_LLD_H_ -#define _I2C_LLD_H_ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ -#define I2C_OAR1_ADD0_9 ((uint16_t)0x03FF) /*!= @p STM32_I2C1_IRQ_PRIORITY > @p PRIORITY_PENDSV. - */ -#if !defined(STM32_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C1_IRQ_PRIORITY 0xA0 -#endif - -/** - * @brief I2C2 interrupt priority level setting. - * @note @p BASEPRI_KERNEL >= @p STM32_I2C2_IRQ_PRIORITY > @p PRIORITY_PENDSV. - */ -#if !defined(STM32_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_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 - -#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 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 Serial Driver condition flags type. - */ -typedef uint32_t i2cflags_t; - -typedef enum { - opmodeI2C, - opmodeSMBusDevice, - opmodeSMBusHost, -} I2C_opMode_t; - -typedef enum { - stdDutyCycle, - fastDutyCycle_2, - fastDutyCycle_16_9, -} I2C_DutyCycle_t; - -/** - * @brief Type of a structure representing an SPI driver. - */ -typedef struct I2CDriver I2CDriver; - -/** - * @brief I2C notification callback type. - * - * @param[in] i2cp pointer to the @p I2CDriver object triggering the - * callback - */ -typedef void (*i2ccallback_t)(I2CDriver *i2cp); - -/** - * @brief Driver configuration structure. - */ -typedef struct { - I2C_opMode_t opMode; /*!< Specifies the I2C mode.*/ - - uint32_t ClockSpeed; /*!< Specifies the clock frequency. Must be set to a value lower than 400kHz */ - - I2C_DutyCycle_t FastModeDutyCycle; /*!< Specifies the I2C fast mode duty cycle */ - - uint16_t OwnAddress1; /*!< Specifies the first device own address. Can be a 7-bit or 10-bit address. */ - - uint16_t Ack; /*!< Enables or disables the acknowledgement. */ - - uint8_t nBitAddress; /*!< Specifies if 7-bit or 10-bit address is acknowledged */ - -} I2CConfig; - -/** - * @brief Structure representing an I2C driver. - */ -struct I2CDriver { - /** - * @brief Driver state. - */ - i2cstate_t state; - /** - * @brief Operation complete callback or @p NULL. - */ - i2ccallback_t endcb; -#if I2C_USE_WAIT - /** - * @brief Thread waiting for I/O completion. - */ - Thread *thread; -#endif /* I2C_USE_WAIT */ -#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) -#if CH_USE_MUTEXES || defined(__DOXYGEN__) - /** - * @brief Mutex protecting the bus. - */ - Mutex mutex; -#elif CH_USE_SEMAPHORES - Semaphore semaphore; -#endif -#endif /* I2C_USE_MUTUAL_EXCLUSION */ - - /* End of the mandatory fields.*/ - /** - * @brief Pointer to the I2Cx registers block. - */ - I2C_TypeDef *i2c_register; - size_t remaining_bytes; - uint8_t *rxbuf; - uint8_t *txbuf; - uint8_t slave_addr1; // 7-bit address of the slave - uint8_t slave_addr2; // used in 10-bit address mode - uint8_t nbit_address; - i2cflags_t errors; - i2cflags_t flags; - /* Status Change @p EventSource.*/ - EventSource sevent; -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -#define i2c_lld_bus_is_busy(i2cp) \ - (i2cp->i2c_register->SR2 & I2C_SR2_BUSY) - - -/* Wait until BUSY flag is reset: a STOP has been generated on the bus - * signaling the end of transmission - */ -#define i2c_lld_wait_bus_free(i2cp) { \ - uint32_t tmo = 0xffff; \ - while((i2cp->i2c_register->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, int32_t clock_speed, I2C_DutyCycle_t duty); -void i2c_lld_set_opmode(I2CDriver *i2cp, I2C_opMode_t opmode); -void i2c_lld_set_own_address(I2CDriver *i2cp, int16_t address, int8_t nr_bit); -void i2c_lld_start(I2CDriver *i2cp); -void i2c_lld_stop(I2CDriver *i2cp); -void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *txbuf); -void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *rxbuf); - -#ifdef __cplusplus -} -#endif -/** @endcond*/ - -#endif // CH_HAL_USE_I2C - -#endif // _I2C_LLD_H_ diff --git a/os/hal/platforms/STM32/i2c_lld_brts.c b/os/hal/platforms/STM32/i2c_lld_brts.c deleted file mode 100644 index 1ac7e4309..000000000 --- a/os/hal/platforms/STM32/i2c_lld_brts.c +++ /dev/null @@ -1,626 +0,0 @@ -/** - * @file STM32/i2c_lld.c - * @brief STM32 I2C subsystem low level driver source. Slave mode not implemented. - * @addtogroup STM32_I2C - * @{ - */ - -#include "ch.h" -#include "hal.h" -#include "i2c_lld.h" - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief I2C1 driver identifier.*/ -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -I2CDriver I2CD1; -#endif - -/** @brief I2C2 driver identifier.*/ -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -I2CDriver I2CD2; -#endif - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Interrupt service routine. - * @details This function handle all ERROR interrupt conditions. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -static void i2c_serve_error_interrupt(I2CDriver *i2cp) { - //TODO: more robust error handling - chSysLockFromIsr(); - i2cp->id_slave_config->id_err_callback(i2cp, i2cp->id_slave_config); - chSysUnlockFromIsr(); -} - -/* helper function, not API - * write bytes in DR register - * return TRUE if last byte written - */ -inline bool_t i2c_lld_txbyte(I2CDriver *i2cp) { -#define _txbufhead (i2cp->id_slave_config->txbufhead) -#define _txbytes (i2cp->id_slave_config->txbytes) -#define _txbuf (i2cp->id_slave_config->txbuf) - - if (_txbufhead < _txbytes){ - /* disable interrupt to avoid jumping to ISR */ - if ( _txbytes - _txbufhead == 1) - i2cp->id_i2c->CR2 &= (~I2C_CR2_ITBUFEN); - i2cp->id_i2c->DR = _txbuf[_txbufhead]; - (_txbufhead)++; - return(FALSE); - } - _txbufhead = 0; - return(TRUE); // last byte written -#undef _txbufhead -#undef _txbytes -#undef _txbuf -} - - -/* helper function, not API - * read bytes from DR register - * return TRUE if last byte read - */ -inline bool_t i2c_lld_rxbyte(I2CDriver *i2cp) { - // temporal variables -#define _rxbuf (i2cp->id_slave_config->rxbuf) -#define _rxbufhead (i2cp->id_slave_config->rxbufhead) -#define _rxbytes (i2cp->id_slave_config->rxbytes) - - /* In order to generate the non-acknowledge pulse after the last received - * data byte, the ACK bit must be cleared just after reading the second - * last data byte (after second last RxNE event). - */ - if (_rxbufhead < (_rxbytes - 1)){ - _rxbuf[_rxbufhead] = i2cp->id_i2c->DR; - if ((_rxbytes - _rxbufhead) <= 2){ - // clear ACK bit for automatically send NACK - i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK); - } - (_rxbufhead)++; - return(FALSE); - } - /* disable interrupt to avoid jumping to ISR */ - i2cp->id_i2c->CR2 &= (~I2C_CR2_ITBUFEN); - - _rxbuf[_rxbufhead] = i2cp->id_i2c->DR; // read last byte - _rxbufhead = 0; - return(TRUE); // last byte read - -#undef _rxbuf -#undef _rxbufhead -#undef _rxbytes -} - - -/** - * @brief Interrupt service routine. - * @details This function handle all regular interrupt conditions. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -static void i2c_serve_event_interrupt(I2CDriver *i2cp) { - -#if CH_DBG_ENABLE_CHECKS - // debug variables - int i = 0; - int n = 0; - int m = 0; -#endif - - /* In 10-bit addressing mode, - – To enter Transmitter mode, a master sends the header (11110xx0) and then the - slave address, (where xx denotes the two most significant bits of the address). - – To enter Receiver mode, a master sends the header (11110xx0) and then the - slave address. Then it should send a repeated Start condition followed by the - header (11110xx1), (where xx denotes the two most significant bits of the - address). - The TRA bit indicates whether the master is in Receiver or Transmitter mode.*/ - - if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent - i2cp->id_state = I2C_MACTIVE; - - if(!(i2cp->id_slave_config->address & 0x8000)){ // slave address is 7-bit - i2cp->id_i2c->DR = ((i2cp->id_slave_config->address & 0x7F) << 1) | - i2cp->rw_bit; - i2cp->id_state = I2C_MWAIT_ADDR_ACK; - return; - } - else{ // slave address is 10-bit - i2cp->id_state = I2C_10BIT_HANDSHAKE; - // send MSB with header. LSB = 0. - i2cp->id_i2c->DR = ((i2cp->id_slave_config->address >> 7) & 0x6) | 0xF0; - return; - } - } - - // "wait" interrupt with ADD10 flag - if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADD10)){ - i2cp->id_i2c->DR = i2cp->id_slave_config->address & 0x00FF; // send remaining bits of address - if (!(i2cp->rw_bit)) - // in transmit mode there is nothing to do with 10-bit handshaking - i2cp->id_state = I2C_MWAIT_ADDR_ACK; - return; - } - - // "wait" interrupt with ADDR flag - if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address ACKed - i2cp->id_i2c->CR1 |= I2C_CR1_START; - return; - } - - if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// restart generated - // send MSB with header. LSB = 1 - i2cp->id_i2c->DR = ((i2cp->id_slave_config->address >> 7) & 0x6) | 0xF1; - i2cp->id_state = I2C_MWAIT_ADDR_ACK; - return; - } - - // "wait" interrupt with ADDR (ADD10 in 10-bit receiver mode) flag - if ((i2cp->id_state == I2C_MWAIT_ADDR_ACK) && (i2cp->id_i2c->SR1 & (I2C_SR1_ADDR | I2C_SR1_ADD10))){// address ACKed - if(i2cp->id_i2c->SR2 & I2C_SR2_TRA){// I2C is transmitting data - i2cp->id_state = I2C_MTRANSMIT; // change state - i2c_lld_txbyte(i2cp); // send first byte - return; - } - else {// I2C is receiving data - /* In order to generate the non-acknowledge pulse after the last received - * data byte, the ACK bit must be cleared just after reading the second - * last data byte (after second last RxNE event). - */ - if (i2cp->id_slave_config->rxbytes > 1) - i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // set ACK bit - i2cp->id_state = I2C_MRECEIVE; // change state - return; - } - } - - // transmitting bytes one by one - if ((i2cp->id_state == I2C_MTRANSMIT) && (i2cp->id_i2c->SR1 & I2C_SR1_TXE)){ - if (i2c_lld_txbyte(i2cp)) - i2cp->id_state = I2C_MWAIT_TF; // last byte written - return; - } - - //receiving bytes one by one - if ((i2cp->id_state == I2C_MRECEIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_RXNE)){ - if (i2c_lld_rxbyte(i2cp)) - i2cp->id_state = I2C_MWAIT_TF; // last byte read - return; - } - - // "wait" BTF bit in status register - if ((i2cp->id_state == I2C_MWAIT_TF) && (i2cp->id_i2c->SR1 & I2C_SR1_BTF)){ - chSysLockFromIsr(); - i2cp->id_i2c->CR2 &= (~I2C_CR2_ITEVTEN); // disable BTF interrupt - chSysUnlockFromIsr(); - /* now driver is ready to generate (re)start/stop condition. - * Callback function is good place to do that. If not callback was - * set - driver only generate stop condition. */ - i2cp->id_state = I2C_READY; - - if (i2cp->id_slave_config->id_callback != NULL) - i2cp->id_slave_config->id_callback(i2cp, i2cp->id_slave_config); - else /* No callback function set. Generate stop */ - i2c_lld_master_stop(i2cp); - - return; - } -#if CH_DBG_ENABLE_CHECKS - else{ // debugging trap - i = i2cp->id_i2c->SR1; - n = i2cp->id_i2c->SR2; - m = i2cp->id_i2c->CR1; - while(TRUE); - } -#endif /* CH_DBG_ENABLE_CHECKS */ -} - -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -/** - * @brief I2C1 event interrupt handler. - */ -CH_IRQ_HANDLER(VectorBC) { - - CH_IRQ_PROLOGUE(); - i2c_serve_event_interrupt(&I2CD1); - CH_IRQ_EPILOGUE(); -} - -/** - * @brief I2C1 error interrupt handler. - */ -CH_IRQ_HANDLER(VectorC0) { - - CH_IRQ_PROLOGUE(); - i2c_serve_error_interrupt(&I2CD1); - CH_IRQ_EPILOGUE(); -} -#endif - -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -/** - * @brief I2C2 event interrupt handler. - */ -CH_IRQ_HANDLER(VectorC4) { - - CH_IRQ_PROLOGUE(); - i2c_serve_event_interrupt(&I2CD2); - CH_IRQ_EPILOGUE(); -} - -/** - * @brief I2C2 error interrupt handler. - */ -CH_IRQ_HANDLER(VectorC8) { - - CH_IRQ_PROLOGUE(); - i2c_serve_error_interrupt(&I2CD2); - CH_IRQ_EPILOGUE(); -} -#endif - -/** - * @brief Low level I2C driver initialization. - */ -void i2c_lld_init(void) { - -#if STM32_I2C_USE_I2C1 - RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; // reset I2C 1 - RCC->APB1RSTR = 0; - i2cObjectInit(&I2CD1); - I2CD1.id_i2c = I2C1; -#endif - -#if STM32_I2C_USE_I2C2 - RCC->APB1RSTR = RCC_APB1RSTR_I2C2RST; // reset I2C 2 - RCC->APB1RSTR = 0; - i2cObjectInit(&I2CD2); - I2CD2.id_i2c = I2C2; -#endif -} - -/** - * @brief Configures and activates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2c_lld_start(I2CDriver *i2cp) { - - /* If in stopped state then enables the I2C clock.*/ - if (i2cp->id_state == I2C_STOP) { -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - NVICEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); - NVICEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); - RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // I2C 1 clock enable - } -#endif -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - NVICEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); - NVICEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); - RCC->APB1ENR |= RCC_APB1ENR_I2C2EN; // I2C 2 clock enable - } -#endif - } - - /* I2C setup.*/ - i2cp->id_i2c->CR1 = I2C_CR1_SWRST; // reset i2c peripherial - i2cp->id_i2c->CR1 = 0; - - i2c_lld_set_clock(i2cp); - i2c_lld_set_opmode(i2cp); - i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN | I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN;// enable interrupts - i2cp->id_i2c->CR1 |= 1; // enable interface -} - -/** - * @brief Set clock speed. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2c_lld_set_clock(I2CDriver *i2cp) { - volatile uint16_t regCCR, regCR2, freq, clock_div; - volatile uint16_t pe_bit_saved; - int32_t clock_speed = i2cp->id_config->ClockSpeed; - I2C_DutyCycle_t duty = i2cp->id_config->FastModeDutyCycle; - - chDbgCheck((i2cp != NULL) && (clock_speed > 0) && (clock_speed <= 4000000), - "i2c_lld_set_clock"); - - /*---------------------------- CR2 Configuration ------------------------*/ - /* Get the I2Cx CR2 value */ - regCR2 = i2cp->id_i2c->CR2; - - /* Clear frequency FREQ[5:0] bits */ - regCR2 &= (uint16_t)~I2C_CR2_FREQ; - /* Set frequency bits depending on pclk1 value */ - freq = (uint16_t)(STM32_PCLK1 / 1000000); - chDbgCheck((freq >= 2) && (freq <= 36), - "i2c_lld_set_clock() : Peripheral clock freq. out of range"); - regCR2 |= freq; - i2cp->id_i2c->CR2 = regCR2; - - /*---------------------------- CCR Configuration ------------------------*/ - pe_bit_saved = (i2cp->id_i2c->CR1 & I2C_CR1_PE); - /* Disable the selected I2C peripheral to configure TRISE */ - i2cp->id_i2c->CR1 &= (uint16_t)~I2C_CR1_PE; - - /* Clear F/S, DUTY and CCR[11:0] bits */ - regCCR = 0; - clock_div = I2C_CCR_CCR; - /* Configure clock_div in standard mode */ - if (clock_speed <= 100000) { - chDbgAssert(duty == stdDutyCycle, - "i2c_lld_set_clock(), #1", "Invalid standard mode duty cycle"); - /* Standard mode clock_div calculate: Tlow/Thigh = 1/1 */ - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2)); - /* Test if CCR value is under 0x4, and set the minimum allowed value */ - if (clock_div < 0x04) clock_div = 0x04; - /* Set clock_div value for standard mode */ - regCCR |= (clock_div & I2C_CCR_CCR); - /* Set Maximum Rise Time for standard mode */ - i2cp->id_i2c->TRISE = freq + 1; - } - /* Configure clock_div in fast mode */ - else if(clock_speed <= 400000) { - chDbgAssert((duty == fastDutyCycle_2) || (duty == fastDutyCycle_16_9), - "i2c_lld_set_clock(), #2", "Invalid fast mode duty cycle"); - if(duty == fastDutyCycle_2) { - /* Fast mode clock_div calculate: Tlow/Thigh = 2/1 */ - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3)); - } - else if(duty == fastDutyCycle_16_9) { - /* Fast mode clock_div calculate: Tlow/Thigh = 16/9 */ - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 25)); - /* Set DUTY bit */ - regCCR |= I2C_CCR_DUTY; - } - /* Test if CCR value is under 0x1, and set the minimum allowed value */ - if(clock_div < 0x01) clock_div = 0x01; - /* Set clock_div value and F/S bit for fast mode*/ - regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR)); - /* Set Maximum Rise Time for fast mode */ - i2cp->id_i2c->TRISE = (freq * 300 / 1000) + 1; - } - chDbgAssert((clock_div <= I2C_CCR_CCR), - "i2c_lld_set_clock(), #3", "Too low clock clock speed selected"); - - /* Write to I2Cx CCR */ - i2cp->id_i2c->CCR = regCCR; - - /* restore the I2C peripheral enabled state */ - i2cp->id_i2c->CR1 |= pe_bit_saved; -} - -/** - * @brief Set operation mode of I2C hardware. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2c_lld_set_opmode(I2CDriver *i2cp) { - I2C_opMode_t opmode = i2cp->id_config->opMode; - uint16_t regCR1; - - /*---------------------------- CR1 Configuration ------------------------*/ - /* Get the I2Cx CR1 value */ - regCR1 = i2cp->id_i2c->CR1; - switch(opmode){ - case opmodeI2C: - regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); - break; - case opmodeSMBusDevice: - regCR1 |= I2C_CR1_SMBUS; - regCR1 &= (uint16_t)~(I2C_CR1_SMBTYPE); - break; - case opmodeSMBusHost: - regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); - break; - } - /* Write to I2Cx CR1 */ - i2cp->id_i2c->CR1 = regCR1; -} - -/** - * @brief Set own address. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2c_lld_set_own_address(I2CDriver *i2cp) { - //TODO: dual address mode - - /*---------------------------- OAR1 Configuration -----------------------*/ - i2cp->id_i2c->OAR1 |= 1 << 14; - - if (&(i2cp->id_config->OwnAddress10) == NULL){// only 7-bit address - i2cp->id_i2c->OAR1 &= (~I2C_OAR1_ADDMODE); - i2cp->id_i2c->OAR1 |= i2cp->id_config->OwnAddress7 << 1; - } - else { - chDbgAssert((i2cp->id_config->OwnAddress10 < 1024), - "i2c_lld_set_own_address(), #1", "10-bit address longer then 10 bit") - i2cp->id_i2c->OAR1 |= I2C_OAR1_ADDMODE; - i2cp->id_i2c->OAR1 |= i2cp->id_config->OwnAddress10; - } -} - - -/** - * @brief Deactivates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2c_lld_stop(I2CDriver *i2cp) { - - /* If in ready state then disables the I2C clock.*/ - if (i2cp->id_state == I2C_READY) { -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - NVICDisableVector(I2C1_EV_IRQn); - NVICDisableVector(I2C1_ER_IRQn); - RCC->APB1ENR &= ~RCC_APB1ENR_I2C1EN; - } -#endif -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - NVICDisableVector(I2C2_EV_IRQn); - NVICDisableVector(I2C2_ER_IRQn); - RCC->APB1ENR &= ~RCC_APB1ENR_I2C2EN; - } -#endif - } - i2cp->id_state = I2C_STOP; -} - -/** - * @brief Generate start condition. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2c_lld_master_start(I2CDriver *i2cp){ - i2cp->id_i2c->CR1 |= I2C_CR1_START; - while (i2cp->id_i2c->CR1 & I2C_CR1_START); - - /* enable interrupts from I2C hardware. They will disable in driver state - machine after the transfer finish.*/ - i2cp->id_i2c->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; -} - -/** - * @brief Generate stop condition. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2c_lld_master_stop(I2CDriver *i2cp){ - i2cp->id_i2c->CR1 |= I2C_CR1_STOP; - while (i2cp->id_i2c->CR1 & I2C_CR1_STOP); -} - -/** - * @brief Begin data transmitting. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object - */ -void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ - - i2cp->id_slave_config = i2cscfg; - i2cp->rw_bit = I2C_WRITE; - - // generate start condition. Later transmission goes in background - i2c_lld_master_start(i2cp); -} - -/** - * @brief Begin data receiving. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object - */ -void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ - - i2cp->id_slave_config = i2cscfg; - i2cp->rw_bit = I2C_READ; - - // generate (re)start condition. Later connection goes asynchronously - i2c_lld_master_start(i2cp); -} - - - -/** - * @brief Transmits data via I2C bus. - * - * @note This function does not use interrupts - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object - * @param[in] restart bool. If TRUE then generate restart condition instead of stop - */ -void i2c_lld_master_transmit_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart) { - - int i = 0; - - i2cp->id_slave_config = i2cscfg; - i2cp->rw_bit = I2C_WRITE; - - - i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate start condition - while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)); // wait Address sent - - i2cp->id_i2c->DR = (i2cp->id_slave_config->address << 1) | I2C_WRITE; // write slave addres in DR - while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)); // wait Address sent - i = i2cp->id_i2c->SR2; - i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit - - // now write data byte by byte in DR register - uint32_t n = 0; - for (n = 0; n < i2cp->id_slave_config->txbytes; n++){ - i2cp->id_i2c->DR = i2cscfg->txbuf[n]; - while (!(i2cp->id_i2c->SR1 & I2C_SR1_TXE)); - } - - while (!(i2cp->id_i2c->SR1 & I2C_SR1_BTF)); - - if (restart){ - i2cp->id_i2c->CR1 |= I2C_CR1_START; // generate restart condition - while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)); // wait start bit - } - else i2cp->id_i2c->CR1 |= I2C_CR1_STOP; // generate stop condition -} - - -/** - * @brief Receives data from the I2C bus. - * @note This function does not use interrupts - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object - */ -void i2c_lld_master_receive_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { - - i2cp->id_slave_config = i2cscfg; - - uint16_t i = 0; - - // send slave addres with read-bit - i2cp->id_i2c->DR = (i2cp->id_slave_config->address << 1) | I2C_READ; - while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)); // wait Address sent - - i = i2cp->id_i2c->SR2; - i = i2cp->id_i2c->SR1; //i2cp->id_i2c->SR1 &= (~I2C_SR1_ADDR); // clear ADDR bit - - // set ACK bit - i2cp->id_i2c->CR1 |= I2C_CR1_ACK; - - // collect data from slave - for (i = 0; i < i2cp->id_slave_config->rxbytes; i++){ - if ((i2cp->id_slave_config->rxbytes - i) == 1){ - // clear ACK bit for automatically send NACK - i2cp->id_i2c->CR1 &= (~I2C_CR1_ACK);} - while (!(i2cp->id_i2c->SR1 & I2C_SR1_RXNE)); - - i2cp->id_slave_config->rxbuf[i] = i2cp->id_i2c->DR; - } - // generate STOP - i2cp->id_i2c->CR1 |= I2C_CR1_STOP; -} - - - -#endif // HAL_USE_I2C diff --git a/os/hal/platforms/STM32/i2c_lld_btrts.h b/os/hal/platforms/STM32/i2c_lld_btrts.h deleted file mode 100644 index 76f7068e2..000000000 --- a/os/hal/platforms/STM32/i2c_lld_btrts.h +++ /dev/null @@ -1,201 +0,0 @@ -/** - * @file STM32/i2c_lld.h - * @brief STM32 I2C subsystem low level driver header. - * @addtogroup STM32_I2C - * @{ - */ - -#ifndef _I2C_LLD_H_ -#define _I2C_LLD_H_ - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @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. */ -/*===========================================================================*/ -#define I2CD_NO_ERROR 0 -/** @brief Bus Error.*/ -#define I2CD_BUS_ERROR 0x01 -/** @brief Arbitration Lost (master mode).*/ -#define I2CD_ARBITRATION_LOST 0x02 -/** @brief Acknowledge Failure.*/ -#define I2CD_ACK_FAILURE 0x04 -/** @brief Overrun/Underrun.*/ -#define I2CD_OVERRUN 0x08 -/** @brief PEC Error in reception.*/ -#define I2CD_PEC_ERROR 0x10 -/** @brief Timeout or Tlow Error.*/ -#define I2CD_TIMEOUT 0x20 -/** @brief SMBus Alert.*/ -#define I2CD_SMB_ALERT 0x40 -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -typedef enum { - opmodeI2C, - opmodeSMBusDevice, - opmodeSMBusHost, -} I2C_opMode_t; - -typedef enum { - stdDutyCycle, - fastDutyCycle_2, - fastDutyCycle_16_9, -} I2C_DutyCycle_t; - -/** - * @brief Driver configuration structure. - */ -typedef struct { - I2C_opMode_t opMode; /*!< Specifies the I2C mode.*/ - uint32_t ClockSpeed; /*!< Specifies the clock frequency. Must be set to a value lower than 400kHz */ - I2C_DutyCycle_t FastModeDutyCycle;/*!< Specifies the I2C fast mode duty cycle */ - uint8_t OwnAddress7; /*!< Specifies the first device 7-bit own address. */ - uint16_t OwnAddress10; /*!< Specifies the second part of device own address in 10-bit mode. Set to NULL if not used. */ -} 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 *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. - */ - I2CConfig *id_config; - /** - * @brief Current slave configuration data. - */ - I2CSlaveConfig *id_slave_config; - /** - * @brief RW-bit sent to slave. - */ - uint8_t rw_bit; - - /*********** End of the mandatory fields. **********************************/ - - /** - * @brief Pointer to the I2Cx registers block. - */ - I2C_TypeDef *id_i2c; -} ; - - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* 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_start(I2CDriver *i2cp); -void i2c_lld_stop(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_master_start(I2CDriver *i2cp); -void i2c_lld_master_stop(I2CDriver *i2cp); - -void i2c_lld_master_transmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); -void i2c_lld_master_receive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); - -void i2c_lld_master_transmit_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, bool_t restart); -void i2c_lld_master_receive_NI(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); - -#ifdef __cplusplus -} -#endif -/** @endcond*/ - -#endif // CH_HAL_USE_I2C - -#endif // _I2C_LLD_H_ diff --git a/os/hal/src/i2c_albi.c b/os/hal/src/i2c_albi.c deleted file mode 100644 index 64bed78eb..000000000 --- a/os/hal/src/i2c_albi.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . -*/ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/** - * @brief I2C Driver initialization. - */ -void i2cInit(void) { - - i2c_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p I2CDriver structure. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2cObjectInit(I2CDriver *i2cp) { - chEvtInit(&i2cp->sevent); - i2cp->errors = I2CD_NO_ERROR; - i2cp->state = I2C_STOP; -// i2cp->i2cd_config = NULL; -#if I2C_USE_WAIT - i2cp->thread = NULL; -#endif /* I2C_USE_WAIT */ -#if I2C_USE_MUTUAL_EXCLUSION -#if CH_USE_MUTEXES - chMtxInit(&i2cp->mutex); -#elif CH_USE_SEMAPHORES - chSemInit(&i2cp->semaphore, 1); -#endif -#endif /* I2C_USE_MUTUAL_EXCLUSION */ -#if defined(I2C_DRIVER_EXT_INIT_HOOK) - I2C_DRIVER_EXT_INIT_HOOK(i2cp); -#endif -} - -/** - * @brief Configures and activates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] config pointer to the @p I2CConfig object - */ -void i2cStart(I2CDriver *i2cp, const I2CConfig *config) { - - chDbgCheck((i2cp != NULL) && (config != NULL), "i2cStart"); - - chSysLock(); - chDbgAssert((i2cp->state == I2C_STOP)||(i2cp->state == I2C_READY), - "i2cStart(), #1", "invalid state"); - - i2cp->nbit_address = config->nBitAddress; - i2c_lld_start(i2cp); - i2c_lld_set_clock(i2cp, config->ClockSpeed, config->FastModeDutyCycle); - i2c_lld_set_opmode(i2cp, config->opMode); - i2c_lld_set_own_address(i2cp, config->OwnAddress1, config->nBitAddress); - i2cp->state = I2C_READY; - chSysUnlock(); -} - -/** - * @brief Deactivates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2cStop(I2CDriver *i2cp) { - - chDbgCheck(i2cp != NULL, "i2cStop"); - - chSysLock(); - chDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY), - "i2cStop(), #1", "invalid state"); - i2c_lld_stop(i2cp); - i2cp->state = I2C_STOP; - chSysUnlock(); -} - -/** - * @brief Sends data ever the I2C bus. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] slave_addr 7-bit or 10-bit address of the slave - * @param[in] n number of words to send - * @param[in] txbuf the pointer to the transmit buffer - * - */ -void i2cMasterTransmit(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *txbuf) { - - chDbgCheck((i2cp != NULL) && (n > 0) && (txbuf != NULL), - "i2cMasterTransmit"); - -#if I2C_USE_WAIT - i2c_lld_wait_bus_free(i2cp); - if(i2c_lld_bus_is_busy(i2cp)) { -#ifdef PRINTTRACE - print("I2C Bus busy!\n"); -#endif - return; - }; -#endif - - chSysLock(); - chDbgAssert(i2cp->state == I2C_READY, - "i2cMasterTransmit(), #1", "not ready"); - - i2cp->state = I2C_ACTIVE; - i2c_lld_master_transmit(i2cp, slave_addr, n, txbuf); - _i2c_wait_s(i2cp); -#if !I2C_USE_WAIT - i2c_lld_wait_bus_free(i2cp); -#endif - if (i2cp->state == I2C_COMPLETE) - i2cp->state = I2C_READY; - chSysUnlock(); -} - -/** - * @brief Receives data from the I2C bus. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] slave_addr 7-bit or 10-bit address of the slave - * @param[in] n number of bytes to receive - * @param[out] rxbuf the pointer to the receive buffer - * - */ -void i2cMasterReceive(I2CDriver *i2cp, uint16_t slave_addr, size_t n, void *rxbuf) { - - chDbgCheck((i2cp != NULL) && (n > 0) && (rxbuf != NULL), - "i2cMasterReceive"); - -#if I2C_USE_WAIT - i2c_lld_wait_bus_free(i2cp); - if(i2c_lld_bus_is_busy(i2cp)) { -#ifdef PRINTTRACE - print("I2C Bus busy!\n"); -#endif - return; - }; -#endif - - chSysLock(); - chDbgAssert(i2cp->state == I2C_READY, - "i2cMasterReceive(), #1", "not ready"); - - i2cp->state = I2C_ACTIVE; - i2c_lld_master_receive(i2cp, slave_addr, n, rxbuf); - _i2c_wait_s(i2cp); -#if !I2C_USE_WAIT - i2c_lld_wait_bus_free(i2cp); -#endif - if (i2cp->state == I2C_COMPLETE) - i2cp->state = I2C_READY; - chSysUnlock(); -} - -uint16_t i2cSMBusAlertResponse(I2CDriver *i2cp) { - uint16_t slv_addr; - - i2cMasterReceive(i2cp, 0x0C, 2, &slv_addr); - return slv_addr; -} - - -/** - * @brief Handles communication events/errors. - * @details Must be called from the I/O interrupt service routine in order to - * notify I/O conditions as errors, signals change etc. - * - * @param[in] i2cp pointer to a @p I2CDriver structure - * @param[in] mask condition flags to be added to the mask - * - * @iclass - */ -void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask) { - - chDbgCheck(i2cp != NULL, "i2cAddFlagsI"); - - i2cp->errors |= mask; - chEvtBroadcastI(&i2cp->sevent); -} - -/** - * @brief Returns and clears the errors mask associated to the driver. - * - * @param[in] i2cp pointer to a @p I2CDriver structure - * @return The condition flags modified since last time this - * function was invoked. - * - * @api - */ -i2cflags_t i2cGetAndClearFlags(I2CDriver *i2cp) { - i2cflags_t mask; - - chDbgCheck(i2cp != NULL, "i2cGetAndClearFlags"); - - chSysLock(); - mask = i2cp->errors; - i2cp->errors = I2CD_NO_ERROR; - chSysUnlock(); - return mask; -} - - - -#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) -/** - * @brief Gains exclusive access to the I2C bus. - * @details This function tries to gain ownership to the I2C bus, if the bus - * is already being used then the invoking thread is queued. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @note This function is only available when the @p I2C_USE_MUTUAL_EXCLUSION - * option is set to @p TRUE. - */ -void i2cAcquireBus(I2CDriver *i2cp) { - - chDbgCheck(i2cp != NULL, "i2cAcquireBus"); - -#if CH_USE_MUTEXES - chMtxLock(&i2cp->mutex); -#elif CH_USE_SEMAPHORES - chSemWait(&i2cp->semaphore); -#endif -} - -/** - * @brief Releases exclusive access to the I2C bus. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @note This function is only available when the @p I2C_USE_MUTUAL_EXCLUSION - * option is set to @p TRUE. - */ -void i2cReleaseBus(I2CDriver *i2cp) { - - chDbgCheck(i2cp != NULL, "i2cReleaseBus"); - -#if CH_USE_MUTEXES - (void)i2cp; - chMtxUnlock(); -#elif CH_USE_SEMAPHORES - chSemSignal(&i2cp->semaphore); -#endif -} -#endif /* I2C_USE_MUTUAL_EXCLUSION */ - -#endif /* CH_HAL_USE_I2C */ diff --git a/os/hal/src/i2c_brts.c b/os/hal/src/i2c_brts.c deleted file mode 100644 index ad9a5d0ac..000000000 --- a/os/hal/src/i2c_brts.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . -*/ - -/** - * @file i2c.c - * @brief I2C Driver code. - * - * @addtogroup I2C - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief I2C Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void i2cInit(void) { - i2c_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p I2CDriver structure. - * - * @param[out] i2cp pointer to the @p I2CDriver object - * - * @init - */ -void i2cObjectInit(I2CDriver *i2cp) { - - i2cp->id_state = I2C_STOP; - i2cp->id_config = NULL; - i2cp->id_slave_config = NULL; - -#if I2C_USE_WAIT - i2cp->id_thread = NULL; -#endif /* I2C_USE_WAIT */ - -#if I2C_USE_MUTUAL_EXCLUSION -#if CH_USE_MUTEXES - chMtxInit(&i2cp->id_mutex); -#else - chSemInit(&i2cp->id_semaphore, 1); -#endif /* CH_USE_MUTEXES */ -#endif /* I2C_USE_MUTUAL_EXCLUSION */ - -#if defined(I2C_DRIVER_EXT_INIT_HOOK) - I2C_DRIVER_EXT_INIT_HOOK(i2cp); -#endif -} - -/** - * @brief Configures and activates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] config pointer to the @p I2CConfig object - * - * @api - */ -void i2cStart(I2CDriver *i2cp, I2CConfig *config) { - - chDbgCheck((i2cp != NULL) && (config != NULL), "i2cStart"); - - chSysLock(); - chDbgAssert((i2cp->id_state == I2C_STOP) || (i2cp->id_state == I2C_READY), - "i2cStart(), #1", - "invalid state"); - i2cp->id_config = config; - i2c_lld_start(i2cp); - i2cp->id_state = I2C_READY; - chSysUnlock(); -} - -/** - * @brief Deactivates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @api - */ -void i2cStop(I2CDriver *i2cp) { - - chDbgCheck(i2cp != NULL, "i2cStop"); - - chSysLock(); - chDbgAssert((i2cp->id_state == I2C_STOP) || (i2cp->id_state == I2C_READY), - "i2cStop(), #1", - "invalid state"); - i2c_lld_stop(i2cp); - i2cp->id_state = I2C_STOP; - chSysUnlock(); -} - -/** - * @brief Generate (re)start on the bus. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2cMasterStart(I2CDriver *i2cp){ - - chDbgCheck((i2cp != NULL), "i2cMasterTransmit"); - - chSysLock(); - i2c_lld_master_start(i2cp); - chSysUnlock(); -} - -/** - * @brief Generate stop on the bus. - * - * @param[in] i2cp pointer to the @p I2CDriver object - */ -void i2cMasterStop(I2CDriver *i2cp){ - - chDbgCheck((i2cp != NULL), "i2cMasterTransmit"); - chSysLock(); - i2c_lld_master_stop(i2cp); - chSysUnlock(); -} - -/** - * @brief Sends data ever the I2C bus. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object - * - */ -void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { - - chDbgCheck((i2cp != NULL) && (i2cscfg != NULL), - "i2cMasterTransmit"); - chDbgAssert(i2cp->id_state == I2C_READY, - "i2cMasterTransmit(), #1", - "not active"); - - chSysLock(); - i2c_lld_master_transmit(i2cp, i2cscfg); - chSysUnlock(); -} - - -/** - * @brief Receives data from the I2C bus. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object - */ -void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { - - chDbgCheck((i2cp != NULL) && (i2cscfg != NULL), - "i2cMasterReceive"); - chDbgAssert(i2cp->id_state == I2C_READY, - "i2cMasterReceive(), #1", - "not active"); - - chSysLock(); - i2c_lld_master_receive(i2cp, i2cscfg); - chSysUnlock(); -} - - - -#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) -/** - * @brief Gains exclusive access to the I2C bus. - * @details This function tries to gain ownership to the I2C bus, if the bus - * is already being used then the invoking thread is queued. - * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION - * must be enabled. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @api - * - */ -void i2cAcquireBus(I2CDriver *i2cp) { - - chDbgCheck(i2cp != NULL, "i2cAcquireBus"); - -#if CH_USE_MUTEXES - chMtxLock(&i2cp->id_mutex); -#elif CH_USE_SEMAPHORES - chSemWait(&i2cp->id_semaphore); -#endif -} - -/** - * @brief Releases exclusive access to the I2C bus. - * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION - * must be enabled. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @api - */ -void i2cReleaseBus(I2CDriver *i2cp) { - - chDbgCheck(i2cp != NULL, "i2cReleaseBus"); - -#if CH_USE_MUTEXES - (void)i2cp; - chMtxUnlock(); -#elif CH_USE_SEMAPHORES - chSemSignal(&i2cp->id_semaphore); -#endif -} -#endif /* I2C_USE_MUTUAL_EXCLUSION */ - -#endif /* HAL_USE_I2C */ - -/** @} */ From 350ae0a1a9721b8889b038cf2fce6a88f1c288e3 Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 18 Jun 2011 11:12:33 +0000 Subject: [PATCH 46/92] I2C. API BROKEN! Structure fields renamed in underscore naming style. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3055 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 11 ++++------- os/hal/platforms/STM32/i2c_lld.c | 32 ++++++++++++++++---------------- os/hal/platforms/STM32/i2c_lld.h | 32 ++++++++++++++++---------------- os/hal/src/i2c.c | 4 ++-- testhal/STM32/I2C/i2c_pns.c | 12 ++++++++---- 5 files changed, 46 insertions(+), 45 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index f5465985b..6b8661c7e 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -148,15 +148,12 @@ struct I2CSlaveConfig{ */ i2cerrorcallback_t id_err_callback; - /** - * @brief Receive and transmit buffers. - */ - size_t txbytes; - size_t rxbytes; + size_t txbytes; /*!< Number of bytes to transmitted. */ + size_t rxbytes; /*!< Number of bytes to received. */ i2cblock_t *rxbuf; /*!< Pointer to receive buffer. */ i2cblock_t *txbuf; /*!< Pointer to transmit buffer.*/ - uint16_t slave_addr; - uint8_t nbit_address; /*!< Length of address (must be 7 or 10).*/ + uint16_t slave_addr; /*!< Slave device address.*/ + uint8_t nbit_addr; /*!< Length of address (must be 7 or 10).*/ i2cflags_t errors; i2cflags_t flags; /* Status Change @p EventSource.*/ diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 4809838b7..75dd9d4bc 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -360,8 +360,8 @@ void i2c_lld_reset(I2CDriver *i2cp){ void i2c_lld_set_clock(I2CDriver *i2cp) { volatile uint16_t regCCR, regCR2, freq, clock_div; volatile uint16_t pe_bit_saved; - int32_t clock_speed = i2cp->id_config->ClockSpeed; - I2C_DutyCycle_t duty = i2cp->id_config->FastModeDutyCycle; + int32_t clock_speed = i2cp->id_config->clock_speed; + i2cdutycycle_t duty = i2cp->id_config->duty_cycle; chDbgCheck((i2cp != NULL) && (clock_speed > 0) && (clock_speed <= 4000000), "i2c_lld_set_clock"); @@ -389,7 +389,7 @@ void i2c_lld_set_clock(I2CDriver *i2cp) { clock_div = I2C_CCR_CCR; /* Configure clock_div in standard mode */ if (clock_speed <= 100000) { - chDbgAssert(duty == stdDutyCycle, + chDbgAssert(duty == STD_DUTY_CYCLE, "i2c_lld_set_clock(), #1", "Invalid standard mode duty cycle"); /* Standard mode clock_div calculate: Tlow/Thigh = 1/1 */ clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2)); @@ -402,13 +402,13 @@ void i2c_lld_set_clock(I2CDriver *i2cp) { } /* Configure clock_div in fast mode */ else if(clock_speed <= 400000) { - chDbgAssert((duty == fastDutyCycle_2) || (duty == fastDutyCycle_16_9), + chDbgAssert((duty == FAST_DUTY_CYCLE_2) || (duty == FAST_DUTY_CYCLE_16_9), "i2c_lld_set_clock(), #2", "Invalid fast mode duty cycle"); - if(duty == fastDutyCycle_2) { + if(duty == FAST_DUTY_CYCLE_2) { /* Fast mode clock_div calculate: Tlow/Thigh = 2/1 */ clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3)); } - else if(duty == fastDutyCycle_16_9) { + else if(duty == FAST_DUTY_CYCLE_16_9) { /* Fast mode clock_div calculate: Tlow/Thigh = 16/9 */ clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 25)); /* Set DUTY bit */ @@ -437,21 +437,21 @@ void i2c_lld_set_clock(I2CDriver *i2cp) { * @param[in] i2cp pointer to the @p I2CDriver object */ void i2c_lld_set_opmode(I2CDriver *i2cp) { - I2C_opMode_t opmode = i2cp->id_config->opMode; + i2copmode_t opmode = i2cp->id_config->op_mode; uint16_t regCR1; /*---------------------------- CR1 Configuration ------------------------*/ /* Get the I2Cx CR1 value */ regCR1 = i2cp->id_i2c->CR1; switch(opmode){ - case opmodeI2C: + case OPMODE_I2C: regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); break; - case opmodeSMBusDevice: + case OPMODE_SMBUS_DEVICE: regCR1 |= I2C_CR1_SMBUS; regCR1 &= (uint16_t)~(I2C_CR1_SMBTYPE); break; - case opmodeSMBusHost: + case OPMODE_SMBUS_HOST: regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); break; } @@ -470,15 +470,15 @@ void i2c_lld_set_own_address(I2CDriver *i2cp) { /*---------------------------- OAR1 Configuration -----------------------*/ i2cp->id_i2c->OAR1 |= 1 << 14; - if (&(i2cp->id_config->OwnAddress10) == NULL){// only 7-bit address + if (&(i2cp->id_config->own_addr_10) == NULL){// only 7-bit address i2cp->id_i2c->OAR1 &= (~I2C_OAR1_ADDMODE); - i2cp->id_i2c->OAR1 |= i2cp->id_config->OwnAddress7 << 1; + i2cp->id_i2c->OAR1 |= i2cp->id_config->own_addr_7 << 1; } else { - chDbgAssert((i2cp->id_config->OwnAddress10 < 1024), + chDbgAssert((i2cp->id_config->own_addr_10 < 1024), "i2c_lld_set_own_address(), #1", "10-bit address longer then 10 bit") i2cp->id_i2c->OAR1 |= I2C_OAR1_ADDMODE; - i2cp->id_i2c->OAR1 |= i2cp->id_config->OwnAddress10; + i2cp->id_i2c->OAR1 |= i2cp->id_config->own_addr_10; } } @@ -522,7 +522,7 @@ void i2c_lld_master_transmit(I2CDriver *i2cp) { i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - switch(i2cp->id_slave_config->nbit_address){ + switch(i2cp->id_slave_config->nbit_addr){ case 7: // LSB = 0 -> write i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) & 0x00FE); @@ -564,7 +564,7 @@ void i2c_lld_master_receive(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // acknowledge returned i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - switch(i2cp->id_slave_config->nbit_address){ + switch(i2cp->id_slave_config->nbit_addr){ case 7: // LSB = 1 -> receive i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) | 0x01); diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 00c6410fa..a97e863f6 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -95,28 +95,28 @@ typedef uint32_t i2cflags_t; typedef enum { - opmodeI2C, - opmodeSMBusDevice, - opmodeSMBusHost, -} I2C_opMode_t; + OPMODE_I2C = 1, + OPMODE_SMBUS_DEVICE = 2, + OPMODE_SMBUS_HOST = 3, +} i2copmode_t; typedef enum { - stdDutyCycle, - fastDutyCycle_2, - fastDutyCycle_16_9, -} I2C_DutyCycle_t; + STD_DUTY_CYCLE = 1, + FAST_DUTY_CYCLE_2 = 2, + FAST_DUTY_CYCLE_16_9 = 3, +} i2cdutycycle_t; /** * @brief Driver configuration structure. */ typedef struct { - I2C_opMode_t opMode; /*!< Specifies the I2C mode.*/ - uint32_t ClockSpeed; /*!< Specifies the clock frequency. Must be set to a value lower than 400kHz */ - I2C_DutyCycle_t FastModeDutyCycle;/*!< Specifies the I2C fast mode duty cycle */ - uint8_t OwnAddress7; /*!< Specifies the first device 7-bit own address. */ - uint16_t OwnAddress10; /*!< Specifies the second part of device own address in 10-bit mode. Set to NULL if not used. */ - uint16_t Ack; /*!< Enables or disables the acknowledgement. */ - uint8_t nBitAddress; /*!< Specifies if 7-bit or 10-bit address is acknowledged */ + i2copmode_t op_mode; /*!< Specifies the I2C mode.*/ + uint32_t clock_speed; /*!< Specifies the clock frequency. Must be set to a value lower than 400kHz */ + i2cdutycycle_t duty_cycle; /*!< Specifies the I2C fast mode duty cycle */ + uint8_t own_addr_7; /*!< Specifies the first device 7-bit own address. */ + uint16_t own_addr_10; /*!< Specifies the second part of device own address in 10-bit mode. Set to NULL if not used. */ + uint16_t ack; /*!< Enables or disables the acknowledgement. */ + uint8_t nbit_own_addr; /*!< Specifies if 7-bit or 10-bit address is acknowledged */ } I2CConfig; @@ -169,7 +169,7 @@ struct I2CDriver{ uint8_t slave_addr1; // 7-bit address of the slave uint8_t slave_addr2; // used in 10-bit address mode - uint8_t nbit_address; + uint8_t nbit_addr; /*********** End of the mandatory fields. **********************************/ diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 6f99a1afb..b43be0261 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -144,7 +144,7 @@ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { uint8_t nbit_addr; txbuf = i2cscfg->txbuf; - nbit_addr = i2cscfg->nbit_address; + nbit_addr = i2cscfg->nbit_addr; n = i2cscfg->txbytes; chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) && \ @@ -194,7 +194,7 @@ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ rxbuf = i2cscfg->rxbuf; n = i2cscfg->rxbytes; - nbit_addr = i2cscfg->nbit_address; + nbit_addr = i2cscfg->nbit_addr; chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) && (n > 0) && \ ((nbit_addr == 7) || (nbit_addr == 10)) && (rxbuf != NULL), diff --git a/testhal/STM32/I2C/i2c_pns.c b/testhal/STM32/I2C/i2c_pns.c index 11982d0a7..fe82fcb4e 100644 --- a/testhal/STM32/I2C/i2c_pns.c +++ b/testhal/STM32/I2C/i2c_pns.c @@ -9,18 +9,22 @@ /* I2C1 */ static I2CConfig i2cfg1 = { - opmodeI2C, + OPMODE_I2C, 100000, - stdDutyCycle, + STD_DUTY_CYCLE, + 0, + 0, 0, 0, }; /* I2C2 */ static I2CConfig i2cfg2 = { - opmodeI2C, + OPMODE_I2C, 100000, - stdDutyCycle, + STD_DUTY_CYCLE, + 0, + 0, 0, 0, }; From f3e571839bd7649073664d1c2c4ea3842695b6d5 Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 18 Jun 2011 13:35:26 +0000 Subject: [PATCH 47/92] I2C. Code cleanups. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3056 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 17 ++++++----------- os/hal/platforms/STM32/i2c_lld.h | 8 ++------ os/hal/src/i2c.c | 2 +- testhal/STM32/I2C/i2c_pns.c | 11 ++--------- 4 files changed, 11 insertions(+), 27 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 6b8661c7e..cc551887d 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -96,11 +96,7 @@ typedef enum { /** * @brief I2C notification callback type. * @details This callback invoked when byte transfer finish event occurs, - * No matter sending or reading. This function designed - * for sending (re)start or stop events to I2C bus from user level. - * - * If callback function is set to NULL - driver atomaticcaly - * generate stop condition after the transfer finish. + * No matter sending or reading. * * @param[in] i2cp pointer to the @p I2CDriver object triggering the * callback @@ -135,8 +131,7 @@ typedef uint8_t i2cblock_t; struct I2CSlaveConfig{ /** * @brief Callback pointer. - * @note Transfer finished callback. Invoke when all data transferred, or - * by DMA buffer events + * @note Transfer finished callback. Invoke when all data transferred. * If set to @p NULL then the callback is disabled. */ i2ccallback_t id_callback; @@ -154,8 +149,8 @@ struct I2CSlaveConfig{ i2cblock_t *txbuf; /*!< Pointer to transmit buffer.*/ uint16_t slave_addr; /*!< Slave device address.*/ uint8_t nbit_addr; /*!< Length of address (must be 7 or 10).*/ - i2cflags_t errors; - i2cflags_t flags; + i2cflags_t errors; /*!< Error flags.*/ + i2cflags_t flags; /*!< State flags.*/ /* Status Change @p EventSource.*/ EventSource sevent; }; @@ -212,7 +207,7 @@ struct I2CSlaveConfig{ * - Callback invocation. * - Waiting thread wakeup, if any. * - Driver state transitions. - * . + * * @note This macro is meant to be used in the low level drivers * implementation only. * @@ -236,7 +231,7 @@ extern "C" { #endif void i2cInit(void); void i2cObjectInit(I2CDriver *i2cp); - void i2cStart(I2CDriver *i2cp, I2CConfig *config); + void i2cStart(I2CDriver *i2cp, const I2CConfig *config); void i2cStop(I2CDriver *i2cp); void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index a97e863f6..815e451f0 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -157,15 +157,11 @@ struct I2CDriver{ /** * @brief Current configuration data. */ - I2CConfig *id_config; + const I2CConfig *id_config; /** * @brief Current slave configuration data. */ I2CSlaveConfig *id_slave_config; - /** - * @brief RW-bit sent to slave. - */ - uint8_t rw_bit; uint8_t slave_addr1; // 7-bit address of the slave uint8_t slave_addr2; // used in 10-bit address mode @@ -194,7 +190,7 @@ struct I2CDriver{ */ #define i2c_lld_wait_bus_free(i2cp) { \ uint32_t tmo = 0xffff; \ - while((i2cp->id_i2c->SR2 & I2C_SR2_BUSY) && tmo--) \ + while((i2cp->id_i2c->SR2 & I2C_SR2_BUSY) && tmo--) \ ; \ } diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index b43be0261..cd1a238ba 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -96,7 +96,7 @@ void i2cObjectInit(I2CDriver *i2cp) { * * @api */ -void i2cStart(I2CDriver *i2cp, I2CConfig *config) { +void i2cStart(I2CDriver *i2cp, const I2CConfig *config) { chDbgCheck((i2cp != NULL) && (config != NULL), "i2cStart"); diff --git a/testhal/STM32/I2C/i2c_pns.c b/testhal/STM32/I2C/i2c_pns.c index fe82fcb4e..63f7d99bd 100644 --- a/testhal/STM32/I2C/i2c_pns.c +++ b/testhal/STM32/I2C/i2c_pns.c @@ -8,7 +8,7 @@ #include "max1236.h" /* I2C1 */ -static I2CConfig i2cfg1 = { +static const I2CConfig i2cfg1 = { OPMODE_I2C, 100000, STD_DUTY_CYCLE, @@ -19,7 +19,7 @@ static I2CConfig i2cfg1 = { }; /* I2C2 */ -static I2CConfig i2cfg2 = { +static const I2CConfig i2cfg2 = { OPMODE_I2C, 100000, STD_DUTY_CYCLE, @@ -36,14 +36,7 @@ void I2CInit_pns(void){ i2cInit(); i2cStart(&I2CD1, &i2cfg1); - while(I2CD1.id_state != I2C_READY){ // wait ready status - chThdSleepMilliseconds(1); - } - i2cStart(&I2CD2, &i2cfg2); - while(I2CD2.id_state != I2C_READY){ // wait ready status - chThdSleepMilliseconds(1); - } /* tune ports for I2C1*/ palSetPadMode(IOPORT2, 6, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); From 79f477ba95384ef082a7f2ec71e228e02e62e864 Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 18 Jun 2011 14:31:27 +0000 Subject: [PATCH 48/92] I2C. "Slave_addr" and "nbit_addr" fields from I2CSlaveConfig structure merged together. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3057 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 12 +++++++-- os/hal/platforms/STM32/i2c_lld.c | 44 +++++++++++++++----------------- os/hal/src/i2c.c | 30 ++++++---------------- 3 files changed, 38 insertions(+), 48 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index cc551887d..b59644588 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -147,8 +147,16 @@ struct I2CSlaveConfig{ size_t rxbytes; /*!< Number of bytes to received. */ i2cblock_t *rxbuf; /*!< Pointer to receive buffer. */ i2cblock_t *txbuf; /*!< Pointer to transmit buffer.*/ - uint16_t slave_addr; /*!< Slave device address.*/ - uint8_t nbit_addr; /*!< Length of address (must be 7 or 10).*/ + /** + * @brief Slave device address. + * @details Bits 0-9 contain slave device address. + * + * Bit 15 must be set to 1 if 10-bit addressing modes used. Otherwise + * keep it cleared. + * + * Bits 10-14 unused. + */ + uint16_t slave_addr; i2cflags_t errors; /*!< Error flags.*/ i2cflags_t flags; /*!< State flags.*/ /* Status Change @p EventSource.*/ diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 75dd9d4bc..c56514095 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -522,19 +522,17 @@ void i2c_lld_master_transmit(I2CDriver *i2cp) { i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - switch(i2cp->id_slave_config->nbit_addr){ - case 7: - // LSB = 0 -> write - i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) & 0x00FE); - break; - case 10: - // add the two msb of 10-bit address to the header - i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr >>7) & 0x0006); - // add the header bits with LSB = 0 -> write - i2cp->slave_addr1 |= 0xF0; - // the remaining 8 bit of 10-bit address - i2cp->slave_addr2 = i2cp->id_slave_config->slave_addr & 0x00FF; - break; + if(i2cp->id_slave_config->slave_addr & 0x8000){// 10-bit mode used + // add the two msb of 10-bit address to the header + i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr >>7) & 0x0006); + // add the header bits with LSB = 0 -> write + i2cp->slave_addr1 |= 0xF0; + // the remaining 8 bit of 10-bit address + i2cp->slave_addr2 = i2cp->id_slave_config->slave_addr & 0x00FF; + } + else{ + // LSB = 0 -> write + i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) & 0x00FE); } i2cp->id_slave_config->flags = 0; @@ -564,19 +562,17 @@ void i2c_lld_master_receive(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // acknowledge returned i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - switch(i2cp->id_slave_config->nbit_addr){ - case 7: + if(i2cp->id_slave_config->slave_addr & 0x8000){// 10-bit mode used + // add the two msb of 10-bit address to the header + i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr >>7) & 0x0006); + // add the header bits (the LSB -> 1 will be add to second + i2cp->slave_addr1 |= 0xF0; + // the remaining 8 bit of 10-bit address + i2cp->slave_addr2 = i2cp->id_slave_config->slave_addr & 0x00FF; + } + else{ // LSB = 1 -> receive i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) | 0x01); - break; - case 10: - // add the two msb of 10-bit address to the header - i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr >>7) & 0x0006); - // add the header bits (the LSB -> 1 will be add to second - i2cp->slave_addr1 |= 0xF0; - // the remaining 8 bit of 10-bit address - i2cp->slave_addr2 = i2cp->id_slave_config->slave_addr & 0x00FF; - break; } i2cp->id_slave_config->flags = I2C_FLG_MASTER_RECEIVER; diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index cd1a238ba..f31dcb7ba 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -139,17 +139,10 @@ void i2cStop(I2CDriver *i2cp) { */ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { - size_t n; - i2cblock_t *txbuf; - uint8_t nbit_addr; - - txbuf = i2cscfg->txbuf; - nbit_addr = i2cscfg->nbit_addr; - n = i2cscfg->txbytes; - - chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) && \ - ((nbit_addr == 7) || (nbit_addr == 10)) && (n > 0) && (txbuf != NULL), - "i2cMasterTransmit"); + chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ + (i2cscfg->txbytes > 0) &&\ + (i2cscfg->txbuf != NULL), + "i2cMasterTransmit"); // init slave config field in driver i2cp->id_slave_config = i2cscfg; @@ -188,17 +181,10 @@ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { */ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ - size_t n; - i2cblock_t *rxbuf; - uint8_t nbit_addr; - - rxbuf = i2cscfg->rxbuf; - n = i2cscfg->rxbytes; - nbit_addr = i2cscfg->nbit_addr; - - chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) && (n > 0) && \ - ((nbit_addr == 7) || (nbit_addr == 10)) && (rxbuf != NULL), - "i2cMasterReceive"); + chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ + (i2cscfg->rxbytes > 0) && \ + (i2cscfg->rxbuf != NULL), + "i2cMasterReceive"); // init slave config field in driver i2cp->id_slave_config = i2cscfg; From 3e1753aa83c99406aa8bec70ce82d80556142d2c Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 18 Jun 2011 14:38:45 +0000 Subject: [PATCH 49/92] I2C. Examples fixed. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3058 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- testhal/STM32/I2C/lis3.c | 1 - testhal/STM32/I2C/max1236.c | 1 - testhal/STM32/I2C/tmp75.c | 1 - 3 files changed, 3 deletions(-) diff --git a/testhal/STM32/I2C/lis3.c b/testhal/STM32/I2C/lis3.c index 7e7c9d221..b07a51f13 100644 --- a/testhal/STM32/I2C/lis3.c +++ b/testhal/STM32/I2C/lis3.c @@ -35,7 +35,6 @@ static I2CSlaveConfig lis3 = { accel_rx_data, accel_tx_data, 0b0011101, - 7, 0, 0, {NULL}, diff --git a/testhal/STM32/I2C/max1236.c b/testhal/STM32/I2C/max1236.c index 36a77ff03..f5f88bfc4 100644 --- a/testhal/STM32/I2C/max1236.c +++ b/testhal/STM32/I2C/max1236.c @@ -47,7 +47,6 @@ static I2CSlaveConfig max1236 = { max1236_rx_data, max1236_tx_data, 0b0110100, - 7, 0, 0, {NULL}, diff --git a/testhal/STM32/I2C/tmp75.c b/testhal/STM32/I2C/tmp75.c index cc1b2ca7f..80aa352ee 100644 --- a/testhal/STM32/I2C/tmp75.c +++ b/testhal/STM32/I2C/tmp75.c @@ -42,7 +42,6 @@ static I2CSlaveConfig tmp75 = { tmp75_rx_data, tmp75_tx_data, 0b1001000, - 7, 0, 0, {NULL}, From 30c130dc10cd5f890c2ad534b97de1ceb2182d0a Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 18 Jun 2011 14:55:29 +0000 Subject: [PATCH 50/92] I2C. Dead code removed. Comments fixed. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3059 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 815e451f0..bfcd5ca91 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -163,9 +163,8 @@ struct I2CDriver{ */ I2CSlaveConfig *id_slave_config; - uint8_t slave_addr1; // 7-bit address of the slave - uint8_t slave_addr2; // used in 10-bit address mode - uint8_t nbit_addr; + uint8_t slave_addr1; /*!< 7-bit address of the slave with r\w bit.*/ + uint8_t slave_addr2; /*!< used in 10-bit address mode. */ /*********** End of the mandatory fields. **********************************/ From b54133ab1beba9d2923450d1d5f1b2c73dc2afa3 Mon Sep 17 00:00:00 2001 From: barthess Date: Tue, 21 Jun 2011 18:30:50 +0000 Subject: [PATCH 51/92] I2C. Some fields from I2CSlaveConfig moved to driver. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3066 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 11 +++--- os/hal/platforms/STM32/i2c_lld.c | 66 +++++++++++++++++--------------- os/hal/platforms/STM32/i2c_lld.h | 10 +++-- os/hal/src/i2c.c | 30 +++++++-------- testhal/STM32/I2C/Makefile | 8 ++-- testhal/STM32/I2C/lis3.c | 21 +++++----- testhal/STM32/I2C/max1236.c | 21 +++++----- testhal/STM32/I2C/tmp75.c | 10 ++--- 8 files changed, 92 insertions(+), 85 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index b59644588..c46e7f096 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -143,8 +143,8 @@ struct I2CSlaveConfig{ */ i2cerrorcallback_t id_err_callback; - size_t txbytes; /*!< Number of bytes to transmitted. */ - size_t rxbytes; /*!< Number of bytes to received. */ +// size_t txbytes; /*!< Number of bytes to transmitted. */ +// size_t rxbytes; /*!< Number of bytes to received. */ i2cblock_t *rxbuf; /*!< Pointer to receive buffer. */ i2cblock_t *txbuf; /*!< Pointer to transmit buffer.*/ /** @@ -157,8 +157,7 @@ struct I2CSlaveConfig{ * Bits 10-14 unused. */ uint16_t slave_addr; - i2cflags_t errors; /*!< Error flags.*/ - i2cflags_t flags; /*!< State flags.*/ + /* Status Change @p EventSource.*/ EventSource sevent; }; @@ -241,8 +240,8 @@ extern "C" { void i2cObjectInit(I2CDriver *i2cp); void i2cStart(I2CDriver *i2cp, const I2CConfig *config); void i2cStop(I2CDriver *i2cp); - void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); - void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); + void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, size_t txbytes, size_t rxbytes); + void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, size_t rxbytes); void i2cMasterStart(I2CDriver *i2cp); void i2cMasterStop(I2CDriver *i2cp); void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask); diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index c56514095..be7707796 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -48,13 +48,13 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { switch(i2c_get_event(i2cp)) { case I2C_EV5_MASTER_MODE_SELECT: - i2cp->id_slave_config->flags &= ~I2C_FLG_HEADER_SENT; + i2cp->flags &= ~I2C_FLG_HEADER_SENT; dp->DR = i2cp->slave_addr1; break; case I2C_EV9_MASTER_ADDR_10BIT: - if(i2cp->id_slave_config->flags & I2C_FLG_MASTER_RECEIVER) { + if(i2cp->flags & I2C_FLG_MASTER_RECEIVER) { i2cp->slave_addr1 |= 0x01; - i2cp->id_slave_config->flags |= I2C_FLG_HEADER_SENT; + i2cp->flags |= I2C_FLG_HEADER_SENT; // i2cp->id_i2c->CR1 = (i2cp->id_i2c->CR1 & (~I2C_CR1_ACK)) | I2C_CR1_STOP; } dp->DR = i2cp->slave_addr2; @@ -65,7 +65,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { // Master Transmitter ---------------------------------------------------- //------------------------------------------------------------------------ case I2C_EV6_MASTER_TRA_MODE_SELECTED: - if(i2cp->id_slave_config->flags & I2C_FLG_HEADER_SENT){ + if(i2cp->flags & I2C_FLG_HEADER_SENT){ dp->CR1 |= I2C_CR1_START; // re-send the start in 10-Bit address mode break; } @@ -73,20 +73,20 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { txBuffp = (uint8_t*)i2cp->id_slave_config->txbuf; datap = txBuffp; txBuffp++; - i2cp->id_slave_config->txbytes--; + i2cp->txbytes--; /* If no further data to be sent, disable the I2C ITBUF in order to not have a TxE interrupt */ - if(i2cp->id_slave_config->txbytes == 0) { + if(i2cp->txbytes == 0) { dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; } //EV8_1 write the first data dp->DR = *datap; break; case I2C_EV8_MASTER_BYTE_TRANSMITTING: - if(i2cp->id_slave_config->txbytes > 0) { + if(i2cp->txbytes > 0) { datap = txBuffp; txBuffp++; - i2cp->id_slave_config->txbytes--; - if(i2cp->id_slave_config->txbytes == 0) { + i2cp->txbytes--; + if(i2cp->txbytes == 0) { /* If no further data to be sent, disable the ITBUF in order to not have a TxE interrupt */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; } @@ -95,7 +95,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { break; case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: /* if nothing to read then generate stop */ - if (i2cp->id_slave_config->rxbytes == 0){ + if (i2cp->rxbytes == 0){ dp->CR1 |= I2C_CR1_STOP; // stop generation /* Disable ITEVT In order to not have again a BTF IT */ dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; @@ -106,7 +106,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { /* Disable ITEVT In order to not have again a BTF IT */ dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; /* send restart and begin reading operations */ - i2c_lld_master_receive(i2cp); + i2c_lld_master_receive(i2cp, i2cp->rxbytes); } break; @@ -116,7 +116,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { //------------------------------------------------------------------------ case I2C_EV6_MASTER_REC_MODE_SELECTED: chSysLockFromIsr(); - switch(i2cp->id_slave_config->flags & EV6_SUBEV_MASK) { + switch(i2cp->flags & EV6_SUBEV_MASK) { case I2C_EV6_3_MASTER_REC_1BTR_MODE_SELECTED: // only an single byte to receive /* Clear ACK */ dp->CR1 &= (uint16_t)~I2C_CR1_ACK; @@ -135,16 +135,16 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { rxBuffp = i2cp->id_slave_config->rxbuf; break; case I2C_EV7_MASTER_REC_BYTE_RECEIVED: - if(i2cp->id_slave_config->rxbytes != 3) { + if(i2cp->rxbytes != 3) { /* Read the data register */ *rxBuffp = dp->DR; rxBuffp++; - i2cp->id_slave_config->rxbytes--; - switch(i2cp->id_slave_config->rxbytes){ + i2cp->rxbytes--; + switch(i2cp->rxbytes){ case 3: /* Disable the ITBUF in order to have only the BTF interrupt */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - i2cp->id_slave_config->flags |= I2C_FLG_3BTR; + i2cp->flags |= I2C_FLG_3BTR; break; case 0: /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ @@ -155,7 +155,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { // when remaining 3 bytes do nothing, wait until RXNE and BTF are set (until 2 bytes are received) break; case I2C_EV7_MASTER_REC_BYTE_QUEUED: - switch(i2cp->id_slave_config->flags & EV7_SUBEV_MASK) { + switch(i2cp->flags & EV7_SUBEV_MASK) { case I2C_EV7_2_MASTER_REC_3BYTES_TO_PROCESS: // DataN-2 and DataN-1 are received chSysLockFromIsr(); @@ -172,8 +172,8 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { chSysUnlockFromIsr(); rxBuffp++; /* Decrement the number of readed bytes */ - i2cp->id_slave_config->rxbytes -= 2; - i2cp->id_slave_config->flags = 0; + i2cp->rxbytes -= 2; + i2cp->flags = 0; // ready for read DataN on the next EV7 break; case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: // only for case of two bytes to be received @@ -187,8 +187,8 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { rxBuffp++; /* Read the DataN*/ *rxBuffp = dp->DR; - i2cp->id_slave_config->rxbytes = 0; - i2cp->id_slave_config->flags = 0; + i2cp->rxbytes = 0; + i2cp->flags = 0; /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ _i2c_isr_code(i2cp, i2cp->id_slave_config); break; @@ -516,7 +516,9 @@ void i2c_lld_stop(I2CDriver *i2cp) { * @param[in] i2cp pointer to the @p I2CDriver object * */ -void i2c_lld_master_transmit(I2CDriver *i2cp) { +void i2c_lld_master_transmit(I2CDriver *i2cp, size_t txbytes, size_t rxbytes) { + i2cp->txbytes = txbytes; + i2cp->rxbytes = rxbytes; // enable ERR, EVT & BUF ITs i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); @@ -535,8 +537,8 @@ void i2c_lld_master_transmit(I2CDriver *i2cp) { i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) & 0x00FE); } - i2cp->id_slave_config->flags = 0; - i2cp->id_slave_config->errors = 0; + i2cp->flags = 0; + i2cp->errors = 0; i2cp->id_i2c->CR1 |= I2C_CR1_START; // send start bit @@ -556,7 +558,9 @@ void i2c_lld_master_transmit(I2CDriver *i2cp) { * @param[in] i2cp pointer to the @p I2CDriver object * */ -void i2c_lld_master_receive(I2CDriver *i2cp){ +void i2c_lld_master_receive(I2CDriver *i2cp, size_t rxbytes){ + i2cp->rxbytes = rxbytes; + // enable ERR, EVT & BUF ITs i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // acknowledge returned @@ -575,16 +579,16 @@ void i2c_lld_master_receive(I2CDriver *i2cp){ i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) | 0x01); } - i2cp->id_slave_config->flags = I2C_FLG_MASTER_RECEIVER; - i2cp->id_slave_config->errors = 0; + i2cp->flags = I2C_FLG_MASTER_RECEIVER; + i2cp->errors = 0; // Only one byte to be received - if(i2cp->id_slave_config->rxbytes == 1) { - i2cp->id_slave_config->flags |= I2C_FLG_1BTR; + if(i2cp->rxbytes == 1) { + i2cp->flags |= I2C_FLG_1BTR; } // Only two bytes to be received - else if(i2cp->id_slave_config->rxbytes == 2) { - i2cp->id_slave_config->flags |= I2C_FLG_2BTR; + else if(i2cp->rxbytes == 2) { + i2cp->flags |= I2C_FLG_2BTR; i2cp->id_i2c->CR1 |= I2C_CR1_POS; // Acknowledge Position } diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index bfcd5ca91..83b4f7812 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -166,6 +166,11 @@ struct I2CDriver{ uint8_t slave_addr1; /*!< 7-bit address of the slave with r\w bit.*/ uint8_t slave_addr2; /*!< used in 10-bit address mode. */ + size_t rxbytes; + size_t txbytes; + + i2cflags_t errors; /*!< Error flags.*/ + i2cflags_t flags; /*!< State flags.*/ /*********** End of the mandatory fields. **********************************/ @@ -217,9 +222,8 @@ 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); -void i2c_lld_master_receive(I2CDriver *i2cp); -void i2c_lld_master_transceive(I2CDriver *i2cp); +void i2c_lld_master_transmit(I2CDriver *i2cp, size_t txbytes, size_t rxbytes); +void i2c_lld_master_receive(I2CDriver *i2cp, size_t rxbytes); #ifdef __cplusplus } diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index f31dcb7ba..dc48b9478 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -137,10 +137,10 @@ void i2cStop(I2CDriver *i2cp) { * @param[in] i2cscfg pointer to the @p I2C slave config * */ -void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { +void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, size_t txbytes, size_t rxbytes) { chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ - (i2cscfg->txbytes > 0) &&\ + (txbytes > 0) &&\ (i2cscfg->txbuf != NULL), "i2cMasterTransmit"); @@ -162,7 +162,7 @@ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { "i2cMasterTransmit(), #1", "not ready"); i2cp->id_state = I2C_ACTIVE; - i2c_lld_master_transmit(i2cp); + i2c_lld_master_transmit(i2cp, txbytes, rxbytes); _i2c_wait_s(i2cp); #if !I2C_USE_WAIT i2c_lld_wait_bus_free(i2cp); @@ -179,10 +179,10 @@ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { * @param[in] i2cscfg pointer to the @p I2C slave config * */ -void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ +void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, size_t rxbytes){ chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ - (i2cscfg->rxbytes > 0) && \ + (rxbytes > 0) && \ (i2cscfg->rxbuf != NULL), "i2cMasterReceive"); @@ -204,7 +204,7 @@ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ "i2cMasterReceive(), #1", "not ready"); i2cp->id_state = I2C_ACTIVE; - i2c_lld_master_receive(i2cp); + i2c_lld_master_receive(i2cp, rxbytes); _i2c_wait_s(i2cp); #if !I2C_USE_WAIT i2c_lld_wait_bus_free(i2cp); @@ -215,11 +215,11 @@ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ } -uint16_t i2cSMBusAlertResponse(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { - - i2cMasterReceive(i2cp, i2cscfg); - return i2cp->id_slave_config->slave_addr; -} +//uint16_t i2cSMBusAlertResponse(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg) { +// +// i2cMasterReceive(i2cp, i2cscfg); +// return i2cp->id_slave_config->slave_addr; +//} /** @@ -236,7 +236,7 @@ void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask) { chDbgCheck(i2cp != NULL, "i2cAddFlagsI"); - i2cp->id_slave_config->errors |= mask; + i2cp->errors |= mask; chEvtBroadcastI(&i2cp->id_slave_config->sevent); } @@ -255,8 +255,8 @@ i2cflags_t i2cGetAndClearFlags(I2CDriver *i2cp) { chDbgCheck(i2cp != NULL, "i2cGetAndClearFlags"); chSysLock(); - mask = i2cp->id_slave_config->errors; - i2cp->id_slave_config->errors = I2CD_NO_ERROR; + mask = i2cp->errors; + i2cp->errors = I2CD_NO_ERROR; chSysUnlock(); return mask; } @@ -279,7 +279,7 @@ void i2cAcquireBus(I2CDriver *i2cp) { chDbgCheck(i2cp != NULL, "i2cAcquireBus"); #if CH_USE_MUTEXES - chMtxLock(&i2cp->mutex); + chMtxLock(&i2cp->id_mutex); #elif CH_USE_SEMAPHORES chSemWait(&i2cp->id_semaphore); #endif diff --git a/testhal/STM32/I2C/Makefile b/testhal/STM32/I2C/Makefile index 62eef3874..9f95a5914 100644 --- a/testhal/STM32/I2C/Makefile +++ b/testhal/STM32/I2C/Makefile @@ -77,9 +77,11 @@ CSRC = $(PORTSRC) \ $(CHIBIOS)/os/various/syscalls.c \ main.c \ i2c_pns.c \ - lis3.c\ - max1236.c\ - tmp75.c\ + tmp75.c\ + max1236.c\ + lis3.c\ + + # C++ sources that can be compiled in ARM or THUMB mode depending on the global # setting. diff --git a/testhal/STM32/I2C/lis3.c b/testhal/STM32/I2C/lis3.c index b07a51f13..a4eb40603 100644 --- a/testhal/STM32/I2C/lis3.c +++ b/testhal/STM32/I2C/lis3.c @@ -30,13 +30,9 @@ static void i2c_lis3_error_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ static I2CSlaveConfig lis3 = { NULL, i2c_lis3_error_cb, - 0, - 0, accel_rx_data, accel_tx_data, 0b0011101, - 0, - 0, {NULL}, }; @@ -109,20 +105,23 @@ int init_lis3(void){ while (i2c_accel_tp == NULL) chThdSleepMilliseconds(1); - lis3.rxbytes = 0; //set to 0 because we need only transmit +#define RXBYTES 0 //set to 0 because we need only transmit +#define TXBYTES 4 /* configure accelerometer */ - lis3.txbytes = 4; lis3.txbuf[0] = ACCEL_CTRL_REG1 | AUTO_INCREMENT_BIT; // register address lis3.txbuf[1] = 0b11100111; lis3.txbuf[2] = 0b01000001; lis3.txbuf[3] = 0b00000000; /* sending */ - i2cMasterTransmit(&I2CD1, &lis3); + i2cMasterTransmit(&I2CD1, &lis3, TXBYTES, RXBYTES); chThdSleepMilliseconds(1); lis3.id_callback = i2c_lis3_cb; +#undef RXBYTES +#undef TXBYTES + return 0; } @@ -130,11 +129,13 @@ int init_lis3(void){ * */ void request_acceleration_data(void){ +#define RXBYTES 6 +#define TXBYTES 1 lis3.txbuf[0] = ACCEL_OUT_DATA | AUTO_INCREMENT_BIT; // register address - lis3.txbytes = 1; - lis3.rxbytes = 6; i2cAcquireBus(&I2CD1); - i2cMasterTransmit(&I2CD1, &lis3); + i2cMasterTransmit(&I2CD1, &lis3, TXBYTES, RXBYTES); i2cReleaseBus(&I2CD1); +#undef RXBYTES +#undef TXBYTES } diff --git a/testhal/STM32/I2C/max1236.c b/testhal/STM32/I2C/max1236.c index f5f88bfc4..80e477170 100644 --- a/testhal/STM32/I2C/max1236.c +++ b/testhal/STM32/I2C/max1236.c @@ -42,13 +42,9 @@ static void i2c_max1236_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ static I2CSlaveConfig max1236 = { NULL, i2c_max1236_error_cb, - 0, - 0, max1236_rx_data, max1236_tx_data, 0b0110100, - 0, - 0, {NULL}, }; @@ -59,29 +55,34 @@ static I2CSlaveConfig max1236 = { */ void init_max1236(void){ /* this data we must send via IC to setup ADC */ - max1236.rxbytes = 0; - max1236.txbytes = 2; // total 2 bytes to be sent +#define RXBYTES 0 +#define TXBYTES 2 max1236.txbuf[0] = 0b10000011; // config register content. Consult datasheet max1236.txbuf[1] = 0b00000111; // config register content. Consult datasheet // transmit out 2 bytes i2cAcquireBus(&I2CD2); - i2cMasterTransmit(&I2CD2, &max1236); + i2cMasterTransmit(&I2CD2, &max1236, TXBYTES, RXBYTES); while(I2CD2.id_state != I2C_READY){ chThdSleepMilliseconds(1); } /* now add pointer to callback function */ max1236.id_callback = i2c_max1236_cb; i2cReleaseBus(&I2CD2); +#undef RXBYTES +#undef TXBYTES } /* Now simply read 8 bytes to get all 4 ADC channels */ void read_max1236(void){ - max1236.txbytes = 0; - max1236.rxbytes = 8; +#define TXBYTES 0 +#define RXBYTES 8 + i2cAcquireBus(&I2CD2); - i2cMasterReceive(&I2CD2, &max1236); + i2cMasterReceive(&I2CD2, &max1236, RXBYTES); i2cReleaseBus(&I2CD2); +#undef RXBYTES +#undef TXBYTES } diff --git a/testhal/STM32/I2C/tmp75.c b/testhal/STM32/I2C/tmp75.c index 80aa352ee..e5f502e23 100644 --- a/testhal/STM32/I2C/tmp75.c +++ b/testhal/STM32/I2C/tmp75.c @@ -37,23 +37,19 @@ static void i2c_tmp75_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ static I2CSlaveConfig tmp75 = { i2c_tmp75_cb, i2c_tmp75_error_cb, - 0, - 0, tmp75_rx_data, tmp75_tx_data, 0b1001000, - 0, - 0, {NULL}, }; /* This is main function. */ void request_temperature(void){ - tmp75.txbytes = 0; // set to zero because we need only reading - tmp75.rxbytes = 2; // we need to read 2 bytes +#define TXBYTES 0 // set to zero because we need only reading +#define RXBYTES 2 // we need to read 2 bytes i2cAcquireBus(&I2CD2); - i2cMasterReceive(&I2CD2, &tmp75); + i2cMasterReceive(&I2CD2, &tmp75, RXBYTES); i2cReleaseBus(&I2CD2); } From 70179f12dd387a82493d13fd51d5aab7e4e55674 Mon Sep 17 00:00:00 2001 From: barthess Date: Tue, 21 Jun 2011 20:17:14 +0000 Subject: [PATCH 52/92] I2C. Slave config structure now have const qualifier. Moset of fields moved to the driver structure. May be broken events subsystem in driver. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3067 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 20 +++--------- os/hal/platforms/STM32/i2c_lld.c | 36 +++++++++++++++------- os/hal/platforms/STM32/i2c_lld.h | 17 +++++----- os/hal/src/i2c.c | 24 +++++++++++---- testhal/STM32/I2C/lis3.c | 53 +++++++++++++++----------------- testhal/STM32/I2C/max1236.c | 12 +++----- testhal/STM32/I2C/tmp75.c | 7 +++-- 7 files changed, 90 insertions(+), 79 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index c46e7f096..ba7131c26 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -103,7 +103,7 @@ typedef enum { * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object triggering the * callback */ -typedef void (*i2ccallback_t)(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); +typedef void (*i2ccallback_t)(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg); /** @@ -114,7 +114,7 @@ typedef void (*i2ccallback_t)(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object triggering the * callback */ -typedef void (*i2cerrorcallback_t)(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg); +typedef void (*i2cerrorcallback_t)(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg); /** @@ -143,20 +143,8 @@ struct I2CSlaveConfig{ */ i2cerrorcallback_t id_err_callback; -// size_t txbytes; /*!< Number of bytes to transmitted. */ -// size_t rxbytes; /*!< Number of bytes to received. */ i2cblock_t *rxbuf; /*!< Pointer to receive buffer. */ i2cblock_t *txbuf; /*!< Pointer to transmit buffer.*/ - /** - * @brief Slave device address. - * @details Bits 0-9 contain slave device address. - * - * Bit 15 must be set to 1 if 10-bit addressing modes used. Otherwise - * keep it cleared. - * - * Bits 10-14 unused. - */ - uint16_t slave_addr; /* Status Change @p EventSource.*/ EventSource sevent; @@ -240,8 +228,8 @@ extern "C" { void i2cObjectInit(I2CDriver *i2cp); void i2cStart(I2CDriver *i2cp, const I2CConfig *config); void i2cStop(I2CDriver *i2cp); - void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, size_t txbytes, size_t rxbytes); - void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, size_t rxbytes); + void i2cMasterTransmit(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t slave_addr, size_t txbytes, size_t rxbytes); + void i2cMasterReceive(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t slave_addr, size_t rxbytes); void i2cMasterStart(I2CDriver *i2cp); void i2cMasterStop(I2CDriver *i2cp); void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask); diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index be7707796..729e14eb3 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -106,7 +106,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { /* Disable ITEVT In order to not have again a BTF IT */ dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; /* send restart and begin reading operations */ - i2c_lld_master_receive(i2cp, i2cp->rxbytes); + i2c_lld_master_receive(i2cp, i2cp->slave_addr, i2cp->rxbytes); } break; @@ -514,9 +514,16 @@ void i2c_lld_stop(I2CDriver *i2cp) { * @brief Transmits data ever the I2C bus as master. * * @param[in] i2cp pointer to the @p I2CDriver object + * @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 modes used. Otherwise keep it cleared. + * Bits 10-14 unused. + * @param[in] txbytes number of bytes to be transmited + * @param[in] rxbytes number of bytes to be received * */ -void i2c_lld_master_transmit(I2CDriver *i2cp, size_t txbytes, size_t rxbytes) { +void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, size_t txbytes, size_t rxbytes) { + i2cp->slave_addr = slave_addr; i2cp->txbytes = txbytes; i2cp->rxbytes = rxbytes; @@ -524,17 +531,17 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, size_t txbytes, size_t rxbytes) { i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - if(i2cp->id_slave_config->slave_addr & 0x8000){// 10-bit mode used + if(slave_addr & 0x8000){// 10-bit mode used // add the two msb of 10-bit address to the header - i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr >>7) & 0x0006); + i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); // add the header bits with LSB = 0 -> write i2cp->slave_addr1 |= 0xF0; // the remaining 8 bit of 10-bit address - i2cp->slave_addr2 = i2cp->id_slave_config->slave_addr & 0x00FF; + i2cp->slave_addr2 = slave_addr & 0x00FF; } else{ // LSB = 0 -> write - i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) & 0x00FE); + i2cp->slave_addr1 = ((slave_addr <<1) & 0x00FE); } i2cp->flags = 0; @@ -556,9 +563,16 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, size_t txbytes, size_t rxbytes) { * @brief Receives data from the I2C bus. * * @param[in] i2cp pointer to the @p I2CDriver object + * @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 modes used. Otherwise keep it cleared. + * Bits 10-14 unused. + * @param[in] txbytes number of bytes to be transmited + * @param[in] rxbytes number of bytes to be received * */ -void i2c_lld_master_receive(I2CDriver *i2cp, size_t rxbytes){ +void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t rxbytes){ + i2cp->slave_addr = slave_addr; i2cp->rxbytes = rxbytes; // enable ERR, EVT & BUF ITs @@ -566,17 +580,17 @@ void i2c_lld_master_receive(I2CDriver *i2cp, size_t rxbytes){ i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // acknowledge returned i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - if(i2cp->id_slave_config->slave_addr & 0x8000){// 10-bit mode used + if(slave_addr & 0x8000){// 10-bit mode used // add the two msb of 10-bit address to the header - i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr >>7) & 0x0006); + i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); // add the header bits (the LSB -> 1 will be add to second i2cp->slave_addr1 |= 0xF0; // the remaining 8 bit of 10-bit address - i2cp->slave_addr2 = i2cp->id_slave_config->slave_addr & 0x00FF; + i2cp->slave_addr2 = slave_addr & 0x00FF; } else{ // LSB = 1 -> receive - i2cp->slave_addr1 = ((i2cp->id_slave_config->slave_addr <<1) | 0x01); + i2cp->slave_addr1 = ((slave_addr <<1) | 0x01); } i2cp->flags = I2C_FLG_MASTER_RECEIVER; diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 83b4f7812..c3df51b07 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -161,17 +161,18 @@ struct I2CDriver{ /** * @brief Current slave configuration data. */ - I2CSlaveConfig *id_slave_config; + const I2CSlaveConfig *id_slave_config; - uint8_t slave_addr1; /*!< 7-bit address of the slave with r\w bit.*/ - uint8_t slave_addr2; /*!< used in 10-bit address mode. */ - - size_t rxbytes; - size_t txbytes; + size_t txbytes; /*!< Number of bytes to transmitted. */ + size_t rxbytes; /*!< Number of bytes to received. */ i2cflags_t errors; /*!< Error flags.*/ i2cflags_t flags; /*!< State flags.*/ + uint16_t slave_addr; /*!< Current slave address. */ + uint8_t slave_addr1; /*!< 7-bit address of the slave with r\w bit.*/ + uint8_t slave_addr2; /*!< Used in 10-bit address mode. */ + /*********** End of the mandatory fields. **********************************/ /** @@ -222,8 +223,8 @@ 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, size_t txbytes, size_t rxbytes); -void i2c_lld_master_receive(I2CDriver *i2cp, size_t rxbytes); +void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, size_t txbytes, size_t rxbytes); +void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t rxbytes); #ifdef __cplusplus } diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index dc48b9478..4e3f5e5b9 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -135,11 +135,17 @@ void i2cStop(I2CDriver *i2cp) { * * @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. Bits 0-9 contain slave + * device address. Bit 15 must be set to 1 if 10-bit + * addressing modes used. Otherwise keep it cleared. + * Bits 10-14 unused. + * @param[in] txbytes number of bytes to be transmited + * @param[in] rxbytes number of bytes to be received */ -void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, size_t txbytes, size_t rxbytes) { +void i2cMasterTransmit(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t slave_addr, size_t txbytes, size_t rxbytes) { chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ + (slave_addr != 0) &&\ (txbytes > 0) &&\ (i2cscfg->txbuf != NULL), "i2cMasterTransmit"); @@ -162,7 +168,7 @@ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, size_t txbytes, "i2cMasterTransmit(), #1", "not ready"); i2cp->id_state = I2C_ACTIVE; - i2c_lld_master_transmit(i2cp, txbytes, rxbytes); + i2c_lld_master_transmit(i2cp, slave_addr, txbytes, rxbytes); _i2c_wait_s(i2cp); #if !I2C_USE_WAIT i2c_lld_wait_bus_free(i2cp); @@ -177,11 +183,16 @@ void i2cMasterTransmit(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, size_t txbytes, * * @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. Bits 0-9 contain slave + * device address. Bit 15 must be set to 1 if 10-bit + * addressing modes used. Otherwise keep it cleared. + * Bits 10-14 unused. + * @param[in] txbytes number of bytes to be transmited */ -void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, size_t rxbytes){ +void i2cMasterReceive(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t slave_addr, size_t rxbytes){ chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ + (slave_addr != 0) &&\ (rxbytes > 0) && \ (i2cscfg->rxbuf != NULL), "i2cMasterReceive"); @@ -204,7 +215,7 @@ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, size_t rxbytes){ "i2cMasterReceive(), #1", "not ready"); i2cp->id_state = I2C_ACTIVE; - i2c_lld_master_receive(i2cp, rxbytes); + i2c_lld_master_receive(i2cp, slave_addr, rxbytes); _i2c_wait_s(i2cp); #if !I2C_USE_WAIT i2c_lld_wait_bus_free(i2cp); @@ -215,6 +226,7 @@ void i2cMasterReceive(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg, size_t rxbytes){ } +// 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); diff --git a/testhal/STM32/I2C/lis3.c b/testhal/STM32/I2C/lis3.c index a4eb40603..00bb712a1 100644 --- a/testhal/STM32/I2C/lis3.c +++ b/testhal/STM32/I2C/lis3.c @@ -26,20 +26,6 @@ static void i2c_lis3_error_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ while(TRUE); } -// Accelerometer lis3lv02dq config -static I2CSlaveConfig lis3 = { - NULL, - i2c_lis3_error_cb, - accel_rx_data, - accel_tx_data, - 0b0011101, - {NULL}, -}; - - - - - /** * This treading need for convenient realize * "read through write" process. @@ -53,7 +39,7 @@ static msg_t I2CAccelThread(void *arg) { int16_t acceleration_y = 0; int16_t acceleration_z = 0; - I2CDriver *i2cp; + I2CSlaveConfig *i2cscfg; msg_t msg; while (TRUE) { @@ -65,30 +51,42 @@ static msg_t I2CAccelThread(void *arg) { chSysUnlock(); /***************** Perform processing here. ***************************/ - i2cp = (I2CDriver *)msg; + i2cscfg = (I2CSlaveConfig *)msg; /* collect measured data */ - acceleration_x = lis3.rxbuf[0] + (lis3.rxbuf[1] << 8); - acceleration_y = lis3.rxbuf[2] + (lis3.rxbuf[3] << 8); - acceleration_z = lis3.rxbuf[4] + (lis3.rxbuf[5] << 8); + acceleration_x = i2cscfg->rxbuf[0] + (i2cscfg->rxbuf[1] << 8); + acceleration_y = i2cscfg->rxbuf[2] + (i2cscfg->rxbuf[3] << 8); + acceleration_z = i2cscfg->rxbuf[4] + (i2cscfg->rxbuf[5] << 8); } return 0; } - - /* This callback raise up when transfer finished */ static void i2c_lis3_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ - (void) i2cscfg; - + (void) i2cp; // only wake up processing thread if (i2c_accel_tp != NULL) { - i2c_accel_tp->p_msg = (msg_t)i2cp; + i2c_accel_tp->p_msg = (msg_t)i2cscfg; chSchReadyI(i2c_accel_tp); i2c_accel_tp = NULL; } } + +// Accelerometer lis3lv02dq config +static const I2CSlaveConfig lis3 = { + i2c_lis3_cb, + i2c_lis3_error_cb, + accel_rx_data, + accel_tx_data, + {NULL}, +}; + + +#define lis3_addr 0b0011101 + + + /** * Init function. Here we will also start personal serving thread. */ @@ -105,8 +103,8 @@ int init_lis3(void){ while (i2c_accel_tp == NULL) chThdSleepMilliseconds(1); -#define RXBYTES 0 //set to 0 because we need only transmit #define TXBYTES 4 +#define RXBYTES 0 //set to 0 because we need only transmit /* configure accelerometer */ lis3.txbuf[0] = ACCEL_CTRL_REG1 | AUTO_INCREMENT_BIT; // register address @@ -115,9 +113,8 @@ int init_lis3(void){ lis3.txbuf[3] = 0b00000000; /* sending */ - i2cMasterTransmit(&I2CD1, &lis3, TXBYTES, RXBYTES); + i2cMasterTransmit(&I2CD1, &lis3, lis3_addr, TXBYTES, RXBYTES); chThdSleepMilliseconds(1); - lis3.id_callback = i2c_lis3_cb; #undef RXBYTES #undef TXBYTES @@ -133,7 +130,7 @@ void request_acceleration_data(void){ #define TXBYTES 1 lis3.txbuf[0] = ACCEL_OUT_DATA | AUTO_INCREMENT_BIT; // register address i2cAcquireBus(&I2CD1); - i2cMasterTransmit(&I2CD1, &lis3, TXBYTES, RXBYTES); + i2cMasterTransmit(&I2CD1, &lis3, lis3_addr, TXBYTES, RXBYTES); i2cReleaseBus(&I2CD1); #undef RXBYTES #undef TXBYTES diff --git a/testhal/STM32/I2C/max1236.c b/testhal/STM32/I2C/max1236.c index 80e477170..ed9d12ca6 100644 --- a/testhal/STM32/I2C/max1236.c +++ b/testhal/STM32/I2C/max1236.c @@ -39,15 +39,15 @@ static void i2c_max1236_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ // ADC maxim MAX1236 config -static I2CSlaveConfig max1236 = { - NULL, +static const I2CSlaveConfig max1236 = { + i2c_max1236_cb, i2c_max1236_error_cb, max1236_rx_data, max1236_tx_data, - 0b0110100, {NULL}, }; +#define max1236_addr 0b0110100 /** * Initilization routine. See datasheet on page 13 to understand @@ -63,12 +63,10 @@ void init_max1236(void){ // transmit out 2 bytes i2cAcquireBus(&I2CD2); - i2cMasterTransmit(&I2CD2, &max1236, TXBYTES, RXBYTES); + i2cMasterTransmit(&I2CD2, &max1236, max1236_addr, TXBYTES, RXBYTES); while(I2CD2.id_state != I2C_READY){ chThdSleepMilliseconds(1); } - /* now add pointer to callback function */ - max1236.id_callback = i2c_max1236_cb; i2cReleaseBus(&I2CD2); #undef RXBYTES #undef TXBYTES @@ -81,7 +79,7 @@ void read_max1236(void){ #define RXBYTES 8 i2cAcquireBus(&I2CD2); - i2cMasterReceive(&I2CD2, &max1236, RXBYTES); + i2cMasterReceive(&I2CD2, &max1236, max1236_addr, RXBYTES); i2cReleaseBus(&I2CD2); #undef RXBYTES #undef TXBYTES diff --git a/testhal/STM32/I2C/tmp75.c b/testhal/STM32/I2C/tmp75.c index e5f502e23..6744fe325 100644 --- a/testhal/STM32/I2C/tmp75.c +++ b/testhal/STM32/I2C/tmp75.c @@ -34,22 +34,23 @@ static void i2c_tmp75_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ } // Fill TMP75 config. -static I2CSlaveConfig tmp75 = { +static const I2CSlaveConfig tmp75 = { i2c_tmp75_cb, i2c_tmp75_error_cb, tmp75_rx_data, tmp75_tx_data, - 0b1001000, {NULL}, }; +#define tmp75_addr 0b1001000 + /* This is main function. */ void request_temperature(void){ #define TXBYTES 0 // set to zero because we need only reading #define RXBYTES 2 // we need to read 2 bytes i2cAcquireBus(&I2CD2); - i2cMasterReceive(&I2CD2, &tmp75, RXBYTES); + i2cMasterReceive(&I2CD2, &tmp75, tmp75_addr, RXBYTES); i2cReleaseBus(&I2CD2); } From 24987e2873a946bc41ee1c5088b703abf9d7c526 Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 22 Jun 2011 08:38:54 +0000 Subject: [PATCH 53/92] I2C. Test changes git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3068 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- testhal/STM32/I2C/lis3.c | 4 ++-- testhal/STM32/I2C/max1236.c | 4 ++-- testhal/STM32/I2C/tmp75.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/testhal/STM32/I2C/lis3.c b/testhal/STM32/I2C/lis3.c index 00bb712a1..14616478b 100644 --- a/testhal/STM32/I2C/lis3.c +++ b/testhal/STM32/I2C/lis3.c @@ -19,7 +19,7 @@ static i2cblock_t accel_rx_data[ACCEL_RX_DEPTH]; static i2cblock_t accel_tx_data[ACCEL_TX_DEPTH]; /* Error trap */ -static void i2c_lis3_error_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ +static void i2c_lis3_error_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ (void)i2cscfg; int status = 0; status = i2cp->id_i2c->SR1; @@ -62,7 +62,7 @@ static msg_t I2CAccelThread(void *arg) { } /* This callback raise up when transfer finished */ -static void i2c_lis3_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ +static void i2c_lis3_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ (void) i2cp; // only wake up processing thread if (i2c_accel_tp != NULL) { diff --git a/testhal/STM32/I2C/max1236.c b/testhal/STM32/I2C/max1236.c index ed9d12ca6..2ba5f89b0 100644 --- a/testhal/STM32/I2C/max1236.c +++ b/testhal/STM32/I2C/max1236.c @@ -18,7 +18,7 @@ static uint16_t ch1 = 0, ch2 = 0, ch3 = 0, ch4 = 0; /* Error trap */ -static void i2c_max1236_error_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ +static void i2c_max1236_error_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ (void)i2cscfg; int status = 0; status = i2cp->id_i2c->SR1; @@ -27,7 +27,7 @@ static void i2c_max1236_error_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ /* This callback raise up when transfer finished */ -static void i2c_max1236_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ +static void i2c_max1236_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ (void)*i2cp; /* get ADC data */ ch1 = ((i2cscfg->rxbuf[0] & 0xF) << 8) + i2cscfg->rxbuf[1]; diff --git a/testhal/STM32/I2C/tmp75.c b/testhal/STM32/I2C/tmp75.c index 6744fe325..1d1432601 100644 --- a/testhal/STM32/I2C/tmp75.c +++ b/testhal/STM32/I2C/tmp75.c @@ -19,7 +19,7 @@ static i2cblock_t tmp75_tx_data[TMP75_TX_DEPTH]; static int16_t temperature = 0; // Simple error trap -static void i2c_tmp75_error_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ +static void i2c_tmp75_error_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ (void)i2cscfg; int status = 0; status = i2cp->id_i2c->SR1; @@ -27,7 +27,7 @@ static void i2c_tmp75_error_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ } /* This callback raise up when transfer finished */ -static void i2c_tmp75_cb(I2CDriver *i2cp, I2CSlaveConfig *i2cscfg){ +static void i2c_tmp75_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ (void)*i2cp; /* store temperature value */ temperature = (i2cscfg->rxbuf[0] << 8) + i2cscfg->rxbuf[1]; From 3f2e823d2aafa5e8ab70fd51b643de12c8989e76 Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 22 Jun 2011 18:00:20 +0000 Subject: [PATCH 54/92] I2C. Small improvemets git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3069 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 2 +- testhal/STM32/I2C/lis3.c | 2 +- testhal/STM32/I2C/max1236.c | 2 +- testhal/STM32/I2C/tmp75.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index ba7131c26..b2df49899 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -147,7 +147,7 @@ struct I2CSlaveConfig{ i2cblock_t *txbuf; /*!< Pointer to transmit buffer.*/ /* Status Change @p EventSource.*/ - EventSource sevent; + EventSource *sevent; }; diff --git a/testhal/STM32/I2C/lis3.c b/testhal/STM32/I2C/lis3.c index 14616478b..68d5a5403 100644 --- a/testhal/STM32/I2C/lis3.c +++ b/testhal/STM32/I2C/lis3.c @@ -79,7 +79,7 @@ static const I2CSlaveConfig lis3 = { i2c_lis3_error_cb, accel_rx_data, accel_tx_data, - {NULL}, + NULL, }; diff --git a/testhal/STM32/I2C/max1236.c b/testhal/STM32/I2C/max1236.c index 2ba5f89b0..636f04f74 100644 --- a/testhal/STM32/I2C/max1236.c +++ b/testhal/STM32/I2C/max1236.c @@ -44,7 +44,7 @@ static const I2CSlaveConfig max1236 = { i2c_max1236_error_cb, max1236_rx_data, max1236_tx_data, - {NULL}, + NULL, }; #define max1236_addr 0b0110100 diff --git a/testhal/STM32/I2C/tmp75.c b/testhal/STM32/I2C/tmp75.c index 1d1432601..66449ad6e 100644 --- a/testhal/STM32/I2C/tmp75.c +++ b/testhal/STM32/I2C/tmp75.c @@ -39,7 +39,7 @@ static const I2CSlaveConfig tmp75 = { i2c_tmp75_error_cb, tmp75_rx_data, tmp75_tx_data, - {NULL}, + NULL, }; #define tmp75_addr 0b1001000 From fbeff97d9230af12326c94e3875adf9438f16ed4 Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 23 Jun 2011 18:05:20 +0000 Subject: [PATCH 55/92] I2C. Variables shared among I2C1 and I2C2 interrupt handlers moved to driver structure. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3070 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 15 ++++++++------- os/hal/platforms/STM32/i2c_lld.h | 6 ++++-- os/hal/src/i2c.c | 2 ++ 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 729e14eb3..e59ef8d45 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -42,7 +42,8 @@ static uint32_t i2c_get_event(I2CDriver *i2cp){ } static void i2c_serve_event_interrupt(I2CDriver *i2cp) { - static __IO uint8_t *txBuffp, *rxBuffp, *datap; +#define txBuffp (i2cp->txBuffp) +#define rxBuffp (i2cp->rxBuffp) I2C_TypeDef *dp = i2cp->id_i2c; @@ -71,26 +72,24 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { } //Initialize the transmit buffer pointer txBuffp = (uint8_t*)i2cp->id_slave_config->txbuf; - datap = txBuffp; - txBuffp++; i2cp->txbytes--; /* If no further data to be sent, disable the I2C ITBUF in order to not have a TxE interrupt */ if(i2cp->txbytes == 0) { dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; } //EV8_1 write the first data - dp->DR = *datap; + dp->DR = *txBuffp; + txBuffp++; break; case I2C_EV8_MASTER_BYTE_TRANSMITTING: if(i2cp->txbytes > 0) { - datap = txBuffp; - txBuffp++; i2cp->txbytes--; if(i2cp->txbytes == 0) { /* If no further data to be sent, disable the ITBUF in order to not have a TxE interrupt */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; } - dp->DR = *datap; + dp->DR = *txBuffp; + txBuffp++; } break; case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: @@ -195,6 +194,8 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { } break; } +#undef rxBuffp +#undef txBuffp } static void i2c_serve_error_interrupt(I2CDriver *i2cp) { diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index c3df51b07..66ee95dd9 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -163,8 +163,10 @@ struct I2CDriver{ */ const I2CSlaveConfig *id_slave_config; - size_t txbytes; /*!< Number of bytes to transmitted. */ - size_t rxbytes; /*!< Number of bytes to received. */ + size_t txbytes; /*!< Number of bytes to be transmitted. */ + size_t rxbytes; /*!< Number of bytes to be received. */ + uint8_t *rxBuffp; /*!< Pointer to the current byte in slave rx buffer. */ + uint8_t *txBuffp; /*!< Pointer to the current byte in slave tx buffer. */ i2cflags_t errors; /*!< Error flags.*/ i2cflags_t flags; /*!< State flags.*/ diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 4e3f5e5b9..56e2f4484 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -69,6 +69,8 @@ void i2cObjectInit(I2CDriver *i2cp) { i2cp->id_state = I2C_STOP; i2cp->id_config = NULL; + i2cp->rxBuffp = NULL; + i2cp->txBuffp = NULL; i2cp->id_slave_config = NULL; #if I2C_USE_WAIT From 10153a4f3062c85b4595558df5df41f8962c6aae Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 23 Jun 2011 18:29:22 +0000 Subject: [PATCH 56/92] I2C. Fixed indent style. All tabs changed to 2 spaces. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3071 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 3 +- os/hal/platforms/STM32/i2c_lld.c | 62 ++++++++++++++++---------------- os/hal/platforms/STM32/i2c_lld.h | 18 +++++----- os/hal/src/i2c.c | 32 ++++++++--------- 4 files changed, 57 insertions(+), 58 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index b2df49899..066ee4a5f 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -146,8 +146,7 @@ struct I2CSlaveConfig{ i2cblock_t *rxbuf; /*!< Pointer to receive buffer. */ i2cblock_t *txbuf; /*!< Pointer to transmit buffer.*/ - /* Status Change @p EventSource.*/ - EventSource *sevent; + EventSource *sevent; /*!< Status Change @p EventSource.*/ }; diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index e59ef8d45..ba6225ba9 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -514,35 +514,35 @@ void i2c_lld_stop(I2CDriver *i2cp) { /** * @brief Transmits data ever the I2C bus as master. * - * @param[in] i2cp pointer to the @p I2CDriver object - * @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 modes used. Otherwise keep it cleared. - * Bits 10-14 unused. - * @param[in] txbytes number of bytes to be transmited - * @param[in] rxbytes number of bytes to be received + * @param[in] i2cp pointer to the @p I2CDriver object + * @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 modes used. Otherwise keep it cleared. + * Bits 10-14 unused. + * @param[in] txbytes number of bytes to be transmited + * @param[in] rxbytes number of bytes to be received * */ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, size_t txbytes, size_t rxbytes) { - i2cp->slave_addr = slave_addr; - i2cp->txbytes = txbytes; - i2cp->rxbytes = rxbytes; + i2cp->slave_addr = slave_addr; + i2cp->txbytes = txbytes; + i2cp->rxbytes = rxbytes; // enable ERR, EVT & BUF ITs i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; if(slave_addr & 0x8000){// 10-bit mode used - // add the two msb of 10-bit address to the header - i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); - // add the header bits with LSB = 0 -> write - i2cp->slave_addr1 |= 0xF0; - // the remaining 8 bit of 10-bit address - i2cp->slave_addr2 = slave_addr & 0x00FF; + // add the two msb of 10-bit address to the header + i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); + // add the header bits with LSB = 0 -> write + i2cp->slave_addr1 |= 0xF0; + // the remaining 8 bit of 10-bit address + i2cp->slave_addr2 = slave_addr & 0x00FF; } else{ - // LSB = 0 -> write - i2cp->slave_addr1 = ((slave_addr <<1) & 0x00FE); + // LSB = 0 -> write + i2cp->slave_addr1 = ((slave_addr <<1) & 0x00FE); } i2cp->flags = 0; @@ -563,13 +563,13 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, size_t txbyte /** * @brief Receives data from the I2C bus. * - * @param[in] i2cp pointer to the @p I2CDriver object - * @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 modes used. Otherwise keep it cleared. - * Bits 10-14 unused. - * @param[in] txbytes number of bytes to be transmited - * @param[in] rxbytes number of bytes to be received + * @param[in] i2cp pointer to the @p I2CDriver object + * @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 modes used. Otherwise keep it cleared. + * Bits 10-14 unused. + * @param[in] txbytes number of bytes to be transmited + * @param[in] rxbytes number of bytes to be received * */ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t rxbytes){ @@ -582,12 +582,12 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t rxbytes i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; if(slave_addr & 0x8000){// 10-bit mode used - // add the two msb of 10-bit address to the header - i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); - // add the header bits (the LSB -> 1 will be add to second - i2cp->slave_addr1 |= 0xF0; - // the remaining 8 bit of 10-bit address - i2cp->slave_addr2 = slave_addr & 0x00FF; + // add the two msb of 10-bit address to the header + i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); + // add the header bits (the LSB -> 1 will be add to second + i2cp->slave_addr1 |= 0xF0; + // the remaining 8 bit of 10-bit address + i2cp->slave_addr2 = slave_addr & 0x00FF; } else{ // LSB = 1 -> receive diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 66ee95dd9..0ad317876 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -163,17 +163,17 @@ struct I2CDriver{ */ const I2CSlaveConfig *id_slave_config; - size_t txbytes; /*!< Number of bytes to be transmitted. */ - size_t rxbytes; /*!< Number of bytes to be received. */ - uint8_t *rxBuffp; /*!< Pointer to the current byte in slave rx buffer. */ - uint8_t *txBuffp; /*!< Pointer to the current byte in slave tx buffer. */ + size_t txbytes; /*!< Number of bytes to be transmitted. */ + size_t rxbytes; /*!< Number of bytes to be received. */ + uint8_t *rxBuffp; /*!< Pointer to the current byte in slave rx buffer. */ + uint8_t *txBuffp; /*!< Pointer to the current byte in slave tx buffer. */ - i2cflags_t errors; /*!< Error flags.*/ - i2cflags_t flags; /*!< State flags.*/ + i2cflags_t errors; /*!< Error flags.*/ + i2cflags_t flags; /*!< State flags.*/ - uint16_t slave_addr; /*!< Current slave address. */ - uint8_t slave_addr1; /*!< 7-bit address of the slave with r\w bit.*/ - uint8_t slave_addr2; /*!< Used in 10-bit address mode. */ + uint16_t slave_addr; /*!< Current slave address. */ + uint8_t slave_addr1;/*!< 7-bit address of the slave with r\w bit.*/ + uint8_t slave_addr2;/*!< Used in 10-bit address mode. */ /*********** End of the mandatory fields. **********************************/ diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 56e2f4484..75541494f 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -135,14 +135,14 @@ void i2cStop(I2CDriver *i2cp) { /** * @brief Sends data ever the I2C bus. * - * @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. Bits 0-9 contain slave - * device address. Bit 15 must be set to 1 if 10-bit - * addressing modes used. Otherwise keep it cleared. - * Bits 10-14 unused. - * @param[in] txbytes number of bytes to be transmited - * @param[in] rxbytes number of bytes to be received + * @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. Bits 0-9 contain slave + * device address. Bit 15 must be set to 1 if 10-bit + * addressing modes used. Otherwise keep it cleared. + * Bits 10-14 unused. + * @param[in] txbytes number of bytes to be transmited + * @param[in] rxbytes number of bytes to be received */ void i2cMasterTransmit(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t slave_addr, size_t txbytes, size_t rxbytes) { @@ -183,13 +183,13 @@ void i2cMasterTransmit(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t /** * @brief Receives data from the I2C bus. * - * @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. Bits 0-9 contain slave - * device address. Bit 15 must be set to 1 if 10-bit - * addressing modes used. Otherwise keep it cleared. - * Bits 10-14 unused. - * @param[in] txbytes number of bytes to be transmited + * @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. Bits 0-9 contain slave + * device address. Bit 15 must be set to 1 if 10-bit + * addressing modes used. Otherwise keep it cleared. + * Bits 10-14 unused. + * @param[in] txbytes number of bytes to be transmited */ void i2cMasterReceive(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t slave_addr, size_t rxbytes){ @@ -251,7 +251,7 @@ void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask) { chDbgCheck(i2cp != NULL, "i2cAddFlagsI"); i2cp->errors |= mask; - chEvtBroadcastI(&i2cp->id_slave_config->sevent); + chEvtBroadcastI(&i2cp->sevent); } /** From 2f77482083766da5b081e3f7bd07924db88ee024 Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 23 Jun 2011 18:31:24 +0000 Subject: [PATCH 57/92] I2C. "Sevent" field moved from I2CSlaveConfig to I2CDriver. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3072 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 1 - os/hal/platforms/STM32/i2c_lld.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 066ee4a5f..8f8ae57f6 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -146,7 +146,6 @@ struct I2CSlaveConfig{ i2cblock_t *rxbuf; /*!< Pointer to receive buffer. */ i2cblock_t *txbuf; /*!< Pointer to transmit buffer.*/ - EventSource *sevent; /*!< Status Change @p EventSource.*/ }; diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 0ad317876..7083bf562 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -175,6 +175,8 @@ struct I2CDriver{ uint8_t slave_addr1;/*!< 7-bit address of the slave with r\w bit.*/ uint8_t slave_addr2;/*!< Used in 10-bit address mode. */ + EventSource sevent; /*!< Status Change @p EventSource.*/ + /*********** End of the mandatory fields. **********************************/ /** From 97e643a2a2086bf8d52c77d599748849ff6a8148 Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 23 Jun 2011 18:50:13 +0000 Subject: [PATCH 58/92] I2C. Commetns style changed to /**/. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3073 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 3 +- os/hal/platforms/STM32/i2c_lld.c | 132 ++++++++++++++++--------------- os/hal/platforms/STM32/i2c_lld.h | 10 +-- os/hal/src/i2c.c | 17 ++-- 4 files changed, 84 insertions(+), 78 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 8f8ae57f6..c14bf2a74 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -78,13 +78,14 @@ * @brief Driver state machine possible states. */ typedef enum { + /* master part */ I2C_UNINIT = 0, /**< @brief Not initialized. */ I2C_STOP = 1, /**< @brief Stopped. */ I2C_READY = 2, /**< @brief Ready. */ I2C_ACTIVE = 3, /**< @brief In communication. */ I2C_COMPLETE = 4, /**< @brief Asynchronous operation complete. */ - // slave part + /* slave part */ I2C_SACTIVE = 10, I2C_STRANSMIT = 11, I2C_SRECEIVE = 12, diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index ba6225ba9..6f2f26714 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -56,28 +56,27 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { if(i2cp->flags & I2C_FLG_MASTER_RECEIVER) { i2cp->slave_addr1 |= 0x01; i2cp->flags |= I2C_FLG_HEADER_SENT; -// i2cp->id_i2c->CR1 = (i2cp->id_i2c->CR1 & (~I2C_CR1_ACK)) | I2C_CR1_STOP; } dp->DR = i2cp->slave_addr2; break; - - //------------------------------------------------------------------------ - // Master Transmitter ---------------------------------------------------- - //------------------------------------------------------------------------ + /************************************************************************** + * Master Transmitter part + */ case I2C_EV6_MASTER_TRA_MODE_SELECTED: if(i2cp->flags & I2C_FLG_HEADER_SENT){ - dp->CR1 |= I2C_CR1_START; // re-send the start in 10-Bit address mode + dp->CR1 |= I2C_CR1_START; /* re-send the start in 10-Bit address mode */ break; } - //Initialize the transmit buffer pointer + /* Initialize the transmit buffer pointer */ txBuffp = (uint8_t*)i2cp->id_slave_config->txbuf; i2cp->txbytes--; - /* If no further data to be sent, disable the I2C ITBUF in order to not have a TxE interrupt */ + /* If no further data to be sent, disable the I2C ITBUF in order + * to not have a TxE interrupt */ if(i2cp->txbytes == 0) { dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; } - //EV8_1 write the first data + /* EV8_1 write the first data */ dp->DR = *txBuffp; txBuffp++; break; @@ -85,7 +84,8 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { if(i2cp->txbytes > 0) { i2cp->txbytes--; if(i2cp->txbytes == 0) { - /* If no further data to be sent, disable the ITBUF in order to not have a TxE interrupt */ + /* If no further data to be sent, disable the ITBUF in order to + * not have a TxE interrupt */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; } dp->DR = *txBuffp; @@ -95,10 +95,11 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: /* if nothing to read then generate stop */ if (i2cp->rxbytes == 0){ - dp->CR1 |= I2C_CR1_STOP; // stop generation + dp->CR1 |= I2C_CR1_STOP; /* Disable ITEVT In order to not have again a BTF IT */ dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; - /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ + /* Portable I2C ISR code defined in the high level driver, + * note, it is a macro.*/ _i2c_isr_code(i2cp, i2cp->id_slave_config); } else{ @@ -110,19 +111,19 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { break; - //------------------------------------------------------------------------ - // Master Receiver ------------------------------------------------------- - //------------------------------------------------------------------------ + /************************************************************************** + * Master Receiver part + */ case I2C_EV6_MASTER_REC_MODE_SELECTED: chSysLockFromIsr(); switch(i2cp->flags & EV6_SUBEV_MASK) { - case I2C_EV6_3_MASTER_REC_1BTR_MODE_SELECTED: // only an single byte to receive + case I2C_EV6_3_MASTER_REC_1BTR_MODE_SELECTED: /* only an single byte to receive */ /* Clear ACK */ dp->CR1 &= (uint16_t)~I2C_CR1_ACK; /* Program the STOP */ dp->CR1 |= I2C_CR1_STOP; break; - case I2C_EV6_1_MASTER_REC_2BTR_MODE_SELECTED: // only two bytes to receive + case I2C_EV6_1_MASTER_REC_2BTR_MODE_SELECTED: /* only two bytes to receive */ /* Clear ACK */ dp->CR1 &= (uint16_t)~I2C_CR1_ACK; /* Disable the ITBUF in order to have only the BTF interrupt */ @@ -151,18 +152,21 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { break; } } - // when remaining 3 bytes do nothing, wait until RXNE and BTF are set (until 2 bytes are received) + /* when remaining 3 bytes do nothing, wait until RXNE and BTF + * are set (until 2 bytes are received) */ break; case I2C_EV7_MASTER_REC_BYTE_QUEUED: switch(i2cp->flags & EV7_SUBEV_MASK) { case I2C_EV7_2_MASTER_REC_3BYTES_TO_PROCESS: - // DataN-2 and DataN-1 are received + /* DataN-2 and DataN-1 are received */ chSysLockFromIsr(); dp->CR2 |= I2C_CR2_ITBUFEN; /* Clear ACK */ dp->CR1 &= (uint16_t)~I2C_CR1_ACK; - /* Read the DataN-2*/ - *rxBuffp = dp->DR; //This clear the RXE & BFT flags and launch the DataN reception in the shift register (ending the SCL stretch) + /* Read the DataN-2 + * This clear the RXE & BFT flags and launch the DataN r + * eception in the shift register (ending the SCL stretch) */ + *rxBuffp = dp->DR; rxBuffp++; /* Program the STOP */ dp->CR1 |= I2C_CR1_STOP; @@ -173,10 +177,10 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { /* Decrement the number of readed bytes */ i2cp->rxbytes -= 2; i2cp->flags = 0; - // ready for read DataN on the next EV7 + /* ready for read DataN on the next EV7 */ break; - case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: // only for case of two bytes to be received - // DataN-1 and DataN are received + case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: /* only for case of two bytes to be received */ + /* DataN-1 and DataN are received */ chSysLockFromIsr(); /* Program the STOP */ dp->CR1 |= I2C_CR1_STOP; @@ -205,38 +209,38 @@ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { reg = i2cp->id_i2c; flags = I2CD_NO_ERROR; - if(reg->SR1 & I2C_SR1_BERR) { // Bus error + if(reg->SR1 & I2C_SR1_BERR) { /* Bus error */ reg->SR1 &= ~I2C_SR1_BERR; flags |= I2CD_BUS_ERROR; } - if(reg->SR1 & I2C_SR1_ARLO) { // Arbitration lost + if(reg->SR1 & I2C_SR1_ARLO) { /* Arbitration lost */ reg->SR1 &= ~I2C_SR1_ARLO; flags |= I2CD_ARBITRATION_LOST; } - if(reg->SR1 & I2C_SR1_AF) { // Acknowledge fail + if(reg->SR1 & I2C_SR1_AF) { /* Acknowledge fail */ reg->SR1 &= ~I2C_SR1_AF; - reg->CR1 |= I2C_CR1_STOP; // setting stop bit + reg->CR1 |= I2C_CR1_STOP; /* setting stop bit */ flags |= I2CD_ACK_FAILURE; } - if(reg->SR1 & I2C_SR1_OVR) { // Overrun + if(reg->SR1 & I2C_SR1_OVR) { /* Overrun */ reg->SR1 &= ~I2C_SR1_OVR; flags |= I2CD_OVERRUN; } - if(reg->SR1 & I2C_SR1_PECERR) { // PEC error + if(reg->SR1 & I2C_SR1_PECERR) { /* PEC error */ reg->SR1 &= ~I2C_SR1_PECERR; flags |= I2CD_PEC_ERROR; } - if(reg->SR1 & I2C_SR1_TIMEOUT) { // SMBus Timeout + if(reg->SR1 & I2C_SR1_TIMEOUT) { /* SMBus Timeout */ reg->SR1 &= ~I2C_SR1_TIMEOUT; flags |= I2CD_TIMEOUT; } - if(reg->SR1 & I2C_SR1_SMBALERT) { // SMBus alert + if(reg->SR1 & I2C_SR1_SMBALERT) { /* SMBus alert */ reg->SR1 &= ~I2C_SR1_SMBALERT; flags |= I2CD_SMB_ALERT; } if(flags != I2CD_NO_ERROR) { - // send communication end signal + /* send communication end signal */ _i2c_isr_code(i2cp, i2cp->id_slave_config); chSysLockFromIsr(); i2cAddFlagsI(i2cp, flags); @@ -295,14 +299,14 @@ CH_IRQ_HANDLER(VectorC8) { void i2c_lld_init(void) { #if STM32_I2C_USE_I2C1 - RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; // reset I2C 1 + RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; /* reset I2C 1 */ RCC->APB1RSTR = 0; i2cObjectInit(&I2CD1); I2CD1.id_i2c = I2C1; #endif #if STM32_I2C_USE_I2C2 - RCC->APB1RSTR = RCC_APB1RSTR_I2C2RST; // reset I2C 2 + RCC->APB1RSTR = RCC_APB1RSTR_I2C2RST; /* reset I2C 2 */ RCC->APB1RSTR = 0; i2cObjectInit(&I2CD2); I2CD2.id_i2c = I2C2; @@ -322,33 +326,35 @@ void i2c_lld_start(I2CDriver *i2cp) { if (&I2CD1 == i2cp) { NVICEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); NVICEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); - RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // I2C 1 clock enable + RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; /* I2C 1 clock enable */ } #endif #if STM32_I2C_USE_I2C2 if (&I2CD2 == i2cp) { NVICEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); NVICEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); - RCC->APB1ENR |= RCC_APB1ENR_I2C2EN; // I2C 2 clock enable + RCC->APB1ENR |= RCC_APB1ENR_I2C2EN; /* I2C 2 clock enable */ } #endif } /* I2C setup.*/ - i2cp->id_i2c->CR1 = I2C_CR1_SWRST; // reset i2c peripherial + i2cp->id_i2c->CR1 = I2C_CR1_SWRST; /* reset i2c peripherial */ i2cp->id_i2c->CR1 = 0; i2c_lld_set_clock(i2cp); i2c_lld_set_opmode(i2cp); - i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN | I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN;// enable interrupts - i2cp->id_i2c->CR1 |= 1; // enable interface + /* enable interrupts */ + i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN | I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; + /* enable interface */ + i2cp->id_i2c->CR1 |= 1; } void i2c_lld_reset(I2CDriver *i2cp){ chDbgCheck((i2cp->id_state == I2C_STOP)||(i2cp->id_state == I2C_READY), "i2c_lld_reset: invalid state"); - RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; // reset I2C 1 + RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; /* reset I2C 1 */ RCC->APB1RSTR = 0; } @@ -466,12 +472,12 @@ void i2c_lld_set_opmode(I2CDriver *i2cp) { * @param[in] i2cp pointer to the @p I2CDriver object */ void i2c_lld_set_own_address(I2CDriver *i2cp) { - //TODO: dual address mode + /* TODO: dual address mode */ - /*---------------------------- OAR1 Configuration -----------------------*/ + /* OAR1 Configuration */ i2cp->id_i2c->OAR1 |= 1 << 14; - if (&(i2cp->id_config->own_addr_10) == NULL){// only 7-bit address + if (&(i2cp->id_config->own_addr_10) == NULL){/* only 7-bit address */ i2cp->id_i2c->OAR1 &= (~I2C_OAR1_ADDMODE); i2cp->id_i2c->OAR1 |= i2cp->id_config->own_addr_7 << 1; } @@ -528,27 +534,27 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, size_t txbyte i2cp->txbytes = txbytes; i2cp->rxbytes = rxbytes; - // enable ERR, EVT & BUF ITs + /* enable ERR, EVT & BUF ITs */ i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - if(slave_addr & 0x8000){// 10-bit mode used - // add the two msb of 10-bit address to the header + if(slave_addr & 0x8000){/* 10-bit mode used */ + /* add the two msb of 10-bit address to the header */ i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); - // add the header bits with LSB = 0 -> write + /* add the header bits with LSB = 0 -> write */ i2cp->slave_addr1 |= 0xF0; - // the remaining 8 bit of 10-bit address + /* the remaining 8 bit of 10-bit address */ i2cp->slave_addr2 = slave_addr & 0x00FF; } else{ - // LSB = 0 -> write + /* LSB = 0 -> write */ i2cp->slave_addr1 = ((slave_addr <<1) & 0x00FE); } i2cp->flags = 0; i2cp->errors = 0; - i2cp->id_i2c->CR1 |= I2C_CR1_START; // send start bit + i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ #if !I2C_USE_WAIT /* Wait until the START condition is generated on the bus: @@ -576,38 +582,38 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t rxbytes i2cp->slave_addr = slave_addr; i2cp->rxbytes = rxbytes; - // enable ERR, EVT & BUF ITs + /* enable ERR, EVT & BUF ITs */ i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); - i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // acknowledge returned + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - if(slave_addr & 0x8000){// 10-bit mode used - // add the two msb of 10-bit address to the header + if(slave_addr & 0x8000){/* 10-bit mode used */ + /* add the two msb of 10-bit address to the header */ i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); - // add the header bits (the LSB -> 1 will be add to second + /* add the header bits (the LSB -> 1 will be add to second */ i2cp->slave_addr1 |= 0xF0; - // the remaining 8 bit of 10-bit address + /* the remaining 8 bit of 10-bit address */ i2cp->slave_addr2 = slave_addr & 0x00FF; } else{ - // LSB = 1 -> receive + /* LSB = 1 -> receive */ i2cp->slave_addr1 = ((slave_addr <<1) | 0x01); } i2cp->flags = I2C_FLG_MASTER_RECEIVER; i2cp->errors = 0; - // Only one byte to be received + /* Only one byte to be received */ if(i2cp->rxbytes == 1) { i2cp->flags |= I2C_FLG_1BTR; } - // Only two bytes to be received + /* Only two bytes to be received */ else if(i2cp->rxbytes == 2) { i2cp->flags |= I2C_FLG_2BTR; - i2cp->id_i2c->CR1 |= I2C_CR1_POS; // Acknowledge Position + i2cp->id_i2c->CR1 |= I2C_CR1_POS; /* Acknowledge Position */ } - i2cp->id_i2c->CR1 |= I2C_CR1_START; // send start bit + i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ #if !I2C_USE_WAIT /* Wait until the START condition is generated on the bus: @@ -619,4 +625,4 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t rxbytes } -#endif // HAL_USE_I2C +#endif /* HAL_USE_I2C */ diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 7083bf562..d0c1415c4 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -72,9 +72,9 @@ #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 -#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_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 @@ -235,6 +235,6 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t rxbytes #endif /** @endcond*/ -#endif // CH_HAL_USE_I2C +#endif /* CH_HAL_USE_I2C */ -#endif // _I2C_LLD_H_ +#endif /* _I2C_LLD_H_ */ diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 75541494f..377b27ecf 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -152,7 +152,7 @@ void i2cMasterTransmit(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t (i2cscfg->txbuf != NULL), "i2cMasterTransmit"); - // init slave config field in driver + /* init slave config field in driver */ i2cp->id_slave_config = i2cscfg; #if I2C_USE_WAIT @@ -199,7 +199,7 @@ void i2cMasterReceive(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t s (i2cscfg->rxbuf != NULL), "i2cMasterReceive"); - // init slave config field in driver + /* init slave config field in driver */ i2cp->id_slave_config = i2cscfg; #if I2C_USE_WAIT @@ -228,13 +228,12 @@ void i2cMasterReceive(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t s } -// 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; -//} - +/* 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. From b1d043cede9e37dccff9731978887f51a514c387 Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 23 Jun 2011 19:06:33 +0000 Subject: [PATCH 59/92] I2C. Some coding style improvements. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3074 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 9 ++++++--- os/hal/platforms/STM32/i2c_lld.c | 4 ++-- os/hal/platforms/STM32/i2c_lld.h | 10 ++++++---- os/hal/src/i2c.c | 15 +++++++++++---- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index c14bf2a74..a024ddd9e 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -115,7 +115,8 @@ typedef void (*i2ccallback_t)(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg); * @param[in] i2cscfg pointer to the @p I2CSlaveConfig object triggering the * callback */ -typedef void (*i2cerrorcallback_t)(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg); +typedef void (*i2cerrorcallback_t)(I2CDriver *i2cp, + const I2CSlaveConfig *i2cscfg); /** @@ -227,8 +228,10 @@ extern "C" { void i2cObjectInit(I2CDriver *i2cp); void i2cStart(I2CDriver *i2cp, const I2CConfig *config); void i2cStop(I2CDriver *i2cp); - void i2cMasterTransmit(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t slave_addr, size_t txbytes, size_t rxbytes); - void i2cMasterReceive(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t slave_addr, size_t rxbytes); + void i2cMasterTransmit(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, + uint16_t slave_addr, size_t txbytes, size_t rxbytes); + void i2cMasterReceive(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, + uint16_t slave_addr, size_t rxbytes); void i2cMasterStart(I2CDriver *i2cp); void i2cMasterStop(I2CDriver *i2cp); void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask); diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 6f2f26714..1dc58e8e6 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -42,8 +42,8 @@ static uint32_t i2c_get_event(I2CDriver *i2cp){ } static void i2c_serve_event_interrupt(I2CDriver *i2cp) { -#define txBuffp (i2cp->txBuffp) -#define rxBuffp (i2cp->rxBuffp) +#define txBuffp (i2cp->txbuff_p) +#define rxBuffp (i2cp->rxbuff_p) I2C_TypeDef *dp = i2cp->id_i2c; diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index d0c1415c4..51c975c37 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -165,8 +165,8 @@ struct I2CDriver{ size_t txbytes; /*!< Number of bytes to be transmitted. */ size_t rxbytes; /*!< Number of bytes to be received. */ - uint8_t *rxBuffp; /*!< Pointer to the current byte in slave rx buffer. */ - uint8_t *txBuffp; /*!< Pointer to the current byte in slave tx buffer. */ + uint8_t *rxbuff_p; /*!< Pointer to the current byte in slave rx buffer. */ + uint8_t *txbuff_p; /*!< Pointer to the current byte in slave tx buffer. */ i2cflags_t errors; /*!< Error flags.*/ i2cflags_t flags; /*!< State flags.*/ @@ -227,8 +227,10 @@ 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, size_t txbytes, size_t rxbytes); -void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t rxbytes); +void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, + size_t txbytes, size_t rxbytes); +void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, + size_t rxbytes); #ifdef __cplusplus } diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 377b27ecf..490ecf656 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -69,8 +69,8 @@ void i2cObjectInit(I2CDriver *i2cp) { i2cp->id_state = I2C_STOP; i2cp->id_config = NULL; - i2cp->rxBuffp = NULL; - i2cp->txBuffp = NULL; + i2cp->rxbuff_p = NULL; + i2cp->txbuff_p = NULL; i2cp->id_slave_config = NULL; #if I2C_USE_WAIT @@ -144,7 +144,11 @@ void i2cStop(I2CDriver *i2cp) { * @param[in] txbytes number of bytes to be transmited * @param[in] rxbytes number of bytes to be received */ -void i2cMasterTransmit(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t slave_addr, size_t txbytes, size_t rxbytes) { +void i2cMasterTransmit(I2CDriver *i2cp, + const I2CSlaveConfig *i2cscfg, + uint16_t slave_addr, + size_t txbytes, + size_t rxbytes) { chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ (slave_addr != 0) &&\ @@ -191,7 +195,10 @@ void i2cMasterTransmit(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t * Bits 10-14 unused. * @param[in] txbytes number of bytes to be transmited */ -void i2cMasterReceive(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t slave_addr, size_t rxbytes){ +void i2cMasterReceive(I2CDriver *i2cp, + const I2CSlaveConfig *i2cscfg, + uint16_t slave_addr, + size_t rxbytes){ chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ (slave_addr != 0) &&\ From 429c031bcb61267a0f20969c5a66eceeefbbb68b Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 23 Jun 2011 19:08:49 +0000 Subject: [PATCH 60/92] I2C. Examples fixed. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3075 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- testhal/STM32/I2C/lis3.c | 1 - testhal/STM32/I2C/max1236.c | 1 - testhal/STM32/I2C/tmp75.c | 1 - 3 files changed, 3 deletions(-) diff --git a/testhal/STM32/I2C/lis3.c b/testhal/STM32/I2C/lis3.c index 68d5a5403..9ce1532a6 100644 --- a/testhal/STM32/I2C/lis3.c +++ b/testhal/STM32/I2C/lis3.c @@ -79,7 +79,6 @@ static const I2CSlaveConfig lis3 = { i2c_lis3_error_cb, accel_rx_data, accel_tx_data, - NULL, }; diff --git a/testhal/STM32/I2C/max1236.c b/testhal/STM32/I2C/max1236.c index 636f04f74..7ea184b14 100644 --- a/testhal/STM32/I2C/max1236.c +++ b/testhal/STM32/I2C/max1236.c @@ -44,7 +44,6 @@ static const I2CSlaveConfig max1236 = { i2c_max1236_error_cb, max1236_rx_data, max1236_tx_data, - NULL, }; #define max1236_addr 0b0110100 diff --git a/testhal/STM32/I2C/tmp75.c b/testhal/STM32/I2C/tmp75.c index 66449ad6e..6a8fe603d 100644 --- a/testhal/STM32/I2C/tmp75.c +++ b/testhal/STM32/I2C/tmp75.c @@ -39,7 +39,6 @@ static const I2CSlaveConfig tmp75 = { i2c_tmp75_error_cb, tmp75_rx_data, tmp75_tx_data, - NULL, }; #define tmp75_addr 0b1001000 From d2b62026fc589cb36955d173417c0741edea4b4a Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 23 Jun 2011 20:18:58 +0000 Subject: [PATCH 61/92] I2C. Small comment added. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3076 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 1 + 1 file changed, 1 insertion(+) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 1dc58e8e6..0bc113313 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -42,6 +42,7 @@ static uint32_t i2c_get_event(I2CDriver *i2cp){ } static void i2c_serve_event_interrupt(I2CDriver *i2cp) { +/* defines for convenience purpose*/ #define txBuffp (i2cp->txbuff_p) #define rxBuffp (i2cp->rxbuff_p) From 73ce7b4fe096f227fbabbe471a283f1b916383fb Mon Sep 17 00:00:00 2001 From: barthess Date: Fri, 24 Jun 2011 10:36:41 +0000 Subject: [PATCH 62/92] I2C. Commets in examples changed to /**/ git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3077 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.h | 4 ++-- testhal/STM32/I2C/lis3.c | 10 +++++----- testhal/STM32/I2C/max1236.c | 12 ++++++------ testhal/STM32/I2C/tmp75.c | 12 ++++++------ 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 51c975c37..d9cd40915 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -165,8 +165,8 @@ struct I2CDriver{ size_t txbytes; /*!< Number of bytes to be transmitted. */ size_t rxbytes; /*!< Number of bytes to be received. */ - uint8_t *rxbuff_p; /*!< Pointer to the current byte in slave rx buffer. */ - uint8_t *txbuff_p; /*!< Pointer to the current byte in slave tx buffer. */ + uint8_t *rxbuff_p; /*!< Pointer to the current byte in slave rx buffer. */ + uint8_t *txbuff_p; /*!< Pointer to the current byte in slave tx buffer. */ i2cflags_t errors; /*!< Error flags.*/ i2cflags_t flags; /*!< State flags.*/ diff --git a/testhal/STM32/I2C/lis3.c b/testhal/STM32/I2C/lis3.c index 9ce1532a6..c50d7e9a6 100644 --- a/testhal/STM32/I2C/lis3.c +++ b/testhal/STM32/I2C/lis3.c @@ -14,7 +14,7 @@ #include "lis3.h" -// buffers +/* buffers */ static i2cblock_t accel_rx_data[ACCEL_RX_DEPTH]; static i2cblock_t accel_tx_data[ACCEL_TX_DEPTH]; @@ -64,7 +64,7 @@ static msg_t I2CAccelThread(void *arg) { /* This callback raise up when transfer finished */ static void i2c_lis3_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ (void) i2cp; - // only wake up processing thread + /* only wake up processing thread */ if (i2c_accel_tp != NULL) { i2c_accel_tp->p_msg = (msg_t)i2cscfg; chSchReadyI(i2c_accel_tp); @@ -73,7 +73,7 @@ static void i2c_lis3_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ } -// Accelerometer lis3lv02dq config +/* Accelerometer lis3lv02dq config */ static const I2CSlaveConfig lis3 = { i2c_lis3_cb, i2c_lis3_error_cb, @@ -103,10 +103,10 @@ int init_lis3(void){ chThdSleepMilliseconds(1); #define TXBYTES 4 -#define RXBYTES 0 //set to 0 because we need only transmit +#define RXBYTES 0 /* set to 0 because we need only transmit */ /* configure accelerometer */ - lis3.txbuf[0] = ACCEL_CTRL_REG1 | AUTO_INCREMENT_BIT; // register address + lis3.txbuf[0] = ACCEL_CTRL_REG1 | AUTO_INCREMENT_BIT; /* register address */ lis3.txbuf[1] = 0b11100111; lis3.txbuf[2] = 0b01000001; lis3.txbuf[3] = 0b00000000; diff --git a/testhal/STM32/I2C/max1236.c b/testhal/STM32/I2C/max1236.c index 7ea184b14..13779b99a 100644 --- a/testhal/STM32/I2C/max1236.c +++ b/testhal/STM32/I2C/max1236.c @@ -10,10 +10,10 @@ #include "max1236.h" -// Data buffers +/* Data buffers */ static i2cblock_t max1236_rx_data[MAX1236_RX_DEPTH]; static i2cblock_t max1236_tx_data[MAX1236_TX_DEPTH]; -// ADC results +/* ADC results */ static uint16_t ch1 = 0, ch2 = 0, ch3 = 0, ch4 = 0; @@ -37,7 +37,7 @@ static void i2c_max1236_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ } -// ADC maxim MAX1236 config +/* ADC maxim MAX1236 config */ static const I2CSlaveConfig max1236 = { i2c_max1236_cb, @@ -56,11 +56,11 @@ void init_max1236(void){ /* this data we must send via IC to setup ADC */ #define RXBYTES 0 #define TXBYTES 2 - max1236.txbuf[0] = 0b10000011; // config register content. Consult datasheet - max1236.txbuf[1] = 0b00000111; // config register content. Consult datasheet + max1236.txbuf[0] = 0b10000011; /* config register content. Consult datasheet */ + max1236.txbuf[1] = 0b00000111; /* config register content. Consult datasheet */ - // transmit out 2 bytes + /* transmit out 2 bytes */ i2cAcquireBus(&I2CD2); i2cMasterTransmit(&I2CD2, &max1236, max1236_addr, TXBYTES, RXBYTES); while(I2CD2.id_state != I2C_READY){ diff --git a/testhal/STM32/I2C/tmp75.c b/testhal/STM32/I2C/tmp75.c index 6a8fe603d..0833e47c1 100644 --- a/testhal/STM32/I2C/tmp75.c +++ b/testhal/STM32/I2C/tmp75.c @@ -12,13 +12,13 @@ #include "tmp75.h" -// input buffer +/* input buffer */ static i2cblock_t tmp75_rx_data[TMP75_RX_DEPTH]; static i2cblock_t tmp75_tx_data[TMP75_TX_DEPTH]; -// temperature value +/* temperature value */ static int16_t temperature = 0; -// Simple error trap +/* Simple error trap */ static void i2c_tmp75_error_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ (void)i2cscfg; int status = 0; @@ -33,7 +33,7 @@ static void i2c_tmp75_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ temperature = (i2cscfg->rxbuf[0] << 8) + i2cscfg->rxbuf[1]; } -// Fill TMP75 config. +/* Fill TMP75 config. */ static const I2CSlaveConfig tmp75 = { i2c_tmp75_cb, i2c_tmp75_error_cb, @@ -45,8 +45,8 @@ static const I2CSlaveConfig tmp75 = { /* This is main function. */ void request_temperature(void){ -#define TXBYTES 0 // set to zero because we need only reading -#define RXBYTES 2 // we need to read 2 bytes +#define TXBYTES 0 /* set to zero because we need only reading */ +#define RXBYTES 2 /* we need to read 2 bytes */ i2cAcquireBus(&I2CD2); i2cMasterReceive(&I2CD2, &tmp75, tmp75_addr, RXBYTES); From f73960c8dcbcc2f4f4b4aba8599a45485038ec82 Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 30 Jun 2011 13:43:42 +0000 Subject: [PATCH 63/92] I2C. API changed. Transmit and receive buffers removed from I2CSlaveConfig. Now pointers to that buffers pass in functions arguments. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3099 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 10 ++++------ os/hal/platforms/STM32/i2c_lld.c | 17 ++++++++++++----- os/hal/platforms/STM32/i2c_lld.h | 6 ++++-- os/hal/src/i2c.c | 15 ++++++++++----- 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index a024ddd9e..953bd88dd 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -144,10 +144,6 @@ struct I2CSlaveConfig{ * If set to @p NULL then the callback is disabled. */ i2cerrorcallback_t id_err_callback; - - i2cblock_t *rxbuf; /*!< Pointer to receive buffer. */ - i2cblock_t *txbuf; /*!< Pointer to transmit buffer.*/ - }; @@ -229,9 +225,11 @@ extern "C" { void i2cStart(I2CDriver *i2cp, const I2CConfig *config); void i2cStop(I2CDriver *i2cp); void i2cMasterTransmit(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, - uint16_t slave_addr, size_t txbytes, size_t rxbytes); + uint16_t slave_addr, + uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes); void i2cMasterReceive(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, - uint16_t slave_addr, size_t rxbytes); + uint16_t slave_addr, uint8_t *rxbuf, size_t rxbytes); void i2cMasterStart(I2CDriver *i2cp); void i2cMasterStop(I2CDriver *i2cp); void i2cAddFlagsI(I2CDriver *i2cp, i2cflags_t mask); diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 0bc113313..d9ca29a9e 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -70,7 +70,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { break; } /* Initialize the transmit buffer pointer */ - txBuffp = (uint8_t*)i2cp->id_slave_config->txbuf; + txBuffp = (uint8_t*)i2cp->txbuf; i2cp->txbytes--; /* If no further data to be sent, disable the I2C ITBUF in order * to not have a TxE interrupt */ @@ -107,7 +107,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { /* Disable ITEVT In order to not have again a BTF IT */ dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; /* send restart and begin reading operations */ - i2c_lld_master_receive(i2cp, i2cp->slave_addr, i2cp->rxbytes); + i2c_lld_master_receive(i2cp, i2cp->slave_addr, i2cp->rxbuf, i2cp->rxbytes); } break; @@ -133,7 +133,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { } chSysUnlockFromIsr(); /* Initialize receive buffer pointer */ - rxBuffp = i2cp->id_slave_config->rxbuf; + rxBuffp = i2cp->rxbuf; break; case I2C_EV7_MASTER_REC_BYTE_RECEIVED: if(i2cp->rxbytes != 3) { @@ -530,10 +530,14 @@ void i2c_lld_stop(I2CDriver *i2cp) { * @param[in] rxbytes number of bytes to be received * */ -void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, size_t txbytes, size_t rxbytes) { +void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, + uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes) { + i2cp->slave_addr = slave_addr; i2cp->txbytes = txbytes; i2cp->rxbytes = rxbytes; + i2cp->txbuf = txbuf; + i2cp->rxbuf = rxbuf; /* enable ERR, EVT & BUF ITs */ i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); @@ -579,9 +583,12 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, size_t txbyte * @param[in] rxbytes number of bytes to be received * */ -void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, size_t rxbytes){ +void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, + uint8_t *rxbuf, size_t rxbytes){ + i2cp->slave_addr = slave_addr; i2cp->rxbytes = rxbytes; + i2cp->rxbuf = rxbuf; /* enable ERR, EVT & BUF ITs */ i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index d9cd40915..f1f065359 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -165,6 +165,8 @@ struct I2CDriver{ size_t txbytes; /*!< Number of bytes to be transmitted. */ size_t rxbytes; /*!< Number of bytes to be received. */ + uint8_t *rxbuf; /*!< Pointer to receive buffer. */ + uint8_t *txbuf; /*!< Pointer to transmit buffer.*/ uint8_t *rxbuff_p; /*!< Pointer to the current byte in slave rx buffer. */ uint8_t *txbuff_p; /*!< Pointer to the current byte in slave tx buffer. */ @@ -228,9 +230,9 @@ 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, - size_t txbytes, 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, - size_t rxbytes); + uint8_t *rxbuf, size_t rxbytes); #ifdef __cplusplus } diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 490ecf656..dca7c6125 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -141,19 +141,23 @@ void i2cStop(I2CDriver *i2cp) { * device address. Bit 15 must be set to 1 if 10-bit * addressing modes used. Otherwise keep it cleared. * Bits 10-14 unused. - * @param[in] txbytes number of bytes to be transmited + * @param[in] txbytes number of bytes to be transmitted + * @param[in] txbuf pointer to transmit buffer * @param[in] rxbytes number of bytes to be received + * @param[in] rxbuf pointer to receive buffer */ void i2cMasterTransmit(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t slave_addr, + uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes) { chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ (slave_addr != 0) &&\ (txbytes > 0) &&\ - (i2cscfg->txbuf != NULL), + (txbuf != NULL), "i2cMasterTransmit"); /* init slave config field in driver */ @@ -174,7 +178,7 @@ void i2cMasterTransmit(I2CDriver *i2cp, "i2cMasterTransmit(), #1", "not ready"); i2cp->id_state = I2C_ACTIVE; - i2c_lld_master_transmit(i2cp, slave_addr, txbytes, rxbytes); + i2c_lld_master_transmit(i2cp, slave_addr, txbuf, txbytes, rxbuf, rxbytes); _i2c_wait_s(i2cp); #if !I2C_USE_WAIT i2c_lld_wait_bus_free(i2cp); @@ -198,12 +202,13 @@ void i2cMasterTransmit(I2CDriver *i2cp, void i2cMasterReceive(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, uint16_t slave_addr, + uint8_t *rxbuf, size_t rxbytes){ chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ (slave_addr != 0) &&\ (rxbytes > 0) && \ - (i2cscfg->rxbuf != NULL), + (rxbuf != NULL), "i2cMasterReceive"); /* init slave config field in driver */ @@ -224,7 +229,7 @@ void i2cMasterReceive(I2CDriver *i2cp, "i2cMasterReceive(), #1", "not ready"); i2cp->id_state = I2C_ACTIVE; - i2c_lld_master_receive(i2cp, slave_addr, rxbytes); + i2c_lld_master_receive(i2cp, slave_addr, rxbuf, rxbytes); _i2c_wait_s(i2cp); #if !I2C_USE_WAIT i2c_lld_wait_bus_free(i2cp); From 551a1c1f22fb53085ab9485115fc3d27af92083c Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 30 Jun 2011 21:37:34 +0000 Subject: [PATCH 64/92] I2C. Added dirty hack to realize thread safe dirver. Needs to be rewrited. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3100 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 6 ++++++ os/hal/src/i2c.c | 16 ++++++---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 953bd88dd..60b2c322d 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -210,10 +210,16 @@ struct I2CSlaveConfig{ (i2cp)->id_state = I2C_COMPLETE; \ if(((i2cp)->id_slave_config)->id_callback) { \ ((i2cp)->id_slave_config)->id_callback(i2cp, i2cscfg); \ + if((i2cp)->id_state == I2C_COMPLETE) \ + (i2cp)->id_state = I2C_READY; \ } \ + else \ + (i2cp)->id_state = I2C_READY; \ _i2c_wakeup_isr(i2cp); \ + i2cReleaseBus(i2cp); \ } + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index dca7c6125..725e92d65 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -71,6 +71,8 @@ void i2cObjectInit(I2CDriver *i2cp) { i2cp->id_config = NULL; i2cp->rxbuff_p = NULL; i2cp->txbuff_p = NULL; + i2cp->rxbuf = NULL; + i2cp->txbuf = NULL; i2cp->id_slave_config = NULL; #if I2C_USE_WAIT @@ -154,6 +156,8 @@ void i2cMasterTransmit(I2CDriver *i2cp, uint8_t *rxbuf, size_t rxbytes) { + i2cAcquireBus(i2cp); + chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ (slave_addr != 0) &&\ (txbytes > 0) &&\ @@ -180,11 +184,6 @@ void i2cMasterTransmit(I2CDriver *i2cp, i2cp->id_state = I2C_ACTIVE; i2c_lld_master_transmit(i2cp, slave_addr, txbuf, txbytes, rxbuf, rxbytes); _i2c_wait_s(i2cp); -#if !I2C_USE_WAIT - i2c_lld_wait_bus_free(i2cp); -#endif - if (i2cp->id_state == I2C_COMPLETE) - i2cp->id_state = I2C_READY; chSysUnlock(); } @@ -205,6 +204,8 @@ void i2cMasterReceive(I2CDriver *i2cp, uint8_t *rxbuf, size_t rxbytes){ + i2cAcquireBus(i2cp); + chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ (slave_addr != 0) &&\ (rxbytes > 0) && \ @@ -231,11 +232,6 @@ void i2cMasterReceive(I2CDriver *i2cp, i2cp->id_state = I2C_ACTIVE; i2c_lld_master_receive(i2cp, slave_addr, rxbuf, rxbytes); _i2c_wait_s(i2cp); -#if !I2C_USE_WAIT - i2c_lld_wait_bus_free(i2cp); -#endif - if (i2cp->id_state == I2C_COMPLETE) - i2cp->id_state = I2C_READY; chSysUnlock(); } From af0e40079ded13b8842e8d129fa6ed2f37fdf678 Mon Sep 17 00:00:00 2001 From: barthess Date: Fri, 1 Jul 2011 13:36:59 +0000 Subject: [PATCH 65/92] I2C. Trying to add optional WAIT support. Driver broken. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3101 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 11 ++++----- os/hal/platforms/STM32/i2c_lld.c | 34 ++++++++++++++++----------- os/hal/platforms/STM32/i2c_lld.h | 2 +- os/hal/src/i2c.c | 40 ++++++++++++++------------------ 4 files changed, 44 insertions(+), 43 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 60b2c322d..0a4ba8b53 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -165,9 +165,9 @@ struct I2CSlaveConfig{ * @notapi */ #define _i2c_wait_s(i2cp) { \ - chDbgAssert((i2cp)->thread == NULL, \ + chDbgAssert((i2cp)->id_thread == NULL, \ "_i2c_wait(), #1", "already waiting"); \ - (i2cp)->thread = chThdSelf(); \ + (i2cp)->id_thread = chThdSelf(); \ chSchGoSleepS(THD_STATE_SUSPENDED); \ } @@ -179,9 +179,9 @@ struct I2CSlaveConfig{ * @notapi */ #define _i2c_wakeup_isr(i2cp) { \ - if ((i2cp)->thread != NULL) { \ - Thread *tp = (i2cp)->thread; \ - (i2cp)->thread = NULL; \ + if ((i2cp)->id_thread != NULL) { \ + Thread *tp = (i2cp)->id_thread; \ + (i2cp)->id_thread = NULL; \ chSysLockFromIsr(); \ chSchReadyI(tp); \ chSysUnlockFromIsr(); \ @@ -216,7 +216,6 @@ struct I2CSlaveConfig{ else \ (i2cp)->id_state = I2C_READY; \ _i2c_wakeup_isr(i2cp); \ - i2cReleaseBus(i2cp); \ } diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index d9ca29a9e..a4aa2927d 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -561,13 +561,16 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ -#if !I2C_USE_WAIT - /* Wait until the START condition is generated on the bus: - * the START bit is cleared by hardware */ - uint32_t timeout = 0xfffff; - while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) - ; -#endif /* I2C_USE_WAIT */ +//#if !I2C_USE_WAIT +// /* Wait until the START condition is generated on the bus: +// * the START bit is cleared by hardware */ +// uint32_t timeout = 0xfffff; +// while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) +// ; +//#endif /* I2C_USE_WAIT */ + uint32_t timeout = 0xfffff; + while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) + ; } @@ -623,13 +626,16 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ -#if !I2C_USE_WAIT - /* Wait until the START condition is generated on the bus: - * the START bit is cleared by hardware */ - uint32_t timeout = 0xfffff; - while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) - ; -#endif /* I2C_USE_WAIT */ +//#if !I2C_USE_WAIT +// /* Wait until the START condition is generated on the bus: +// * the START bit is cleared by hardware */ +// uint32_t timeout = 0xfffff; +// while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) +// ; +//#endif /* I2C_USE_WAIT */ + uint32_t timeout = 0xfffff; + while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) + ; } diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index f1f065359..0b95a893d 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -142,7 +142,7 @@ struct I2CDriver{ /** * @brief Thread waiting for I/O completion. */ - Thread *thread; + Thread *id_thread; #endif /* I2C_USE_WAIT */ #if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) #if CH_USE_MUTEXES || defined(__DOXYGEN__) diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 725e92d65..3f4095aa3 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -156,8 +156,6 @@ void i2cMasterTransmit(I2CDriver *i2cp, uint8_t *rxbuf, size_t rxbytes) { - i2cAcquireBus(i2cp); - chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ (slave_addr != 0) &&\ (txbytes > 0) &&\ @@ -167,15 +165,15 @@ void i2cMasterTransmit(I2CDriver *i2cp, /* init slave config field in driver */ i2cp->id_slave_config = i2cscfg; -#if I2C_USE_WAIT - i2c_lld_wait_bus_free(i2cp); - if(i2c_lld_bus_is_busy(i2cp)) { -#ifdef PRINTTRACE - print("I2C Bus busy!\n"); -#endif - return; - }; -#endif +//#if I2C_USE_WAIT +// i2c_lld_wait_bus_free(i2cp); +// if(i2c_lld_bus_is_busy(i2cp)) { +//#ifdef PRINTTRACE +// print("I2C Bus busy!\n"); +//#endif +// return; +// }; +//#endif chSysLock(); chDbgAssert(i2cp->id_state == I2C_READY, @@ -204,8 +202,6 @@ void i2cMasterReceive(I2CDriver *i2cp, uint8_t *rxbuf, size_t rxbytes){ - i2cAcquireBus(i2cp); - chDbgCheck((i2cp != NULL) && (i2cscfg != NULL) &&\ (slave_addr != 0) &&\ (rxbytes > 0) && \ @@ -215,15 +211,15 @@ void i2cMasterReceive(I2CDriver *i2cp, /* init slave config field in driver */ i2cp->id_slave_config = i2cscfg; -#if I2C_USE_WAIT - i2c_lld_wait_bus_free(i2cp); - if(i2c_lld_bus_is_busy(i2cp)) { -#ifdef PRINTTRACE - print("I2C Bus busy!\n"); -#endif - return; - }; -#endif +//#if I2C_USE_WAIT +// i2c_lld_wait_bus_free(i2cp); +// if(i2c_lld_bus_is_busy(i2cp)) { +//#ifdef PRINTTRACE +// print("I2C Bus busy!\n"); +//#endif +// return; +// }; +//#endif chSysLock(); chDbgAssert(i2cp->id_state == I2C_READY, From ccb28114da9485c5e3f950fd31dfb67be1b8a173 Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 3 Jul 2011 18:02:55 +0000 Subject: [PATCH 66/92] I2C. Driver looks working, but sometimes hangs up. I don't know, my big project cause troubles in it, or driver cause troubles in my project. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3116 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 35 ++++++++++-- os/hal/platforms/STM32/i2c_lld.c | 95 +++++++++++++++++++++++++------- os/hal/platforms/STM32/i2c_lld.h | 2 + os/hal/src/i2c.c | 42 ++++++++------ testhal/STM32/I2C/halconf.h | 8 +++ testhal/STM32/I2C/lis3.c | 22 ++++---- testhal/STM32/I2C/main.c | 19 +++++++ testhal/STM32/I2C/max1236.c | 19 +++---- testhal/STM32/I2C/tmp75.c | 8 +-- 9 files changed, 179 insertions(+), 71 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 0a4ba8b53..774c0cf22 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -165,9 +165,9 @@ struct I2CSlaveConfig{ * @notapi */ #define _i2c_wait_s(i2cp) { \ - chDbgAssert((i2cp)->id_thread == NULL, \ + chDbgAssert((i2cp)->id_thread == NULL, \ "_i2c_wait(), #1", "already waiting"); \ - (i2cp)->id_thread = chThdSelf(); \ + (i2cp)->id_thread = chThdSelf(); \ chSchGoSleepS(THD_STATE_SUSPENDED); \ } @@ -179,9 +179,9 @@ struct I2CSlaveConfig{ * @notapi */ #define _i2c_wakeup_isr(i2cp) { \ - if ((i2cp)->id_thread != NULL) { \ - Thread *tp = (i2cp)->id_thread; \ - (i2cp)->id_thread = NULL; \ + if ((i2cp)->id_thread != NULL) { \ + Thread *tp = (i2cp)->id_thread; \ + (i2cp)->id_thread = NULL; \ chSysLockFromIsr(); \ chSchReadyI(tp); \ chSysUnlockFromIsr(); \ @@ -218,6 +218,31 @@ struct I2CSlaveConfig{ _i2c_wakeup_isr(i2cp); \ } +/** + * @brief Error ISR code. + * @details This code handles the portable part of the ISR code: + * - Error callback invocation. + * - Waiting thread wakeup, if any. + * - Driver state transitions. + * + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define _i2c_isr_err_code(i2cp, i2cscfg) { \ + (i2cp)->id_state = I2C_COMPLETE; \ + if(((i2cp)->id_slave_config)->id_err_callback) { \ + ((i2cp)->id_slave_config)->id_err_callback(i2cp, i2cscfg); \ + if((i2cp)->id_state == I2C_COMPLETE) \ + (i2cp)->id_state = I2C_READY; \ + } \ + else \ + (i2cp)->id_state = I2C_READY; \ + _i2c_wakeup_isr(i2cp); \ +} /*===========================================================================*/ /* External declarations. */ diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index a4aa2927d..30352f3c4 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -94,20 +94,20 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { } break; case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: + /* Disable ITEVT In order to not have again a BTF IT */ + dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; /* if nothing to read then generate stop */ if (i2cp->rxbytes == 0){ dp->CR1 |= I2C_CR1_STOP; - /* Disable ITEVT In order to not have again a BTF IT */ - dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; /* Portable I2C ISR code defined in the high level driver, * note, it is a macro.*/ _i2c_isr_code(i2cp, i2cp->id_slave_config); } else{ - /* Disable ITEVT In order to not have again a BTF IT */ - dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; /* send restart and begin reading operations */ - i2c_lld_master_receive(i2cp, i2cp->slave_addr, i2cp->rxbuf, i2cp->rxbytes); + chSysLockFromIsr(); + i2c_lld_master_transceive(i2cp); + chSysUnlockFromIsr(); } break; @@ -242,10 +242,10 @@ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { if(flags != I2CD_NO_ERROR) { /* send communication end signal */ - _i2c_isr_code(i2cp, i2cp->id_slave_config); chSysLockFromIsr(); i2cAddFlagsI(i2cp, flags); chSysUnlockFromIsr(); + _i2c_isr_err_code(i2cp, i2cp->id_slave_config); } } @@ -539,10 +539,6 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, i2cp->txbuf = txbuf; i2cp->rxbuf = rxbuf; - /* enable ERR, EVT & BUF ITs */ - i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); - i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - if(slave_addr & 0x8000){/* 10-bit mode used */ /* add the two msb of 10-bit address to the header */ i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); @@ -568,9 +564,18 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, // while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) // ; //#endif /* I2C_USE_WAIT */ - uint32_t timeout = 0xfffff; - while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) - ; + + + uint32_t timeout = I2C_START_TIMEOUT; + while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) + ; + /* is timeout overflows? */ + chDbgAssert(timeout < I2C_START_TIMEOUT, + "i2c_lld_master_transmit(), #1", "time is out"); + + /* enable ERR, EVT & BUF ITs */ + i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; } @@ -593,11 +598,6 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, i2cp->rxbytes = rxbytes; i2cp->rxbuf = rxbuf; - /* enable ERR, EVT & BUF ITs */ - i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); - i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ - i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - if(slave_addr & 0x8000){/* 10-bit mode used */ /* add the two msb of 10-bit address to the header */ i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); @@ -633,9 +633,62 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, // while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) // ; //#endif /* I2C_USE_WAIT */ - uint32_t timeout = 0xfffff; - while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) - ; + + + uint32_t timeout = I2C_START_TIMEOUT; + while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) + ; + /* is timeout overflows? */ + chDbgAssert(timeout < I2C_START_TIMEOUT, + "i2c_lld_master_receive(), #1", "time is out"); + + /* enable ERR, EVT & BUF ITs */ + i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ + i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; +} + + + +void i2c_lld_master_transceive(I2CDriver *i2cp){ + + i2cp->flags = I2C_FLG_MASTER_RECEIVER; + i2cp->errors = 0; + + i2cp->slave_addr1 |= 0x01; + + /* Only one byte to be received */ + if(i2cp->rxbytes == 1) { + i2cp->flags |= I2C_FLG_1BTR; + } + /* Only two bytes to be received */ + else if(i2cp->rxbytes == 2) { + i2cp->flags |= I2C_FLG_2BTR; + i2cp->id_i2c->CR1 |= I2C_CR1_POS; /* Acknowledge Position */ + } + + i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ + +//#if !I2C_USE_WAIT +// /* Wait until the START condition is generated on the bus: +// * the START bit is cleared by hardware */ +// uint32_t timeout = 0xfffff; +// while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) +// ; +//#endif /* I2C_USE_WAIT */ + + + uint32_t timeout = I2C_START_TIMEOUT; + while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) + ; + /* is timeout overflows? */ + chDbgAssert(timeout < I2C_START_TIMEOUT, + "i2c_lld_master_receive(), #1", "time is out"); + + /* enable ERR, EVT & BUF ITs */ + i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ + i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; } diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 0b95a893d..2659e4475 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -13,6 +13,7 @@ /*===========================================================================*/ /* Driver constants. */ /*===========================================================================*/ +#define I2C_START_TIMEOUT 0xFFFF /*===========================================================================*/ /* Driver pre-compile time settings. */ @@ -233,6 +234,7 @@ 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 } diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 3f4095aa3..93d00bcae 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -165,15 +165,18 @@ void i2cMasterTransmit(I2CDriver *i2cp, /* init slave config field in driver */ i2cp->id_slave_config = i2cscfg; -//#if I2C_USE_WAIT -// i2c_lld_wait_bus_free(i2cp); -// if(i2c_lld_bus_is_busy(i2cp)) { -//#ifdef PRINTTRACE -// print("I2C Bus busy!\n"); -//#endif -// return; -// }; -//#endif +#if I2C_USE_WAIT + i2c_lld_wait_bus_free(i2cp); + if(i2c_lld_bus_is_busy(i2cp)) { +#ifdef PRINTTRACE + print("I2C Bus busy!\n"); + return; +#else + /* the time is out */ + chDbgAssert(FALSE, "i2cMasterTransmit(), #1", "time is out"); +#endif + }; +#endif chSysLock(); chDbgAssert(i2cp->id_state == I2C_READY, @@ -211,15 +214,18 @@ void i2cMasterReceive(I2CDriver *i2cp, /* init slave config field in driver */ i2cp->id_slave_config = i2cscfg; -//#if I2C_USE_WAIT -// i2c_lld_wait_bus_free(i2cp); -// if(i2c_lld_bus_is_busy(i2cp)) { -//#ifdef PRINTTRACE -// print("I2C Bus busy!\n"); -//#endif -// return; -// }; -//#endif +#if I2C_USE_WAIT + i2c_lld_wait_bus_free(i2cp); + if(i2c_lld_bus_is_busy(i2cp)) { +#ifdef PRINTTRACE + print("I2C Bus busy!\n"); + return; +#else + /* the time is out */ + chDbgAssert(FALSE, "i2cMasterReceive(), #1", "time is out"); +#endif + }; +#endif chSysLock(); chDbgAssert(i2cp->id_state == I2C_READY, diff --git a/testhal/STM32/I2C/halconf.h b/testhal/STM32/I2C/halconf.h index b128d89cf..65d88f586 100644 --- a/testhal/STM32/I2C/halconf.h +++ b/testhal/STM32/I2C/halconf.h @@ -173,6 +173,14 @@ /* I2C driver related settings. */ /*===========================================================================*/ +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(I2C_USE_WAIT) || defined(__DOXYGEN__) +#define I2C_USE_WAIT TRUE +#endif + /** * @brief Enables the mutual exclusion APIs on the I2C bus. */ diff --git a/testhal/STM32/I2C/lis3.c b/testhal/STM32/I2C/lis3.c index c50d7e9a6..26a3292f5 100644 --- a/testhal/STM32/I2C/lis3.c +++ b/testhal/STM32/I2C/lis3.c @@ -54,9 +54,9 @@ static msg_t I2CAccelThread(void *arg) { i2cscfg = (I2CSlaveConfig *)msg; /* collect measured data */ - acceleration_x = i2cscfg->rxbuf[0] + (i2cscfg->rxbuf[1] << 8); - acceleration_y = i2cscfg->rxbuf[2] + (i2cscfg->rxbuf[3] << 8); - acceleration_z = i2cscfg->rxbuf[4] + (i2cscfg->rxbuf[5] << 8); + acceleration_x = accel_rx_data[0] + (accel_rx_data[1] << 8); + acceleration_y = accel_rx_data[2] + (accel_rx_data[3] << 8); + acceleration_z = accel_rx_data[4] + (accel_rx_data[5] << 8); } return 0; } @@ -77,8 +77,6 @@ static void i2c_lis3_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ static const I2CSlaveConfig lis3 = { i2c_lis3_cb, i2c_lis3_error_cb, - accel_rx_data, - accel_tx_data, }; @@ -106,13 +104,13 @@ int init_lis3(void){ #define RXBYTES 0 /* set to 0 because we need only transmit */ /* configure accelerometer */ - lis3.txbuf[0] = ACCEL_CTRL_REG1 | AUTO_INCREMENT_BIT; /* register address */ - lis3.txbuf[1] = 0b11100111; - lis3.txbuf[2] = 0b01000001; - lis3.txbuf[3] = 0b00000000; + accel_tx_data[0] = ACCEL_CTRL_REG1 | AUTO_INCREMENT_BIT; /* register address */ + accel_tx_data[1] = 0b11100111; + accel_tx_data[2] = 0b01000001; + accel_tx_data[3] = 0b00000000; /* sending */ - i2cMasterTransmit(&I2CD1, &lis3, lis3_addr, TXBYTES, RXBYTES); + i2cMasterTransmit(&I2CD1, &lis3, lis3_addr, accel_tx_data, TXBYTES, accel_rx_data, RXBYTES); chThdSleepMilliseconds(1); #undef RXBYTES @@ -127,9 +125,9 @@ int init_lis3(void){ void request_acceleration_data(void){ #define RXBYTES 6 #define TXBYTES 1 - lis3.txbuf[0] = ACCEL_OUT_DATA | AUTO_INCREMENT_BIT; // register address + accel_tx_data[0] = ACCEL_OUT_DATA | AUTO_INCREMENT_BIT; // register address i2cAcquireBus(&I2CD1); - i2cMasterTransmit(&I2CD1, &lis3, lis3_addr, TXBYTES, RXBYTES); + i2cMasterTransmit(&I2CD1, &lis3, lis3_addr, accel_tx_data, TXBYTES, accel_rx_data, RXBYTES); i2cReleaseBus(&I2CD1); #undef RXBYTES #undef TXBYTES diff --git a/testhal/STM32/I2C/main.c b/testhal/STM32/I2C/main.c index 793f73f49..ce8cb5522 100644 --- a/testhal/STM32/I2C/main.c +++ b/testhal/STM32/I2C/main.c @@ -29,6 +29,23 @@ +/* + * Red LEDs blinker thread, times are in milliseconds. + */ +static WORKING_AREA(BlinkWA, 128); +static msg_t Blink(void *arg) { + (void)arg; + while (TRUE) { + palClearPad(IOPORT3, GPIOC_LED); + chThdSleepMilliseconds(500); + palSetPad(IOPORT3, GPIOC_LED); + chThdSleepMilliseconds(500); + } + return 0; +} + + + /* Temperature polling thread */ static WORKING_AREA(PollTmp75ThreadWA, 128); static msg_t PollTmp75Thread(void *arg) { @@ -110,6 +127,8 @@ int main(void) { PollAccelThread, NULL); + /* Creates the blinker thread. */ + chThdCreateStatic(BlinkWA, sizeof(BlinkWA), LOWPRIO, Blink, NULL); /* main loop that do nothing */ while (TRUE) { diff --git a/testhal/STM32/I2C/max1236.c b/testhal/STM32/I2C/max1236.c index 13779b99a..3e3dbd0c1 100644 --- a/testhal/STM32/I2C/max1236.c +++ b/testhal/STM32/I2C/max1236.c @@ -29,11 +29,12 @@ static void i2c_max1236_error_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg) /* This callback raise up when transfer finished */ static void i2c_max1236_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ (void)*i2cp; + (void)*i2cscfg; /* get ADC data */ - ch1 = ((i2cscfg->rxbuf[0] & 0xF) << 8) + i2cscfg->rxbuf[1]; - ch2 = ((i2cscfg->rxbuf[2] & 0xF) << 8) + i2cscfg->rxbuf[3]; - ch3 = ((i2cscfg->rxbuf[4] & 0xF) << 8) + i2cscfg->rxbuf[5]; - ch4 = ((i2cscfg->rxbuf[6] & 0xF) << 8) + i2cscfg->rxbuf[7]; + 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]; } @@ -42,8 +43,6 @@ static void i2c_max1236_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ static const I2CSlaveConfig max1236 = { i2c_max1236_cb, i2c_max1236_error_cb, - max1236_rx_data, - max1236_tx_data, }; #define max1236_addr 0b0110100 @@ -56,13 +55,13 @@ void init_max1236(void){ /* this data we must send via IC to setup ADC */ #define RXBYTES 0 #define TXBYTES 2 - max1236.txbuf[0] = 0b10000011; /* config register content. Consult datasheet */ - max1236.txbuf[1] = 0b00000111; /* config register content. Consult datasheet */ + 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, TXBYTES, RXBYTES); + i2cMasterTransmit(&I2CD2, &max1236, max1236_addr, max1236_tx_data, TXBYTES, max1236_rx_data, RXBYTES); while(I2CD2.id_state != I2C_READY){ chThdSleepMilliseconds(1); } @@ -78,7 +77,7 @@ void read_max1236(void){ #define RXBYTES 8 i2cAcquireBus(&I2CD2); - i2cMasterReceive(&I2CD2, &max1236, max1236_addr, RXBYTES); + i2cMasterReceive(&I2CD2, &max1236, max1236_addr, max1236_rx_data, RXBYTES); i2cReleaseBus(&I2CD2); #undef RXBYTES #undef TXBYTES diff --git a/testhal/STM32/I2C/tmp75.c b/testhal/STM32/I2C/tmp75.c index 0833e47c1..6276e7c8e 100644 --- a/testhal/STM32/I2C/tmp75.c +++ b/testhal/STM32/I2C/tmp75.c @@ -14,7 +14,6 @@ /* input buffer */ static i2cblock_t tmp75_rx_data[TMP75_RX_DEPTH]; -static i2cblock_t tmp75_tx_data[TMP75_TX_DEPTH]; /* temperature value */ static int16_t temperature = 0; @@ -29,16 +28,15 @@ static void i2c_tmp75_error_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ /* This callback raise up when transfer finished */ static void i2c_tmp75_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ (void)*i2cp; + (void)*i2cscfg; /* store temperature value */ - temperature = (i2cscfg->rxbuf[0] << 8) + i2cscfg->rxbuf[1]; + temperature = (tmp75_rx_data[0] << 8) + tmp75_rx_data[1]; } /* Fill TMP75 config. */ static const I2CSlaveConfig tmp75 = { i2c_tmp75_cb, i2c_tmp75_error_cb, - tmp75_rx_data, - tmp75_tx_data, }; #define tmp75_addr 0b1001000 @@ -49,7 +47,7 @@ void request_temperature(void){ #define RXBYTES 2 /* we need to read 2 bytes */ i2cAcquireBus(&I2CD2); - i2cMasterReceive(&I2CD2, &tmp75, tmp75_addr, RXBYTES); + i2cMasterReceive(&I2CD2, &tmp75, tmp75_addr, tmp75_rx_data, RXBYTES); i2cReleaseBus(&I2CD2); } From 03acd18161901b17be78e280ebbebbc0bbd47c8f Mon Sep 17 00:00:00 2001 From: barthess Date: Mon, 4 Jul 2011 14:27:00 +0000 Subject: [PATCH 67/92] git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3117 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 57 +++++++++++++++++++++----------- os/hal/platforms/STM32/i2c_lld.h | 3 +- os/hal/src/i2c.c | 17 +++++----- 3 files changed, 48 insertions(+), 29 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 30352f3c4..f44749e11 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -28,6 +28,8 @@ I2CDriver I2CD2; /*===========================================================================*/ /* Driver local variables. */ /*===========================================================================*/ +static volatile uint16_t regSR1 = 0; +static volatile uint16_t regSR2 = 0; /*===========================================================================*/ /* Driver local functions. */ @@ -35,8 +37,8 @@ I2CDriver I2CD2; static uint32_t i2c_get_event(I2CDriver *i2cp){ - uint32_t regSR1 = i2cp->id_i2c->SR1; - uint32_t regSR2 = i2cp->id_i2c->SR2; + regSR1 = i2cp->id_i2c->SR1; + regSR2 = i2cp->id_i2c->SR2; /* return the last event value from I2C status registers */ return (I2C_EV_MASK & (regSR1 | (regSR2 << 16))); } @@ -46,6 +48,10 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { #define txBuffp (i2cp->txbuff_p) #define rxBuffp (i2cp->rxbuff_p) + /* debug variables */ + uint16_t sr1 = 0; + uint16_t sr2 = 0; + I2C_TypeDef *dp = i2cp->id_i2c; switch(i2c_get_event(i2cp)) { @@ -148,6 +154,8 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { i2cp->flags |= I2C_FLG_3BTR; break; case 0: + dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; + dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ _i2c_isr_code(i2cp, i2cp->id_slave_config); break; @@ -166,7 +174,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { dp->CR1 &= (uint16_t)~I2C_CR1_ACK; /* Read the DataN-2 * This clear the RXE & BFT flags and launch the DataN r - * eception in the shift register (ending the SCL stretch) */ + * exception in the shift register (ending the SCL stretch) */ *rxBuffp = dp->DR; rxBuffp++; /* Program the STOP */ @@ -183,6 +191,8 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: /* only for case of two bytes to be received */ /* DataN-1 and DataN are received */ chSysLockFromIsr(); + dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; + dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; /* Program the STOP */ dp->CR1 |= I2C_CR1_STOP; /* Read the DataN-1*/ @@ -198,6 +208,11 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { break; } break; + default: + sr1 = regSR1; + sr2 = regSR2; +// chDbgAssert(FALSE, "i2c_serve_event_interrupt(), #1", "unhandled flags"); + break; } #undef rxBuffp #undef txBuffp @@ -528,6 +543,7 @@ void i2c_lld_stop(I2CDriver *i2cp) { * Bits 10-14 unused. * @param[in] txbytes number of bytes to be transmited * @param[in] rxbytes number of bytes to be received + * TODO: other parameters * */ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, @@ -555,6 +571,10 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, i2cp->flags = 0; i2cp->errors = 0; + /* enable ERR, EVT & BUF ITs */ + i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; + i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ //#if !I2C_USE_WAIT @@ -573,9 +593,7 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, chDbgAssert(timeout < I2C_START_TIMEOUT, "i2c_lld_master_transmit(), #1", "time is out"); - /* enable ERR, EVT & BUF ITs */ - i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); - i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; + } @@ -589,6 +607,7 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, * Bits 10-14 unused. * @param[in] txbytes number of bytes to be transmited * @param[in] rxbytes number of bytes to be received + * TODO: other parameters * */ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, @@ -614,6 +633,11 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, i2cp->flags = I2C_FLG_MASTER_RECEIVER; i2cp->errors = 0; + /* enable ERR, EVT & BUF ITs */ + i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ + i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; + /* Only one byte to be received */ if(i2cp->rxbytes == 1) { i2cp->flags |= I2C_FLG_1BTR; @@ -641,15 +665,10 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, /* is timeout overflows? */ chDbgAssert(timeout < I2C_START_TIMEOUT, "i2c_lld_master_receive(), #1", "time is out"); - - /* enable ERR, EVT & BUF ITs */ - i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); - i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ - i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; } - +/* TODO: doxy strings or remove this redundant function */ void i2c_lld_master_transceive(I2CDriver *i2cp){ i2cp->flags = I2C_FLG_MASTER_RECEIVER; @@ -664,10 +683,15 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ /* Only two bytes to be received */ else if(i2cp->rxbytes == 2) { i2cp->flags |= I2C_FLG_2BTR; - i2cp->id_i2c->CR1 |= I2C_CR1_POS; /* Acknowledge Position */ + i2cp->id_i2c->CR1 |= I2C_CR1_POS; /* Acknowledge Position */ } - i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ + /* enable ERR, EVT & BUF ITs */ + i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ + i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; + + i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ //#if !I2C_USE_WAIT // /* Wait until the START condition is generated on the bus: @@ -684,11 +708,6 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ /* is timeout overflows? */ chDbgAssert(timeout < I2C_START_TIMEOUT, "i2c_lld_master_receive(), #1", "time is out"); - - /* enable ERR, EVT & BUF ITs */ - i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); - i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ - i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; } diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 2659e4475..8285cddcf 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -198,7 +198,8 @@ struct I2CDriver{ /* Wait until BUSY flag is reset: a STOP has been generated on the bus - * signaling the end of transmission + * 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 = 0xffff; \ diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 93d00bcae..4aade6fe9 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -165,18 +165,18 @@ void i2cMasterTransmit(I2CDriver *i2cp, /* init slave config field in driver */ i2cp->id_slave_config = i2cscfg; -#if I2C_USE_WAIT +#if CH_DBG_ENABLE_ASSERTS i2c_lld_wait_bus_free(i2cp); - if(i2c_lld_bus_is_busy(i2cp)) { + if(i2c_lld_bus_is_busy(i2cp)) { /* Probably slave locks up and need reset. */ #ifdef PRINTTRACE print("I2C Bus busy!\n"); return; #else - /* the time is out */ + /* the time is out. Probably slave locks up. */ chDbgAssert(FALSE, "i2cMasterTransmit(), #1", "time is out"); -#endif +#endif /* PRINTTRACE */ }; -#endif +#endif /* CH_DBG_ENABLE_ASSERTS */ chSysLock(); chDbgAssert(i2cp->id_state == I2C_READY, @@ -214,18 +214,17 @@ void i2cMasterReceive(I2CDriver *i2cp, /* init slave config field in driver */ i2cp->id_slave_config = i2cscfg; -#if I2C_USE_WAIT +#if CH_DBG_ENABLE_ASSERTS i2c_lld_wait_bus_free(i2cp); if(i2c_lld_bus_is_busy(i2cp)) { #ifdef PRINTTRACE print("I2C Bus busy!\n"); return; #else - /* the time is out */ chDbgAssert(FALSE, "i2cMasterReceive(), #1", "time is out"); -#endif +#endif /* PRINTTRACE */ }; -#endif +#endif /* CH_DBG_ENABLE_ASSERTS */ chSysLock(); chDbgAssert(i2cp->id_state == I2C_READY, From 2303c1542cc8d15b960272a90a48780da126a584 Mon Sep 17 00:00:00 2001 From: barthess Date: Tue, 5 Jul 2011 14:27:15 +0000 Subject: [PATCH 68/92] I2C. Small fixes git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3122 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index f44749e11..5a07630ae 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -590,7 +590,7 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) ; /* is timeout overflows? */ - chDbgAssert(timeout < I2C_START_TIMEOUT, + chDbgAssert(timeout <= I2C_START_TIMEOUT, "i2c_lld_master_transmit(), #1", "time is out"); @@ -663,7 +663,7 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) ; /* is timeout overflows? */ - chDbgAssert(timeout < I2C_START_TIMEOUT, + chDbgAssert(timeout <= I2C_START_TIMEOUT, "i2c_lld_master_receive(), #1", "time is out"); } @@ -706,7 +706,7 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) ; /* is timeout overflows? */ - chDbgAssert(timeout < I2C_START_TIMEOUT, + chDbgAssert(timeout <= I2C_START_TIMEOUT, "i2c_lld_master_receive(), #1", "time is out"); } From ff535c27e64be34157fa37908bac9b9d460eaf57 Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 6 Jul 2011 13:54:56 +0000 Subject: [PATCH 69/92] I2C. Fix one potential problem in driver, but main problem with stack overflow still not solved. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3124 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 26 ++++++++++++++++---------- os/hal/platforms/STM32/i2c_lld.h | 12 ++++++------ 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 5a07630ae..1c80cdb2f 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -48,10 +48,6 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { #define txBuffp (i2cp->txbuff_p) #define rxBuffp (i2cp->rxbuff_p) - /* debug variables */ - uint16_t sr1 = 0; - uint16_t sr2 = 0; - I2C_TypeDef *dp = i2cp->id_i2c; switch(i2c_get_event(i2cp)) { @@ -206,14 +202,24 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ _i2c_isr_code(i2cp, i2cp->id_slave_config); break; + case I2C_FLG_MASTER_RECEIVER: + /* Here we trapped in case of interrupt "lost" when 2 bytes received. + * because STM32 I2C has ORed interrupt sources */ + if (i2cp->rxbytes > 4){ + *rxBuffp = dp->DR; + rxBuffp++; + /* Decrement the number of readed bytes */ + (i2cp->rxbytes)--; + } + else{ + /* something going too wrong*/ + port_halt(); + } + break; } break; - default: - sr1 = regSR1; - sr2 = regSR2; -// chDbgAssert(FALSE, "i2c_serve_event_interrupt(), #1", "unhandled flags"); - break; } + #undef rxBuffp #undef txBuffp } @@ -668,7 +674,7 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, } -/* TODO: doxy strings or remove this redundant function */ +/** TODO: doxy strings or remove this redundant function */ void i2c_lld_master_transceive(I2CDriver *i2cp){ i2cp->flags = I2C_FLG_MASTER_RECEIVER; diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 8285cddcf..b41f8f6fa 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -63,7 +63,7 @@ #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_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 */ @@ -71,7 +71,7 @@ #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 +#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 */ @@ -164,15 +164,15 @@ struct I2CDriver{ */ const I2CSlaveConfig *id_slave_config; - size_t txbytes; /*!< Number of bytes to be transmitted. */ - size_t rxbytes; /*!< Number of bytes to be received. */ + __IO size_t txbytes; /*!< Number of bytes to be transmitted. */ + __IO size_t rxbytes; /*!< Number of bytes to be received. */ uint8_t *rxbuf; /*!< Pointer to receive buffer. */ uint8_t *txbuf; /*!< Pointer to transmit buffer.*/ uint8_t *rxbuff_p; /*!< Pointer to the current byte in slave rx buffer. */ uint8_t *txbuff_p; /*!< Pointer to the current byte in slave tx buffer. */ - i2cflags_t errors; /*!< Error flags.*/ - i2cflags_t flags; /*!< State flags.*/ + __IO i2cflags_t errors; /*!< Error flags.*/ + __IO i2cflags_t flags; /*!< State flags.*/ uint16_t slave_addr; /*!< Current slave address. */ uint8_t slave_addr1;/*!< 7-bit address of the slave with r\w bit.*/ From 6eca6554847f7a824fbbafd892c4b3797e74983d Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 7 Jul 2011 21:53:01 +0000 Subject: [PATCH 70/92] I2C. Driver still cause stack overflows. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3134 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 2 ++ os/hal/platforms/STM32/i2c_lld.c | 62 +++++++++++++++++++++----------- os/hal/src/i2c.c | 4 +-- 3 files changed, 45 insertions(+), 23 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 774c0cf22..1e7ce3e1e 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -167,8 +167,10 @@ struct I2CSlaveConfig{ #define _i2c_wait_s(i2cp) { \ chDbgAssert((i2cp)->id_thread == NULL, \ "_i2c_wait(), #1", "already waiting"); \ + chSysLock(); \ (i2cp)->id_thread = chThdSelf(); \ chSchGoSleepS(THD_STATE_SUSPENDED); \ + chSysUnlock(); \ } /** diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 1c80cdb2f..b2e404c71 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -152,6 +152,10 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { case 0: dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + + regSR1 = dp->SR1; + regSR2 = dp->SR2; + /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ _i2c_isr_code(i2cp, i2cp->id_slave_config); break; @@ -186,19 +190,31 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { break; case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: /* only for case of two bytes to be received */ /* DataN-1 and DataN are received */ - chSysLockFromIsr(); +// chSysLockFromIsr(); dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; /* Program the STOP */ dp->CR1 |= I2C_CR1_STOP; /* Read the DataN-1*/ *rxBuffp = dp->DR; - chSysUnlockFromIsr(); rxBuffp++; /* Read the DataN*/ *rxBuffp = dp->DR; i2cp->rxbytes = 0; i2cp->flags = 0; + + while(dp->CR1 & I2C_CR1_STOP){ + ; + } + + regSR1 = dp->SR1; + regSR2 = dp->SR2; + + if((regSR1 + regSR2) > 0){ + chDbgPanic("i2c_lld_master_receive"); + } + +// chSysUnlockFromIsr(); /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ _i2c_isr_code(i2cp, i2cp->id_slave_config); break; @@ -577,8 +593,6 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, i2cp->flags = 0; i2cp->errors = 0; - /* enable ERR, EVT & BUF ITs */ - i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ @@ -592,14 +606,15 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, //#endif /* I2C_USE_WAIT */ - uint32_t timeout = I2C_START_TIMEOUT; - while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) - ; - /* is timeout overflows? */ - chDbgAssert(timeout <= I2C_START_TIMEOUT, - "i2c_lld_master_transmit(), #1", "time is out"); - - +// uint32_t timeout = I2C_START_TIMEOUT; +// while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) +// ; +// /* is timeout overflows? */ +// chDbgAssert(timeout <= I2C_START_TIMEOUT, +// "i2c_lld_master_transmit(), #1", "time is out"); +// +// /* enable ERR, EVT & BUF ITs */ +// i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); } @@ -619,6 +634,10 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, uint8_t *rxbuf, size_t rxbytes){ + if(i2cp->id_i2c->SR1 + i2cp->id_i2c->SR2 > 0){ + chDbgPanic("i2c_lld_master_receive"); + } + i2cp->slave_addr = slave_addr; i2cp->rxbytes = rxbytes; i2cp->rxbuf = rxbuf; @@ -639,8 +658,6 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, i2cp->flags = I2C_FLG_MASTER_RECEIVER; i2cp->errors = 0; - /* enable ERR, EVT & BUF ITs */ - i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; @@ -665,12 +682,17 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, //#endif /* I2C_USE_WAIT */ + uint32_t timeout = I2C_START_TIMEOUT; while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) ; /* is timeout overflows? */ chDbgAssert(timeout <= I2C_START_TIMEOUT, "i2c_lld_master_receive(), #1", "time is out"); + + /* enable ERR, EVT & BUF ITs */ + i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + } @@ -708,12 +730,12 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ //#endif /* I2C_USE_WAIT */ - uint32_t timeout = I2C_START_TIMEOUT; - while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) - ; - /* is timeout overflows? */ - chDbgAssert(timeout <= I2C_START_TIMEOUT, - "i2c_lld_master_receive(), #1", "time is out"); +// uint32_t timeout = I2C_START_TIMEOUT; +// while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) +// ; +// /* is timeout overflows? */ +// chDbgAssert(timeout <= I2C_START_TIMEOUT, +// "i2c_lld_master_receive(), #1", "time is out"); } diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 4aade6fe9..4882330bd 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -178,11 +178,11 @@ void i2cMasterTransmit(I2CDriver *i2cp, }; #endif /* CH_DBG_ENABLE_ASSERTS */ - chSysLock(); chDbgAssert(i2cp->id_state == I2C_READY, "i2cMasterTransmit(), #1", "not ready"); i2cp->id_state = I2C_ACTIVE; + chSysLock(); i2c_lld_master_transmit(i2cp, slave_addr, txbuf, txbytes, rxbuf, rxbytes); _i2c_wait_s(i2cp); chSysUnlock(); @@ -226,14 +226,12 @@ void i2cMasterReceive(I2CDriver *i2cp, }; #endif /* CH_DBG_ENABLE_ASSERTS */ - chSysLock(); chDbgAssert(i2cp->id_state == I2C_READY, "i2cMasterReceive(), #1", "not ready"); i2cp->id_state = I2C_ACTIVE; i2c_lld_master_receive(i2cp, slave_addr, rxbuf, rxbytes); _i2c_wait_s(i2cp); - chSysUnlock(); } From b064c25e390f880570f119f5533e431aaae55721 Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 9 Jul 2011 22:25:31 +0000 Subject: [PATCH 71/92] I2C. Main problem fixed, but some minor problems must to be fixed. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3142 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 366 +++++++++++++++++++------------ os/hal/src/i2c.c | 2 - 2 files changed, 221 insertions(+), 147 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index b2e404c71..df46e2167 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -28,33 +28,188 @@ I2CDriver I2CD2; /*===========================================================================*/ /* Driver local variables. */ /*===========================================================================*/ -static volatile uint16_t regSR1 = 0; -static volatile uint16_t regSR2 = 0; + +/* Debugging variables */ +#if CH_DBG_ENABLE_ASSERTS +static volatile uint16_t dbgSR1 = 0; +static volatile uint16_t dbgSR2 = 0; +static volatile uint16_t dbgCR1 = 0; +static volatile uint16_t dbgCR2 = 0; +#endif /* CH_DBG_ENABLE_ASSERTS */ /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ +/** + * Function for debugging purpose. + * Internal use only. + */ +#if CH_DBG_ENABLE_ASSERTS +void _i2c_unhandled_case(I2CDriver *i2cp){ + dbgCR1 = i2cp->id_i2c->CR1; + dbgCR2 = i2cp->id_i2c->CR2; + chDbgAssert((dbgSR1 + dbgSR2) == 0, + "i2c_serve_event_interrupt(), #1", + "unhandled case"); +} +#else +#define _i2c_unhandled_case(i2cp) +#endif /* CH_DBG_ENABLE_ASSERTS */ + +/** + * Return the last event value from I2C status registers. + * Internal use only. + */ static uint32_t i2c_get_event(I2CDriver *i2cp){ - regSR1 = i2cp->id_i2c->SR1; - regSR2 = i2cp->id_i2c->SR2; - /* return the last event value from I2C status registers */ + uint16_t regSR1 = i2cp->id_i2c->SR1; + uint16_t regSR2 = i2cp->id_i2c->SR2; +#if CH_DBG_ENABLE_ASSERTS + dbgSR1 = regSR1; + dbgSR2 = regSR2; +#endif /* CH_DBG_ENABLE_ASSERTS */ + return (I2C_EV_MASK & (regSR1 | (regSR2 << 16))); } +/** + * Function only handle the flags/interrupts and do not perform data reads. + * Internal use only. + */ +void _i2c_ev6_master_rec_mode_selected(I2CDriver *i2cp){ +#define txBuffp (i2cp->txbuff_p) +#define rxBuffp (i2cp->rxbuff_p) + + I2C_TypeDef *dp = i2cp->id_i2c; + + switch(i2cp->flags & EV6_SUBEV_MASK) { + + case I2C_EV6_3_MASTER_REC_1BTR_MODE_SELECTED: /* only an single byte to receive */ + /* Clear ACK */ + dp->CR1 &= (uint16_t)~I2C_CR1_ACK; + /* Program the STOP */ + dp->CR1 |= I2C_CR1_STOP; + while(dp->CR1 & I2C_CR1_STOP) + ; + break; + + case I2C_EV6_1_MASTER_REC_2BTR_MODE_SELECTED: /* only two bytes to receive */ + /* Clear ACK */ + dp->CR1 &= (uint16_t)~I2C_CR1_ACK; + /* Disable the ITBUF in order to have only the BTF interrupt */ + chSysLockFromIsr(); + dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + chSysUnlockFromIsr(); + break; + + default: /* more than 2 bytes to receive */ + break; + } +#undef txBuffp +#undef rxBuffp +} + +/** + * Internal use only. + */ +void _i2c_ev7_master_rec_byte_qued(I2CDriver *i2cp){ +#define txBuffp (i2cp->txbuff_p) +#define rxBuffp (i2cp->rxbuff_p) + + I2C_TypeDef *dp = i2cp->id_i2c; + + switch(i2cp->flags & EV7_SUBEV_MASK) { + + case I2C_EV7_2_MASTER_REC_3BYTES_TO_PROCESS: + /* DataN-2 and DataN-1 are received */ + chSysLockFromIsr(); + dp->CR2 |= I2C_CR2_ITBUFEN; + chSysUnlockFromIsr(); + /* Clear ACK */ + dp->CR1 &= (uint16_t)~I2C_CR1_ACK; + /* Read the DataN-2 + * This clear the RXE & BFT flags and launch the DataN r + * exception in the shift register (ending the SCL stretch) */ + *rxBuffp = dp->DR; + rxBuffp++; + /* Program the STOP */ + dp->CR1 |= I2C_CR1_STOP; + /* Read the DataN-1 */ + *rxBuffp = dp->DR; + rxBuffp++; + /* Decrement the number of readed bytes */ + i2cp->rxbytes -= 2; + i2cp->flags = 0; + /* ready for read DataN on the next EV7 */ + while(dp->CR1 & I2C_CR1_STOP) + ; + break; + + case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: /* only for case of two bytes to be received */ + /* DataN-1 and DataN are received */ + chSysLockFromIsr(); + dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; + dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + chSysUnlockFromIsr(); + /* Program the STOP */ + dp->CR1 |= I2C_CR1_STOP; + /* Read the DataN-1*/ + *rxBuffp = dp->DR; + rxBuffp++; + /* Read the DataN*/ + *rxBuffp = dp->DR; + i2cp->rxbytes = 0; + i2cp->flags = 0; + while(dp->CR1 & I2C_CR1_STOP) + ; + chDbgAssert(((dp->SR1) + (dp->SR2)) == 0, + "i2c_serve_event_interrupt(), #1", + "interrupt source(s) not resetted"); + /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ + _i2c_isr_code(i2cp, i2cp->id_slave_config); + break; + + case I2C_FLG_MASTER_RECEIVER: + /* Here we trapped in case of one interrupt "lost" when 2 bytes received. + * That is possible because STM32 I2C has OR'ed interrupt sources. */ + if (i2cp->rxbytes > 4){ + *rxBuffp = dp->DR; + rxBuffp++; + /* Decrement the number of readed bytes */ + (i2cp->rxbytes)--; + } + else{ + /* something going too wrong*/ + port_halt(); + } + break; + + default: + _i2c_unhandled_case(i2cp); + break; + } +#undef txBuffp +#undef rxBuffp +} + +/** + * + */ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { -/* defines for convenience purpose*/ +/* defines for convenience purpose */ #define txBuffp (i2cp->txbuff_p) #define rxBuffp (i2cp->rxbuff_p) I2C_TypeDef *dp = i2cp->id_i2c; switch(i2c_get_event(i2cp)) { + case I2C_EV5_MASTER_MODE_SELECT: i2cp->flags &= ~I2C_FLG_HEADER_SENT; dp->DR = i2cp->slave_addr1; break; + case I2C_EV9_MASTER_ADDR_10BIT: if(i2cp->flags & I2C_FLG_MASTER_RECEIVER) { i2cp->slave_addr1 |= 0x01; @@ -77,66 +232,59 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { /* If no further data to be sent, disable the I2C ITBUF in order * to not have a TxE interrupt */ if(i2cp->txbytes == 0) { + chSysLockFromIsr(); dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + chSysUnlockFromIsr(); } /* EV8_1 write the first data */ dp->DR = *txBuffp; txBuffp++; break; + case I2C_EV8_MASTER_BYTE_TRANSMITTING: if(i2cp->txbytes > 0) { i2cp->txbytes--; if(i2cp->txbytes == 0) { /* If no further data to be sent, disable the ITBUF in order to * not have a TxE interrupt */ + chSysLockFromIsr(); dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + chSysUnlockFromIsr(); } dp->DR = *txBuffp; txBuffp++; } break; + case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: /* Disable ITEVT In order to not have again a BTF IT */ + chSysLockFromIsr(); dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; + chSysUnlockFromIsr(); /* if nothing to read then generate stop */ if (i2cp->rxbytes == 0){ dp->CR1 |= I2C_CR1_STOP; + while(dp->CR1 & I2C_CR1_STOP) + ; /* Portable I2C ISR code defined in the high level driver, * note, it is a macro.*/ _i2c_isr_code(i2cp, i2cp->id_slave_config); } else{ /* send restart and begin reading operations */ - chSysLockFromIsr(); i2c_lld_master_transceive(i2cp); - chSysUnlockFromIsr(); } break; - /************************************************************************** * Master Receiver part */ case I2C_EV6_MASTER_REC_MODE_SELECTED: - chSysLockFromIsr(); - switch(i2cp->flags & EV6_SUBEV_MASK) { - case I2C_EV6_3_MASTER_REC_1BTR_MODE_SELECTED: /* only an single byte to receive */ - /* Clear ACK */ - dp->CR1 &= (uint16_t)~I2C_CR1_ACK; - /* Program the STOP */ - dp->CR1 |= I2C_CR1_STOP; - break; - case I2C_EV6_1_MASTER_REC_2BTR_MODE_SELECTED: /* only two bytes to receive */ - /* Clear ACK */ - dp->CR1 &= (uint16_t)~I2C_CR1_ACK; - /* Disable the ITBUF in order to have only the BTF interrupt */ - dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - break; - } - chSysUnlockFromIsr(); + _i2c_ev6_master_rec_mode_selected(i2cp); /* Initialize receive buffer pointer */ rxBuffp = i2cp->rxbuf; break; + case I2C_EV7_MASTER_REC_BYTE_RECEIVED: if(i2cp->rxbytes != 3) { /* Read the data register */ @@ -146,16 +294,16 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { switch(i2cp->rxbytes){ case 3: /* Disable the ITBUF in order to have only the BTF interrupt */ + chSysLockFromIsr(); dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + chSysUnlockFromIsr(); i2cp->flags |= I2C_FLG_3BTR; break; case 0: + chSysLockFromIsr(); dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - - regSR1 = dp->SR1; - regSR2 = dp->SR2; - + chSysUnlockFromIsr(); /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ _i2c_isr_code(i2cp, i2cp->id_slave_config); break; @@ -164,82 +312,30 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { /* when remaining 3 bytes do nothing, wait until RXNE and BTF * are set (until 2 bytes are received) */ break; + case I2C_EV7_MASTER_REC_BYTE_QUEUED: - switch(i2cp->flags & EV7_SUBEV_MASK) { - case I2C_EV7_2_MASTER_REC_3BYTES_TO_PROCESS: - /* DataN-2 and DataN-1 are received */ - chSysLockFromIsr(); - dp->CR2 |= I2C_CR2_ITBUFEN; - /* Clear ACK */ - dp->CR1 &= (uint16_t)~I2C_CR1_ACK; - /* Read the DataN-2 - * This clear the RXE & BFT flags and launch the DataN r - * exception in the shift register (ending the SCL stretch) */ - *rxBuffp = dp->DR; - rxBuffp++; - /* Program the STOP */ - dp->CR1 |= I2C_CR1_STOP; - /* Read the DataN-1 */ - *rxBuffp = dp->DR; - chSysUnlockFromIsr(); - rxBuffp++; - /* Decrement the number of readed bytes */ - i2cp->rxbytes -= 2; - i2cp->flags = 0; - /* ready for read DataN on the next EV7 */ - break; - case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: /* only for case of two bytes to be received */ - /* DataN-1 and DataN are received */ -// chSysLockFromIsr(); - dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; - dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - /* Program the STOP */ - dp->CR1 |= I2C_CR1_STOP; - /* Read the DataN-1*/ - *rxBuffp = dp->DR; - rxBuffp++; - /* Read the DataN*/ - *rxBuffp = dp->DR; - i2cp->rxbytes = 0; - i2cp->flags = 0; + _i2c_ev7_master_rec_byte_qued(i2cp); + break; - while(dp->CR1 & I2C_CR1_STOP){ - ; - } - - regSR1 = dp->SR1; - regSR2 = dp->SR2; - - if((regSR1 + regSR2) > 0){ - chDbgPanic("i2c_lld_master_receive"); - } - -// chSysUnlockFromIsr(); - /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ - _i2c_isr_code(i2cp, i2cp->id_slave_config); - break; - case I2C_FLG_MASTER_RECEIVER: - /* Here we trapped in case of interrupt "lost" when 2 bytes received. - * because STM32 I2C has ORed interrupt sources */ - if (i2cp->rxbytes > 4){ - *rxBuffp = dp->DR; - rxBuffp++; - /* Decrement the number of readed bytes */ - (i2cp->rxbytes)--; - } - else{ - /* something going too wrong*/ - port_halt(); - } - break; - } + default: /* only 1 byte to read from data register */ + /* Read the data register */ + *rxBuffp = dp->DR; + rxBuffp++; + i2cp->rxbytes--; + /* disable interrupts */ + chSysLockFromIsr(); + dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; + dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + chSysUnlockFromIsr(); + /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ + _i2c_isr_code(i2cp, i2cp->id_slave_config); break; } - #undef rxBuffp #undef txBuffp } + static void i2c_serve_error_interrupt(I2CDriver *i2cp) { i2cflags_t flags; I2C_TypeDef *reg; @@ -362,15 +458,19 @@ void i2c_lld_start(I2CDriver *i2cp) { if (i2cp->id_state == I2C_STOP) { #if STM32_I2C_USE_I2C1 if (&I2CD1 == i2cp) { - NVICEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); - NVICEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); + NVICEnableVector(I2C1_EV_IRQn, + CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); + NVICEnableVector(I2C1_ER_IRQn, + CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; /* I2C 1 clock enable */ } #endif #if STM32_I2C_USE_I2C2 if (&I2CD2 == i2cp) { - NVICEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); - NVICEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); + NVICEnableVector(I2C2_EV_IRQn, + CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); + NVICEnableVector(I2C2_ER_IRQn, + CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); RCC->APB1ENR |= RCC_APB1ENR_I2C2EN; /* I2C 2 clock enable */ } #endif @@ -382,8 +482,11 @@ void i2c_lld_start(I2CDriver *i2cp) { i2c_lld_set_clock(i2cp); i2c_lld_set_opmode(i2cp); + /* enable interrupts */ - i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN | I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; + // i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN | I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; + /* interrups will be enabled in data transfer routines */ + /* enable interface */ i2cp->id_i2c->CR1 |= 1; } @@ -597,24 +700,15 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ -//#if !I2C_USE_WAIT -// /* Wait until the START condition is generated on the bus: -// * the START bit is cleared by hardware */ -// uint32_t timeout = 0xfffff; -// while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) -// ; -//#endif /* I2C_USE_WAIT */ - - // uint32_t timeout = I2C_START_TIMEOUT; // while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) // ; -// /* is timeout overflows? */ +// /* is time out? */ // chDbgAssert(timeout <= I2C_START_TIMEOUT, // "i2c_lld_master_transmit(), #1", "time is out"); // -// /* enable ERR, EVT & BUF ITs */ -// i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + /* enable ERR, EVT & BUF ITs */ + i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); } @@ -634,6 +728,7 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, uint8_t *rxbuf, size_t rxbytes){ + /* check interrupt sources */ if(i2cp->id_i2c->SR1 + i2cp->id_i2c->SR2 > 0){ chDbgPanic("i2c_lld_master_receive"); } @@ -673,26 +768,15 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ -//#if !I2C_USE_WAIT -// /* Wait until the START condition is generated on the bus: -// * the START bit is cleared by hardware */ -// uint32_t timeout = 0xfffff; +// uint32_t timeout = I2C_START_TIMEOUT; // while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) // ; -//#endif /* I2C_USE_WAIT */ - - - - uint32_t timeout = I2C_START_TIMEOUT; - while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) - ; - /* is timeout overflows? */ - chDbgAssert(timeout <= I2C_START_TIMEOUT, - "i2c_lld_master_receive(), #1", "time is out"); +// /* is time out? */ +// chDbgAssert(timeout <= I2C_START_TIMEOUT, +// "i2c_lld_master_receive(), #1", "time is out"); /* enable ERR, EVT & BUF ITs */ i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); - } @@ -714,28 +798,20 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_POS; /* Acknowledge Position */ } - /* enable ERR, EVT & BUF ITs */ - i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ -//#if !I2C_USE_WAIT -// /* Wait until the START condition is generated on the bus: -// * the START bit is cleared by hardware */ -// uint32_t timeout = 0xfffff; -// while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) -// ; -//#endif /* I2C_USE_WAIT */ + uint32_t timeout = I2C_START_TIMEOUT; + while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) + ; + /* is timeout overflows? */ + chDbgAssert(timeout <= I2C_START_TIMEOUT, + "i2c_lld_master_receive(), #1", "time is out"); - -// uint32_t timeout = I2C_START_TIMEOUT; -// while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) -// ; -// /* is timeout overflows? */ -// chDbgAssert(timeout <= I2C_START_TIMEOUT, -// "i2c_lld_master_receive(), #1", "time is out"); + /* enable ERR, EVT & BUF ITs */ + i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); } diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 4882330bd..4c9a46e5e 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -182,10 +182,8 @@ void i2cMasterTransmit(I2CDriver *i2cp, "i2cMasterTransmit(), #1", "not ready"); i2cp->id_state = I2C_ACTIVE; - chSysLock(); i2c_lld_master_transmit(i2cp, slave_addr, txbuf, txbytes, rxbuf, rxbytes); _i2c_wait_s(i2cp); - chSysUnlock(); } /** From 00885674924c98404203f61aafbe18393eebab2b Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 10 Jul 2011 18:17:16 +0000 Subject: [PATCH 72/92] I2C. Most of problems have been resolved. Needs testing. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3149 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 68 +++++++++++++------------------- 1 file changed, 28 insertions(+), 40 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index df46e2167..25b8a30bf 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -98,9 +98,7 @@ void _i2c_ev6_master_rec_mode_selected(I2CDriver *i2cp){ /* Clear ACK */ dp->CR1 &= (uint16_t)~I2C_CR1_ACK; /* Disable the ITBUF in order to have only the BTF interrupt */ - chSysLockFromIsr(); dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - chSysUnlockFromIsr(); break; default: /* more than 2 bytes to receive */ @@ -121,11 +119,9 @@ void _i2c_ev7_master_rec_byte_qued(I2CDriver *i2cp){ switch(i2cp->flags & EV7_SUBEV_MASK) { - case I2C_EV7_2_MASTER_REC_3BYTES_TO_PROCESS: + case I2C_EV7_2_MASTER_REC_3BYTES_TO_PROCESS:/* only for case of three bytes to be received */ /* DataN-2 and DataN-1 are received */ - chSysLockFromIsr(); dp->CR2 |= I2C_CR2_ITBUFEN; - chSysUnlockFromIsr(); /* Clear ACK */ dp->CR1 &= (uint16_t)~I2C_CR1_ACK; /* Read the DataN-2 @@ -148,10 +144,8 @@ void _i2c_ev7_master_rec_byte_qued(I2CDriver *i2cp){ case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: /* only for case of two bytes to be received */ /* DataN-1 and DataN are received */ - chSysLockFromIsr(); dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - chSysUnlockFromIsr(); /* Program the STOP */ dp->CR1 |= I2C_CR1_STOP; /* Read the DataN-1*/ @@ -163,26 +157,18 @@ void _i2c_ev7_master_rec_byte_qued(I2CDriver *i2cp){ i2cp->flags = 0; while(dp->CR1 & I2C_CR1_STOP) ; - chDbgAssert(((dp->SR1) + (dp->SR2)) == 0, - "i2c_serve_event_interrupt(), #1", - "interrupt source(s) not resetted"); /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ _i2c_isr_code(i2cp, i2cp->id_slave_config); break; - case I2C_FLG_MASTER_RECEIVER: - /* Here we trapped in case of one interrupt "lost" when 2 bytes received. - * That is possible because STM32 I2C has OR'ed interrupt sources. */ - if (i2cp->rxbytes > 4){ + case I2C_FLG_MASTER_RECEIVER: /* some time in hi loaded cases */ + if (i2cp->rxbytes > 3){ *rxBuffp = dp->DR; rxBuffp++; - /* Decrement the number of readed bytes */ (i2cp->rxbytes)--; } - else{ - /* something going too wrong*/ - port_halt(); - } + else + _i2c_unhandled_case(i2cp); break; default: @@ -232,9 +218,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { /* If no further data to be sent, disable the I2C ITBUF in order * to not have a TxE interrupt */ if(i2cp->txbytes == 0) { - chSysLockFromIsr(); dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - chSysUnlockFromIsr(); } /* EV8_1 write the first data */ dp->DR = *txBuffp; @@ -247,9 +231,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { if(i2cp->txbytes == 0) { /* If no further data to be sent, disable the ITBUF in order to * not have a TxE interrupt */ - chSysLockFromIsr(); dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - chSysUnlockFromIsr(); } dp->DR = *txBuffp; txBuffp++; @@ -258,9 +240,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: /* Disable ITEVT In order to not have again a BTF IT */ - chSysLockFromIsr(); dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; - chSysUnlockFromIsr(); /* if nothing to read then generate stop */ if (i2cp->rxbytes == 0){ dp->CR1 |= I2C_CR1_STOP; @@ -271,8 +251,10 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { _i2c_isr_code(i2cp, i2cp->id_slave_config); } else{ + chSysLockFromIsr(); /* send restart and begin reading operations */ i2c_lld_master_transceive(i2cp); + chSysUnlockFromIsr(); } break; @@ -294,21 +276,22 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { switch(i2cp->rxbytes){ case 3: /* Disable the ITBUF in order to have only the BTF interrupt */ - chSysLockFromIsr(); dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - chSysUnlockFromIsr(); i2cp->flags |= I2C_FLG_3BTR; break; case 0: - chSysLockFromIsr(); dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - chSysUnlockFromIsr(); /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ _i2c_isr_code(i2cp, i2cp->id_slave_config); break; } } + else{ + /* Disable the ITBUF in order to have only the BTF interrupt */ + dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + i2cp->flags |= I2C_FLG_3BTR; + } /* when remaining 3 bytes do nothing, wait until RXNE and BTF * are set (until 2 bytes are received) */ break; @@ -317,16 +300,16 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { _i2c_ev7_master_rec_byte_qued(i2cp); break; - default: /* only 1 byte to read from data register */ + default: /* only 1 byte must to be read to complete trasfer. Stop already sent to bus. */ + chDbgAssert((i2cp->rxbytes) == 1, + "i2c_serve_event_interrupt(), #1", + "more than 1 byte to be received"); /* Read the data register */ *rxBuffp = dp->DR; - rxBuffp++; - i2cp->rxbytes--; + i2cp->rxbytes = 0; /* disable interrupts */ - chSysLockFromIsr(); dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - chSysUnlockFromIsr(); /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ _i2c_isr_code(i2cp, i2cp->id_slave_config); break; @@ -728,10 +711,9 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, uint8_t *rxbuf, size_t rxbytes){ - /* check interrupt sources */ - if(i2cp->id_i2c->SR1 + i2cp->id_i2c->SR2 > 0){ - chDbgPanic("i2c_lld_master_receive"); - } + chDbgAssert((i2cp->id_i2c->SR1 + i2cp->id_i2c->SR2) == 0, + "i2c_lld_master_receive(), #1", + "some interrupt sources not clear"); i2cp->slave_addr = slave_addr; i2cp->rxbytes = rxbytes; @@ -783,6 +765,14 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, /** TODO: doxy strings or remove this redundant function */ void i2c_lld_master_transceive(I2CDriver *i2cp){ + chDbgAssert((i2cp != NULL) && (i2cp->slave_addr1 != 0) &&\ + (i2cp->rxbytes > 0) && (i2cp->rxbuf != NULL), + "i2c_lld_master_transceive(), #1", + ""); + + /* first send start bit to reduce blocking time */ + i2cp->id_i2c->CR1 |= I2C_CR1_START; + i2cp->flags = I2C_FLG_MASTER_RECEIVER; i2cp->errors = 0; @@ -801,8 +791,6 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ - uint32_t timeout = I2C_START_TIMEOUT; while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) ; From caeaf6536e6d9dc087d9a23ff71c442cd2762e63 Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 10 Jul 2011 21:40:49 +0000 Subject: [PATCH 73/92] I2C. Fixed bug occures when read-through-write two bytes. Code cleanups. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3150 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 66 ++++++++++++-------------------- 1 file changed, 25 insertions(+), 41 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 25b8a30bf..27ab1d809 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -90,8 +90,8 @@ void _i2c_ev6_master_rec_mode_selected(I2CDriver *i2cp){ dp->CR1 &= (uint16_t)~I2C_CR1_ACK; /* Program the STOP */ dp->CR1 |= I2C_CR1_STOP; - while(dp->CR1 & I2C_CR1_STOP) - ; +// while(dp->CR1 & I2C_CR1_STOP) +// ; break; case I2C_EV6_1_MASTER_REC_2BTR_MODE_SELECTED: /* only two bytes to receive */ @@ -121,7 +121,6 @@ void _i2c_ev7_master_rec_byte_qued(I2CDriver *i2cp){ case I2C_EV7_2_MASTER_REC_3BYTES_TO_PROCESS:/* only for case of three bytes to be received */ /* DataN-2 and DataN-1 are received */ - dp->CR2 |= I2C_CR2_ITBUFEN; /* Clear ACK */ dp->CR1 &= (uint16_t)~I2C_CR1_ACK; /* Read the DataN-2 @@ -137,9 +136,8 @@ void _i2c_ev7_master_rec_byte_qued(I2CDriver *i2cp){ /* Decrement the number of readed bytes */ i2cp->rxbytes -= 2; i2cp->flags = 0; - /* ready for read DataN on the next EV7 */ - while(dp->CR1 & I2C_CR1_STOP) - ; + /* ready for read DataN. Enable interrupt for next (and last) RxNE event*/ + dp->CR2 |= I2C_CR2_ITBUFEN; break; case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: /* only for case of two bytes to be received */ @@ -155,8 +153,6 @@ void _i2c_ev7_master_rec_byte_qued(I2CDriver *i2cp){ *rxBuffp = dp->DR; i2cp->rxbytes = 0; i2cp->flags = 0; - while(dp->CR1 & I2C_CR1_STOP) - ; /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ _i2c_isr_code(i2cp, i2cp->id_slave_config); break; @@ -251,10 +247,11 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { _i2c_isr_code(i2cp, i2cp->id_slave_config); } else{ - chSysLockFromIsr(); + // chSysLockFromIsr(); /* send restart and begin reading operations */ + // i2c_lld_master_receive(i2cp, i2cp->slave_addr, i2cp->rxbuf, i2cp->rxbytes); i2c_lld_master_transceive(i2cp); - chSysUnlockFromIsr(); + // chSysUnlockFromIsr(); } break; @@ -268,26 +265,18 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { break; case I2C_EV7_MASTER_REC_BYTE_RECEIVED: - if(i2cp->rxbytes != 3) { + if(i2cp->rxbytes > 3) { /* Read the data register */ *rxBuffp = dp->DR; rxBuffp++; i2cp->rxbytes--; - switch(i2cp->rxbytes){ - case 3: + if(i2cp->rxbytes == 3){ /* Disable the ITBUF in order to have only the BTF interrupt */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; i2cp->flags |= I2C_FLG_3BTR; - break; - case 0: - dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; - dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ - _i2c_isr_code(i2cp, i2cp->id_slave_config); - break; } } - else{ + else if (i2cp->rxbytes == 3){ /* Disable the ITBUF in order to have only the BTF interrupt */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; i2cp->flags |= I2C_FLG_3BTR; @@ -683,13 +672,6 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ -// uint32_t timeout = I2C_START_TIMEOUT; -// while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) -// ; -// /* is time out? */ -// chDbgAssert(timeout <= I2C_START_TIMEOUT, -// "i2c_lld_master_transmit(), #1", "time is out"); -// /* enable ERR, EVT & BUF ITs */ i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); } @@ -750,13 +732,6 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ -// uint32_t timeout = I2C_START_TIMEOUT; -// while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) -// ; -// /* is time out? */ -// chDbgAssert(timeout <= I2C_START_TIMEOUT, -// "i2c_lld_master_receive(), #1", "time is out"); - /* enable ERR, EVT & BUF ITs */ i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); } @@ -770,13 +745,23 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ "i2c_lld_master_transceive(), #1", ""); - /* first send start bit to reduce blocking time */ - i2cp->id_i2c->CR1 |= I2C_CR1_START; - i2cp->flags = I2C_FLG_MASTER_RECEIVER; i2cp->errors = 0; - i2cp->slave_addr1 |= 0x01; + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ + i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; + + if(i2cp->slave_addr & 0x8000){/* 10-bit mode used */ + /* add the two msb of 10-bit address to the header */ + i2cp->slave_addr1 = ((i2cp->slave_addr >>7) & 0x0006); + /* add the header bits (the LSB -> 1 will be add to second */ + i2cp->slave_addr1 |= 0xF0; + /* the remaining 8 bit of 10-bit address */ + i2cp->slave_addr2 = i2cp->slave_addr & 0x00FF; + } + else{ + i2cp->slave_addr1 |= 0x01; + } /* Only one byte to be received */ if(i2cp->rxbytes == 1) { @@ -788,8 +773,7 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_POS; /* Acknowledge Position */ } - i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ - i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; + i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ uint32_t timeout = I2C_START_TIMEOUT; while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) From 0ada09b54288d8d632dad6cb4149234ccea34c43 Mon Sep 17 00:00:00 2001 From: barthess Date: Mon, 11 Jul 2011 19:49:14 +0000 Subject: [PATCH 74/92] I2C. Code clean ups. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3151 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/i2c.c | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 4c9a46e5e..cd12d42eb 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -165,18 +165,8 @@ void i2cMasterTransmit(I2CDriver *i2cp, /* init slave config field in driver */ i2cp->id_slave_config = i2cscfg; -#if CH_DBG_ENABLE_ASSERTS i2c_lld_wait_bus_free(i2cp); - if(i2c_lld_bus_is_busy(i2cp)) { /* Probably slave locks up and need reset. */ -#ifdef PRINTTRACE - print("I2C Bus busy!\n"); - return; -#else - /* the time is out. Probably slave locks up. */ - chDbgAssert(FALSE, "i2cMasterTransmit(), #1", "time is out"); -#endif /* PRINTTRACE */ - }; -#endif /* CH_DBG_ENABLE_ASSERTS */ + chDbgAssert(!(i2c_lld_bus_is_busy(i2cp)), "i2cMasterReceive(), #1", "time is out"); chDbgAssert(i2cp->id_state == I2C_READY, "i2cMasterTransmit(), #1", "not ready"); @@ -212,17 +202,8 @@ void i2cMasterReceive(I2CDriver *i2cp, /* init slave config field in driver */ i2cp->id_slave_config = i2cscfg; -#if CH_DBG_ENABLE_ASSERTS i2c_lld_wait_bus_free(i2cp); - if(i2c_lld_bus_is_busy(i2cp)) { -#ifdef PRINTTRACE - print("I2C Bus busy!\n"); - return; -#else - chDbgAssert(FALSE, "i2cMasterReceive(), #1", "time is out"); -#endif /* PRINTTRACE */ - }; -#endif /* CH_DBG_ENABLE_ASSERTS */ + chDbgAssert(!(i2c_lld_bus_is_busy(i2cp)), "i2cMasterReceive(), #1", "time is out"); chDbgAssert(i2cp->id_state == I2C_READY, "i2cMasterReceive(), #1", "not ready"); From 44960790c58f9055068dbc427384ae8d20048334 Mon Sep 17 00:00:00 2001 From: barthess Date: Tue, 12 Jul 2011 14:21:44 +0000 Subject: [PATCH 75/92] I2C. Comments improvements. Code cleanups. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3152 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 394 ++++++++++++------------------- 1 file changed, 157 insertions(+), 237 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 27ab1d809..84959c7f0 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -41,9 +41,17 @@ static volatile uint16_t dbgCR2 = 0; /* Driver local functions. */ /*===========================================================================*/ +/* defines for convenience purpose */ +#define txBuffp (i2cp->txbuff_p) +#define rxBuffp (i2cp->rxbuff_p) + /** - * Function for debugging purpose. - * Internal use only. + * @brief Function for I2C debugging purpose. + * @note Internal use only. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi */ #if CH_DBG_ENABLE_ASSERTS void _i2c_unhandled_case(I2CDriver *i2cp){ @@ -57,107 +65,97 @@ void _i2c_unhandled_case(I2CDriver *i2cp){ #define _i2c_unhandled_case(i2cp) #endif /* CH_DBG_ENABLE_ASSERTS */ - /** - * Return the last event value from I2C status registers. - * Internal use only. + * @brief Return the last event value from I2C status registers. + * @note Internal use only. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi */ static uint32_t i2c_get_event(I2CDriver *i2cp){ uint16_t regSR1 = i2cp->id_i2c->SR1; uint16_t regSR2 = i2cp->id_i2c->SR2; -#if CH_DBG_ENABLE_ASSERTS - dbgSR1 = regSR1; - dbgSR2 = regSR2; -#endif /* CH_DBG_ENABLE_ASSERTS */ + #if CH_DBG_ENABLE_ASSERTS + dbgSR1 = regSR1; + dbgSR2 = regSR2; + #endif /* CH_DBG_ENABLE_ASSERTS */ return (I2C_EV_MASK & (regSR1 | (regSR2 << 16))); } /** - * Function only handle the flags/interrupts and do not perform data reads. - * Internal use only. + * @brief Handle the flags/interrupts. + * @note Internal use only. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi */ void _i2c_ev6_master_rec_mode_selected(I2CDriver *i2cp){ -#define txBuffp (i2cp->txbuff_p) -#define rxBuffp (i2cp->rxbuff_p) - I2C_TypeDef *dp = i2cp->id_i2c; switch(i2cp->flags & EV6_SUBEV_MASK) { case I2C_EV6_3_MASTER_REC_1BTR_MODE_SELECTED: /* only an single byte to receive */ - /* Clear ACK */ - dp->CR1 &= (uint16_t)~I2C_CR1_ACK; - /* Program the STOP */ - dp->CR1 |= I2C_CR1_STOP; -// while(dp->CR1 & I2C_CR1_STOP) -// ; + dp->CR1 &= (uint16_t)~I2C_CR1_ACK; /* Clear ACK */ + dp->CR1 |= I2C_CR1_STOP; /* Program the STOP */ break; case I2C_EV6_1_MASTER_REC_2BTR_MODE_SELECTED: /* only two bytes to receive */ - /* Clear ACK */ - dp->CR1 &= (uint16_t)~I2C_CR1_ACK; - /* Disable the ITBUF in order to have only the BTF interrupt */ - dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + dp->CR1 &= (uint16_t)~I2C_CR1_ACK; /* Clear ACK */ + dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; /* Disable the ITBUF in order to have only the BTF interrupt */ break; default: /* more than 2 bytes to receive */ break; } -#undef txBuffp -#undef rxBuffp } /** - * Internal use only. + * @brief Handle cases of 2 or 3 bytes receiving. + * @note Internal use only. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi */ void _i2c_ev7_master_rec_byte_qued(I2CDriver *i2cp){ -#define txBuffp (i2cp->txbuff_p) -#define rxBuffp (i2cp->rxbuff_p) - I2C_TypeDef *dp = i2cp->id_i2c; switch(i2cp->flags & EV7_SUBEV_MASK) { - case I2C_EV7_2_MASTER_REC_3BYTES_TO_PROCESS:/* only for case of three bytes to be received */ - /* DataN-2 and DataN-1 are received */ - /* Clear ACK */ - dp->CR1 &= (uint16_t)~I2C_CR1_ACK; - /* Read the DataN-2 - * This clear the RXE & BFT flags and launch the DataN r - * exception in the shift register (ending the SCL stretch) */ - *rxBuffp = dp->DR; + case I2C_EV7_2_MASTER_REC_3BYTES_TO_PROCESS: + /* Only for case of three bytes to be received. + * DataN-2 and DataN-1 already received. */ + dp->CR1 &= (uint16_t)~I2C_CR1_ACK; /* Clear ACK */ + *rxBuffp = dp->DR; /* Read the DataN-2. This clear the RXE & BFT flags and launch the DataN exception in the shift register (ending the SCL stretch) */ rxBuffp++; - /* Program the STOP */ - dp->CR1 |= I2C_CR1_STOP; - /* Read the DataN-1 */ - *rxBuffp = dp->DR; + dp->CR1 |= I2C_CR1_STOP; /* Program the STOP */ + *rxBuffp = dp->DR; /* Read the DataN-1 */ rxBuffp++; - /* Decrement the number of readed bytes */ - i2cp->rxbytes -= 2; + i2cp->rxbytes -= 2; /* Decrement the number of readed bytes */ i2cp->flags = 0; - /* ready for read DataN. Enable interrupt for next (and last) RxNE event*/ - dp->CR2 |= I2C_CR2_ITBUFEN; + dp->CR2 |= I2C_CR2_ITBUFEN; /* ready for read DataN. Enable interrupt for next (and last) RxNE event*/ break; - case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: /* only for case of two bytes to be received */ - /* DataN-1 and DataN are received */ + case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: + /* only for case of two bytes to be received + * DataN-1 and DataN are received */ dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - /* Program the STOP */ - dp->CR1 |= I2C_CR1_STOP; - /* Read the DataN-1*/ - *rxBuffp = dp->DR; + dp->CR1 |= I2C_CR1_STOP; /* Program the STOP */ + *rxBuffp = dp->DR; /* Read the DataN-1*/ rxBuffp++; - /* Read the DataN*/ - *rxBuffp = dp->DR; + *rxBuffp = dp->DR; /* Read the DataN*/ i2cp->rxbytes = 0; i2cp->flags = 0; - /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ - _i2c_isr_code(i2cp, i2cp->id_slave_config); + _i2c_isr_code(i2cp, i2cp->id_slave_config); /* Portable I2C ISR code defined in the high level driver. */ break; - case I2C_FLG_MASTER_RECEIVER: /* some time in hi loaded cases */ + case I2C_FLG_MASTER_RECEIVER: + /* some time in hi load cases possible to miss interrupt + * ??? TODO: really?*/ if (i2cp->rxbytes > 3){ *rxBuffp = dp->DR; rxBuffp++; @@ -171,18 +169,17 @@ void _i2c_ev7_master_rec_byte_qued(I2CDriver *i2cp){ _i2c_unhandled_case(i2cp); break; } -#undef txBuffp -#undef rxBuffp } /** + * @brief Main I2C interrupt handler. + * @note Internal use only. * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi */ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { -/* defines for convenience purpose */ -#define txBuffp (i2cp->txbuff_p) -#define rxBuffp (i2cp->rxbuff_p) - I2C_TypeDef *dp = i2cp->id_i2c; switch(i2c_get_event(i2cp)) { @@ -205,28 +202,22 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { */ case I2C_EV6_MASTER_TRA_MODE_SELECTED: if(i2cp->flags & I2C_FLG_HEADER_SENT){ - dp->CR1 |= I2C_CR1_START; /* re-send the start in 10-Bit address mode */ + dp->CR1 |= I2C_CR1_START; /* re-send the start in 10-Bit address mode */ break; } - /* Initialize the transmit buffer pointer */ - txBuffp = (uint8_t*)i2cp->txbuf; + txBuffp = (uint8_t*)i2cp->txbuf; /* Initialize the transmit buffer pointer */ i2cp->txbytes--; - /* If no further data to be sent, disable the I2C ITBUF in order - * to not have a TxE interrupt */ - if(i2cp->txbytes == 0) { + if(i2cp->txbytes == 0) { /* If no further data to be sent, disable the I2C ITBUF in order to not have a TxE interrupt */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; } - /* EV8_1 write the first data */ - dp->DR = *txBuffp; + dp->DR = *txBuffp; /* EV8_1 write the first data */ txBuffp++; break; case I2C_EV8_MASTER_BYTE_TRANSMITTING: if(i2cp->txbytes > 0) { i2cp->txbytes--; - if(i2cp->txbytes == 0) { - /* If no further data to be sent, disable the ITBUF in order to - * not have a TxE interrupt */ + if(i2cp->txbytes == 0) { /* If no further data to be sent, disable the ITBUF in order to not have a TxE interrupt */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; } dp->DR = *txBuffp; @@ -235,23 +226,13 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { break; case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: - /* Disable ITEVT In order to not have again a BTF IT */ - dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; - /* if nothing to read then generate stop */ - if (i2cp->rxbytes == 0){ + dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; /* Disable ITEVT In order to not have again a BTF IT */ + if (i2cp->rxbytes == 0){ /* if nothing to read then generate stop */ dp->CR1 |= I2C_CR1_STOP; - while(dp->CR1 & I2C_CR1_STOP) - ; - /* Portable I2C ISR code defined in the high level driver, - * note, it is a macro.*/ - _i2c_isr_code(i2cp, i2cp->id_slave_config); + _i2c_isr_code(i2cp, i2cp->id_slave_config); /* Portable I2C ISR code defined in the high level driver. */ } - else{ - // chSysLockFromIsr(); - /* send restart and begin reading operations */ - // i2c_lld_master_receive(i2cp, i2cp->slave_addr, i2cp->rxbuf, i2cp->rxbytes); + else{ /* start reading operation */ i2c_lld_master_transceive(i2cp); - // chSysUnlockFromIsr(); } break; @@ -260,51 +241,40 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { */ case I2C_EV6_MASTER_REC_MODE_SELECTED: _i2c_ev6_master_rec_mode_selected(i2cp); - /* Initialize receive buffer pointer */ - rxBuffp = i2cp->rxbuf; + rxBuffp = i2cp->rxbuf; /* Initialize receive buffer pointer */ break; case I2C_EV7_MASTER_REC_BYTE_RECEIVED: if(i2cp->rxbytes > 3) { - /* Read the data register */ - *rxBuffp = dp->DR; + *rxBuffp = dp->DR; /* Read the data register */ rxBuffp++; i2cp->rxbytes--; - if(i2cp->rxbytes == 3){ - /* Disable the ITBUF in order to have only the BTF interrupt */ + if(i2cp->rxbytes == 3){ /* Disable the ITBUF in order to have only the BTF interrupt */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; i2cp->flags |= I2C_FLG_3BTR; } } - else if (i2cp->rxbytes == 3){ - /* Disable the ITBUF in order to have only the BTF interrupt */ + else if (i2cp->rxbytes == 3){ /* Disable the ITBUF in order to have only the BTF interrupt */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; i2cp->flags |= I2C_FLG_3BTR; } - /* when remaining 3 bytes do nothing, wait until RXNE and BTF - * are set (until 2 bytes are received) */ break; case I2C_EV7_MASTER_REC_BYTE_QUEUED: _i2c_ev7_master_rec_byte_qued(i2cp); break; - default: /* only 1 byte must to be read to complete trasfer. Stop already sent to bus. */ + default: /* only 1 byte must to be read to complete trasfer. Stop already sent to bus. */ chDbgAssert((i2cp->rxbytes) == 1, "i2c_serve_event_interrupt(), #1", "more than 1 byte to be received"); - /* Read the data register */ - *rxBuffp = dp->DR; + *rxBuffp = dp->DR; /* Read the data register */ i2cp->rxbytes = 0; - /* disable interrupts */ - dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; + dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; /* disable interrupts */ dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; - /* Portable I2C ISR code defined in the high level driver, note, it is a macro.*/ - _i2c_isr_code(i2cp, i2cp->id_slave_config); + _i2c_isr_code(i2cp, i2cp->id_slave_config); /* Portable I2C ISR code defined in the high level driver.*/ break; } -#undef rxBuffp -#undef txBuffp } @@ -345,8 +315,7 @@ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { flags |= I2CD_SMB_ALERT; } - if(flags != I2CD_NO_ERROR) { - /* send communication end signal */ + if(flags != I2CD_NO_ERROR) { /* send communication end signal */ chSysLockFromIsr(); i2cAddFlagsI(i2cp, flags); chSysUnlockFromIsr(); @@ -425,16 +394,14 @@ void i2c_lld_init(void) { * @param[in] i2cp pointer to the @p I2CDriver object */ void i2c_lld_start(I2CDriver *i2cp) { - - /* If in stopped state then enables the I2C clock.*/ - if (i2cp->id_state == I2C_STOP) { + if (i2cp->id_state == I2C_STOP) { /* If in stopped state then enables the I2C clock.*/ #if STM32_I2C_USE_I2C1 if (&I2CD1 == i2cp) { NVICEnableVector(I2C1_EV_IRQn, CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); NVICEnableVector(I2C1_ER_IRQn, CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); - RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; /* I2C 1 clock enable */ + RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; /* I2C 1 clock enable */ } #endif #if STM32_I2C_USE_I2C2 @@ -443,24 +410,16 @@ void i2c_lld_start(I2CDriver *i2cp) { CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); NVICEnableVector(I2C2_ER_IRQn, CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); - RCC->APB1ENR |= RCC_APB1ENR_I2C2EN; /* I2C 2 clock enable */ + RCC->APB1ENR |= RCC_APB1ENR_I2C2EN; /* I2C 2 clock enable */ } #endif } - /* I2C setup.*/ - i2cp->id_i2c->CR1 = I2C_CR1_SWRST; /* reset i2c peripherial */ + i2cp->id_i2c->CR1 = I2C_CR1_SWRST; /* reset i2c peripherial */ i2cp->id_i2c->CR1 = 0; - i2c_lld_set_clock(i2cp); i2c_lld_set_opmode(i2cp); - - /* enable interrupts */ - // i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN | I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; - /* interrups will be enabled in data transfer routines */ - - /* enable interface */ - i2cp->id_i2c->CR1 |= 1; + i2cp->id_i2c->CR1 |= 1; /* enable interface */ } void i2c_lld_reset(I2CDriver *i2cp){ @@ -486,69 +445,52 @@ void i2c_lld_set_clock(I2CDriver *i2cp) { chDbgCheck((i2cp != NULL) && (clock_speed > 0) && (clock_speed <= 4000000), "i2c_lld_set_clock"); - /*---------------------------- CR2 Configuration ------------------------*/ - /* Get the I2Cx CR2 value */ - regCR2 = i2cp->id_i2c->CR2; - - /* Clear frequency FREQ[5:0] bits */ - regCR2 &= (uint16_t)~I2C_CR2_FREQ; - /* Set frequency bits depending on pclk1 value */ - freq = (uint16_t)(STM32_PCLK1 / 1000000); + /************************************************************************** + * CR2 Configuration + */ + regCR2 = i2cp->id_i2c->CR2; /* Get the I2Cx CR2 value */ + regCR2 &= (uint16_t)~I2C_CR2_FREQ; /* Clear frequency FREQ[5:0] bits */ + freq = (uint16_t)(STM32_PCLK1 / 1000000); /* Set frequency bits depending on pclk1 value */ chDbgCheck((freq >= 2) && (freq <= 36), "i2c_lld_set_clock() : Peripheral clock freq. out of range"); regCR2 |= freq; i2cp->id_i2c->CR2 = regCR2; - /*---------------------------- CCR Configuration ------------------------*/ + /************************************************************************** + * CCR Configuration + */ pe_bit_saved = (i2cp->id_i2c->CR1 & I2C_CR1_PE); - /* Disable the selected I2C peripheral to configure TRISE */ - i2cp->id_i2c->CR1 &= (uint16_t)~I2C_CR1_PE; - - /* Clear F/S, DUTY and CCR[11:0] bits */ - regCCR = 0; + i2cp->id_i2c->CR1 &= (uint16_t)~I2C_CR1_PE; /* Disable the selected I2C peripheral to configure TRISE */ + regCCR = 0; /* Clear F/S, DUTY and CCR[11:0] bits */ clock_div = I2C_CCR_CCR; - /* Configure clock_div in standard mode */ - if (clock_speed <= 100000) { + + if (clock_speed <= 100000) { /* Configure clock_div in standard mode */ chDbgAssert(duty == STD_DUTY_CYCLE, "i2c_lld_set_clock(), #1", "Invalid standard mode duty cycle"); - /* Standard mode clock_div calculate: Tlow/Thigh = 1/1 */ - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2)); - /* Test if CCR value is under 0x4, and set the minimum allowed value */ - if (clock_div < 0x04) clock_div = 0x04; - /* Set clock_div value for standard mode */ - regCCR |= (clock_div & I2C_CCR_CCR); - /* Set Maximum Rise Time for standard mode */ - i2cp->id_i2c->TRISE = freq + 1; + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2)); /* Standard mode clock_div calculate: Tlow/Thigh = 1/1 */ + if (clock_div < 0x04) clock_div = 0x04; /* Test if CCR value is under 0x4, and set the minimum allowed value */ + regCCR |= (clock_div & I2C_CCR_CCR); /* Set clock_div value for standard mode */ + i2cp->id_i2c->TRISE = freq + 1; /* Set Maximum Rise Time for standard mode */ } - /* Configure clock_div in fast mode */ - else if(clock_speed <= 400000) { + else if(clock_speed <= 400000) { /* Configure clock_div in fast mode */ chDbgAssert((duty == FAST_DUTY_CYCLE_2) || (duty == FAST_DUTY_CYCLE_16_9), "i2c_lld_set_clock(), #2", "Invalid fast mode duty cycle"); if(duty == FAST_DUTY_CYCLE_2) { - /* Fast mode clock_div calculate: Tlow/Thigh = 2/1 */ - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3)); + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3)); /* Fast mode clock_div calculate: Tlow/Thigh = 2/1 */ } else if(duty == FAST_DUTY_CYCLE_16_9) { - /* Fast mode clock_div calculate: Tlow/Thigh = 16/9 */ - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 25)); - /* Set DUTY bit */ - regCCR |= I2C_CCR_DUTY; + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 25)); /* Fast mode clock_div calculate: Tlow/Thigh = 16/9 */ + regCCR |= I2C_CCR_DUTY; /* Set DUTY bit */ } - /* Test if CCR value is under 0x1, and set the minimum allowed value */ - if(clock_div < 0x01) clock_div = 0x01; - /* Set clock_div value and F/S bit for fast mode*/ - regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR)); - /* Set Maximum Rise Time for fast mode */ - i2cp->id_i2c->TRISE = (freq * 300 / 1000) + 1; + if(clock_div < 0x01) clock_div = 0x01; /* Test if CCR value is under 0x1, and set the minimum allowed value */ + regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR)); /* Set clock_div value and F/S bit for fast mode*/ + i2cp->id_i2c->TRISE = (freq * 300 / 1000) + 1; /* Set Maximum Rise Time for fast mode */ } chDbgAssert((clock_div <= I2C_CCR_CCR), "i2c_lld_set_clock(), #3", "Too low clock clock speed selected"); - /* Write to I2Cx CCR */ - i2cp->id_i2c->CCR = regCCR; - - /* restore the I2C peripheral enabled state */ - i2cp->id_i2c->CR1 |= pe_bit_saved; + i2cp->id_i2c->CCR = regCCR; /* Write to I2Cx CCR */ + i2cp->id_i2c->CR1 |= pe_bit_saved; /* restore the I2C peripheral enabled state */ } /** @@ -560,9 +502,7 @@ void i2c_lld_set_opmode(I2CDriver *i2cp) { i2copmode_t opmode = i2cp->id_config->op_mode; uint16_t regCR1; - /*---------------------------- CR1 Configuration ------------------------*/ - /* Get the I2Cx CR1 value */ - regCR1 = i2cp->id_i2c->CR1; + regCR1 = i2cp->id_i2c->CR1; /* Get the I2Cx CR1 value */ switch(opmode){ case OPMODE_I2C: regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); @@ -575,8 +515,8 @@ void i2c_lld_set_opmode(I2CDriver *i2cp) { regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); break; } - /* Write to I2Cx CR1 */ - i2cp->id_i2c->CR1 = regCR1; + + i2cp->id_i2c->CR1 = regCR1; /* Write to I2Cx CR1 */ } /** @@ -587,10 +527,9 @@ void i2c_lld_set_opmode(I2CDriver *i2cp) { void i2c_lld_set_own_address(I2CDriver *i2cp) { /* TODO: dual address mode */ - /* OAR1 Configuration */ i2cp->id_i2c->OAR1 |= 1 << 14; - if (&(i2cp->id_config->own_addr_10) == NULL){/* only 7-bit address */ + if (&(i2cp->id_config->own_addr_10) == NULL){ /* only 7-bit address */ i2cp->id_i2c->OAR1 &= (~I2C_OAR1_ADDMODE); i2cp->id_i2c->OAR1 |= i2cp->id_config->own_addr_7 << 1; } @@ -609,9 +548,7 @@ void i2c_lld_set_own_address(I2CDriver *i2cp) { * @param[in] i2cp pointer to the @p I2CDriver object */ void i2c_lld_stop(I2CDriver *i2cp) { - - /* If in ready state then disables the I2C clock.*/ - if (i2cp->id_state == I2C_READY) { + if (i2cp->id_state == I2C_READY) { /* If in ready state then disables the I2C clock.*/ #if STM32_I2C_USE_I2C1 if (&I2CD1 == i2cp) { NVICDisableVector(I2C1_EV_IRQn); @@ -627,21 +564,22 @@ void i2c_lld_stop(I2CDriver *i2cp) { } #endif } + i2cp->id_state = I2C_STOP; } /** - * @brief Transmits data ever the I2C bus as master. + * @brief Transmits data via the I2C bus as master. * * @param[in] i2cp pointer to the @p I2CDriver object * @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 modes used. Otherwise keep it cleared. * Bits 10-14 unused. - * @param[in] txbytes number of bytes to be transmited + * @param[in] txbuf pointer to the transmit buffer + * @param[in] txbytes number of bytes to be transmitted + * @param[in] rxbuf pointer to the receive buffer * @param[in] rxbytes number of bytes to be received - * TODO: other parameters - * */ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes) { @@ -652,28 +590,21 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, i2cp->txbuf = txbuf; i2cp->rxbuf = rxbuf; - if(slave_addr & 0x8000){/* 10-bit mode used */ - /* add the two msb of 10-bit address to the header */ - i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); - /* add the header bits with LSB = 0 -> write */ - i2cp->slave_addr1 |= 0xF0; - /* the remaining 8 bit of 10-bit address */ - i2cp->slave_addr2 = slave_addr & 0x00FF; + if(slave_addr & 0x8000){ /* 10-bit mode used */ + i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); /* add the two msb of 10-bit address to the header */ + i2cp->slave_addr1 |= 0xF0; /* add the header bits with LSB = 0 -> write */ + i2cp->slave_addr2 = slave_addr & 0x00FF; /* the remaining 8 bit of 10-bit address */ } else{ - /* LSB = 0 -> write */ - i2cp->slave_addr1 = ((slave_addr <<1) & 0x00FE); + i2cp->slave_addr1 = ((slave_addr <<1) & 0x00FE); /* LSB = 0 -> write */ } i2cp->flags = 0; i2cp->errors = 0; i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - - i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ - - /* enable ERR, EVT & BUF ITs */ - i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ + i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); /* enable ERR, EVT & BUF ITs */ } @@ -685,10 +616,8 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, * device address. Bit 15 must be set to 1 if 10-bit * addressing modes used. Otherwise keep it cleared. * Bits 10-14 unused. - * @param[in] txbytes number of bytes to be transmited + * @param[in] rxbuf pointer to the receive buffer * @param[in] rxbytes number of bytes to be received - * TODO: other parameters - * */ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, uint8_t *rxbuf, size_t rxbytes){ @@ -701,43 +630,40 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, i2cp->rxbytes = rxbytes; i2cp->rxbuf = rxbuf; - if(slave_addr & 0x8000){/* 10-bit mode used */ - /* add the two msb of 10-bit address to the header */ - i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); - /* add the header bits (the LSB -> 1 will be add to second */ - i2cp->slave_addr1 |= 0xF0; - /* the remaining 8 bit of 10-bit address */ - i2cp->slave_addr2 = slave_addr & 0x00FF; + if(slave_addr & 0x8000){ /* 10-bit mode used */ + i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); /* add the two msb of 10-bit address to the header */ + i2cp->slave_addr1 |= 0xF0; /* add the header bits (the LSB -> 1 will be add to second */ + i2cp->slave_addr2 = slave_addr & 0x00FF; /* the remaining 8 bit of 10-bit address */ } else{ - /* LSB = 1 -> receive */ - i2cp->slave_addr1 = ((slave_addr <<1) | 0x01); + i2cp->slave_addr1 = ((slave_addr <<1) | 0x01); /* LSB = 1 -> receive */ } i2cp->flags = I2C_FLG_MASTER_RECEIVER; i2cp->errors = 0; - - i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - /* Only one byte to be received */ - if(i2cp->rxbytes == 1) { + if(i2cp->rxbytes == 1) { /* Only one byte to be received */ i2cp->flags |= I2C_FLG_1BTR; } - /* Only two bytes to be received */ - else if(i2cp->rxbytes == 2) { + else if(i2cp->rxbytes == 2) { /* Only two bytes to be received */ i2cp->flags |= I2C_FLG_2BTR; - i2cp->id_i2c->CR1 |= I2C_CR1_POS; /* Acknowledge Position */ + i2cp->id_i2c->CR1 |= I2C_CR1_POS; /* Acknowledge Position */ } - i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ - - /* enable ERR, EVT & BUF ITs */ - i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ + i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); /* enable ERR, EVT & BUF ITs */ } -/** TODO: doxy strings or remove this redundant function */ +/** + * @brief Realize read-though-write behavior. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ void i2c_lld_master_transceive(I2CDriver *i2cp){ chDbgAssert((i2cp != NULL) && (i2cp->slave_addr1 != 0) &&\ @@ -747,44 +673,38 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ i2cp->flags = I2C_FLG_MASTER_RECEIVER; i2cp->errors = 0; - - i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - if(i2cp->slave_addr & 0x8000){/* 10-bit mode used */ - /* add the two msb of 10-bit address to the header */ - i2cp->slave_addr1 = ((i2cp->slave_addr >>7) & 0x0006); - /* add the header bits (the LSB -> 1 will be add to second */ - i2cp->slave_addr1 |= 0xF0; - /* the remaining 8 bit of 10-bit address */ - i2cp->slave_addr2 = i2cp->slave_addr & 0x00FF; + if(i2cp->slave_addr & 0x8000){ /* 10-bit mode used */ + i2cp->slave_addr1 = ((i2cp->slave_addr >>7) & 0x0006);/* add the two msb of 10-bit address to the header */ + i2cp->slave_addr1 |= 0xF0; /* add the header bits (the LSB -> 1 will be add to second */ + i2cp->slave_addr2 = i2cp->slave_addr & 0x00FF; /* the remaining 8 bit of 10-bit address */ } else{ i2cp->slave_addr1 |= 0x01; } - /* Only one byte to be received */ - if(i2cp->rxbytes == 1) { + if(i2cp->rxbytes == 1) { /* Only one byte to be received */ i2cp->flags |= I2C_FLG_1BTR; } - /* Only two bytes to be received */ - else if(i2cp->rxbytes == 2) { + else if(i2cp->rxbytes == 2) { /* Only two bytes to be received */ i2cp->flags |= I2C_FLG_2BTR; - i2cp->id_i2c->CR1 |= I2C_CR1_POS; /* Acknowledge Position */ + i2cp->id_i2c->CR1 |= I2C_CR1_POS; /* Acknowledge Position */ } - i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ + i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ uint32_t timeout = I2C_START_TIMEOUT; while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) ; - /* is timeout overflows? */ chDbgAssert(timeout <= I2C_START_TIMEOUT, "i2c_lld_master_receive(), #1", "time is out"); - /* enable ERR, EVT & BUF ITs */ - i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); + i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); /* enable ERR, EVT & BUF ITs */ } +#undef rxBuffp +#undef txBuffp #endif /* HAL_USE_I2C */ From 621d794bf0d2a6456221f1e478de66e48c293063 Mon Sep 17 00:00:00 2001 From: barthess Date: Tue, 12 Jul 2011 18:26:39 +0000 Subject: [PATCH 76/92] I2C. Documentation improvements. Dead code clenups. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3153 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/dox/i2c.dox | 26 +++++++++++++++++---- os/hal/include/i2c.h | 19 ++++++--------- os/hal/platforms/STM32/i2c_lld.c | 2 +- os/hal/platforms/STM32/i2c_lld.h | 40 ++++++++++++++++---------------- os/hal/src/i2c.c | 18 +++++++++----- 5 files changed, 61 insertions(+), 44 deletions(-) diff --git a/os/hal/dox/i2c.dox b/os/hal/dox/i2c.dox index 1ffd2da47..cd5e3f698 100644 --- a/os/hal/dox/i2c.dox +++ b/os/hal/dox/i2c.dox @@ -31,12 +31,28 @@ * functionalities can be used in any moment, any transition not explicitly * shown in the following diagram has to be considered an error and shall * be captured by an assertion (if enabled). - * @if LATEX_PDF - * @else - * @endif - * + * @dot + digraph example { + rankdir="LR"; + node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", + width="0.9", height="0.9"]; + edge [fontname=Helvetica, fontsize=8]; + + uninit [label="I2C_UNINIT", style="bold"]; + stop [label="I2C_STOP\nLow Power"]; + ready [label="I2C_READY\nClock Enabled"]; + active [label="I2C_ACTIVE\nBus Active"]; + + uninit -> stop [label="i2cInit()"]; + stop -> stop [label="i2cStop()"]; + stop -> ready [label="i2cStart()"]; + ready -> active [label="i2cMasterTransmit()\ni2cMasterReceive()"]; + active -> ready [label="_i2c_isr_code()"]; + ready -> stop [label="i2cStop()"]; + } + * @enddot * The driver is not thread safe for performance reasons, if you need to access - * the I2C bus from multiple thread then use the @p i2cAcquireBus() and + * the I2C bus from multiple threads then use the @p i2cAcquireBus() and * @p i2cReleaseBus() APIs in order to gain exclusive access. * * @ingroup IO diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 1e7ce3e1e..19eab3b35 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -79,13 +79,12 @@ */ typedef enum { /* master part */ - I2C_UNINIT = 0, /**< @brief Not initialized. */ - I2C_STOP = 1, /**< @brief Stopped. */ - I2C_READY = 2, /**< @brief Ready. */ - I2C_ACTIVE = 3, /**< @brief In communication. */ - I2C_COMPLETE = 4, /**< @brief Asynchronous operation complete. */ + I2C_UNINIT = 0, /**< @brief Not initialized. */ + I2C_STOP = 1, /**< @brief Stopped. */ + I2C_READY = 2, /**< @brief Ready. */ + I2C_ACTIVE = 3, /**< @brief In communication. */ - /* slave part */ + /* Slave part. Not realized. */ I2C_SACTIVE = 10, I2C_STRANSMIT = 11, I2C_SRECEIVE = 12, @@ -209,11 +208,9 @@ struct I2CSlaveConfig{ * @notapi */ #define _i2c_isr_code(i2cp, i2cscfg) { \ - (i2cp)->id_state = I2C_COMPLETE; \ if(((i2cp)->id_slave_config)->id_callback) { \ ((i2cp)->id_slave_config)->id_callback(i2cp, i2cscfg); \ - if((i2cp)->id_state == I2C_COMPLETE) \ - (i2cp)->id_state = I2C_READY; \ + (i2cp)->id_state = I2C_READY; \ } \ else \ (i2cp)->id_state = I2C_READY; \ @@ -235,11 +232,9 @@ struct I2CSlaveConfig{ * @notapi */ #define _i2c_isr_err_code(i2cp, i2cscfg) { \ - (i2cp)->id_state = I2C_COMPLETE; \ if(((i2cp)->id_slave_config)->id_err_callback) { \ ((i2cp)->id_slave_config)->id_err_callback(i2cp, i2cscfg); \ - if((i2cp)->id_state == I2C_COMPLETE) \ - (i2cp)->id_state = I2C_READY; \ + (i2cp)->id_state = I2C_READY; \ } \ else \ (i2cp)->id_state = I2C_READY; \ diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 84959c7f0..1b36fde8f 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -1,7 +1,7 @@ /** * @file STM32/i2c_lld.c * @brief STM32 I2C subsystem low level driver source. Slave mode not implemented. - * @addtogroup STM32_I2C + * @addtogroup I2C * @{ */ diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index b41f8f6fa..c91e3103a 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -1,7 +1,7 @@ /** * @file STM32/i2c_lld.h * @brief STM32 I2C subsystem low level driver header. - * @addtogroup STM32_I2C + * @addtogroup I2C * @{ */ @@ -111,13 +111,13 @@ typedef enum { * @brief Driver configuration structure. */ typedef struct { - i2copmode_t op_mode; /*!< Specifies the I2C mode.*/ - uint32_t clock_speed; /*!< Specifies the clock frequency. Must be set to a value lower than 400kHz */ - i2cdutycycle_t duty_cycle; /*!< Specifies the I2C fast mode duty cycle */ - uint8_t own_addr_7; /*!< Specifies the first device 7-bit own address. */ - uint16_t own_addr_10; /*!< Specifies the second part of device own address in 10-bit mode. Set to NULL if not used. */ - uint16_t ack; /*!< Enables or disables the acknowledgement. */ - uint8_t nbit_own_addr; /*!< Specifies if 7-bit or 10-bit address is acknowledged */ + 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. */ + uint16_t ack; /**< @brief Enables or disables the acknowledgment. */ + uint8_t nbit_own_addr; /**< @brief Specifies if 7-bit or 10-bit address is acknowledged */ } I2CConfig; @@ -164,21 +164,21 @@ struct I2CDriver{ */ const I2CSlaveConfig *id_slave_config; - __IO size_t txbytes; /*!< Number of bytes to be transmitted. */ - __IO size_t rxbytes; /*!< Number of bytes to be received. */ - uint8_t *rxbuf; /*!< Pointer to receive buffer. */ - uint8_t *txbuf; /*!< Pointer to transmit buffer.*/ - uint8_t *rxbuff_p; /*!< Pointer to the current byte in slave rx buffer. */ - uint8_t *txbuff_p; /*!< Pointer to the current byte in slave tx buffer. */ + __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; /*!< Error flags.*/ - __IO i2cflags_t flags; /*!< State flags.*/ + __IO i2cflags_t errors; /*!< @brief Error flags.*/ + __IO i2cflags_t flags; /*!< @brief State flags.*/ - uint16_t slave_addr; /*!< Current slave address. */ - uint8_t slave_addr1;/*!< 7-bit address of the slave with r\w bit.*/ - uint8_t slave_addr2;/*!< Used in 10-bit address mode. */ + 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 Used in 10-bit address mode. */ - EventSource sevent; /*!< Status Change @p EventSource.*/ + EventSource sevent; /*!< @brief Status Change @p EventSource.*/ /*********** End of the mandatory fields. **********************************/ diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index cd12d42eb..b169fb70d 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -135,18 +135,23 @@ void i2cStop(I2CDriver *i2cp) { } /** - * @brief Sends data ever the I2C bus. + * @brief Sends data via the I2C bus. + * + * @details Function designed to realize "read-through-write" transfer + * paradigm. If you want transmit data without any further read, + * than set @b rxbuf field to 0. * * @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. Bits 0-9 contain slave * device address. Bit 15 must be set to 1 if 10-bit - * addressing modes used. Otherwise keep it cleared. + * addressing mode used. Otherwise keep it cleared. * Bits 10-14 unused. - * @param[in] txbytes number of bytes to be transmitted * @param[in] txbuf pointer to transmit buffer - * @param[in] rxbytes number of bytes to be received + * @param[in] txbytes number of bytes to be transmitted * @param[in] rxbuf pointer to receive buffer + * @param[in] rxbytes number of bytes to be received, set it to 0 if + * you want transmit only */ void i2cMasterTransmit(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, @@ -183,9 +188,10 @@ void i2cMasterTransmit(I2CDriver *i2cp, * @param[in] i2cscfg pointer to the @p I2C slave config * @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 modes used. Otherwise keep it cleared. + * addressing mode used. Otherwise keep it cleared. * Bits 10-14 unused. - * @param[in] txbytes number of bytes to be transmited + * @param[in] rxbytes number of bytes to be received + * @param[in] rxbuf pointer to receive buffer */ void i2cMasterReceive(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg, From 71ebbf914fa1cf07e969bdf774a861a4d76d0b9a Mon Sep 17 00:00:00 2001 From: barthess Date: Tue, 12 Jul 2011 18:34:11 +0000 Subject: [PATCH 77/92] I2C. Comments cleanups. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3154 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 1b36fde8f..594f833a1 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -154,8 +154,9 @@ void _i2c_ev7_master_rec_byte_qued(I2CDriver *i2cp){ break; case I2C_FLG_MASTER_RECEIVER: - /* some time in hi load cases possible to miss interrupt - * ??? TODO: really?*/ + /* Some times in hi load scenarions it is possible to "miss" interrupt + * because STM32 I2C has OR'ed interrupt sources. This case handle that + * scenario. */ if (i2cp->rxbytes > 3){ *rxBuffp = dp->DR; rxBuffp++; From 146118a1365dcfc7b9b1e2263dd3eb2e94d0fe27 Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 13 Jul 2011 11:07:48 +0000 Subject: [PATCH 78/92] I2C. Stability improvements in very hi load scenarios. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3157 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 594f833a1..e261c825f 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -11,6 +11,19 @@ #if HAL_USE_I2C || defined(__DOXYGEN__) +/*===========================================================================*/ +/* Datasheet notes. */ +/*===========================================================================*/ +/** + * From RM0008.pdf + * + * Note: + * When the STOP, START or PEC bit is set, the software must NOT perform + * any write access to I2C_CR1 before this bit is cleared by hardware. + * Otherwise there is a risk of setting a second STOP, START or PEC request. + */ + + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ @@ -100,6 +113,8 @@ void _i2c_ev6_master_rec_mode_selected(I2CDriver *i2cp){ case I2C_EV6_3_MASTER_REC_1BTR_MODE_SELECTED: /* only an single byte to receive */ dp->CR1 &= (uint16_t)~I2C_CR1_ACK; /* Clear ACK */ dp->CR1 |= I2C_CR1_STOP; /* Program the STOP */ + while(dp->CR1 & I2C_CR1_STOP) + ; break; case I2C_EV6_1_MASTER_REC_2BTR_MODE_SELECTED: /* only two bytes to receive */ @@ -137,6 +152,8 @@ void _i2c_ev7_master_rec_byte_qued(I2CDriver *i2cp){ i2cp->rxbytes -= 2; /* Decrement the number of readed bytes */ i2cp->flags = 0; dp->CR2 |= I2C_CR2_ITBUFEN; /* ready for read DataN. Enable interrupt for next (and last) RxNE event*/ + while(dp->CR1 & I2C_CR1_STOP) + ; break; case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: @@ -151,6 +168,8 @@ void _i2c_ev7_master_rec_byte_qued(I2CDriver *i2cp){ i2cp->rxbytes = 0; i2cp->flags = 0; _i2c_isr_code(i2cp, i2cp->id_slave_config); /* Portable I2C ISR code defined in the high level driver. */ + while(dp->CR1 & I2C_CR1_STOP) + ; break; case I2C_FLG_MASTER_RECEIVER: @@ -231,6 +250,8 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { if (i2cp->rxbytes == 0){ /* if nothing to read then generate stop */ dp->CR1 |= I2C_CR1_STOP; _i2c_isr_code(i2cp, i2cp->id_slave_config); /* Portable I2C ISR code defined in the high level driver. */ + while(dp->CR1 & I2C_CR1_STOP) + ; } else{ /* start reading operation */ i2c_lld_master_transceive(i2cp); @@ -297,6 +318,8 @@ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { if(reg->SR1 & I2C_SR1_AF) { /* Acknowledge fail */ reg->SR1 &= ~I2C_SR1_AF; reg->CR1 |= I2C_CR1_STOP; /* setting stop bit */ + while(i2cp->id_i2c->CR1 & I2C_CR1_STOP) + ; flags |= I2CD_ACK_FAILURE; } if(reg->SR1 & I2C_SR1_OVR) { /* Overrun */ From 2bdd9885e282b8cf26642f4a4b73fc4e61da872c Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 13 Jul 2011 20:41:26 +0000 Subject: [PATCH 79/92] I2C. Code cleanups. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3159 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index e261c825f..62a269dba 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -490,15 +490,18 @@ void i2c_lld_set_clock(I2CDriver *i2cp) { if (clock_speed <= 100000) { /* Configure clock_div in standard mode */ chDbgAssert(duty == STD_DUTY_CYCLE, - "i2c_lld_set_clock(), #1", "Invalid standard mode duty cycle"); + "i2c_lld_set_clock(), #1", + "Invalid standard mode duty cycle"); clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2)); /* Standard mode clock_div calculate: Tlow/Thigh = 1/1 */ if (clock_div < 0x04) clock_div = 0x04; /* Test if CCR value is under 0x4, and set the minimum allowed value */ regCCR |= (clock_div & I2C_CCR_CCR); /* Set clock_div value for standard mode */ i2cp->id_i2c->TRISE = freq + 1; /* Set Maximum Rise Time for standard mode */ } else if(clock_speed <= 400000) { /* Configure clock_div in fast mode */ - chDbgAssert((duty == FAST_DUTY_CYCLE_2) || (duty == FAST_DUTY_CYCLE_16_9), - "i2c_lld_set_clock(), #2", "Invalid fast mode duty cycle"); + chDbgAssert((duty == FAST_DUTY_CYCLE_2) || + (duty == FAST_DUTY_CYCLE_16_9), + "i2c_lld_set_clock(), #2", + "Invalid fast mode duty cycle"); if(duty == FAST_DUTY_CYCLE_2) { clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3)); /* Fast mode clock_div calculate: Tlow/Thigh = 2/1 */ } From e02d3607dc1dc88966a78cefc7aadb5eba941908 Mon Sep 17 00:00:00 2001 From: barthess Date: Thu, 14 Jul 2011 14:47:13 +0000 Subject: [PATCH 80/92] I2C. Waits moved from ISR. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3161 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 46 ++++++++++++++++++++++++++------ os/hal/platforms/STM32/i2c_lld.h | 11 ++++++++ 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 62a269dba..086af776e 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -48,12 +48,23 @@ static volatile uint16_t dbgSR1 = 0; static volatile uint16_t dbgSR2 = 0; static volatile uint16_t dbgCR1 = 0; static volatile uint16_t dbgCR2 = 0; + +static uint32_t polling_time_worst = 0; +static uint32_t polling_time_begin = 0; +static uint32_t polling_time_delta = 0; + #endif /* CH_DBG_ENABLE_ASSERTS */ /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ +#if STM32_I2C_USE_POLLING_WAIT +#else +VirtualTimer i2c_waiting_vt; +#endif /* STM32_I2C_USE_POLLING_WAIT */ + + /* defines for convenience purpose */ #define txBuffp (i2cp->txbuff_p) #define rxBuffp (i2cp->rxbuff_p) @@ -113,8 +124,6 @@ void _i2c_ev6_master_rec_mode_selected(I2CDriver *i2cp){ case I2C_EV6_3_MASTER_REC_1BTR_MODE_SELECTED: /* only an single byte to receive */ dp->CR1 &= (uint16_t)~I2C_CR1_ACK; /* Clear ACK */ dp->CR1 |= I2C_CR1_STOP; /* Program the STOP */ - while(dp->CR1 & I2C_CR1_STOP) - ; break; case I2C_EV6_1_MASTER_REC_2BTR_MODE_SELECTED: /* only two bytes to receive */ @@ -146,14 +155,14 @@ void _i2c_ev7_master_rec_byte_qued(I2CDriver *i2cp){ dp->CR1 &= (uint16_t)~I2C_CR1_ACK; /* Clear ACK */ *rxBuffp = dp->DR; /* Read the DataN-2. This clear the RXE & BFT flags and launch the DataN exception in the shift register (ending the SCL stretch) */ rxBuffp++; + chSysLockFromIsr(); dp->CR1 |= I2C_CR1_STOP; /* Program the STOP */ *rxBuffp = dp->DR; /* Read the DataN-1 */ + chSysUnlockFromIsr(); rxBuffp++; i2cp->rxbytes -= 2; /* Decrement the number of readed bytes */ i2cp->flags = 0; dp->CR2 |= I2C_CR2_ITBUFEN; /* ready for read DataN. Enable interrupt for next (and last) RxNE event*/ - while(dp->CR1 & I2C_CR1_STOP) - ; break; case I2C_EV7_3_MASTER_REC_2BYTES_TO_PROCESS: @@ -161,15 +170,15 @@ void _i2c_ev7_master_rec_byte_qued(I2CDriver *i2cp){ * DataN-1 and DataN are received */ dp->CR2 &= (uint16_t)~I2C_CR2_ITEVTEN; dp->CR2 &= (uint16_t)~I2C_CR2_ITBUFEN; + chSysLockFromIsr(); dp->CR1 |= I2C_CR1_STOP; /* Program the STOP */ *rxBuffp = dp->DR; /* Read the DataN-1*/ rxBuffp++; *rxBuffp = dp->DR; /* Read the DataN*/ + chSysUnlockFromIsr(); i2cp->rxbytes = 0; i2cp->flags = 0; _i2c_isr_code(i2cp, i2cp->id_slave_config); /* Portable I2C ISR code defined in the high level driver. */ - while(dp->CR1 & I2C_CR1_STOP) - ; break; case I2C_FLG_MASTER_RECEIVER: @@ -250,8 +259,6 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { if (i2cp->rxbytes == 0){ /* if nothing to read then generate stop */ dp->CR1 |= I2C_CR1_STOP; _i2c_isr_code(i2cp, i2cp->id_slave_config); /* Portable I2C ISR code defined in the high level driver. */ - while(dp->CR1 & I2C_CR1_STOP) - ; } else{ /* start reading operation */ i2c_lld_master_transceive(i2cp); @@ -629,6 +636,17 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, i2cp->flags = 0; i2cp->errors = 0; + #if CH_DBG_ENABLE_ASSERTS + polling_time_begin = PWMD4.tim->CNT; + #endif + while(i2cp->id_i2c->CR1 & I2C_CR1_STOP) + ; + #if CH_DBG_ENABLE_ASSERTS + polling_time_delta = PWMD4.tim->CNT - polling_time_begin; + if (polling_time_delta > polling_time_worst) + polling_time_worst = polling_time_delta; + #endif + i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); /* enable ERR, EVT & BUF ITs */ @@ -668,6 +686,18 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, i2cp->flags = I2C_FLG_MASTER_RECEIVER; i2cp->errors = 0; + + #if CH_DBG_ENABLE_ASSERTS + polling_time_begin = PWMD4.tim->CNT; + #endif + while(i2cp->id_i2c->CR1 & I2C_CR1_STOP) + ; + #if CH_DBG_ENABLE_ASSERTS + polling_time_delta = PWMD4.tim->CNT - polling_time_begin; + if (polling_time_delta > polling_time_worst) + polling_time_worst = polling_time_delta; + #endif + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index c91e3103a..d964b342a 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -19,6 +19,17 @@ /* Driver pre-compile time settings. */ /*===========================================================================*/ +/** + * @brief Waiting method switch. + * @details If set to @p TRUE than waiting of STOP generation will use + * while() loop polling. Otherwise -- virtual timer will be used. + * @note The default is @p TRUE. + * @note Virtual timer resolution is 1/@p CH_FREQUENCY seconds. + */ +#if !defined(STM32_I2C_USE_POLLING_WAIT) || defined(__DOXYGEN__) +#define STM32_I2C_USE_POLLING_WAIT TRUE +#endif + /** * @brief I2C1 driver enable switch. * @details If set to @p TRUE the support for I2C1 is included. From b569145b24a59d0741a26885767efa04146f78a5 Mon Sep 17 00:00:00 2001 From: barthess Date: Tue, 19 Jul 2011 20:45:57 +0000 Subject: [PATCH 81/92] I2C. STOP waitings was replaced by GPT callback functions. Need much of testing. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3166 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 9 +- os/hal/platforms/STM32/i2c_lld.c | 182 +++++++++++++++++++++++-------- os/hal/platforms/STM32/i2c_lld.h | 47 +++++++- os/hal/src/i2c.c | 4 +- 4 files changed, 188 insertions(+), 54 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 19eab3b35..16d6f77b6 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -79,10 +79,11 @@ */ typedef enum { /* master part */ - I2C_UNINIT = 0, /**< @brief Not initialized. */ - I2C_STOP = 1, /**< @brief Stopped. */ - I2C_READY = 2, /**< @brief Ready. */ - I2C_ACTIVE = 3, /**< @brief In communication. */ + I2C_UNINIT = 0, /**< @brief Not initialized. */ + I2C_STOP = 1, /**< @brief Stopped. */ + I2C_READY = 2, /**< @brief Ready. */ + I2C_ACTIVE_TRANSMIT = 3,/**< @brief Transmit in progress. */ + I2C_ACTIVE_RECEIVE = 4, /**< @brief Receive in progress. */ /* Slave part. Not realized. */ I2C_SACTIVE = 10, diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 086af776e..84c395fb5 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -23,6 +23,11 @@ * Otherwise there is a risk of setting a second STOP, START or PEC request. */ +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ +#define I2C_STOP_GPT_TIMEOUT 50 /* waiting timer value */ +#define I2C_START_GPT_TIMEOUT 50 /* waiting timer value */ /*===========================================================================*/ /* Driver exported variables. */ @@ -48,27 +53,83 @@ static volatile uint16_t dbgSR1 = 0; static volatile uint16_t dbgSR2 = 0; static volatile uint16_t dbgCR1 = 0; static volatile uint16_t dbgCR2 = 0; - -static uint32_t polling_time_worst = 0; -static uint32_t polling_time_begin = 0; -static uint32_t polling_time_delta = 0; - #endif /* CH_DBG_ENABLE_ASSERTS */ +/* defines for convenience purpose */ +#define txBuffp (i2cp->txbuff_p) +#define rxBuffp (i2cp->rxbuff_p) + /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ #if STM32_I2C_USE_POLLING_WAIT #else -VirtualTimer i2c_waiting_vt; +/* + * GPT1 callback. + */ +static void gpt1cb(GPTDriver *gptp) { + (void)gptp; + I2CDriver *i2cp = &I2CD1; + + chSysLockFromIsr(); + i2cp->flags &= ~I2C_FLG_TIMER_ARMED; + + switch(i2cp->id_state){ + case I2C_ACTIVE_TRANSMIT: + i2c_lld_master_transmit(i2cp, i2cp->slave_addr, i2cp->txbuf, i2cp->txbytes, i2cp->rxbuf, i2cp->rxbytes); + break; + + case I2C_ACTIVE_RECEIVE: + i2c_lld_master_receive(i2cp, i2cp->slave_addr, i2cp->rxbuf, i2cp->rxbytes); + break; + + default: + break; + } + chSysUnlockFromIsr(); +} + + + +/* + * GPT2 callback. + */ +static void gpt2cb(GPTDriver *gptp) { + (void)gptp; + I2CDriver *i2cp = &I2CD2; + + chSysLockFromIsr(); + i2cp->flags &= ~I2C_FLG_TIMER_ARMED; + + switch(i2cp->id_state){ + case I2C_ACTIVE_TRANSMIT: + i2c_lld_master_transmit(i2cp, i2cp->slave_addr, i2cp->txbuf, i2cp->txbytes, i2cp->rxbuf, i2cp->rxbytes); + break; + + case I2C_ACTIVE_RECEIVE: + i2c_lld_master_receive(i2cp, i2cp->slave_addr, i2cp->rxbuf, i2cp->rxbytes); + break; + + default: + break; + } + chSysUnlockFromIsr(); +} + +/* GPT1 configuration. */ +static const GPTConfig gpt1cfg = { + 1000000, /* 1MHz timer clock.*/ + gpt1cb /* Timer callback.*/ +}; + +/* GPT2 configuration. */ +static const GPTConfig gpt2cfg = { + 1000000, /* 1MHz timer clock.*/ + gpt2cb /* Timer callback.*/ +}; #endif /* STM32_I2C_USE_POLLING_WAIT */ - -/* defines for convenience purpose */ -#define txBuffp (i2cp->txbuff_p) -#define rxBuffp (i2cp->rxbuff_p) - /** * @brief Function for I2C debugging purpose. * @note Internal use only. @@ -408,15 +469,33 @@ void i2c_lld_init(void) { RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; /* reset I2C 1 */ RCC->APB1RSTR = 0; i2cObjectInit(&I2CD1); - I2CD1.id_i2c = I2C1; -#endif + I2CD1.id_i2c = I2C1; + +#if !(STM32_I2C_I2C1_USE_POLLING_WAIT) + I2CD1.timer = &GPTD1;//TODO: remove hardcode + I2CD1.timer_cfg = &gpt1cfg;//TODO: remove hardcode +#else + I2CD1.timer = NULL; + I2CD1.timer_cfg = NULL; +#endif /* !(STM32_I2C_I2C1_USE_POLLING_WAIT) */ + +#endif /* STM32_I2C_USE_I2C */ #if STM32_I2C_USE_I2C2 RCC->APB1RSTR = RCC_APB1RSTR_I2C2RST; /* reset I2C 2 */ RCC->APB1RSTR = 0; i2cObjectInit(&I2CD2); - I2CD2.id_i2c = I2C2; -#endif + I2CD2.id_i2c = I2C2; + +#if !(STM32_I2C_I2C2_USE_POLLING_WAIT) + I2CD2.timer = &GPTD2;//TODO: remove hardcode + I2CD2.timer_cfg = &gpt2cfg;//TODO: remove hardcode +#else + I2CD2.timer = NULL; + I2CD2.timer_cfg = NULL; +#endif /* !(STM32_I2C_I2C2_USE_POLLING_WAIT) */ + +#endif /* STM32_I2C_USE_I2C2 */ } /** @@ -425,6 +504,9 @@ void i2c_lld_init(void) { * @param[in] i2cp pointer to the @p I2CDriver object */ void i2c_lld_start(I2CDriver *i2cp) { + if (i2cp->timer != NULL || i2cp->timer_cfg != NULL) + gptStart(i2cp->timer, i2cp->timer_cfg); + if (i2cp->id_state == I2C_STOP) { /* If in stopped state then enables the I2C clock.*/ #if STM32_I2C_USE_I2C1 if (&I2CD1 == i2cp) { @@ -633,22 +715,22 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, i2cp->slave_addr1 = ((slave_addr <<1) & 0x00FE); /* LSB = 0 -> write */ } + chDbgAssert(!(i2cp->flags & I2C_FLG_TIMER_ARMED), + "i2c_lld_master_transmit(), #1", "time to STOP is out"); + if ((i2cp->id_i2c->CR1 & I2C_CR1_STOP) && i2cp->timer != NULL && i2cp->timer_cfg != NULL){ + gptStartOneShot(i2cp->timer, I2C_STOP_GPT_TIMEOUT); + i2cp->flags |= I2C_FLG_TIMER_ARMED; + return; + } + else{ + while(i2cp->id_i2c->CR1 & I2C_CR1_STOP) + ; + } + i2cp->flags = 0; i2cp->errors = 0; - - #if CH_DBG_ENABLE_ASSERTS - polling_time_begin = PWMD4.tim->CNT; - #endif - while(i2cp->id_i2c->CR1 & I2C_CR1_STOP) - ; - #if CH_DBG_ENABLE_ASSERTS - polling_time_delta = PWMD4.tim->CNT - polling_time_begin; - if (polling_time_delta > polling_time_worst) - polling_time_worst = polling_time_delta; - #endif - i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ + i2cp->id_i2c->CR1 |= I2C_CR1_START; i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); /* enable ERR, EVT & BUF ITs */ } @@ -675,6 +757,7 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, i2cp->rxbytes = rxbytes; i2cp->rxbuf = rxbuf; + if(slave_addr & 0x8000){ /* 10-bit mode used */ i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); /* add the two msb of 10-bit address to the header */ i2cp->slave_addr1 |= 0xF0; /* add the header bits (the LSB -> 1 will be add to second */ @@ -684,19 +767,22 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, i2cp->slave_addr1 = ((slave_addr <<1) | 0x01); /* LSB = 1 -> receive */ } - i2cp->flags = I2C_FLG_MASTER_RECEIVER; - i2cp->errors = 0; - #if CH_DBG_ENABLE_ASSERTS - polling_time_begin = PWMD4.tim->CNT; - #endif - while(i2cp->id_i2c->CR1 & I2C_CR1_STOP) - ; - #if CH_DBG_ENABLE_ASSERTS - polling_time_delta = PWMD4.tim->CNT - polling_time_begin; - if (polling_time_delta > polling_time_worst) - polling_time_worst = polling_time_delta; - #endif + chDbgAssert(!(i2cp->flags & I2C_FLG_TIMER_ARMED), + "i2c_lld_master_receive(), #1", "time to STOP is out"); + if ((i2cp->id_i2c->CR1 & I2C_CR1_STOP) && i2cp->timer != NULL && i2cp->timer_cfg != NULL){ + gptStartOneShot(i2cp->timer, I2C_STOP_GPT_TIMEOUT); + i2cp->flags |= I2C_FLG_TIMER_ARMED; + return; + } + else{ + while(i2cp->id_i2c->CR1 & I2C_CR1_STOP) + ; + } + + + i2cp->flags |= I2C_FLG_MASTER_RECEIVER; + i2cp->errors = 0; i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; @@ -728,11 +814,6 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ "i2c_lld_master_transceive(), #1", ""); - i2cp->flags = I2C_FLG_MASTER_RECEIVER; - i2cp->errors = 0; - i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ - i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; - if(i2cp->slave_addr & 0x8000){ /* 10-bit mode used */ i2cp->slave_addr1 = ((i2cp->slave_addr >>7) & 0x0006);/* add the two msb of 10-bit address to the header */ i2cp->slave_addr1 |= 0xF0; /* add the header bits (the LSB -> 1 will be add to second */ @@ -742,6 +823,14 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ i2cp->slave_addr1 |= 0x01; } + + + + i2cp->flags |= I2C_FLG_MASTER_RECEIVER; + i2cp->errors = 0; + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ + i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; + if(i2cp->rxbytes == 1) { /* Only one byte to be received */ i2cp->flags |= I2C_FLG_1BTR; } @@ -750,6 +839,9 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_POS; /* Acknowledge Position */ } + +//TODO: use timer here also!! + i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ uint32_t timeout = I2C_START_TIMEOUT; diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index d964b342a..b5f75e77f 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -20,16 +20,45 @@ /*===========================================================================*/ /** - * @brief Waiting method switch. + * @brief TODO!!!!!!!! * @details If set to @p TRUE than waiting of STOP generation will use * while() loop polling. Otherwise -- virtual timer will be used. * @note The default is @p TRUE. * @note Virtual timer resolution is 1/@p CH_FREQUENCY seconds. */ -#if !defined(STM32_I2C_USE_POLLING_WAIT) || defined(__DOXYGEN__) -#define STM32_I2C_USE_POLLING_WAIT TRUE +#if !defined(STM32_I2C_I2C1_USE_GPT_TIM1) || \ + !defined(STM32_I2C_I2C1_USE_GPT_TIM2) || \ + !defined(STM32_I2C_I2C1_USE_GPT_TIM3) || \ + !defined(STM32_I2C_I2C1_USE_GPT_TIM4) || \ + !defined(STM32_I2C_I2C1_USE_GPT_TIM5) || \ + !defined(STM32_I2C_I2C1_USE_GPT_TIM8) || \ + !defined(STM32_I2C_I2C1_USE_VIRTUAL_TIMER) || \ + !defined(STM32_I2C_I2C1_USE_POLLING_WAIT) || \ + defined(__DOXYGEN__) +#define STM32_I2C_I2C1_USE_POLLING_WAIT TRUE #endif + + +#if !defined(STM32_I2C_I2C2_USE_GPT_TIM1) || \ + !defined(STM32_I2C_I2C2_USE_GPT_TIM2) || \ + !defined(STM32_I2C_I2C2_USE_GPT_TIM3) || \ + !defined(STM32_I2C_I2C2_USE_GPT_TIM4) || \ + !defined(STM32_I2C_I2C2_USE_GPT_TIM5) || \ + !defined(STM32_I2C_I2C2_USE_GPT_TIM8) || \ + !defined(STM32_I2C_I2C2_USE_VIRTUAL_TIMER) || \ + !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. @@ -89,6 +118,7 @@ #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) @@ -197,6 +227,17 @@ struct I2CDriver{ * @brief Pointer to the I2Cx registers block. */ I2C_TypeDef *id_i2c; + + /** + * @brief Timer for waiting STOP condition on the bus. + * @details Workaround for STM32 buggy I2C cell. + */ + GPTDriver *timer; + + /** + * @brief Config for workaround timer. + */ + const GPTConfig *timer_cfg; } ; diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index b169fb70d..b233764f5 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -176,7 +176,7 @@ void i2cMasterTransmit(I2CDriver *i2cp, chDbgAssert(i2cp->id_state == I2C_READY, "i2cMasterTransmit(), #1", "not ready"); - i2cp->id_state = I2C_ACTIVE; + i2cp->id_state = I2C_ACTIVE_TRANSMIT; i2c_lld_master_transmit(i2cp, slave_addr, txbuf, txbytes, rxbuf, rxbytes); _i2c_wait_s(i2cp); } @@ -214,7 +214,7 @@ void i2cMasterReceive(I2CDriver *i2cp, chDbgAssert(i2cp->id_state == I2C_READY, "i2cMasterReceive(), #1", "not ready"); - i2cp->id_state = I2C_ACTIVE; + i2cp->id_state = I2C_ACTIVE_RECEIVE; i2c_lld_master_receive(i2cp, slave_addr, rxbuf, rxbytes); _i2c_wait_s(i2cp); } From 302d06cc6652cd44f961c35c7194ff3145f55406 Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 20 Jul 2011 08:35:05 +0000 Subject: [PATCH 82/92] I2C. All polling waitins code replaced by "waiting" GPT interrups. Documentation fixes. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3167 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/dox/i2c.dox | 20 ++-- os/hal/include/i2c.h | 11 ++- os/hal/platforms/STM32/i2c_lld.c | 160 +++++++++++++++++-------------- os/hal/platforms/STM32/i2c_lld.h | 43 +++------ 4 files changed, 118 insertions(+), 116 deletions(-) diff --git a/os/hal/dox/i2c.dox b/os/hal/dox/i2c.dox index cd5e3f698..8e6f78649 100644 --- a/os/hal/dox/i2c.dox +++ b/os/hal/dox/i2c.dox @@ -22,7 +22,12 @@ * @defgroup I2C I2C Driver * @brief Generic I2C Driver. * @details This module implements a generic I2C (Inter-Integrated Circuit) - * driver. + * driver. On STM32 platform you can choose method of waiting START + * and STOP bits: polling wait or wait using GPT. GPT method use + * one timer per I2C interface, on the other hand -- polling is + * block function that starts transfer. + * @note If you decide to use polling wait -- do NOT start transmit or + * receive from callback because it run in ISR context. * @pre In order to use the I2C driver the @p HAL_USE_I2C option * must be enabled in @p halconf.h. * @@ -34,20 +39,23 @@ * @dot digraph example { rankdir="LR"; - node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", + node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="false", width="0.9", height="0.9"]; edge [fontname=Helvetica, fontsize=8]; uninit [label="I2C_UNINIT", style="bold"]; stop [label="I2C_STOP\nLow Power"]; ready [label="I2C_READY\nClock Enabled"]; - active [label="I2C_ACTIVE\nBus Active"]; + active_tx [label="I2C_ACTIVE_TRANSMIT\nBus TX Active"]; + active_rx [label="I2C_ACTIVE_RECEIVE\nBus RX Active"]; uninit -> stop [label="i2cInit()"]; - stop -> stop [label="i2cStop()"]; + stop -> stop [label="i2cStop()"]; stop -> ready [label="i2cStart()"]; - ready -> active [label="i2cMasterTransmit()\ni2cMasterReceive()"]; - active -> ready [label="_i2c_isr_code()"]; + ready -> active_tx [label="i2cMasterTransmit()"]; + ready -> active_rx [label="i2cMasterReceive()"]; + active_tx -> ready [label="_i2c_isr_code()"]; + active_rx -> ready [label="_i2c_isr_code()"]; ready -> stop [label="i2cStop()"]; } * @enddot diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 16d6f77b6..73f633353 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -79,11 +79,12 @@ */ typedef enum { /* master part */ - I2C_UNINIT = 0, /**< @brief Not initialized. */ - I2C_STOP = 1, /**< @brief Stopped. */ - I2C_READY = 2, /**< @brief Ready. */ - I2C_ACTIVE_TRANSMIT = 3,/**< @brief Transmit in progress. */ - I2C_ACTIVE_RECEIVE = 4, /**< @brief Receive in progress. */ + I2C_UNINIT = 0, /**< @brief Not initialized. */ + I2C_STOP = 1, /**< @brief Stopped. */ + I2C_READY = 2, /**< @brief Ready. */ + I2C_ACTIVE_TRANSMIT = 3, /**< @brief Transmit in progress. */ + I2C_ACTIVE_RECEIVE = 4, /**< @brief Receive in progress. */ + I2C_ACTIVE_TRANSCEIVE = 5, /**< @brief Receive after transmit in progress. */ /* Slave part. Not realized. */ I2C_SACTIVE = 10, diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 84c395fb5..20db34fff 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -63,12 +63,10 @@ static volatile uint16_t dbgCR2 = 0; /* Driver local functions. */ /*===========================================================================*/ -#if STM32_I2C_USE_POLLING_WAIT +#if STM32_I2C_I2C1_USE_POLLING_WAIT #else -/* - * GPT1 callback. - */ -static void gpt1cb(GPTDriver *gptp) { +/* I2C1 GPT callback. */ +static void i2c1gptcb(GPTDriver *gptp) { (void)gptp; I2CDriver *i2cp = &I2CD1; @@ -84,18 +82,26 @@ static void gpt1cb(GPTDriver *gptp) { i2c_lld_master_receive(i2cp, i2cp->slave_addr, i2cp->rxbuf, i2cp->rxbytes); break; + case I2C_ACTIVE_TRANSCEIVE: + i2c_lld_master_transceive(i2cp); + break; + default: break; } chSysUnlockFromIsr(); } +/* I2C1 GPT configuration. */ +static const GPTConfig i2c1gptcfg = { + 1000000, /* 1MHz timer clock.*/ + i2c1gptcb /* Timer callback.*/ +}; +#endif /* STM32_I2C_I2C1_USE_POLLING_WAIT */ - - -/* - * GPT2 callback. - */ -static void gpt2cb(GPTDriver *gptp) { +#if STM32_I2C_I2C2_USE_POLLING_WAIT +#else +/* I2C2 GPT callback. */ +static void i2c2gptcb(GPTDriver *gptp) { (void)gptp; I2CDriver *i2cp = &I2CD2; @@ -111,24 +117,21 @@ static void gpt2cb(GPTDriver *gptp) { i2c_lld_master_receive(i2cp, i2cp->slave_addr, i2cp->rxbuf, i2cp->rxbytes); break; + case I2C_ACTIVE_TRANSCEIVE: + i2c_lld_master_transceive(i2cp); + break; + default: break; } chSysUnlockFromIsr(); } - -/* GPT1 configuration. */ -static const GPTConfig gpt1cfg = { +/* I2C2 GPT configuration. */ +static const GPTConfig i2c2gptcfg = { 1000000, /* 1MHz timer clock.*/ - gpt1cb /* Timer callback.*/ + i2c2gptcb /* Timer callback.*/ }; - -/* GPT2 configuration. */ -static const GPTConfig gpt2cfg = { - 1000000, /* 1MHz timer clock.*/ - gpt2cb /* Timer callback.*/ -}; -#endif /* STM32_I2C_USE_POLLING_WAIT */ +#endif /* STM32_I2C_I2C2_USE_POLLING_WAIT */ /** * @brief Function for I2C debugging purpose. @@ -322,6 +325,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { _i2c_isr_code(i2cp, i2cp->id_slave_config); /* Portable I2C ISR code defined in the high level driver. */ } else{ /* start reading operation */ + i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ i2c_lld_master_transceive(i2cp); } break; @@ -471,12 +475,12 @@ void i2c_lld_init(void) { i2cObjectInit(&I2CD1); I2CD1.id_i2c = I2C1; -#if !(STM32_I2C_I2C1_USE_POLLING_WAIT) - I2CD1.timer = &GPTD1;//TODO: remove hardcode - I2CD1.timer_cfg = &gpt1cfg;//TODO: remove hardcode -#else +#if STM32_I2C_I2C1_USE_POLLING_WAIT I2CD1.timer = NULL; I2CD1.timer_cfg = NULL; +#else + I2CD1.timer = &(STM32_I2C_I2C1_USE_GPT_TIM); + I2CD1.timer_cfg = &i2c1gptcfg; #endif /* !(STM32_I2C_I2C1_USE_POLLING_WAIT) */ #endif /* STM32_I2C_USE_I2C */ @@ -487,12 +491,12 @@ void i2c_lld_init(void) { i2cObjectInit(&I2CD2); I2CD2.id_i2c = I2C2; -#if !(STM32_I2C_I2C2_USE_POLLING_WAIT) - I2CD2.timer = &GPTD2;//TODO: remove hardcode - I2CD2.timer_cfg = &gpt2cfg;//TODO: remove hardcode -#else +#if STM32_I2C_I2C2_USE_POLLING_WAIT I2CD2.timer = NULL; I2CD2.timer_cfg = NULL; +#else + I2CD2.timer = &(STM32_I2C_I2C2_USE_GPT_TIM); + I2CD2.timer_cfg = &i2c2gptcfg; #endif /* !(STM32_I2C_I2C2_USE_POLLING_WAIT) */ #endif /* STM32_I2C_USE_I2C2 */ @@ -700,21 +704,7 @@ 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) { - i2cp->slave_addr = slave_addr; - i2cp->txbytes = txbytes; - i2cp->rxbytes = rxbytes; - i2cp->txbuf = txbuf; - i2cp->rxbuf = rxbuf; - - if(slave_addr & 0x8000){ /* 10-bit mode used */ - i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); /* add the two msb of 10-bit address to the header */ - i2cp->slave_addr1 |= 0xF0; /* add the header bits with LSB = 0 -> write */ - i2cp->slave_addr2 = slave_addr & 0x00FF; /* the remaining 8 bit of 10-bit address */ - } - else{ - i2cp->slave_addr1 = ((slave_addr <<1) & 0x00FE); /* LSB = 0 -> write */ - } - + /* "waiting" for STOP bit routine*/ chDbgAssert(!(i2cp->flags & I2C_FLG_TIMER_ARMED), "i2c_lld_master_transmit(), #1", "time to STOP is out"); if ((i2cp->id_i2c->CR1 & I2C_CR1_STOP) && i2cp->timer != NULL && i2cp->timer_cfg != NULL){ @@ -727,6 +717,24 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, ; } + /* init driver fields */ + i2cp->slave_addr = slave_addr; + i2cp->txbytes = txbytes; + i2cp->rxbytes = rxbytes; + i2cp->txbuf = txbuf; + i2cp->rxbuf = rxbuf; + + /* init address fields */ + if(slave_addr & 0x8000){ /* 10-bit mode used */ + i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); /* add the two msb of 10-bit address to the header */ + i2cp->slave_addr1 |= 0xF0; /* add the header bits with LSB = 0 -> write */ + i2cp->slave_addr2 = slave_addr & 0x00FF; /* the remaining 8 bit of 10-bit address */ + } + else{ + i2cp->slave_addr1 = ((slave_addr <<1) & 0x00FE); /* LSB = 0 -> write */ + } + + /* setting flags and register bits */ i2cp->flags = 0; i2cp->errors = 0; i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; @@ -753,21 +761,7 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, "i2c_lld_master_receive(), #1", "some interrupt sources not clear"); - i2cp->slave_addr = slave_addr; - i2cp->rxbytes = rxbytes; - i2cp->rxbuf = rxbuf; - - - if(slave_addr & 0x8000){ /* 10-bit mode used */ - i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); /* add the two msb of 10-bit address to the header */ - i2cp->slave_addr1 |= 0xF0; /* add the header bits (the LSB -> 1 will be add to second */ - i2cp->slave_addr2 = slave_addr & 0x00FF; /* the remaining 8 bit of 10-bit address */ - } - else{ - i2cp->slave_addr1 = ((slave_addr <<1) | 0x01); /* LSB = 1 -> receive */ - } - - + /* "waiting" for STOP bit routine*/ chDbgAssert(!(i2cp->flags & I2C_FLG_TIMER_ARMED), "i2c_lld_master_receive(), #1", "time to STOP is out"); if ((i2cp->id_i2c->CR1 & I2C_CR1_STOP) && i2cp->timer != NULL && i2cp->timer_cfg != NULL){ @@ -780,7 +774,22 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, ; } + /* init driver fields */ + i2cp->slave_addr = slave_addr; + i2cp->rxbytes = rxbytes; + i2cp->rxbuf = rxbuf; + /* init address fields */ + if(slave_addr & 0x8000){ /* 10-bit mode used */ + i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); /* add the two msb of 10-bit address to the header */ + i2cp->slave_addr1 |= 0xF0; /* add the header bits (the LSB -> 1 will be add to second */ + i2cp->slave_addr2 = slave_addr & 0x00FF; /* the remaining 8 bit of 10-bit address */ + } + else{ + i2cp->slave_addr1 = ((slave_addr <<1) | 0x01); /* LSB = 1 -> receive */ + } + + /* setting flags and register bits */ i2cp->flags |= I2C_FLG_MASTER_RECEIVER; i2cp->errors = 0; @@ -814,6 +823,22 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ "i2c_lld_master_transceive(), #1", ""); + i2cp->id_state = I2C_ACTIVE_TRANSCEIVE; + + /* "waiting" for START bit routine*/ + chDbgAssert(!(i2cp->flags & I2C_FLG_TIMER_ARMED), + "i2c_lld_master_transceive(), #1", "time to START is out"); + if ((i2cp->id_i2c->CR1 & I2C_CR1_START) && i2cp->timer != NULL && i2cp->timer_cfg != NULL){ + gptStartOneShot(i2cp->timer, I2C_START_GPT_TIMEOUT); + i2cp->flags |= I2C_FLG_TIMER_ARMED; + return; + } + else{ + while(i2cp->id_i2c->CR1 & I2C_CR1_START) + ; + } + + /* init address fields */ if(i2cp->slave_addr & 0x8000){ /* 10-bit mode used */ i2cp->slave_addr1 = ((i2cp->slave_addr >>7) & 0x0006);/* add the two msb of 10-bit address to the header */ i2cp->slave_addr1 |= 0xF0; /* add the header bits (the LSB -> 1 will be add to second */ @@ -823,9 +848,7 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ i2cp->slave_addr1 |= 0x01; } - - - + /* setting flags and register bits */ i2cp->flags |= I2C_FLG_MASTER_RECEIVER; i2cp->errors = 0; i2cp->id_i2c->CR1 |= I2C_CR1_ACK; /* acknowledge returned */ @@ -839,17 +862,6 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ i2cp->id_i2c->CR1 |= I2C_CR1_POS; /* Acknowledge Position */ } - -//TODO: use timer here also!! - - i2cp->id_i2c->CR1 |= I2C_CR1_START; /* send start bit */ - - uint32_t timeout = I2C_START_TIMEOUT; - while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout--) - ; - chDbgAssert(timeout <= I2C_START_TIMEOUT, - "i2c_lld_master_receive(), #1", "time is out"); - i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); /* enable ERR, EVT & BUF ITs */ } diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index b5f75e77f..44ecdf70e 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -20,45 +20,25 @@ /*===========================================================================*/ /** - * @brief TODO!!!!!!!! - * @details If set to @p TRUE than waiting of STOP generation will use - * while() loop polling. Otherwise -- virtual timer will be used. - * @note The default is @p TRUE. - * @note Virtual timer resolution is 1/@p CH_FREQUENCY seconds. + * @brief I2C1 driver synchronization choice between GPT and polling. + * @note The default is polling wait. */ -#if !defined(STM32_I2C_I2C1_USE_GPT_TIM1) || \ - !defined(STM32_I2C_I2C1_USE_GPT_TIM2) || \ - !defined(STM32_I2C_I2C1_USE_GPT_TIM3) || \ - !defined(STM32_I2C_I2C1_USE_GPT_TIM4) || \ - !defined(STM32_I2C_I2C1_USE_GPT_TIM5) || \ - !defined(STM32_I2C_I2C1_USE_GPT_TIM8) || \ - !defined(STM32_I2C_I2C1_USE_VIRTUAL_TIMER) || \ - !defined(STM32_I2C_I2C1_USE_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 - - -#if !defined(STM32_I2C_I2C2_USE_GPT_TIM1) || \ - !defined(STM32_I2C_I2C2_USE_GPT_TIM2) || \ - !defined(STM32_I2C_I2C2_USE_GPT_TIM3) || \ - !defined(STM32_I2C_I2C2_USE_GPT_TIM4) || \ - !defined(STM32_I2C_I2C2_USE_GPT_TIM5) || \ - !defined(STM32_I2C_I2C2_USE_GPT_TIM8) || \ - !defined(STM32_I2C_I2C2_USE_VIRTUAL_TIMER) || \ - !defined(STM32_I2C_I2C2_USE_POLLING_WAIT) || \ +/** + * @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. @@ -127,6 +107,7 @@ #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. */ /*===========================================================================*/ @@ -237,7 +218,7 @@ struct I2CDriver{ /** * @brief Config for workaround timer. */ - const GPTConfig *timer_cfg; + const GPTConfig *timer_cfg; } ; From b913fe956cc2d46a8bd7aad24a2ac4d792923422 Mon Sep 17 00:00:00 2001 From: barthess Date: Wed, 20 Jul 2011 08:35:30 +0000 Subject: [PATCH 83/92] I2C. Small fixes in tests. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3168 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- testhal/STM32/I2C/halconf.h | 2 +- testhal/STM32/I2C/mcuconf.h | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/testhal/STM32/I2C/halconf.h b/testhal/STM32/I2C/halconf.h index 65d88f586..f64120126 100644 --- a/testhal/STM32/I2C/halconf.h +++ b/testhal/STM32/I2C/halconf.h @@ -58,7 +58,7 @@ * @brief Enables the GPT subsystem. */ #if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) -#define HAL_USE_GPT FALSE +#define HAL_USE_GPT TRUE #endif /** diff --git a/testhal/STM32/I2C/mcuconf.h b/testhal/STM32/I2C/mcuconf.h index 465de58b8..005c8f83c 100644 --- a/testhal/STM32/I2C/mcuconf.h +++ b/testhal/STM32/I2C/mcuconf.h @@ -61,11 +61,12 @@ /* * GPT driver system settings. */ -#define STM32_GPT_USE_TIM1 FALSE -#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM1 TRUE +#define STM32_GPT_USE_TIM2 TRUE #define STM32_GPT_USE_TIM3 FALSE #define STM32_GPT_USE_TIM4 FALSE #define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM8 FALSE #define STM32_GPT_TIM1_IRQ_PRIORITY 7 #define STM32_GPT_TIM2_IRQ_PRIORITY 7 #define STM32_GPT_TIM3_IRQ_PRIORITY 7 @@ -80,6 +81,7 @@ #define STM32_ICU_USE_TIM3 FALSE #define STM32_ICU_USE_TIM4 TRUE #define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE #define STM32_ICU_TIM1_IRQ_PRIORITY 7 #define STM32_ICU_TIM2_IRQ_PRIORITY 7 #define STM32_ICU_TIM3_IRQ_PRIORITY 7 @@ -95,6 +97,7 @@ #define STM32_PWM_USE_TIM3 TRUE #define STM32_PWM_USE_TIM4 TRUE #define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE #define STM32_PWM_TIM1_IRQ_PRIORITY 2 #define STM32_PWM_TIM2_IRQ_PRIORITY 2 #define STM32_PWM_TIM3_IRQ_PRIORITY 2 @@ -154,6 +157,12 @@ #define STM32_I2C_I2C2_DMA_PRIORITY 4 #define STM32_I2C_I2C1_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 FALSE +/* I2C2 */ +#define STM32_I2C_I2C2_USE_GPT_TIM GPTD2 +#define STM32_I2C_I2C2_USE_POLLING_WAIT FALSE /* * EXTI system settings. From 28b3dd95f1a5fe8ea51df21bc6eba7cd5f78c071 Mon Sep 17 00:00:00 2001 From: barthess Date: Sun, 31 Jul 2011 21:06:23 +0000 Subject: [PATCH 84/92] I2C. Code cleanups. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3187 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.c | 79 ++++++++++++++++++-------------- os/hal/platforms/STM32/i2c_lld.h | 4 +- testhal/STM32/I2C/mcuconf.h | 10 ---- 3 files changed, 46 insertions(+), 47 deletions(-) diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 20db34fff..033077f2c 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -26,8 +26,10 @@ /*===========================================================================*/ /* Driver constants. */ /*===========================================================================*/ -#define I2C_STOP_GPT_TIMEOUT 50 /* waiting timer value */ -#define I2C_START_GPT_TIMEOUT 50 /* waiting timer value */ +/* TODO: may be? move this defines in i2c_lld.h and mcuconf.h */ +#define I2C_STOP_GPT_TIMEOUT 50 /* waiting timer value */ +#define I2C_START_GPT_TIMEOUT 50 /* waiting timer value */ +#define I2C_POLLING_TIMEOUT 0xFFFF /* timeout for syncronouse driver */ /*===========================================================================*/ /* Driver exported variables. */ @@ -705,17 +707,20 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes) { /* "waiting" for STOP bit routine*/ - chDbgAssert(!(i2cp->flags & I2C_FLG_TIMER_ARMED), - "i2c_lld_master_transmit(), #1", "time to STOP is out"); - if ((i2cp->id_i2c->CR1 & I2C_CR1_STOP) && i2cp->timer != NULL && i2cp->timer_cfg != NULL){ - gptStartOneShot(i2cp->timer, I2C_STOP_GPT_TIMEOUT); - i2cp->flags |= I2C_FLG_TIMER_ARMED; - return; - } - else{ - while(i2cp->id_i2c->CR1 & I2C_CR1_STOP) - ; - } + #if STM32_I2C_I2C1_USE_POLLING_WAIT + uint32_t timeout = I2C_POLLING_TIMEOUT; + /* TODO: timeout and Assert here */ + while((i2cp->id_i2c->CR1 & I2C_CR1_STOP) && timeout) + timeout--; + chDbgAssert((timeout > 0), "i2c_lld_master_transmit(), #1", "time to STOP is out"); + #else + chDbgAssert(!(i2cp->flags & I2C_FLG_TIMER_ARMED), "i2c_lld_master_transmit(), #1", "time to STOP is out"); + if ((i2cp->id_i2c->CR1 & I2C_CR1_STOP) && i2cp->timer != NULL && i2cp->timer_cfg != NULL){ + gptStartOneShot(i2cp->timer, I2C_STOP_GPT_TIMEOUT); + i2cp->flags |= I2C_FLG_TIMER_ARMED; + return; + } + #endif /* STM32_I2C_I2C1_USE_POLLING_WAIT */ /* init driver fields */ i2cp->slave_addr = slave_addr; @@ -762,17 +767,19 @@ void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, "some interrupt sources not clear"); /* "waiting" for STOP bit routine*/ - chDbgAssert(!(i2cp->flags & I2C_FLG_TIMER_ARMED), - "i2c_lld_master_receive(), #1", "time to STOP is out"); - if ((i2cp->id_i2c->CR1 & I2C_CR1_STOP) && i2cp->timer != NULL && i2cp->timer_cfg != NULL){ - gptStartOneShot(i2cp->timer, I2C_STOP_GPT_TIMEOUT); - i2cp->flags |= I2C_FLG_TIMER_ARMED; - return; - } - else{ - while(i2cp->id_i2c->CR1 & I2C_CR1_STOP) - ; - } + #if STM32_I2C_I2C1_USE_POLLING_WAIT + uint32_t timeout = I2C_POLLING_TIMEOUT; + while((i2cp->id_i2c->CR1 & I2C_CR1_STOP) && timeout) + timeout--; + chDbgAssert((timeout > 0), "i2c_lld_master_receive(), #1", "time to STOP is out"); + #else + chDbgAssert(!(i2cp->flags & I2C_FLG_TIMER_ARMED), "i2c_lld_master_receive(), #1", "time to STOP is out"); + if ((i2cp->id_i2c->CR1 & I2C_CR1_STOP) && i2cp->timer != NULL && i2cp->timer_cfg != NULL){ + gptStartOneShot(i2cp->timer, I2C_STOP_GPT_TIMEOUT); + i2cp->flags |= I2C_FLG_TIMER_ARMED; + return; + } + #endif /* STM32_I2C_I2C1_USE_POLLING_WAIT */ /* init driver fields */ i2cp->slave_addr = slave_addr; @@ -826,17 +833,19 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ i2cp->id_state = I2C_ACTIVE_TRANSCEIVE; /* "waiting" for START bit routine*/ - chDbgAssert(!(i2cp->flags & I2C_FLG_TIMER_ARMED), - "i2c_lld_master_transceive(), #1", "time to START is out"); - if ((i2cp->id_i2c->CR1 & I2C_CR1_START) && i2cp->timer != NULL && i2cp->timer_cfg != NULL){ - gptStartOneShot(i2cp->timer, I2C_START_GPT_TIMEOUT); - i2cp->flags |= I2C_FLG_TIMER_ARMED; - return; - } - else{ - while(i2cp->id_i2c->CR1 & I2C_CR1_START) - ; - } + #if STM32_I2C_I2C1_USE_POLLING_WAIT + uint32_t timeout = I2C_POLLING_TIMEOUT; + while((i2cp->id_i2c->CR1 & I2C_CR1_START) && timeout); + timeout--; + chDbgAssert((timeout > 0), "i2c_lld_master_transceive(), #1", "time to START is out"); + #else + chDbgAssert(!(i2cp->flags & I2C_FLG_TIMER_ARMED), "i2c_lld_master_transceive(), #1", "time to START is out"); + if ((i2cp->id_i2c->CR1 & I2C_CR1_START) && i2cp->timer != NULL && i2cp->timer_cfg != NULL){ + gptStartOneShot(i2cp->timer, I2C_START_GPT_TIMEOUT); + i2cp->flags |= I2C_FLG_TIMER_ARMED; + return; + } + #endif /* STM32_I2C_I2C1_USE_POLLING_WAIT */ /* init address fields */ if(i2cp->slave_addr & 0x8000){ /* 10-bit mode used */ diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 44ecdf70e..6de73f6b0 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -113,7 +113,7 @@ /*===========================================================================*/ /** - * @brief Serial Driver condition flags type. + * @brief I2C Driver condition flags type. */ typedef uint32_t i2cflags_t; @@ -211,7 +211,7 @@ struct I2CDriver{ /** * @brief Timer for waiting STOP condition on the bus. - * @details Workaround for STM32 buggy I2C cell. + * @details This is workaround for STM32 buggy I2C cell. */ GPTDriver *timer; diff --git a/testhal/STM32/I2C/mcuconf.h b/testhal/STM32/I2C/mcuconf.h index 005c8f83c..105c168f4 100644 --- a/testhal/STM32/I2C/mcuconf.h +++ b/testhal/STM32/I2C/mcuconf.h @@ -164,16 +164,6 @@ #define STM32_I2C_I2C2_USE_GPT_TIM GPTD2 #define STM32_I2C_I2C2_USE_POLLING_WAIT FALSE -/* - * EXTI system settings. - */ -#define STM32_EXTI0_PRIORITY 5 -#define STM32_EXTI1_PRIORITY 5 -#define STM32_EXTI2_PRIORITY 5 -#define STM32_EXTI3_PRIORITY 5 -#define STM32_EXTI4_PRIORITY 5 -#define STM32_EXTI9_5_PRIORITY 5 -#define STM32_EXTI15_10_PRIORITY 5 /* * USB driver system settings. From 4bcff1c283004b10e7a39e855da996621f9eec6d Mon Sep 17 00:00:00 2001 From: barthess Date: Fri, 5 Aug 2011 10:42:42 +0000 Subject: [PATCH 85/92] I2C. Added optional fields hook to I2CSlaveConfig structure. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3189 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 73f633353..1ff50f471 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -145,6 +145,9 @@ struct I2CSlaveConfig{ * 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 }; From 6ee04cf23282fff92b088ac6f408e5233eb3aa75 Mon Sep 17 00:00:00 2001 From: barthess Date: Fri, 5 Aug 2011 17:24:23 +0000 Subject: [PATCH 86/92] I2C. Added template of synchronouse deriver. It does not work for a moment. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3190 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/i2c.h | 1 + os/hal/platforms/STM32/i2c_lld.c | 242 ++++++++++++++++++++++++++++--- os/hal/platforms/STM32/i2c_lld.h | 19 ++- os/hal/src/i2c.c | 8 + testhal/STM32/I2C/chconf.h | 2 +- testhal/STM32/I2C/halconf.h | 9 +- testhal/STM32/I2C/i2c_pns.c | 8 +- testhal/STM32/I2C/lis3.c | 91 +++--------- testhal/STM32/I2C/main.c | 4 +- testhal/STM32/I2C/max1236.c | 31 ++-- testhal/STM32/I2C/mcuconf.h | 4 +- testhal/STM32/I2C/tmp75.c | 8 +- 12 files changed, 291 insertions(+), 136 deletions(-) diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h index 1ff50f471..acf09ec9c 100644 --- a/os/hal/include/i2c.h +++ b/os/hal/include/i2c.h @@ -270,6 +270,7 @@ extern "C" { void i2cAcquireBus(I2CDriver *i2cp); void i2cReleaseBus(I2CDriver *i2cp); #endif /* I2C_USE_MUTUAL_EXCLUSION */ + #ifdef __cplusplus } #endif diff --git a/os/hal/platforms/STM32/i2c_lld.c b/os/hal/platforms/STM32/i2c_lld.c index 033077f2c..a93e2f0a1 100644 --- a/os/hal/platforms/STM32/i2c_lld.c +++ b/os/hal/platforms/STM32/i2c_lld.c @@ -29,7 +29,7 @@ /* TODO: may be? move this defines in i2c_lld.h and mcuconf.h */ #define I2C_STOP_GPT_TIMEOUT 50 /* waiting timer value */ #define I2C_START_GPT_TIMEOUT 50 /* waiting timer value */ -#define I2C_POLLING_TIMEOUT 0xFFFF /* timeout for syncronouse driver */ +#define I2C_POLLING_TIMEOUT 0xFFFF /*===========================================================================*/ /* Driver exported variables. */ @@ -58,15 +58,16 @@ static volatile uint16_t dbgCR2 = 0; #endif /* CH_DBG_ENABLE_ASSERTS */ /* defines for convenience purpose */ +#if I2C_SUPPORTS_CALLBACKS #define txBuffp (i2cp->txbuff_p) #define rxBuffp (i2cp->rxbuff_p) +#endif /* I2C_SUPPORTS_CALLBACKS */ /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ - -#if STM32_I2C_I2C1_USE_POLLING_WAIT -#else +#if I2C_SUPPORTS_CALLBACKS +#if !(STM32_I2C_I2C1_USE_POLLING_WAIT) /* I2C1 GPT callback. */ static void i2c1gptcb(GPTDriver *gptp) { (void)gptp; @@ -100,8 +101,7 @@ static const GPTConfig i2c1gptcfg = { }; #endif /* STM32_I2C_I2C1_USE_POLLING_WAIT */ -#if STM32_I2C_I2C2_USE_POLLING_WAIT -#else +#if !(STM32_I2C_I2C2_USE_POLLING_WAIT) /* I2C2 GPT callback. */ static void i2c2gptcb(GPTDriver *gptp) { (void)gptp; @@ -134,6 +134,7 @@ static const GPTConfig i2c2gptcfg = { i2c2gptcb /* Timer callback.*/ }; #endif /* STM32_I2C_I2C2_USE_POLLING_WAIT */ +#endif /* I2C_SUPPORTS_CALLBACKS */ /** * @brief Function for I2C debugging purpose. @@ -155,6 +156,7 @@ void _i2c_unhandled_case(I2CDriver *i2cp){ #define _i2c_unhandled_case(i2cp) #endif /* CH_DBG_ENABLE_ASSERTS */ +#if I2C_SUPPORTS_CALLBACKS /** * @brief Return the last event value from I2C status registers. * @note Internal use only. @@ -372,7 +374,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) { break; } } - +#endif /* I2C_SUPPORTS_CALLBACKS */ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { i2cflags_t flags; @@ -417,7 +419,9 @@ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { chSysLockFromIsr(); i2cAddFlagsI(i2cp, flags); chSysUnlockFromIsr(); + #if I2C_SUPPORTS_CALLBACKS _i2c_isr_err_code(i2cp, i2cp->id_slave_config); + #endif /* I2C_SUPPORTS_CALLBACKS */ } } @@ -426,13 +430,14 @@ static void i2c_serve_error_interrupt(I2CDriver *i2cp) { /** * @brief I2C1 event interrupt handler. */ +#if I2C_SUPPORTS_CALLBACKS CH_IRQ_HANDLER(VectorBC) { CH_IRQ_PROLOGUE(); i2c_serve_event_interrupt(&I2CD1); CH_IRQ_EPILOGUE(); } - +#endif /* I2C_SUPPORTS_CALLBACKS */ /** * @brief I2C1 error interrupt handler. */ @@ -442,19 +447,20 @@ CH_IRQ_HANDLER(VectorC0) { i2c_serve_error_interrupt(&I2CD1); CH_IRQ_EPILOGUE(); } -#endif +#endif /* STM32_I2C_USE_I2C1 */ #if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) /** * @brief I2C2 event interrupt handler. */ +#if I2C_SUPPORTS_CALLBACKS CH_IRQ_HANDLER(VectorC4) { CH_IRQ_PROLOGUE(); i2c_serve_event_interrupt(&I2CD2); CH_IRQ_EPILOGUE(); } - +#endif /* I2C_SUPPORTS_CALLBACKS */ /** * @brief I2C2 error interrupt handler. */ @@ -464,7 +470,7 @@ CH_IRQ_HANDLER(VectorC8) { i2c_serve_error_interrupt(&I2CD2); CH_IRQ_EPILOGUE(); } -#endif +#endif /* STM32_I2C_USE_I2C2 */ /** * @brief Low level I2C driver initialization. @@ -477,13 +483,12 @@ void i2c_lld_init(void) { i2cObjectInit(&I2CD1); I2CD1.id_i2c = I2C1; -#if STM32_I2C_I2C1_USE_POLLING_WAIT - I2CD1.timer = NULL; - I2CD1.timer_cfg = NULL; -#else +#if I2C_SUPPORTS_CALLBACKS +#if !(STM32_I2C_I2C1_USE_POLLING_WAIT) I2CD1.timer = &(STM32_I2C_I2C1_USE_GPT_TIM); I2CD1.timer_cfg = &i2c1gptcfg; #endif /* !(STM32_I2C_I2C1_USE_POLLING_WAIT) */ +#endif /* I2C_SUPPORTS_CALLBACKS */ #endif /* STM32_I2C_USE_I2C */ @@ -493,13 +498,12 @@ void i2c_lld_init(void) { i2cObjectInit(&I2CD2); I2CD2.id_i2c = I2C2; -#if STM32_I2C_I2C2_USE_POLLING_WAIT - I2CD2.timer = NULL; - I2CD2.timer_cfg = NULL; -#else +#if I2C_SUPPORTS_CALLBACKS +#if !(STM32_I2C_I2C2_USE_POLLING_WAIT) I2CD2.timer = &(STM32_I2C_I2C2_USE_GPT_TIM); I2CD2.timer_cfg = &i2c2gptcfg; #endif /* !(STM32_I2C_I2C2_USE_POLLING_WAIT) */ +#endif /* I2C_SUPPORTS_CALLBACKS */ #endif /* STM32_I2C_USE_I2C2 */ } @@ -510,14 +514,17 @@ void i2c_lld_init(void) { * @param[in] i2cp pointer to the @p I2CDriver object */ void i2c_lld_start(I2CDriver *i2cp) { - if (i2cp->timer != NULL || i2cp->timer_cfg != NULL) +#if (!(STM32_I2C_I2C2_USE_POLLING_WAIT) && I2C_SUPPORTS_CALLBACKS) gptStart(i2cp->timer, i2cp->timer_cfg); +#endif /* !(STM32_I2C_I2C2_USE_POLLING_WAIT) */ if (i2cp->id_state == I2C_STOP) { /* If in stopped state then enables the I2C clock.*/ #if STM32_I2C_USE_I2C1 if (&I2CD1 == i2cp) { +#if I2C_SUPPORTS_CALLBACKS NVICEnableVector(I2C1_EV_IRQn, CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); +#endif /* I2C_SUPPORTS_CALLBACKS */ NVICEnableVector(I2C1_ER_IRQn, CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; /* I2C 1 clock enable */ @@ -525,8 +532,10 @@ void i2c_lld_start(I2CDriver *i2cp) { #endif #if STM32_I2C_USE_I2C2 if (&I2CD2 == i2cp) { +#if I2C_SUPPORTS_CALLBACKS NVICEnableVector(I2C2_EV_IRQn, CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); +#endif /* I2C_SUPPORTS_CALLBACKS */ NVICEnableVector(I2C2_ER_IRQn, CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); RCC->APB1ENR |= RCC_APB1ENR_I2C2EN; /* I2C 2 clock enable */ @@ -690,6 +699,8 @@ void i2c_lld_stop(I2CDriver *i2cp) { i2cp->id_state = I2C_STOP; } + +#if I2C_SUPPORTS_CALLBACKS /** * @brief Transmits data via the I2C bus as master. * @@ -709,7 +720,6 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, /* "waiting" for STOP bit routine*/ #if STM32_I2C_I2C1_USE_POLLING_WAIT uint32_t timeout = I2C_POLLING_TIMEOUT; - /* TODO: timeout and Assert here */ while((i2cp->id_i2c->CR1 & I2C_CR1_STOP) && timeout) timeout--; chDbgAssert((timeout > 0), "i2c_lld_master_transmit(), #1", "time to STOP is out"); @@ -747,7 +757,6 @@ void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); /* enable ERR, EVT & BUF ITs */ } - /** * @brief Receives data from the I2C bus. * @@ -874,6 +883,195 @@ void i2c_lld_master_transceive(I2CDriver *i2cp){ i2cp->id_i2c->CR2 |= (I2C_CR2_ITERREN|I2C_CR2_ITEVTEN|I2C_CR2_ITBUFEN); /* enable ERR, EVT & BUF ITs */ } +#else /*I2C_SUPPORTS_CALLBACKS*/ + +/** + * @brief Synchronously transmits data via the I2C bus as master. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @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 modes used. Otherwise keep it cleared. + * Bits 10-14 unused. + * @param[in] txbuf pointer to the transmit buffer + * @param[in] txbytes number of bytes to be transmitted + * @param[in] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + */ +void i2c_lld_master_transmit(I2CDriver *i2cp, uint16_t slave_addr, + uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes) { + + /* init driver fields */ + i2cp->slave_addr = slave_addr; + i2cp->txbytes = txbytes; + i2cp->rxbytes = rxbytes; + i2cp->txbuf = txbuf; + i2cp->rxbuf = rxbuf; + + /* init address fields */ + if(slave_addr & 0x8000){ /* 10-bit mode used */ + i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); /* add the two msb of 10-bit address to the header */ + i2cp->slave_addr1 |= 0xF0; /* add the header bits with LSB = 0 -> write */ + i2cp->slave_addr2 = slave_addr & 0x00FF; /* the remaining 8 bit of 10-bit address */ + } + else{ + i2cp->slave_addr1 = ((slave_addr <<1) & 0x00FE); /* LSB = 0 -> write */ + } + + i2cp->flags = 0; + i2cp->errors = 0; + i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; + i2cp->id_i2c->CR2 &= ~I2C_CR2_ITEVTEN; /* disable event interrupts */ + i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN; /* enable error interrupts */ + + i2cp->id_i2c->CR1 |= I2C_CR1_START; + while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)) + ; + i2cp->id_i2c->DR = i2cp->slave_addr1; + while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)) + ; + while (!(i2cp->id_i2c->SR2 & I2C_SR2_BUSY)) + ; + i2cp->id_i2c->DR = *txbuf; + txbuf++; + i2cp->txbytes--; + while(i2cp->txbytes > 0){ + while(!(i2cp->id_i2c->SR1 & I2C_SR1_BTF)) + ; + i2cp->id_i2c->DR = *txbuf; + txbuf++; + i2cp->txbytes--; + } + while(!(i2cp->id_i2c->SR1 & I2C_SR1_BTF)) + ; + if(rxbytes == 0){ + i2cp->id_i2c->CR1 |= I2C_CR1_STOP; + while (i2cp->id_i2c->CR1 & I2C_CR1_STOP) + ; + } + else{ + i2c_lld_master_receive(i2cp, slave_addr, rxbuf, rxbytes); + } +} + + +/** + * @brief Synchronously receives data from the I2C bus. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @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 modes used. Otherwise keep it cleared. + * Bits 10-14 unused. + * @param[in] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + */ +void i2c_lld_master_receive(I2CDriver *i2cp, uint16_t slave_addr, + uint8_t *rxbuf, size_t rxbytes){ + + /* init driver fields */ + i2cp->slave_addr = slave_addr; + i2cp->rxbytes = rxbytes; + i2cp->rxbuf = rxbuf; + + /* init address fields */ + if(slave_addr & 0x8000){ /* 10-bit mode used */ + i2cp->slave_addr1 = ((slave_addr >>7) & 0x0006); /* add the two msb of 10-bit address to the header */ + i2cp->slave_addr1 |= 0xF0; /* add the header bits (the LSB -> 1 will be add to second */ + i2cp->slave_addr2 = slave_addr & 0x00FF; /* the remaining 8 bit of 10-bit address */ + } + else{ + i2cp->slave_addr1 = ((slave_addr <<1) | 0x01); /* LSB = 1 -> receive */ + } + + + /* setting flags and register bits */ + i2cp->flags = 0; + i2cp->errors = 0; + i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; + i2cp->id_i2c->CR2 &= ~I2C_CR2_ITEVTEN; /* disable event interrupts */ + i2cp->id_i2c->CR2 |= I2C_CR2_ITERREN; /* enable error interrupts */ + + i2cp->id_i2c->CR1 |= I2C_CR1_START; + while (!(i2cp->id_i2c->SR1 & I2C_SR1_SB)) + ; + + i2cp->id_i2c->DR = i2cp->slave_addr1; + while (!(i2cp->id_i2c->SR1 & I2C_SR1_ADDR)) + ; + + if(i2cp->rxbytes >= 3){ /* more than 2 bytes receiving procedure */ + while(!(i2cp->id_i2c->SR2 & I2C_SR2_BUSY)) /* to clear ADDR bit */ + ; + while(i2cp->rxbytes > 3){ + while(!(i2cp->id_i2c->SR1 & I2C_SR1_BTF)) + ; + *rxbuf = i2cp->id_i2c->DR; + rxbuf++; + i2cp->rxbytes--; + } + while(!(i2cp->id_i2c->SR1 & I2C_SR1_BTF)) /* stopping procedure */ + ; + i2cp->id_i2c->CR1 &= ~I2C_CR1_ACK; + chSysLock(); + i2cp->id_i2c->CR1 |= I2C_CR1_STOP; + *rxbuf = i2cp->id_i2c->DR; + rxbuf++; + i2cp->rxbytes--; + chSysUnlock(); + while(!(i2cp->id_i2c->SR1 & I2C_SR1_RXNE)) + ; + *rxbuf = i2cp->id_i2c->DR; + rxbuf++; + i2cp->rxbytes--; + while (i2cp->id_i2c->CR1 & I2C_CR1_STOP) + ; + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; + } + else{ /* 1 or 2 bytes receiving procedure */ + if(i2cp->rxbytes == 2){ + i2cp->id_i2c->CR1 |= I2C_CR1_POS; + chSysLock(); + while(!(i2cp->id_i2c->SR2 & I2C_SR2_BUSY)) /* to clear ADDR bit */ + ; + i2cp->id_i2c->CR1 &= ~I2C_CR1_ACK; + chSysUnlock(); + while(!(i2cp->id_i2c->SR1 & I2C_SR1_BTF)) + ; + chSysLock(); + i2cp->id_i2c->CR1 |= I2C_CR1_STOP; + *rxbuf = i2cp->id_i2c->DR; + rxbuf++; + i2cp->rxbytes--; + chSysUnlock(); + *rxbuf = i2cp->id_i2c->DR; + rxbuf++; + i2cp->rxbytes--; + while (i2cp->id_i2c->CR1 & I2C_CR1_STOP) + ; + i2cp->id_i2c->CR1 &= ~I2C_CR1_POS; + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; + } + else{ /* 1 byte */ + i2cp->id_i2c->CR1 &= ~I2C_CR1_ACK; + chSysLock(); + while(!(i2cp->id_i2c->SR2 & I2C_SR2_BUSY)) /* to clear ADDR bit */ + ; + i2cp->id_i2c->CR1 |= I2C_CR1_STOP; + chSysUnlock(); + while(!(i2cp->id_i2c->SR1 & I2C_SR1_RXNE)) + ; + *rxbuf = i2cp->id_i2c->DR; + rxbuf++; + i2cp->rxbytes--; + while (i2cp->id_i2c->CR1 & I2C_CR1_STOP) + ; + i2cp->id_i2c->CR1 |= I2C_CR1_ACK; + } + } +} +#endif /* I2C_SUPPORTS_CALLBACKS */ + #undef rxBuffp #undef txBuffp diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 6de73f6b0..69d1753bb 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -13,11 +13,17 @@ /*===========================================================================*/ /* Driver constants. */ /*===========================================================================*/ -#define I2C_START_TIMEOUT 0xFFFF /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ +/** + * @brief Switch between callback based and synchronouse driver. + * @note The default is synchronouse. + */ +#if !defined(I2C_SUPPORTS_CALLBACKS) || defined(__DOXYGEN__) +#define I2C_SUPPORTS_CALLBACKS FALSE +#endif /** * @brief I2C1 driver synchronization choice between GPT and polling. @@ -161,6 +167,7 @@ struct I2CDriver{ * @brief Driver state. */ i2cstate_t id_state; + #if I2C_USE_WAIT /** * @brief Thread waiting for I/O completion. @@ -177,6 +184,7 @@ struct I2CDriver{ Semaphore id_semaphore; #endif #endif /* I2C_USE_MUTUAL_EXCLUSION */ + /** * @brief Current configuration data. */ @@ -198,7 +206,7 @@ struct I2CDriver{ 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 Used in 10-bit address mode. */ + uint8_t slave_addr2;/*!< @brief Uses in 10-bit address mode. */ EventSource sevent; /*!< @brief Status Change @p EventSource.*/ @@ -209,6 +217,8 @@ struct I2CDriver{ */ 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. @@ -219,7 +229,8 @@ struct I2CDriver{ * @brief Config for workaround timer. */ const GPTConfig *timer_cfg; -} ; +#endif /* !(STM32_I2C_I2C1_USE_POLLING_WAIT) */ +}; /*===========================================================================*/ @@ -235,7 +246,7 @@ struct I2CDriver{ * does not block thread, only if slave not response it does. */ #define i2c_lld_wait_bus_free(i2cp) { \ - uint32_t tmo = 0xffff; \ + uint32_t tmo = 0xfffff; \ while((i2cp->id_i2c->SR2 & I2C_SR2_BUSY) && tmo--) \ ; \ } diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index b233764f5..9676a3250 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -178,7 +178,11 @@ void i2cMasterTransmit(I2CDriver *i2cp, i2cp->id_state = I2C_ACTIVE_TRANSMIT; i2c_lld_master_transmit(i2cp, slave_addr, txbuf, txbytes, rxbuf, rxbytes); +#if I2C_SUPPORTS_CALLBACKS _i2c_wait_s(i2cp); +#else + i2cp->id_state = I2C_READY; +#endif /* I2C_SUPPORTS_CALLBACKS */ } /** @@ -216,7 +220,11 @@ void i2cMasterReceive(I2CDriver *i2cp, i2cp->id_state = I2C_ACTIVE_RECEIVE; i2c_lld_master_receive(i2cp, slave_addr, rxbuf, rxbytes); +#if I2C_SUPPORTS_CALLBACKS _i2c_wait_s(i2cp); +#else + i2cp->id_state = I2C_READY; +#endif /* I2C_SUPPORTS_CALLBACKS */ } diff --git a/testhal/STM32/I2C/chconf.h b/testhal/STM32/I2C/chconf.h index 9f5273ba5..a293288d3 100644 --- a/testhal/STM32/I2C/chconf.h +++ b/testhal/STM32/I2C/chconf.h @@ -188,7 +188,7 @@ * @note The default is @p TRUE. */ #if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__) -#define CH_USE_MUTEXES FALSE +#define CH_USE_MUTEXES TRUE #endif /** diff --git a/testhal/STM32/I2C/halconf.h b/testhal/STM32/I2C/halconf.h index f64120126..da52785c0 100644 --- a/testhal/STM32/I2C/halconf.h +++ b/testhal/STM32/I2C/halconf.h @@ -178,7 +178,7 @@ * @note Disabling this option saves both code and data space. */ #if !defined(I2C_USE_WAIT) || defined(__DOXYGEN__) -#define I2C_USE_WAIT TRUE +#define I2C_USE_WAIT FALSE #endif /** @@ -188,6 +188,13 @@ #define I2C_USE_MUTUAL_EXCLUSION TRUE #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. */ /*===========================================================================*/ diff --git a/testhal/STM32/I2C/i2c_pns.c b/testhal/STM32/I2C/i2c_pns.c index 63f7d99bd..44f4a8a33 100644 --- a/testhal/STM32/I2C/i2c_pns.c +++ b/testhal/STM32/I2C/i2c_pns.c @@ -32,7 +32,6 @@ static const I2CConfig i2cfg2 = { void I2CInit_pns(void){ - i2cInit(); i2cStart(&I2CD1, &i2cfg1); @@ -46,13 +45,12 @@ void I2CInit_pns(void){ palSetPadMode(IOPORT2, 10, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); palSetPadMode(IOPORT2, 11, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); - /* startups. Pauses added just to be safe */ + chThdSleepMilliseconds(1000); init_max1236(); - chThdSleepMilliseconds(100); - + chThdSleepMilliseconds(1000); init_lis3(); - chThdSleepMilliseconds(100); + chThdSleepMilliseconds(1000); } diff --git a/testhal/STM32/I2C/lis3.c b/testhal/STM32/I2C/lis3.c index 26a3292f5..401f56199 100644 --- a/testhal/STM32/I2C/lis3.c +++ b/testhal/STM32/I2C/lis3.c @@ -14,10 +14,17 @@ #include "lis3.h" +#define lis3_addr 0b0011101 + + /* buffers */ static i2cblock_t accel_rx_data[ACCEL_RX_DEPTH]; static i2cblock_t accel_tx_data[ACCEL_TX_DEPTH]; +static int16_t acceleration_x = 0; +static int16_t acceleration_y = 0; +static int16_t acceleration_z = 0; + /* Error trap */ static void i2c_lis3_error_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ (void)i2cscfg; @@ -26,50 +33,10 @@ static void i2c_lis3_error_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ while(TRUE); } -/** - * This treading need for convenient realize - * "read through write" process. - */ -static WORKING_AREA(I2CAccelThreadWA, 128); -static Thread *i2c_accel_tp = NULL; -static msg_t I2CAccelThread(void *arg) { - (void)arg; - - int16_t acceleration_x = 0; - int16_t acceleration_y = 0; - int16_t acceleration_z = 0; - - I2CSlaveConfig *i2cscfg; - msg_t msg; - - while (TRUE) { - /* Waiting for wake up */ - chSysLock(); - i2c_accel_tp = chThdSelf(); - chSchGoSleepS(THD_STATE_SUSPENDED); - msg = chThdSelf()->p_msg; /* Retrieving the message, optional.*/ - chSysUnlock(); - - /***************** Perform processing here. ***************************/ - i2cscfg = (I2CSlaveConfig *)msg; - - /* collect measured data */ - acceleration_x = accel_rx_data[0] + (accel_rx_data[1] << 8); - acceleration_y = accel_rx_data[2] + (accel_rx_data[3] << 8); - acceleration_z = accel_rx_data[4] + (accel_rx_data[5] << 8); - } - return 0; -} - /* This callback raise up when transfer finished */ static void i2c_lis3_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ - (void) i2cp; - /* only wake up processing thread */ - if (i2c_accel_tp != NULL) { - i2c_accel_tp->p_msg = (msg_t)i2cscfg; - chSchReadyI(i2c_accel_tp); - i2c_accel_tp = NULL; - } + (void)i2cp; + (void)i2cscfg; } @@ -80,29 +47,10 @@ static const I2CSlaveConfig lis3 = { }; -#define lis3_addr 0b0011101 - - - /** * Init function. Here we will also start personal serving thread. */ int init_lis3(void){ - - /* Starting the accelerometer serving thread.*/ - i2c_accel_tp = chThdCreateStatic(I2CAccelThreadWA, - sizeof(I2CAccelThreadWA), - HIGHPRIO, - I2CAccelThread, - NULL); - - /* wait thread statup */ - while (i2c_accel_tp == NULL) - chThdSleepMilliseconds(1); - -#define TXBYTES 4 -#define RXBYTES 0 /* set to 0 because we need only transmit */ - /* configure accelerometer */ accel_tx_data[0] = ACCEL_CTRL_REG1 | AUTO_INCREMENT_BIT; /* register address */ accel_tx_data[1] = 0b11100111; @@ -110,12 +58,7 @@ int init_lis3(void){ accel_tx_data[3] = 0b00000000; /* sending */ - i2cMasterTransmit(&I2CD1, &lis3, lis3_addr, accel_tx_data, TXBYTES, accel_rx_data, RXBYTES); - chThdSleepMilliseconds(1); - -#undef RXBYTES -#undef TXBYTES - + i2cMasterTransmit(&I2CD1, &lis3, lis3_addr, accel_tx_data, 4, accel_rx_data, 0); return 0; } @@ -123,13 +66,13 @@ int init_lis3(void){ * */ void request_acceleration_data(void){ -#define RXBYTES 6 -#define TXBYTES 1 accel_tx_data[0] = ACCEL_OUT_DATA | AUTO_INCREMENT_BIT; // register address - i2cAcquireBus(&I2CD1); - i2cMasterTransmit(&I2CD1, &lis3, lis3_addr, accel_tx_data, TXBYTES, accel_rx_data, RXBYTES); - i2cReleaseBus(&I2CD1); -#undef RXBYTES -#undef TXBYTES + //i2cAcquireBus(&I2CD1); + i2cMasterTransmit(&I2CD1, &lis3, lis3_addr, accel_tx_data, 1, accel_rx_data, 6); + //i2cReleaseBus(&I2CD1); + + acceleration_x = accel_rx_data[0] + (accel_rx_data[1] << 8); + acceleration_y = accel_rx_data[2] + (accel_rx_data[3] << 8); + acceleration_z = accel_rx_data[4] + (accel_rx_data[5] << 8); } diff --git a/testhal/STM32/I2C/main.c b/testhal/STM32/I2C/main.c index ce8cb5522..b828953c5 100644 --- a/testhal/STM32/I2C/main.c +++ b/testhal/STM32/I2C/main.c @@ -68,7 +68,7 @@ static msg_t PollMax1236Thread(void *arg) { systime_t time = chTimeNow(); while (TRUE) { - time += MS2ST(20); + time += MS2ST(200); /* Call reading function */ read_max1236(); chThdSleepUntil(time); @@ -83,7 +83,7 @@ static msg_t PollAccelThread(void *arg) { systime_t time = chTimeNow(); while (TRUE) { - time += MS2ST(2); + time += MS2ST(20); request_acceleration_data(); chThdSleepUntil(time); } diff --git a/testhal/STM32/I2C/max1236.c b/testhal/STM32/I2C/max1236.c index 3e3dbd0c1..09e2c8b35 100644 --- a/testhal/STM32/I2C/max1236.c +++ b/testhal/STM32/I2C/max1236.c @@ -10,6 +10,10 @@ #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]; @@ -31,10 +35,6 @@ static void i2c_max1236_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ (void)*i2cp; (void)*i2cscfg; /* get ADC data */ - 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]; } @@ -45,7 +45,6 @@ static const I2CSlaveConfig max1236 = { i2c_max1236_error_cb, }; -#define max1236_addr 0b0110100 /** * Initilization routine. See datasheet on page 13 to understand @@ -53,32 +52,24 @@ static const I2CSlaveConfig max1236 = { */ void init_max1236(void){ /* this data we must send via IC to setup ADC */ -#define RXBYTES 0 -#define TXBYTES 2 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, TXBYTES, max1236_rx_data, RXBYTES); - while(I2CD2.id_state != I2C_READY){ - chThdSleepMilliseconds(1); - } + i2cMasterTransmit(&I2CD2, &max1236, max1236_addr, max1236_tx_data, 2, max1236_rx_data, 0); i2cReleaseBus(&I2CD2); -#undef RXBYTES -#undef TXBYTES } /* Now simply read 8 bytes to get all 4 ADC channels */ void read_max1236(void){ -#define TXBYTES 0 -#define RXBYTES 8 - i2cAcquireBus(&I2CD2); - i2cMasterReceive(&I2CD2, &max1236, max1236_addr, max1236_rx_data, RXBYTES); + i2cMasterReceive(&I2CD2, &max1236, max1236_addr, max1236_rx_data, 8); i2cReleaseBus(&I2CD2); -#undef RXBYTES -#undef TXBYTES + + 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]; } diff --git a/testhal/STM32/I2C/mcuconf.h b/testhal/STM32/I2C/mcuconf.h index 105c168f4..809c3abd2 100644 --- a/testhal/STM32/I2C/mcuconf.h +++ b/testhal/STM32/I2C/mcuconf.h @@ -159,10 +159,10 @@ #define STM32_I2C_I2C2_DMA_ERROR_HOOK() chSysHalt() /* I2C1 */ #define STM32_I2C_I2C1_USE_GPT_TIM GPTD1 -#define STM32_I2C_I2C1_USE_POLLING_WAIT FALSE +#define STM32_I2C_I2C1_USE_POLLING_WAIT TRUE /* I2C2 */ #define STM32_I2C_I2C2_USE_GPT_TIM GPTD2 -#define STM32_I2C_I2C2_USE_POLLING_WAIT FALSE +#define STM32_I2C_I2C2_USE_POLLING_WAIT TRUE /* diff --git a/testhal/STM32/I2C/tmp75.c b/testhal/STM32/I2C/tmp75.c index 6276e7c8e..72e634527 100644 --- a/testhal/STM32/I2C/tmp75.c +++ b/testhal/STM32/I2C/tmp75.c @@ -14,6 +14,7 @@ /* input buffer */ static i2cblock_t tmp75_rx_data[TMP75_RX_DEPTH]; + /* temperature value */ static int16_t temperature = 0; @@ -30,7 +31,6 @@ static void i2c_tmp75_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){ (void)*i2cp; (void)*i2cscfg; /* store temperature value */ - temperature = (tmp75_rx_data[0] << 8) + tmp75_rx_data[1]; } /* Fill TMP75 config. */ @@ -43,12 +43,10 @@ static const I2CSlaveConfig tmp75 = { /* This is main function. */ void request_temperature(void){ -#define TXBYTES 0 /* set to zero because we need only reading */ -#define RXBYTES 2 /* we need to read 2 bytes */ - i2cAcquireBus(&I2CD2); - i2cMasterReceive(&I2CD2, &tmp75, tmp75_addr, tmp75_rx_data, RXBYTES); + i2cMasterReceive(&I2CD2, &tmp75, tmp75_addr, tmp75_rx_data, 2); i2cReleaseBus(&I2CD2); + temperature = (tmp75_rx_data[0] << 8) + tmp75_rx_data[1]; } From 45b489851878769402af4a353fa2b759c815be39 Mon Sep 17 00:00:00 2001 From: barthess Date: Sat, 6 Aug 2011 07:41:02 +0000 Subject: [PATCH 87/92] I2C. Default choise changed to callback based driver. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3191 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32/i2c_lld.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/os/hal/platforms/STM32/i2c_lld.h b/os/hal/platforms/STM32/i2c_lld.h index 69d1753bb..38b9add05 100644 --- a/os/hal/platforms/STM32/i2c_lld.h +++ b/os/hal/platforms/STM32/i2c_lld.h @@ -22,7 +22,7 @@ * @note The default is synchronouse. */ #if !defined(I2C_SUPPORTS_CALLBACKS) || defined(__DOXYGEN__) -#define I2C_SUPPORTS_CALLBACKS FALSE +#define I2C_SUPPORTS_CALLBACKS TRUE #endif /** From 0752e9d7e973161c32e4b667c7a8d06c68b0a9eb Mon Sep 17 00:00:00 2001 From: barthess Date: Tue, 9 Aug 2011 10:07:11 +0000 Subject: [PATCH 88/92] I2C. Syncing with trunk (step 1) git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@3214 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- boards/ST_STM3220G_EVAL/board.c | 58 +++++ boards/ST_STM3220G_EVAL/board.h | 245 ++++++++++++++++++ boards/ST_STM3220G_EVAL/board.mk | 5 + boards/ST_STM32L_DISCOVERY/board.c | 12 +- boards/ST_STM32L_DISCOVERY/board.h | 28 ++ demos/ARM7-AT91SAM7S-FATFS-GCC/Makefile | 16 +- demos/ARM7-AT91SAM7S-FATFS-GCC/ch.ld | 111 -------- demos/ARM7-AT91SAM7S-GCC/Makefile | 16 +- demos/ARM7-AT91SAM7S-GCC/ch.ld | 99 ------- demos/ARM7-AT91SAM7X-FATFS-GCC/Makefile | 16 +- demos/ARM7-AT91SAM7X-FATFS-GCC/ch.ld | 111 -------- demos/ARM7-AT91SAM7X-GCC/Makefile | 16 +- demos/ARM7-AT91SAM7X-GCC/ch.ld | 104 -------- demos/ARM7-AT91SAM7X-LWIP-GCC/Makefile | 14 +- demos/ARM7-AT91SAM7X-LWIP-GCC/ch.ld | 104 -------- demos/ARM7-AT91SAM7X-UIP-GCC/Makefile | 18 +- demos/ARM7-AT91SAM7X-UIP-GCC/ch.ld | 104 -------- demos/ARM7-LPC214x-FATFS-GCC/Makefile | 16 +- demos/ARM7-LPC214x-FATFS-GCC/ch.ld | 107 -------- demos/ARM7-LPC214x-FATFS-GCC/main.c | 4 +- demos/ARM7-LPC214x-G++/Makefile | 16 +- demos/ARM7-LPC214x-G++/ch.ld | 107 -------- demos/ARM7-LPC214x-GCC/Makefile | 16 +- demos/ARM7-LPC214x-GCC/ch.ld | 107 -------- demos/ARMCM0-LPC1114-LPCXPRESSO/Makefile | 8 +- demos/ARMCM0-LPC1114-LPCXPRESSO/ch.ld | 130 ---------- demos/ARMCM3-LPC1343-LPCXPRESSO/Makefile | 8 +- demos/ARMCM3-LPC1343-LPCXPRESSO/ch.ld | 130 ---------- demos/ARMCM3-STM32F100-DISCOVERY/Makefile | 12 +- demos/ARMCM3-STM32F100-DISCOVERY/ch.ld | 130 ---------- demos/ARMCM3-STM32F103-FATFS/Makefile | 12 +- demos/ARMCM3-STM32F103-FATFS/ch.ld | 130 ---------- demos/ARMCM3-STM32F103-G++/Makefile | 12 +- demos/ARMCM3-STM32F103-G++/ch.ld | 130 ---------- demos/ARMCM3-STM32F103/Makefile | 12 +- demos/ARMCM3-STM32F103/ch.ld | 130 ---------- demos/ARMCM3-STM32F103ZG-FATFS/Makefile | 14 +- demos/ARMCM3-STM32F103ZG-FATFS/ch.ld | 130 ---------- demos/ARMCM3-STM32F107/Makefile | 14 +- demos/ARMCM3-STM32F107/ch.ld | 130 ---------- demos/ARMCM3-STM32L152-DISCOVERY/Makefile | 10 +- demos/ARMCM3-STM32L152-DISCOVERY/ch.ld | 130 ---------- demos/ARMCM3-STM32L152-DISCOVERY/halconf.h | 4 +- docs/Doxyfile_chm | 13 +- docs/Doxyfile_html | 13 +- docs/rsc/header_chm.html | 2 +- docs/rsc/header_html.html | 2 +- readme.txt | 42 ++- testhal/LPC11xx/IRQ_STORM/Makefile | 10 +- testhal/LPC11xx/IRQ_STORM/ch.ld | 130 ---------- testhal/LPC13xx/IRQ_STORM/Makefile | 10 +- testhal/LPC13xx/IRQ_STORM/ch.ld | 130 ---------- testhal/STM32/ADC/ch.ld | 130 ---------- testhal/STM32/CAN/ch.ld | 130 ---------- testhal/STM32/GPT/ch.ld | 130 ---------- testhal/STM32/GPT/openocd.bat | 3 - testhal/STM32/GPT/openocd.cfg | 13 - testhal/STM32/I2C/ch.ld | 130 ---------- testhal/STM32/IRQ_STORM/ch.ld | 130 ---------- testhal/STM32/PWM-ICU/Makefile | 204 --------------- testhal/STM32/PWM-ICU/ch.ld | 130 ---------- testhal/STM32/SDIO/ch.ld | 130 ---------- testhal/STM32/SPI/Makefile | 204 --------------- testhal/STM32/SPI/ch.ld | 130 ---------- testhal/STM32/UART/Makefile | 204 --------------- testhal/STM32/UART/ch.ld | 130 ---------- testhal/STM32/USB_CDC/ch.ld | 130 ---------- testhal/STM32/USB_MSC/ch.ld | 130 ---------- testhal/{STM32/CAN => STM32F1xx/ADC}/Makefile | 14 +- testhal/{STM32 => STM32F1xx}/ADC/chconf.h | 0 testhal/{STM32 => STM32F1xx}/ADC/halconf.h | 0 testhal/{STM32 => STM32F1xx}/ADC/main.c | 0 testhal/{STM32 => STM32F1xx}/ADC/mcuconf.h | 0 testhal/{STM32 => STM32F1xx}/ADC/readme.txt | 0 testhal/{STM32/GPT => STM32F1xx/CAN}/Makefile | 14 +- testhal/{STM32 => STM32F1xx}/CAN/chconf.h | 0 testhal/{STM32 => STM32F1xx}/CAN/halconf.h | 0 testhal/{STM32 => STM32F1xx}/CAN/main.c | 0 testhal/{STM32 => STM32F1xx}/CAN/mcuconf.h | 0 testhal/{STM32 => STM32F1xx}/CAN/readme.txt | 0 .../IRQ_STORM => STM32F1xx/GPT}/Makefile | 14 +- testhal/{STM32 => STM32F1xx}/GPT/chconf.h | 0 testhal/{STM32 => STM32F1xx}/GPT/halconf.h | 0 testhal/{STM32 => STM32F1xx}/GPT/main.c | 0 testhal/{STM32 => STM32F1xx}/GPT/mcuconf.h | 0 testhal/{STM32 => STM32F1xx}/GPT/readme.txt | 0 testhal/{STM32 => STM32F1xx}/GPT/run | 0 testhal/{STM32 => STM32F1xx}/I2C/Makefile | 0 testhal/{STM32 => STM32F1xx}/I2C/chconf.h | 0 testhal/{STM32 => STM32F1xx}/I2C/halconf.h | 0 testhal/{STM32 => STM32F1xx}/I2C/i2c_pns.c | 0 testhal/{STM32 => STM32F1xx}/I2C/i2c_pns.h | 0 testhal/{STM32 => STM32F1xx}/I2C/lis3.c | 0 testhal/{STM32 => STM32F1xx}/I2C/lis3.h | 0 testhal/{STM32 => STM32F1xx}/I2C/main.c | 0 testhal/{STM32 => STM32F1xx}/I2C/main.h | 0 testhal/{STM32 => STM32F1xx}/I2C/max1236.c | 0 testhal/{STM32 => STM32F1xx}/I2C/max1236.h | 0 testhal/{STM32 => STM32F1xx}/I2C/mcuconf.h | 0 testhal/{STM32 => STM32F1xx}/I2C/tmp75.c | 0 testhal/{STM32 => STM32F1xx}/I2C/tmp75.h | 0 testhal/STM32F1xx/IRQ_STORM/Makefile | 204 +++++++++++++++ .../{STM32 => STM32F1xx}/IRQ_STORM/chconf.h | 0 .../{STM32 => STM32F1xx}/IRQ_STORM/halconf.h | 0 testhal/{STM32 => STM32F1xx}/IRQ_STORM/main.c | 0 .../{STM32 => STM32F1xx}/IRQ_STORM/mcuconf.h | 0 .../{STM32 => STM32F1xx}/IRQ_STORM/readme.txt | 0 .../{STM32/ADC => STM32F1xx/PWM-ICU}/Makefile | 11 +- testhal/{STM32 => STM32F1xx}/PWM-ICU/chconf.h | 0 .../{STM32 => STM32F1xx}/PWM-ICU/halconf.h | 0 testhal/{STM32 => STM32F1xx}/PWM-ICU/main.c | 0 .../{STM32 => STM32F1xx}/PWM-ICU/mcuconf.h | 0 .../{STM32 => STM32F1xx}/PWM-ICU/readme.txt | 0 testhal/{STM32 => STM32F1xx}/SDIO/Makefile | 11 +- testhal/{STM32 => STM32F1xx}/SDIO/chconf.h | 0 testhal/{STM32 => STM32F1xx}/SDIO/halconf.h | 0 testhal/{STM32 => STM32F1xx}/SDIO/main.c | 0 testhal/{STM32 => STM32F1xx}/SDIO/mcuconf.h | 0 testhal/{STM32 => STM32F1xx}/SDIO/readme.txt | 0 testhal/STM32F1xx/SPI/Makefile | 204 +++++++++++++++ testhal/{STM32 => STM32F1xx}/SPI/chconf.h | 0 testhal/{STM32 => STM32F1xx}/SPI/halconf.h | 0 testhal/{STM32 => STM32F1xx}/SPI/main.c | 0 testhal/{STM32 => STM32F1xx}/SPI/mcuconf.h | 0 testhal/{STM32 => STM32F1xx}/SPI/readme.txt | 0 testhal/STM32F1xx/UART/Makefile | 204 +++++++++++++++ testhal/{STM32 => STM32F1xx}/UART/chconf.h | 0 testhal/{STM32 => STM32F1xx}/UART/halconf.h | 0 testhal/{STM32 => STM32F1xx}/UART/main.c | 0 testhal/{STM32 => STM32F1xx}/UART/mcuconf.h | 0 testhal/{STM32 => STM32F1xx}/UART/readme.txt | 0 testhal/{STM32 => STM32F1xx}/USB_CDC/Makefile | 14 +- testhal/{STM32 => STM32F1xx}/USB_CDC/chconf.h | 0 .../{STM32 => STM32F1xx}/USB_CDC/halconf.h | 0 testhal/{STM32 => STM32F1xx}/USB_CDC/main.c | 0 .../{STM32 => STM32F1xx}/USB_CDC/mcuconf.h | 0 testhal/{STM32 => STM32F1xx}/USB_MSC/Makefile | 14 +- testhal/{STM32 => STM32F1xx}/USB_MSC/chconf.h | 0 .../{STM32 => STM32F1xx}/USB_MSC/halconf.h | 0 testhal/{STM32 => STM32F1xx}/USB_MSC/main.c | 0 .../{STM32 => STM32F1xx}/USB_MSC/mcuconf.h | 0 todo.txt | 6 +- 142 files changed, 1186 insertions(+), 4660 deletions(-) create mode 100644 boards/ST_STM3220G_EVAL/board.c create mode 100644 boards/ST_STM3220G_EVAL/board.h create mode 100644 boards/ST_STM3220G_EVAL/board.mk delete mode 100644 demos/ARM7-AT91SAM7S-FATFS-GCC/ch.ld delete mode 100644 demos/ARM7-AT91SAM7S-GCC/ch.ld delete mode 100644 demos/ARM7-AT91SAM7X-FATFS-GCC/ch.ld delete mode 100644 demos/ARM7-AT91SAM7X-GCC/ch.ld delete mode 100644 demos/ARM7-AT91SAM7X-LWIP-GCC/ch.ld delete mode 100644 demos/ARM7-AT91SAM7X-UIP-GCC/ch.ld delete mode 100644 demos/ARM7-LPC214x-FATFS-GCC/ch.ld delete mode 100644 demos/ARM7-LPC214x-G++/ch.ld delete mode 100644 demos/ARM7-LPC214x-GCC/ch.ld delete mode 100644 demos/ARMCM0-LPC1114-LPCXPRESSO/ch.ld delete mode 100644 demos/ARMCM3-LPC1343-LPCXPRESSO/ch.ld delete mode 100644 demos/ARMCM3-STM32F100-DISCOVERY/ch.ld delete mode 100644 demos/ARMCM3-STM32F103-FATFS/ch.ld delete mode 100644 demos/ARMCM3-STM32F103-G++/ch.ld delete mode 100644 demos/ARMCM3-STM32F103/ch.ld delete mode 100644 demos/ARMCM3-STM32F103ZG-FATFS/ch.ld delete mode 100644 demos/ARMCM3-STM32F107/ch.ld delete mode 100644 demos/ARMCM3-STM32L152-DISCOVERY/ch.ld delete mode 100644 testhal/LPC11xx/IRQ_STORM/ch.ld delete mode 100644 testhal/LPC13xx/IRQ_STORM/ch.ld delete mode 100644 testhal/STM32/ADC/ch.ld delete mode 100644 testhal/STM32/CAN/ch.ld delete mode 100644 testhal/STM32/GPT/ch.ld delete mode 100644 testhal/STM32/GPT/openocd.bat delete mode 100644 testhal/STM32/GPT/openocd.cfg delete mode 100644 testhal/STM32/I2C/ch.ld delete mode 100644 testhal/STM32/IRQ_STORM/ch.ld delete mode 100644 testhal/STM32/PWM-ICU/Makefile delete mode 100644 testhal/STM32/PWM-ICU/ch.ld delete mode 100644 testhal/STM32/SDIO/ch.ld delete mode 100644 testhal/STM32/SPI/Makefile delete mode 100644 testhal/STM32/SPI/ch.ld delete mode 100644 testhal/STM32/UART/Makefile delete mode 100644 testhal/STM32/UART/ch.ld delete mode 100644 testhal/STM32/USB_CDC/ch.ld delete mode 100644 testhal/STM32/USB_MSC/ch.ld rename testhal/{STM32/CAN => STM32F1xx/ADC}/Makefile (93%) rename testhal/{STM32 => STM32F1xx}/ADC/chconf.h (100%) rename testhal/{STM32 => STM32F1xx}/ADC/halconf.h (100%) rename testhal/{STM32 => STM32F1xx}/ADC/main.c (100%) rename testhal/{STM32 => STM32F1xx}/ADC/mcuconf.h (100%) rename testhal/{STM32 => STM32F1xx}/ADC/readme.txt (100%) rename testhal/{STM32/GPT => STM32F1xx/CAN}/Makefile (93%) rename testhal/{STM32 => STM32F1xx}/CAN/chconf.h (100%) rename testhal/{STM32 => STM32F1xx}/CAN/halconf.h (100%) rename testhal/{STM32 => STM32F1xx}/CAN/main.c (100%) rename testhal/{STM32 => STM32F1xx}/CAN/mcuconf.h (100%) rename testhal/{STM32 => STM32F1xx}/CAN/readme.txt (100%) rename testhal/{STM32/IRQ_STORM => STM32F1xx/GPT}/Makefile (93%) rename testhal/{STM32 => STM32F1xx}/GPT/chconf.h (100%) rename testhal/{STM32 => STM32F1xx}/GPT/halconf.h (100%) rename testhal/{STM32 => STM32F1xx}/GPT/main.c (100%) rename testhal/{STM32 => STM32F1xx}/GPT/mcuconf.h (100%) rename testhal/{STM32 => STM32F1xx}/GPT/readme.txt (100%) rename testhal/{STM32 => STM32F1xx}/GPT/run (100%) rename testhal/{STM32 => STM32F1xx}/I2C/Makefile (100%) rename testhal/{STM32 => STM32F1xx}/I2C/chconf.h (100%) rename testhal/{STM32 => STM32F1xx}/I2C/halconf.h (100%) rename testhal/{STM32 => STM32F1xx}/I2C/i2c_pns.c (100%) rename testhal/{STM32 => STM32F1xx}/I2C/i2c_pns.h (100%) rename testhal/{STM32 => STM32F1xx}/I2C/lis3.c (100%) rename testhal/{STM32 => STM32F1xx}/I2C/lis3.h (100%) rename testhal/{STM32 => STM32F1xx}/I2C/main.c (100%) rename testhal/{STM32 => STM32F1xx}/I2C/main.h (100%) rename testhal/{STM32 => STM32F1xx}/I2C/max1236.c (100%) rename testhal/{STM32 => STM32F1xx}/I2C/max1236.h (100%) rename testhal/{STM32 => STM32F1xx}/I2C/mcuconf.h (100%) rename testhal/{STM32 => STM32F1xx}/I2C/tmp75.c (100%) rename testhal/{STM32 => STM32F1xx}/I2C/tmp75.h (100%) create mode 100644 testhal/STM32F1xx/IRQ_STORM/Makefile rename testhal/{STM32 => STM32F1xx}/IRQ_STORM/chconf.h (100%) rename testhal/{STM32 => STM32F1xx}/IRQ_STORM/halconf.h (100%) rename testhal/{STM32 => STM32F1xx}/IRQ_STORM/main.c (100%) rename testhal/{STM32 => STM32F1xx}/IRQ_STORM/mcuconf.h (100%) rename testhal/{STM32 => STM32F1xx}/IRQ_STORM/readme.txt (100%) rename testhal/{STM32/ADC => STM32F1xx/PWM-ICU}/Makefile (93%) rename testhal/{STM32 => STM32F1xx}/PWM-ICU/chconf.h (100%) rename testhal/{STM32 => STM32F1xx}/PWM-ICU/halconf.h (100%) rename testhal/{STM32 => STM32F1xx}/PWM-ICU/main.c (100%) rename testhal/{STM32 => STM32F1xx}/PWM-ICU/mcuconf.h (100%) rename testhal/{STM32 => STM32F1xx}/PWM-ICU/readme.txt (100%) rename testhal/{STM32 => STM32F1xx}/SDIO/Makefile (92%) rename testhal/{STM32 => STM32F1xx}/SDIO/chconf.h (100%) rename testhal/{STM32 => STM32F1xx}/SDIO/halconf.h (100%) rename testhal/{STM32 => STM32F1xx}/SDIO/main.c (100%) rename testhal/{STM32 => STM32F1xx}/SDIO/mcuconf.h (100%) rename testhal/{STM32 => STM32F1xx}/SDIO/readme.txt (100%) create mode 100644 testhal/STM32F1xx/SPI/Makefile rename testhal/{STM32 => STM32F1xx}/SPI/chconf.h (100%) rename testhal/{STM32 => STM32F1xx}/SPI/halconf.h (100%) rename testhal/{STM32 => STM32F1xx}/SPI/main.c (100%) rename testhal/{STM32 => STM32F1xx}/SPI/mcuconf.h (100%) rename testhal/{STM32 => STM32F1xx}/SPI/readme.txt (100%) create mode 100644 testhal/STM32F1xx/UART/Makefile rename testhal/{STM32 => STM32F1xx}/UART/chconf.h (100%) rename testhal/{STM32 => STM32F1xx}/UART/halconf.h (100%) rename testhal/{STM32 => STM32F1xx}/UART/main.c (100%) rename testhal/{STM32 => STM32F1xx}/UART/mcuconf.h (100%) rename testhal/{STM32 => STM32F1xx}/UART/readme.txt (100%) rename testhal/{STM32 => STM32F1xx}/USB_CDC/Makefile (93%) rename testhal/{STM32 => STM32F1xx}/USB_CDC/chconf.h (100%) rename testhal/{STM32 => STM32F1xx}/USB_CDC/halconf.h (100%) rename testhal/{STM32 => STM32F1xx}/USB_CDC/main.c (100%) rename testhal/{STM32 => STM32F1xx}/USB_CDC/mcuconf.h (100%) rename testhal/{STM32 => STM32F1xx}/USB_MSC/Makefile (93%) rename testhal/{STM32 => STM32F1xx}/USB_MSC/chconf.h (100%) rename testhal/{STM32 => STM32F1xx}/USB_MSC/halconf.h (100%) rename testhal/{STM32 => STM32F1xx}/USB_MSC/main.c (100%) rename testhal/{STM32 => STM32F1xx}/USB_MSC/mcuconf.h (100%) diff --git a/boards/ST_STM3220G_EVAL/board.c b/boards/ST_STM3220G_EVAL/board.c new file mode 100644 index 000000000..efb8ef566 --- /dev/null +++ b/boards/ST_STM3220G_EVAL/board.c @@ -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 . +*/ + +#include "ch.h" +#include "hal.h" + +/** + * @brief PAL setup. + * @details Digital I/O ports static configuration as defined in @p board.h. + * This variable is used by the HAL when initializing the PAL driver. + */ +#if HAL_USE_PAL || defined(__DOXYGEN__) +const PALConfig pal_default_config = +{ + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, + {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, + {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, + {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH} +}; +#endif + +/* + * Early initialization code. + * This initialization must be performed just after stack setup and before + * any other initialization. + */ +void __early_init(void) { + + stm32_clock_init(); +} + +/* + * Board-specific initialization code. + */ +void boardInit(void) { +} diff --git a/boards/ST_STM3220G_EVAL/board.h b/boards/ST_STM3220G_EVAL/board.h new file mode 100644 index 000000000..e10a5203c --- /dev/null +++ b/boards/ST_STM3220G_EVAL/board.h @@ -0,0 +1,245 @@ +/* + 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 . +*/ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +/* + * Setup for STMicroelectronics STM3220G-EVAL board. + */ + +/* + * Board identifier. + */ +#define BOARD_ST_STM3220G_EVAL +#define BOARD_NAME "ST STM3220G-EVAL" + +/* + * Board frequencies. + * NOTE: The HSE crystal is not fitted by default on the board. + */ +#define STM32_LSECLK 32768 +#define STM32_HSECLK 25000000 + +/* + * MCU type as defined in the ST header file stm32f2xx.h. + */ +#define STM32F2XX + +/* + * IO pins assignments. + */ + +#define GPIOA_WAKEUP_BUTTON 0 + +#define GPIOB_ETHER_INT 14 +#define GPIOB_NAND_INT 15 + +#define GPIOC_TAMPER_BUTTON 0 +#define GPIOC_LED4 7 + +#define GPIOF_POT 9 + +#define GPIOG_LED1 6 +#define GPIOG_LED2 8 +#define GPIOG_USER_BUTTON 15 + +#define GPIOH_EXPANDER_INT 12 +#define GPIOH_SD_DETECT 13 + +#define GPIOI_LED3 9 + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0 << ((n) * 2)) +#define PIN_MODE_OUTPUT(n) (1 << ((n) * 2)) +#define PIN_MODE_ALTERNATE(n) (2 << ((n) * 2)) +#define PIN_MODE_ANALOG(n) (3 << ((n) * 2)) +#define PIN_OTYPE_PUSHPULL(n) (0 << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1 << (n)) +#define PIN_OSPEED_2M(n) (0 << ((n) * 2)) +#define PIN_OSPEED_25M(n) (1 << ((n) * 2)) +#define PIN_OSPEED_50M(n) (2 << ((n) * 2)) +#define PIN_OSPEED_100M(n) (3 << ((n) * 2)) +#define PIN_PUDR_FLOATING(n) (0 << ((n) * 2)) +#define PIN_PUDR_PULLUP(n) (1 << ((n) * 2)) +#define PIN_PUDR_PULLDOWN(n) (2 << ((n) * 2)) +#define PIN_AFIO_AF0(n) (0 << ((n % 8) * 4)) +#define PIN_AFIO_AF1(n) (1 << ((n % 8) * 4)) +#define PIN_AFIO_AF2(n) (2 << ((n % 8) * 4)) +#define PIN_AFIO_AF3(n) (3 << ((n % 8) * 4)) +#define PIN_AFIO_AF4(n) (4 << ((n % 8) * 4)) +#define PIN_AFIO_AF5(n) (5 << ((n % 8) * 4)) +#define PIN_AFIO_AF6(n) (6 << ((n % 8) * 4)) +#define PIN_AFIO_AF7(n) (7 << ((n % 8) * 4)) +#define PIN_AFIO_AF8(n) (8 << ((n % 8) * 4)) +#define PIN_AFIO_AF9(n) (9 << ((n % 8) * 4)) +#define PIN_AFIO_AF10(n) (10 << ((n % 8) * 4)) +#define PIN_AFIO_AF11(n) (11 << ((n % 8) * 4)) +#define PIN_AFIO_AF12(n) (12 << ((n % 8) * 4)) +#define PIN_AFIO_AF13(n) (13 << ((n % 8) * 4)) +#define PIN_AFIO_AF14(n) (14 << ((n % 8) * 4)) +#define PIN_AFIO_AF15(n) (15 << ((n % 8) * 4)) + +/* + * Port A setup. + * All input with pull-up except: + * PA8 - MCO 1 (alternate 0). + * PA13 - JTMS/SWDAT (alternate 0). + * PA14 - JTCK/SWCLK (alternate 0). + * PA15 - JTDI (alternate 0). + */ +#define VAL_GPIOA_MODER (PIN_MODE_ALTERNATE(8) | \ + PIN_MODE_ALTERNATE(13) | \ + PIN_MODE_ALTERNATE(14) | \ + PIN_MODE_ALTERNATE(15)) +#define VAL_GPIOA_OTYPER 0x00000000 +#define VAL_GPIOA_OSPEEDR 0xFFFFFFFF +#define VAL_GPIOA_PUPDR (PIN_PUDR_FLOATING(13) | \ + PIN_PUDR_FLOATING(14) | \ + PIN_PUDR_FLOATING(15)) +#define VAL_GPIOA_ODR 0xFFFFFFFF +#define VAL_GPIOA_AFRL 0x00000000 +#define VAL_GPIOA_AFRH 0x00000000 + +/* + * Port B setup. + * All input with pull-up except: + * PB3 - JTDO (alternate 0). + * PB4 - JNTRST (alternate 0). + */ +#define VAL_GPIOB_MODER (PIN_MODE_ALTERNATE(3) | \ + PIN_MODE_ALTERNATE(4)) +#define VAL_GPIOB_OTYPER 0x00000000 +#define VAL_GPIOB_OSPEEDR 0xFFFFFFFF +#define VAL_GPIOB_PUPDR (~(PIN_PUDR_FLOATING(3) | \ + PIN_PUDR_FLOATING(4))) +#define VAL_GPIOB_ODR 0xFFFFFFFF +#define VAL_GPIOB_AFRL 0x00000000 +#define VAL_GPIOB_AFRH 0x00000000 + +/* + * Port C setup. + * All input with pull-up except: + * PC9 - MCO2 (alternate 0). + * PC10 - USART3_TX (alternate 7). + * PC11 - USART3_RX (alternate 7). + * PC14 - OSC32_INT (input floating). + * PC15 - OSC32_OUT (input floating). + */ +#define VAL_GPIOC_MODER (PIN_MODE_ALTERNATE(9) | \ + PIN_MODE_ALTERNATE(10) | \ + PIN_MODE_ALTERNATE(11)) +#define VAL_GPIOC_OTYPER 0x00000000 +#define VAL_GPIOC_OSPEEDR 0xFFFFFFFF +#define VAL_GPIOC_PUPDR (~(PIN_PUDR_PULLUP(11) | \ + PIN_PUDR_FLOATING(14) | \ + PIN_PUDR_FLOATING(15))) +#define VAL_GPIOC_ODR 0xFFFFFFFF +#define VAL_GPIOC_AFRL 0x00000000 +#define VAL_GPIOC_AFRH (PIN_AFIO_AF7(10) | \ + PIN_AFIO_AF7(11)) + +/* + * Port D setup. + * All input with pull-up. + */ +#define VAL_GPIOD_MODER 0x00000000 +#define VAL_GPIOD_OTYPER 0x00000000 +#define VAL_GPIOD_OSPEEDR 0xFFFFFFFF +#define VAL_GPIOD_PUPDR 0xFFFFFFFF +#define VAL_GPIOD_ODR 0xFFFFFFFF +#define VAL_GPIOD_AFRL 0x00000000 +#define VAL_GPIOD_AFRH 0x00000000 + +/* + * Port E setup. + * All input with pull-up. + */ +#define VAL_GPIOE_MODER 0x00000000 +#define VAL_GPIOE_OTYPER 0x00000000 +#define VAL_GPIOE_OSPEEDR 0xFFFFFFFF +#define VAL_GPIOE_PUPDR 0xFFFFFFFF +#define VAL_GPIOE_ODR 0xFFFFFFFF +#define VAL_GPIOE_AFRL 0x00000000 +#define VAL_GPIOE_AFRH 0x00000000 + +/* + * Port F setup. + * All input with pull-up. + */ +#define VAL_GPIOF_MODER 0x00000000 +#define VAL_GPIOF_OTYPER 0x00000000 +#define VAL_GPIOF_OSPEEDR 0xFFFFFFFF +#define VAL_GPIOF_PUPDR 0xFFFFFFFF +#define VAL_GPIOF_ODR 0xFFFFFFFF +#define VAL_GPIOF_AFRL 0x00000000 +#define VAL_GPIOF_AFRH 0x00000000 + +/* + * Port G setup. + * All input with pull-up. + */ +#define VAL_GPIOG_MODER (PIN_MODE_OUTPUT(GPIOG_LED1)) +#define VAL_GPIOG_OTYPER 0x00000000 +#define VAL_GPIOG_OSPEEDR 0xFFFFFFFF +#define VAL_GPIOG_PUPDR (~(PIN_PUDR_FLOATING(GPIOG_LED1))) +#define VAL_GPIOG_ODR 0xFFFFFFBF +#define VAL_GPIOG_AFRL 0x00000000 +#define VAL_GPIOG_AFRH 0x00000000 + +/* + * Port H setup. + * All input with pull-up. + */ +#define VAL_GPIOH_MODER 0x00000000 +#define VAL_GPIOH_OTYPER 0x00000000 +#define VAL_GPIOH_OSPEEDR 0xFFFFFFFF +#define VAL_GPIOH_PUPDR 0xFFFFFFFF +#define VAL_GPIOH_ODR 0xFFFFFFFF +#define VAL_GPIOH_AFRL 0x00000000 +#define VAL_GPIOH_AFRH 0x00000000 + +/* + * Port I setup. + * All input with pull-up. + */ +#define VAL_GPIOI_MODER 0x00000000 +#define VAL_GPIOI_OTYPER 0x00000000 +#define VAL_GPIOI_OSPEEDR 0xFFFFFFFF +#define VAL_GPIOI_PUPDR 0xFFFFFFFF +#define VAL_GPIOI_ODR 0xFFFFFFFF +#define VAL_GPIOI_AFRL 0x00000000 +#define VAL_GPIOI_AFRH 0x00000000 + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* _BOARD_H_ */ diff --git a/boards/ST_STM3220G_EVAL/board.mk b/boards/ST_STM3220G_EVAL/board.mk new file mode 100644 index 000000000..3121594a6 --- /dev/null +++ b/boards/ST_STM3220G_EVAL/board.mk @@ -0,0 +1,5 @@ +# List of all the board related files. +BOARDSRC = ${CHIBIOS}/boards/ST_STM3220G_EVAL/board.c + +# Required include directories +BOARDINC = ${CHIBIOS}/boards/ST_STM3220G_EVAL diff --git a/boards/ST_STM32L_DISCOVERY/board.c b/boards/ST_STM32L_DISCOVERY/board.c index 37015943a..4a93dada2 100644 --- a/boards/ST_STM32L_DISCOVERY/board.c +++ b/boards/ST_STM32L_DISCOVERY/board.c @@ -29,12 +29,12 @@ #if HAL_USE_PAL || defined(__DOXYGEN__) const PALConfig pal_default_config = { - {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, VAL_GPIOA_ODR}, - {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, VAL_GPIOB_ODR}, - {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, VAL_GPIOC_ODR}, - {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, VAL_GPIOD_ODR}, - {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, VAL_GPIOE_ODR}, - {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, VAL_GPIOH_ODR} + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH} }; #endif diff --git a/boards/ST_STM32L_DISCOVERY/board.h b/boards/ST_STM32L_DISCOVERY/board.h index ddad89b5e..d95480c15 100644 --- a/boards/ST_STM32L_DISCOVERY/board.h +++ b/boards/ST_STM32L_DISCOVERY/board.h @@ -69,6 +69,22 @@ #define PIN_PUDR_FLOATING(n) (0 << ((n) * 2)) #define PIN_PUDR_PULLUP(n) (1 << ((n) * 2)) #define PIN_PUDR_PULLDOWN(n) (2 << ((n) * 2)) +#define PIN_AFIO_AF0(n) (0 << ((n % 8) * 4)) +#define PIN_AFIO_AF1(n) (1 << ((n % 8) * 4)) +#define PIN_AFIO_AF2(n) (2 << ((n % 8) * 4)) +#define PIN_AFIO_AF3(n) (3 << ((n % 8) * 4)) +#define PIN_AFIO_AF4(n) (4 << ((n % 8) * 4)) +#define PIN_AFIO_AF5(n) (5 << ((n % 8) * 4)) +#define PIN_AFIO_AF6(n) (6 << ((n % 8) * 4)) +#define PIN_AFIO_AF7(n) (7 << ((n % 8) * 4)) +#define PIN_AFIO_AF8(n) (8 << ((n % 8) * 4)) +#define PIN_AFIO_AF9(n) (9 << ((n % 8) * 4)) +#define PIN_AFIO_AF10(n) (10 << ((n % 8) * 4)) +#define PIN_AFIO_AF11(n) (11 << ((n % 8) * 4)) +#define PIN_AFIO_AF12(n) (12 << ((n % 8) * 4)) +#define PIN_AFIO_AF13(n) (13 << ((n % 8) * 4)) +#define PIN_AFIO_AF14(n) (14 << ((n % 8) * 4)) +#define PIN_AFIO_AF15(n) (15 << ((n % 8) * 4)) /* * Port A setup. @@ -89,6 +105,8 @@ PIN_PUDR_FLOATING(14) | \ PIN_PUDR_FLOATING(15))) #define VAL_GPIOA_ODR 0xFFFFFFFF +#define VAL_GPIOA_AFRL 0x00000000 +#define VAL_GPIOA_AFRH 0x00000000 /* * Port B setup. @@ -109,6 +127,8 @@ PIN_PUDR_FLOATING(GPIOB_LED4) | \ PIN_PUDR_FLOATING(GPIOB_LED3))) #define VAL_GPIOB_ODR 0xFFFFFF3F +#define VAL_GPIOB_AFRL 0x00000000 +#define VAL_GPIOB_AFRH 0x00000000 /* * Port C setup. @@ -122,6 +142,8 @@ #define VAL_GPIOC_PUPDR (~(PIN_PUDR_FLOATING(15) | \ PIN_PUDR_FLOATING(14))) #define VAL_GPIOC_ODR 0xFFFFFFFF +#define VAL_GPIOC_AFRL 0x00000000 +#define VAL_GPIOC_AFRH 0x00000000 /* * Port D setup. @@ -132,6 +154,8 @@ #define VAL_GPIOD_OSPEEDR 0xFFFFFFFF #define VAL_GPIOD_PUPDR 0xFFFFFFFF #define VAL_GPIOD_ODR 0xFFFFFFFF +#define VAL_GPIOD_AFRL 0x00000000 +#define VAL_GPIOD_AFRH 0x00000000 /* * Port E setup. @@ -142,6 +166,8 @@ #define VAL_GPIOE_OSPEEDR 0xFFFFFFFF #define VAL_GPIOE_PUPDR 0xFFFFFFFF #define VAL_GPIOE_ODR 0xFFFFFFFF +#define VAL_GPIOE_AFRL 0x00000000 +#define VAL_GPIOE_AFRH 0x00000000 /* * Port H setup. @@ -152,6 +178,8 @@ #define VAL_GPIOH_OSPEEDR 0xFFFFFFFF #define VAL_GPIOH_PUPDR 0xFFFFFFFF #define VAL_GPIOH_ODR 0xFFFFFFFF +#define VAL_GPIOH_AFRL 0x00000000 +#define VAL_GPIOH_AFRH 0x00000000 #if !defined(_FROM_ASM_) #ifdef __cplusplus diff --git a/demos/ARM7-AT91SAM7S-FATFS-GCC/Makefile b/demos/ARM7-AT91SAM7S-FATFS-GCC/Makefile index 531e2506a..2a2c9e910 100644 --- a/demos/ARM7-AT91SAM7S-FATFS-GCC/Makefile +++ b/demos/ARM7-AT91SAM7S-FATFS-GCC/Makefile @@ -39,19 +39,19 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT= ch.ld - -# Imported source files +# Imported source files and paths CHIBIOS = ../.. include $(CHIBIOS)/boards/OLIMEX_SAM7_P256/board.mk include $(CHIBIOS)/os/hal/platforms/AT91SAM7/platform.mk include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARM/port.mk +include $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk include $(CHIBIOS)/ext/fatfs/fatfs.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/AT91SAM7S256.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ @@ -90,14 +90,12 @@ TCSRC = TCPPSRC = # List ASM source files here -ASMSRC = $(PORTASM) \ - $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7/vectors.s +ASMSRC = $(PORTASM) INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \ $(HALINC) $(PLATFORMINC) $(BOARDINC) \ $(FATFSINC) \ - $(CHIBIOS)/os/various \ - $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7 + $(CHIBIOS)/os/various # # Project, sources and paths diff --git a/demos/ARM7-AT91SAM7S-FATFS-GCC/ch.ld b/demos/ARM7-AT91SAM7S-FATFS-GCC/ch.ld deleted file mode 100644 index b999dac9a..000000000 --- a/demos/ARM7-AT91SAM7S-FATFS-GCC/ch.ld +++ /dev/null @@ -1,111 +0,0 @@ -/* - 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 . -*/ - -/* - * AT91SAM7X256 memory setup. - */ -__und_stack_size__ = 0x0004; -__abt_stack_size__ = 0x0004; -__fiq_stack_size__ = 0x0010; -__irq_stack_size__ = 0x0080; -__svc_stack_size__ = 0x0004; -__sys_stack_size__ = 0x0400; -__stacks_total_size__ = __und_stack_size__ + __abt_stack_size__ + __fiq_stack_size__ + __irq_stack_size__ + __svc_stack_size__ + __sys_stack_size__; - -MEMORY -{ - flash : org = 0x100000, len = 256k - ram : org = 0x200020, len = 64k - 0x20 -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; - -SECTIONS -{ - . = 0; - - .text : ALIGN(16) SUBALIGN(16) - { - _text = .; - KEEP(*(vectors)) - *(.text) - *(.text.*); - *(.rodata); - *(.rodata.*); - *(.glue_7t); - *(.glue_7); - *(.gcc*); - *(.ctors); - *(.dtors); - . = ALIGN(4); - _etext = .; - } > flash - - .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} - - __exidx_start = .; - .ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > flash - __exidx_end = .; - - .eh_frame_hdr : {*(.eh_frame_hdr)} - - .eh_frame : ONLY_IF_RO {*(.eh_frame)} - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - _data = .; - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - _edata = .; - } > ram AT > flash - - .bss : - { - _bss_start = .; - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - _bss_end = .; - } > ram - - /DISCARD/ : - { - *(.eh_*) - } -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARM7-AT91SAM7S-GCC/Makefile b/demos/ARM7-AT91SAM7S-GCC/Makefile index 515224c81..fb169d6e1 100644 --- a/demos/ARM7-AT91SAM7S-GCC/Makefile +++ b/demos/ARM7-AT91SAM7S-GCC/Makefile @@ -39,18 +39,18 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT= ch.ld - -# Imported source files +# Imported source files and paths CHIBIOS = ../.. include $(CHIBIOS)/boards/OLIMEX_SAM7_P256/board.mk include $(CHIBIOS)/os/hal/platforms/AT91SAM7/platform.mk include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARM/port.mk +include $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/AT91SAM7S256.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ @@ -86,13 +86,11 @@ TCSRC = TCPPSRC = # List ASM source files here -ASMSRC = $(PORTASM) \ - $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7/vectors.s +ASMSRC = $(PORTASM) INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \ $(HALINC) $(PLATFORMINC) $(BOARDINC) \ - $(CHIBIOS)/os/various \ - $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7 + $(CHIBIOS)/os/various # # Project, sources and paths diff --git a/demos/ARM7-AT91SAM7S-GCC/ch.ld b/demos/ARM7-AT91SAM7S-GCC/ch.ld deleted file mode 100644 index e26268451..000000000 --- a/demos/ARM7-AT91SAM7S-GCC/ch.ld +++ /dev/null @@ -1,99 +0,0 @@ -/* - 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 . -*/ - -/* - * AT91SAM7X256 memory setup. - */ -__und_stack_size__ = 0x0004; -__abt_stack_size__ = 0x0004; -__fiq_stack_size__ = 0x0010; -__irq_stack_size__ = 0x0080; -__svc_stack_size__ = 0x0004; -__sys_stack_size__ = 0x0400; -__stacks_total_size__ = __und_stack_size__ + __abt_stack_size__ + __fiq_stack_size__ + __irq_stack_size__ + __svc_stack_size__ + __sys_stack_size__; - -MEMORY -{ - flash : org = 0x100000, len = 256k - ram : org = 0x200020, len = 64k - 0x20 -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; - -SECTIONS -{ - . = 0; - - .text : ALIGN(16) SUBALIGN(16) - { - _text = .; - KEEP(*(vectors)) - *(.text) - *(.text.*); - *(.rodata); - *(.rodata.*); - *(.glue_7t); - *(.glue_7); - *(.gcc*); - *(.ctors); - *(.dtors); - . = ALIGN(4); - _etext = .; - } > flash - - _textdata = _etext; - - .data : - { - _data = .; - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - _edata = .; - } > ram AT > flash - - .bss : - { - _bss_start = .; - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - _bss_end = .; - } > ram - - /DISCARD/ : - { - *(.eh_*) - } -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARM7-AT91SAM7X-FATFS-GCC/Makefile b/demos/ARM7-AT91SAM7X-FATFS-GCC/Makefile index 6553ef548..4b8fc0650 100644 --- a/demos/ARM7-AT91SAM7X-FATFS-GCC/Makefile +++ b/demos/ARM7-AT91SAM7X-FATFS-GCC/Makefile @@ -39,19 +39,19 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT= ch.ld - -# Imported source files +# Imported source files and paths CHIBIOS = ../.. include $(CHIBIOS)/boards/OLIMEX_SAM7_EX256/board.mk include $(CHIBIOS)/os/hal/platforms/AT91SAM7/platform.mk include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARM/port.mk +include $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk include $(CHIBIOS)/ext/fatfs/fatfs.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/AT91SAM7X256.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ @@ -90,14 +90,12 @@ TCSRC = TCPPSRC = # List ASM source files here -ASMSRC = $(PORTASM) \ - $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7/vectors.s +ASMSRC = $(PORTASM) INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \ $(HALINC) $(PLATFORMINC) $(BOARDINC) \ $(FATFSINC) \ - $(CHIBIOS)/os/various \ - $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7 + $(CHIBIOS)/os/various # # Project, sources and paths diff --git a/demos/ARM7-AT91SAM7X-FATFS-GCC/ch.ld b/demos/ARM7-AT91SAM7X-FATFS-GCC/ch.ld deleted file mode 100644 index b999dac9a..000000000 --- a/demos/ARM7-AT91SAM7X-FATFS-GCC/ch.ld +++ /dev/null @@ -1,111 +0,0 @@ -/* - 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 . -*/ - -/* - * AT91SAM7X256 memory setup. - */ -__und_stack_size__ = 0x0004; -__abt_stack_size__ = 0x0004; -__fiq_stack_size__ = 0x0010; -__irq_stack_size__ = 0x0080; -__svc_stack_size__ = 0x0004; -__sys_stack_size__ = 0x0400; -__stacks_total_size__ = __und_stack_size__ + __abt_stack_size__ + __fiq_stack_size__ + __irq_stack_size__ + __svc_stack_size__ + __sys_stack_size__; - -MEMORY -{ - flash : org = 0x100000, len = 256k - ram : org = 0x200020, len = 64k - 0x20 -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; - -SECTIONS -{ - . = 0; - - .text : ALIGN(16) SUBALIGN(16) - { - _text = .; - KEEP(*(vectors)) - *(.text) - *(.text.*); - *(.rodata); - *(.rodata.*); - *(.glue_7t); - *(.glue_7); - *(.gcc*); - *(.ctors); - *(.dtors); - . = ALIGN(4); - _etext = .; - } > flash - - .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} - - __exidx_start = .; - .ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > flash - __exidx_end = .; - - .eh_frame_hdr : {*(.eh_frame_hdr)} - - .eh_frame : ONLY_IF_RO {*(.eh_frame)} - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - _data = .; - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - _edata = .; - } > ram AT > flash - - .bss : - { - _bss_start = .; - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - _bss_end = .; - } > ram - - /DISCARD/ : - { - *(.eh_*) - } -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARM7-AT91SAM7X-GCC/Makefile b/demos/ARM7-AT91SAM7X-GCC/Makefile index e6480eb1c..2fae31137 100644 --- a/demos/ARM7-AT91SAM7X-GCC/Makefile +++ b/demos/ARM7-AT91SAM7X-GCC/Makefile @@ -39,18 +39,18 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT= ch.ld - -# Imported source files +# Imported source files and paths CHIBIOS = ../.. include $(CHIBIOS)/boards/OLIMEX_SAM7_EX256/board.mk include $(CHIBIOS)/os/hal/platforms/AT91SAM7/platform.mk include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARM/port.mk +include $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/AT91SAM7X256.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ @@ -86,13 +86,11 @@ TCSRC = TCPPSRC = # List ASM source files here -ASMSRC = $(PORTASM) \ - $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7/vectors.s +ASMSRC = $(PORTASM) INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \ $(HALINC) $(PLATFORMINC) $(BOARDINC) \ - $(CHIBIOS)/os/various \ - $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7 + $(CHIBIOS)/os/various # # Project, sources and paths diff --git a/demos/ARM7-AT91SAM7X-GCC/ch.ld b/demos/ARM7-AT91SAM7X-GCC/ch.ld deleted file mode 100644 index 9308935be..000000000 --- a/demos/ARM7-AT91SAM7X-GCC/ch.ld +++ /dev/null @@ -1,104 +0,0 @@ -/* - 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 . -*/ - -/* - * AT91SAM7X256 memory setup. - */ -__und_stack_size__ = 0x0004; -__abt_stack_size__ = 0x0004; -__fiq_stack_size__ = 0x0010; -__irq_stack_size__ = 0x0080; -__svc_stack_size__ = 0x0004; -__sys_stack_size__ = 0x0400; -__stacks_total_size__ = __und_stack_size__ + __abt_stack_size__ + __fiq_stack_size__ + __irq_stack_size__ + __svc_stack_size__ + __sys_stack_size__; - -MEMORY -{ - flash : org = 0x100000, len = 256k - ram : org = 0x200020, len = 64k - 0x20 -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; - -SECTIONS -{ - . = 0; - - .text : ALIGN(16) SUBALIGN(16) - { - _text = .; - KEEP(*(vectors)) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.glue_7t) - *(.glue_7) - *(.gcc*) - *(.ctors) - *(.dtors) - } > flash - - .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} - - __exidx_start = .; - .ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > flash - __exidx_end = .; - - .eh_frame_hdr : {*(.eh_frame_hdr)} - - .eh_frame : ONLY_IF_RO {*(.eh_frame)} - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - _data = .; - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - _edata = .; - } > ram AT > flash - - .bss : - { - _bss_start = .; - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - _bss_end = .; - } > ram -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARM7-AT91SAM7X-LWIP-GCC/Makefile b/demos/ARM7-AT91SAM7X-LWIP-GCC/Makefile index b181251e7..3f1aaa275 100644 --- a/demos/ARM7-AT91SAM7X-LWIP-GCC/Makefile +++ b/demos/ARM7-AT91SAM7X-LWIP-GCC/Makefile @@ -39,19 +39,19 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT= ch.ld - -# Imported source files +# Imported source files and paths CHIBIOS = ../.. include $(CHIBIOS)/boards/OLIMEX_SAM7_EX256/board.mk include $(CHIBIOS)/os/hal/platforms/AT91SAM7/platform.mk include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARM/port.mk +include $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk include ./lwip/lwip.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/AT91SAM7X256.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ @@ -95,13 +95,11 @@ TCSRC = TCPPSRC = # List ASM source files here -ASMSRC = $(PORTASM) \ - $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7/vectors.s +ASMSRC = $(PORTASM) INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \ $(HALINC) $(PLATFORMINC) $(BOARDINC) $(LWINC) \ $(CHIBIOS)/os/various \ - $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7 \ ./lwip # diff --git a/demos/ARM7-AT91SAM7X-LWIP-GCC/ch.ld b/demos/ARM7-AT91SAM7X-LWIP-GCC/ch.ld deleted file mode 100644 index 9308935be..000000000 --- a/demos/ARM7-AT91SAM7X-LWIP-GCC/ch.ld +++ /dev/null @@ -1,104 +0,0 @@ -/* - 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 . -*/ - -/* - * AT91SAM7X256 memory setup. - */ -__und_stack_size__ = 0x0004; -__abt_stack_size__ = 0x0004; -__fiq_stack_size__ = 0x0010; -__irq_stack_size__ = 0x0080; -__svc_stack_size__ = 0x0004; -__sys_stack_size__ = 0x0400; -__stacks_total_size__ = __und_stack_size__ + __abt_stack_size__ + __fiq_stack_size__ + __irq_stack_size__ + __svc_stack_size__ + __sys_stack_size__; - -MEMORY -{ - flash : org = 0x100000, len = 256k - ram : org = 0x200020, len = 64k - 0x20 -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; - -SECTIONS -{ - . = 0; - - .text : ALIGN(16) SUBALIGN(16) - { - _text = .; - KEEP(*(vectors)) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.glue_7t) - *(.glue_7) - *(.gcc*) - *(.ctors) - *(.dtors) - } > flash - - .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} - - __exidx_start = .; - .ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > flash - __exidx_end = .; - - .eh_frame_hdr : {*(.eh_frame_hdr)} - - .eh_frame : ONLY_IF_RO {*(.eh_frame)} - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - _data = .; - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - _edata = .; - } > ram AT > flash - - .bss : - { - _bss_start = .; - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - _bss_end = .; - } > ram -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARM7-AT91SAM7X-UIP-GCC/Makefile b/demos/ARM7-AT91SAM7X-UIP-GCC/Makefile index bad6e49f8..c1724acc9 100644 --- a/demos/ARM7-AT91SAM7X-UIP-GCC/Makefile +++ b/demos/ARM7-AT91SAM7X-UIP-GCC/Makefile @@ -39,18 +39,18 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT= ch.ld - -# Imported source files +# Imported source files and paths CHIBIOS = ../.. include $(CHIBIOS)/boards/OLIMEX_SAM7_EX256/board.mk include $(CHIBIOS)/os/hal/platforms/AT91SAM7/platform.mk include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARM/port.mk +include $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/AT91SAM7X256.ld + # List of the required uIP source files. USRC = $(CHIBIOS)/ext/uip-1.0/uip/uip_arp.c \ $(CHIBIOS)/ext/uip-1.0/uip/psock.c \ @@ -99,14 +99,14 @@ TCSRC = TCPPSRC = # List ASM source files here -ASMSRC = $(PORTASM) \ - $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7/vectors.s +ASMSRC = $(PORTASM) INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \ $(HALINC) $(PLATFORMINC) $(BOARDINC) \ $(CHIBIOS)/os/various \ - $(CHIBIOS)/os/ports/GCC/ARM/AT91SAM7 \ - ./web $(CHIBIOS)/ext/uip-1.0/uip $(CHIBIOS)/ext/uip-1.0/apps/webserver + $(CHIBIOS)/ext/uip-1.0/uip \ + $(CHIBIOS)/ext/uip-1.0/apps/webserver \ + ./web # # Project, sources and paths diff --git a/demos/ARM7-AT91SAM7X-UIP-GCC/ch.ld b/demos/ARM7-AT91SAM7X-UIP-GCC/ch.ld deleted file mode 100644 index 9308935be..000000000 --- a/demos/ARM7-AT91SAM7X-UIP-GCC/ch.ld +++ /dev/null @@ -1,104 +0,0 @@ -/* - 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 . -*/ - -/* - * AT91SAM7X256 memory setup. - */ -__und_stack_size__ = 0x0004; -__abt_stack_size__ = 0x0004; -__fiq_stack_size__ = 0x0010; -__irq_stack_size__ = 0x0080; -__svc_stack_size__ = 0x0004; -__sys_stack_size__ = 0x0400; -__stacks_total_size__ = __und_stack_size__ + __abt_stack_size__ + __fiq_stack_size__ + __irq_stack_size__ + __svc_stack_size__ + __sys_stack_size__; - -MEMORY -{ - flash : org = 0x100000, len = 256k - ram : org = 0x200020, len = 64k - 0x20 -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; - -SECTIONS -{ - . = 0; - - .text : ALIGN(16) SUBALIGN(16) - { - _text = .; - KEEP(*(vectors)) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.glue_7t) - *(.glue_7) - *(.gcc*) - *(.ctors) - *(.dtors) - } > flash - - .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} - - __exidx_start = .; - .ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > flash - __exidx_end = .; - - .eh_frame_hdr : {*(.eh_frame_hdr)} - - .eh_frame : ONLY_IF_RO {*(.eh_frame)} - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - _data = .; - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - _edata = .; - } > ram AT > flash - - .bss : - { - _bss_start = .; - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - _bss_end = .; - } > ram -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARM7-LPC214x-FATFS-GCC/Makefile b/demos/ARM7-LPC214x-FATFS-GCC/Makefile index d69954793..bb3b93ed4 100644 --- a/demos/ARM7-LPC214x-FATFS-GCC/Makefile +++ b/demos/ARM7-LPC214x-FATFS-GCC/Makefile @@ -39,19 +39,19 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT = ch.ld - -# Imported source files +# Imported source files and paths CHIBIOS = ../.. include $(CHIBIOS)/boards/OLIMEX_LPC_P2148/board.mk include $(CHIBIOS)/os/hal/platforms/LPC214x/platform.mk include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARM/port.mk +include $(CHIBIOS)/os/ports/GCC/ARM/LPC214x/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk include $(CHIBIOS)/ext/fatfs/fatfs.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/LPC2148.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ @@ -91,14 +91,12 @@ TCSRC = TCPPSRC = # List ASM source files here -ASMSRC = $(PORTASM) \ - $(CHIBIOS)/os/ports/GCC/ARM/LPC214x/vectors.s +ASMSRC = $(PORTASM) INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \ $(HALINC) $(PLATFORMINC) $(BOARDINC) \ $(FATFSINC) \ - $(CHIBIOS)/os/various \ - $(CHIBIOS)/os/ports/GCC/ARM/LPC214x + $(CHIBIOS)/os/various # # Project, sources and paths diff --git a/demos/ARM7-LPC214x-FATFS-GCC/ch.ld b/demos/ARM7-LPC214x-FATFS-GCC/ch.ld deleted file mode 100644 index 40683d14e..000000000 --- a/demos/ARM7-LPC214x-FATFS-GCC/ch.ld +++ /dev/null @@ -1,107 +0,0 @@ -/* - 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 . -*/ - -/* - * LPC2148 memory setup. - */ -__und_stack_size__ = 0x0004; -__abt_stack_size__ = 0x0004; -__fiq_stack_size__ = 0x0010; -__irq_stack_size__ = 0x0080; -__svc_stack_size__ = 0x0004; -__sys_stack_size__ = 0x0400; -__stacks_total_size__ = __und_stack_size__ + __abt_stack_size__ + __fiq_stack_size__ + __irq_stack_size__ + __svc_stack_size__ + __sys_stack_size__; - -MEMORY -{ - flash : org = 0x00000000, len = 512k - 12k - ram : org = 0x40000200, len = 32k - 0x200 - 288 -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; -__dma_start__ = 0x7FD00000; -__dma_size__ = 8k; -__dma_end__ = 0x7FD00000 + __dma_size__; - -SECTIONS -{ - . = 0; - - .text : ALIGN(16) SUBALIGN(16) - { - _text = .; - KEEP(*(vectors)) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.glue_7t) - *(.glue_7) - *(.gcc*) - *(.ctors) - *(.dtors) - } > flash - - .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} - - __exidx_start = .; - .ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > flash - __exidx_end = .; - - .eh_frame_hdr : {*(.eh_frame_hdr)} - - .eh_frame : ONLY_IF_RO {*(.eh_frame)} - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - _data = .; - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - _edata = .; - } > ram AT > flash - - .bss : - { - _bss_start = .; - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - _bss_end = .; - } > ram -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARM7-LPC214x-FATFS-GCC/main.c b/demos/ARM7-LPC214x-FATFS-GCC/main.c index bb8c012af..b5d7e82d6 100644 --- a/demos/ARM7-LPC214x-FATFS-GCC/main.c +++ b/demos/ARM7-LPC214x-FATFS-GCC/main.c @@ -273,8 +273,8 @@ int main(void) { evtInit(&evt, MS2ST(500)); /* Initializes an event timer object. */ evtStart(&evt); /* Starts the event timer. */ chEvtRegister(&evt.et_es, &el0, 0); /* Registers on the timer event source. */ - chEvtRegister(&MMCD1.mmc_inserted_event, &el1, 1); - chEvtRegister(&MMCD1.mmc_removed_event, &el2, 2); + chEvtRegister(&MMCD1.inserted_event, &el1, 1); + chEvtRegister(&MMCD1.removed_event, &el2, 2); while (TRUE)// chThdSleepMilliseconds(50); chEvtDispatch(evhndl, chEvtWaitOne(ALL_EVENTS)); return 0; diff --git a/demos/ARM7-LPC214x-G++/Makefile b/demos/ARM7-LPC214x-G++/Makefile index 118ec0cae..5d5723568 100644 --- a/demos/ARM7-LPC214x-G++/Makefile +++ b/demos/ARM7-LPC214x-G++/Makefile @@ -39,18 +39,18 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT = ch.ld - -# Imported source files +# Imported source files and paths CHIBIOS = ../.. include $(CHIBIOS)/boards/OLIMEX_LPC_P2148/board.mk include $(CHIBIOS)/os/hal/platforms/LPC214x/platform.mk include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARM/port.mk +include $(CHIBIOS)/os/ports/GCC/ARM/LPC214x/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/LPC2148.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ @@ -86,13 +86,11 @@ TCSRC = TCPPSRC = # List ASM source files here -ASMSRC = $(PORTASM) \ - $(CHIBIOS)/os/ports/GCC/ARM/LPC214x/vectors.s +ASMSRC = $(PORTASM) INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \ $(HALINC) $(PLATFORMINC) $(BOARDINC) \ - $(CHIBIOS)/os/various \ - $(CHIBIOS)/os/ports/GCC/ARM/LPC214x + $(CHIBIOS)/os/various # # Project, sources and paths diff --git a/demos/ARM7-LPC214x-G++/ch.ld b/demos/ARM7-LPC214x-G++/ch.ld deleted file mode 100644 index 40683d14e..000000000 --- a/demos/ARM7-LPC214x-G++/ch.ld +++ /dev/null @@ -1,107 +0,0 @@ -/* - 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 . -*/ - -/* - * LPC2148 memory setup. - */ -__und_stack_size__ = 0x0004; -__abt_stack_size__ = 0x0004; -__fiq_stack_size__ = 0x0010; -__irq_stack_size__ = 0x0080; -__svc_stack_size__ = 0x0004; -__sys_stack_size__ = 0x0400; -__stacks_total_size__ = __und_stack_size__ + __abt_stack_size__ + __fiq_stack_size__ + __irq_stack_size__ + __svc_stack_size__ + __sys_stack_size__; - -MEMORY -{ - flash : org = 0x00000000, len = 512k - 12k - ram : org = 0x40000200, len = 32k - 0x200 - 288 -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; -__dma_start__ = 0x7FD00000; -__dma_size__ = 8k; -__dma_end__ = 0x7FD00000 + __dma_size__; - -SECTIONS -{ - . = 0; - - .text : ALIGN(16) SUBALIGN(16) - { - _text = .; - KEEP(*(vectors)) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.glue_7t) - *(.glue_7) - *(.gcc*) - *(.ctors) - *(.dtors) - } > flash - - .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} - - __exidx_start = .; - .ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > flash - __exidx_end = .; - - .eh_frame_hdr : {*(.eh_frame_hdr)} - - .eh_frame : ONLY_IF_RO {*(.eh_frame)} - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - _data = .; - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - _edata = .; - } > ram AT > flash - - .bss : - { - _bss_start = .; - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - _bss_end = .; - } > ram -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARM7-LPC214x-GCC/Makefile b/demos/ARM7-LPC214x-GCC/Makefile index ac9a4d653..67116791e 100644 --- a/demos/ARM7-LPC214x-GCC/Makefile +++ b/demos/ARM7-LPC214x-GCC/Makefile @@ -39,18 +39,18 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT = ch.ld - -# Imported source files +# Imported source files and paths CHIBIOS = ../.. include $(CHIBIOS)/boards/OLIMEX_LPC_P2148/board.mk include $(CHIBIOS)/os/hal/platforms/LPC214x/platform.mk include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARM/port.mk +include $(CHIBIOS)/os/ports/GCC/ARM/LPC214x/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/LPC2148.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ @@ -86,13 +86,11 @@ TCSRC = TCPPSRC = # List ASM source files here -ASMSRC = $(PORTASM) \ - $(CHIBIOS)/os/ports/GCC/ARM/LPC214x/vectors.s +ASMSRC = $(PORTASM) INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \ $(HALINC) $(PLATFORMINC) $(BOARDINC) \ - $(CHIBIOS)/os/various \ - $(CHIBIOS)/os/ports/GCC/ARM/LPC214x + $(CHIBIOS)/os/various # # Project, sources and paths diff --git a/demos/ARM7-LPC214x-GCC/ch.ld b/demos/ARM7-LPC214x-GCC/ch.ld deleted file mode 100644 index 40683d14e..000000000 --- a/demos/ARM7-LPC214x-GCC/ch.ld +++ /dev/null @@ -1,107 +0,0 @@ -/* - 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 . -*/ - -/* - * LPC2148 memory setup. - */ -__und_stack_size__ = 0x0004; -__abt_stack_size__ = 0x0004; -__fiq_stack_size__ = 0x0010; -__irq_stack_size__ = 0x0080; -__svc_stack_size__ = 0x0004; -__sys_stack_size__ = 0x0400; -__stacks_total_size__ = __und_stack_size__ + __abt_stack_size__ + __fiq_stack_size__ + __irq_stack_size__ + __svc_stack_size__ + __sys_stack_size__; - -MEMORY -{ - flash : org = 0x00000000, len = 512k - 12k - ram : org = 0x40000200, len = 32k - 0x200 - 288 -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; -__dma_start__ = 0x7FD00000; -__dma_size__ = 8k; -__dma_end__ = 0x7FD00000 + __dma_size__; - -SECTIONS -{ - . = 0; - - .text : ALIGN(16) SUBALIGN(16) - { - _text = .; - KEEP(*(vectors)) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.glue_7t) - *(.glue_7) - *(.gcc*) - *(.ctors) - *(.dtors) - } > flash - - .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} - - __exidx_start = .; - .ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > flash - __exidx_end = .; - - .eh_frame_hdr : {*(.eh_frame_hdr)} - - .eh_frame : ONLY_IF_RO {*(.eh_frame)} - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - _data = .; - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - _edata = .; - } > ram AT > flash - - .bss : - { - _bss_start = .; - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - _bss_end = .; - } > ram -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARMCM0-LPC1114-LPCXPRESSO/Makefile b/demos/ARMCM0-LPC1114-LPCXPRESSO/Makefile index 7ed1b6e78..8f455c75f 100644 --- a/demos/ARMCM0-LPC1114-LPCXPRESSO/Makefile +++ b/demos/ARMCM0-LPC1114-LPCXPRESSO/Makefile @@ -47,9 +47,6 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT= ch.ld - # Imported source files CHIBIOS = ../.. include $(CHIBIOS)/boards/EA_LPCXPRESSO_BB_1114/board.mk @@ -59,6 +56,9 @@ include $(CHIBIOS)/os/ports/GCC/ARMCMx/LPC11xx/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/LPC1114.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ @@ -69,7 +69,7 @@ CSRC = $(PORTSRC) \ $(BOARDSRC) \ $(CHIBIOS)/os/various/evtimer.c \ $(CHIBIOS)/os/various/syscalls.c \ - main.c + main.c # C++ sources that can be compiled in ARM or THUMB mode depending on the global # setting. diff --git a/demos/ARMCM0-LPC1114-LPCXPRESSO/ch.ld b/demos/ARMCM0-LPC1114-LPCXPRESSO/ch.ld deleted file mode 100644 index cfc5ff3b6..000000000 --- a/demos/ARMCM0-LPC1114-LPCXPRESSO/ch.ld +++ /dev/null @@ -1,130 +0,0 @@ -/* - 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 . -*/ - -/* - * LPC1114 memory setup. - */ -__main_stack_size__ = 0x0100; -__process_stack_size__ = 0x0100; -__stacks_total_size__ = __main_stack_size__ + __process_stack_size__; - -MEMORY -{ - flash : org = 0x00000000, len = 32k - ram : org = 0x10000000, len = 8k -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; - -SECTIONS -{ - . = 0; - _text = .; - - startup : ALIGN(16) SUBALIGN(16) - { - KEEP(*(vectors)) - } > flash - - constructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE(__init_array_end = .); - } > flash - - destructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__fini_array_start = .); - KEEP(*(.fini_array)) - KEEP(*(SORT(.fini_array.*))) - PROVIDE(__fini_array_end = .); - } > flash - - .text : ALIGN(16) SUBALIGN(16) - { - *(.text.startup.*) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.glue_7t) - *(.glue_7) - *(.gcc*) - } > flash - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > flash - - .ARM.exidx : { - PROVIDE(__exidx_start = .); - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - PROVIDE(__exidx_end = .); - } > flash - - .eh_frame_hdr : - { - *(.eh_frame_hdr) - } > flash - - .eh_frame : ONLY_IF_RO - { - *(.eh_frame) - } > flash - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - PROVIDE(_data = .); - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - PROVIDE(_edata = .); - } > ram AT > flash - - .bss : - { - PROVIDE(_bss_start = .); - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - PROVIDE(_bss_end = .); - } > ram -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARMCM3-LPC1343-LPCXPRESSO/Makefile b/demos/ARMCM3-LPC1343-LPCXPRESSO/Makefile index dc3cc484f..f544b4f57 100644 --- a/demos/ARMCM3-LPC1343-LPCXPRESSO/Makefile +++ b/demos/ARMCM3-LPC1343-LPCXPRESSO/Makefile @@ -47,9 +47,6 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT= ch.ld - # Imported source files CHIBIOS = ../.. include $(CHIBIOS)/boards/EA_LPCXPRESSO_BB_1343/board.mk @@ -59,6 +56,9 @@ include $(CHIBIOS)/os/ports/GCC/ARMCMx/LPC13xx/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/LPC1343.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ @@ -69,7 +69,7 @@ CSRC = $(PORTSRC) \ $(BOARDSRC) \ $(CHIBIOS)/os/various/evtimer.c \ $(CHIBIOS)/os/various/syscalls.c \ - main.c + main.c # C++ sources that can be compiled in ARM or THUMB mode depending on the global # setting. diff --git a/demos/ARMCM3-LPC1343-LPCXPRESSO/ch.ld b/demos/ARMCM3-LPC1343-LPCXPRESSO/ch.ld deleted file mode 100644 index 703f09ca4..000000000 --- a/demos/ARMCM3-LPC1343-LPCXPRESSO/ch.ld +++ /dev/null @@ -1,130 +0,0 @@ -/* - 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 . -*/ - -/* - * LPC1343 memory setup. - */ -__main_stack_size__ = 0x0100; -__process_stack_size__ = 0x0100; -__stacks_total_size__ = __main_stack_size__ + __process_stack_size__; - -MEMORY -{ - flash : org = 0x00000000, len = 32k - ram : org = 0x10000000, len = 8k -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; - -SECTIONS -{ - . = 0; - _text = .; - - startup : ALIGN(16) SUBALIGN(16) - { - KEEP(*(vectors)) - } > flash - - constructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE(__init_array_end = .); - } > flash - - destructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__fini_array_start = .); - KEEP(*(.fini_array)) - KEEP(*(SORT(.fini_array.*))) - PROVIDE(__fini_array_end = .); - } > flash - - .text : ALIGN(16) SUBALIGN(16) - { - *(.text.startup.*) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.glue_7t) - *(.glue_7) - *(.gcc*) - } > flash - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > flash - - .ARM.exidx : { - PROVIDE(__exidx_start = .); - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - PROVIDE(__exidx_end = .); - } > flash - - .eh_frame_hdr : - { - *(.eh_frame_hdr) - } > flash - - .eh_frame : ONLY_IF_RO - { - *(.eh_frame) - } > flash - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - PROVIDE(_data = .); - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - PROVIDE(_edata = .); - } > ram AT > flash - - .bss : - { - PROVIDE(_bss_start = .); - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - PROVIDE(_bss_end = .); - } > ram -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARMCM3-STM32F100-DISCOVERY/Makefile b/demos/ARMCM3-STM32F100-DISCOVERY/Makefile index 792a57e5f..b34f9edf1 100644 --- a/demos/ARMCM3-STM32F100-DISCOVERY/Makefile +++ b/demos/ARMCM3-STM32F100-DISCOVERY/Makefile @@ -52,18 +52,18 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT= ch.ld - -# Imported source files +# Imported source files and paths CHIBIOS = ../.. include $(CHIBIOS)/boards/ST_STM32VL_DISCOVERY/board.mk -include $(CHIBIOS)/os/hal/platforms/STM32/platform.mk +include $(CHIBIOS)/os/hal/platforms/STM32F1xx/platform.mk include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32/port.mk +include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F1xx/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/STM32F100xB.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ diff --git a/demos/ARMCM3-STM32F100-DISCOVERY/ch.ld b/demos/ARMCM3-STM32F100-DISCOVERY/ch.ld deleted file mode 100644 index 83ea62bd5..000000000 --- a/demos/ARMCM3-STM32F100-DISCOVERY/ch.ld +++ /dev/null @@ -1,130 +0,0 @@ -/* - 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 . -*/ - -/* - * ST32F100xB memory setup. - */ -__main_stack_size__ = 0x0400; -__process_stack_size__ = 0x0400; -__stacks_total_size__ = __main_stack_size__ + __process_stack_size__; - -MEMORY -{ - flash : org = 0x08000000, len = 128k - ram : org = 0x20000000, len = 8k -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; - -SECTIONS -{ - . = 0; - _text = .; - - startup : ALIGN(16) SUBALIGN(16) - { - KEEP(*(vectors)) - } > flash - - constructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE(__init_array_end = .); - } > flash - - destructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__fini_array_start = .); - KEEP(*(.fini_array)) - KEEP(*(SORT(.fini_array.*))) - PROVIDE(__fini_array_end = .); - } > flash - - .text : ALIGN(16) SUBALIGN(16) - { - *(.text.startup.*) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.glue_7t) - *(.glue_7) - *(.gcc*) - } > flash - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > flash - - .ARM.exidx : { - PROVIDE(__exidx_start = .); - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - PROVIDE(__exidx_end = .); - } > flash - - .eh_frame_hdr : - { - *(.eh_frame_hdr) - } > flash - - .eh_frame : ONLY_IF_RO - { - *(.eh_frame) - } > flash - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - PROVIDE(_data = .); - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - PROVIDE(_edata = .); - } > ram AT > flash - - .bss : - { - PROVIDE(_bss_start = .); - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - PROVIDE(_bss_end = .); - } > ram -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARMCM3-STM32F103-FATFS/Makefile b/demos/ARMCM3-STM32F103-FATFS/Makefile index 5e7ac0c65..0d31e021a 100644 --- a/demos/ARMCM3-STM32F103-FATFS/Makefile +++ b/demos/ARMCM3-STM32F103-FATFS/Makefile @@ -52,19 +52,19 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT= ch.ld - -# Imported source files +# Imported source files and paths CHIBIOS = ../.. include $(CHIBIOS)/boards/OLIMEX_STM32_P103/board.mk -include $(CHIBIOS)/os/hal/platforms/STM32/platform.mk +include $(CHIBIOS)/os/hal/platforms/STM32F1xx/platform.mk include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32/port.mk +include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F1xx/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk include $(CHIBIOS)/ext/fatfs/fatfs.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/STM32F103xB.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ diff --git a/demos/ARMCM3-STM32F103-FATFS/ch.ld b/demos/ARMCM3-STM32F103-FATFS/ch.ld deleted file mode 100644 index 4d97e7682..000000000 --- a/demos/ARMCM3-STM32F103-FATFS/ch.ld +++ /dev/null @@ -1,130 +0,0 @@ -/* - 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 . -*/ - -/* - * ST32F103 memory setup. - */ -__main_stack_size__ = 0x0400; -__process_stack_size__ = 0x0400; -__stacks_total_size__ = __main_stack_size__ + __process_stack_size__; - -MEMORY -{ - flash : org = 0x08000000, len = 128k - ram : org = 0x20000000, len = 20k -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; - -SECTIONS -{ - . = 0; - _text = .; - - startup : ALIGN(16) SUBALIGN(16) - { - KEEP(*(vectors)) - } > flash - - constructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE(__init_array_end = .); - } > flash - - destructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__fini_array_start = .); - KEEP(*(.fini_array)) - KEEP(*(SORT(.fini_array.*))) - PROVIDE(__fini_array_end = .); - } > flash - - .text : ALIGN(16) SUBALIGN(16) - { - *(.text.startup.*) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.glue_7t) - *(.glue_7) - *(.gcc*) - } > flash - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > flash - - .ARM.exidx : { - PROVIDE(__exidx_start = .); - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - PROVIDE(__exidx_end = .); - } > flash - - .eh_frame_hdr : - { - *(.eh_frame_hdr) - } > flash - - .eh_frame : ONLY_IF_RO - { - *(.eh_frame) - } > flash - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - PROVIDE(_data = .); - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - PROVIDE(_edata = .); - } > ram AT > flash - - .bss : - { - PROVIDE(_bss_start = .); - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - PROVIDE(_bss_end = .); - } > ram -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARMCM3-STM32F103-G++/Makefile b/demos/ARMCM3-STM32F103-G++/Makefile index 9dba58699..e88957c87 100644 --- a/demos/ARMCM3-STM32F103-G++/Makefile +++ b/demos/ARMCM3-STM32F103-G++/Makefile @@ -52,18 +52,18 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT= ch.ld - -# Imported source files +# Imported source files and paths CHIBIOS = ../.. include $(CHIBIOS)/boards/OLIMEX_STM32_P103/board.mk -include $(CHIBIOS)/os/hal/platforms/STM32/platform.mk +include $(CHIBIOS)/os/hal/platforms/STM32F1xx/platform.mk include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32/port.mk +include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F1xx/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/STM32F103xB.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ diff --git a/demos/ARMCM3-STM32F103-G++/ch.ld b/demos/ARMCM3-STM32F103-G++/ch.ld deleted file mode 100644 index 4d97e7682..000000000 --- a/demos/ARMCM3-STM32F103-G++/ch.ld +++ /dev/null @@ -1,130 +0,0 @@ -/* - 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 . -*/ - -/* - * ST32F103 memory setup. - */ -__main_stack_size__ = 0x0400; -__process_stack_size__ = 0x0400; -__stacks_total_size__ = __main_stack_size__ + __process_stack_size__; - -MEMORY -{ - flash : org = 0x08000000, len = 128k - ram : org = 0x20000000, len = 20k -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; - -SECTIONS -{ - . = 0; - _text = .; - - startup : ALIGN(16) SUBALIGN(16) - { - KEEP(*(vectors)) - } > flash - - constructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE(__init_array_end = .); - } > flash - - destructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__fini_array_start = .); - KEEP(*(.fini_array)) - KEEP(*(SORT(.fini_array.*))) - PROVIDE(__fini_array_end = .); - } > flash - - .text : ALIGN(16) SUBALIGN(16) - { - *(.text.startup.*) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.glue_7t) - *(.glue_7) - *(.gcc*) - } > flash - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > flash - - .ARM.exidx : { - PROVIDE(__exidx_start = .); - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - PROVIDE(__exidx_end = .); - } > flash - - .eh_frame_hdr : - { - *(.eh_frame_hdr) - } > flash - - .eh_frame : ONLY_IF_RO - { - *(.eh_frame) - } > flash - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - PROVIDE(_data = .); - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - PROVIDE(_edata = .); - } > ram AT > flash - - .bss : - { - PROVIDE(_bss_start = .); - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - PROVIDE(_bss_end = .); - } > ram -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARMCM3-STM32F103/Makefile b/demos/ARMCM3-STM32F103/Makefile index 74f23b072..4d4ba0246 100644 --- a/demos/ARMCM3-STM32F103/Makefile +++ b/demos/ARMCM3-STM32F103/Makefile @@ -52,18 +52,18 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT= ch.ld - -# Imported source files +# Imported source files and paths CHIBIOS = ../.. include $(CHIBIOS)/boards/OLIMEX_STM32_P103/board.mk -include $(CHIBIOS)/os/hal/platforms/STM32/platform.mk +include $(CHIBIOS)/os/hal/platforms/STM32F1xx/platform.mk include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32/port.mk +include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F1xx/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/STM32F103xB.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ diff --git a/demos/ARMCM3-STM32F103/ch.ld b/demos/ARMCM3-STM32F103/ch.ld deleted file mode 100644 index 4d97e7682..000000000 --- a/demos/ARMCM3-STM32F103/ch.ld +++ /dev/null @@ -1,130 +0,0 @@ -/* - 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 . -*/ - -/* - * ST32F103 memory setup. - */ -__main_stack_size__ = 0x0400; -__process_stack_size__ = 0x0400; -__stacks_total_size__ = __main_stack_size__ + __process_stack_size__; - -MEMORY -{ - flash : org = 0x08000000, len = 128k - ram : org = 0x20000000, len = 20k -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; - -SECTIONS -{ - . = 0; - _text = .; - - startup : ALIGN(16) SUBALIGN(16) - { - KEEP(*(vectors)) - } > flash - - constructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE(__init_array_end = .); - } > flash - - destructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__fini_array_start = .); - KEEP(*(.fini_array)) - KEEP(*(SORT(.fini_array.*))) - PROVIDE(__fini_array_end = .); - } > flash - - .text : ALIGN(16) SUBALIGN(16) - { - *(.text.startup.*) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.glue_7t) - *(.glue_7) - *(.gcc*) - } > flash - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > flash - - .ARM.exidx : { - PROVIDE(__exidx_start = .); - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - PROVIDE(__exidx_end = .); - } > flash - - .eh_frame_hdr : - { - *(.eh_frame_hdr) - } > flash - - .eh_frame : ONLY_IF_RO - { - *(.eh_frame) - } > flash - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - PROVIDE(_data = .); - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - PROVIDE(_edata = .); - } > ram AT > flash - - .bss : - { - PROVIDE(_bss_start = .); - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - PROVIDE(_bss_end = .); - } > ram -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARMCM3-STM32F103ZG-FATFS/Makefile b/demos/ARMCM3-STM32F103ZG-FATFS/Makefile index 36b6c20c4..2485c272c 100644 --- a/demos/ARMCM3-STM32F103ZG-FATFS/Makefile +++ b/demos/ARMCM3-STM32F103ZG-FATFS/Makefile @@ -52,19 +52,19 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT= ch.ld - -# Imported source files +# Imported source files and paths CHIBIOS = ../.. include $(CHIBIOS)/boards/ST_STM3210E_EVAL/board.mk -include $(CHIBIOS)/os/hal/platforms/STM32/platform.mk +include $(CHIBIOS)/os/hal/platforms/STM32F1xx/platform.mk include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32/port.mk +include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F1xx/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk include $(CHIBIOS)/ext/fatfs/fatfs.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/STM32F103xG.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ @@ -78,7 +78,7 @@ CSRC = $(PORTSRC) \ $(CHIBIOS)/os/various/syscalls.c \ $(CHIBIOS)/os/various/shell.c \ $(CHIBIOS)/os/various/chprintf.c \ - main.c + main.c # C++ sources that can be compiled in ARM or THUMB mode depending on the global # setting. diff --git a/demos/ARMCM3-STM32F103ZG-FATFS/ch.ld b/demos/ARMCM3-STM32F103ZG-FATFS/ch.ld deleted file mode 100644 index 363ddce9f..000000000 --- a/demos/ARMCM3-STM32F103ZG-FATFS/ch.ld +++ /dev/null @@ -1,130 +0,0 @@ -/* - 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 . -*/ - -/* - * ST32F103xG memory setup. - */ -__main_stack_size__ = 0x0400; -__process_stack_size__ = 0x0400; -__stacks_total_size__ = __main_stack_size__ + __process_stack_size__; - -MEMORY -{ - flash : org = 0x08000000, len = 1m - ram : org = 0x20000000, len = 96k -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; - -SECTIONS -{ - . = 0; - _text = .; - - startup : ALIGN(16) SUBALIGN(16) - { - KEEP(*(vectors)) - } > flash - - constructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE(__init_array_end = .); - } > flash - - destructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__fini_array_start = .); - KEEP(*(.fini_array)) - KEEP(*(SORT(.fini_array.*))) - PROVIDE(__fini_array_end = .); - } > flash - - .text : ALIGN(16) SUBALIGN(16) - { - *(.text.startup.*) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.glue_7t) - *(.glue_7) - *(.gcc*) - } > flash - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > flash - - .ARM.exidx : { - PROVIDE(__exidx_start = .); - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - PROVIDE(__exidx_end = .); - } > flash - - .eh_frame_hdr : - { - *(.eh_frame_hdr) - } > flash - - .eh_frame : ONLY_IF_RO - { - *(.eh_frame) - } > flash - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - PROVIDE(_data = .); - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - PROVIDE(_edata = .); - } > ram AT > flash - - .bss : - { - PROVIDE(_bss_start = .); - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - PROVIDE(_bss_end = .); - } > ram -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARMCM3-STM32F107/Makefile b/demos/ARMCM3-STM32F107/Makefile index 9a7631be9..90607b250 100644 --- a/demos/ARMCM3-STM32F107/Makefile +++ b/demos/ARMCM3-STM32F107/Makefile @@ -52,18 +52,18 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT= ch.ld - -# Imported source files +# Imported source files and paths CHIBIOS = ../.. include $(CHIBIOS)/boards/OLIMEX_STM32_P107/board.mk -include $(CHIBIOS)/os/hal/platforms/STM32/platform.mk +include $(CHIBIOS)/os/hal/platforms/STM32F1xx/platform.mk include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32/port.mk +include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F1xx/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/STM32F107xC.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ @@ -74,7 +74,7 @@ CSRC = $(PORTSRC) \ $(BOARDSRC) \ $(CHIBIOS)/os/various/evtimer.c \ $(CHIBIOS)/os/various/syscalls.c \ - main.c + main.c # C++ sources that can be compiled in ARM or THUMB mode depending on the global # setting. diff --git a/demos/ARMCM3-STM32F107/ch.ld b/demos/ARMCM3-STM32F107/ch.ld deleted file mode 100644 index 1381b8b1c..000000000 --- a/demos/ARMCM3-STM32F107/ch.ld +++ /dev/null @@ -1,130 +0,0 @@ -/* - 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 . -*/ - -/* - * ST32F107 memory setup. - */ -__main_stack_size__ = 0x0200; -__process_stack_size__ = 0x0400; -__stacks_total_size__ = __main_stack_size__ + __process_stack_size__; - -MEMORY -{ - flash : org = 0x08000000, len = 256k - ram : org = 0x20000000, len = 64k -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; - -SECTIONS -{ - . = 0; - _text = .; - - startup : ALIGN(16) SUBALIGN(16) - { - KEEP(*(vectors)) - } > flash - - constructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE(__init_array_end = .); - } > flash - - destructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__fini_array_start = .); - KEEP(*(.fini_array)) - KEEP(*(SORT(.fini_array.*))) - PROVIDE(__fini_array_end = .); - } > flash - - .text : ALIGN(16) SUBALIGN(16) - { - *(.text.startup.*) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.glue_7t) - *(.glue_7) - *(.gcc*) - } > flash - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > flash - - .ARM.exidx : { - PROVIDE(__exidx_start = .); - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - PROVIDE(__exidx_end = .); - } > flash - - .eh_frame_hdr : - { - *(.eh_frame_hdr) - } > flash - - .eh_frame : ONLY_IF_RO - { - *(.eh_frame) - } > flash - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - PROVIDE(_data = .); - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - PROVIDE(_edata = .); - } > ram AT > flash - - .bss : - { - PROVIDE(_bss_start = .); - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - PROVIDE(_bss_end = .); - } > ram -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARMCM3-STM32L152-DISCOVERY/Makefile b/demos/ARMCM3-STM32L152-DISCOVERY/Makefile index 65ba0eece..603ceb433 100644 --- a/demos/ARMCM3-STM32L152-DISCOVERY/Makefile +++ b/demos/ARMCM3-STM32L152-DISCOVERY/Makefile @@ -52,10 +52,7 @@ endif # Define project name here PROJECT = ch -# Define linker script file here -LDSCRIPT= ch.ld - -# Imported source files +# Imported source files and paths CHIBIOS = ../.. include $(CHIBIOS)/boards/ST_STM32L_DISCOVERY/board.mk include $(CHIBIOS)/os/hal/platforms/STM32L1xx/platform.mk @@ -64,6 +61,9 @@ include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32L1xx/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include $(CHIBIOS)/test/test.mk +# Define linker script file here +LDSCRIPT= $(PORTLD)/STM32L152xB.ld + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ @@ -74,7 +74,7 @@ CSRC = $(PORTSRC) \ $(BOARDSRC) \ $(CHIBIOS)/os/various/evtimer.c \ $(CHIBIOS)/os/various/syscalls.c \ - main.c + main.c # C++ sources that can be compiled in ARM or THUMB mode depending on the global # setting. diff --git a/demos/ARMCM3-STM32L152-DISCOVERY/ch.ld b/demos/ARMCM3-STM32L152-DISCOVERY/ch.ld deleted file mode 100644 index 51237c594..000000000 --- a/demos/ARMCM3-STM32L152-DISCOVERY/ch.ld +++ /dev/null @@ -1,130 +0,0 @@ -/* - 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 . -*/ - -/* - * ST32L1152xB memory setup. - */ -__main_stack_size__ = 0x0400; -__process_stack_size__ = 0x0400; -__stacks_total_size__ = __main_stack_size__ + __process_stack_size__; - -MEMORY -{ - flash : org = 0x08000000, len = 128k - ram : org = 0x20000000, len = 16k -} - -__ram_start__ = ORIGIN(ram); -__ram_size__ = LENGTH(ram); -__ram_end__ = __ram_start__ + __ram_size__; - -SECTIONS -{ - . = 0; - _text = .; - - startup : ALIGN(16) SUBALIGN(16) - { - KEEP(*(vectors)) - } > flash - - constructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE(__init_array_end = .); - } > flash - - destructors : ALIGN(4) SUBALIGN(4) - { - PROVIDE(__fini_array_start = .); - KEEP(*(.fini_array)) - KEEP(*(SORT(.fini_array.*))) - PROVIDE(__fini_array_end = .); - } > flash - - .text : ALIGN(16) SUBALIGN(16) - { - *(.text.startup.*) - *(.text) - *(.text.*) - *(.rodata) - *(.rodata.*) - *(.glue_7t) - *(.glue_7) - *(.gcc*) - } > flash - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > flash - - .ARM.exidx : { - PROVIDE(__exidx_start = .); - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - PROVIDE(__exidx_end = .); - } > flash - - .eh_frame_hdr : - { - *(.eh_frame_hdr) - } > flash - - .eh_frame : ONLY_IF_RO - { - *(.eh_frame) - } > flash - - . = ALIGN(4); - _etext = .; - _textdata = _etext; - - .data : - { - PROVIDE(_data = .); - *(.data) - . = ALIGN(4); - *(.data.*) - . = ALIGN(4); - *(.ramtext) - . = ALIGN(4); - PROVIDE(_edata = .); - } > ram AT > flash - - .bss : - { - PROVIDE(_bss_start = .); - *(.bss) - . = ALIGN(4); - *(.bss.*) - . = ALIGN(4); - *(COMMON) - . = ALIGN(4); - PROVIDE(_bss_end = .); - } > ram -} - -PROVIDE(end = .); -_end = .; - -__heap_base__ = _end; -__heap_end__ = __ram_end__ - __stacks_total_size__; diff --git a/demos/ARMCM3-STM32L152-DISCOVERY/halconf.h b/demos/ARMCM3-STM32L152-DISCOVERY/halconf.h index f575e536f..3895ff70a 100644 --- a/demos/ARMCM3-STM32L152-DISCOVERY/halconf.h +++ b/demos/ARMCM3-STM32L152-DISCOVERY/halconf.h @@ -115,7 +115,7 @@ * @brief Enables the SERIAL over USB subsystem. */ #if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) -#define HAL_USE_SERIAL_USB FALSE +#define HAL_USE_SERIAL_USB TRUE #endif /** @@ -136,7 +136,7 @@ * @brief Enables the USB subsystem. */ #if !defined(HAL_USE_USB) || defined(__DOXYGEN__) -#define HAL_USE_USB FALSE +#define HAL_USE_USB TRUE #endif /*===========================================================================*/ diff --git a/docs/Doxyfile_chm b/docs/Doxyfile_chm index f6580b758..085a4d06a 100644 --- a/docs/Doxyfile_chm +++ b/docs/Doxyfile_chm @@ -647,10 +647,11 @@ INPUT = ../docs/src \ ../os/kernel/templates \ ../os/ports \ ../os/ports/GCC/ARM \ - ../os/ports/GCC/ARM\LPC214x \ - ../os/ports/GCC/ARM\AT91SAM7 \ + ../os/ports/GCC/ARM/LPC214x \ + ../os/ports/GCC/ARM/AT91SAM7 \ ../os/ports/GCC/ARMCMx \ - ../os/ports/GCC/ARMCMx/STM32 \ + ../os/ports/GCC/ARMCMx/STM32F1xx \ + ../os/ports/GCC/ARMCMx/STM32L1xx \ ../os/ports/GCC/ARMCMx/LPC11xx \ ../os/ports/GCC/ARMCMx/LPC13xx \ ../os/ports/GCC/PPC \ @@ -679,7 +680,8 @@ INPUT = ../docs/src \ ../os/hal/platforms/LPC214x/platform.dox \ ../os/hal/platforms/MSP430/platform.dox \ ../os/hal/platforms/SPC56x/platform.dox \ - ../os/hal/platforms/STM32/platform.dox \ + ../os/hal/platforms/STM32F1xx/platform.dox \ + ../os/hal/platforms/STM32L1xx/platform.dox \ ../os/hal/platforms/STM8L/platform.dox \ ../os/hal/platforms/STM8S/platform.dox \ ../os/various \ @@ -742,7 +744,8 @@ RECURSIVE = NO # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = ../os/hal/platforms/STM32/stm32f10x.h \ +EXCLUDE = ../os/hal/platforms/STM32F1xx/stm32f10x.h \ + ../os/hal/platforms/STM32L1xx/stm32l10x.h \ ../os/hal/platforms/STM8/stm8s.h \ ../os/hal/platforms/STM8/stm8s_type.h \ ../os/hal/platforms/LPC11xx/LPC11xx.h \ diff --git a/docs/Doxyfile_html b/docs/Doxyfile_html index 0d2e6e31b..7e85cd9ed 100644 --- a/docs/Doxyfile_html +++ b/docs/Doxyfile_html @@ -647,10 +647,11 @@ INPUT = ../docs/src \ ../os/kernel/templates \ ../os/ports \ ../os/ports/GCC/ARM \ - ../os/ports/GCC/ARM\LPC214x \ - ../os/ports/GCC/ARM\AT91SAM7 \ + ../os/ports/GCC/ARM/LPC214x \ + ../os/ports/GCC/ARM/AT91SAM7 \ ../os/ports/GCC/ARMCMx \ - ../os/ports/GCC/ARMCMx/STM32 \ + ../os/ports/GCC/ARMCMx/STM32F1xx \ + ../os/ports/GCC/ARMCMx/STM32L1xx \ ../os/ports/GCC/ARMCMx/LPC11xx \ ../os/ports/GCC/ARMCMx/LPC13xx \ ../os/ports/GCC/PPC \ @@ -679,7 +680,8 @@ INPUT = ../docs/src \ ../os/hal/platforms/LPC214x/platform.dox \ ../os/hal/platforms/MSP430/platform.dox \ ../os/hal/platforms/SPC56x/platform.dox \ - ../os/hal/platforms/STM32/platform.dox \ + ../os/hal/platforms/STM32F1xx/platform.dox \ + ../os/hal/platforms/STM32L1xx/platform.dox \ ../os/hal/platforms/STM8L/platform.dox \ ../os/hal/platforms/STM8S/platform.dox \ ../os/various \ @@ -742,7 +744,8 @@ RECURSIVE = NO # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = ../os/hal/platforms/STM32/stm32f10x.h \ +EXCLUDE = ../os/hal/platforms/STM32F1xx/stm32f10x.h \ + ../os/hal/platforms/STM32L1xx/stm32l10x.h \ ../os/hal/platforms/STM8/stm8s.h \ ../os/hal/platforms/STM8/stm8s_type.h \ ../os/hal/platforms/LPC11xx/LPC11xx.h \ diff --git a/docs/rsc/header_chm.html b/docs/rsc/header_chm.html index 7900d8bf2..a27feac41 100644 --- a/docs/rsc/header_chm.html +++ b/docs/rsc/header_chm.html @@ -13,7 +13,7 @@ -
ChibiOS/RT 2.3.1
+
ChibiOS/RT 2.3.3
diff --git a/docs/rsc/header_html.html b/docs/rsc/header_html.html index 8e3887f51..46b76b597 100644 --- a/docs/rsc/header_html.html +++ b/docs/rsc/header_html.html @@ -20,7 +20,7 @@ $(document).ready(initResizable); -
ChibiOS/RT
2.3.1
+
ChibiOS/RT
2.3.3