Added some buxfixes to spi code

This commit is contained in:
Dario 2023-05-16 21:15:53 +01:00
parent 0bc924bba2
commit 38bdbbe526
12 changed files with 186 additions and 68 deletions

11
include/sta/config.hpp Normal file
View File

@ -0,0 +1,11 @@
#ifndef STA_CONFIG
#define STA_CONFIG
// Use the raspberry pi for this project.
#include <sta/raspi/mcu/common.hpp>
// #define DEBUG
#define STA_PRINTF_USE_STDLIB
#define STA_DEBUG_PRINTF
#endif

View File

@ -70,14 +70,6 @@ namespace sta
*/ */
void print(uint32_t num, IntegerBase base = IntegerBase::DEC); void print(uint32_t num, IntegerBase base = IntegerBase::DEC);
/**
* @brief Print integer in selected base.
*
* @param num Integer
* @param base Integer base
*/
void print(size_t num, IntegerBase base = IntegerBase::DEC);
/** /**
* @brief Print c-string. * @brief Print c-string.
* *
@ -143,14 +135,6 @@ namespace sta
*/ */
void println(uint32_t num, IntegerBase base = IntegerBase::DEC); void println(uint32_t num, IntegerBase base = IntegerBase::DEC);
/**
* @brief Print integer in selected base followed by a new-line.
*
* @param num Integer
* @param base Integer base
*/
void println(size_t num, IntegerBase base = IntegerBase::DEC);
/** /**
* @brief Print c-string followed by a new-line. * @brief Print c-string followed by a new-line.
* *

View File

@ -0,0 +1,44 @@
/**
* @file
* @brief Delay functions.
*
* Configuration:
* * STA_RASPI_DELAY_US_TIM: 1 MHz TIM instance used by sta::delayUs
*
* NOTE: TIM time base must be started before use of sta::delayUs by calling sta::initHAL.
* When using startup system task this is handled automatically.
*/
#ifndef STA_CORE_RASPI_DELAY_HPP
#define STA_CORE_RASPI_DELAY_HPP
// Only enable module on RASPI platform
#include <sta/config.hpp>
#if defined(STA_PLATFORM_RASPI) || defined(DOXYGEN)
#include <cstdint>
namespace sta
{
/**
* @brief Millisecond delay.
*
* @param ms Milliseconds
*/
void delayMs(uint32_t ms);
/**
* @brief Microsecond delay.
*
* @param us Microseconds
*/
void delayUs(uint32_t us);
} // namespace sta
#endif // STA_PLATFORM_RASPI
#endif // STA_CORE_RASPI_DELAY_HPP

View File

@ -37,12 +37,6 @@ namespace sta
uint8_t pin_; uint8_t pin_;
GpioMode mode_; GpioMode mode_;
}; };
class DummyGpioPin : public RaspiGpioPin {
DummyGpioPin();
void setState(GpioPinState state) override;
};
} // namespace sta } // namespace sta
#endif // STA_RASPI_GPIO_ENABLED #endif // STA_RASPI_GPIO_ENABLED

View File

@ -36,9 +36,15 @@ namespace sta
int spifd_; int spifd_;
bool open_; bool open_;
const bool persistent_open_; const bool persistent_open_;
SPISettings settings_;
uint8_t mode_;
uint8_t dataSize_;
uint8_t bitOrder_;
uint32_t clkSpeed_;
void update_setting(int setting, int value); void update_setting(int setting, int value);
int get_setting(int setting, void * rslt_ptr); void get_setting(int setting, void * rslt_ptr);
void update_settings(); void update_settings();
}; };

View File

