mirror of https://github.com/ARMmbed/mbed-os.git
Fixes for SPI slave implementation (#336)
* Start on SPI slave comms test * Free pins in SPI and SPISlave destructor * Improve LPC1768 readable()pull/15530/head
parent
e6043218fd
commit
d1dbb405c8
|
@ -33,7 +33,7 @@ namespace mbed {
|
||||||
|
|
||||||
/** A SPI slave, used for communicating with a SPI master device.
|
/** A SPI slave, used for communicating with a SPI master device.
|
||||||
*
|
*
|
||||||
* The default format is set to 8 bits, mode 0 and a clock frequency of 1MHz.
|
* The default format is set to 8 bits, mode 0.
|
||||||
*
|
*
|
||||||
* @note Synchronization level: Not protected
|
* @note Synchronization level: Not protected
|
||||||
*
|
*
|
||||||
|
@ -80,6 +80,11 @@ public:
|
||||||
SPISlave(const spi_pinmap_t &pinmap);
|
SPISlave(const spi_pinmap_t &pinmap);
|
||||||
SPISlave(const spi_pinmap_t &&) = delete; // prevent passing of temporary objects
|
SPISlave(const spi_pinmap_t &&) = delete; // prevent passing of temporary objects
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructor. Frees the SPI peripheral so it can be used elsewhere.
|
||||||
|
*/
|
||||||
|
~SPISlave();
|
||||||
|
|
||||||
/** Configure the data transmission format.
|
/** Configure the data transmission format.
|
||||||
*
|
*
|
||||||
* @param bits Number of bits per SPI frame (4 - 16).
|
* @param bits Number of bits per SPI frame (4 - 16).
|
||||||
|
@ -96,12 +101,6 @@ public:
|
||||||
*/
|
*/
|
||||||
void format(int bits, int mode = 0);
|
void format(int bits, int mode = 0);
|
||||||
|
|
||||||
/** Set the SPI bus clock frequency.
|
|
||||||
*
|
|
||||||
* @param hz Clock frequency in hz (default = 1MHz).
|
|
||||||
*/
|
|
||||||
void frequency(int hz = 1000000);
|
|
||||||
|
|
||||||
/** Polls the SPI to see if data has been received.
|
/** Polls the SPI to see if data has been received.
|
||||||
*
|
*
|
||||||
* @return Presence of received data.
|
* @return Presence of received data.
|
||||||
|
@ -133,8 +132,6 @@ protected:
|
||||||
int _bits;
|
int _bits;
|
||||||
/* Clock phase and polarity */
|
/* Clock phase and polarity */
|
||||||
int _mode;
|
int _mode;
|
||||||
/* Clock frequency */
|
|
||||||
int _hz;
|
|
||||||
|
|
||||||
#endif //!defined(DOXYGEN_ONLY)
|
#endif //!defined(DOXYGEN_ONLY)
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,23 +24,34 @@ namespace mbed {
|
||||||
SPISlave::SPISlave(PinName mosi, PinName miso, PinName sclk, PinName ssel) :
|
SPISlave::SPISlave(PinName mosi, PinName miso, PinName sclk, PinName ssel) :
|
||||||
_spi(),
|
_spi(),
|
||||||
_bits(8),
|
_bits(8),
|
||||||
_mode(0),
|
_mode(0)
|
||||||
_hz(1000000)
|
|
||||||
{
|
{
|
||||||
spi_init(&_spi, mosi, miso, sclk, ssel);
|
spi_init(&_spi, mosi, miso, sclk, ssel);
|
||||||
spi_format(&_spi, _bits, _mode, 1);
|
spi_format(&_spi, _bits, _mode, 1);
|
||||||
spi_frequency(&_spi, _hz);
|
|
||||||
|
// For legacy compatibility, tell the HAL to set the frequency to 1MHz.
|
||||||
|
// This is done even though it does not make sense to set the frequency of a slave device;
|
||||||
|
// it has to run at whatever SCLK frequency the master supplies.
|
||||||
|
spi_frequency(&_spi, 1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
SPISlave::SPISlave(const spi_pinmap_t &pinmap) :
|
SPISlave::SPISlave(const spi_pinmap_t &pinmap) :
|
||||||
_spi(),
|
_spi(),
|
||||||
_bits(8),
|
_bits(8),
|
||||||
_mode(0),
|
_mode(0)
|
||||||
_hz(1000000)
|
|
||||||
{
|
{
|
||||||
spi_init_direct(&_spi, &pinmap);
|
spi_init_direct(&_spi, &pinmap);
|
||||||
spi_format(&_spi, _bits, _mode, 1);
|
spi_format(&_spi, _bits, _mode, 1);
|
||||||
spi_frequency(&_spi, _hz);
|
|
||||||
|
// For legacy compatibility, tell the HAL to set the frequency to 1MHz.
|
||||||
|
// This is done even though it does not make sense to set the frequency of a slave device;
|
||||||
|
// it has to run at whatever SCLK frequency the master supplies.
|
||||||
|
spi_frequency(&_spi, 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPISlave::~SPISlave()
|
||||||
|
{
|
||||||
|
spi_free(&_spi);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPISlave::format(int bits, int mode)
|
void SPISlave::format(int bits, int mode)
|
||||||
|
@ -50,12 +61,6 @@ void SPISlave::format(int bits, int mode)
|
||||||
spi_format(&_spi, _bits, _mode, 1);
|
spi_format(&_spi, _bits, _mode, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPISlave::frequency(int hz)
|
|
||||||
{
|
|
||||||
_hz = hz;
|
|
||||||
spi_frequency(&_spi, _hz);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SPISlave::receive(void)
|
int SPISlave::receive(void)
|
||||||
{
|
{
|
||||||
return (spi_slave_receive(&_spi));
|
return (spi_slave_receive(&_spi));
|
||||||
|
|
|
@ -71,6 +71,12 @@ struct i2c_s {
|
||||||
struct spi_s {
|
struct spi_s {
|
||||||
LPC_SSP_TypeDef *spi;
|
LPC_SSP_TypeDef *spi;
|
||||||
uint8_t bits_per_word;
|
uint8_t bits_per_word;
|
||||||
|
|
||||||
|
// Pin names, so that we can unmap them when the SPI is freed
|
||||||
|
PinName mosi_pin;
|
||||||
|
PinName miso_pin;
|
||||||
|
PinName sclk_pin;
|
||||||
|
PinName ssel_pin;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct flash_s {
|
struct flash_s {
|
||||||
|
|
|
@ -34,18 +34,30 @@ void spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap) {
|
||||||
case SPI_1: LPC_SC->PCONP |= 1 << 10; break;
|
case SPI_1: LPC_SC->PCONP |= 1 << 10; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pin out the spi pins
|
// Pin out the spi pins.
|
||||||
pin_function(pinmap->mosi_pin, pinmap->mosi_function);
|
// Note: SCLK is the only pin that is always required.
|
||||||
pin_mode(pinmap->mosi_pin, PullNone);
|
if(pinmap->mosi_pin != NC)
|
||||||
pin_function(pinmap->miso_pin, pinmap->miso_function);
|
{
|
||||||
pin_mode(pinmap->miso_pin, PullNone);
|
pin_function(pinmap->mosi_pin, pinmap->mosi_function);
|
||||||
|
pin_mode(pinmap->mosi_pin, PullNone);
|
||||||
|
}
|
||||||
|
if(pinmap->miso_pin != NC)
|
||||||
|
{
|
||||||
|
pin_function(pinmap->miso_pin, pinmap->miso_function);
|
||||||
|
pin_mode(pinmap->miso_pin, PullNone);
|
||||||
|
}
|
||||||
pin_function(pinmap->sclk_pin, pinmap->sclk_function);
|
pin_function(pinmap->sclk_pin, pinmap->sclk_function);
|
||||||
pin_mode(pinmap->sclk_pin, PullNone);
|
pin_mode(pinmap->sclk_pin, PullNone);
|
||||||
|
|
||||||
if (pinmap->ssel_pin != NC) {
|
if (pinmap->ssel_pin != NC) {
|
||||||
pin_function(pinmap->ssel_pin, pinmap->ssel_function);
|
pin_function(pinmap->ssel_pin, pinmap->ssel_function);
|
||||||
pin_mode(pinmap->ssel_pin, PullNone);
|
pin_mode(pinmap->ssel_pin, PullNone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save pins
|
||||||
|
obj->mosi_pin = pinmap->mosi_pin;
|
||||||
|
obj->miso_pin = pinmap->miso_pin;
|
||||||
|
obj->sclk_pin = pinmap->sclk_pin;
|
||||||
|
obj->ssel_pin = pinmap->ssel_pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
SPIName spi_get_peripheral_name(PinName mosi, PinName miso, PinName sclk)
|
SPIName spi_get_peripheral_name(PinName mosi, PinName miso, PinName sclk)
|
||||||
|
@ -80,7 +92,14 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
|
||||||
spi_init_direct(obj, &pinmap);
|
spi_init_direct(obj, &pinmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void spi_free(spi_t *obj) {}
|
void spi_free(spi_t *obj)
|
||||||
|
{
|
||||||
|
// Reset all pins to GPIO function
|
||||||
|
if(obj->mosi_pin != NC) pin_function(obj->mosi_pin, 0);
|
||||||
|
if(obj->miso_pin != NC) pin_function(obj->miso_pin, 0);
|
||||||
|
pin_function(obj->sclk_pin, 0);
|
||||||
|
if(obj->ssel_pin != NC) pin_function(obj->ssel_pin, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void spi_format(spi_t *obj, int bits, int mode, int slave) {
|
void spi_format(spi_t *obj, int bits, int mode, int slave) {
|
||||||
ssp_disable(obj);
|
ssp_disable(obj);
|
||||||
|
@ -233,7 +252,7 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
|
||||||
}
|
}
|
||||||
|
|
||||||
int spi_slave_receive(spi_t *obj) {
|
int spi_slave_receive(spi_t *obj) {
|
||||||
return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0);
|
return ssp_readable(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
int spi_slave_read(spi_t *obj) {
|
int spi_slave_read(spi_t *obj) {
|
||||||
|
|
Loading…
Reference in New Issue