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
Jamie Smith 2024-09-03 19:34:13 -07:00 committed by GitHub
parent e6043218fd
commit d1dbb405c8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 56 additions and 29 deletions

View File

@ -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)
}; };

View File

@ -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));

View File

@ -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 {

View File

@ -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) {