*
* This program 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; version 2 of the License.
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
uint8_t ao_i2c_mutex[STM_NUM_I2C];
# define I2C_HIGH_SLOW 5000 /* ns, 100kHz clock */
-#ifdef MEGAMETRUM
+#ifdef TELEMEGA
# define I2C_HIGH_FAST 2000 /* ns, 167kHz clock */
#else
# define I2C_HIGH_FAST 1000 /* ns, 333kHz clock */
#if AO_PCLK1 == 16000000
# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_16_MHZ
#endif
+#if AO_PCLK1 == 24000000
+# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_24_MHZ
+#endif
#if AO_PCLK1 == 32000000
# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_32_MHZ
#endif
ao_wakeup(&ao_i2c_state[index]);
}
if (sr1 & (1 << STM_I2C_SR1_RXNE)) {
- if (ao_i2c_recv_len[index]) {
+ if (ao_i2c_recv_len[index]) {
*(ao_i2c_recv_data[index]++) = stm_i2c->dr;
if (!--ao_i2c_recv_len[index])
ao_wakeup(&ao_i2c_recv_len[index]);
ao_i2c_start(uint8_t index, uint16_t addr)
{
struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
- uint32_t sr1, sr2;
int t;
ao_i2c_state[index] = I2C_IDLE;
if (!(stm_i2c->cr1 & (1 << STM_I2C_CR1_START)))
break;
}
- ao_alarm(AO_MS_TO_TICKS(250));
ao_arch_block_interrupts();
stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN);
ao_i2c_ev_isr(index);
while (ao_i2c_state[index] == I2C_IDLE)
- if (ao_sleep(&ao_i2c_state[index]))
+ if (ao_sleep_for(&ao_i2c_state[index], AO_MS_TO_TICKS(250)))
break;
ao_arch_release_interrupts();
- ao_clear_alarm();
return ao_i2c_state[index] == I2C_RUNNING;
}
ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop)
{
struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
- uint8_t *b = block;
- uint32_t sr1;
uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index;
- int t;
/* Clear any pending ADDR bit */
(void) stm_i2c->sr2;
(0 << STM_DMA_CCR_PINC) |
(0 << STM_DMA_CCR_CIRC) |
(STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
-
+
ao_dma_start(tx_dma_index);
- ao_alarm(1 + len);
ao_arch_block_interrupts();
while (!ao_dma_done[tx_dma_index])
- if (ao_sleep(&ao_dma_done[tx_dma_index]))
+ if (ao_sleep_for(&ao_dma_done[tx_dma_index], 1 + len))
break;
- ao_clear_alarm();
ao_dma_done_transfer(tx_dma_index);
stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN);
while ((stm_i2c->sr1 & (1 << STM_I2C_SR1_BTF)) == 0)
- if (ao_sleep(&ao_i2c_state[index]))
+ if (ao_sleep_for(&ao_i2c_state[index], 1 + len))
break;
stm_i2c->cr2 = AO_STM_I2C_CR2;
ao_arch_release_interrupts();
stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP);
ao_i2c_wait_stop(index);
}
- return TRUE;
+ return true;
}
-void
+static void
ao_i2c_recv_dma_isr(int index)
{
int i;
ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop)
{
struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c;
- uint8_t *b = block;
- int t;
- uint8_t ret = TRUE;
+ uint8_t ret = true;
if (len == 0)
- return TRUE;
+ return true;
if (len == 1) {
ao_i2c_recv_data[index] = block;
ao_i2c_recv_len[index] = 1;
if (stop)
stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP);
- ao_alarm(1);
ao_arch_block_interrupts();
while (ao_i2c_recv_len[index])
- if (ao_sleep(&ao_i2c_recv_len[index]))
+ if (ao_sleep_for(&ao_i2c_recv_len[index], 1))
break;
ao_arch_release_interrupts();
ret = ao_i2c_recv_len[index] == 0;
- ao_clear_alarm();
} else {
uint8_t rx_dma_index = ao_i2c_stm_info[index].rx_dma_index;
ao_dma_set_transfer(rx_dma_index,
block,
len,
(0 << STM_DMA_CCR_MEM2MEM) |
- (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) |
(STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
(STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
(1 << STM_DMA_CCR_MINC) |
(0 << STM_DMA_CCR_PINC) |
(0 << STM_DMA_CCR_CIRC) |
(STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
+
+ /* XXX ao_i2c_recv_dma_isr hasn't ever been used, so it
+ * doesn't appear to be necessary. Testing with a device
+ * that uses i2c would really be useful here to discover
+ * whether this function is necessary or not.
+ */
+#if 0
+ ao_dma_set_isr(rx_dma_index, ao_i2c_recv_dma_isr);
+#else
+ (void) ao_i2c_recv_dma_isr;
+#endif
stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK);
stm_i2c->cr2 = AO_STM_I2C_CR2 |
(1 << STM_I2C_CR2_DMAEN) | (1 << STM_I2C_CR2_LAST);
ao_i2c_wait_addr(index);
ao_dma_start(rx_dma_index);
- ao_alarm(len);
ao_arch_block_interrupts();
while (!ao_dma_done[rx_dma_index])
- if (ao_sleep(&ao_dma_done[rx_dma_index]))
+ if (ao_sleep_for(&ao_dma_done[rx_dma_index], len))
break;
ao_arch_release_interrupts();
- ao_clear_alarm();
ret = ao_dma_done[rx_dma_index];
ao_dma_done_transfer(rx_dma_index);
stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP);
return ret;
}
-void
+static void
ao_i2c_channel_init(uint8_t index)
{
struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c;