GPIO HAL Updates #36

Merged
meierj merged 35 commits from mueller/gpio-hal-updates into eive/develop 2022-03-03 09:44:47 +01:00
7 changed files with 53 additions and 31 deletions

View File

@ -8,6 +8,23 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased] # [unreleased]
# [v5.0.0]
## Changes
- GPIO HAL: Renamed entries of enumerations to avoid nameclashes with Windows defines.
`IN` and `OUT` in `Direction` changed to `DIR_IN` and `DIR_OUT`.
`CALLBACK` in `GpioTypes` changed to `TYPE_CALLBACK`
## Removed
- Removed the `HkSwitchHelper`. This module should not be needed anymore, now that the local
datapools have been implemented
## Additions
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
# [v4.0.0] # [v4.0.0]
## Additions ## Additions

View File

@ -71,9 +71,9 @@ add and link against the FSFW library in general.
4. Link against the FSFW library 4. Link against the FSFW library
```cmake ```cmake
target_link_libraries(<YourProjectName> PRIVATE fsfw) target_link_libraries(${YourProjectName} PRIVATE fsfw)
``` ```
5. It should now be possible use the FSFW as a static library from the user code. 5. It should now be possible use the FSFW as a static library from the user code.

View File

@ -9,18 +9,18 @@ using gpioId_t = uint16_t;
namespace gpio { namespace gpio {
enum Levels : uint8_t { LOW = 0, HIGH = 1, NONE = 99 }; enum class Levels : int { LOW = 0, HIGH = 1, NONE = 99 };
enum Direction : uint8_t { DIR_IN = 0, DIR_OUT = 1 }; enum class Direction : int { IN = 0, OUT = 1 };
enum GpioOperation { READ, WRITE }; enum class GpioOperation { READ, WRITE };
enum class GpioTypes { enum class GpioTypes {
NONE, NONE,
GPIO_REGULAR_BY_CHIP, GPIO_REGULAR_BY_CHIP,
GPIO_REGULAR_BY_LABEL, GPIO_REGULAR_BY_LABEL,
GPIO_REGULAR_BY_LINE_NAME, GPIO_REGULAR_BY_LINE_NAME,
TYPE_CALLBACK CALLBACK
}; };
static constexpr gpioId_t NO_GPIO = -1; static constexpr gpioId_t NO_GPIO = -1;
@ -57,7 +57,7 @@ class GpioBase {
// Can be used to cast GpioBase to a concrete child implementation // Can be used to cast GpioBase to a concrete child implementation
gpio::GpioTypes gpioType = gpio::GpioTypes::NONE; gpio::GpioTypes gpioType = gpio::GpioTypes::NONE;
std::string consumer; std::string consumer;
gpio::Direction direction = gpio::Direction::DIR_IN; gpio::Direction direction = gpio::Direction::IN;
gpio::Levels initValue = gpio::Levels::NONE; gpio::Levels initValue = gpio::Levels::NONE;
}; };
@ -79,8 +79,8 @@ class GpiodRegularBase : public GpioBase {
class GpiodRegularByChip : public GpiodRegularBase { class GpiodRegularByChip : public GpiodRegularBase {
public: public:
GpiodRegularByChip() GpiodRegularByChip()
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP, std::string(), : GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP, std::string(), gpio::Direction::IN,
gpio::Direction::DIR_IN, gpio::LOW, 0) {} gpio::Levels::LOW, 0) {}
GpiodRegularByChip(std::string chipname_, int lineNum_, std::string consumer_, GpiodRegularByChip(std::string chipname_, int lineNum_, std::string consumer_,
gpio::Direction direction_, gpio::Levels initValue_) gpio::Direction direction_, gpio::Levels initValue_)
@ -89,8 +89,8 @@ class GpiodRegularByChip : public GpiodRegularBase {
chipname(chipname_) {} chipname(chipname_) {}
GpiodRegularByChip(std::string chipname_, int lineNum_, std::string consumer_) GpiodRegularByChip(std::string chipname_, int lineNum_, std::string consumer_)
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP, consumer_, gpio::Direction::DIR_IN, : GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP, consumer_, gpio::Direction::IN,
gpio::LOW, lineNum_), gpio::Levels::LOW, lineNum_),
chipname(chipname_) {} chipname(chipname_) {}
std::string chipname; std::string chipname;
@ -105,8 +105,8 @@ class GpiodRegularByLabel : public GpiodRegularBase {
label(label_) {} label(label_) {}
GpiodRegularByLabel(std::string label_, int lineNum_, std::string consumer_) GpiodRegularByLabel(std::string label_, int lineNum_, std::string consumer_)
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LABEL, consumer_, gpio::Direction::DIR_IN, : GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LABEL, consumer_, gpio::Direction::IN,
gpio::LOW, lineNum_), gpio::Levels::LOW, lineNum_),
label(label_) {} label(label_) {}
std::string label; std::string label;
@ -126,8 +126,8 @@ class GpiodRegularByLineName : public GpiodRegularBase {
lineName(lineName_) {} lineName(lineName_) {}
GpiodRegularByLineName(std::string lineName_, std::string consumer_) GpiodRegularByLineName(std::string lineName_, std::string consumer_)
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME, consumer_, : GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME, consumer_, gpio::Direction::IN,
gpio::Direction::DIR_IN, gpio::LOW), gpio::Levels::LOW),
lineName(lineName_) {} lineName(lineName_) {}
std::string lineName; std::string lineName;
@ -137,7 +137,7 @@ class GpioCallback : public GpioBase {
public: public:
GpioCallback(std::string consumer, gpio::Direction direction_, gpio::Levels initValue_, GpioCallback(std::string consumer, gpio::Direction direction_, gpio::Levels initValue_,
gpio::gpio_cb_t callback, void* callbackArgs) gpio::gpio_cb_t callback, void* callbackArgs)
: GpioBase(gpio::GpioTypes::TYPE_CALLBACK, consumer, direction_, initValue_), : GpioBase(gpio::GpioTypes::CALLBACK, consumer, direction_, initValue_),
callback(callback), callback(callback),
callbackArgs(callbackArgs) {} callbackArgs(callbackArgs) {}

View File

@ -74,7 +74,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
configureGpioByLineName(gpioConfig.first, *regularGpio); configureGpioByLineName(gpioConfig.first, *regularGpio);
break; break;
} }
case (gpio::GpioTypes::TYPE_CALLBACK): { case (gpio::GpioTypes::CALLBACK): {
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioConfig.second); auto gpioCallback = dynamic_cast<GpioCallback*>(gpioConfig.second);
if (gpioCallback->callback == nullptr) { if (gpioCallback->callback == nullptr) {
return GPIO_INVALID_INSTANCE; return GPIO_INVALID_INSTANCE;
@ -161,11 +161,12 @@ ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, struct gpiod
consumer = regularGpio.consumer; consumer = regularGpio.consumer;
/* Configure direction and add a description to the GPIO */ /* Configure direction and add a description to the GPIO */
switch (direction) { switch (direction) {
case (gpio::DIR_OUT): { case (gpio::Direction::OUT): {
result = gpiod_line_request_output(lineHandle, consumer.c_str(), regularGpio.initValue); result = gpiod_line_request_output(lineHandle, consumer.c_str(),
static_cast<int>(regularGpio.initValue));
break; break;
} }
case (gpio::DIR_IN): { case (gpio::Direction::IN): {
result = gpiod_line_request_input(lineHandle, consumer.c_str()); result = gpiod_line_request_input(lineHandle, consumer.c_str());
break; break;
} }
@ -211,7 +212,7 @@ ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) {
if (regularGpio == nullptr) { if (regularGpio == nullptr) {
return GPIO_TYPE_FAILURE; return GPIO_TYPE_FAILURE;
} }
return driveGpio(gpioId, *regularGpio, gpio::HIGH); return driveGpio(gpioId, *regularGpio, gpio::Levels::HIGH);
} else { } else {
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second); auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
if (gpioCallback->callback == nullptr) { if (gpioCallback->callback == nullptr) {
@ -243,7 +244,7 @@ ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) {
if (regularGpio == nullptr) { if (regularGpio == nullptr) {
return GPIO_TYPE_FAILURE; return GPIO_TYPE_FAILURE;
} }
return driveGpio(gpioId, *regularGpio, gpio::LOW); return driveGpio(gpioId, *regularGpio, gpio::Levels::LOW);
} else { } else {
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second); auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
if (gpioCallback->callback == nullptr) { if (gpioCallback->callback == nullptr) {
@ -258,11 +259,11 @@ ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) {
ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId, GpiodRegularBase& regularGpio, ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId, GpiodRegularBase& regularGpio,
gpio::Levels logicLevel) { gpio::Levels logicLevel) {
int result = gpiod_line_set_value(regularGpio.lineHandle, logicLevel); int result = gpiod_line_set_value(regularGpio.lineHandle, static_cast<int>(logicLevel));
if (result < 0) { if (result < 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID " << gpioId sif::warning << "LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID " << gpioId
<< " to logic level " << logicLevel << std::endl; << " to logic level " << static_cast<int>(logicLevel) << std::endl;
#else #else
sif::printWarning( sif::printWarning(
"LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID %d to " "LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID %d to "
@ -326,7 +327,7 @@ ReturnValue_t LinuxLibgpioIF::checkForConflicts(GpioMap& mapToAdd) {
} }
break; break;
} }
case (gpio::GpioTypes::TYPE_CALLBACK): { case (gpio::GpioTypes::CALLBACK): {
auto callbackGpio = dynamic_cast<GpioCallback*>(gpioConfig.second); auto callbackGpio = dynamic_cast<GpioCallback*>(gpioConfig.second);
if (callbackGpio == nullptr) { if (callbackGpio == nullptr) {
return GPIO_TYPE_FAILURE; return GPIO_TYPE_FAILURE;
@ -366,13 +367,13 @@ ReturnValue_t LinuxLibgpioIF::checkForConflictsById(gpioId_t gpioIdToCheck,
case (gpio::GpioTypes::GPIO_REGULAR_BY_CHIP): case (gpio::GpioTypes::GPIO_REGULAR_BY_CHIP):
case (gpio::GpioTypes::GPIO_REGULAR_BY_LABEL): case (gpio::GpioTypes::GPIO_REGULAR_BY_LABEL):
case (gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME): { case (gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME): {
if (gpioType == gpio::GpioTypes::NONE or gpioType == gpio::GpioTypes::TYPE_CALLBACK) { if (gpioType == gpio::GpioTypes::NONE or gpioType == gpio::GpioTypes::CALLBACK) {
eraseDuplicateDifferentType = true; eraseDuplicateDifferentType = true;
} }
break; break;
} }
case (gpio::GpioTypes::TYPE_CALLBACK): { case (gpio::GpioTypes::CALLBACK): {
if (gpioType != gpio::GpioTypes::TYPE_CALLBACK) { if (gpioType != gpio::GpioTypes::CALLBACK) {
eraseDuplicateDifferentType = true; eraseDuplicateDifferentType = true;
} }
} }

View File

@ -409,5 +409,4 @@ void SpiComIF::setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed)
if (retval != 0) { if (retval != 0) {
utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Updating SPI default clock failed"); utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Updating SPI default clock failed");
} }
} }

View File

@ -62,4 +62,9 @@
#define FSFW_HAL_I2C_WIRETAPPING 0 #define FSFW_HAL_I2C_WIRETAPPING 0
#endif #endif
// Can be used for low-level debugging of the I2C bus
#ifndef FSFW_HAL_I2C_WIRETAPPING
#define FSFW_HAL_I2C_WIRETAPPING 0
#endif
#endif /* FSFW_FSFW_H_ */ #endif /* FSFW_FSFW_H_ */

View File

@ -73,7 +73,7 @@ TEST_CASE("Command Executor", "[cmd-exec]") {
REQUIRE(result != CommandExecutor::COMMAND_ERROR); REQUIRE(result != CommandExecutor::COMMAND_ERROR);
// This ensures that the tests do not block indefinitely // This ensures that the tests do not block indefinitely
usleep(500); usleep(500);
REQUIRE(limitIdx < 500); REQUIRE(limitIdx < 50000);
} }
limitIdx = 0; limitIdx = 0;
CHECK(bytesHaveBeenRead == true); CHECK(bytesHaveBeenRead == true);