Updated debug printing for raspi + added persistent_open setting for raspi spi

This commit is contained in:
Dario 2023-05-16 14:58:09 +01:00
parent 21cb870014
commit 0bc924bba2
14 changed files with 529 additions and 93 deletions

View File

@ -0,0 +1,49 @@
#ifndef STA_CORE_DEBUG_PRINTF_HPP
#define STA_CORE_DEBUG_PRINTF_HPP
#include <sta/config.hpp>
// Determine if module should be enabled
// Condition 1: STA_DEBUG_PRINTF is defined
// Condition 2:
// STA_DEBUG_PRINTF_FORCE is defined
// or
// DEBUG is defined but not NDEBUG
#ifdef STA_DEBUG_PRINTF
# ifdef STA_DEBUG_PRINTF_FORCE
# define STA_DEBUG_SERIAL_ENABLED
# else // !STA_DEBUG_PRINTF_FORCE
# if defined(DEBUG) && !defined(NDEBUG)
# define STA_DEBUG_PRINTF_ENABLED
# endif // DEBUG && !NDEBUG
# endif // !STA_DEBUG_PRINTF_FORCE
#endif // STA_DEBUG_PRINTF
#if defined(STA_DEBUG_PRINTF_ENABLED) || defined(DOXYGEN)
#include <sta/printable.hpp>
/**
* @brief Print debug output.
*
* @param ... See @ref sta::PrintableUART::print
*
* @ingroup sta_core_debug
*/
# define STA_DEBUG_PRINT(...) sta::print(__VA_ARGS__)
/**
* @brief Print debug output followed by new-line to UART.
*
* @param ... See @ref sta::PrintableUART::println
*
* @ingroup sta_core_debug
*/
# define STA_DEBUG_PRINTLN(...) sta::println(__VA_ARGS__)
#else // !STA_DEBUG_PRINTF_ENABLED
# define STA_DEBUG_PRINT(...) ((void)0)
# define STA_DEBUG_PRINTLN(...) ((void)0)
#endif // !STA_DEBUG_PRINTF_ENABLED
#endif // STA_CORE_DEBUG_PRINTF_HPP

206
include/sta/printable.hpp Normal file
View File

@ -0,0 +1,206 @@
/**
* @file
* @brief Printable UART interface definition.
*/
#ifndef STA_CORE_PRINTABLE_HPP
#define STA_CORE_PRINTABLE_HPP
#include <sta/printf.hpp>
#include <cstddef>
#include <cstdint>
namespace sta
{
/**
* @brief Integer representation.
*
* @ingroup sta_core
*/
enum class IntegerBase
{
DEC, /**< Decimal */
BIN, /**< Binary */
HEX /**< Hexadecimal */
};
/**
* @brief Print single character.
*
* @param c Character to print
*/
void print(char c);
/**
* @brief Print boolean value.
*
* @param b Boolean value
*/
void print(bool b);
/**
* @brief Print floating point value.
*
* @param d Floating point value
*/
void print(double d);
/**
* @brief Print integer in selected base.
*
* @param num 8-bit unsigned integer
* @param base Integer base
*/
void print(uint8_t num, IntegerBase base = IntegerBase::DEC);
/**
* @brief Print integer in selected base.
*
* @param num 16-bit unsigned integer
* @param base Integer base
*/
void print(uint16_t num, IntegerBase base = IntegerBase::DEC);
/**
* @brief Print integer in selected base.
*
* @param num 32-bit unsigned integer
* @param base Integer base
*/
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.
*
* @param str Null terminated string
*/
void print(const char * str);
/**
* @brief Print string.
*
* @param str String buffer
* @param length String length
*/
void print(const char * str, size_t length);
/**
* @brief Print new-line.
*/
void println();
/**
* @brief Print single character followed by a new-line.
*
* @param c Character to print
*/
void println(char c);
/**
* @brief Print boolean value followed by a new-line.
*
* @param b Boolean value
*/
void println(bool b);
/**
* @brief Print floating point value followed by a new-line.
*
* @param d Floating point value
*/
void println(double d);
/**
* @brief Print integer in selected base followed by a new-line.
*
* @param num 8-bit unsigned integer
* @param base Integer base
*/
void println(uint8_t num, IntegerBase base = IntegerBase::DEC);
/**
* @brief Print integer in selected base followed by a new-line.
*
* @param num 16-bit unsigned integer
* @param base Integer base
*/
void println(uint16_t num, IntegerBase base = IntegerBase::DEC);
/**
* @brief Print integer in selected base followed by a new-line.
*
* @param num 32-bit unsigned integer
* @param base Integer base
*/
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.
*
* @param str Null terminated string
*/
void println(const char * str);
/**
* @brief Print string followed by a new-line.
*
* @param str String buffer
* @param length String length
*/
void println(const char * str, size_t length);
/**
* @brief Print unsigned integer in selected base.
*
* @param value Unsigned integer value
* @param base Integer base
* @param fmt printf format string for base 10
* @param size Size of value in bytes
*/
void printBase(uintmax_t value, IntegerBase base, const char * fmt, size_t size);
/**
* @brief Print unsigned integer in base 10.
*
* @param value Unsigned integer value
* @param fmt printf format string
*/
void printDec(uintmax_t value, const char * fmt);
/**
* @brief Print unsigned integer in base 2.
*
* @param value Unsigned integer value
* @param digits Number of digits to print
*/
void printBin(uintmax_t value, size_t digits);
/**
* @brief Print unsigned integer in base 16.
*
* @param value Unsigned integer value
* @param digits Number of digits to print
*/
void printHex(uintmax_t value, size_t digits);
} // namespace sta
#endif // STA_CORE_PRINTABLE_HPP