@ -81,8 +81,7 @@ namespace sta
* *
* @return %SPI settings * @return %SPI settings
*/ */
const SPISettings & settings() const; const SPISettings & settings();
/** /**
* @brief Acquire usage rights to use the interface. * @brief Acquire usage rights to use the interface.

View File

@ -2,6 +2,8 @@
#include <cinttypes> #include <cinttypes>
#include <cstring> #include <cstring>
#include <sta/assert.hpp>
#include <sta/lang.hpp>
namespace sta namespace sta
{ {
@ -22,17 +24,17 @@ namespace sta
print(buffer); print(buffer);
} }
void print(uint8_t num, IntegerBase base /* = IntegerBase::DEC */) void print(uint8_t num, IntegerBase base)
{ {
printBase(num, base, "%" PRIu8, sizeof(num)); printBase(num, base, "%" PRIu8, sizeof(num));
} }
void print(uint16_t num, IntegerBase base /* = IntegerBase::DEC */) void print(uint16_t num, IntegerBase base)
{ {
printBase(num, base, "%" PRIu16, sizeof(num)); printBase(num, base, "%" PRIu16, sizeof(num));
} }
void print(uint32_t num, IntegerBase base /* = IntegerBase::DEC */) void print(uint32_t num, IntegerBase base)
{ {
printBase(num, base, "%" PRIu32, sizeof(num)); printBase(num, base, "%" PRIu32, sizeof(num));
} }
@ -42,6 +44,10 @@ namespace sta
print(str, strlen(str)); print(str, strlen(str));
} }
void print(const char * str, size_t length) {
print(str, length);
}
void println() void println()
{ {
print("\r\n", 2); print("\r\n", 2);
@ -65,19 +71,19 @@ namespace sta
println(); println();
} }
void println(uint8_t num, IntegerBase base /* = IntegerBase::DEC */) void println(uint8_t num, IntegerBase base)
{ {
print(num, base); print(num, base);
println(); println();
} }
void println(uint16_t num, IntegerBase base /* = IntegerBase::DEC */) void println(uint16_t num, IntegerBase base)
{ {
print(num, base); print(num, base);
println(); println();
} }
void println(uint32_t num, IntegerBase base /* = IntegerBase::DEC */) void println(uint32_t num, IntegerBase base)
{ {
print(num, base); print(num, base);
println(); println();
@ -96,12 +102,26 @@ namespace sta
void printBase(uintmax_t value, IntegerBase base, const char * fmt, size_t size) void printBase(uintmax_t value, IntegerBase base, const char * fmt, size_t size)
{ {
switch (base)
{
case IntegerBase::DEC:
printDec(value, fmt);
break;
case IntegerBase::HEX:
printHex(value, size);
break;
case IntegerBase::BIN:
printBin(value, size);
break;
default:
STA_ASSERT_MSG(false, "Case for IntegerBase enum not handled");
STA_UNREACHABLE();
}
} }
void printDec(uintmax_t value, const char * fmt) void printDec(uintmax_t value, const char * fmt)
{ {
printf(fmt, value);
} }
void printBin(uintmax_t value, size_t digits) void printBin(uintmax_t value, size_t digits)
@ -111,7 +131,7 @@ namespace sta
void printHex(uintmax_t value, size_t digits) void printHex(uintmax_t value, size_t digits)
{ {
printf("%x", value);
} }
} // namespace sta } // namespace sta

23
src/raspi/delay.cpp Normal file
View File

@ -0,0 +1,23 @@
#include <sta/raspi/delay.hpp>
#ifdef STA_PLATFORM_RASPI
#include <sta/raspi/hal.hpp>
#include <sta/assert.hpp>
#include <sta/lang.hpp>
namespace sta
{
void delayMs(uint32_t ms)
{
delay(ms);
}
void delayUs(uint32_t us)
{
delayMicroseconds(us);
}
} // namespace sta
#endif // STA_PLATFORM_RASPI

View File

@ -16,15 +16,12 @@ namespace sta
digitalWrite(pin_, state == GpioPinState::GPIO_LOW ? LOW : HIGH); digitalWrite(pin_, state == GpioPinState::GPIO_LOW ? LOW : HIGH);
} }
DummyGpioPin::DummyGpioPin() : RaspiGpioPin { -1 , GpioMode::GPIO_INPUT } class DummyGpioPin : public RaspiGpioPin {
{ public:
DummyGpioPin() : RaspiGpioPin { 0, GpioMode::GPIO_INPUT } {}
} void setState(GpioPinState state) override {}
};
void DummyGpioPin::setState(GpioPinState state)
{
// Don't do anything.
}
static DummyGpioPin dummyGpio; static DummyGpioPin dummyGpio;

View File

