diff options
| -rw-r--r-- | src/drivers/ao_hmc5883.c | 22 | ||||
| -rw-r--r-- | src/drivers/ao_mpu6000.c | 16 | ||||
| -rw-r--r-- | src/stm/ao_arch_funcs.h | 13 | ||||
| -rw-r--r-- | src/stm/ao_i2c_stm.c | 328 | 
4 files changed, 327 insertions, 52 deletions
| diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index 0077daf9..43d04f70 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -48,13 +48,10 @@ ao_hmc5883_write(uint8_t addr, uint8_t *data, uint8_t len)  {  	ao_i2c_get(AO_HMC5883_I2C_INDEX);  	ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); -	ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX); +	ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX, FALSE);  	ao_hmc5883_addr_reg = addr; -	if (len) { -		ao_i2c_send(data, len, AO_HMC5883_I2C_INDEX); -		ao_hmc5883_update_addr(len); -	} -	ao_i2c_stop(AO_HMC5883_I2C_INDEX); +	ao_i2c_send(data, len, AO_HMC5883_I2C_INDEX, TRUE); +	ao_hmc5883_update_addr(len);  	ao_i2c_put(AO_HMC5883_I2C_INDEX);  } @@ -64,15 +61,12 @@ ao_hmc5883_read(uint8_t addr, uint8_t *data, uint8_t len)  	ao_i2c_get(AO_HMC5883_I2C_INDEX);  	if (addr != ao_hmc5883_addr_reg) {  		ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); -		ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX); +		ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX, FALSE);  		ao_hmc5883_addr_reg = addr;  	}  	ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); -	if (len) { -		ao_i2c_recv(data, len, AO_HMC5883_I2C_INDEX); -		ao_hmc5883_update_addr(len); -	} -	ao_i2c_stop(AO_HMC5883_I2C_INDEX); +	ao_i2c_recv(data, len, AO_HMC5883_I2C_INDEX, TRUE); +	ao_hmc5883_update_addr(len);  	ao_i2c_put(AO_HMC5883_I2C_INDEX);  } @@ -92,7 +86,7 @@ ao_hmc5883_setup(void)  	ao_i2c_get(AO_HMC5883_I2C_INDEX);  	present = ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); -	ao_i2c_stop(AO_HMC5883_I2C_INDEX); +	ao_i2c_recv(NULL, 0, AO_HMC5883_I2C_INDEX, TRUE);  	ao_i2c_put(AO_HMC5883_I2C_INDEX);  	if (!present)  		return 0; @@ -109,7 +103,7 @@ ao_hmc5883_show(void)  	{  		ao_i2c_get(AO_HMC5883_I2C_INDEX);  		data = ao_i2c_start(AO_HMC5883_I2C_INDEX, addr << 1); -		ao_i2c_stop(AO_HMC5883_I2C_INDEX); +		ao_i2c_recv(NULL, 0, AO_HMC5883_I2C_INDEX, TRUE);  		ao_i2c_put(AO_HMC5883_I2C_INDEX);  		if (data)  			printf("address %02x responds\n", addr << 1); diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index 290f1390..d7f67d6e 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -35,10 +35,8 @@ ao_mpu6000_write(uint8_t addr, uint8_t *data, uint8_t len)  {  	ao_i2c_get(AO_MPU6000_I2C_INDEX);  	ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); -	ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX); -	if (len) -		ao_i2c_send(data, len, AO_MPU6000_I2C_INDEX); -	ao_i2c_stop(AO_MPU6000_I2C_INDEX); +	ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE); +	ao_i2c_send(data, len, AO_MPU6000_I2C_INDEX, TRUE);  	ao_i2c_put(AO_MPU6000_I2C_INDEX);  } @@ -47,11 +45,9 @@ ao_mpu6000_read(uint8_t addr, uint8_t *data, uint8_t len)  {  	ao_i2c_get(AO_MPU6000_I2C_INDEX);  	ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); -	ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX); +	ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE);  	ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_READ); -	if (len) -		ao_i2c_recv(data, len, AO_MPU6000_I2C_INDEX); -	ao_i2c_stop(AO_MPU6000_I2C_INDEX); +	ao_i2c_recv(data, len, AO_MPU6000_I2C_INDEX, TRUE);  	ao_i2c_put(AO_MPU6000_I2C_INDEX);  } @@ -78,9 +74,11 @@ ao_mpu6000_show(void)  	ao_mpu6000_read(MPU6000_WHO_AM_I, data, 1);  	printf ("mpu6000 WHO_AM_I: %02x\n", data[0]); -	ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, data, 1); +#if 0 +	ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, data, 14);  	for (i = 0; i < 14; i++)  		printf ("reg %02x: %02x\n", i + MPU6000_ACCEL_XOUT_H, data[i]); +#endif  }  static const struct ao_cmds ao_mpu6000_cmds[] = { diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 3027b337..447042dd 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -105,7 +105,7 @@ ao_dma_set_transfer(uint8_t 		index,  		    uint32_t		ccr);  void -ao_dma_set_isr(uint8_t index, void (*isr)(void)); +ao_dma_set_isr(uint8_t index, void (*isr)(int index));  void  ao_dma_start(uint8_t index); @@ -131,16 +131,13 @@ uint8_t  ao_i2c_start(uint8_t i2c_index, uint16_t address);  void -ao_i2c_stop(uint8_t i2c_index); - -void  ao_i2c_put(uint8_t i2c_index); -void -ao_i2c_send(void *block, uint16_t len, uint8_t i2c_index); +uint8_t +ao_i2c_send(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop); -void -ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index); +uint8_t +ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop);  void  ao_i2c_init(void); diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 0717be98..9ab001d7 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -23,6 +23,8 @@ struct ao_i2c_stm_info {  	struct stm_i2c	*stm_i2c;  }; +#define I2C_TIMEOUT	100 +  #define I2C_IDLE	0  #define I2C_RUNNING	1  #define I2C_ERROR	2 @@ -47,7 +49,7 @@ uint8_t 	ao_i2c_mutex[STM_NUM_I2C];  			(1 << STM_I2C_CR1_PE))  #define AO_STM_I2C_CR2  ((0 << STM_I2C_CR2_LAST) |			\ -			 (1 << STM_I2C_CR2_DMAEN) |			\ +			 (0 << STM_I2C_CR2_DMAEN) |			\  			 (0 << STM_I2C_CR2_ITBUFEN) |			\  			 (0 << STM_I2C_CR2_ITEVTEN) |			\  			 (0 << STM_I2C_CR2_ITERREN) |			\ @@ -66,20 +68,44 @@ static const struct ao_i2c_stm_info	ao_i2c_stm_info[STM_NUM_I2C] = {  	},  }; +static uint8_t	*ao_i2c_recv_data[STM_NUM_I2C]; +static uint16_t	ao_i2c_recv_len[STM_NUM_I2C]; +static uint16_t	ev_count; +  static void  ao_i2c_ev_isr(uint8_t index)  {  	struct stm_i2c	*stm_i2c = ao_i2c_stm_info[index].stm_i2c;  	uint32_t	sr1; +	++ev_count;  	sr1 = stm_i2c->sr1;  	if (sr1 & (1 << STM_I2C_SR1_SB))  		stm_i2c->dr = ao_i2c_addr[index];  	if (sr1 & (1 << STM_I2C_SR1_ADDR)) { -		(void) stm_i2c->sr2; +		stm_i2c->cr2 &= ~(1 << STM_I2C_CR2_ITEVTEN);  		ao_i2c_state[index] = I2C_RUNNING;  		ao_wakeup(&ao_i2c_state[index]);  	} +	if (sr1 & (1 << STM_I2C_SR1_BTF)) { +		stm_i2c->cr2 &= ~(1 << STM_I2C_CR2_ITEVTEN); +		ao_wakeup(&ao_i2c_state[index]); +	} +#if 0 +	if (sr1 & (1 << STM_I2C_SR1_RXNE)) { +		if (ao_i2c_recv_len[index]) {			 +			switch (--ao_i2c_recv_len[index]) { +			case 0: +				ao_wakeup(&ao_i2c_recv_len[index]); +				break; +			case 1: +				stm_i2c->cr1 &= ~(1 << STM_I2C_CR1_ACK); +				break; +			} +			*(ao_i2c_recv_data[index]++) = stm_i2c->dr; +		} +	} +#endif  }  void stm_i2c1_ev_isr(void) { ao_i2c_ev_isr(0); } @@ -118,38 +144,205 @@ ao_i2c_put(uint8_t index)  	ao_mutex_put(&ao_i2c_mutex[index]);  } +static inline uint32_t in_sr1(char *where, struct stm_i2c *stm_i2c) { +	uint32_t	sr1 = stm_i2c->sr1; +	printf("%s: sr1: %x\n", where, sr1); flush(); +	return sr1; +} + +static inline uint32_t in_sr2(char *where, struct stm_i2c *stm_i2c) { +	uint32_t	sr2 = stm_i2c->sr2; +	printf("%s: sr2: %x\n", where, sr2); flush(); +	return sr2; +} + +static inline void out_cr1(char *where, struct stm_i2c *stm_i2c, uint32_t cr1) { +	printf("%s: cr1: %x\n", where, cr1); flush(); +	stm_i2c->cr1 = cr1; +} + +static inline uint32_t in_cr1(char *where, struct stm_i2c *stm_i2c) { +	uint32_t	cr1 = stm_i2c->cr1; +	printf("%s: cr1: %x\n", where, cr1); flush(); +	return cr1; +} + +static inline void out_cr2(char *where, struct stm_i2c *stm_i2c, uint32_t cr2) { +	printf("%s: cr2: %x\n", where, cr2); flush(); +	stm_i2c->cr2 = cr2; +} + +static inline uint32_t in_dr(char *where, struct stm_i2c *stm_i2c) { +	uint32_t	dr = stm_i2c->dr; +	printf("%s: dr: %x\n", where, dr); flush(); +	return dr; +} + +static inline void out_dr(char *where, struct stm_i2c *stm_i2c, uint32_t dr) { +	printf("%s: dr: %x\n", where, dr); flush(); +	stm_i2c->dr = dr; +} +  uint8_t -ao_i2c_start(uint8_t index, uint16_t addr) +ao_i2c_check_status(char *where, uint8_t index, uint32_t sr1_want, uint32_t sr2_want)  {  	struct stm_i2c	*stm_i2c = ao_i2c_stm_info[index].stm_i2c; +	uint32_t	sr1_got, sr2_got; + +	if (sr1_want) { +		sr1_got = in_sr1(where, stm_i2c); +		if ((sr1_got & sr1_want) != sr1_want) { +			printf ("%s: sr1 wanted %x got %x\n", where, sr1_want, sr1_got); +			return FALSE; +		} +	} +	if (sr2_want) { +		sr2_got = in_sr2(where, stm_i2c); +		if ((sr2_got & sr2_want) != sr2_want) { +			printf ("%s: sr1 wanted %x got %x\n", +				where, sr2_want, sr2_got); +			return FALSE; +		} +	} +	printf ("%s: got sr1 %x and sr2 %x\n", where, sr1_want, sr2_want); +	return TRUE; +} + +static uint8_t +ao_i2c_check_idle(uint8_t index) +{ +	struct stm_i2c	*stm_i2c = ao_i2c_stm_info[index].stm_i2c; +	uint32_t	s = 0; +	int		t; +	for (t = 0; t < I2C_TIMEOUT; t++) { +		if (!ao_i2c_check_status("check idle", index, +					 0, +					 (1 << STM_I2C_SR2_BUSY))) +		{ +			break; +		} +		ao_yield(); +	} +	if (t == I2C_TIMEOUT) +		return FALSE; +	return TRUE; +} + +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; + +#if 0 +	if (!ao_i2c_check_idle(index)) { +		printf ("i2c busy\n"); +		return FALSE; +	} +#endif +		  	ao_i2c_state[index] = I2C_IDLE;  	ao_i2c_addr[index] = addr; -	stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN); -	stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START); -	ao_arch_critical( -		while (ao_i2c_state[index] == I2C_IDLE) -			ao_sleep(&ao_i2c_state[index]); -		); +#if 0 +	out_cr2("start", stm_i2c, AO_STM_I2C_CR2); +	out_cr1("start", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START)); +	for (t = 0; t < I2C_TIMEOUT; t++) { +		if (ao_i2c_check_status("waiting for start", +					index, +					(1 << STM_I2C_SR1_SB), +					(1 << STM_I2C_SR2_BUSY) | +					(1 << STM_I2C_SR2_MSL))) +			break; +		ao_yield(); +	} +	if (t == I2C_TIMEOUT) { +		printf ("No start mode\n"); +		return FALSE; +	} +	out_dr("address", stm_i2c, addr); +	if (addr & 1) { +		sr1 = (1 << STM_I2C_SR1_ADDR); +		sr2 = (1 << STM_I2C_SR2_BUSY) | (1 << STM_I2C_SR2_MSL); +	} else { +		sr1 = (1 << STM_I2C_SR1_TXE) | (1 << STM_I2C_SR1_ADDR); +		sr2 = (1 << STM_I2C_SR2_TRA) | (1 << STM_I2C_SR2_BUSY) | (1 << STM_I2C_SR2_MSL); +	} +		 +	for (t = 0; t < I2C_TIMEOUT; t++) { +		if (ao_i2c_check_status("waiting for addr", +					index, +					sr1, sr2)) +			break; +		ao_yield(); +	} +	if (t == I2C_TIMEOUT) { +		printf ("Set addr failed\n"); +		return FALSE; +	} +	ao_i2c_state[index] = I2C_RUNNING; +#else +	out_cr2("start", stm_i2c, AO_STM_I2C_CR2); +	out_cr1("start", stm_i2c, +		AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START)); +	out_cr2("start", stm_i2c, +		AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); +	ao_alarm(1); +	cli(); +	while (ao_i2c_state[index] == I2C_IDLE) +		if (ao_sleep(&ao_i2c_state[index])) +			break; +	sei(); +	ao_clear_alarm(); +#endif  	return ao_i2c_state[index] == I2C_RUNNING;  } -void +static void  ao_i2c_stop(uint8_t index)  {  	struct stm_i2c	*stm_i2c = ao_i2c_stm_info[index].stm_i2c;  	ao_i2c_state[index] = I2C_IDLE; -	stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); +	out_cr2("enable isr", stm_i2c, +		AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); +	ev_count = 0; +	out_cr1("stop", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + +	/* XXX check to see if there is an interrupt here */ +	while (in_cr1("stop", stm_i2c) & (1 << STM_I2C_CR1_STOP)) +		ao_yield(); +	printf ("ev_count in stop: %d\n", ev_count);  } -void -ao_i2c_send(void *block, uint16_t len, uint8_t index) +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; +	int		t; + +#if 0 +	while (len--) { +		for (t = 0; t < I2C_TIMEOUT; t++) { +			if (ao_i2c_check_status("send", index, +						(1 << STM_I2C_SR1_TXE), +						0)) +				break; +			ao_yield(); +		} +		if (t == I2C_TIMEOUT) +			return FALSE; +		out_dr("send", stm_i2c, *b++); +	} +#else  	uint8_t		tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; -	stm_i2c->cr2 &= ~(1 << STM_I2C_CR2_LAST); +	/* Clear any pending ADDR bit */ +	in_sr2("send clear addr", stm_i2c); +	out_cr2("send", stm_i2c, AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_DMAEN));  	ao_dma_set_transfer(tx_dma_index,  			    &stm_i2c->dr,  			    block, @@ -164,20 +357,104 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index)  			    (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));  	ao_dma_start(tx_dma_index); -	ao_arch_critical( -		while (!ao_dma_done[tx_dma_index]) -			ao_sleep(&ao_dma_done[tx_dma_index]); -		); +	ao_alarm(1 + len); +	cli(); +	while (!ao_dma_done[tx_dma_index]) +		if (ao_sleep(&ao_dma_done[tx_dma_index])) { +			printf ("send timeout\n"); +			break; +		}  	ao_dma_done_transfer(tx_dma_index); +	out_cr2("send enable isr", stm_i2c, +		AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); +	while ((in_sr1("send_btf", stm_i2c) & (1 << STM_I2C_SR1_BTF)) == 0) +		if (ao_sleep(&ao_i2c_state[index])) +			break; +	out_cr2("send disable isr", stm_i2c, AO_STM_I2C_CR2); +	sei(); +#endif +	if (stop) +		ao_i2c_stop(index); +	return TRUE;  }  void -ao_i2c_recv(void *block, uint16_t len, uint8_t index) +ao_i2c_recv_dma_isr(int index) +{ +	int		i; +	struct stm_i2c	*stm_i2c = NULL; + +	for (i = 0; i < STM_NUM_I2C; i++) +		if (index == ao_i2c_stm_info[i].rx_dma_index) { +			stm_i2c = ao_i2c_stm_info[i].stm_i2c; +			break; +		} +	if (!stm_i2c) +		return; +	stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_LAST); +	ao_dma_done[index] = 1; +	ao_wakeup(&ao_dma_done[index]); +} + +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		rx_dma_index = ao_i2c_stm_info[index].rx_dma_index; +	uint8_t		*b = block; +	int		t; + +	switch (len) { +	case 0: +		return TRUE; +	case 1: +		out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1); +		/* Clear any pending ADDR bit */ +		in_sr2("clear addr", stm_i2c); +		out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); +		break; +	case 2: +		/* Clear any pending ADDR bit */ +		out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_POS)); +		if (in_sr1("clear addr", stm_i2c) & (1 << STM_I2C_SR1_ADDR)) +			in_sr2("clear addr", stm_i2c); +		out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); +		break; +	default: +//		out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK) | (1 << STM_I2C_CR1_POS)); +		out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK)); +		/* Clear any pending ADDR bit */ +		if (in_sr1("clear addr", stm_i2c) & (1 << STM_I2C_SR1_ADDR)) +			in_sr2("clear addr", stm_i2c); +		break; +	} + +	while (len--) { +		for (t = 0; t < I2C_TIMEOUT; t++) { +			if (in_sr1("recv", stm_i2c) & (1 << STM_I2C_SR1_RXNE)) +				break; +			ao_yield(); +		} +		if (t == I2C_TIMEOUT) +			return FALSE; +		*b++ = in_dr("recv", stm_i2c); +		if (len == 2 && stop) { +			out_cr1("clear ack", stm_i2c, +//				AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP) | (1 << STM_I2C_CR1_POS)); +				AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); +		} +	} +	if (stop) { +		for (t = 0; t < I2C_TIMEOUT; t++) { +			if (!(in_cr1("recv stop", stm_i2c) & (1 << STM_I2C_CR1_STOP))) +				break; +			ao_yield(); +		} +		if (t == I2C_TIMEOUT) +			return FALSE; +	} -	stm_i2c->cr2 |= (1 << STM_I2C_CR2_LAST); +#if 0 +	uint8_t		rx_dma_index = ao_i2c_stm_info[index].rx_dma_index;  	ao_dma_set_transfer(rx_dma_index,  			    &stm_i2c->dr,  			    block, @@ -190,6 +467,13 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index)  			    (0 << STM_DMA_CCR_PINC) |  			    (0 << STM_DMA_CCR_CIRC) |  			    (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); +	if (len >= 2) { +		stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK) | (1 << STM_I2C_CR1_POS); +		stm_i2c->cr2 = AO_STM_I2C_CR2; +	} else { +		stm_i2c->cr1 = AO_STM_I2C_CR1; +		stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_LAST); +	}  	ao_dma_start(rx_dma_index);  	cli(); @@ -197,6 +481,7 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index)  		ao_sleep(&ao_dma_done[rx_dma_index]);  	sei();  	ao_dma_done_transfer(rx_dma_index); +#endif  }  void @@ -219,6 +504,7 @@ ao_i2c_channel_init(uint8_t index)  			(0 << STM_I2C_CCR_DUTY) |  			(20 << STM_I2C_CCR_CCR)); +  	stm_i2c->cr1 = AO_STM_I2C_CR1;  } | 