View File

@ -77,13 +77,6 @@ namespace sta
* @param base Integer base
*/
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.
*
@ -142,13 +135,6 @@ namespace sta
* @param base Integer base
*/
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.
*

View File

@ -15,7 +15,7 @@
namespace sta
{
class RaspiGpioPin : GpioPin
class RaspiGpioPin : public GpioPin
{
public:
enum class GpioMode {
@ -31,18 +31,18 @@ namespace sta
void setState(GpioPinState state) override;
static RaspiGpioPin DUMMY_GPIO;
static RaspiGpioPin * DUMMY_GPIO;
private:
uint8_t pin_;
GpioMode mode_;
};
class DummyGpioPin : RaspiGpioPin {
class DummyGpioPin : public RaspiGpioPin {
DummyGpioPin();
void setState(GpioPinState state) override;
}
};
} // namespace sta
#endif // STA_RASPI_GPIO_ENABLED

View File

@ -2,7 +2,7 @@
#define STA_CORE_RASPI_HAL_HPP
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <stdio.h>
#include <sys/ioctl.h>
#endif //STA_CORE_RASPI_HAL_HPP

View File

@ -0,0 +1,13 @@
/**
* @file
* @brief Common configuration for Raspberry Pi MCUs
*/
#ifndef STA_CORE_RASPI_MCU_COMMON_HPP
#define STA_CORE_RASPI_MCU_COMMON_HPP
#define STA_MCU_LITTLE_ENDIAN
// Enable STM32 platform
#define STA_PLATFORM_RASPI
#endif // STA_CORE_RASPI_MCU_COMMON_HPP

View File

@ -9,10 +9,15 @@
namespace sta
{
enum class SPINode {
DEV_0_0,
DEV_0_1
};
class RaspiSPI : public SPI
{
public:
RaspiSPI(const char * dev, const SPISettings & settings, Mutex * mutex = nullptr);
RaspiSPI(SPINode node, const SPISettings & settings, Mutex * mutex = nullptr, bool persistent_open = true);
~RaspiSPI();
void transfer(uint8_t value) override;
@ -30,18 +35,17 @@ namespace sta
char * spidev_;
int spifd_;
bool open_;
const bool persistent_open_;
void update_setting(int setting, int value);
int get_setting(int setting, void * rslt_ptr);
void update_settings();
};
class RaspiSPIDevice : SPIDevice
class RaspiSPIDevice : public SPIDevice
{
public:
RaspiSPIDevice(RaspiSPI * intf);
void select() override;
void deselect() override;
};
} // namespace sta

View File

@ -93,7 +93,7 @@ namespace sta
*
* @return SPI settings
*/
const SpiSettings & settings() const;
const SPISettings & settings() const;
/**

View File

@ -1,7 +1,13 @@
#include <sta/assert.hpp>
#ifdef STA_ASSERT_ENABLED
#include <sta/debug_serial.hpp>
// TODO: This will probably destroy some stuff when working with stm32!
#ifdef STA_PRINTF_USE_STDLIB
# include <sta/debug_printf.hpp>
#else
# include <sta/debug_serial.hpp>
#endif
#include <sta/lang.hpp>

117
src/printable.cpp Normal file
View File

@ -0,0 +1,117 @@
#include <sta/printable.hpp>
#include <cinttypes>
#include <cstring>
namespace sta
{
void print(char c)
{
print(&c, 1);
}
void print(bool b)
{
print(b ? "true" : "false");
}
void print(double d)
{
char buffer[64];
snprintf(buffer, sizeof(buffer), "%f", d);
print(buffer);
}
void print(uint8_t num, IntegerBase base /* = IntegerBase::DEC */)
{
printBase(num, base, "%" PRIu8, sizeof(num));
}
void print(uint16_t num, IntegerBase base /* = IntegerBase::DEC */)
{
printBase(num, base, "%" PRIu16, sizeof(num));
}
void print(uint32_t num, IntegerBase base /* = IntegerBase::DEC */)
{
printBase(num, base, "%" PRIu32, sizeof(num));
}
void print(const char * str)
{
print(str, strlen(str));
}
void println()
{
print("\r\n", 2);
}
void println(char c)
{
print(&c, 1);
println();
}
void println(bool b)
{
print(b);
println();
}
void println(double d)
{
print(d);
println();
}
void println(uint8_t num, IntegerBase base /* = IntegerBase::DEC */)
{
print(num, base);
println();
}
void println(uint16_t num, IntegerBase base /* = IntegerBase::DEC */)
{
print(num, base);
println();
}
void println(uint32_t num, IntegerBase base /* = IntegerBase::DEC */)
{
print(num, base);
println();
}
void println(const char * str)
{
println(str, strlen(str));
}
void println(const char * str, size_t length)
{
print(str, length);
println();
}
void printBase(uintmax_t value, IntegerBase base, const char * fmt, size_t size)
{
}
void printDec(uintmax_t value, const char * fmt)
{
}
void printBin(uintmax_t value, size_t digits)
{
}
void printHex(uintmax_t value, size_t digits)
{
}
} // namespace sta

