From d913fbb416e2e0a7f936783a5ed40ea8dc048caf Mon Sep 17 00:00:00 2001 From: "Jakob.Meier" Date: Sat, 16 Jan 2021 12:22:17 +0100 Subject: [PATCH] old approach gpio lib --- bsp_q7s/ObjectFactory.cpp | 5 +- bsp_q7s/comIF/GpioComIF.cpp | 265 +++++++++++++++++++++++++++ bsp_q7s/comIF/GpioComIF.h | 57 ++++++ bsp_q7s/comIF/I2cComIF.cpp | 2 +- bsp_q7s/comIF/cookies/GpioCookie.cpp | 26 +++ bsp_q7s/comIF/cookies/GpioCookie.h | 48 +++++ 6 files changed, 400 insertions(+), 3 deletions(-) create mode 100644 bsp_q7s/comIF/GpioComIF.cpp create mode 100644 bsp_q7s/comIF/GpioComIF.h create mode 100644 bsp_q7s/comIF/cookies/GpioCookie.cpp create mode 100644 bsp_q7s/comIF/cookies/GpioCookie.h diff --git a/bsp_q7s/ObjectFactory.cpp b/bsp_q7s/ObjectFactory.cpp index 3c6d3efb..7c33b2e4 100644 --- a/bsp_q7s/ObjectFactory.cpp +++ b/bsp_q7s/ObjectFactory.cpp @@ -56,9 +56,9 @@ void ObjectFactory::produce(){ CspCookie* acuCspCookie = new CspCookie(ACU::MAX_REPLY_LENGTH, addresses::ACU); I2cCookie* i2cCookieTmp1075tcs1 = new I2cCookie(addresses::TMP1075_TCS_1, - TMP1075::MAX_REPLY_LENGTH, std::string("/dev/i2c-1")); + TMP1075::MAX_REPLY_LENGTH, std::string("/dev/i2c-0")); I2cCookie* i2cCookieTmp1075tcs2 = new I2cCookie(addresses::TMP1075_TCS_2, - TMP1075::MAX_REPLY_LENGTH, std::string("/dev/i2c-1")); + TMP1075::MAX_REPLY_LENGTH, std::string("/dev/i2c-0")); /* Communication interfaces */ new CspComIF(objects::CSP_COM_IF); @@ -77,6 +77,7 @@ void ObjectFactory::produce(){ new GomspaceDeviceHandler(objects::ACU_HANDLER, objects::CSP_COM_IF, acuCspCookie, ACU::MAX_CONFIGTABLE_ADDRESS, ACU::MAX_HKTABLE_ADDRESS); + /* Temperature sensors */ Tmp1075Handler* tmp1075Handler_1 = new Tmp1075Handler( objects::TMP1075_HANDLER_1, objects::I2C_COM_IF, i2cCookieTmp1075tcs1); diff --git a/bsp_q7s/comIF/GpioComIF.cpp b/bsp_q7s/comIF/GpioComIF.cpp new file mode 100644 index 00000000..78ad9bba --- /dev/null +++ b/bsp_q7s/comIF/GpioComIF.cpp @@ -0,0 +1,265 @@ +#include +#include +#include +#include + + +GpioComIF::GpioComIF(object_id_t objectId): SystemObject(objectId){ +} + +GpioComIF::~GpioComIF() {} + +ReturnValue_t GpioComIF::initializeInterface(CookieIF * cookie) { + + ReturnValue_t result; + GpioMap mapToAdd; + + if(cookie == nullptr) { + return NULLPOINTER; + } + GpioCookie* GpioCookie = dynamic_cast(cookie); + if(GpioCookie == nullptr) { + sif::error << "GpioComIF: Invalid Gpio Cookie!" + << std::endl; + return NULLPOINTER; + } + + mapToAdd = GpioCookie->getGpioMap(); + + result = checkForConflicts(mapToAdd); + if (result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + + /* Register new GPIOs in gpioMap*/ + result = initializeAndConfigure(mapToAdd); + if (result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t GpioComIF::sendMessage(CookieIF *cookie, + const uint8_t *sendData, size_t sendLen) { + + ReturnValue_t result; + int fd; + std::string deviceFile; + + if(sendData == nullptr) { + sif::error << "GpioComIF::sendMessage: Send Data is nullptr" + << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + if(sendLen == 0) { + return HasReturnvaluesIF::RETURN_OK; + } + + I2cCookie* i2cCookie = dynamic_cast(cookie); + if(i2cCookie == nullptr) { + sif::error << "GpioComIF::sendMessasge: Invalid I2C Cookie!" + << std::endl; + return NULLPOINTER; + } + + address_t i2cAddress = i2cCookie->getAddress(); + i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress); + if (i2cDeviceMapIter == i2cDeviceMap.end()) { + sif::error << "GpioComIF::sendMessage: i2cAddress of Cookie not " + << "registered in i2cDeviceMap" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + deviceFile = i2cCookie->getDeviceFile(); + result = openDevice(deviceFile, i2cAddress, &fd); + if (result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + + if (write(fd, sendData, sendLen) != (int)sendLen) { + sif::error << "GpioComIF::sendMessage: Failed to send data to I2C " + "device with error code " << errno << ". Error description: " + << strerror(errno) << std::endl; + close(fd); + return HasReturnvaluesIF::RETURN_FAILED; + } + close(fd); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t GpioComIF::getSendSuccess(CookieIF *cookie) { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t GpioComIF::requestReceiveMessage(CookieIF *cookie, + size_t requestLen) { + + ReturnValue_t result; + int fd; + std::string deviceFile; + + if (requestLen == 0) { + return HasReturnvaluesIF::RETURN_OK; + } + + I2cCookie* i2cCookie = dynamic_cast(cookie); + if(i2cCookie == nullptr) { + sif::error << "GpioComIF::requestReceiveMessage: Invalid I2C Cookie!" + << std::endl; + i2cDeviceMapIter->second.replyLen = 0; + return NULLPOINTER; + } + + address_t i2cAddress = i2cCookie->getAddress(); + i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress); + if (i2cDeviceMapIter == i2cDeviceMap.end()) { + sif::error << "GpioComIF::requestReceiveMessage: i2cAddress of Cookie not " + << "registered in i2cDeviceMap" << std::endl; + i2cDeviceMapIter->second.replyLen = 0; + return HasReturnvaluesIF::RETURN_FAILED; + } + + deviceFile = i2cCookie->getDeviceFile(); + result = openDevice(deviceFile, i2cAddress, &fd); + if (result != HasReturnvaluesIF::RETURN_OK){ + i2cDeviceMapIter->second.replyLen = 0; + return result; + } + + uint8_t* replyBuffer = i2cDeviceMapIter->second.replyBuffer.data(); + + if (read(fd, replyBuffer, requestLen) != (int)requestLen) { + sif::error << "GpioComIF::requestReceiveMessage: Reading from I2C " + << "device failed with error code " << errno <<". Description" + << " of error: " << strerror(errno) << std::endl; + close(fd); + i2cDeviceMapIter->second.replyLen = 0; + return HasReturnvaluesIF::RETURN_FAILED; + } + + i2cDeviceMapIter->second.replyLen = requestLen; + + close(fd); + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t GpioComIF::readReceivedMessage(CookieIF *cookie, + uint8_t **buffer, size_t* size) { + I2cCookie* i2cCookie = dynamic_cast(cookie); + if(i2cCookie == nullptr) { + sif::error << "GpioComIF::readReceivedMessage: Invalid I2C Cookie!" + << std::endl; + return NULLPOINTER; + } + + address_t i2cAddress = i2cCookie->getAddress(); + i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress); + if (i2cDeviceMapIter == i2cDeviceMap.end()) { + sif::error << "GpioComIF::readReceivedMessage: i2cAddress of Cookie not " + << "found in i2cDeviceMap" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + *buffer = i2cDeviceMapIter->second.replyBuffer.data(); + *size = i2cDeviceMapIter->second.replyLen; + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t GpioComIF::openDevice(std::string deviceFile, + address_t i2cAddress, int* fileDescriptor) { + *fileDescriptor = open(deviceFile.c_str(), O_RDWR); + if (*fileDescriptor < 0) { + sif::error << "GpioComIF: Opening i2c device failed with error code " + << errno << ". Error description: " << strerror(errno) + << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + if (ioctl(*fileDescriptor, I2C_SLAVE, i2cAddress) < 0) { + sif::error << "GpioComIF: Specifying target device failed with error " + << "code " << errno << ". Error description " + << strerror(errno) << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t GpioComIF::checkForConflicts(GpioMap mapToAdd){ + gpio_t gpio; + GpioMapIter mapToAddIter = mapToAdd.begin(); + for(; mapToAddIter != mapToAdd.end(); mapToAddIter++){ + gpio = mapToAddIter.first(); + if(gpioMapIter.find(gpio) != mapToAdd.end()){ + /* An entry for this GPIO already exists. Check if configuration + * of direction is equivalent */ + if (mapToAddIter.second() != gpioMapIter.second()){ + sif::error << "GpioComIF::checkForConflicts: Detected conflict " + << "for GPIO " << mapToAddIter.first() << std::endl; + return HasReturnvaluesIF::RETURN_OK; + } + /* Remove element from map to add because a entry for this GPIO + * already exists */ + mapToAdd.erase(mapToAddIter); + } + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t GpioComIF::initializeAndConfigure(GpioMap mapToAdd){ + + int exportfd; + int directionfd; + std::string gpioStr; + GpioMapIter mapToAddItr; + + mapToAddItr = mapToAdd.begin(); + /* Perform initialization for all GPIOs in map */ + for(; mapToAddItr != mapToAdd.end(); mapToAddItr++){ + /* The GPIO has to be exported to be able to see it in sysfs */ + exportfd = open("/sys/class/gpio/export", O_WRONLY); + if (exportfd < 0) + { + sif::error << "GpioComIF::initializeAndConfigure: Cannot open GPIO " + << mapToAddItr.first() << " to export it" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + gpioStr = std::to_string(mapToAddItr.first()); + write(exportfd, gpioStr.c_str(), gpioStr.length() + 1); + close(exportfd); + + /* Set direction of the GPIO */ + std::string directionPath = "/sys/class/gpio/" + gpioStr + + "/direction"; + directionfd = open(directionPath.c_str(), O_RDWR); + if (directionfd < 0) + { + sif::error << "Cannot open " << directionPath.c_str() << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + if (mapToAdd.second() == Gpio::IN) { + write(directionfd, "in", 3); + } + else if (mapToAdd.second() == Gpio::OUT) { + write(directionfd, "out", 4); + } + else { + sif::error << "GpioComIF::initializeAndConfigure: Invalid direction" + << " specified" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + close(directionfd); + + /* Add GPIO to GpioMap of GpioComIF */ + std::pair insertionResult = gpioMap.insert(mapToAddItr); + if (insertionResult.second() != true) { + sif::error << "GpioComIF::initializeAndConfigure: Failed to add " + << "GPIO " << gpioStr.c_st() << " to gpioMap" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/bsp_q7s/comIF/GpioComIF.h b/bsp_q7s/comIF/GpioComIF.h new file mode 100644 index 00000000..f90a82d0 --- /dev/null +++ b/bsp_q7s/comIF/GpioComIF.h @@ -0,0 +1,57 @@ +#ifndef BSP_Q7S_COMIF_I2s COMIF_H_ +#define BSP_Q7S_COMIF_I2COMIF_H_ + +#include +#include +#include + +/** + * @brief This is the communication interface to drive GPIOs by using the + * the linux sysfs. + * + * @author J. Meier + */ +class GpioComIF: public DeviceCommunicationIF, public SystemObject { +public: + GpioComIF(object_id_t objectId); + + virtual ~GpioComIF(); + + ReturnValue_t initializeInterface(CookieIF * cookie) override; + ReturnValue_t sendMessage(CookieIF *cookie,const uint8_t *sendData, + size_t sendLen) override; + ReturnValue_t getSendSuccess(CookieIF *cookie) override; + ReturnValue_t requestReceiveMessage(CookieIF *cookie, + size_t requestLen) override; + ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, + size_t *size) override; + +private: + + /* All GPIOs will be stored in this map after successful initialization */ + GpioMap gpioMap; + GpioMapIter gpioMapIter; + + /** + * @brief This function checks if GPIOs are already registered and whether + * there exists a conflict in the GPIO configuration. E.g. the + * direction. + * + * @param mapToAdd The GPIOs which shall be added to the gpioMap + * + * @return RETURN_OK if successful, otherwise RETURN_FAILED + */ + ReturnValue_t checkForConflicts(GpioMap mapToAdd); + + /** + * @brief This function initializes all GPIOs specified in the mapToAdd. + * + * @param Map with the GPIOs to initialize. + * + * @return RETURN_OK if successful, otherwise RETURN_FAILED + */ + ReturnValue_t GpioComIF::initializeAndConfigure(GpioMap mapToAdd); + +}; + +#endif /* BSP_Q7S_COMIF_I2COMIF_H_ */ diff --git a/bsp_q7s/comIF/I2cComIF.cpp b/bsp_q7s/comIF/I2cComIF.cpp index ccf4ee2a..8cbd45b3 100644 --- a/bsp_q7s/comIF/I2cComIF.cpp +++ b/bsp_q7s/comIF/I2cComIF.cpp @@ -121,7 +121,7 @@ ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF *cookie, I2cCookie* i2cCookie = dynamic_cast(cookie); if(i2cCookie == nullptr) { - sif::error << "I2cComIF::sendMessage: Invalid I2C Cookie!" + sif::error << "I2cComIF::requestReceiveMessage: Invalid I2C Cookie!" << std::endl; i2cDeviceMapIter->second.replyLen = 0; return NULLPOINTER; diff --git a/bsp_q7s/comIF/cookies/GpioCookie.cpp b/bsp_q7s/comIF/cookies/GpioCookie.cpp new file mode 100644 index 00000000..68d37007 --- /dev/null +++ b/bsp_q7s/comIF/cookies/GpioCookie.cpp @@ -0,0 +1,26 @@ +#include + +GpioCookie::GpioCookie() { +} + +void GpioCookie::addGpio(gpioMap newEntry){ + gpioMapIter = gpioMap.find(newEntry); + if(gpioMapIter == gpioMap.end()) { + std::pair status = i2cDeviceMap.emplace(newEntry); + if (status.second == false) { + sif::error << "GpioCookie::addGpio: Failed to add GPIO " + << newEntry.first << "to GPIO map" << std::endl; + return HasReturnvaluesIF::RETURN_OK; + } + } + else { + sif::error << "GpioCookie::addGpio: GPIO already exists in GPIO map " + << std::endl; + } +} + +GpioMap getGpioMap() const{ + return gpioMap; +} + +GpioCookie::~GpioCookie() {} diff --git a/bsp_q7s/comIF/cookies/GpioCookie.h b/bsp_q7s/comIF/cookies/GpioCookie.h new file mode 100644 index 00000000..22c99b76 --- /dev/null +++ b/bsp_q7s/comIF/cookies/GpioCookie.h @@ -0,0 +1,48 @@ +#ifndef SAM9G20_COMIF_COOKIES_I2C_COOKIE_H_ +#define SAM9G20_COMIF_COOKIES_I2C_COOKIE_H_ + +#include +#include + +namespace Gpio { + enum Direction { + IN = 0, + OUT = 1 + }; +} + +using gpio_t = uint32_t; +using direction_t = bool; +using GpioMap = std::unordered_map; +using GpioMapIter = GpioMap::iterator; + +/** + * @brief Cookie for the GpioComIF. Allows the GpioComIF to determine which + * GPIOs to initialize and whether they should be configured as in- or + * output. + * @details One GpioCookie can hold multiple GPIO configurations. To add a new + * GPIO configuration to a GpioCookie use the GpioCookie::addGpio + * function. + * + * @author J. Meier + */ +class GpioCookie: public CookieIF { +public: + + GpioCookie(); + + virtual ~GpioCookie(); + + void addGpio(gpioMap newEntry); + /** + * @brief Get map with register GPIOs. + */ + GpioMap getGpioMap() const; + +private: + + GpioMap gpioMap; + GpioMapIter gpioMapIter; +}; + +#endif