X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=src%2Fstm%2Fao_i2c_stm.c;h=c02bc5a535169f0922b638f4947756c8d5133256;hp=779e227503110971abcb3c8aa14744ef1594b1ed;hb=119a829e58aff5dd7801fe7ef8cae886bf31fec1;hpb=f221c78e6237e0a118ebe85c25e433fe16a7735d diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 779e2275..c02bc5a5 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -3,7 +3,8 @@ * * 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 @@ -36,7 +37,7 @@ static uint16_t ao_i2c_addr[STM_NUM_I2C]; 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 */ @@ -74,6 +75,9 @@ uint8_t ao_i2c_mutex[STM_NUM_I2C]; #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 @@ -137,7 +141,7 @@ ao_i2c_ev_isr(uint8_t index) 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]); @@ -185,7 +189,6 @@ uint8_t 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; @@ -196,15 +199,13 @@ ao_i2c_start(uint8_t index, uint16_t addr) 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; } @@ -239,10 +240,7 @@ uint8_t 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; @@ -260,18 +258,16 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) (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(); @@ -279,7 +275,7 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); ao_i2c_wait_stop(index); } - return TRUE; + return true; } void @@ -304,12 +300,10 @@ uint8_t 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; @@ -327,14 +321,12 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) 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, @@ -342,13 +334,24 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) 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); @@ -357,13 +360,11 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) 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);