From a7a3770d5198d26c963127094a18175696f04827 Mon Sep 17 00:00:00 2001 From: Uwe Hermann Date: Wed, 30 Dec 2009 23:09:14 +0100 Subject: [PATCH] Add initial SPI code. For now, add the following basic SPI functions: - spi_init_master() - spi_write() - spi_read() This is incomplete and untested, yet. Also, add some more SPI bit definition macros and comments. --- include/libopenstm32/spi.h | 70 +++++++++++++++++++++++++------------- lib/Makefile | 2 +- lib/spi.c | 64 ++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 25 deletions(-) create mode 100644 lib/spi.c diff --git a/include/libopenstm32/spi.h b/include/libopenstm32/spi.h index 6f54b30b..f7baa793 100644 --- a/include/libopenstm32/spi.h +++ b/include/libopenstm32/spi.h @@ -93,44 +93,66 @@ /* Note: None of the CR1 bits are used in I2S mode. */ -#define SPI_CR1_BIDIMODE (1 << 15) +/* BIDIMODE: Bidirectional data mode enable */ +#define SPI_CR1_BIDIMODE_2LINE_UNIDIR (0 << 15) +#define SPI_CR1_BIDIMODE_1LINE_BIDIR (1 << 15) + +/* BIDIOE: Output enable in bidirectional mode */ #define SPI_CR1_BIDIOE (1 << 14) + +/* CRCEN: Hardware CRC calculation enable */ #define SPI_CR1_CRCEN (1 << 13) + +/* CRCNEXT: Transmit CRC next */ #define SPI_CR1_CRCNEXT (1 << 12) -#define SPI_CR1_DFF (1 << 11) + +/* DFF: Data frame format */ +#define SPI_CR1_DFF_8BIT (0 << 11) +#define SPI_CR1_DFF_16BIT (1 << 11) + +/* RXONLY: Receive only */ #define SPI_CR1_RXONLY (1 << 10) + +/* SSM: Software slave management */ #define SPI_CR1_SSM (1 << 9) + +/* SSI: Internal slave select */ #define SPI_CR1_SSI (1 << 8) + +/* LSBFIRST: Frame format */ +#define SPI_CR1_MSBFIRST (0 << 7) #define SPI_CR1_LSBFIRST (1 << 7) -#define SPI_CR1_SPE (1 << 6) -/* SPI_CR1[5:3]: BR[2:0]: Baud rate control: */ -#define SPI_CR1_BR (1 << 3) -#define SPI_CR1_MSTR (1 << 2) -#define SPI_CR1_CPOL (1 << 1) -#define SPI_CR1_CPHA (1 << 0) -/* CR1_BIDIMODE values */ -#define SPI_CR1_BIDIMODE_2LINE_UNIDIR 0x00 -#define SPI_CR1_BIDIMODE_1LINE_BIDIR 0x01 +/* SPE: SPI enable */ +#define SPI_CR1_SPE (1 << 6) -/* CR1_DFF (data frame format) values */ -#define SPI_CR1_DFF_8BIT 0x00 -#define SPI_CR1_DFF_16BIT 0x01 +/* BR[2:0]: Baud rate control */ +#define SPI_CR1_BAUDRATE_FPCLK_DIV_2 (0x00 << 3) +#define SPI_CR1_BAUDRATE_FPCLK_DIV_4 (0x01 << 3) +#define SPI_CR1_BAUDRATE_FPCLK_DIV_8 (0x02 << 3) +#define SPI_CR1_BAUDRATE_FPCLK_DIV_16 (0x03 << 3) +#define SPI_CR1_BAUDRATE_FPCLK_DIV_32 (0x04 << 3) +#define SPI_CR1_BAUDRATE_FPCLK_DIV_64 (0x05 << 3) +#define SPI_CR1_BAUDRATE_FPCLK_DIV_128 (0x06 << 3) +#define SPI_CR1_BAUDRATE_FPCLK_DIV_256 (0x07 << 3) + +/* MSTR: Master selection */ +#define SPI_CR1_MSTR (1 << 2) -/* CR1_BR[2:0] values */ -#define SPI_CR1_BAUDRATE_FPCLK_DIV_2 0x00 -#define SPI_CR1_BAUDRATE_FPCLK_DIV_4 0x01 -#define SPI_CR1_BAUDRATE_FPCLK_DIV_8 0x02 -#define SPI_CR1_BAUDRATE_FPCLK_DIV_16 0x03 -#define SPI_CR1_BAUDRATE_FPCLK_DIV_32 0x04 -#define SPI_CR1_BAUDRATE_FPCLK_DIV_64 0x05 -#define SPI_CR1_BAUDRATE_FPCLK_DIV_128 0x06 -#define SPI_CR1_BAUDRATE_FPCLK_DIV_256 0x07 +/* CPOL: Clock polarity */ +#define SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE (0 << 1) +#define SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE (1 << 1) -/* TODO: Bit values of other registers. */ +/* CPHA: Clock phase */ +#define SPI_CR1_CPHA_CLK_TRANSITION_1 (0 << 0) +#define SPI_CR1_CPHA_CLK_TRANSITION_2 (1 << 0) /* --- Function prototypes ------------------------------------------------- */ +int spi_init_master(u32 spi, u32 br, u32 cpol, u32 cpha, u32 dff, u32 lsbfirst); +void spi_write(u32 spi, u16 data); +u16 spi_read(u32 spi); + /* TODO */ #endif diff --git a/lib/Makefile b/lib/Makefile index 8dd2a085..855aa9b0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -27,7 +27,7 @@ CFLAGS = -Os -g -Wall -Wextra -I../include -fno-common \ -mcpu=cortex-m3 -mthumb -Wstrict-prototypes # ARFLAGS = rcsv ARFLAGS = rcs -OBJS = rcc.o gpio.o usart.o adc.o +OBJS = rcc.o gpio.o usart.o adc.o spi.o # Be silent per default, but 'make V=1' will show all compiler calls. ifneq ($(V),1) diff --git a/lib/spi.c b/lib/spi.c new file mode 100644 index 00000000..02936eed --- /dev/null +++ b/lib/spi.c @@ -0,0 +1,64 @@ +/* + * This file is part of the libopenstm32 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * 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, either version 3 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 + * 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, see . + */ + +#include + +/* + * SPI and I2S code. + * + * Examples: + * spi_init_master(SPI1, 1000000, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE, + * SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_DFF_8BIT, + * SPI_CR1_LSBFIRST); + * spi_write(SPI1, 0x55); // 8-bit write + * spi_write(SPI1, 0xaa88); // 16-bit write + * reg8 = spi_read(SPI1); // 8-bit read + * reg16 = spi_read(SPI1); // 16-bit read + */ + +int spi_init_master(u32 spi, u32 br, u32 cpol, u32 cpha, u32 dff, u32 lsbfirst) +{ + u32 reg32 = 0; + + reg32 |= br; /* Set BAUD rate bits. */ + reg32 |= cpol; /* Set CPOL value. */ + reg32 |= cpha; /* Set CPHA value. */ + reg32 |= dff; /* Set data format (8 or 16 bits). */ + reg32 |= lsbfirst; /* Set frame format (LSB-first or MSB-first). */ + + /* TODO: NSS pin handling. */ + + /* TODO: Set MSTR and SPE bits. */ + + SPI_CR1(spi) = reg32; + + return 0; /* TODO */ +} + +void spi_write(u32 spi, u16 data) +{ + /* Write data (8 or 16 bits, depending on DFF) into DR. */ + SPI_DR(spi) = data; +} + +u16 spi_read(u32 spi) +{ + /* Read the data (8 or 16 bits, depending on DFF bit) from DR. */ + return SPI_DR(spi); +}