aboutsummaryrefslogtreecommitdiff
path: root/apps/px4io/i2c.c
diff options
context:
space:
mode:
authorLorenz Meier <lm@inf.ethz.ch>2013-04-28 01:17:12 +0200
committerLorenz Meier <lm@inf.ethz.ch>2013-04-28 01:30:14 +0200
commitf57439b90e23de260259dec051d3e2ead2d61c8c (patch)
tree5cd778d2cf0c9afb2851ab9042bbecc5b742a497 /apps/px4io/i2c.c
parent8040b9b96e8f7c07aa981150c33f850096062f70 (diff)
downloadpx4-firmware-f57439b90e23de260259dec051d3e2ead2d61c8c.tar.gz
px4-firmware-f57439b90e23de260259dec051d3e2ead2d61c8c.tar.bz2
px4-firmware-f57439b90e23de260259dec051d3e2ead2d61c8c.zip
Moved all drivers to new world, PX4IO completely in new world
Diffstat (limited to 'apps/px4io/i2c.c')
-rw-r--r--apps/px4io/i2c.c340
1 files changed, 0 insertions, 340 deletions
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 <stdint.h>
-
-#include <nuttx/arch.h>
-#include <arch/board/board.h>
-#include <stm32_i2c.h>
-#include <stm32_dma.h>
-
-//#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, &regs, &reg_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);
-}