diff options
Diffstat (limited to 'src/stm/ao_spi_stm.c')
| -rw-r--r-- | src/stm/ao_spi_stm.c | 198 | 
1 files changed, 90 insertions, 108 deletions
| diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 3b5773b6..2b6834fd 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -84,12 +84,48 @@ validate_spi(struct stm_spi *stm_spi, int which, uint16_t len)  #define validate_spi(stm_spi, which, len) do { (void) (which); (void) (len); } while (0)  #endif +static void +ao_spi_run(uint8_t id, uint8_t which, uint16_t len) +{ +	struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi; +	uint8_t	mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index; +	uint8_t	miso_dma_index = ao_spi_stm_info[id].miso_dma_index; + +	validate_spi(stm_spi, which, len); + +	stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | +			(0 << STM_SPI_CR2_RXNEIE) | +			(0 << STM_SPI_CR2_ERRIE) | +			(0 << STM_SPI_CR2_SSOE) | +			(1 << STM_SPI_CR2_TXDMAEN) | +			(1 << STM_SPI_CR2_RXDMAEN)); + +	ao_dma_start(miso_dma_index); +	ao_dma_start(mosi_dma_index); + +	ao_arch_critical( +		while (!ao_dma_done[miso_dma_index]) +			ao_sleep(&ao_dma_done[miso_dma_index]); +		); + +	while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0); +	while (stm_spi->sr & (1 << STM_SPI_SR_BSY)); + +	validate_spi(stm_spi, which+1, len); + +	stm_spi->cr2 = 0; + +	ao_dma_done_transfer(mosi_dma_index); +	ao_dma_done_transfer(miso_dma_index); +} +  void  ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)  { -	struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; -	uint8_t	mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; -	uint8_t	miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index; +	uint8_t id = AO_SPI_INDEX(spi_index); +	struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi; +	uint8_t	mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index; +	uint8_t	miso_dma_index = ao_spi_stm_info[id].miso_dma_index;  	/* Set up the transmit DMA to deliver data */  	ao_dma_set_transfer(mosi_dma_index, @@ -105,9 +141,6 @@ ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)  			    (0 << STM_DMA_CCR_CIRC) |  			    (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); -	/* Clear RXNE */ -	(void) stm_spi->dr; -  	/* Set up the receive DMA -- when this is done, we know the SPI unit  	 * is idle. Without this, we'd have to poll waiting for the BSY bit to  	 * be cleared @@ -124,28 +157,17 @@ ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)  			    (0 << STM_DMA_CCR_PINC) |  			    (0 << STM_DMA_CCR_CIRC) |  			    (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); -	stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | -			(0 << STM_SPI_CR2_RXNEIE) | -			(0 << STM_SPI_CR2_ERRIE) | -			(0 << STM_SPI_CR2_SSOE) | -			(1 << STM_SPI_CR2_TXDMAEN) | -			(1 << STM_SPI_CR2_RXDMAEN)); -	ao_dma_start(miso_dma_index); -	ao_dma_start(mosi_dma_index); -	ao_arch_critical( -		while (!ao_dma_done[miso_dma_index]) -			ao_sleep(&ao_dma_done[miso_dma_index]); -		); -	ao_dma_done_transfer(mosi_dma_index); -	ao_dma_done_transfer(miso_dma_index); + +	ao_spi_run(id, 1, len);  }  void  ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)  { -	struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; -	uint8_t	mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; -	uint8_t	miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index; +	uint8_t id = AO_SPI_INDEX(spi_index); +	struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi; +	uint8_t	mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index; +	uint8_t	miso_dma_index = ao_spi_stm_info[id].miso_dma_index;  	/* Set up the transmit DMA to deliver data */  	ao_dma_set_transfer(mosi_dma_index, @@ -161,9 +183,6 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)  			    (0 << STM_DMA_CCR_CIRC) |  			    (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); -	/* Clear RXNE */ -	(void) stm_spi->dr; -  	/* Set up the receive DMA -- when this is done, we know the SPI unit  	 * is idle. Without this, we'd have to poll waiting for the BSY bit to  	 * be cleared @@ -180,27 +199,16 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)  			    (0 << STM_DMA_CCR_PINC) |  			    (0 << STM_DMA_CCR_CIRC) |  			    (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); -	stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | -			(0 << STM_SPI_CR2_RXNEIE) | -			(0 << STM_SPI_CR2_ERRIE) | -			(0 << STM_SPI_CR2_SSOE) | -			(1 << STM_SPI_CR2_TXDMAEN) | -			(1 << STM_SPI_CR2_RXDMAEN)); -	ao_dma_start(miso_dma_index); -	ao_dma_start(mosi_dma_index); -	ao_arch_critical( -		while (!ao_dma_done[miso_dma_index]) -			ao_sleep(&ao_dma_done[miso_dma_index]); -		); -	ao_dma_done_transfer(mosi_dma_index); -	ao_dma_done_transfer(miso_dma_index); + +	ao_spi_run(id, 3, len);  }  void  ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index)  { -	uint8_t		*b = block; -	struct stm_spi	*stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; +	uint8_t		id = AO_SPI_INDEX(spi_index); +	const uint8_t	*b = block; +	struct stm_spi	*stm_spi = ao_spi_stm_info[id].stm_spi;  	stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |  			(0 << STM_SPI_CR2_RXNEIE) | @@ -208,22 +216,28 @@ ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index)  			(0 << STM_SPI_CR2_SSOE) |  			(0 << STM_SPI_CR2_TXDMAEN) |  			(0 << STM_SPI_CR2_RXDMAEN)); - -	/* Clear RXNE */ -	(void) stm_spi->dr; - +	validate_spi(stm_spi, 7, len);  	while (len--) {  		while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));  		stm_spi->dr = *b++;  	} +	while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0) +		; +	while (stm_spi->sr & (1 << STM_SPI_SR_BSY)) +		; +	/* Clear the OVR flag */ +	(void) stm_spi->dr; +	(void) stm_spi->sr; +	validate_spi(stm_spi, 8, len);  }  void  ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)  { -	struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; -	uint8_t	mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; -	uint8_t	miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index; +	uint8_t		id = AO_SPI_INDEX(spi_index); +	struct stm_spi	*stm_spi = ao_spi_stm_info[id].stm_spi; +	uint8_t		mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index; +	uint8_t		miso_dma_index = ao_spi_stm_info[id].miso_dma_index;  	spi_dev_null = 0xff; @@ -241,9 +255,6 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)  			    (0 << STM_DMA_CCR_CIRC) |  			    (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); -	/* Clear RXNE */ -	(void) stm_spi->dr; -  	/* Set up the receive DMA to capture data */  	ao_dma_set_transfer(miso_dma_index,  			    &stm_spi->dr, @@ -258,31 +269,16 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)  			    (0 << STM_DMA_CCR_CIRC) |  			    (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); -	stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | -			(0 << STM_SPI_CR2_RXNEIE) | -			(0 << STM_SPI_CR2_ERRIE) | -			(0 << STM_SPI_CR2_SSOE) | -			(1 << STM_SPI_CR2_TXDMAEN) | -			(1 << STM_SPI_CR2_RXDMAEN)); -	ao_dma_start(miso_dma_index); -	ao_dma_start(mosi_dma_index); - -	/* Wait until the SPI unit is done */ -	ao_arch_critical( -		while (!ao_dma_done[miso_dma_index]) -			ao_sleep(&ao_dma_done[miso_dma_index]); -		); - -	ao_dma_done_transfer(mosi_dma_index); -	ao_dma_done_transfer(miso_dma_index); +	ao_spi_run(id, 9, len);  }  void  ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)  { -	struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; -	uint8_t	mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; -	uint8_t	miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index; +	uint8_t		id = AO_SPI_INDEX(spi_index); +	struct stm_spi	*stm_spi = ao_spi_stm_info[id].stm_spi; +	uint8_t		mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index; +	uint8_t		miso_dma_index = ao_spi_stm_info[id].miso_dma_index;  	/* Set up transmit DMA to send data */  	ao_dma_set_transfer(mosi_dma_index, @@ -298,9 +294,6 @@ ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)  			    (0 << STM_DMA_CCR_CIRC) |  			    (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); -	/* Clear RXNE */ -	(void) stm_spi->dr; -  	/* Set up the receive DMA to capture data */  	ao_dma_set_transfer(miso_dma_index,  			    &stm_spi->dr, @@ -314,24 +307,7 @@ ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)  			    (0 << STM_DMA_CCR_PINC) |  			    (0 << STM_DMA_CCR_CIRC) |  			    (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); - -	stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | -			(0 << STM_SPI_CR2_RXNEIE) | -			(0 << STM_SPI_CR2_ERRIE) | -			(0 << STM_SPI_CR2_SSOE) | -			(1 << STM_SPI_CR2_TXDMAEN) | -			(1 << STM_SPI_CR2_RXDMAEN)); -	ao_dma_start(miso_dma_index); -	ao_dma_start(mosi_dma_index); - -	/* Wait until the SPI unit is done */ -	ao_arch_critical( -		while (!ao_dma_done[miso_dma_index]) -			ao_sleep(&ao_dma_done[miso_dma_index]); -		); - -	ao_dma_done_transfer(mosi_dma_index); -	ao_dma_done_transfer(miso_dma_index); +	ao_spi_run(id, 11, len);  }  static void @@ -426,20 +402,7 @@ ao_spi_config(uint8_t spi_index, uint32_t speed)  {  	uint8_t		id = AO_SPI_INDEX(spi_index);  	struct stm_spi	*stm_spi = ao_spi_stm_info[id].stm_spi; -	stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) |			/* Three wire mode */ -			(0 << STM_SPI_CR1_BIDIOE) | -			(0 << STM_SPI_CR1_CRCEN) |			/* CRC disabled */ -			(0 << STM_SPI_CR1_CRCNEXT) | -			(0 << STM_SPI_CR1_DFF) | -			(0 << STM_SPI_CR1_RXONLY) | -			(1 << STM_SPI_CR1_SSM) |        		/* Software SS handling */ -			(1 << STM_SPI_CR1_SSI) |			/*  ... */ -			(0 << STM_SPI_CR1_LSBFIRST) |			/* Big endian */ -			(1 << STM_SPI_CR1_SPE) |			/* Enable SPI unit */ -			(speed << STM_SPI_CR1_BR) |	/* baud rate to pclk/4 */ -			(1 << STM_SPI_CR1_MSTR) | -			(0 << STM_SPI_CR1_CPOL) |			/* Format 0 */ -			(0 << STM_SPI_CR1_CPHA)); +  	if (spi_index != ao_spi_index[id]) {  		/* Disable old config @@ -454,6 +417,21 @@ ao_spi_config(uint8_t spi_index, uint32_t speed)  		 */  		ao_spi_index[id] = spi_index;  	} +	stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) |		/* Three wire mode */ +			(0 << STM_SPI_CR1_BIDIOE) | +			(0 << STM_SPI_CR1_CRCEN) |		/* CRC disabled */ +			(0 << STM_SPI_CR1_CRCNEXT) | +			(0 << STM_SPI_CR1_DFF) | +			(0 << STM_SPI_CR1_RXONLY) | +			(1 << STM_SPI_CR1_SSM) |        	/* Software SS handling */ +			(1 << STM_SPI_CR1_SSI) |		/*  ... */ +			(0 << STM_SPI_CR1_LSBFIRST) |		/* Big endian */ +			(1 << STM_SPI_CR1_SPE) |		/* Enable SPI unit */ +			(speed << STM_SPI_CR1_BR) |		/* baud rate to pclk/4 */ +			(1 << STM_SPI_CR1_MSTR) | +			(0 << STM_SPI_CR1_CPOL) |		/* Format 0 */ +			(0 << STM_SPI_CR1_CPHA)); +	validate_spi(stm_spi, 13, 0);  }  uint8_t @@ -471,6 +449,7 @@ void  ao_spi_get(uint8_t spi_index, uint32_t speed)  {  	uint8_t		id = AO_SPI_INDEX(spi_index); +  	ao_mutex_get(&ao_spi_mutex[id]);  	ao_spi_config(spi_index, speed);  } @@ -494,13 +473,16 @@ ao_spi_channel_init(uint8_t spi_index)  	ao_spi_disable_index(spi_index);  	stm_spi->cr1 = 0; -	(void) stm_spi->sr;  	stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |  			(0 << STM_SPI_CR2_RXNEIE) |  			(0 << STM_SPI_CR2_ERRIE) |  			(0 << STM_SPI_CR2_SSOE) |  			(0 << STM_SPI_CR2_TXDMAEN) |  			(0 << STM_SPI_CR2_RXDMAEN)); + +	/* Clear any pending data and error flags */ +	(void) stm_spi->dr; +	(void) stm_spi->sr;  }  #if DEBUG | 
