diff options
| -rw-r--r-- | src/core/ao.h | 7 | ||||
| -rw-r--r-- | src/drivers/ao_ms5607.c | 164 | ||||
| -rw-r--r-- | src/drivers/ao_ms5607.h | 38 | ||||
| -rw-r--r-- | src/megametrum-v0.1/Makefile | 7 | ||||
| -rw-r--r-- | src/megametrum-v0.1/ao_megametrum.c | 3 | ||||
| -rw-r--r-- | src/megametrum-v0.1/ao_pins.h | 5 | ||||
| -rw-r--r-- | src/stm-demo/Makefile | 5 | ||||
| -rw-r--r-- | src/stm-demo/ao_demo.c | 79 | ||||
| -rw-r--r-- | src/stm-demo/ao_pins.h | 5 | ||||
| -rw-r--r-- | src/stm/ao_arch_funcs.h | 28 | ||||
| -rw-r--r-- | src/stm/ao_dma_stm.c | 99 | ||||
| -rw-r--r-- | src/stm/ao_spi_stm.c | 240 | ||||
| -rw-r--r-- | src/stm/stm32l.h | 180 | 
13 files changed, 847 insertions, 13 deletions
| diff --git a/src/core/ao.h b/src/core/ao.h index 080cadb2..67efa437 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -114,6 +114,7 @@ ao_start_scheduler(void);  #define AO_PANIC_USB		10	/* Trying to send USB packet while busy */  #define AO_PANIC_BT		11	/* Communications with bluetooth device failed */  #define AO_PANIC_STACK		12	/* Stack overflow */ +#define AO_PANIC_SPI		13	/* SPI communication failure */  /* Stop the operating system, beeping and blinking the reason */  void @@ -1895,4 +1896,10 @@ int32_t ao_freq_to_set(int32_t freq, int32_t cal);  #include <ao_arch_funcs.h> +/* + * ao_ms5607.c + */ + +void ao_ms5607_init(void); +  #endif /* _AO_H_ */ diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c new file mode 100644 index 00000000..970fea1e --- /dev/null +++ b/src/drivers/ao_ms5607.c @@ -0,0 +1,164 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> +#include "ao_ms5607.h" + +#define AO_MS5607_CS_GPIO	stm_gpioc +#define AO_MS5607_CS		4 +#define AO_MS5607_CS_MASK	(1 << AO_MS5607_CS) +#define AO_MS5607_SPI_INDEX	(STM_SPI_INDEX(1)) + +struct ms5607_prom { +	uint16_t	reserved; +	uint16_t	sens; +	uint16_t	off; +	uint16_t	tcs; +	uint16_t	tco; +	uint16_t	tref; +	uint16_t	tempsens; +	uint16_t	crc; +}; + +static struct ms5607_prom ms5607_prom; + +static void +ao_ms5607_start(void) { +	ao_spi_get(AO_MS5607_SPI_INDEX); +	stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 0); +} + +static void +ao_ms5607_stop(void) { +	stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); +	ao_spi_put(AO_MS5607_SPI_INDEX); +} + +static void +ao_ms5607_reset(void) { +	uint8_t	cmd; + +	cmd = AO_MS5607_RESET; +	ao_ms5607_start(); +	ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); +	ao_ms5607_stop(); +} + +static uint16_t +ao_ms5607_prom_read(uint8_t addr) +{ +	uint8_t	cmd = AO_MS5607_PROM_READ(addr); +	uint8_t d[2]; + +	ao_ms5607_start(); +	ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); +	ao_spi_recv(d, 2, AO_MS5607_SPI_INDEX); +	ao_ms5607_stop(); +	return ((uint16_t) d[0] << 8) | (uint16_t) d[1]; +} + +static void +ao_ms5607_init_chip(void) { +	uint8_t		addr; +	uint16_t	*prom; +	ao_ms5607_reset(); +	prom = &ms5607_prom.reserved; + +	for (addr = 0; addr <= 7; addr++) +		prom[addr] = ao_ms5607_prom_read(addr); +} + +static uint32_t +ao_ms5607_convert(uint8_t cmd) { +	uint8_t	reply[3]; +	uint8_t read; + +	ao_ms5607_start(); +	ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); +	ao_ms5607_stop(); + +	ao_delay(AO_MS_TO_TICKS(200)); + +	ao_ms5607_start(); +	read = AO_MS5607_ADC_READ; +	ao_spi_send(&read, 1, AO_MS5607_SPI_INDEX); +	ao_spi_recv(&reply, 3, AO_MS5607_SPI_INDEX); +	ao_ms5607_stop(); + +	return ((uint32_t) reply[0] << 16) | ((uint32_t) reply[1] << 8) | (uint32_t) reply[2]; +} + +static void +ao_ms5607_dump(void) +{ +	uint8_t	addr; +	uint32_t d1, d2; +	int32_t	dT; +	int32_t TEMP; +	int64_t OFF; +	int64_t SENS; +	int32_t P; + +	ao_ms5607_init_chip(); +	printf ("reserved: %d\n", ms5607_prom.reserved); +	printf ("sens:     %d\n", ms5607_prom.sens); +	printf ("off:      %d\n", ms5607_prom.off); +	printf ("tcs:      %d\n", ms5607_prom.tcs); +	printf ("tco:      %d\n", ms5607_prom.tco); +	printf ("tref:     %d\n", ms5607_prom.tref); +	printf ("tempsens: %d\n", ms5607_prom.tempsens); +	printf ("crc:      %d\n", ms5607_prom.crc); +	d1 =  ao_ms5607_convert(AO_MS5607_CONVERT_D1_4096); +	printf ("Conversion D1: %d\n", d1); +	d2 =  ao_ms5607_convert(AO_MS5607_CONVERT_D2_4096); +	printf ("Conversion D2: %d\n", d2); + +	dT = d2 - ((int32_t) ms5607_prom.tref << 8); +	 +	TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23); + +	OFF = ((int64_t) ms5607_prom.off << 17) + (((int64_t) ms5607_prom.tco * dT) >> 6); + +	SENS = ((int64_t) ms5607_prom.sens << 16) + (((int64_t) ms5607_prom.tcs * dT) >> 7); + +	if (TEMP < 2000) { +		int32_t	T2 = ((int64_t) dT * (int64_t) dT) >> 31; +		int32_t TEMPM = TEMP - 2000; +		int64_t OFF2 = (61 * (int64_t) TEMPM * (int64_t) TEMPM) >> 4; +		int64_t SENS2 = 2 * (int64_t) TEMPM * (int64_t) TEMPM; +	} + +	P = ((((int64_t) d1 * SENS) >> 21) - OFF) >> 15; +	 +	printf ("Temperature: %d", TEMP); +	printf ("Pressure %d\n", P); +} + +__code struct ao_cmds ao_ms5607_cmds[] = { +	{ ao_ms5607_dump,	"p\0Display MS5607 data" }, +	{ 0, NULL }, +}; + +void +ao_ms5607_init(void) +{ +	ao_cmd_register(&ao_ms5607_cmds[0]); + +	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); +	stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); +	stm_moder_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, STM_MODER_OUTPUT); +} diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h new file mode 100644 index 00000000..6c245368 --- /dev/null +++ b/src/drivers/ao_ms5607.h @@ -0,0 +1,38 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_MS5607_H_ +#define _AO_MS5607_H_ + +#define AO_MS5607_RESET			0x1e + +#define AO_MS5607_CONVERT_D1_256	0x40 +#define AO_MS5607_CONVERT_D1_512	0x42 +#define AO_MS5607_CONVERT_D1_1024	0x44 +#define AO_MS5607_CONVERT_D1_2048	0x46 +#define AO_MS5607_CONVERT_D1_4096	0x48 + +#define AO_MS5607_CONVERT_D2_256	0x50 +#define AO_MS5607_CONVERT_D2_512	0x52 +#define AO_MS5607_CONVERT_D2_1024	0x54 +#define AO_MS5607_CONVERT_D2_2048	0x56 +#define AO_MS5607_CONVERT_D2_4096	0x58 + +#define AO_MS5607_ADC_READ		0x00 +#define AO_MS5607_PROM_READ(ad)		0xA0 | ((ad) << 1) + +#endif /* _AO_MS5607_H_ */ diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 23160d9b..fbcb4a57 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -31,13 +31,16 @@ ALTOS_SRC = \  	ao_serial_stm.c \  	ao_gps_skytraq.c \  	ao_cc1120.c \ -	ao_freq.c +	ao_freq.c \ +	ao_dma_stm.c \ +	ao_spi_stm.c \ +	ao_ms5607.c  PRODUCT=MegaMetrum-v0.1  PRODUCT_DEF=-DMEGAMETRUM  IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -O0 -g  PROG=megametrum-v0.1-$(VERSION).elf diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 6bf43cb1..0d88f4c1 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -29,6 +29,9 @@ main(void)  	ao_cmd_init();  	ao_gps_init();  	ao_config_init(); +	ao_dma_init(); +	ao_spi_init(); +	ao_ms5607_init();  	ao_start_scheduler();  	return 0; diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index dadeb380..ee4510e6 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -42,10 +42,13 @@  #define HAS_BEEP		0  #define HAS_SPI_1		1 -#define SPI_1_PE13_PE14_PE15	1 +#define SPI_1_PA5_PA6_PA7	1 +#define SPI_1_PB3_PB4_PB5	0 +#define SPI_1_PE13_PE14_PE15	0  #define HAS_SPI_2		1  #define SPI_2_PB13_PB14_PB15	1 +#define SPI_2_PD1_PD3_PD4	0  #define HAS_I2C_1		1  #define I2C_1_PB8_PB9		1 diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 366291c6..c1f49371 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -26,7 +26,10 @@ ALTOS_SRC = \  	ao_timer.c \  	ao_serial_stm.c \  	ao_lcd_stm.c \ -	ao_lcd_font.c +	ao_lcd_font.c \ +	ao_mutex.c \ +	ao_dma_stm.c \ +	ao_spi_stm.c   PRODUCT=StmDemo-v0.0  PRODUCT_DEF=-DSTM_DEMO diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 544f261f..54f7c8f2 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -50,6 +50,71 @@ void _lseek() { }  void _exit () { }  void _read () { }  void _fstat() { } + +static void +ao_dma_test(void) { +	static char	src[20] = "hello, world"; +	static char	dst[20]; +	 +	dst[0] = '\0'; +	ao_dma_set_transfer(STM_DMA_INDEX(1), dst, src, 13, +			    (1 << STM_DMA_CCR_MEM2MEM) | +			    (STM_DMA_CCR_PL_LOW << 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) | +			    (1 << STM_DMA_CCR_PINC) | +			    (0 << STM_DMA_CCR_CIRC) | +			    (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); +	ao_dma_start(STM_DMA_INDEX(1)); +	cli(); +	while (!ao_dma_done[STM_DMA_INDEX(1)]) +		ao_sleep(&ao_dma_done[STM_DMA_INDEX(1)]); +	sei(); +	printf ("copied %s\n", dst); +} + +static void +ao_spi_write(void) { +	unsigned char	data[] = { 0x55, 0xaa, 0xff, 0x00 }; +	int i; + +	for (i = 0; i < 10; i++) { +		ao_spi_get(0); +		stm_gpio_set(&stm_gpioc, 12, 0); +		ao_spi_send(data, 1, 0); +		stm_gpio_set(&stm_gpioc, 12, 1); +		ao_spi_put(0); +		printf("."); +		flush(); +		ao_delay(100); +	} +} + +static void +ao_spi_read(void) { +	unsigned char	data[4]; +	int i; + +	for (i = 0; i < 10; i++) { +		ao_spi_get(0); +		stm_gpio_set(&stm_gpioc, 12, 0); +		ao_spi_recv(data, 4, 0); +		printf("."); +		flush(); +		stm_gpio_set(&stm_gpioc, 12, 1); +		ao_spi_put(0); +		ao_delay(100); +	} +} + +__code struct ao_cmds ao_demo_cmds[] = { +	{ ao_dma_test,	"D\0DMA test" }, +	{ ao_spi_write, "W\0SPI write" }, +	{ ao_spi_read, "R\0SPI read" }, +	{ 0, NULL } +}; +  int  main(void)  { @@ -57,11 +122,19 @@ main(void)  	ao_serial_init();  	ao_timer_init(); +	ao_dma_init();  	ao_cmd_init(); -	ao_lcd_stm_init(); -	ao_lcd_font_init(); -	ao_add_task(&demo_task, ao_demo, "demo"); +//	ao_lcd_stm_init(); +//	ao_lcd_font_init(); +	ao_spi_init(); + +	ao_cmd_register(&ao_demo_cmds[0]); +	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); +	stm_gpio_set(&stm_gpioc, 12, 1); +	stm_moder_set(&stm_gpioc, 12, STM_MODER_OUTPUT); +	stm_otyper_set(&stm_gpioc, 12, STM_OTYPER_PUSH_PULL); +  	ao_start_scheduler();  	return 0;  } diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 798a292e..09c88f90 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -34,6 +34,11 @@  #define SERIAL_3_PC10_PC11	0  #define SERIAL_3_PD8_PD9	1 +#define HAS_SPI_1		1 +#define SPI_1_PB3_PB4_PB5	1 + +#define HAS_SPI_2		0 +  #define HAS_USB			0  #define HAS_BEEP		0  #define PACKET_HAS_SLAVE	0 diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 9b68f19a..29e3f42f 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -18,6 +18,8 @@  #ifndef _AO_ARCH_FUNCS_H_  #define _AO_ARCH_FUNCS_H_ +/* ao_spi_stm.c + */  extern uint8_t	ao_spi_mutex[STM_NUM_SPI];  static inline void ao_spi_get(uint8_t spi_index) { ao_mutex_get(&ao_spi_mutex[spi_index]); } @@ -30,6 +32,30 @@ void  ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);  void -ao_spi_init(uint8_t spi_index); +ao_spi_init(void); + +/* ao_dma_stm.c + */ + +extern uint8_t ao_dma_done[STM_NUM_DMA]; + +void +ao_dma_set_transfer(uint8_t 		index, +		    volatile void	*peripheral, +		    void		*memory, +		    uint16_t		count, +		    uint32_t		ccr); + +void +ao_dma_start(uint8_t index); + +void +ao_dma_done_transfer(uint8_t index); + +void +ao_dma_abort(uint8_t index); + +void +ao_dma_init(void);  #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c new file mode 100644 index 00000000..70b9e48a --- /dev/null +++ b/src/stm/ao_dma_stm.c @@ -0,0 +1,99 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +#define NUM_DMA	7 + +struct ao_dma_config { +	uint32_t	isr; +}; + +uint8_t ao_dma_done[NUM_DMA]; + +static struct ao_dma_config ao_dma_config[NUM_DMA]; +static uint8_t ao_dma_mutex[NUM_DMA]; + +static void +ao_dma_isr(uint8_t index) { +	/* Get channel interrupt bits */ +	uint32_t	isr = stm_dma.isr & (STM_DMA_ISR_MASK << +					     STM_DMA_ISR(index)); + +	/* Ack them */ +	stm_dma.ifcr = isr; +	isr >>= STM_DMA_ISR(index); +	ao_dma_config[index].isr |= isr; +	ao_dma_done[index] = 1; +	ao_wakeup(&ao_dma_done[index]); +} + +void stm_dma1_channel1_isr(void) { ao_dma_isr(STM_DMA_INDEX(1)); } +void stm_dma1_channel2_isr(void) { ao_dma_isr(STM_DMA_INDEX(2)); } +void stm_dma1_channel3_isr(void) { ao_dma_isr(STM_DMA_INDEX(3)); } +void stm_dma1_channel4_isr(void) { ao_dma_isr(STM_DMA_INDEX(4)); } +void stm_dma1_channel5_isr(void) { ao_dma_isr(STM_DMA_INDEX(5)); } +void stm_dma1_channel6_isr(void) { ao_dma_isr(STM_DMA_INDEX(6)); } +void stm_dma1_channel7_isr(void) { ao_dma_isr(STM_DMA_INDEX(7)); } + +void +ao_dma_set_transfer(uint8_t 		index, +		    volatile void	*peripheral, +		    void		*memory, +		    uint16_t		count, +		    uint32_t		ccr) +{ +	ao_mutex_get(&ao_dma_mutex[index]); +	stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE); +	stm_dma.channel[index].cndtr = count; +	stm_dma.channel[index].cpar = (uint32_t) peripheral; +	stm_dma.channel[index].cmar = (uint32_t) memory; +} + +void +ao_dma_start(uint8_t index) +{ +	ao_dma_done[index] = 0; +	stm_dma.channel[index].ccr |= (1 << STM_DMA_CCR_EN); +} + +void +ao_dma_done_transfer(uint8_t index) +{ +	stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); +	ao_mutex_put(&ao_dma_mutex[index]); +} + +void +ao_dma_abort(uint8_t index) +{ +	stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); +} + +void +ao_dma_init(void) +{ +	int	index; + +	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); + +	for (index = 0; index < STM_NUM_DMA; index++) { +		stm_nvic_set_enable(STM_ISR_DMA1_CHANNEL1_POS + index); +		stm_nvic_set_priority(STM_ISR_DMA1_CHANNEL1_POS + index, 4); +	} +	 +} diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c new file mode 100644 index 00000000..da04302b --- /dev/null +++ b/src/stm/ao_spi_stm.c @@ -0,0 +1,240 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> + +struct ao_spi_stm_info { +	uint8_t	miso_dma_index; +	uint8_t mosi_dma_index; +	struct stm_spi *stm_spi; +}; + +uint8_t	ao_spi_mutex[STM_NUM_SPI]; + +static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = { +	{ +		.miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_RX), +		.mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_TX), +		&stm_spi1 +	}, +	{ +		.miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_RX), +		.mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_TX), +		&stm_spi2 +	} +}; + +static uint8_t	spi_dev_null; + +void +ao_spi_send(void *block, uint16_t len, uint8_t spi_index) +{ +	struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; +	uint8_t	mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; +	uint8_t	miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + +	ao_dma_set_transfer(mosi_dma_index, +			    &stm_spi->dr, +			    block, +			    len, +			    (0 << STM_DMA_CCR_MEM2MEM) | +			    (STM_DMA_CCR_PL_MEDIUM << 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_MEM_TO_PER << STM_DMA_CCR_DIR)); +	/* Clear any stale data */ +	(void) stm_spi->dr; +	ao_dma_set_transfer(miso_dma_index, +			    &stm_spi->dr, +			    &spi_dev_null, +			    len, +			    (0 << STM_DMA_CCR_MEM2MEM) | +			    (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | +			    (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | +			    (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | +			    (0 << 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)); +	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); +} + +void +ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) +{ +	struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; +#if 0 +	uint8_t *d = block; + +	while (len--) { +		stm_spi->dr = 0xff; +		while (!(stm_spi->sr & (1 << STM_SPI_SR_RXNE))); +		*d++ = stm_spi->dr; +	} +	while (stm_spi->sr & (1 << STM_SPI_SR_BSY)); +#else +	uint8_t	mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; +	uint8_t	miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + +	ao_dma_set_transfer(mosi_dma_index, +			    &stm_spi->dr, +			    &spi_dev_null, +			    len, +			    (0 << STM_DMA_CCR_MEM2MEM) | +			    (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | +			    (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | +			    (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | +			    (0 << STM_DMA_CCR_MINC) | +			    (0 << STM_DMA_CCR_PINC) | +			    (0 << STM_DMA_CCR_CIRC) | +			    (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); +	/* Clear any stale data */ +	(void) stm_spi->dr; +	ao_dma_set_transfer(miso_dma_index, +			    &stm_spi->dr, +			    block, +			    len, +			    (0 << STM_DMA_CCR_MEM2MEM) | +			    (STM_DMA_CCR_PL_MEDIUM << 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)); +	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); +#endif +} + +static void +ao_spi_channel_init(uint8_t spi_index) +{ +	struct stm_spi	*stm_spi = ao_spi_stm_info[spi_index].stm_spi; + +	stm_spi->cr1 = 0; +	(void) stm_spi->sr; +	stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | +			(0 << STM_SPI_CR1_BIDIOE) | +			(0 << STM_SPI_CR1_CRCEN) | +			(0 << STM_SPI_CR1_CRCNEXT) | +			(0 << STM_SPI_CR1_DFF) | +			(0 << STM_SPI_CR1_RXONLY) | +			(1 << STM_SPI_CR1_SSM) | +			(1 << STM_SPI_CR1_SSI) | +			(0 << STM_SPI_CR1_LSBFIRST) | +			(1 << STM_SPI_CR1_SPE) | +			(STM_SPI_CR1_BR_PCLK_4 << STM_SPI_CR1_BR) | +			(1 << STM_SPI_CR1_MSTR) | +			(0 << STM_SPI_CR1_CPOL) | +			(0 << STM_SPI_CR1_CPHA)); +	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)); +} + +void +ao_spi_init(void) +{ +#if HAS_SPI_1 +# if SPI_1_PA5_PA6_PA7 +	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); +	stm_afr_set(&stm_gpioa, 5, STM_AFR_AF5); +	stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5); +	stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5); +# else +#  if SPI_1_PB3_PB4_PB5 +	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); +	stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5); +	stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5); +	stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5); +#  else +#   if SPI_1_PE13_PE14_PE15 +	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN); +	stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5); +	stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5); +	stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5); +#   else +#    error "No SPI_1 port configuration specified" +#   endif +#  endif +# endif + +	stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); + +	ao_spi_channel_init(0); + +	stm_nvic_set_enable(STM_ISR_SPI1_POS); +	stm_nvic_set_priority(STM_ISR_SPI1_POS, 3); +#endif + +#if HAS_SPI_2 +# if SPI_2_PB13_PB14_PB15 +	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); +	stm_afr_set(&stm_gpiob, 13, STM_AFR_AF5); +	stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5); +	stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5); +# else +#  if SPI_2_PPD1_PD3_PD4 +	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); +	stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5); +	stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5); +	stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5); +#  else +#   error "No SPI_2 port configuration specified" +#  endif +# endif + +	stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); + +	ao_spi_channel_init(1); + +	stm_nvic_set_enable(STM_ISR_SPI2_POS); +	stm_nvic_set_priority(STM_ISR_SPI2_POS, 3); +#endif +} diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 531a4fb9..b40ec0ee 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -159,6 +159,17 @@ stm_afr_get(struct stm_gpio *gpio, int pin) {  	}  } +static inline void +stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) { +	/* Use the bit set/reset register to do this atomically */ +	gpio->bsrr = ((uint32_t) (value ^ 1) << (pin + 16)) | ((uint32_t) value << pin); +} + +static inline uint8_t +stm_gpio_isset(struct stm_gpio *gpio, int pin) { +	return (gpio->idr >> pin) & 1; +} +  extern struct stm_gpio stm_gpioa;  extern struct stm_gpio stm_gpiob;  extern struct stm_gpio stm_gpioc; @@ -238,11 +249,6 @@ extern struct stm_usart stm_usart3;  #define STM_USART_CR3_IREN	(1)	/* IrDA mode enable */  #define STM_USART_CR3_EIE	(0)	/* Error interrupt enable */ -struct stm_spi { -}; - -extern struct stm_spi stm_spi1; -  struct stm_tim {  }; @@ -842,4 +848,168 @@ isr(tim7)  #define STM_ISR_TIM6_POS		43  #define STM_ISR_TIM7_POS		44 +struct stm_dma_channel { +	vuint32_t	ccr; +	vuint32_t	cndtr; +	vuint32_t	cpar; +	vuint32_t	cmar; +	vuint32_t	reserved; +}; + +#define STM_NUM_DMA	7 + +struct stm_dma { +	vuint32_t		isr; +	vuint32_t		ifcr; +	struct stm_dma_channel	channel[STM_NUM_DMA]; +}; + +extern struct stm_dma stm_dma; + +/* DMA channels go from 1 to 7, instead of 0 to 6 (sigh) + */ + +#define STM_DMA_INDEX(channel)		((channel) - 1) + +#define STM_DMA_ISR(index)		((index) << 2) +#define STM_DMA_ISR_MASK			0xf +#define STM_DMA_ISR_TEIF			3 +#define STM_DMA_ISR_HTIF			2 +#define STM_DMA_ISR_TCIF			1 +#define STM_DMA_ISR_GIF				0 + +#define STM_DMA_IFCR(index)		((index) << 2) +#define STM_DMA_IFCR_MASK			0xf +#define STM_DMA_IFCR_CTEIF      		3 +#define STM_DMA_IFCR_CHTIF			2 +#define STM_DMA_IFCR_CTCIF			1 +#define STM_DMA_IFCR_CGIF			0 + +#define STM_DMA_CCR_MEM2MEM		(14) + +#define STM_DMA_CCR_PL			(12) +#define  STM_DMA_CCR_PL_LOW			(0) +#define  STM_DMA_CCR_PL_MEDIUM			(1) +#define  STM_DMA_CCR_PL_HIGH			(2) +#define  STM_DMA_CCR_PL_VERY_HIGH		(3) +#define  STM_DMA_CCR_PL_MASK			(3) + +#define STM_DMA_CCR_MSIZE		(10) +#define  STM_DMA_CCR_MSIZE_8			(0) +#define  STM_DMA_CCR_MSIZE_16			(1) +#define  STM_DMA_CCR_MSIZE_32			(2) +#define  STM_DMA_CCR_MSIZE_MASK			(3) + +#define STM_DMA_CCR_PSIZE		(8) +#define  STM_DMA_CCR_PSIZE_8			(0) +#define  STM_DMA_CCR_PSIZE_16			(1) +#define  STM_DMA_CCR_PSIZE_32			(2) +#define  STM_DMA_CCR_PSIZE_MASK			(3) + +#define STM_DMA_CCR_MINC		(7) +#define STM_DMA_CCR_PINC		(6) +#define STM_DMA_CCR_CIRC		(5) +#define STM_DMA_CCR_DIR			(4) +#define  STM_DMA_CCR_DIR_PER_TO_MEM		0 +#define  STM_DMA_CCR_DIR_MEM_TO_PER		1 +#define STM_DMA_CCR_TEIE		(3) +#define STM_DMA_CCR_HTIE		(2) +#define STM_DMA_CCR_TCIE		(1) +#define STM_DMA_CCR_EN			(0) + +#define STM_DMA_CHANNEL_ADC1		1 +#define STM_DMA_CHANNEL_SPI1_RX		2 +#define STM_DMA_CHANNEL_SPI1_TX		3 +#define STM_DMA_CHANNEL_SPI2_RX		4 +#define STM_DMA_CHANNEL_SPI2_TX		5 +#define STM_DMA_CHANNEL_USART3_TX	2 +#define STM_DMA_CHANNEL_USART3_RX	3 +#define STM_DMA_CHANNEL_USART1_TX	4 +#define STM_DMA_CHANNEL_USART1_RX	5 +#define STM_DMA_CHANNEL_USART2_RX	6 +#define STM_DMA_CHANNEL_USART2_TX	7 +#define STM_DMA_CHANNEL_I2C2_TX		4 +#define STM_DMA_CHANNEL_I2C2_RX		5 +#define STM_DMA_CHANNEL_I2C1_RX		6 +#define STM_DMA_CHANNEL_I2C1_TX		7 +#define STM_DMA_CHANNEL_TIM2_CH3	1 +#define STM_DMA_CHANNEL_TIM2_UP		2 +#define STM_DMA_CHANNEL_TIM2_CH1	5 +#define STM_DMA_CHANNEL_TIM2_CH2	7 +#define STM_DMA_CHANNEL_TIM2_CH4	7 +#define STM_DMA_CHANNEL_TIM3_CH3	2 +#define STM_DMA_CHANNEL_TIM3_CH4	3 +#define STM_DMA_CHANNEL_TIM3_UP		3 +#define STM_DMA_CHANNEL_TIM3_CH1	6 +#define STM_DMA_CHANNEL_TIM3_TRIG	6 +#define STM_DMA_CHANNEL_TIM4_CH1	1 +#define STM_DMA_CHANNEL_TIM4_CH2	4 +#define STM_DMA_CHANNEL_TIM4_CH3	5 +#define STM_DMA_CHANNEL_TIM4_UP		7 +#define STM_DMA_CHANNEL_TIM6_UP_DA	2 +#define STM_DMA_CHANNEL_C_CHANNEL1	2 +#define STM_DMA_CHANNEL_TIM7_UP_DA	3 +#define STM_DMA_CHANNEL_C_CHANNEL2	3 + +/* + * Only spi channel 1 and 2 can use DMA + */ +#define STM_NUM_SPI	2 + +struct stm_spi { +	vuint32_t	cr1; +	vuint32_t	cr2; +	vuint32_t	sr; +	vuint32_t	dr; +	vuint32_t	crcpr; +	vuint32_t	rxcrcr; +	vuint32_t	txcrcr; +}; + +extern struct stm_spi stm_spi1, stm_spi2, stm_spi3; + +/* SPI channels go from 1 to 3, instead of 0 to 2 (sigh) + */ + +#define STM_SPI_INDEX(channel)		((channel) - 1) + +#define STM_SPI_CR1_BIDIMODE		15 +#define STM_SPI_CR1_BIDIOE		14 +#define STM_SPI_CR1_CRCEN		13 +#define STM_SPI_CR1_CRCNEXT		12 +#define STM_SPI_CR1_DFF			11 +#define STM_SPI_CR1_RXONLY		10 +#define STM_SPI_CR1_SSM			9 +#define STM_SPI_CR1_SSI			8 +#define STM_SPI_CR1_LSBFIRST		7 +#define STM_SPI_CR1_SPE			6 +#define STM_SPI_CR1_BR			3 +#define  STM_SPI_CR1_BR_PCLK_2			0 +#define  STM_SPI_CR1_BR_PCLK_4			1 +#define  STM_SPI_CR1_BR_PCLK_8			2 +#define  STM_SPI_CR1_BR_PCLK_16			3 +#define  STM_SPI_CR1_BR_PCLK_32			4 +#define  STM_SPI_CR1_BR_PCLK_64			5 +#define  STM_SPI_CR1_BR_PCLK_128		6 +#define  STM_SPI_CR1_BR_PCLK_256		7 +#define  STM_SPI_CR1_BR_MASK			7 + +#define STM_SPI_CR1_MSTR		2 +#define STM_SPI_CR1_CPOL		1 +#define STM_SPI_CR1_CPHA		0 + +#define STM_SPI_CR2_TXEIE	7 +#define STM_SPI_CR2_RXNEIE	6 +#define STM_SPI_CR2_ERRIE	5 +#define STM_SPI_CR2_SSOE	2 +#define STM_SPI_CR2_TXDMAEN	1 +#define STM_SPI_CR2_RXDMAEN	0 + +#define STM_SPI_SR_BSY		7 +#define STM_SPI_SR_OVR		6 +#define STM_SPI_SR_MODF		5 +#define STM_SPI_SR_CRCERR	4 +#define STM_SPI_SR_TXE		1 +#define STM_SPI_SR_RXNE		0 +  #endif /* _STM32L_H_ */ | 