View File

@ -49,11 +49,6 @@ namespace sta
printBase(num, base, "%" PRIu32, sizeof(num));
}
void PrintableUART::print(size_t num, IntegerBase base /* = IntegerBase::DEC */)
{
printBase(num, base, "%z", sizeof(num));
}
void PrintableUART::print(const char * str)
{
print(str, strlen(str));
@ -106,12 +101,6 @@ namespace sta
println();
}
void PrintableUART::println(size_t num, IntegerBase base /* = IntegerBase::DEC */)
{
print(num, base);
println();
}
void PrintableUART::println(const char * str)
{
println(str, strlen(str));

View File

@ -21,15 +21,13 @@ namespace sta
}
DummyGpioPin::setState(GpioPinState state)
void DummyGpioPin::setState(GpioPinState state)
{
// If this gets called, something is wrong!
STA_UNREACHABLE();
// Don't do anything.
}
static DummyGpioPin dummyGpio;
RaspiGpioPin * RaspiGpioPin::DUMMY_GPIO = &dummyGpio;
} // namespace sta

View File

@ -1,8 +1,9 @@
#include <sta/raspi/spi.hpp>
#ifdef STA_PLATFORM_RASPI
#include <sta/raspi/gpio_pin.hpp>
#include <sta/spi/settings.hpp>
#include <sta/assert.hpp>
#include <sta/endian.hpp>
#include <sta/lang.hpp>
@ -10,28 +11,36 @@
#include <cstdlib>
#include <string.h>
// Imports needed for SPI handling on Linux.
#include <linux/spi/spidev.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#define SYSTEM_ENDIANNESS __cpp_lib_endian
#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_SEND(result) STA_ASSERT_MSG(result >= 0, "ioctl sending spi message failed!")
#define STA_DEBUG_FD_OPEN() STA_ASSERT_MSG(open_, "File descriptor wasn't opened!")
#define STA_DEBUG_NULLPTR(ptr) STA_ASSERT_MSG(ptr != nullptr, "Pointer is nullptr!")
// TODO: Check out "cpu_to_leXX()" and "leXX()_to_cpu()" on Linux!
namespace sta
{
RaspiSPI::RaspiSPI(const char * dev, const SPISettings & settings, Mutex * mutex = nullptr)
: SPI(settings, mutex)
RaspiSPI::RaspiSPI(SPINode node, const SPISettings & settings, Mutex * mutex, bool persistent_open = true)
: SPI(settings, mutex), open_{ false }, persistent_open_{ persistent_open }
{
// Check validity of parameters.
STA_ASSERT(dev != nullptr);
STA_ASSERT(mutex != nullptr);
STA_DEBUG_NULLPTR(mutex);
open_ = false;
spidev_ = (char *)malloc(strlen(dev)+1);
// Safer version of malloc + strcpy
spidev_ = strdup(node == SPINode::DEV_0_0 ? "/dev/spidev0.0" : "/dev/spidev0.1");
// Check if memory allocation was successful.
STA_ASSERT(spidev_ != nullptr);
strcpy(spidev_ , dev);
STA_DEBUG_NULLPTR(spidev_);
}
RaspiSPI::~RaspiSPI()
@ -48,37 +57,37 @@ namespace sta
void RaspiSPI::transfer(uint8_t value)
{
STA_ASSERT(open_);
STA_DEBUG_FD_OPEN();
struct spi_ioc_transfer spi_message[1];
memset(spi_message, 0, sizeof(spi_message));
spi_message[0].tx_buf = (unsigned long)&value;
spi_message[0].len = 1;
int result = ioctl(m_spifd, SPI_IOC_MESSAGE(1), spi_message);
int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message);
STA_ASSERT(result == 0);
STA_DEBUG_IOCTL_SEND(result);
}
void RaspiSPI::transfer16(uint16_t value)
{
STA_ASSERT(open_);
STA_DEBUG_FD_OPEN();
struct spi_ioc_transfer spi_message[1];
memset(spi_message, 0, sizeof(spi_message));
spi_message[0].tx_buf = (unsigned long)&value;
spi_message[0].len = 1;
int result = ioctl(m_spifd, SPI_IOC_MESSAGE(1), spi_message);
int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message);
STA_ASSERT(result == 0);
STA_DEBUG_IOCTL_SEND(result);
}
void RaspiSPI::transfer(const uint8_t * buffer, size_t size)
{
STA_ASSERT(open_);
STA_ASSERT(buffer != nullptr);
STA_ASSERT(size != 0);
STA_DEBUG_FD_OPEN();
STA_DEBUG_NULLPTR(buffer);
STA_ASSERT_MSG(size != 0, "Buffer size cannot be 0!");
struct spi_ioc_transfer spi_message[1];
memset(spi_message, 0, sizeof(spi_message));
@ -87,14 +96,15 @@ namespace sta
int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message);
STA_ASSERT(result == 0);
STA_DEBUG_IOCTL_SEND(result);
}
void RaspiSPI::transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size)
{
STA_ASSERT(txBuffer != nullptr);
STA_ASSERT(rxBuffer != nullptr);
STA_ASSERT(size != 0);
STA_DEBUG_FD_OPEN();
STA_DEBUG_NULLPTR(txBuffer);
STA_DEBUG_NULLPTR(rxBuffer);
STA_ASSERT_MSG(size != 0, "Buffer size cannot be 0!");
struct spi_ioc_transfer spi_message[1];
memset(spi_message, 0, sizeof(spi_message));
@ -105,24 +115,30 @@ namespace sta
int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message);
STA_ASSERT(result == 0);
STA_DEBUG_IOCTL_SEND(result);
}
void RaspiSPI::receive(uint8_t * buffer, size_t size)
{
STA_ASSERT(buffer != nullptr);
STA_DEBUG_FD_OPEN();
STA_DEBUG_NULLPTR(buffer);
STA_ASSERT_MSG(size != 0, "Buffer size cannot be 0!");
struct spi_ioc_transfer spi_message[1];
memset(spi_message, 0, sizeof(spi_message));
spi_message[0].rx_buf = (unsigned long)buffer;
spi_message[0].len = size;
return ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message);
int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message);
STA_DEBUG_IOCTL_SEND(result);
}
void RaspiSPI::fill(uint8_t value, size_t count)
{
STA_ASSERT(count != 0);
STA_DEBUG_FD_OPEN();
STA_ASSERT_MSG(count != 0, "Buffer size cannot be 0!");
uint8_t * buffer = new uint8_t[count];
memset(buffer, value, count);
@ -134,15 +150,78 @@ namespace sta
int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message);
STA_DEBUG_IOCTL_SEND(result);
delete[] buffer;
}
void RaspiSPI::update_setting(int setting, int value)
{
STA_ASSERT(open_);
STA_DEBUG_FD_OPEN();
int result = ioctl(spifd_, setting, value);
STA_ASSERT(result >= 0);
STA_DEBUG_IOCTL_WRITE(result);
}
int RaspiSPI::get_setting(int setting, void * rslt_ptr)
{
STA_DEBUG_FD_OPEN();
int result = ioctl(spifd_, setting, rslt_ptr);
STA_DEBUG_IOCTL_READ(result);
}
void RaspiSPI::update_settings()
{
SPISettings settings = this->settings();
int mode;
switch (settings.mode)
{
case SPIMode::MODE_0:
mode = SPI_MODE_0;
break;
case SPIMode::MODE_1:
mode = SPI_MODE_1;
break;
case SPIMode::MODE_2:
mode = SPI_MODE_2;
break;
case SPIMode::MODE_3:
mode = SPI_MODE_3;
break;
default:
STA_ASSERT_MSG(false, "Case for SPIMode enum not handled");
STA_UNREACHABLE();
}
// Set the spi mode.
update_setting(SPI_IOC_WR_MODE, mode);
// 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);
// 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);
// Set the maximum clock speed.
update_setting(SPI_IOC_WR_MAX_SPEED_HZ, settings.clkSpeed);
#if defined(DEBUG)
uint8_t r_mode = 0;
get_setting(SPI_IOC_RD_MODE, &r_mode);
STA_ASSERT_MSG(r_mode == mode, "The mode wasn't set correctly!");
uint8_t r_dataSize = 0;
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!");
uint8_t r_bitOrder = 0;
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!");
uint32_t 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!");
#endif // STA_DEBUG
}
void RaspiSPI::acquire()
@ -156,20 +235,19 @@ namespace sta
return;
spifd_ = open(spidev_, O_RDWR);
STA_ASSERT(spifd_ < 0);
STA_ASSERT(spifd_ >= 0);
open_ = true;
update_setting(SPI_IOC_WR_MODE, &m_spiconfig.mode);
update_setting(SPI_IOC_RD_MODE, &m_spiconfig.mode);
update_setting(SPI_IOC_WR_BITS_PER_WORD, &m_spiconfig.bits_per_word);
update_setting(SPI_IOC_RD_BITS_PER_WORD, &m_spiconfig.bits_per_word);
uppdate_setting(SPI_IOC_WR_MAX_SPEED_HZ, &m_spiconfig.speed);
update_setting(SPI_IOC_RD_MAX_SPEED_HZ, &m_spiconfig.speed);
update_settings();
}
void RaspiSPI::release()
{
if (!persistent_open_) {
close(spifd_);
}
SPI::release();
}
@ -177,16 +255,6 @@ namespace sta
{
}
RaspiSPIDevice::select()
{
// do nothing since the raspi SPI API doesn't require GPIO interaction.
}
RaspiSPIDevice::deselect()
{
// do nothing since the raspi SPI API doesn't require GPIO interaction.
}
} // namespace sta

View File

@ -70,7 +70,7 @@ namespace sta
}
const SpiSettings & SPIDevice::settings() const
const SPISettings & SPIDevice::settings() const
{
return intf_->settings();
}
@ -78,11 +78,11 @@ namespace sta
void SPIDevice::select()
{
csPin_->setState(GpioPinState::LOW);
csPin_->setState(GpioPinState::GPIO_LOW);
}
void SPIDevice::deselect()
{
csPin_->setState(GpioPinState::HIGH);
csPin_->setState(GpioPinState::GPIO_HIGH);
}
} // namespace sta