mirror of https://github.com/ARMmbed/mbed-os.git
[NUCLEO_F030R8] Add SPI api, corrections in I2C
parent
08941aaba1
commit
ca173a1867
|
@ -44,7 +44,7 @@
|
||||||
#define DEVICE_I2C 1
|
#define DEVICE_I2C 1
|
||||||
#define DEVICE_I2CSLAVE 0
|
#define DEVICE_I2CSLAVE 0
|
||||||
|
|
||||||
#define DEVICE_SPI 0
|
#define DEVICE_SPI 1
|
||||||
#define DEVICE_SPISLAVE 0
|
#define DEVICE_SPISLAVE 0
|
||||||
|
|
||||||
#define DEVICE_RTC 1
|
#define DEVICE_RTC 1
|
||||||
|
|
|
@ -42,12 +42,12 @@
|
||||||
#define LONG_TIMEOUT ((int)0x8000)
|
#define LONG_TIMEOUT ((int)0x8000)
|
||||||
|
|
||||||
static const PinMap PinMap_I2C_SDA[] = {
|
static const PinMap PinMap_I2C_SDA[] = {
|
||||||
{PB_9, I2C_1, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_OD, GPIO_PuPd_NOPULL, GPIO_AF_1)},
|
{PB_9, I2C_1, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_OD, GPIO_PuPd_UP, GPIO_AF_1)},
|
||||||
{NC, NC, 0}
|
{NC, NC, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const PinMap PinMap_I2C_SCL[] = {
|
static const PinMap PinMap_I2C_SCL[] = {
|
||||||
{PB_8, I2C_1, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_OD, GPIO_PuPd_NOPULL, GPIO_AF_1)},
|
{PB_8, I2C_1, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_OD, GPIO_PuPd_UP, GPIO_AF_1)},
|
||||||
{NC, NC, 0}
|
{NC, NC, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -71,10 +71,10 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
|
||||||
//}
|
//}
|
||||||
|
|
||||||
// Configure I2C pins
|
// Configure I2C pins
|
||||||
pinmap_pinout(sda, PinMap_I2C_SDA);
|
|
||||||
pinmap_pinout(scl, PinMap_I2C_SCL);
|
pinmap_pinout(scl, PinMap_I2C_SCL);
|
||||||
pin_mode(sda, OpenDrain);
|
|
||||||
pin_mode(scl, OpenDrain);
|
pin_mode(scl, OpenDrain);
|
||||||
|
pinmap_pinout(sda, PinMap_I2C_SDA);
|
||||||
|
pin_mode(sda, OpenDrain);
|
||||||
|
|
||||||
// Reset to clear pending flags if any
|
// Reset to clear pending flags if any
|
||||||
i2c_reset(obj);
|
i2c_reset(obj);
|
||||||
|
@ -120,12 +120,15 @@ void i2c_frequency(i2c_t *obj, int hz) {
|
||||||
|
|
||||||
inline int i2c_start(i2c_t *obj) {
|
inline int i2c_start(i2c_t *obj) {
|
||||||
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
|
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
|
||||||
int timeout = LONG_TIMEOUT;
|
int timeout;
|
||||||
|
|
||||||
// Test BUSY Flag
|
// Test BUSY Flag
|
||||||
while (I2C_GetFlagStatus(i2c, I2C_ISR_BUSY) != RESET)
|
timeout = LONG_TIMEOUT;
|
||||||
{
|
while (I2C_GetFlagStatus(i2c, I2C_ISR_BUSY) != RESET) {
|
||||||
if ((timeout--) == 0) return 0;
|
timeout--;
|
||||||
|
if (timeout == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
I2C_GenerateSTART(i2c, ENABLE);
|
I2C_GenerateSTART(i2c, ENABLE);
|
||||||
|
@ -135,27 +138,21 @@ inline int i2c_start(i2c_t *obj) {
|
||||||
|
|
||||||
inline int i2c_stop(i2c_t *obj) {
|
inline int i2c_stop(i2c_t *obj) {
|
||||||
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
|
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
|
||||||
|
|
||||||
I2C_GenerateSTOP(i2c, ENABLE);
|
I2C_GenerateSTOP(i2c, ENABLE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
|
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
|
||||||
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
|
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
|
||||||
int timeout;
|
|
||||||
int count;
|
int count;
|
||||||
int value;
|
int value;
|
||||||
|
|
||||||
if (length == 0) return 0;
|
if (length == 0) return 0;
|
||||||
|
|
||||||
// Configure slave address, nbytes, reload, end mode and start or stop generation
|
// Configure slave address, nbytes, reload, end mode and start or stop generation
|
||||||
if (stop) {
|
I2C_TransferHandling(i2c, address, length, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
|
||||||
I2C_TransferHandling(i2c, address, length, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
I2C_TransferHandling(i2c, address, length, I2C_Reload_Mode, I2C_Generate_Start_Read);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read all bytes
|
// Read all bytes
|
||||||
for (count = 0; count < length; count++) {
|
for (count = 0; count < length; count++) {
|
||||||
|
@ -163,40 +160,25 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
|
||||||
data[count] = (char)value;
|
data[count] = (char)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stop) {
|
|
||||||
// Wait until STOPF flag is set
|
|
||||||
timeout = LONG_TIMEOUT;
|
|
||||||
while (I2C_GetFlagStatus(i2c, I2C_ISR_STOPF) == RESET)
|
|
||||||
{
|
|
||||||
if ((timeout--) == 0) return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear STOPF flag
|
|
||||||
I2C_ClearFlag(i2c, I2C_ICR_STOPCF);
|
|
||||||
}
|
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
|
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
|
||||||
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
|
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
|
||||||
int timeout;
|
//int timeout;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
|
if (length == 0) return 0;
|
||||||
|
|
||||||
|
// TODO: the stop is always sent even with I2C_SoftEnd_Mode. To be corrected.
|
||||||
|
|
||||||
// Test BUSY Flag
|
|
||||||
//timeout = LONG_TIMEOUT;
|
|
||||||
//while (I2C_GetFlagStatus(i2c, I2C_ISR_BUSY) != RESET)
|
|
||||||
//{
|
|
||||||
// if((timeout--) == 0) return 0;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Configure slave address, nbytes, reload, end mode and start or stop generation
|
// Configure slave address, nbytes, reload, end mode and start or stop generation
|
||||||
if (stop) {
|
//if (stop) {
|
||||||
I2C_TransferHandling(i2c, address, length, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);
|
I2C_TransferHandling(i2c, address, length, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);
|
||||||
}
|
//}
|
||||||
else {
|
//else {
|
||||||
I2C_TransferHandling(i2c, address, length, I2C_Reload_Mode, I2C_Generate_Start_Write);
|
// I2C_TransferHandling(i2c, address, length, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
|
||||||
}
|
//}
|
||||||
|
|
||||||
// Write all bytes
|
// Write all bytes
|
||||||
for (count = 0; count < length; count++) {
|
for (count = 0; count < length; count++) {
|
||||||
|
@ -206,17 +188,20 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if (stop) {
|
if (stop) {
|
||||||
// Wait until STOPF flag is set
|
// Wait until STOPF flag is set
|
||||||
timeout = LONG_TIMEOUT;
|
timeout = LONG_TIMEOUT;
|
||||||
while (I2C_GetFlagStatus(i2c, I2C_ISR_STOPF) == RESET)
|
while (I2C_GetFlagStatus(i2c, I2C_ISR_STOPF) == RESET) {
|
||||||
{
|
timeout--;
|
||||||
if ((timeout--) == 0) return 0;
|
if (timeout == 0) {
|
||||||
}
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Clear STOPF flag
|
// Clear STOPF flag
|
||||||
I2C_ClearFlag(i2c, I2C_ICR_STOPCF);
|
I2C_ClearFlag(i2c, I2C_ICR_STOPCF);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -224,11 +209,15 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
|
||||||
int i2c_byte_read(i2c_t *obj, int last) {
|
int i2c_byte_read(i2c_t *obj, int last) {
|
||||||
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
|
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
|
||||||
uint8_t data;
|
uint8_t data;
|
||||||
int timeout = FLAG_TIMEOUT;
|
int timeout;
|
||||||
|
|
||||||
// Wait until the byte is received
|
// Wait until the byte is received
|
||||||
|
timeout = FLAG_TIMEOUT;
|
||||||
while (I2C_GetFlagStatus(i2c, I2C_ISR_RXNE) == RESET) {
|
while (I2C_GetFlagStatus(i2c, I2C_ISR_RXNE) == RESET) {
|
||||||
if ((timeout--) == 0) return 0;
|
timeout--;
|
||||||
|
if (timeout == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data = I2C_ReceiveData(i2c);
|
data = I2C_ReceiveData(i2c);
|
||||||
|
@ -238,21 +227,18 @@ int i2c_byte_read(i2c_t *obj, int last) {
|
||||||
|
|
||||||
int i2c_byte_write(i2c_t *obj, int data) {
|
int i2c_byte_write(i2c_t *obj, int data) {
|
||||||
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
|
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
|
||||||
int timeout = FLAG_TIMEOUT;
|
int timeout;
|
||||||
|
|
||||||
// Wait until TXIS flag is set
|
// Wait until the previous byte is transmitted
|
||||||
timeout = LONG_TIMEOUT;
|
timeout = FLAG_TIMEOUT;
|
||||||
while (I2C_GetFlagStatus(i2c, I2C_ISR_TXIS) == RESET)
|
while (I2C_GetFlagStatus(i2c, I2C_ISR_TXIS) == RESET) {
|
||||||
{
|
timeout--;
|
||||||
if ((timeout--) == 0) return 0;
|
if (timeout == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
I2C_SendData(i2c, (uint8_t)data);
|
I2C_SendData(i2c, (uint8_t)data);
|
||||||
|
|
||||||
// Wait until the byte is transmitted
|
|
||||||
//while (I2C_GetFlagStatus(i2c, I2C_ISR_TCR) == RESET) {
|
|
||||||
// if ((timeout--) == 0) return 0;
|
|
||||||
//}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,258 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
*******************************************************************************
|
||||||
|
* Copyright (c) 2014, STMicroelectronics
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
#include "spi_api.h"
|
||||||
|
|
||||||
|
#if DEVICE_SPI
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "cmsis.h"
|
||||||
|
#include "pinmap.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
static const PinMap PinMap_SPI_MOSI[] = {
|
||||||
|
{PA_7, SPI_1, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_NOPULL, GPIO_AF_0)},
|
||||||
|
{NC, NC, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const PinMap PinMap_SPI_MISO[] = {
|
||||||
|
{PA_6, SPI_1, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_NOPULL, GPIO_AF_0)},
|
||||||
|
{NC, NC, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const PinMap PinMap_SPI_SCLK[] = {
|
||||||
|
{PA_5, SPI_1, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_NOPULL, GPIO_AF_0)},
|
||||||
|
{NC, NC, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Only used in Slave mode
|
||||||
|
static const PinMap PinMap_SPI_SSEL[] = {
|
||||||
|
{PB_6, SPI_1, STM_PIN_DATA(GPIO_Mode_IN, GPIO_OType_PP, GPIO_PuPd_NOPULL, 0)}, // Generic IO, not real H/W NSS pin
|
||||||
|
{NC, NC, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void init_spi(spi_t *obj) {
|
||||||
|
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
||||||
|
SPI_InitTypeDef SPI_InitStructure;
|
||||||
|
|
||||||
|
SPI_Cmd(spi, DISABLE);
|
||||||
|
|
||||||
|
SPI_InitStructure.SPI_Mode = obj->mode;
|
||||||
|
SPI_InitStructure.SPI_NSS = obj->nss;
|
||||||
|
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
|
||||||
|
SPI_InitStructure.SPI_DataSize = obj->bits;
|
||||||
|
SPI_InitStructure.SPI_CPOL = obj->cpol;
|
||||||
|
SPI_InitStructure.SPI_CPHA = obj->cpha;
|
||||||
|
SPI_InitStructure.SPI_BaudRatePrescaler = obj->br_presc;
|
||||||
|
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
|
||||||
|
SPI_InitStructure.SPI_CRCPolynomial = 7;
|
||||||
|
SPI_Init(spi, &SPI_InitStructure);
|
||||||
|
|
||||||
|
SPI_RxFIFOThresholdConfig(spi, SPI_RxFIFOThreshold_QF);
|
||||||
|
|
||||||
|
SPI_Cmd(spi, ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
|
||||||
|
// Determine the SPI to use
|
||||||
|
SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
|
||||||
|
SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
|
||||||
|
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
||||||
|
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
|
||||||
|
|
||||||
|
SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
|
||||||
|
SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
|
||||||
|
|
||||||
|
obj->spi = (SPIName)pinmap_merge(spi_data, spi_cntl);
|
||||||
|
|
||||||
|
if (obj->spi == (SPIName)NC) {
|
||||||
|
error("SPI pinout mapping failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable SPI clock
|
||||||
|
if (obj->spi == SPI_1) {
|
||||||
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
|
||||||
|
}
|
||||||
|
if (obj->spi == SPI_2) {
|
||||||
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure the SPI pins
|
||||||
|
pinmap_pinout(mosi, PinMap_SPI_MOSI);
|
||||||
|
pinmap_pinout(miso, PinMap_SPI_MISO);
|
||||||
|
pinmap_pinout(sclk, PinMap_SPI_SCLK);
|
||||||
|
|
||||||
|
// Save new values
|
||||||
|
obj->bits = SPI_DataSize_8b;
|
||||||
|
obj->cpol = SPI_CPOL_Low;
|
||||||
|
obj->cpha = SPI_CPHA_1Edge;
|
||||||
|
obj->br_presc = SPI_BaudRatePrescaler_8; // 1 MHz
|
||||||
|
|
||||||
|
if (ssel == NC) { // Master
|
||||||
|
obj->mode = SPI_Mode_Master;
|
||||||
|
obj->nss = SPI_NSS_Soft;
|
||||||
|
}
|
||||||
|
else { // Slave
|
||||||
|
pinmap_pinout(ssel, PinMap_SPI_SSEL);
|
||||||
|
obj->mode = SPI_Mode_Slave;
|
||||||
|
obj->nss = SPI_NSS_Soft;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_spi(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_free(spi_t *obj) {
|
||||||
|
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
||||||
|
SPI_I2S_DeInit(spi);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_format(spi_t *obj, int bits, int mode, int slave) {
|
||||||
|
// Save new values
|
||||||
|
if (bits == 8) {
|
||||||
|
obj->bits = SPI_DataSize_8b;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
obj->bits = SPI_DataSize_16b;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case 0:
|
||||||
|
obj->cpol = SPI_CPOL_Low;
|
||||||
|
obj->cpha = SPI_CPHA_1Edge;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
obj->cpol = SPI_CPOL_Low;
|
||||||
|
obj->cpha = SPI_CPHA_2Edge;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
obj->cpol = SPI_CPOL_High;
|
||||||
|
obj->cpha = SPI_CPHA_1Edge;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
obj->cpol = SPI_CPOL_High;
|
||||||
|
obj->cpha = SPI_CPHA_2Edge;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slave == 0) {
|
||||||
|
obj->mode = SPI_Mode_Master;
|
||||||
|
obj->nss = SPI_NSS_Soft;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
obj->mode = SPI_Mode_Slave;
|
||||||
|
obj->nss = SPI_NSS_Hard;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_spi(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_frequency(spi_t *obj, int hz) {
|
||||||
|
// Get SPI clock frequency
|
||||||
|
uint32_t PCLK = SystemCoreClock;
|
||||||
|
|
||||||
|
// Choose the baud rate divisor (between 2 and 256)
|
||||||
|
uint32_t divisor = PCLK / hz;
|
||||||
|
|
||||||
|
// Find the nearest power-of-2
|
||||||
|
divisor = (divisor > 0 ? divisor-1 : 0);
|
||||||
|
divisor |= divisor >> 1;
|
||||||
|
divisor |= divisor >> 2;
|
||||||
|
divisor |= divisor >> 4;
|
||||||
|
divisor |= divisor >> 8;
|
||||||
|
divisor |= divisor >> 16;
|
||||||
|
divisor++;
|
||||||
|
|
||||||
|
uint32_t baud_rate = __builtin_ffs(divisor) - 2;
|
||||||
|
|
||||||
|
// Save new value
|
||||||
|
obj->br_presc = ((baud_rate > 7) ? (7 << 3) : (baud_rate << 3));
|
||||||
|
|
||||||
|
init_spi(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ssp_readable(spi_t *obj) {
|
||||||
|
int status;
|
||||||
|
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
||||||
|
// Check if data is received
|
||||||
|
status = ((SPI_I2S_GetFlagStatus(spi, SPI_I2S_FLAG_RXNE) != RESET) ? 1 : 0);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ssp_writeable(spi_t *obj) {
|
||||||
|
int status;
|
||||||
|
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
||||||
|
// Check if data is transmitted
|
||||||
|
status = ((SPI_I2S_GetFlagStatus(spi, SPI_I2S_FLAG_TXE) != RESET) ? 1 : 0);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ssp_write(spi_t *obj, int value) {
|
||||||
|
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
||||||
|
while (!ssp_writeable(obj));
|
||||||
|
SPI_SendData8(spi, (uint8_t)value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ssp_read(spi_t *obj) {
|
||||||
|
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
||||||
|
while (!ssp_readable(obj));
|
||||||
|
return (int)SPI_ReceiveData8(spi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ssp_busy(spi_t *obj) {
|
||||||
|
int status;
|
||||||
|
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
||||||
|
status = ((SPI_I2S_GetFlagStatus(spi, SPI_I2S_FLAG_BSY) != RESET) ? 1 : 0);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int spi_master_write(spi_t *obj, int value) {
|
||||||
|
ssp_write(obj, value);
|
||||||
|
return ssp_read(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
int spi_slave_receive(spi_t *obj) {
|
||||||
|
return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0);
|
||||||
|
};
|
||||||
|
|
||||||
|
int spi_slave_read(spi_t *obj) {
|
||||||
|
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
||||||
|
return (int)SPI_ReceiveData8(spi);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_slave_write(spi_t *obj, int value) {
|
||||||
|
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
||||||
|
while (!ssp_writeable(obj));
|
||||||
|
SPI_SendData8(spi, (uint8_t)value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int spi_busy(spi_t *obj) {
|
||||||
|
return ssp_busy(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue