From f57439b90e23de260259dec051d3e2ead2d61c8c Mon Sep 17 00:00:00 2001 From: Lorenz Meier Date: Sun, 28 Apr 2013 01:17:12 +0200 Subject: Moved all drivers to new world, PX4IO completely in new world --- apps/px4io/i2c.c | 340 ------------------------------------------------------- 1 file changed, 340 deletions(-) delete mode 100644 apps/px4io/i2c.c (limited to 'apps/px4io/i2c.c') diff --git a/apps/px4io/i2c.c b/apps/px4io/i2c.c deleted file mode 100644 index 4485daa5b..000000000 --- a/apps/px4io/i2c.c +++ /dev/null @@ -1,340 +0,0 @@ -/**************************************************************************** - * - * Copyright (C) 2012 PX4 Development Team. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name PX4 nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/** - * @file i2c.c - * - * I2C communication for the PX4IO module. - */ - -#include - -#include -#include -#include -#include - -//#define DEBUG -#include "px4io.h" - -/* - * I2C register definitions. - */ -#define I2C_BASE STM32_I2C1_BASE - -#define REG(_reg) (*(volatile uint32_t *)(I2C_BASE + _reg)) - -#define rCR1 REG(STM32_I2C_CR1_OFFSET) -#define rCR2 REG(STM32_I2C_CR2_OFFSET) -#define rOAR1 REG(STM32_I2C_OAR1_OFFSET) -#define rOAR2 REG(STM32_I2C_OAR2_OFFSET) -#define rDR REG(STM32_I2C_DR_OFFSET) -#define rSR1 REG(STM32_I2C_SR1_OFFSET) -#define rSR2 REG(STM32_I2C_SR2_OFFSET) -#define rCCR REG(STM32_I2C_CCR_OFFSET) -#define rTRISE REG(STM32_I2C_TRISE_OFFSET) - -static int i2c_interrupt(int irq, void *context); -static void i2c_rx_setup(void); -static void i2c_tx_setup(void); -static void i2c_rx_complete(void); -static void i2c_tx_complete(void); - -static DMA_HANDLE rx_dma; -static DMA_HANDLE tx_dma; - -static uint8_t rx_buf[68]; -static unsigned rx_len; - -static const uint8_t junk_buf[] = { 0xff, 0xff, 0xff, 0xff }; - -static const uint8_t *tx_buf = junk_buf; -static unsigned tx_len = sizeof(junk_buf); -unsigned tx_count; - -static uint8_t selected_page; -static uint8_t selected_offset; - -enum { - DIR_NONE = 0, - DIR_TX = 1, - DIR_RX = 2 -} direction; - -void -i2c_init(void) -{ - debug("i2c init"); - - /* allocate DMA handles and initialise DMA */ - rx_dma = stm32_dmachannel(DMACHAN_I2C1_RX); - i2c_rx_setup(); - tx_dma = stm32_dmachannel(DMACHAN_I2C1_TX); - i2c_tx_setup(); - - /* enable the i2c block clock and reset it */ - modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_I2C1EN); - modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_I2C1RST); - modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST, 0); - - /* configure the i2c GPIOs */ - stm32_configgpio(GPIO_I2C1_SCL); - stm32_configgpio(GPIO_I2C1_SDA); - - /* soft-reset the block */ - rCR1 |= I2C_CR1_SWRST; - rCR1 = 0; - - /* set for DMA operation */ - rCR2 |= I2C_CR2_ITEVFEN |I2C_CR2_ITERREN | I2C_CR2_DMAEN; - - /* set the frequency value in CR2 */ - rCR2 &= ~I2C_CR2_FREQ_MASK; - rCR2 |= STM32_PCLK1_FREQUENCY / 1000000; - - /* set divisor and risetime for fast mode */ - uint16_t result = STM32_PCLK1_FREQUENCY / (400000 * 25); - if (result < 1) - result = 1; - result = 3; - rCCR &= ~I2C_CCR_CCR_MASK; - rCCR |= I2C_CCR_DUTY | I2C_CCR_FS | result; - rTRISE = (uint16_t)((((STM32_PCLK1_FREQUENCY / 1000000) * 300) / 1000) + 1); - - /* set our device address */ - rOAR1 = 0x1a << 1; - - /* enable event interrupts */ - irq_attach(STM32_IRQ_I2C1EV, i2c_interrupt); - irq_attach(STM32_IRQ_I2C1ER, i2c_interrupt); - up_enable_irq(STM32_IRQ_I2C1EV); - up_enable_irq(STM32_IRQ_I2C1ER); - - /* and enable the I2C port */ - rCR1 |= I2C_CR1_ACK | I2C_CR1_PE; - -#ifdef DEBUG - i2c_dump(); -#endif -} - - -/* - reset the I2C bus - used to recover from lockups - */ -void i2c_reset(void) -{ - rCR1 |= I2C_CR1_SWRST; - rCR1 = 0; - - /* set for DMA operation */ - rCR2 |= I2C_CR2_ITEVFEN |I2C_CR2_ITERREN | I2C_CR2_DMAEN; - - /* set the frequency value in CR2 */ - rCR2 &= ~I2C_CR2_FREQ_MASK; - rCR2 |= STM32_PCLK1_FREQUENCY / 1000000; - - /* set divisor and risetime for fast mode */ - uint16_t result = STM32_PCLK1_FREQUENCY / (400000 * 25); - if (result < 1) - result = 1; - result = 3; - rCCR &= ~I2C_CCR_CCR_MASK; - rCCR |= I2C_CCR_DUTY | I2C_CCR_FS | result; - rTRISE = (uint16_t)((((STM32_PCLK1_FREQUENCY / 1000000) * 300) / 1000) + 1); - - /* set our device address */ - rOAR1 = 0x1a << 1; - - /* and enable the I2C port */ - rCR1 |= I2C_CR1_ACK | I2C_CR1_PE; -} - -static int -i2c_interrupt(int irq, FAR void *context) -{ - uint16_t sr1 = rSR1; - - if (sr1 & (I2C_SR1_STOPF | I2C_SR1_AF | I2C_SR1_ADDR)) { - - if (sr1 & I2C_SR1_STOPF) { - /* write to CR1 to clear STOPF */ - (void)rSR1; /* as recommended, re-read SR1 */ - rCR1 |= I2C_CR1_PE; - } - - /* DMA never stops, so we should do that now */ - switch (direction) { - case DIR_TX: - i2c_tx_complete(); - break; - case DIR_RX: - i2c_rx_complete(); - break; - default: - /* not currently transferring - must be a new txn */ - break; - } - direction = DIR_NONE; - } - - if (sr1 & I2C_SR1_ADDR) { - - /* clear ADDR to ack our selection and get direction */ - (void)rSR1; /* as recommended, re-read SR1 */ - uint16_t sr2 = rSR2; - - if (sr2 & I2C_SR2_TRA) { - /* we are the transmitter */ - - direction = DIR_TX; - - } else { - /* we are the receiver */ - - direction = DIR_RX; - } - } - - /* clear any errors that might need it (this handles AF as well */ - if (sr1 & I2C_SR1_ERRORMASK) - rSR1 = 0; - - return 0; -} - -static void -i2c_rx_setup(void) -{ - /* - * Note that we configure DMA in circular mode; this means that a too-long - * transfer will overwrite the buffer, but that avoids us having to deal with - * bailing out of a transaction while the master is still babbling at us. - */ - rx_len = 0; - stm32_dmasetup(rx_dma, (uintptr_t)&rDR, (uintptr_t)&rx_buf[0], sizeof(rx_buf), - DMA_CCR_CIRC | - DMA_CCR_MINC | - DMA_CCR_PSIZE_32BITS | - DMA_CCR_MSIZE_8BITS | - DMA_CCR_PRIMED); - - stm32_dmastart(rx_dma, NULL, NULL, false); -} - -static void -i2c_rx_complete(void) -{ - rx_len = sizeof(rx_buf) - stm32_dmaresidual(rx_dma); - stm32_dmastop(rx_dma); - - if (rx_len >= 2) { - selected_page = rx_buf[0]; - selected_offset = rx_buf[1]; - - /* work out how many registers are being written */ - unsigned count = (rx_len - 2) / 2; - if (count > 0) { - registers_set(selected_page, selected_offset, (const uint16_t *)&rx_buf[2], count); - } else { - /* no registers written, must be an address cycle */ - uint16_t *regs; - unsigned reg_count; - - /* work out which registers are being addressed */ - int ret = registers_get(selected_page, selected_offset, ®s, ®_count); - if (ret == 0) { - tx_buf = (uint8_t *)regs; - tx_len = reg_count * 2; - } else { - tx_buf = junk_buf; - tx_len = sizeof(junk_buf); - } - - /* disable interrupts while reconfiguring DMA for the selected registers */ - irqstate_t flags = irqsave(); - - stm32_dmastop(tx_dma); - i2c_tx_setup(); - - irqrestore(flags); - } - } - - /* prepare for the next transaction */ - i2c_rx_setup(); -} - -static void -i2c_tx_setup(void) -{ - /* - * Note that we configure DMA in circular mode; this means that a too-long - * transfer will copy the buffer more than once, but that avoids us having - * to deal with bailing out of a transaction while the master is still - * babbling at us. - */ - stm32_dmasetup(tx_dma, (uintptr_t)&rDR, (uintptr_t)&tx_buf[0], tx_len, - DMA_CCR_DIR | - DMA_CCR_CIRC | - DMA_CCR_MINC | - DMA_CCR_PSIZE_8BITS | - DMA_CCR_MSIZE_8BITS | - DMA_CCR_PRIMED); - - stm32_dmastart(tx_dma, NULL, NULL, false); -} - -static void -i2c_tx_complete(void) -{ - tx_count = tx_len - stm32_dmaresidual(tx_dma); - stm32_dmastop(tx_dma); - - /* for debug purposes, save the length of the last transmit as seen by the DMA */ - - /* leave tx_buf/tx_len alone, so that a retry will see the same data */ - - /* prepare for the next transaction */ - i2c_tx_setup(); -} - -void -i2c_dump(void) -{ - debug("CR1 0x%08x CR2 0x%08x", rCR1, rCR2); - debug("OAR1 0x%08x OAR2 0x%08x", rOAR1, rOAR2); - debug("CCR 0x%08x TRISE 0x%08x", rCCR, rTRISE); - debug("SR1 0x%08x SR2 0x%08x", rSR1, rSR2); -} -- cgit v1.2.3