From 0c779512d6db7fd513c8982059b869df0be29210 Mon Sep 17 00:00:00 2001 From: Ken Sarkies Date: Mon, 15 Oct 2012 14:34:33 +1030 Subject: Initial documentation for SPI, I2C and CRC (no code changes) --- include/libopencm3/stm32/crc.h | 14 ++ include/libopencm3/stm32/i2c.h | 38 ++++ include/libopencm3/stm32/spi.h | 62 +++++++ lib/stm32/crc.c | 46 ++++- lib/stm32/i2c.c | 165 +++++++++++++++++ lib/stm32/spi.c | 408 ++++++++++++++++++++++++++++++++++++++++- 6 files changed, 730 insertions(+), 3 deletions(-) diff --git a/include/libopencm3/stm32/crc.h b/include/libopencm3/stm32/crc.h index 3848191..aa30182 100644 --- a/include/libopencm3/stm32/crc.h +++ b/include/libopencm3/stm32/crc.h @@ -1,3 +1,17 @@ +/** @defgroup crc_defines CRC Defines + +@brief libopencm3 Defined Constants and Types for the STM32F CRC Generator + +@ingroup STM32F_defines + +@version 1.0.0 + +@author @htmlonly © @endhtmlonly 2010 Thomas Otto + +@date 18 August 2012 + +LGPL License Terms @ref lgpl_license + */ /* * This file is part of the libopencm3 project. * diff --git a/include/libopencm3/stm32/i2c.h b/include/libopencm3/stm32/i2c.h index 13257eb..a59c420 100644 --- a/include/libopencm3/stm32/i2c.h +++ b/include/libopencm3/stm32/i2c.h @@ -1,3 +1,19 @@ +/** @defgroup i2c_defines I2C Defines + +@ingroup STM32F_defines + +@brief libopencm3 Defined Constants and Types for the STM32 I2C + +@version 1.0.0 + +@author @htmlonly © @endhtmlonly 2010 Thomas Otto +@author @htmlonly © @endhtmlonly 2012 Ken Sarkies + +@date 12 October 2012 + +LGPL License Terms @ref lgpl_license + */ + /* * This file is part of the libopencm3 project. * @@ -23,11 +39,19 @@ #include #include +/**@{*/ + /* --- Convenience macros -------------------------------------------------- */ /* I2C register base adresses (for convenience) */ +/****************************************************************************/ +/** @defgroup i2c_reg_base I2C register base address +@ingroup i2c_defines + +@{*/ #define I2C1 I2C1_BASE #define I2C2 I2C2_BASE +/**@}*/ /* --- I2C registers ------------------------------------------------------- */ @@ -146,6 +170,11 @@ /* Note: Bits [7:6] are reserved, and forced to 0 by hardware. */ /* FREQ[5:0]: Peripheral clock frequency (valid values: 2-36 MHz) */ +/****************************************************************************/ +/** @defgroup i2c_clock I2C clock frequency settings +@ingroup i2c_defines + +@{*/ #define I2C_CR2_FREQ_2MHZ 0x02 #define I2C_CR2_FREQ_3MHZ 0x03 #define I2C_CR2_FREQ_4MHZ 0x04 @@ -181,6 +210,7 @@ #define I2C_CR2_FREQ_34MHZ 0x22 #define I2C_CR2_FREQ_35MHZ 0x23 #define I2C_CR2_FREQ_36MHZ 0x24 +/**@}*/ /* --- I2Cx_OAR1 values ---------------------------------------------------- */ @@ -311,8 +341,14 @@ /* --- I2C const definitions ----------------------------------------------- */ +/****************************************************************************/ +/** @defgroup i2c_rw I2C Read/Write bit +@ingroup i2c_defines + +@{*/ #define I2C_WRITE 0 #define I2C_READ 1 +/**@}*/ /* --- I2C funtion prototypes----------------------------------------------- */ @@ -336,3 +372,5 @@ void i2c_send_data(u32 i2c, u8 data); END_DECLS #endif +/**@}*/ + diff --git a/include/libopencm3/stm32/spi.h b/include/libopencm3/stm32/spi.h index 11ba820..f23df3a 100644 --- a/include/libopencm3/stm32/spi.h +++ b/include/libopencm3/stm32/spi.h @@ -1,3 +1,19 @@ +/** @defgroup spi_defines SPI Defines + +@ingroup STM32F_defines + +@brief libopencm3 Defined Constants and Types for the STM32 SPI + +@version 1.0.0 + +@author @htmlonly © @endhtmlonly 2009 Uwe Hermann +@author @htmlonly © @endhtmlonly 2012 Ken Sarkies + +@date 12 October 2012 + +LGPL License Terms @ref lgpl_license + */ + /* * This file is part of the libopencm3 project. * @@ -23,13 +39,21 @@ #include #include +/**@{*/ + /* Registers can be accessed as 16bit or 32bit values. */ /* --- Convenience macros -------------------------------------------------- */ +/****************************************************************************/ +/** @defgroup spi_reg_base SPI Register base address +@ingroup spi_defines + +@{*/ #define SPI1 SPI1_BASE #define SPI2 SPI2_I2S_BASE #define SPI3 SPI3_I2S_BASE +/**@}*/ /* --- SPI registers ------------------------------------------------------- */ @@ -110,8 +134,14 @@ #define SPI_CR1_CRCNEXT (1 << 12) /* DFF: Data frame format */ +/****************************************************************************/ +/** @defgroup spi_dff SPI data frame format +@ingroup spi_defines + +@{*/ #define SPI_CR1_DFF_8BIT (0 << 11) #define SPI_CR1_DFF_16BIT (1 << 11) +/**@}*/ #define SPI_CR1_DFF (1 << 11) /* RXONLY: Receive only */ @@ -124,13 +154,24 @@ #define SPI_CR1_SSI (1 << 8) /* LSBFIRST: Frame format */ +/****************************************************************************/ +/** @defgroup spi_lsbfirst SPI lsb/msb first +@ingroup spi_defines + +@{*/ #define SPI_CR1_MSBFIRST (0 << 7) #define SPI_CR1_LSBFIRST (1 << 7) +/**@}*/ /* SPE: SPI enable */ #define SPI_CR1_SPE (1 << 6) /* BR[2:0]: Baud rate control */ +/****************************************************************************/ +/** @defgroup spi_baudrate SPI peripheral baud rates +@ingroup spi_defines + +@{*/ #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) @@ -139,6 +180,12 @@ #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) +/**@}*/ +/****************************************************************************/ +/** @defgroup spi_br_pre SPI peripheral baud rate prescale values +@ingroup spi_defines + +@{*/ #define SPI_CR1_BR_FPCLK_DIV_2 0x0 #define SPI_CR1_BR_FPCLK_DIV_4 0x1 #define SPI_CR1_BR_FPCLK_DIV_8 0x2 @@ -147,18 +194,31 @@ #define SPI_CR1_BR_FPCLK_DIV_64 0x5 #define SPI_CR1_BR_FPCLK_DIV_128 0x6 #define SPI_CR1_BR_FPCLK_DIV_256 0x7 +/**@}*/ /* MSTR: Master selection */ #define SPI_CR1_MSTR (1 << 2) /* CPOL: Clock polarity */ +/****************************************************************************/ +/** @defgroup spi_cpol SPI clock polarity +@ingroup spi_defines + +@{*/ #define SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE (0 << 1) #define SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE (1 << 1) +/**@}*/ #define SPI_CR1_CPOL (1 << 1) /* CPHA: Clock phase */ +/****************************************************************************/ +/** @defgroup spi_cpha SPI clock phase +@ingroup spi_defines + +@{*/ #define SPI_CR1_CPHA_CLK_TRANSITION_1 (0 << 0) #define SPI_CR1_CPHA_CLK_TRANSITION_2 (1 << 0) +/**@}*/ #define SPI_CR1_CPHA (1 << 0) /* --- SPI_CR2 values ------------------------------------------------------ */ @@ -347,4 +407,6 @@ void spi_disable_rx_dma(u32 spi); END_DECLS +/**@}*/ + #endif diff --git a/lib/stm32/crc.c b/lib/stm32/crc.c index bbbe1fd..bd9e8d2 100644 --- a/lib/stm32/crc.c +++ b/lib/stm32/crc.c @@ -1,3 +1,17 @@ +/** @defgroup crc_file CRC + +@ingroup STM32F_files + +@brief libopencm3 STM32Fxxx CRC + +@version 1.0.0 + +@author @htmlonly © @endhtmlonly 2012 Karl Palsson + +@date 15 October 2012 + +LGPL License Terms @ref lgpl_license + */ /* * This file is part of the libopencm3 project. * @@ -19,11 +33,30 @@ #include +/**@{*/ + +/*-----------------------------------------------------------------------------*/ +/** @brief CRC Reset. + +Reset the CRC unit and forces the data register to all 1s. + +*/ + void crc_reset(void) { CRC_CR |= CRC_CR_RESET; } +/*-----------------------------------------------------------------------------*/ +/** @brief CRC Calculate. + +Writes a data word to the register, the write operation stalling until the +computation is complete. + +@param[in] data Unsigned int32. +@returns int32 Computed CRC result +*/ + u32 crc_calculate(u32 data) { CRC_DR = data; @@ -31,6 +64,16 @@ u32 crc_calculate(u32 data) return CRC_DR; } +/*-----------------------------------------------------------------------------*/ +/** @brief CRC Calculate of a Block of Data. + +Writes data words consecutively to the register, the write operation stalling +until the computation of each word is complete. + +@param[in] datap Unsigned int32. pointer to an array of 32 bit data words. +@returns int32 Final computed CRC result +*/ + u32 crc_calculate_block(u32 *datap, int size) { int i; @@ -39,6 +82,5 @@ u32 crc_calculate_block(u32 *datap, int size) } return CRC_DR; } - - +/**@}*/ diff --git a/lib/stm32/i2c.c b/lib/stm32/i2c.c index 87d9061..e1d3a09 100644 --- a/lib/stm32/i2c.c +++ b/lib/stm32/i2c.c @@ -1,3 +1,28 @@ +/** @defgroup i2c_file I2C + +@ingroup STM32F_files + +@brief libopencm3 STM32Fxxx I2C + +@version 1.0.0 + +@author @htmlonly © @endhtmlonly 2010 Thomas Otto +@author @htmlonly © @endhtmlonly 2012 Ken Sarkies + +@date 15 October 2012 + +Devices can have up to two I2C peripherals. The peripherals support SMBus and +PMBus variants. + +A peripheral begins after reset in Slave mode. To become a Master a start +condition must be generated. The peripheral will remain in Master mode unless +a multimaster contention is lost or a stop condition is generated. + +@todo all sorts of lovely stuff like DMA, Interrupts, SMBus variant, Status +register access, Error conditions + +LGPL License Terms @ref lgpl_license + */ /* * This file is part of the libopencm3 project. * @@ -20,6 +45,17 @@ #include #include +/**@{*/ + +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Reset. + +The I2C peripheral and all its associated configuration registers are placed in the +reset condition. The reset is effected via the RCC peripheral reset system. + +@param[in] i2c Unsigned int32. I2C peripheral identifier @ref i2c_reg_base. +*/ + void i2c_reset(u32 i2c) { switch (i2c) { @@ -34,26 +70,69 @@ void i2c_reset(u32 i2c) } } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Peripheral Enable. + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +*/ + void i2c_peripheral_enable(u32 i2c) { I2C_CR1(i2c) |= I2C_CR1_PE; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Peripheral Disable. + +This must not be reset while in Master mode until a communication has finished. +In Slave mode, the peripheral is disabled only after communication has ended. + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +*/ + void i2c_peripheral_disable(u32 i2c) { I2C_CR1(i2c) &= ~I2C_CR1_PE; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Send Start Condition. + +If in Master mode this will cause a restart condition to occur at the end of the +current transmission. If in Slave mode, this will initiate a start condition +when the current bus activity is completed. + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +*/ + void i2c_send_start(u32 i2c) { I2C_CR1(i2c) |= I2C_CR1_START; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Send Stop Condition. + +After the current byte transfer this will initiate a stop condition if in Master +mode, or simply release the bus if in Slave mode. + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +*/ + void i2c_send_stop(u32 i2c) { I2C_CR1(i2c) |= I2C_CR1_STOP; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Set the 7 bit Slave Address for the Peripheral. + +This sets an address for Slave mode operation, in 7 bit form. + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +@param[in] slave Unsigned int8. Slave address 0...127. +*/ + void i2c_set_own_7bit_slave_address(u32 i2c, u8 slave) { I2C_OAR1(i2c) = (u16)(slave << 1); @@ -61,21 +140,61 @@ void i2c_set_own_7bit_slave_address(u32 i2c, u8 slave) I2C_OAR1(i2c) |= (1 << 14); /* Datasheet: always keep 1 by software. */ } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Set the 10 bit Slave Address for the Peripheral. + +This sets an address for Slave mode operation, in 10 bit form. + +@todo add "I2C_OAR1(i2c) |= (1 << 14);" as above + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +@param[in] slave Unsigned int16. Slave address 0...1023. +*/ + void i2c_set_own_10bit_slave_address(u32 i2c, u16 slave) { I2C_OAR1(i2c) = (u16)(I2C_OAR1_ADDMODE | slave); } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Set Fast Mode. + +Set the clock frequency to the high clock rate mode (up to 400kHz). The actual +clock frequency must be set with @ref i2c_set_clock_frequency + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +*/ + void i2c_set_fast_mode(u32 i2c) { I2C_CCR(i2c) |= I2C_CCR_FS; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Set Standard Mode. + +Set the clock frequency to the standard clock rate mode (up to 100kHz). The actual +clock frequency must be set with @ref i2c_set_clock_frequency + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +*/ + void i2c_set_standard_mode(u32 i2c) { I2C_CCR(i2c) &= ~I2C_CCR_FS; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Set Peripheral Clock Frequency. + +Set the peripheral clock frequency: 2MHz to 36MHz (the APB frequency). Note that +this is not the I2C bus clock. This is set in conjunction with the Clock +Control register to generate the Master bus clock, see @ref i2c_set_ccr + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +@param[in] freq Unsigned int8. Clock Frequency Setting @ref i2c_clock. +*/ + void i2c_set_clock_frequency(u32 i2c, u8 freq) { u16 reg16; @@ -84,6 +203,21 @@ void i2c_set_clock_frequency(u32 i2c, u8 freq) I2C_CR2(i2c) = reg16; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Set Bus Clock Frequency. + +Set the bus clock frequency. This is a 12 bit number (0...4095) calculated +from the formulae given in the STM32F1 reference manual in the description +of the CCR field. It is a divisor of the peripheral clock frequency +@ref i2c_set_clock_frequency modified by the fast mode setting +@ref i2c_set_fast_mode + +@todo provide additional API assitance to set the clock, eg macros + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +@param[in] freq Unsigned int16. Bus Clock Frequency Setting 0...4095. +*/ + void i2c_set_ccr(u32 i2c, u16 freq) { u16 reg16; @@ -92,17 +226,48 @@ void i2c_set_ccr(u32 i2c, u16 freq) I2C_CCR(i2c) = reg16; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Set the Rise Time. + +Set the maximum rise time on the bus according to the I2C specification, as 1 +more than the specified rise time in peripheral clock cycles. This is a 6 bit +number. + +@todo provide additional APIP assistance. + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +@param[in] trise Unsigned int16. Rise Time Setting 0...63. +*/ + void i2c_set_trise(u32 i2c, u16 trise) { I2C_TRISE(i2c) = trise; } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Send the 7-bit Slave Address. + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +@param[in] slave Unsigned int16. Slave address 0...1023. +@param[in] readwrite Unsigned int8. Single bit to instruct slave to receive or send @ref i2c_rw. +*/ + void i2c_send_7bit_address(u32 i2c, u8 slave, u8 readwrite) { I2C_DR(i2c) = (u8)((slave << 1) | readwrite); } +/*-----------------------------------------------------------------------------*/ +/** @brief I2C Send Data. + +@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. +@param[in] data Unsigned int8. Byte to send. +*/ + void i2c_send_data(u32 i2c, u8 data) { I2C_DR(i2c) = data; } + +/**@}*/ + diff --git a/lib/stm32/spi.c b/lib/stm32/spi.c index 828e123..90675b3 100644 --- a/lib/stm32/spi.c +++ b/lib/stm32/spi.c @@ -1,3 +1,43 @@ +/** @defgroup spi_file SPI + +@ingroup STM32F_files + +@brief libopencm3 STM32Fxxx SPI + +@version 1.0.0 + +@author @htmlonly © @endhtmlonly 2009 Uwe Hermann +@author @htmlonly © @endhtmlonly 2012 Ken Sarkies + +@date 15 October 2012 + +Devices can have up to three SPI peripherals. The common 4-wire full-duplex +mode of operation is supported, along with 3-wire variants using unidirectional +communication modes or half-duplex bidirectional communication. A variety of +options allows many of the SPI variants to be supported. Multimaster operation +is also supported. A CRC can be generated and checked in hardware. + +@note Some JTAG pins need to be remapped if SPI is to be used. + +@note The I2S protocol shares the SPI hardware so the two protocols cannot be +used at the same time on the same peripheral. + +Example: 1Mbps, positive clock polarity, leading edge trigger, 8-bit words, +LSB first. +@code + 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 +@endcode + +@todo need additional functions to aid ISRs in retrieving status + +LGPL License Terms @ref lgpl_license + */ /* * This file is part of the libopencm3 project. * @@ -41,6 +81,17 @@ * reg16 = spi_read(SPI1); // 16-bit read */ +/**@{*/ + +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Reset. + +The SPI peripheral and all its associated configuration registers are placed in the +reset condition. The reset is effected via the RCC peripheral reset system. + +@param[in] spi_peripheral Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_reset(u32 spi_peripheral) { switch (spi_peripheral) { @@ -59,6 +110,25 @@ void spi_reset(u32 spi_peripheral) } } +/*-----------------------------------------------------------------------------*/ +/** @brief Configure the SPI as Master. + +The SPI peripheral is configured as a master with communication parameters +baudrate, data format 8/16 bits, frame format lsb/msb first, clock polarity +and phase. The SPI enable, CRC enable and CRC next controls are not affected. +These must be controlled separately. + +@todo NSS pin handling. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +@param[in] br Unsigned int32. Baudrate @ref spi_baudrate. +@param[in] cpol Unsigned int32. Clock polarity @ref spi_cpol. +@param[in] cpha Unsigned int32. Clock Phase @ref spi_cpha. +@param[in] dff Unsigned int32. Data frame format 8/16 bits @ref spi_dff. +@param[in] lsbfirst Unsigned int32. Frame format lsb/msb first @ref spi_lsbfirst. +@returns int. Error code. +*/ + int spi_init_master(u32 spi, u32 br, u32 cpol, u32 cpha, u32 dff, u32 lsbfirst) { u32 reg32 = SPI_CR1(spi); @@ -82,28 +152,66 @@ int spi_init_master(u32 spi, u32 br, u32 cpol, u32 cpha, u32 dff, u32 lsbfirst) } /* TODO: Error handling? */ +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Enable. + +The SPI peripheral is enabled. + +@todo Error handling? + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_enable(u32 spi) { SPI_CR1(spi) |= SPI_CR1_SPE; /* Enable SPI. */ } /* TODO: Error handling? */ +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Disable. + +The SPI peripheral is disabled. + +@todo Follow procedure from section 23.3.8 in the TRM. +(possibly create a "clean disable" function separately) + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_disable(u32 spi) { u32 reg32; - /* TODO: Follow procedure from section 23.3.8 in the TRM. */ reg32 = SPI_CR1(spi); reg32 &= ~(SPI_CR1_SPE); /* Disable SPI. */ SPI_CR1(spi) = reg32; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Data Write. + +Data is written to the SPI interface. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +@param[in] data Unsigned int16. 8 or 16 bit data to be written. +*/ + void spi_write(u32 spi, u16 data) { /* Write data (8 or 16 bits, depending on DFF) into DR. */ SPI_DR(spi) = data; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Data Write with Blocking. + +Data is written to the SPI interface after the previous write transfer has finished. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +@param[in] data Unsigned int16. 8 or 16 bit data to be written. +*/ + void spi_send(u32 spi, u16 data) { /* Wait for transfer finished. */ @@ -114,6 +222,15 @@ void spi_send(u32 spi, u16 data) SPI_DR(spi) = data; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Data Read. + +Data is read from the SPI interface after the incoming transfer has finished. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +@returns data Unsigned int16. 8 or 16 bit data. +*/ + u16 spi_read(u32 spi) { /* Wait for transfer finished. */ @@ -124,6 +241,17 @@ u16 spi_read(u32 spi) return SPI_DR(spi); } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Data Write and Read Exchange. + +Data is written to the SPI interface, then a read is done after the incoming transfer +has finished. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +@param[in] data Unsigned int16. 8 or 16 bit data to be written. +@returns data Unsigned int16. 8 or 16 bit data. +*/ + u16 spi_xfer(u32 spi, u16 data) { spi_write(spi, data); @@ -136,98 +264,251 @@ u16 spi_xfer(u32 spi, u16 data) return SPI_DR(spi); } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set Bidirectional Simplex Mode. + +The SPI peripheral is set for bidirectional transfers in two-wire simplex mode +(using a clock wire and a bidirectional data wire). + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_bidirectional_mode(u32 spi) { SPI_CR1(spi) |= SPI_CR1_BIDIMODE; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set Unidirectional Mode. + +The SPI peripheral is set for unidirectional transfers. This is used in full duplex +mode or when the SPI is placed in two-wire simplex mode that uses a clock wire and a +unidirectional data wire. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_unidirectional_mode(u32 spi) { SPI_CR1(spi) &= ~SPI_CR1_BIDIMODE; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set Bidirectional Simplex Receive Only Mode. + +The SPI peripheral is set for bidirectional transfers in two-wire simplex mode +(using a clock wire and a bidirectional data wire), and is placed in a receive state. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_bidirectional_receive_only_mode(u32 spi) { SPI_CR1(spi) |= SPI_CR1_BIDIMODE; SPI_CR1(spi) &= ~SPI_CR1_BIDIOE; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set Bidirectional Simplex Receive Only Mode. + +The SPI peripheral is set for bidirectional transfers in two-wire simplex mode +(using a clock wire and a bidirectional data wire), and is placed in a transmit state. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_bidirectional_transmit_only_mode(u32 spi) { SPI_CR1(spi) |= SPI_CR1_BIDIMODE; SPI_CR1(spi) |= SPI_CR1_BIDIOE; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Enable the CRC. + +The SPI peripheral is set to use a CRC field for transmit and receive. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_enable_crc(u32 spi) { SPI_CR1(spi) |= SPI_CR1_CRCEN; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Disable the CRC. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_disable_crc(u32 spi) { SPI_CR1(spi) &= ~SPI_CR1_CRCEN; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Next Transmit is a Data Word + +The next transmission to take place is a data word from the transmit buffer. +This must be called before transmission to distinguish between sending +of a data or CRC word. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_next_tx_from_buffer(u32 spi) { SPI_CR1(spi) &= ~SPI_CR1_CRCNEXT; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Next Transmit is a CRC Word + +The next transmission to take place is a crc word from the hardware crc unit. +This must be called before transmission to distinguish between sending +of a data or CRC word. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_next_tx_from_crc(u32 spi) { SPI_CR1(spi) |= SPI_CR1_CRCNEXT; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set Data Frame Format to 8 bits + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_dff_8bit(u32 spi) { SPI_CR1(spi) &= ~SPI_CR1_DFF; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set Data Frame Format to 16 bits + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_dff_16bit(u32 spi) { SPI_CR1(spi) |= SPI_CR1_DFF; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set Full Duplex (3-wire) Mode + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_full_duplex_mode(u32 spi) { SPI_CR1(spi) &= ~SPI_CR1_RXONLY; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set Receive Only Mode for Simplex (2-wire) Unidirectional Transfers + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_receive_only_mode(u32 spi) { SPI_CR1(spi) |= SPI_CR1_RXONLY; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Enable Slave Management by Hardware + +In slave mode the NSS hardware input is used as a select enable for the slave. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_disable_software_slave_management(u32 spi) { SPI_CR1(spi) &= ~SPI_CR1_SSM; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Enable Slave Management by Software + +In slave mode the NSS hardware input is replaced by an internal software +enable/disable of the slave (@ref spi_set_nss_high). + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_enable_software_slave_management(u32 spi) { SPI_CR1(spi) |= SPI_CR1_SSM; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set the Software NSS Signal High + +In slave mode, and only when software slave management is used, this replaces +the NSS signal with a slave select enable signal. + +@todo these should perhaps be combined with an SSM enable as it is meaningless otherwise + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_nss_high(u32 spi) { SPI_CR1(spi) |= SPI_CR1_SSI; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set the Software NSS Signal Low + +In slave mode, and only when software slave management is used, this replaces +the NSS signal with a slave select disable signal. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_nss_low(u32 spi) { SPI_CR1(spi) &= ~SPI_CR1_SSI; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set to Send LSB First + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_send_lsb_first(u32 spi) { SPI_CR1(spi) |= SPI_CR1_LSBFIRST; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set to Send MSB First + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_send_msb_first(u32 spi) { SPI_CR1(spi) &= ~SPI_CR1_LSBFIRST; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set the Baudrate Prescaler + +@todo Why is this specification different to the spi_init_master baudrate values? + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +@param[in] baudrate Unsigned int8. Baudrate prescale value @ref spi_br_pre. +*/ + void spi_set_baudrate_prescaler(u32 spi, u8 baudrate) { u32 reg32; @@ -240,92 +521,217 @@ void spi_set_baudrate_prescaler(u32 spi, u8 baudrate) SPI_CR1(spi) = reg32; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set to Master Mode + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_master_mode(u32 spi) { SPI_CR1(spi) |= SPI_CR1_MSTR; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set to Slave Mode + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_slave_mode(u32 spi) { SPI_CR1(spi) &= ~SPI_CR1_MSTR; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set the Clock Polarity to High when Idle + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_clock_polarity_1(u32 spi) { SPI_CR1(spi) |= SPI_CR1_CPOL; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set the Clock Polarity to Low when Idle + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_clock_polarity_0(u32 spi) { SPI_CR1(spi) &= ~SPI_CR1_CPOL; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set the Clock Phase to Capture on Trailing Edge + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_clock_phase_1(u32 spi) { SPI_CR1(spi) |= SPI_CR1_CPHA; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set the Clock Phase to Capture on Leading Edge + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_set_clock_phase_0(u32 spi) { SPI_CR1(spi) &= ~SPI_CR1_CPHA; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Enable the Transmit Buffer Empty Interrupt + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_enable_tx_buffer_empty_interrupt(u32 spi) { SPI_CR2(spi) |= SPI_CR2_TXEIE; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Disable the Transmit Buffer Empty Interrupt + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_disable_tx_buffer_empty_interrupt(u32 spi) { SPI_CR2(spi) &= ~SPI_CR2_TXEIE; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Enable the Receive Buffer Ready Interrupt + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_enable_rx_buffer_not_empty_interrupt(u32 spi) { SPI_CR2(spi) |= SPI_CR2_RXNEIE; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Disable the Receive Buffer Ready Interrupt + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_disable_rx_buffer_not_empty_interrupt(u32 spi) { SPI_CR2(spi) &= ~SPI_CR2_RXNEIE; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Enable the Error Interrupt + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_enable_error_interrupt(u32 spi) { SPI_CR2(spi) |= SPI_CR2_ERRIE; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Disable the Error Interrupt + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_disable_error_interrupt(u32 spi) { SPI_CR2(spi) &= ~SPI_CR2_ERRIE; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set the NSS Pin as an Output + +Normally used in master mode to allows the master to place all devices on the +SPI bus into slave mode. Multimaster mode is not possible. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_enable_ss_output(u32 spi) { SPI_CR2(spi) |= SPI_CR2_SSOE; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Set the NSS Pin as an Input + +In master mode this allows the master to sense the presence of other masters. If +NSS is then pulled low the master is placed into slave mode. In slave mode NSS +becomes a slave enable. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_disable_ss_output(u32 spi) { SPI_CR2(spi) &= ~SPI_CR2_SSOE; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Enable Transmit Transfers via DMA + +This allows transmissions to proceed unattended using DMA to move data to the +transmit buffer as it becomes available. The DMA channels provided for each +SPI peripheral are given in the Technical Manual DMA section. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_enable_tx_dma(u32 spi) { SPI_CR2(spi) |= SPI_CR2_TXDMAEN; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Disable Transmit Transfers via DMA + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_disable_tx_dma(u32 spi) { SPI_CR2(spi) &= ~SPI_CR2_TXDMAEN; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Enable Receive Transfers via DMA + +This allows received data streams to proceed unattended using DMA to move data from +the receive buffer as data becomes available. The DMA channels provided for each +SPI peripheral are given in the Technical Manual DMA section. + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_enable_rx_dma(u32 spi) { SPI_CR2(spi) |= SPI_CR2_RXDMAEN; } +/*-----------------------------------------------------------------------------*/ +/** @brief SPI Disable Receive Transfers via DMA + +@param[in] spi Unsigned int32. SPI peripheral identifier @ref spi_reg_base. +*/ + void spi_disable_rx_dma(u32 spi) { SPI_CR2(spi) &= ~SPI_CR2_RXDMAEN; } + +/**@}*/ -- cgit v1.2.3