@ -10,12 +10,14 @@
#include <cstdlib> #include <cstdlib>
#include <string.h> #include <string.h>
#include <cstdio>
// Imports needed for SPI handling on Linux. // Imports needed for SPI handling on Linux.
#include <linux/spi/spidev.h> #include <linux/spi/spidev.h>
#include <unistd.h> #include <unistd.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h>
#define STA_DEBUG_IOCTL_WRITE(result) STA_ASSERT_MSG(result >= 0, "ioctl writing failed!") #define STA_DEBUG_IOCTL_WRITE(result) STA_ASSERT_MSG(result >= 0, "ioctl writing failed!")
#define STA_DEBUG_IOCTL_READ(result) STA_ASSERT_MSG(result >= 0, "ioctl reading failed!") #define STA_DEBUG_IOCTL_READ(result) STA_ASSERT_MSG(result >= 0, "ioctl reading failed!")
@ -28,8 +30,8 @@
namespace sta namespace sta
{ {
RaspiSPI::RaspiSPI(SPINode node, const SPISettings & settings, Mutex * mutex, bool persistent_open = true) RaspiSPI::RaspiSPI(SPINode node, const SPISettings & settings, Mutex * mutex, bool persistent_open)
: SPI(settings, mutex), open_{ false }, persistent_open_{ persistent_open } : SPI(settings, mutex), open_{ false }, persistent_open_{ persistent_open }, settings_{ settings }
{ {
// Check validity of parameters. // Check validity of parameters.
STA_DEBUG_NULLPTR(mutex); STA_DEBUG_NULLPTR(mutex);
@ -60,6 +62,8 @@ namespace sta
STA_DEBUG_FD_OPEN(); STA_DEBUG_FD_OPEN();
struct spi_ioc_transfer spi_message[1]; struct spi_ioc_transfer spi_message[1];
// According to the documentation, spi_message should be zero intialized.
memset(spi_message, 0, sizeof(spi_message)); memset(spi_message, 0, sizeof(spi_message));
spi_message[0].tx_buf = (unsigned long)&value; spi_message[0].tx_buf = (unsigned long)&value;
spi_message[0].len = 1; spi_message[0].len = 1;
@ -74,6 +78,8 @@ namespace sta
STA_DEBUG_FD_OPEN(); STA_DEBUG_FD_OPEN();
struct spi_ioc_transfer spi_message[1]; struct spi_ioc_transfer spi_message[1];
// According to the documentation, spi_message should be zero intialized.
memset(spi_message, 0, sizeof(spi_message)); memset(spi_message, 0, sizeof(spi_message));
spi_message[0].tx_buf = (unsigned long)&value; spi_message[0].tx_buf = (unsigned long)&value;
spi_message[0].len = 1; spi_message[0].len = 1;
@ -90,10 +96,18 @@ namespace sta
STA_ASSERT_MSG(size != 0, "Buffer size cannot be 0!"); STA_ASSERT_MSG(size != 0, "Buffer size cannot be 0!");
struct spi_ioc_transfer spi_message[1]; struct spi_ioc_transfer spi_message[1];
// According to the documentation, spi_message should be zero intialized.
memset(spi_message, 0, sizeof(spi_message)); memset(spi_message, 0, sizeof(spi_message));
spi_message[0].tx_buf = (unsigned long)buffer; spi_message[0].tx_buf = (unsigned long)buffer;
spi_message[0].len = size; spi_message[0].len = size;
printf("Sending ");
for (int i = 0; i < size; i++) {
printf("%x, ", buffer[i]);
}
printf("\n");
int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message); int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message);
STA_DEBUG_IOCTL_SEND(result); STA_DEBUG_IOCTL_SEND(result);
@ -107,6 +121,8 @@ namespace sta
STA_ASSERT_MSG(size != 0, "Buffer size cannot be 0!"); STA_ASSERT_MSG(size != 0, "Buffer size cannot be 0!");
struct spi_ioc_transfer spi_message[1]; struct spi_ioc_transfer spi_message[1];
// According to the documentation, spi_message should be zero intialized.
memset(spi_message, 0, sizeof(spi_message)); memset(spi_message, 0, sizeof(spi_message));
spi_message[0].rx_buf = (unsigned long)rxBuffer; spi_message[0].rx_buf = (unsigned long)rxBuffer;
@ -115,6 +131,10 @@ namespace sta
int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message); int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message);
if (result == -1) {
printf("Sending failed with error '%s'! \n", strerror(errno));
}
STA_DEBUG_IOCTL_SEND(result); STA_DEBUG_IOCTL_SEND(result);
} }
@ -125,6 +145,8 @@ namespace sta
STA_ASSERT_MSG(size != 0, "Buffer size cannot be 0!"); STA_ASSERT_MSG(size != 0, "Buffer size cannot be 0!");
struct spi_ioc_transfer spi_message[1]; struct spi_ioc_transfer spi_message[1];
// According to the documentation, spi_message should be zero intialized.
memset(spi_message, 0, sizeof(spi_message)); memset(spi_message, 0, sizeof(spi_message));
spi_message[0].rx_buf = (unsigned long)buffer; spi_message[0].rx_buf = (unsigned long)buffer;
@ -132,6 +154,12 @@ namespace sta
int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message); int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message);
printf("Receiving ");
for (int i = 0; i < size; i++) {
printf("%x, ", buffer[i]);
}
printf("\n");
STA_DEBUG_IOCTL_SEND(result); STA_DEBUG_IOCTL_SEND(result);
} }
@ -157,12 +185,10 @@ namespace sta
void RaspiSPI::update_setting(int setting, int value) void RaspiSPI::update_setting(int setting, int value)
{ {
STA_DEBUG_FD_OPEN();
int result = ioctl(spifd_, setting, value);
STA_DEBUG_IOCTL_WRITE(result);
} }
int RaspiSPI::get_setting(int setting, void * rslt_ptr) void RaspiSPI::get_setting(int setting, void * rslt_ptr)
{ {
STA_DEBUG_FD_OPEN(); STA_DEBUG_FD_OPEN();
int result = ioctl(spifd_, setting, rslt_ptr); int result = ioctl(spifd_, setting, rslt_ptr);
@ -171,56 +197,63 @@ namespace sta
void RaspiSPI::update_settings() void RaspiSPI::update_settings()
{ {
SPISettings settings = this->settings(); STA_DEBUG_FD_OPEN();
int mode;
switch (settings.mode) switch (settings_.mode)
{ {
case SPIMode::MODE_0: case SPIMode::MODE_0:
mode = SPI_MODE_0; mode_ = SPI_MODE_0;
break; break;
case SPIMode::MODE_1: case SPIMode::MODE_1:
mode = SPI_MODE_1; mode_ = SPI_MODE_1;
break; break;
case SPIMode::MODE_2: case SPIMode::MODE_2:
mode = SPI_MODE_2; mode_ = SPI_MODE_2;
break; break;
case SPIMode::MODE_3: case SPIMode::MODE_3:
mode = SPI_MODE_3; mode_ = SPI_MODE_3;
break; break;
default: default:
STA_ASSERT_MSG(false, "Case for SPIMode enum not handled"); STA_ASSERT_MSG(false, "Case for SPIMode enum not handled");
STA_UNREACHABLE(); STA_UNREACHABLE();
} }
dataSize_ = settings_.dataSize == SPIDataSize::SIZE_8 ? 0 : 16;
bitOrder_ = settings_.bitOrder == SPIBitOrder::MSB ? 0 : 1;
clkSpeed_ = settings_.clkSpeed;
// Set the spi mode. // Set the spi mode.
update_setting(SPI_IOC_WR_MODE, mode); int result = ioctl(spifd_, SPI_IOC_WR_MODE, &mode_);
STA_DEBUG_IOCTL_WRITE(result);
// Set the word size. According to the documentation "the value zero signifies eight bits". // Set the word size. According to the documentation "the value zero signifies eight bits".
update_setting(SPI_IOC_WR_BITS_PER_WORD, settings.dataSize == SPIDataSize::SIZE_8 ? 0 : 16); result = ioctl(spifd_, SPI_IOC_WR_BITS_PER_WORD, &dataSize_);
STA_DEBUG_IOCTL_WRITE(result);
// Set the bit order. According to the documentation zero means MSB first, everything else means LSB first. // Set the bit order. According to the documentation zero means MSB first, everything else means LSB first.
update_setting(SPI_IOC_WR_LSB_FIRST, settings.bitOrder == SPIBitOrder::MSB ? 0 : 1); result = ioctl(spifd_, SPI_IOC_WR_LSB_FIRST, &bitOrder_);
STA_DEBUG_IOCTL_WRITE(result);
// Set the maximum clock speed. // Set the maximum clock speed.
update_setting(SPI_IOC_WR_MAX_SPEED_HZ, settings.clkSpeed); result = ioctl(spifd_, SPI_IOC_WR_MAX_SPEED_HZ, &clkSpeed_);
STA_DEBUG_IOCTL_WRITE(result);
#if defined(DEBUG) #if defined(DEBUG)
uint8_t r_mode = 0; uint8_t r_mode = 0;
get_setting(SPI_IOC_RD_MODE, &r_mode); get_setting(SPI_IOC_RD_MODE, &r_mode);
STA_ASSERT_MSG(r_mode == mode, "The mode wasn't set correctly!"); STA_ASSERT_MSG(r_mode == mode_, "The mode wasn't set correctly!");
uint8_t r_dataSize = 0; uint8_t r_dataSize = 0;
get_setting(SPI_IOC_WR_BITS_PER_WORD, &r_dataSize); get_setting(SPI_IOC_WR_BITS_PER_WORD, &r_dataSize);
STA_ASSERT_MSG(r_dataSize == (settings.dataSize == SPIDataSize::SIZE_8 ? 0 : 16), "The data size wasn't set correctly!"); STA_ASSERT_MSG(r_dataSize == (settings_.dataSize == SPIDataSize::SIZE_8 ? 8 : 16), "The data size wasn't set correctly!");
uint8_t r_bitOrder = 0; uint8_t r_bitOrder = 0;
get_setting(SPI_IOC_RD_LSB_FIRST, &r_bitOrder); get_setting(SPI_IOC_RD_LSB_FIRST, &r_bitOrder);
STA_ASSERT_MSG(r_bitOrder == (settings.bitOrder == SPIBitOrder::MSB ? 0 : 1), "The data size wasn't set correctly!"); STA_ASSERT_MSG(r_bitOrder == (settings_.bitOrder == SPIBitOrder::MSB ? 0 : 1), "The data size wasn't set correctly!");
uint32_t r_clk_Speed; uint32_t r_clk_Speed;
get_setting(SPI_IOC_RD_MAX_SPEED_HZ, &r_clk_Speed); get_setting(SPI_IOC_RD_MAX_SPEED_HZ, &r_clk_Speed);
STA_ASSERT_MSG(r_clk_Speed == settings.clkSpeed, "The clock speed wasn't set correctly!"); STA_ASSERT_MSG(r_clk_Speed == settings_.clkSpeed, "The clock speed wasn't set correctly!");
#endif // STA_DEBUG #endif // STA_DEBUG
} }
@ -235,16 +268,18 @@ namespace sta
return; return;
spifd_ = open(spidev_, O_RDWR); spifd_ = open(spidev_, O_RDWR);
STA_ASSERT(spifd_ >= 0);
open_ = true; open_ = true;
STA_ASSERT(spifd_ >= 0);
update_settings(); update_settings();
} }
void RaspiSPI::release() void RaspiSPI::release()
{ {
if (!persistent_open_) { STA_ASSERT_MSG(open_, "'release' was called despite the device being closed! This has to be a bug!");
if (!persistent_open_ && open_) {
close(spifd_); close(spifd_);
} }

View File

@ -1,5 +1,6 @@
#include <sta/spi/spi.hpp> #include <sta/spi/spi.hpp>
#include <cstdio>
namespace sta namespace sta
{ {
@ -7,7 +8,7 @@ namespace sta
: settings_{settings}, mutex_{mutex} : settings_{settings}, mutex_{mutex}
{} {}
const SPISettings & SPI::settings() const const SPISettings & SPI::settings()
{ {
return settings_; return settings_;
} }

View File

@ -1,5 +1,7 @@
#include <sta/stm32/i2c.hpp> #include <sta/stm32/i2c.hpp>
#if false
namespace sta { namespace sta {
STM32I2cDevice::STM32I2cDevice(I2C_HandleTypeDef* i2cHandle, uint16_t address, Mutex* mutex, bool master, bool blocking) STM32I2cDevice::STM32I2cDevice(I2C_HandleTypeDef* i2cHandle, uint16_t address, Mutex* mutex, bool master, bool blocking)
: I2cDevice(address, mutex, master, blocking) { : I2cDevice(address, mutex, master, blocking) {
@ -51,3 +53,5 @@ namespace sta {
return res == HAL_OK; return res == HAL_OK;
} }
} }
#endif // false