Update 3 #20
|
@ -61,6 +61,14 @@ if(TGT_BSP)
|
|||
set(ADD_LINUX_FILES TRUE)
|
||||
set(ADD_CSP_LIB TRUE)
|
||||
endif()
|
||||
|
||||
if(${TGT_BSP} MATCHES "arm/raspberrypi")
|
||||
add_definitions(-DRASPBERRY_PI)
|
||||
endif()
|
||||
|
||||
if(${TGT_BSP} MATCHES "arm/q7s")
|
||||
add_definitions(-DXIPHOS_Q7S)
|
||||
endif()
|
||||
else()
|
||||
# Required by FSFW library
|
||||
set(FSFW_CONFIG_PATH "${BSP_PATH}/fsfwconfig")
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include <fsfw/tasks/PeriodicTaskIF.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
|
||||
#include <mission/utility/InitMission.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// This is configured for linux without \cr
|
||||
|
@ -28,7 +30,7 @@ ServiceInterfaceStream sif::error("ERROR", true, false, true);
|
|||
|
||||
ObjectManagerIF *objectManager = nullptr;
|
||||
|
||||
void InitMission::initMission() {
|
||||
void initmission::initMission() {
|
||||
sif::info << "Building global objects.." << std::endl;
|
||||
/* Instantiate global object manager and also create all objects */
|
||||
objectManager = new ObjectManager(ObjectFactory::produce);
|
||||
|
@ -39,7 +41,7 @@ void InitMission::initMission() {
|
|||
initTasks();
|
||||
}
|
||||
|
||||
void InitMission::initTasks(){
|
||||
void initmission::initTasks(){
|
||||
/* TMTC Distribution */
|
||||
PeriodicTaskIF* TmTcDistributor = TaskFactory::instance()->
|
||||
createPeriodicTask("DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef BSP_LINUX_INITMISSION_H_
|
||||
#define BSP_LINUX_INITMISSION_H_
|
||||
|
||||
namespace InitMission {
|
||||
namespace initmission {
|
||||
void initMission();
|
||||
void initTasks();
|
||||
};
|
||||
|
|
|
@ -24,7 +24,7 @@ int main(void)
|
|||
<< SW_SUBVERSION << "." << SW_SUBSUBVERSION << " -- " << std::endl;
|
||||
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
|
||||
|
||||
InitMission::initMission();
|
||||
initmission::initMission();
|
||||
|
||||
for(;;) {
|
||||
// suspend main thread by sleeping it.
|
||||
|
|
|
@ -6,6 +6,7 @@ target_sources(${TARGET_NAME} PUBLIC
|
|||
|
||||
add_subdirectory(boardconfig)
|
||||
add_subdirectory(comIF)
|
||||
add_subdirectory(devices)
|
||||
add_subdirectory(boardtest)
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include "ObjectFactory.h"
|
||||
#include <OBSWConfig.h>
|
||||
|
||||
#include <mission/utility/InitMission.h>
|
||||
|
||||
#include <fsfw/objectmanager/ObjectManagerIF.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
@ -13,7 +15,7 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
// This is configured for linux without \cr
|
||||
/* This is configured for linux without CR */
|
||||
#ifdef LINUX
|
||||
ServiceInterfaceStream sif::debug("DEBUG");
|
||||
ServiceInterfaceStream sif::info("INFO");
|
||||
|
@ -28,7 +30,7 @@ ServiceInterfaceStream sif::error("ERROR", true, false, true);
|
|||
|
||||
ObjectManagerIF *objectManager = nullptr;
|
||||
|
||||
void InitMission::initMission() {
|
||||
void initmission::initMission() {
|
||||
sif::info << "Building global objects.." << std::endl;
|
||||
/* Instantiate global object manager and also create all objects */
|
||||
objectManager = new ObjectManager(ObjectFactory::produce);
|
||||
|
@ -39,144 +41,148 @@ void InitMission::initMission() {
|
|||
initTasks();
|
||||
}
|
||||
|
||||
void InitMission::initTasks(){
|
||||
void initmission::initTasks() {
|
||||
TaskFactory* factory = TaskFactory::instance();
|
||||
if(factory == nullptr) {
|
||||
/* Should never happen ! */
|
||||
return;
|
||||
}
|
||||
#if OBSW_PRINT_MISSED_DEADLINES == 1
|
||||
void (*missedDeadlineFunc) (void) = TaskFactory::printMissedDeadline;
|
||||
#else
|
||||
void (*missedDeadlineFunc) (void) = nullptr;
|
||||
#endif
|
||||
|
||||
/* TMTC Distribution */
|
||||
PeriodicTaskIF* TmTcDistributor = TaskFactory::instance()->
|
||||
createPeriodicTask("DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE,
|
||||
0.2, nullptr);
|
||||
ReturnValue_t result = TmTcDistributor->addComponent(
|
||||
PeriodicTaskIF* tmTcDistributor = factory->createPeriodicTask(
|
||||
"DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
|
||||
ReturnValue_t result = tmTcDistributor->addComponent(
|
||||
objects::CCSDS_PACKET_DISTRIBUTOR);
|
||||
if(result!=HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("CCSDS_DISTRIB", objects::CCSDS_PACKET_DISTRIBUTOR);
|
||||
}
|
||||
result = TmTcDistributor->addComponent(objects::PUS_PACKET_DISTRIBUTOR);
|
||||
if(result!=HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
result = tmTcDistributor->addComponent(objects::PUS_PACKET_DISTRIBUTOR);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("PUS_PACKET_DISTRIB", objects::PUS_PACKET_DISTRIBUTOR);
|
||||
}
|
||||
result = TmTcDistributor->addComponent(objects::TM_FUNNEL);
|
||||
result = tmTcDistributor->addComponent(objects::TM_FUNNEL);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
initmission::printAddObjectError("TM_FUNNEL", objects::TM_FUNNEL);
|
||||
}
|
||||
|
||||
/* UDP bridge */
|
||||
PeriodicTaskIF* UdpBridgeTask = TaskFactory::instance()->createPeriodicTask(
|
||||
"UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE,
|
||||
0.2, nullptr);
|
||||
result = UdpBridgeTask->addComponent(objects::UDP_BRIDGE);
|
||||
PeriodicTaskIF* udpBridgeTask = factory->createPeriodicTask(
|
||||
"UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
|
||||
result = udpBridgeTask->addComponent(objects::UDP_BRIDGE);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "Add component UDP Unix Bridge failed" << std::endl;
|
||||
initmission::printAddObjectError("UDP_BRIDGE", objects::UDP_BRIDGE);
|
||||
}
|
||||
PeriodicTaskIF* UdpPollingTask = TaskFactory::instance()->
|
||||
createPeriodicTask("UDP_POLLING", 80,
|
||||
PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, nullptr);
|
||||
result = UdpPollingTask->addComponent(objects::UDP_POLLING_TASK);
|
||||
PeriodicTaskIF* udpPollingTask = factory->createPeriodicTask(
|
||||
"UDP_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
|
||||
result = udpPollingTask->addComponent(objects::UDP_POLLING_TASK);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "Add component UDP Polling failed" << std::endl;
|
||||
initmission::printAddObjectError("UDP_POLLING", objects::UDP_POLLING_TASK);
|
||||
}
|
||||
|
||||
/* PUS Services */
|
||||
PeriodicTaskIF* PusVerification = TaskFactory::instance()->
|
||||
createPeriodicTask("PUS_VERIF_1", 40,
|
||||
PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, nullptr);
|
||||
result = PusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
PeriodicTaskIF* pusVerification = factory->createPeriodicTask(
|
||||
"PUS_VERIF", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
|
||||
result = pusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("PUS_VERIF", objects::PUS_SERVICE_1_VERIFICATION);
|
||||
}
|
||||
|
||||
PeriodicTaskIF* PusEvents = TaskFactory::instance()->
|
||||
createPeriodicTask("PUS_VERIF_1", 60,
|
||||
PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, nullptr);
|
||||
result = PusVerification->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
PeriodicTaskIF* pusEvents = factory->createPeriodicTask(
|
||||
"PUS_EVENTS", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
|
||||
result = pusVerification->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("PUS_EVENTS", objects::PUS_SERVICE_5_EVENT_REPORTING);
|
||||
}
|
||||
|
||||
PeriodicTaskIF* PusHighPrio = TaskFactory::instance()->
|
||||
createPeriodicTask("PUS_HIGH_PRIO", 50,
|
||||
PeriodicTaskIF::MINIMUM_STACK_SIZE,
|
||||
0.200, nullptr);
|
||||
result = PusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
|
||||
if(result!=HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
PeriodicTaskIF* pusHighPrio = factory->createPeriodicTask(
|
||||
"PUS_HIGH_PRIO", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
|
||||
result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("PUS_2", objects::PUS_SERVICE_2_DEVICE_ACCESS);
|
||||
}
|
||||
result = PusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
|
||||
if(result!=HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
result = pusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("PUS_9", objects::PUS_SERVICE_9_TIME_MGMT);
|
||||
}
|
||||
|
||||
PeriodicTaskIF* PusMedPrio = TaskFactory::instance()->
|
||||
createPeriodicTask("PUS_HIGH_PRIO", 40,
|
||||
PeriodicTaskIF::MINIMUM_STACK_SIZE,
|
||||
0.8, nullptr);
|
||||
result = PusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
|
||||
if(result!=HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
PeriodicTaskIF* pusMedPrio = factory->createPeriodicTask(
|
||||
"PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
|
||||
result = pusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("PUS_8", objects::PUS_SERVICE_8_FUNCTION_MGMT);
|
||||
}
|
||||
result = PusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
|
||||
if(result!=HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
result = pusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("PUS_200", objects::PUS_SERVICE_200_MODE_MGMT);
|
||||
}
|
||||
result = pusMedPrio->addComponent(objects::PUS_SERVICE_20_PARAMETERS);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("PUS_20", objects::PUS_SERVICE_20_PARAMETERS);
|
||||
}
|
||||
|
||||
PeriodicTaskIF* PusLowPrio = TaskFactory::instance()->
|
||||
createPeriodicTask("PUSB", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE,
|
||||
1.6, nullptr);
|
||||
result = PusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST);
|
||||
if(result!=HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
PeriodicTaskIF* pusLowPrio = factory->createPeriodicTask(
|
||||
"PUS_LOW_PRIO", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.6, missedDeadlineFunc);
|
||||
result = pusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("PUS_17", objects::PUS_SERVICE_17_TEST);
|
||||
}
|
||||
|
||||
//TODO: Add handling of missed deadlines
|
||||
/* Polling Sequence Table Default */
|
||||
FixedTimeslotTaskIF * PollingSequenceTableTaskDefault =
|
||||
TaskFactory::instance()->createFixedTimeslotTask("PST_TASK_DEFAULT",
|
||||
50, PeriodicTaskIF::MINIMUM_STACK_SIZE*4, 3.0,
|
||||
nullptr);
|
||||
result = pst::pollingSequenceInitDefault(PollingSequenceTableTaskDefault);
|
||||
FixedTimeslotTaskIF * pollingSequenceTableTaskDefault = factory->createFixedTimeslotTask(
|
||||
"PST_TASK_DEFAULT", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0,
|
||||
missedDeadlineFunc);
|
||||
result = pst::pollingSequenceInitDefault(pollingSequenceTableTaskDefault);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "InitMission::initTasks: Creating PST failed!"
|
||||
<< std::endl;
|
||||
sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl;
|
||||
}
|
||||
|
||||
#if TE0720 == 0
|
||||
FixedTimeslotTaskIF* GomSpacePstTask = TaskFactory::instance()->
|
||||
FixedTimeslotTaskIF* gomSpacePstTask = factory->
|
||||
createFixedTimeslotTask("GS_PST_TASK", 50,
|
||||
PeriodicTaskIF::MINIMUM_STACK_SIZE*8, 3.0, nullptr);
|
||||
result = pst::gomspacePstInit(GomSpacePstTask);
|
||||
PeriodicTaskIF::MINIMUM_STACK_SIZE*8, 3.0, missedDeadlineFunc);
|
||||
result = pst::gomspacePstInit(gomSpacePstTask);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "InitMission::initTasks: GomSpace PST initialization "
|
||||
<< "failed!" << std::endl;
|
||||
sif::error << "InitMission::initTasks: GomSpace PST initialization failed!" << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
PeriodicTaskIF* testTask = factory->createPeriodicTask(
|
||||
"GPIOD_TEST", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1, missedDeadlineFunc);
|
||||
#if OBSW_ADD_TEST_CODE == 1
|
||||
result = testTask->addComponent(objects::TEST_TASK);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("TEST_TASK", objects::TEST_TASK);
|
||||
}
|
||||
#endif /* OBSW_ADD_TEST_CODE == 1 */
|
||||
#if TE0720 == 1 && TEST_LIBGPIOD == 1
|
||||
PeriodicTaskIF* TestTask = TaskFactory::instance()->
|
||||
createPeriodicTask("Libgpiod Test Task", 60,
|
||||
PeriodicTaskIF::MINIMUM_STACK_SIZE, 1, nullptr);
|
||||
result = TestTask->addComponent(objects::LIBGPIOD_TEST);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component libgpiod test task object" << std::endl;
|
||||
result = testTask->addComponent(objects::LIBGPIOD_TEST);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("GPIOD_TEST", objects::LIBGPIOD_TEST);
|
||||
}
|
||||
#endif
|
||||
#endif /* TE0720 == 1 && TEST_LIBGPIOD == 1 */
|
||||
|
||||
//Main thread sleep
|
||||
sif::info << "Starting tasks.." << std::endl;
|
||||
TmTcDistributor->startTask();
|
||||
UdpBridgeTask->startTask();
|
||||
UdpPollingTask->startTask();
|
||||
tmTcDistributor->startTask();
|
||||
udpBridgeTask->startTask();
|
||||
udpPollingTask->startTask();
|
||||
|
||||
#if TE0720 == 0
|
||||
GomSpacePstTask->startTask();
|
||||
gomSpacePstTask->startTask();
|
||||
#endif
|
||||
PollingSequenceTableTaskDefault->startTask();
|
||||
pollingSequenceTableTaskDefault->startTask();
|
||||
|
||||
PusVerification->startTask();
|
||||
PusEvents->startTask();
|
||||
PusHighPrio->startTask();
|
||||
PusMedPrio->startTask();
|
||||
PusLowPrio->startTask();
|
||||
pusVerification->startTask();
|
||||
pusEvents->startTask();
|
||||
pusHighPrio->startTask();
|
||||
pusMedPrio->startTask();
|
||||
pusLowPrio->startTask();
|
||||
|
||||
#if TE0720 == 1 && TEST_LIBGPIOD == 1
|
||||
TestTask->startTask();
|
||||
#endif
|
||||
testTask->startTask();
|
||||
sif::info << "Tasks started.." << std::endl;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef BSP_Q7S_INITMISSION_H_
|
||||
#define BSP_Q7S_INITMISSION_H_
|
||||
|
||||
namespace InitMission {
|
||||
namespace initmission {
|
||||
void initMission();
|
||||
void initTasks();
|
||||
};
|
||||
|
|
|
@ -4,15 +4,9 @@
|
|||
#include <devices/addresses.h>
|
||||
#include <devices/gpioIds.h>
|
||||
#include <tmtc/pusIds.h>
|
||||
#include <devices/powerSwitcherList.h>
|
||||
|
||||
#include <fsfw/datapoollocal/LocalDataPoolManager.h>
|
||||
#include <fsfw/tmtcservices/CommandingServiceBase.h>
|
||||
#include <fsfw/tmtcservices/PusServiceBase.h>
|
||||
#include <fsfw/osal/linux/TmTcUnixUdpBridge.h>
|
||||
#include <fsfw/tmtcpacket/pus/TmPacketStored.h>
|
||||
#include <fsfw/osal/linux/TcUnixUdpPollingTask.h>
|
||||
|
||||
#include <fsfwconfig/devices/powerSwitcherList.h>
|
||||
#include <bsp_q7s/devices/HeaterHandler.h>
|
||||
|
||||
#include <mission/core/GenericFactory.h>
|
||||
#include <mission/devices/PDU1Handler.h>
|
||||
|
@ -21,7 +15,6 @@
|
|||
#include <mission/devices/PCDUHandler.h>
|
||||
#include <mission/devices/P60DockHandler.h>
|
||||
#include <mission/devices/Tmp1075Handler.h>
|
||||
#include <mission/devices/HeaterHandler.h>
|
||||
#include <mission/devices/SolarArrayDeploymentHandler.h>
|
||||
#include <mission/devices/devicedefinitions/GomSpacePackets.h>
|
||||
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h>
|
||||
|
@ -34,8 +27,15 @@
|
|||
#include <linux/gpio/LinuxLibgpioIF.h>
|
||||
#include <linux/gpio/GpioCookie.h>
|
||||
|
||||
#include <fsfw/datapoollocal/LocalDataPoolManager.h>
|
||||
#include <fsfw/tmtcservices/CommandingServiceBase.h>
|
||||
#include <fsfw/tmtcservices/PusServiceBase.h>
|
||||
#include <fsfw/osal/linux/TmTcUnixUdpBridge.h>
|
||||
#include <fsfw/tmtcpacket/pus/TmPacketStored.h>
|
||||
#include <fsfw/osal/linux/TcUnixUdpPollingTask.h>
|
||||
|
||||
#if TEST_LIBGPIOD == 1
|
||||
#include "LibgpiodTest.h"
|
||||
#include <linux/boardtest/LibgpiodTest.h>
|
||||
#endif
|
||||
|
||||
void Factory::setStaticFrameworkObjectIds() {
|
||||
|
@ -119,37 +119,37 @@ void ObjectFactory::produce(){
|
|||
new LinuxLibgpioIF(objects::GPIO_IF);
|
||||
#if TE0720 == 0
|
||||
/* Pin H2-11 on stack connector */
|
||||
GpioConfig_t gpioConfigHeater0(std::string("gpiochip7"), 18,
|
||||
GpiodRegular gpioConfigHeater0(std::string("gpiochip7"), 18,
|
||||
std::string("Heater0"), gpio::OUT, 0);
|
||||
heaterGpiosCookie->addGpio(gpioIds::HEATER_0, gpioConfigHeater0);
|
||||
|
||||
/* Pin H2-12 on stack connector */
|
||||
GpioConfig_t gpioConfigHeater1(std::string("gpiochip7"), 14,
|
||||
GpiodRegular gpioConfigHeater1(std::string("gpiochip7"), 14,
|
||||
std::string("Heater1"), gpio::OUT, 0);
|
||||
heaterGpiosCookie->addGpio(gpioIds::HEATER_1, gpioConfigHeater1);
|
||||
|
||||
/* Pin H2-13 on stack connector */
|
||||
GpioConfig_t gpioConfigHeater2(std::string("gpiochip7"), 20,
|
||||
GpiodRegular gpioConfigHeater2(std::string("gpiochip7"), 20,
|
||||
std::string("Heater2"), gpio::OUT, 0);
|
||||
heaterGpiosCookie->addGpio(gpioIds::HEATER_2, gpioConfigHeater2);
|
||||
|
||||
GpioConfig_t gpioConfigHeater3(std::string("gpiochip7"), 16,
|
||||
GpiodRegular gpioConfigHeater3(std::string("gpiochip7"), 16,
|
||||
std::string("Heater3"), gpio::OUT, 0);
|
||||
heaterGpiosCookie->addGpio(gpioIds::HEATER_3, gpioConfigHeater3);
|
||||
|
||||
GpioConfig_t gpioConfigHeater4(std::string("gpiochip7"), 24,
|
||||
GpiodRegular gpioConfigHeater4(std::string("gpiochip7"), 24,
|
||||
std::string("Heater4"), gpio::OUT, 0);
|
||||
heaterGpiosCookie->addGpio(gpioIds::HEATER_4, gpioConfigHeater4);
|
||||
|
||||
GpioConfig_t gpioConfigHeater5(std::string("gpiochip7"), 26,
|
||||
GpiodRegular gpioConfigHeater5(std::string("gpiochip7"), 26,
|
||||
std::string("Heater5"), gpio::OUT, 0);
|
||||
heaterGpiosCookie->addGpio(gpioIds::HEATER_5, gpioConfigHeater5);
|
||||
|
||||
GpioConfig_t gpioConfigHeater6(std::string("gpiochip7"), 22,
|
||||
GpiodRegular gpioConfigHeater6(std::string("gpiochip7"), 22,
|
||||
std::string("Heater6"), gpio::OUT, 0);
|
||||
heaterGpiosCookie->addGpio(gpioIds::HEATER_6, gpioConfigHeater6);
|
||||
|
||||
GpioConfig_t gpioConfigHeater7(std::string("gpiochip7"), 28,
|
||||
GpiodRegular gpioConfigHeater7(std::string("gpiochip7"), 28,
|
||||
std::string("Heater7"), gpio::OUT, 0);
|
||||
heaterGpiosCookie->addGpio(gpioIds::HEATER_7, gpioConfigHeater7);
|
||||
|
||||
|
@ -157,10 +157,10 @@ void ObjectFactory::produce(){
|
|||
pcduSwitches::TCS_BOARD_8V_HEATER_IN);
|
||||
|
||||
GpioCookie* solarArrayDeplCookie = new GpioCookie;
|
||||
GpioConfig_t gpioConfigDeplSA1(std::string("gpiochip7"), 25,
|
||||
GpiodRegular gpioConfigDeplSA1(std::string("gpiochip7"), 25,
|
||||
std::string("DeplSA1"), gpio::OUT, 0);
|
||||
solarArrayDeplCookie->addGpio(gpioIds::DEPLSA1, gpioConfigDeplSA1);
|
||||
GpioConfig_t gpioConfigDeplSA2(std::string("gpiochip7"), 23,
|
||||
GpiodRegular gpioConfigDeplSA2(std::string("gpiochip7"), 23,
|
||||
std::string("DeplSA2"), gpio::OUT, 0);
|
||||
solarArrayDeplCookie->addGpio(gpioIds::DEPLSA2, gpioConfigDeplSA2);
|
||||
|
||||
|
@ -180,14 +180,14 @@ void ObjectFactory::produce(){
|
|||
GpioConfig_t gpioConfigMio0(std::string("gpiochip0"), 0,
|
||||
std::string("MIO0"), gpio::IN, 0);
|
||||
GpioCookie* gpioCookie = new GpioCookie;
|
||||
gpioCookie->addGpio(gpioIds::Test_ID, gpioConfigMio0);
|
||||
gpioCookie->addGpio(gpioIds::TEST_ID_0, gpioConfigMio0);
|
||||
new LibgpiodTest(objects::LIBGPIOD_TEST, objects::GPIO_IF, gpioCookie);
|
||||
#elif TE0720 == 1
|
||||
/* Configuration for MIO0 on TE0720-03-1CFA */
|
||||
GpioConfig_t gpioConfigForDummyHeater(std::string("gpiochip0"), 0,
|
||||
std::string("Heater0"), gpio::OUT, 0);
|
||||
heaterGpiosCookie->addGpio(gpioIds::HEATER_0, gpioConfigForDummyHeater);
|
||||
new HeaterHandler(objects::HEATER_HANDLER, objects::GPIO_IF, heaterGpiosCookie, objects::PCDU_HANDLER,
|
||||
pcduSwitches::TCS_BOARD_8V_HEATER_IN);
|
||||
new HeaterHandler(objects::HEATER_HANDLER, objects::GPIO_IF, heaterGpiosCookie,
|
||||
objects::PCDU_HANDLER, pcduSwitches::TCS_BOARD_8V_HEATER_IN);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
target_sources(${TARGET_NAME} PRIVATE
|
||||
LibgpiodTest.cpp
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
#include "LibgpiodTest.h"
|
||||
|
||||
#include <fsfwconfig/devices/gpioIds.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <fsfw/objectmanager/ObjectManagerIF.h>
|
||||
|
||||
LibgpiodTest::LibgpiodTest(object_id_t objectId, object_id_t gpioIfobjectId,
|
||||
GpioCookie* gpioCookie):
|
||||
TestTask(objectId) {
|
||||
|
||||
gpioInterface = objectManager->get<GpioIF>(gpioIfobjectId);
|
||||
if (gpioInterface == nullptr) {
|
||||
sif::error << "LibgpiodTest::LibgpiodTest: Invalid Gpio interface." << std::endl;
|
||||
}
|
||||
gpioInterface->initialize(gpioCookie);
|
||||
}
|
||||
|
||||
LibgpiodTest::~LibgpiodTest() {
|
||||
}
|
||||
|
||||
ReturnValue_t LibgpiodTest::performPeriodicAction() {
|
||||
int gpioState;
|
||||
ReturnValue_t result;
|
||||
|
||||
result = gpioInterface->readGpio(gpioIds::Test_ID, &gpioState);
|
||||
if (result != RETURN_OK) {
|
||||
sif::debug << "LibgpiodTest::performPeriodicAction: Failed to read gpio "
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
else {
|
||||
sif::debug << "LibgpiodTest::performPeriodicAction: MIO 0 state = " << gpioState
|
||||
<< std::endl;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
3
bsp_q7s/devices/CMakeLists.txt
Normal file
3
bsp_q7s/devices/CMakeLists.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
target_sources(${TARGET_NAME} PRIVATE
|
||||
HeaterHandler.cpp
|
||||
)
|
|
@ -1,13 +1,14 @@
|
|||
#include <mission/devices/HeaterHandler.h>
|
||||
#include "HeaterHandler.h"
|
||||
#include <fsfwconfig/devices/powerSwitcherList.h>
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
#include <devices/gpioIds.h>
|
||||
#include <linux/gpio/GpioCookie.h>
|
||||
|
||||
HeaterHandler::HeaterHandler(object_id_t setObjectId_, object_id_t gpioDriverId_,
|
||||
CookieIF * gpioCookie_, object_id_t mainLineSwitcherObjectId_, uint8_t mainLineSwitch_) :
|
||||
SystemObject(setObjectId_), gpioDriverId(gpioDriverId_), gpioCookie(gpioCookie_), mainLineSwitcherObjectId(
|
||||
mainLineSwitcherObjectId_), mainLineSwitch(mainLineSwitch_), actionHelper(this,
|
||||
nullptr) {
|
||||
SystemObject(setObjectId_), gpioDriverId(gpioDriverId_), gpioCookie(gpioCookie_),
|
||||
mainLineSwitcherObjectId(mainLineSwitcherObjectId_), mainLineSwitch(mainLineSwitch_),
|
||||
actionHelper(this, nullptr) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize,
|
||||
MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||
}
|
||||
|
@ -42,7 +43,7 @@ ReturnValue_t HeaterHandler::initialize() {
|
|||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
|
||||
result = gpioInterface->initialize(gpioCookie);
|
||||
result = gpioInterface->addGpios(dynamic_cast<GpioCookie*>(gpioCookie));
|
||||
if (result != RETURN_OK) {
|
||||
sif::error << "HeaterHandler::initialize: Failed to initialize Gpio interface" << std::endl;
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
|
@ -116,7 +116,7 @@ private:
|
|||
|
||||
CookieIF * gpioCookie;
|
||||
|
||||
GpioIF* gpioInterface;
|
||||
GpioIF* gpioInterface = nullptr;
|
||||
|
||||
/** Queue to receive messages from other objects. */
|
||||
MessageQueueIF* commandQueue = nullptr;
|
|
@ -13,15 +13,15 @@
|
|||
int main(void)
|
||||
{
|
||||
std::cout << "-- EIVE OBSW --" << std::endl;
|
||||
std::cout << "-- Compiled for Linux " << " --" << std::endl;
|
||||
std::cout << "-- Compiled for Linux (Xiphos Q7S) --" << std::endl;
|
||||
std::cout << "-- Software version " << SW_NAME << " v" << SW_VERSION << "."
|
||||
<< SW_SUBVERSION << "." << SW_SUBSUBVERSION << " -- " << std::endl;
|
||||
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
|
||||
|
||||
InitMission::initMission();
|
||||
initmission::initMission();
|
||||
|
||||
for(;;) {
|
||||
// suspend main thread by sleeping it.
|
||||
/* Suspend main thread by sleeping it. */
|
||||
TaskFactory::delayTask(5000);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,8 @@ target_sources(${TARGET_NAME} PUBLIC
|
|||
|
||||
add_subdirectory(boardconfig)
|
||||
add_subdirectory(boardtest)
|
||||
|
||||
# wiringPi is deprecated unfortunately..
|
||||
#target_link_libraries(${TARGET_NAME} PRIVATE
|
||||
# wiringPi
|
||||
#)
|
||||
add_subdirectory(gpio)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
#include "InitMission.h"
|
||||
#include "ObjectFactory.h"
|
||||
|
||||
#include <fsfwconfig/objects/systemObjectList.h>
|
||||
#include <fsfwconfig/OBSWConfig.h>
|
||||
#include <fsfwconfig/pollingsequence/PollingSequenceFactory.h>
|
||||
|
||||
#include <mission/utility/InitMission.h>
|
||||
|
||||
#include <fsfw/objectmanager/ObjectManagerIF.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
#include <fsfw/objectmanager/ObjectManager.h>
|
||||
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
|
||||
#include <fsfw/tasks/PeriodicTaskIF.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <fsfwconfig/objects/systemObjectList.h>
|
||||
#include <fsfwconfig/OBSWConfig.h>
|
||||
#include <fsfwconfig/pollingsequence/PollingSequenceFactory.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
@ -21,7 +24,7 @@ ServiceInterfaceStream sif::error("ERROR");
|
|||
|
||||
ObjectManagerIF *objectManager = nullptr;
|
||||
|
||||
void InitMission::initMission() {
|
||||
void initmission::initMission() {
|
||||
sif::info << "Building global objects.." << std::endl;
|
||||
/* Instantiate global object manager and also create all objects */
|
||||
objectManager = new ObjectManager(ObjectFactory::produce);
|
||||
|
@ -32,129 +35,131 @@ void InitMission::initMission() {
|
|||
initTasks();
|
||||
}
|
||||
|
||||
void InitMission::initTasks(){
|
||||
void initmission::initTasks() {
|
||||
TaskFactory* factory = TaskFactory::instance();
|
||||
if(factory == nullptr) {
|
||||
/* Should never happen ! */
|
||||
return;
|
||||
}
|
||||
#if OBSW_PRINT_MISSED_DEADLINES == 1
|
||||
void (*missedDeadlineFunc) (void) = TaskFactory::printMissedDeadline;
|
||||
#else
|
||||
void (*missedDeadlineFunc) (void) = nullptr;
|
||||
#endif
|
||||
|
||||
/* TMTC Distribution */
|
||||
PeriodicTaskIF* TmTcDistributor = TaskFactory::instance()->
|
||||
createPeriodicTask("DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE,
|
||||
0.100, nullptr);
|
||||
ReturnValue_t result = TmTcDistributor->addComponent(
|
||||
PeriodicTaskIF* tmTcDistributor = factory->createPeriodicTask(
|
||||
"DIST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
|
||||
ReturnValue_t result = tmTcDistributor->addComponent(
|
||||
objects::CCSDS_PACKET_DISTRIBUTOR);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
}
|
||||
result = TmTcDistributor->addComponent(objects::PUS_PACKET_DISTRIBUTOR);
|
||||
result = tmTcDistributor->addComponent(objects::PUS_PACKET_DISTRIBUTOR);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
}
|
||||
result = TmTcDistributor->addComponent(objects::TM_FUNNEL);
|
||||
result = tmTcDistributor->addComponent(objects::TM_FUNNEL);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
}
|
||||
|
||||
/* UDP bridge */
|
||||
PeriodicTaskIF* UdpBridgeTask = TaskFactory::instance()->createPeriodicTask(
|
||||
"UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE,
|
||||
0.2, nullptr);
|
||||
result = UdpBridgeTask->addComponent(objects::UDP_BRIDGE);
|
||||
PeriodicTaskIF* udpBridgeTask = factory->createPeriodicTask(
|
||||
"UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc);
|
||||
result = udpBridgeTask->addComponent(objects::UDP_BRIDGE);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "Add component UDP Unix Bridge failed" << std::endl;
|
||||
}
|
||||
PeriodicTaskIF* UdpPollingTask = TaskFactory::instance()->
|
||||
createPeriodicTask("UDP_POLLING", 80,
|
||||
PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, nullptr);
|
||||
result = UdpPollingTask->addComponent(objects::UDP_POLLING_TASK);
|
||||
PeriodicTaskIF* udpPollingTask = factory->createPeriodicTask(
|
||||
"UDP_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
|
||||
result = udpPollingTask->addComponent(objects::UDP_POLLING_TASK);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "Add component UDP Polling failed" << std::endl;
|
||||
}
|
||||
|
||||
/* PUS Services */
|
||||
PeriodicTaskIF* PusVerification = TaskFactory::instance()->
|
||||
createPeriodicTask("PUS_VERIF_1", 40,
|
||||
PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, nullptr);
|
||||
result = PusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
|
||||
PeriodicTaskIF* pusVerification = factory->createPeriodicTask(
|
||||
"PUS_VERIF", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
|
||||
result = pusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
}
|
||||
|
||||
PeriodicTaskIF* PusEvents = TaskFactory::instance()->
|
||||
createPeriodicTask("PUS_VERIF_1", 60,
|
||||
PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, nullptr);
|
||||
result = PusVerification->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING);
|
||||
PeriodicTaskIF* pusEvents = factory->createPeriodicTask(
|
||||
"PUS_EVENTS", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
|
||||
result = pusVerification->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
initmission::printAddObjectError("PUS5", objects::PUS_SERVICE_5_EVENT_REPORTING);
|
||||
}
|
||||
|
||||
PeriodicTaskIF* PusHighPrio = TaskFactory::instance()->
|
||||
createPeriodicTask("PUS_HIGH_PRIO", 50,
|
||||
PeriodicTaskIF::MINIMUM_STACK_SIZE,
|
||||
0.200, nullptr);
|
||||
result = PusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
}
|
||||
result = PusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
}
|
||||
|
||||
PeriodicTaskIF* PusMedPrio = TaskFactory::instance()->
|
||||
createPeriodicTask("PUS_HIGH_PRIO", 40,
|
||||
PeriodicTaskIF::MINIMUM_STACK_SIZE,
|
||||
0.8, nullptr);
|
||||
result = PusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
}
|
||||
result = PusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
}
|
||||
|
||||
PeriodicTaskIF* PusLowPrio = TaskFactory::instance()->
|
||||
createPeriodicTask("PUSB", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE,
|
||||
1.6, nullptr);
|
||||
result = PusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add component failed" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
#if OBSW_ADD_TEST_CODE == 1
|
||||
FixedTimeslotTaskIF* TestTimeslotTask = TaskFactory::instance()->
|
||||
createFixedTimeslotTask("PST_TEST_TASK", 10,
|
||||
PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr);
|
||||
result = pst::pollingSequenceTestFunction(TestTimeslotTask);
|
||||
PeriodicTaskIF* pusHighPrio = factory->createPeriodicTask(
|
||||
"PUS_HIGH_PRIO", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
|
||||
result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "InitMission::createTasks: Test PST initialization "
|
||||
<< "failed!" << std::endl;
|
||||
initmission::printAddObjectError("PUS2", objects::PUS_SERVICE_2_DEVICE_ACCESS);
|
||||
}
|
||||
result = pusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("PUS9", objects::PUS_SERVICE_9_TIME_MGMT);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
PeriodicTaskIF* SpiTestTask = TaskFactory::instance()->
|
||||
createPeriodicTask("SPI_TEST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE,
|
||||
2.0, nullptr);
|
||||
result = SpiTestTask->addComponent(objects::SPI_TEST);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
sif::error << "Object add SPI test failed" << std::endl;
|
||||
PeriodicTaskIF* pusMedPrio = factory->createPeriodicTask(
|
||||
"PUS_HIGH_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
|
||||
result = pusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("PUS8", objects::PUS_SERVICE_8_FUNCTION_MGMT);
|
||||
}
|
||||
result = pusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("PUS200", objects::PUS_SERVICE_200_MODE_MGMT);
|
||||
}
|
||||
result = pusMedPrio->addComponent(objects::PUS_SERVICE_20_PARAMETERS);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("PUS20", objects::PUS_SERVICE_20_PARAMETERS);
|
||||
}
|
||||
|
||||
//Main thread sleep
|
||||
PeriodicTaskIF* pusLowPrio = factory->createPeriodicTask(
|
||||
"PUS_LOW_PRIO", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.6, missedDeadlineFunc);
|
||||
result = pusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("PUS17", objects::PUS_SERVICE_17_TEST);
|
||||
}
|
||||
|
||||
PeriodicTaskIF* testTask = factory->createPeriodicTask(
|
||||
"TEST_TASK", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
|
||||
#if OBSW_ADD_TEST_CODE == 1
|
||||
result = testTask->addComponent(objects::TEST_TASK);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("TEST_TASK", objects::TEST_TASK);
|
||||
}
|
||||
#endif /* OBSW_ADD_TEST_CODE == 1 */
|
||||
#if RPI_ADD_SPI_TEST == 1
|
||||
result = testTask->addComponent(objects::SPI_TEST);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("SPI_TEST", objects::SPI_TEST);
|
||||
}
|
||||
#endif /* RPI_ADD_SPI_TEST == 1 */
|
||||
#if RPI_ADD_GPIO_TEST == 1
|
||||
result = testTask->addComponent(objects::LIBGPIOD_TEST);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
initmission::printAddObjectError("GPIOD_TEST", objects::LIBGPIOD_TEST);
|
||||
}
|
||||
#endif /* RPI_ADD_GPIO_TEST == 1 */
|
||||
|
||||
sif::info << "Starting tasks.." << std::endl;
|
||||
TmTcDistributor->startTask();
|
||||
UdpBridgeTask->startTask();
|
||||
UdpPollingTask->startTask();
|
||||
tmTcDistributor->startTask();
|
||||
udpBridgeTask->startTask();
|
||||
udpPollingTask->startTask();
|
||||
|
||||
PusVerification->startTask();
|
||||
PusEvents->startTask();
|
||||
PusHighPrio->startTask();
|
||||
PusMedPrio->startTask();
|
||||
PusLowPrio->startTask();
|
||||
|
||||
SpiTestTask->startTask();
|
||||
pusVerification->startTask();
|
||||
pusEvents->startTask();
|
||||
pusHighPrio->startTask();
|
||||
pusMedPrio->startTask();
|
||||
pusLowPrio->startTask();
|
||||
|
||||
#if OBSW_ADD_TEST_CODE == 1
|
||||
TestTimeslotTask->startTask();
|
||||
#endif
|
||||
testTask->startTask();
|
||||
#endif /* OBSW_ADD_TEST_CODE == 1 */
|
||||
sif::info << "Tasks started.." << std::endl;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef BSP_LINUX_INITMISSION_H_
|
||||
#define BSP_LINUX_INITMISSION_H_
|
||||
|
||||
namespace InitMission {
|
||||
namespace initmission {
|
||||
void initMission();
|
||||
void initTasks();
|
||||
};
|
||||
|
|
|
@ -1,20 +1,27 @@
|
|||
#include "ObjectFactory.h"
|
||||
#include <bsp_rpi/boardtest/SpiTest.h>
|
||||
#include <fsfw/datapoollocal/LocalDataPoolManager.h>
|
||||
#include <bsp_rpi/gpio/GPIORPi.h>
|
||||
|
||||
#include <objects/systemObjectList.h>
|
||||
#include <devices/gpioIds.h>
|
||||
#include <OBSWConfig.h>
|
||||
#include <tmtc/apid.h>
|
||||
#include <tmtc/pusIds.h>
|
||||
|
||||
#include <linux/boardtest/LibgpiodTest.h>
|
||||
#include <linux/boardtest/SpiTestClass.h>
|
||||
#include <linux/gpio/GpioCookie.h>
|
||||
#include <linux/gpio/LinuxLibgpioIF.h>
|
||||
|
||||
#include <mission/core/GenericFactory.h>
|
||||
#include <mission/utility/TmFunnel.h>
|
||||
|
||||
#include <fsfw/datapoollocal/LocalDataPoolManager.h>
|
||||
#include <fsfw/tmtcservices/CommandingServiceBase.h>
|
||||
#include <fsfw/tmtcservices/PusServiceBase.h>
|
||||
#include <fsfw/osal/linux/TmTcUnixUdpBridge.h>
|
||||
#include <fsfw/tmtcpacket/pus/TmPacketStored.h>
|
||||
#include <fsfw/osal/linux/TcUnixUdpPollingTask.h>
|
||||
|
||||
#include <mission/core/GenericFactory.h>
|
||||
#include <mission/utility/TmFunnel.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
|
||||
void Factory::setStaticFrameworkObjectIds() {
|
||||
PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR;
|
||||
|
@ -44,5 +51,23 @@ void ObjectFactory::produce(){
|
|||
objects::TM_STORE, objects::TC_STORE);
|
||||
new TcUnixUdpPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE);
|
||||
|
||||
new SpiTest(objects::SPI_TEST);
|
||||
new LinuxLibgpioIF(objects::GPIO_IF);
|
||||
|
||||
#if RPI_ADD_SPI_TEST == 1
|
||||
new SpiTestClass(objects::SPI_TEST);
|
||||
#endif
|
||||
|
||||
#if RPI_LOOPBACK_TEST_GPIO == 1
|
||||
GpioCookie* gpioCookie = new GpioCookie();
|
||||
/* Loopback pins. Adapt according to setup */
|
||||
gpioId_t gpioIdSender = gpioIds::TEST_ID_0;
|
||||
int bcmPinSender = 26;
|
||||
gpioId_t gpioIdReader = gpioIds::TEST_ID_1;
|
||||
int bcmPinReader = 16;
|
||||
gpio::createRpiGpioConfig(gpioCookie, gpioIdSender, bcmPinSender, "GPIO_LB_SENDER",
|
||||
gpio::Direction::OUT, 0);
|
||||
gpio::createRpiGpioConfig(gpioCookie, gpioIdReader, bcmPinReader, "GPIO_LB_READER",
|
||||
gpio::Direction::IN, 0);
|
||||
new LibgpiodTest(objects::LIBGPIOD_TEST, objects::GPIO_IF, gpioCookie);
|
||||
#endif
|
||||
}
|
||||
|
|
10
bsp_rpi/boardconfig/rpi_config.h
Normal file
10
bsp_rpi/boardconfig/rpi_config.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef BSP_RPI_BOARDCONFIG_RPI_CONFIG_H_
|
||||
#define BSP_RPI_BOARDCONFIG_RPI_CONFIG_H_
|
||||
|
||||
#define RPI_ADD_GPIO_TEST 1
|
||||
#define RPI_ADD_SPI_TEST 1
|
||||
#define RPI_LOOPBACK_TEST_GPIO 1
|
||||
|
||||
|
||||
|
||||
#endif /* BSP_RPI_BOARDCONFIG_RPI_CONFIG_H_ */
|
|
@ -1,6 +1,4 @@
|
|||
target_sources(${TARGET_NAME} PRIVATE
|
||||
SpiTest.cpp
|
||||
RPiGPIO.cpp
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
#include "SpiTest.h"
|
||||
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
|
||||
|
||||
SpiTest::SpiTest(object_id_t objectId): SystemObject(objectId) {
|
||||
sif::info << "Setting up Raspberry Pi WiringPi library." << std::endl;
|
||||
// wiringPiSetupGpio();
|
||||
|
||||
// pinMode(SS_MGM_0_LIS3, OUTPUT);
|
||||
// pinMode(SS_MGM_1_RM, OUTPUT);
|
||||
// pinMode(SS_GYRO_0_ADIS, OUTPUT);
|
||||
// pinMode(SS_GYRO_1_L3G, OUTPUT);
|
||||
// pinMode(SS_GYRO_2_L3G, OUTPUT);
|
||||
// pinMode(SS_MGM_2_LIS3, OUTPUT);
|
||||
// pinMode(SS_MGM_3_RM, OUTPUT);
|
||||
//
|
||||
// digitalWrite(SS_MGM_0_LIS3, HIGH);
|
||||
// digitalWrite(SS_MGM_1_RM, HIGH);
|
||||
// digitalWrite(SS_GYRO_0_ADIS, HIGH);
|
||||
// digitalWrite(SS_GYRO_1_L3G, HIGH);
|
||||
// digitalWrite(SS_GYRO_2_L3G, HIGH);
|
||||
// digitalWrite(SS_MGM_2_LIS3, HIGH);
|
||||
// digitalWrite(SS_MGM_3_RM, HIGH);
|
||||
|
||||
int spiFd = open(spiDeviceName.c_str(), O_RDWR);
|
||||
if (spiFd < 0){
|
||||
sif::error << "Could not open SPI device!" << std::endl;
|
||||
}
|
||||
|
||||
spiMode = SPI_MODE_3;
|
||||
int ret = ioctl(spiFd, SPI_IOC_WR_MODE, &spiMode);
|
||||
if(ret < 0) {
|
||||
sif::error << "Could not set write mode!" << std::endl;
|
||||
}
|
||||
|
||||
/* Datenrate setzen */
|
||||
ret = ioctl(spiFd, SPI_IOC_WR_MAX_SPEED_HZ, &spiSpeed);
|
||||
if(ret < 0) {
|
||||
sif::error << "Could not SPI speed!" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t SpiTest::performOperation(uint8_t opCode) {
|
||||
if(oneShot) {
|
||||
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t SpiTest::initialize() {
|
||||
//transferHandle.rx_buf = reinterpret_cast<__u64>(receiveBuffer);
|
||||
//transferHandle.tx_buf = reinterpret_cast<__u64>(sendBuffer);
|
||||
//transferHandle.speed_hz = 976000;
|
||||
//transferHandle.len = 2;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
#ifndef BSP_LINUX_TEST_SPITEST_H_
|
||||
#define BSP_LINUX_TEST_SPITEST_H_
|
||||
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <linux/spi/spidev.h>
|
||||
#include <string>
|
||||
|
||||
class SpiTest:
|
||||
public SystemObject,
|
||||
public ExecutableObjectIF {
|
||||
public:
|
||||
SpiTest(object_id_t objectId);
|
||||
|
||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
ReturnValue_t initialize() override;
|
||||
private:
|
||||
// These chip selects (BCM number) will be pulled high if not used
|
||||
// ACS board specific.
|
||||
enum SpiChipSelects {
|
||||
SS_MGM_0_LIS3 = 0, //!< MGM 0, LIS3MDLTR, U6, A side
|
||||
SS_MGM_1_RM = 1, //!< MGM 1, RM3100, U7, A side
|
||||
SS_GYRO_0_ADIS = 2, //!< Gyro 0, ADIS16485, U3, A side
|
||||
SS_GYRO_1_L3G = 3, //!< Gyro 1, L3GD20H, U4, A side
|
||||
SS_GYRO_2_L3G = 4, //!< Gyro 2, L3GD20h, U5, B side
|
||||
SS_MGM_2_LIS3 = 17, //!< MGM 2, LIS3MDLTR, U8, B side
|
||||
SS_MGM_3_RM = 27, //!< MGM 3, RM3100, U9, B side
|
||||
};
|
||||
|
||||
const std::string spiDeviceName = "/dev/spidev0.0";
|
||||
int spiFd = 0;
|
||||
|
||||
uint8_t spiMode = SPI_MODE_3;
|
||||
uint32_t spiSpeed = 976000;
|
||||
|
||||
uint8_t sendBuffer[32];
|
||||
uint8_t receiveBuffer[32];
|
||||
struct spi_ioc_transfer transferHandle;
|
||||
|
||||
bool oneShot = true;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* BSP_LINUX_TEST_SPITEST_H_ */
|
9
bsp_rpi/gpio/CMakeLists.txt
Normal file
9
bsp_rpi/gpio/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
target_sources(${TARGET_NAME} PUBLIC
|
||||
GPIORPi.cpp
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
36
bsp_rpi/gpio/GPIORPi.cpp
Normal file
36
bsp_rpi/gpio/GPIORPi.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include "GPIORPi.h"
|
||||
#include <FSFWConfig.h>
|
||||
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
#include <linux/gpio/GpioCookie.h>
|
||||
|
||||
ReturnValue_t gpio::createRpiGpioConfig(GpioCookie* cookie, gpioId_t gpioId, int bcmPin,
|
||||
std::string consumer, gpio::Direction direction, int initValue) {
|
||||
if(cookie == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
GpiodRegular config;
|
||||
/* Default chipname for Raspberry Pi. There is still gpiochip1 for expansion, but most users
|
||||
will not need this */
|
||||
config.chipname = "gpiochip0";
|
||||
|
||||
config.consumer = consumer;
|
||||
config.direction = direction;
|
||||
config.initValue = initValue;
|
||||
|
||||
/* Sanity check for the BCM pins before assigning it */
|
||||
if(bcmPin > 27) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "createRpiGpioConfig: BCM pin " << bcmPin << " invalid!" << std::endl;
|
||||
#else
|
||||
sif::printError("createRpiGpioConfig: BCM pin %d invalid!\n", bcmPin);
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
config.lineNum = bcmPin;
|
||||
cookie->addGpio(gpioId, config);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
26
bsp_rpi/gpio/GPIORPi.h
Normal file
26
bsp_rpi/gpio/GPIORPi.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef BSP_RPI_GPIO_GPIORPI_H_
|
||||
#define BSP_RPI_GPIO_GPIORPI_H_
|
||||
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <linux/gpio/gpioDefinitions.h>
|
||||
|
||||
class GpioCookie;
|
||||
|
||||
namespace gpio {
|
||||
|
||||
/**
|
||||
* Create a GpioConfig_t. This function does a sanity check on the BCM pin number and fails if the
|
||||
* BCM pin is invalid.
|
||||
* @param cookie Adds the configuration to this cookie directly
|
||||
* @param gpioId ID which identifies the GPIO configuration
|
||||
* @param bcmPin Raspberry Pi BCM pin
|
||||
* @param consumer Information string
|
||||
* @param direction GPIO direction
|
||||
* @param initValue Intial value for output pins, 0 for low, 1 for high
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t createRpiGpioConfig(GpioCookie* cookie, gpioId_t gpioId, int bcmPin,
|
||||
std::string consumer, gpio::Direction direction, int initValue);
|
||||
}
|
||||
|
||||
#endif /* BSP_RPI_GPIO_GPIORPI_H_ */
|
|
@ -1,12 +1,10 @@
|
|||
#include "InitMission.h"
|
||||
|
||||
#include <OBSWVersion.h>
|
||||
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
/**
|
||||
* @brief This is the main program for the target hardware.
|
||||
* @return
|
||||
|
@ -14,15 +12,15 @@
|
|||
int main(void)
|
||||
{
|
||||
std::cout << "-- EIVE OBSW --" << std::endl;
|
||||
std::cout << "-- Compiled for Linux " << " --" << std::endl;
|
||||
std::cout << "-- Compiled for Linux (Raspberry Pi) --" << std::endl;
|
||||
std::cout << "-- Software version " << SW_NAME << " v" << SW_VERSION << "."
|
||||
<< SW_SUBVERSION << "." << SW_SUBSUBVERSION << " -- " << std::endl;
|
||||
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
|
||||
|
||||
InitMission::initMission();
|
||||
initmission::initMission();
|
||||
|
||||
for(;;) {
|
||||
// suspend main thread by sleeping it.
|
||||
/* suspend main thread by sleeping it. */
|
||||
TaskFactory::delayTask(5000);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ fi
|
|||
os_fsfw="linux"
|
||||
tgt_bsp="arm/raspberrypi"
|
||||
build_generator=""
|
||||
build_dir="Debug-RPi"
|
||||
if [ "${OS}" = "Windows_NT" ]; then
|
||||
build_generator="MinGW Makefiles"
|
||||
# Could be other OS but this works for now.
|
||||
|
@ -24,4 +25,5 @@ else
|
|||
build_generator="Unix Makefiles"
|
||||
fi
|
||||
|
||||
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "debug" -t "${tgt_bsp}"
|
||||
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "debug" -t "${tgt_bsp}" \
|
||||
-l"${build_dir}"
|
||||
|
|
|
@ -17,6 +17,7 @@ fi
|
|||
os_fsfw="linux"
|
||||
tgt_bsp="arm/raspberrypi"
|
||||
build_generator=""
|
||||
build_dir="Release-RPi"
|
||||
if [ "${OS}" = "Windows_NT" ]; then
|
||||
build_generator="MinGW Makefiles"
|
||||
# Could be other OS but this works for now.
|
||||
|
@ -24,4 +25,5 @@ else
|
|||
build_generator="Unix Makefiles"
|
||||
fi
|
||||
|
||||
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "release" -t "${tgt_bsp}"
|
||||
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "release" -t "${tgt_bsp}" \
|
||||
-l"${build_dir}"
|
||||
|
|
|
@ -17,6 +17,7 @@ fi
|
|||
os_fsfw="linux"
|
||||
tgt_bsp="arm/raspberrypi"
|
||||
build_generator=""
|
||||
build_dir="RelWithDeb-RPi"
|
||||
if [ "${OS}" = "Windows_NT" ]; then
|
||||
build_generator="MinGW Makefiles"
|
||||
# Could be other OS but this works for now.
|
||||
|
@ -24,4 +25,5 @@ else
|
|||
build_generator="Unix Makefiles"
|
||||
fi
|
||||
|
||||
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "reldeb" -t "${tgt_bsp}"
|
||||
python3 cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "reldeb" -t "${tgt_bsp}" \
|
||||
-l"${build_dir}"
|
||||
|
|
|
@ -61,9 +61,10 @@ def main():
|
|||
else:
|
||||
cmake_target_cfg_cmd = ""
|
||||
|
||||
# TODO: Use builddir if given (need to check whether path is relative or absolute)
|
||||
build_folder = cmake_build_type
|
||||
|
||||
if args.builddir is not None:
|
||||
build_folder = args.builddir
|
||||
|
||||
build_path = source_location + os.path.sep + build_folder
|
||||
if os.path.isdir(build_path):
|
||||
remove_old_dir = input(f"{build_folder} folder already exists. Remove old directory? [y/n]: ")
|
||||
|
|
2
fsfw
2
fsfw
|
@ -1 +1 @@
|
|||
Subproject commit 7d0916a44e18c87b00998448333023186b3d85b1
|
||||
Subproject commit 8b561d073c5a664bae2a901c142fcb2e10faf539
|
|
@ -6,20 +6,24 @@
|
|||
#ifndef FSFWCONFIG_OBSWCONFIG_H_
|
||||
#define FSFWCONFIG_OBSWCONFIG_H_
|
||||
|
||||
#define TEST_LIBGPIOD 0
|
||||
#ifdef RASPBERRY_PI
|
||||
#include <rpi_config.h>
|
||||
#endif
|
||||
#include "OBSWVersion.h"
|
||||
|
||||
/* These defines should be disabled for mission code but are useful for
|
||||
debugging. */
|
||||
#define OBSW_VERBOSE_LEVEL 1
|
||||
#define OBSW_VERBOSE_LEVEL 1
|
||||
#define OBSW_PRINT_MISSED_DEADLINES 1
|
||||
#define OBSW_ADD_TEST_CODE 1
|
||||
#define TEST_LIBGPIOD 0
|
||||
|
||||
#define TE0720 0
|
||||
#define TE0720 0
|
||||
|
||||
#define P60DOCK_DEBUG 0
|
||||
#define PDU1_DEBUG 0
|
||||
#define PDU2_DEBUG 0
|
||||
#define ACU_DEBUG 1
|
||||
|
||||
#include "OBSWVersion.h"
|
||||
#define P60DOCK_DEBUG 0
|
||||
#define PDU1_DEBUG 0
|
||||
#define PDU2_DEBUG 0
|
||||
#define ACU_DEBUG 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
|
|
|
@ -15,7 +15,8 @@ namespace gpioIds {
|
|||
HEATER_7,
|
||||
DEPLSA1,
|
||||
DEPLSA2,
|
||||
Test_ID
|
||||
TEST_ID_0,
|
||||
TEST_ID_1
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ enum {
|
|||
MGM_LIS3MDL,
|
||||
MGM_RM3100,
|
||||
LINUX_LIBGPIO_IF,
|
||||
LINUX_SPI_COM_IF,
|
||||
PCDU_HANDLER,
|
||||
HEATER_HANDLER,
|
||||
SA_DEPL_HANDLER
|
||||
|
|
|
@ -2,4 +2,6 @@ add_subdirectory(gpio)
|
|||
add_subdirectory(i2c)
|
||||
add_subdirectory(csp)
|
||||
add_subdirectory(spi)
|
||||
add_subdirectory(utility)
|
||||
add_subdirectory(boardtest)
|
||||
|
||||
|
|
10
linux/boardtest/CMakeLists.txt
Normal file
10
linux/boardtest/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
target_sources(${TARGET_NAME} PRIVATE
|
||||
LibgpiodTest.cpp
|
||||
I2cTestClass.cpp
|
||||
SpiTestClass.cpp
|
||||
UartTestClass.cpp
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
8
linux/boardtest/I2cTestClass.cpp
Normal file
8
linux/boardtest/I2cTestClass.cpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <linux/boardtest/I2cTestClass.h>
|
||||
|
||||
I2cTestClass::I2cTestClass(object_id_t objectId): TestTask(objectId) {
|
||||
}
|
||||
|
||||
ReturnValue_t I2cTestClass::performPeriodicAction() {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
17
linux/boardtest/I2cTestClass.h
Normal file
17
linux/boardtest/I2cTestClass.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef LINUX_BOARDTEST_I2CTESTCLASS_H_
|
||||
#define LINUX_BOARDTEST_I2CTESTCLASS_H_
|
||||
|
||||
#include <test/testtasks/TestTask.h>
|
||||
|
||||
class I2cTestClass: public TestTask {
|
||||
public:
|
||||
I2cTestClass(object_id_t objectId);
|
||||
|
||||
ReturnValue_t performPeriodicAction() override;
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* LINUX_BOARDTEST_I2CTESTCLASS_H_ */
|
99
linux/boardtest/LibgpiodTest.cpp
Normal file
99
linux/boardtest/LibgpiodTest.cpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
#include "LibgpiodTest.h"
|
||||
|
||||
#include <fsfwconfig/devices/gpioIds.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <fsfw/objectmanager/ObjectManagerIF.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
|
||||
LibgpiodTest::LibgpiodTest(object_id_t objectId, object_id_t gpioIfobjectId,
|
||||
GpioCookie* gpioCookie):
|
||||
TestTask(objectId) {
|
||||
|
||||
gpioInterface = objectManager->get<GpioIF>(gpioIfobjectId);
|
||||
if (gpioInterface == nullptr) {
|
||||
sif::error << "LibgpiodTest::LibgpiodTest: Invalid Gpio interface." << std::endl;
|
||||
}
|
||||
gpioInterface->addGpios(gpioCookie);
|
||||
testCase = TestCases::LOOPBACK;
|
||||
}
|
||||
|
||||
LibgpiodTest::~LibgpiodTest() {
|
||||
}
|
||||
|
||||
ReturnValue_t LibgpiodTest::performPeriodicAction() {
|
||||
int gpioState;
|
||||
ReturnValue_t result;
|
||||
|
||||
switch(testCase) {
|
||||
case(TestCases::READ): {
|
||||
result = gpioInterface->readGpio(gpioIds::TEST_ID_0, &gpioState);
|
||||
if (result != RETURN_OK) {
|
||||
sif::debug << "LibgpiodTest::performPeriodicAction: Failed to read gpio "
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
else {
|
||||
sif::debug << "LibgpiodTest::performPeriodicAction: MIO 0 state = " << gpioState
|
||||
<< std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(TestCases::LOOPBACK): {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t LibgpiodTest::performOneShotAction() {
|
||||
int gpioState;
|
||||
ReturnValue_t result;
|
||||
|
||||
switch(testCase) {
|
||||
case(TestCases::READ): {
|
||||
break;
|
||||
}
|
||||
case(TestCases::LOOPBACK): {
|
||||
result = gpioInterface->pullHigh(gpioIds::TEST_ID_0);
|
||||
if(result == HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::info << "LibgpiodTest::performOneShotAction: "
|
||||
"GPIO pulled high successfully for loopback test" << std::endl;
|
||||
}
|
||||
else {
|
||||
sif::warning << "LibgpiodTest::performOneShotAction: Could not pull GPIO high!"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
result = gpioInterface->readGpio(gpioIds::TEST_ID_1, &gpioState);
|
||||
if(result == HasReturnvaluesIF::RETURN_OK and gpioState == 1) {
|
||||
sif::info << "LibgpiodTest::performOneShotAction: "
|
||||
"GPIO state read successfully and is high" << std::endl;
|
||||
}
|
||||
else {
|
||||
sif::warning << "LibgpiodTest::performOneShotAction: GPIO read and is not high!"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
result = gpioInterface->pullLow(gpioIds::TEST_ID_0);
|
||||
if(result == HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::info << "LibgpiodTest::performOneShotAction: "
|
||||
"GPIO pulled low successfully for loopback test" << std::endl;
|
||||
}
|
||||
result = gpioInterface->readGpio(gpioIds::TEST_ID_1, &gpioState);
|
||||
if(result == HasReturnvaluesIF::RETURN_OK and gpioState == 0) {
|
||||
sif::info << "LibgpiodTest::performOneShotAction: "
|
||||
"GPIO state read successfully and is low" << std::endl;
|
||||
}
|
||||
else {
|
||||
sif::warning << "LibgpiodTest::performOneShotAction: GPIO read and is not low!"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
|
@ -12,11 +12,19 @@
|
|||
*/
|
||||
class LibgpiodTest: public TestTask {
|
||||
public:
|
||||
enum TestCases {
|
||||
READ = 0,
|
||||
LOOPBACK = 1
|
||||
};
|
||||
|
||||
TestCases testCase;
|
||||
|
||||
LibgpiodTest(object_id_t objectId, object_id_t gpioIfobjectId, GpioCookie* gpioCookie);
|
||||
virtual ~LibgpiodTest();
|
||||
|
||||
protected:
|
||||
virtual ReturnValue_t performPeriodicAction() override;
|
||||
ReturnValue_t performOneShotAction() override;
|
||||
ReturnValue_t performPeriodicAction() override;
|
||||
|
||||
private:
|
||||
GpioIF* gpioInterface;
|
8
linux/boardtest/SpiTestClass.cpp
Normal file
8
linux/boardtest/SpiTestClass.cpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <linux/boardtest/SpiTestClass.h>
|
||||
|
||||
SpiTestClass::SpiTestClass(object_id_t objectId): TestTask(objectId) {
|
||||
}
|
||||
|
||||
ReturnValue_t SpiTestClass::performPeriodicAction() {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
18
linux/boardtest/SpiTestClass.h
Normal file
18
linux/boardtest/SpiTestClass.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef LINUX_BOARDTEST_SPITESTCLASS_H_
|
||||
#define LINUX_BOARDTEST_SPITESTCLASS_H_
|
||||
|
||||
#include <test/testtasks/TestTask.h>
|
||||
|
||||
class SpiTestClass: public TestTask {
|
||||
public:
|
||||
SpiTestClass(object_id_t objectId);
|
||||
|
||||
ReturnValue_t performPeriodicAction() override;
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* LINUX_BOARDTEST_SPITESTCLASS_H_ */
|
8
linux/boardtest/UartTestClass.cpp
Normal file
8
linux/boardtest/UartTestClass.cpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <linux/boardtest/UartTestClass.h>
|
||||
|
||||
UartTestClass::UartTestClass(object_id_t objectId): TestTask(objectId) {
|
||||
}
|
||||
|
||||
ReturnValue_t UartTestClass::performPeriodicAction() {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
15
linux/boardtest/UartTestClass.h
Normal file
15
linux/boardtest/UartTestClass.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef LINUX_BOARDTEST_UARTTESTCLASS_H_
|
||||
#define LINUX_BOARDTEST_UARTTESTCLASS_H_
|
||||
|
||||
#include <test/testtasks/TestTask.h>
|
||||
|
||||
class UartTestClass: public TestTask {
|
||||
public:
|
||||
UartTestClass(object_id_t objectId);
|
||||
|
||||
ReturnValue_t performPeriodicAction() override;
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif /* LINUX_BOARDTEST_UARTTESTCLASS_H_ */
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef BSP_LINUX_COMIF_COOKIES_CSPCOMIF_H_
|
||||
#define BSP_LINUX_COMIF_COOKIES_CSPCOMIF_H_
|
||||
#ifndef LINUX_CSP_CSPCOMIF_H_
|
||||
#define LINUX_CSP_CSPCOMIF_H_
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
|
@ -86,4 +86,4 @@ private:
|
|||
void initiatePingRequest(uint8_t cspAddress, uint16_t querySize);
|
||||
};
|
||||
|
||||
#endif /* BSP_LINUX_COMIF_COOKIES_CSPCOMIF_H_ */
|
||||
#endif /* LINUX_CSP_CSPCOMIF_H_ */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef BSP_Q7S_COMIF_COOKIES_CSPCOOKIE_H_
|
||||
#define BSP_Q7S_COMIF_COOKIES_CSPCOOKIE_H_
|
||||
#ifndef LINUX_CSP_CSPCOOKIE_H_
|
||||
#define LINUX_CSP_CSPCOOKIE_H_
|
||||
|
||||
#include <fsfw/devicehandlers/CookieIF.h>
|
||||
#include <cstdint>
|
||||
|
@ -24,4 +24,4 @@ private:
|
|||
uint8_t cspAddress;
|
||||
};
|
||||
|
||||
#endif /* BSP_Q7S_COMIF_COOKIES_CSPCOOKIE_H_ */
|
||||
#endif /* LINUX_CSP_CSPCOOKIE_H_ */
|
||||
|
|
|
@ -3,6 +3,10 @@ target_sources(${TARGET_NAME} PUBLIC
|
|||
LinuxLibgpioIF.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(${TARGET_NAME} PUBLIC
|
||||
gpiod
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,25 +1,29 @@
|
|||
#include "GpioCookie.h"
|
||||
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
|
||||
GpioCookie::GpioCookie() {
|
||||
}
|
||||
|
||||
void GpioCookie::addGpio(gpioId_t gpioId, GpioConfig_t gpioConfig){
|
||||
gpioMapIter = gpioMap.find(gpioId);
|
||||
ReturnValue_t GpioCookie::addGpio(gpioId_t gpioId, GpiodRegular& gpioConfig){
|
||||
auto gpioMapIter = gpioMap.find(gpioId);
|
||||
if(gpioMapIter == gpioMap.end()) {
|
||||
std::pair status = gpioMap.emplace(gpioId, gpioConfig);
|
||||
if (status.second == false) {
|
||||
sif::error << "GpioCookie::addGpio: Failed to add GPIO "
|
||||
<< gpioId << "to GPIO map" << std::endl;
|
||||
auto statusPair = gpioMap.emplace(gpioId, new GpiodRegular(gpioConfig));
|
||||
if (statusPair.second == false) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
sif::error << "GpioCookie::addGpio: Failed to add GPIO " << gpioId <<
|
||||
"to GPIO map" << std::endl;
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
else {
|
||||
sif::error << "GpioCookie::addGpio: GPIO already exists in GPIO map "
|
||||
<< std::endl;
|
||||
}
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
sif::error << "GpioCookie::addGpio: GPIO already exists in GPIO map " << std::endl;
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
GpioMap GpioCookie::getGpioMap() const{
|
||||
GpioMap GpioCookie::getGpioMap() const {
|
||||
return gpioMap;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,48 +1,10 @@
|
|||
#ifndef SAM9G20_COMIF_COOKIES_GPIO_COOKIE_H_
|
||||
#define SAM9G20_COMIF_COOKIES_GPIO_COOKIE_H_
|
||||
#ifndef LINUX_GPIO_GPIOCOOKIE_H_
|
||||
#define LINUX_GPIO_GPIOCOOKIE_H_
|
||||
|
||||
#include "GpioIF.h"
|
||||
#include "gpioDefinitions.h"
|
||||
#include <fsfw/devicehandlers/CookieIF.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace gpio {
|
||||
enum Direction {
|
||||
IN = 0,
|
||||
OUT = 1
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Struct containing information about the GPIO to use. This is
|
||||
* required by the libgpiod to access and drive a GPIO.
|
||||
* @param chipname String of the chipname specifying the group which contains
|
||||
* the GPIO to access. E.g. gpiochip0. To detect names of
|
||||
* GPIO groups run gpiodetect on the linux command line.
|
||||
* @param lineNum The offset of the GPIO within the GPIO group.
|
||||
* @param consumer Name of the consumer. Simply a description of the GPIO configuration.
|
||||
* @param direction Specifies whether the GPIO should be used as in- or output.
|
||||
* @param initValue Defines the initial state of the GPIO when configured as output. Only required
|
||||
* for output GPIOs.
|
||||
* @param lineHandle The handle returned by gpiod_chip_get_line will be later written to this
|
||||
* pointer.
|
||||
*/
|
||||
typedef struct GpioConfig {
|
||||
GpioConfig(std::string chipname_, int lineNum_, std::string consumer_,
|
||||
gpio::Direction direction_, int initValue_) :
|
||||
chipname(chipname_), lineNum(lineNum_), consumer(consumer_), direction(direction_),
|
||||
initValue(initValue_) {
|
||||
}
|
||||
std::string chipname;
|
||||
int lineNum;
|
||||
std::string consumer;
|
||||
gpio::Direction direction;
|
||||
int initValue;
|
||||
struct gpiod_line* lineHandle = nullptr;
|
||||
} GpioConfig_t;
|
||||
using GpioMap = std::unordered_map<gpioId_t, GpioConfig_t>;
|
||||
using GpioMapIter = GpioMap::iterator;
|
||||
|
||||
/**
|
||||
* @brief Cookie for the GpioIF. Allows the GpioIF to determine which
|
||||
|
@ -61,16 +23,17 @@ public:
|
|||
|
||||
virtual ~GpioCookie();
|
||||
|
||||
void addGpio(gpioId_t gpioId, GpioConfig_t gpioConfig);
|
||||
ReturnValue_t addGpio(gpioId_t gpioId, GpiodRegular& gpioConfig);
|
||||
/**
|
||||
* @brief Get map with registered GPIOs.
|
||||
*/
|
||||
GpioMap getGpioMap() const;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Returns a copy of the internal GPIO map.
|
||||
*/
|
||||
GpioMap gpioMap;
|
||||
GpioMapIter gpioMapIter;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* LINUX_GPIO_GPIOCOOKIE_H_ */
|
||||
|
|
|
@ -1,33 +1,35 @@
|
|||
#ifndef BSP_Q7S_GPIO_GPIOIF_H_
|
||||
#define BSP_Q7S_GPIO_GPIOIF_H_
|
||||
#ifndef LINUX_GPIO_GPIOIF_H_
|
||||
#define LINUX_GPIO_GPIOIF_H_
|
||||
|
||||
#include "gpioDefinitions.h"
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <fsfw/devicehandlers/CookieIF.h>
|
||||
|
||||
typedef uint16_t gpioId_t;
|
||||
class GpioCookie;
|
||||
|
||||
/**
|
||||
* @brief This class defines the interface for objects requiring the control
|
||||
* over GPIOs.
|
||||
* @author J. Meier
|
||||
*/
|
||||
class GpioIF : public HasReturnvaluesIF{
|
||||
class GpioIF : public HasReturnvaluesIF {
|
||||
public:
|
||||
|
||||
virtual ~GpioIF() {};
|
||||
|
||||
/**
|
||||
* @brief Called by the GPIO using object.
|
||||
* @brief Called by the GPIO using object.
|
||||
* @param cookie Cookie specifying informations of the GPIOs required
|
||||
* by a object.
|
||||
*/
|
||||
virtual ReturnValue_t initialize(CookieIF * cookie) = 0;
|
||||
virtual ReturnValue_t addGpios(GpioCookie* cookie) = 0;
|
||||
|
||||
/**
|
||||
* @brief By implementing this function a child must provide the
|
||||
* functionality to pull a certain GPIO to high logic level.
|
||||
*
|
||||
* @param gpioId A unique number which specifies the GPIO to drive.
|
||||
* @return Returns RETURN_OK for success. This should never return RETURN_FAILED.
|
||||
*/
|
||||
virtual ReturnValue_t pullHigh(gpioId_t gpioId) = 0;
|
||||
|
||||
|
@ -49,4 +51,4 @@ public:
|
|||
virtual ReturnValue_t readGpio(gpioId_t gpioId, int* gpioState) = 0;
|
||||
};
|
||||
|
||||
#endif /* BSP_Q7S_GPIO_GPIOIF_H_ */
|
||||
#endif /* LINUX_GPIO_GPIOIF_H_ */
|
||||
|
|
|
@ -1,141 +1,186 @@
|
|||
#include "LinuxLibgpioIF.h"
|
||||
#include "GpioCookie.h"
|
||||
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
#include <linux/gpio/gpioDefinitions.h>
|
||||
|
||||
#include <utility>
|
||||
#include <unistd.h>
|
||||
#include <gpiod.h>
|
||||
|
||||
|
||||
LinuxLibgpioIF::LinuxLibgpioIF(object_id_t objectId) : SystemObject(objectId) {
|
||||
}
|
||||
|
||||
LinuxLibgpioIF::~LinuxLibgpioIF() {
|
||||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::initialize(CookieIF * cookie){
|
||||
ReturnValue_t LinuxLibgpioIF::addGpios(GpioCookie* gpioCookie) {
|
||||
ReturnValue_t result;
|
||||
GpioMap mapToAdd;
|
||||
|
||||
if(cookie == nullptr) {
|
||||
if(gpioCookie == nullptr) {
|
||||
sif::error << "LinuxLibgpioIF::initialize: Invalid cookie" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
GpioCookie* gpioCookie = dynamic_cast<GpioCookie*>(cookie);
|
||||
if(gpioCookie == nullptr) {
|
||||
sif::error << "LinuxLibgpioIF: Invalid Gpio Cookie!"
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
mapToAdd = gpioCookie->getGpioMap();
|
||||
GpioMap mapToAdd = gpioCookie->getGpioMap();
|
||||
|
||||
result = checkForConflicts(mapToAdd);
|
||||
if (result != RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
|
||||
result = configureGpios(&mapToAdd);
|
||||
result = configureGpios(mapToAdd);
|
||||
if (result != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
/* Register new GPIOs in gpioMap*/
|
||||
/* Register new GPIOs in gpioMap */
|
||||
gpioMap.insert(mapToAdd.begin(), mapToAdd.end());
|
||||
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap* mapToAdd) {
|
||||
GpioMapIter mapToAddIter;
|
||||
ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
||||
for(auto& gpioConfig: mapToAdd) {
|
||||
switch(gpioConfig.second->gpioType) {
|
||||
case(gpio::GpioTypes::NONE): {
|
||||
return GPIO_INVALID_INSTANCE;
|
||||
}
|
||||
case(gpio::GpioTypes::GPIOD_REGULAR): {
|
||||
GpiodRegular* regularGpio = dynamic_cast<GpiodRegular*>(gpioConfig.second);
|
||||
configureRegularGpio(gpioConfig.first, regularGpio);
|
||||
break;
|
||||
}
|
||||
case(gpio::GpioTypes::CALLBACK): {
|
||||
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
|
||||
if(gpioCallback->callback == nullptr) {
|
||||
return GPIO_INVALID_INSTANCE;
|
||||
}
|
||||
gpioCallback->callback(gpioMapIter->first, gpio::GpioOperation::READ,
|
||||
0, gpioCallback->callbackArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, GpiodRegular *regularGpio) {
|
||||
std::string chipname;
|
||||
unsigned int lineNum;
|
||||
struct gpiod_chip *chip;
|
||||
gpio::Direction direction;
|
||||
std::string consumer;
|
||||
struct gpiod_line *lineHandle;
|
||||
int result;
|
||||
int result = 0;
|
||||
|
||||
mapToAddIter = mapToAdd->begin();
|
||||
for (; mapToAddIter != mapToAdd->end(); mapToAddIter++) {
|
||||
|
||||
chipname = mapToAddIter->second.chipname;
|
||||
chip = gpiod_chip_open_by_name(chipname.c_str());
|
||||
if (!chip) {
|
||||
sif::error << "LinuxLibgpioIF::configureGpios: Failed to open chip "
|
||||
<< chipname << ". Gpio ID: " << mapToAddIter->first << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
lineNum = mapToAddIter->second.lineNum;
|
||||
lineHandle = gpiod_chip_get_line(chip, lineNum);
|
||||
if (!lineHandle) {
|
||||
sif::error << "LinuxLibgpioIF::configureGpios: Failed to open line" << std::endl;
|
||||
gpiod_chip_close(chip);
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
direction = mapToAddIter->second.direction;
|
||||
consumer = mapToAddIter->second.consumer;
|
||||
/* Configure direction and add a description to the GPIO */
|
||||
switch (direction) {
|
||||
case gpio::OUT:
|
||||
result = gpiod_line_request_output(lineHandle, consumer.c_str(),
|
||||
mapToAddIter->second.initValue);
|
||||
if (result < 0) {
|
||||
sif::error << "LinuxLibgpioIF::configureGpios: Failed to request line "
|
||||
<< lineNum << " from GPIO instance with ID: " << mapToAddIter->first
|
||||
<< std::endl;
|
||||
gpiod_line_release(lineHandle);
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
break;
|
||||
case gpio::IN:
|
||||
result = gpiod_line_request_input(lineHandle, consumer.c_str());
|
||||
if (result < 0) {
|
||||
sif::error << "LinuxLibgpioIF::configureGpios: Failed to request line "
|
||||
<< lineNum << " from GPIO instance with ID: " << mapToAddIter->first
|
||||
<< std::endl;
|
||||
gpiod_line_release(lineHandle);
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sif::error << "LinuxLibgpioIF::configureGpios: Invalid direction specified"
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
/**
|
||||
* Write line handle to GPIO configuration instance so it can later be used to set or
|
||||
* read states of GPIOs.
|
||||
*/
|
||||
mapToAddIter->second.lineHandle = lineHandle;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId){
|
||||
return driveGpio(gpioId, 1);
|
||||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId){
|
||||
return driveGpio(gpioId, 0);
|
||||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId,
|
||||
unsigned int logiclevel) {
|
||||
int result;
|
||||
struct gpiod_line *lineHandle;
|
||||
|
||||
gpioMapIter = gpioMap.find(gpioId);
|
||||
if (gpioMapIter == gpioMap.end()){
|
||||
sif::debug << "LinuxLibgpioIF::driveGpio: Unknown gpio id " << gpioId << std::endl;
|
||||
chipname = regularGpio->chipname;
|
||||
chip = gpiod_chip_open_by_name(chipname.c_str());
|
||||
if (!chip) {
|
||||
sif::error << "LinuxLibgpioIF::configureGpios: Failed to open chip "
|
||||
<< chipname << ". Gpio ID: " << gpioId << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
lineHandle = gpioMapIter->second.lineHandle;
|
||||
result = gpiod_line_set_value(lineHandle, logiclevel);
|
||||
lineNum = regularGpio->lineNum;
|
||||
lineHandle = gpiod_chip_get_line(chip, lineNum);
|
||||
if (!lineHandle) {
|
||||
sif::error << "LinuxLibgpioIF::configureGpios: Failed to open line" << std::endl;
|
||||
gpiod_chip_close(chip);
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
direction = regularGpio->direction;
|
||||
consumer = regularGpio->consumer;
|
||||
/* Configure direction and add a description to the GPIO */
|
||||
switch (direction) {
|
||||
case(gpio::OUT): {
|
||||
result = gpiod_line_request_output(lineHandle, consumer.c_str(),
|
||||
regularGpio->initValue);
|
||||
if (result < 0) {
|
||||
sif::error << "LinuxLibgpioIF::configureGpios: Failed to request line " << lineNum <<
|
||||
" from GPIO instance with ID: " << gpioId << std::endl;
|
||||
gpiod_line_release(lineHandle);
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(gpio::IN): {
|
||||
result = gpiod_line_request_input(lineHandle, consumer.c_str());
|
||||
if (result < 0) {
|
||||
sif::error << "LinuxLibgpioIF::configureGpios: Failed to request line "
|
||||
<< lineNum << " from GPIO instance with ID: " << gpioId << std::endl;
|
||||
gpiod_line_release(lineHandle);
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
sif::error << "LinuxLibgpioIF::configureGpios: Invalid direction specified"
|
||||
<< std::endl;
|
||||
return GPIO_INVALID_INSTANCE;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Write line handle to GPIO configuration instance so it can later be used to set or
|
||||
* read states of GPIOs.
|
||||
*/
|
||||
regularGpio->lineHandle = lineHandle;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) {
|
||||
gpioMapIter = gpioMap.find(gpioId);
|
||||
if (gpioMapIter == gpioMap.end()) {
|
||||
sif::warning << "LinuxLibgpioIF::driveGpio: Unknown GPIOD ID " << gpioId << std::endl;
|
||||
return UNKNOWN_GPIO_ID;
|
||||
}
|
||||
|
||||
if(gpioMapIter->second->gpioType == gpio::GpioTypes::GPIOD_REGULAR) {
|
||||
return driveGpio(gpioId, dynamic_cast<GpiodRegular*>(gpioMapIter->second), 1);
|
||||
}
|
||||
else {
|
||||
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
|
||||
if(gpioCallback->callback == nullptr) {
|
||||
return GPIO_INVALID_INSTANCE;
|
||||
}
|
||||
gpioCallback->callback(gpioMapIter->first, gpio::GpioOperation::WRITE,
|
||||
1, gpioCallback->callbackArgs);
|
||||
}
|
||||
return GPIO_TYPE_FAILURE;
|
||||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) {
|
||||
gpioMapIter = gpioMap.find(gpioId);
|
||||
if (gpioMapIter == gpioMap.end()) {
|
||||
sif::warning << "LinuxLibgpioIF::driveGpio: Unknown GPIOD ID " << gpioId << std::endl;
|
||||
return UNKNOWN_GPIO_ID;
|
||||
}
|
||||
|
||||
if(gpioMapIter->second->gpioType == gpio::GpioTypes::GPIOD_REGULAR) {
|
||||
return driveGpio(gpioId, dynamic_cast<GpiodRegular*>(gpioMapIter->second), 0);
|
||||
}
|
||||
else {
|
||||
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
|
||||
if(gpioCallback->callback == nullptr) {
|
||||
return GPIO_INVALID_INSTANCE;
|
||||
}
|
||||
gpioCallback->callback(gpioMapIter->first, gpio::GpioOperation::WRITE,
|
||||
0, gpioCallback->callbackArgs);
|
||||
}
|
||||
return GPIO_TYPE_FAILURE;
|
||||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId,
|
||||
GpiodRegular* regularGpio, unsigned int logicLevel) {
|
||||
if(regularGpio == nullptr) {
|
||||
return GPIO_TYPE_FAILURE;
|
||||
}
|
||||
|
||||
int result = gpiod_line_set_value(regularGpio->lineHandle, logicLevel);
|
||||
if (result < 0) {
|
||||
sif::error << "LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID "
|
||||
<< gpioId << " to logic level " << logiclevel << std::endl;
|
||||
sif::warning << "LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID " << gpioId <<
|
||||
" to logic level " << logicLevel << std::endl;
|
||||
return DRIVE_GPIO_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -143,38 +188,76 @@ ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId,
|
|||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::readGpio(gpioId_t gpioId, int* gpioState) {
|
||||
struct gpiod_line *lineHandle;
|
||||
|
||||
gpioMapIter = gpioMap.find(gpioId);
|
||||
if (gpioMapIter == gpioMap.end()){
|
||||
sif::debug << "LinuxLibgpioIF::readGpio: Unknown gpio id " << gpioId << std::endl;
|
||||
return RETURN_FAILED;
|
||||
sif::warning << "LinuxLibgpioIF::readGpio: Unknown GPIOD ID " << gpioId << std::endl;
|
||||
return UNKNOWN_GPIO_ID;
|
||||
}
|
||||
|
||||
if(gpioMapIter->second->gpioType == gpio::GpioTypes::GPIOD_REGULAR) {
|
||||
GpiodRegular* regularGpio = dynamic_cast<GpiodRegular*>(gpioMapIter->second);
|
||||
if(regularGpio == nullptr) {
|
||||
return GPIO_TYPE_FAILURE;
|
||||
}
|
||||
*gpioState = gpiod_line_get_value(regularGpio->lineHandle);
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
lineHandle = gpioMapIter->second.lineHandle;
|
||||
*gpioState = gpiod_line_get_value(lineHandle);
|
||||
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::checkForConflicts(GpioMap mapToAdd){
|
||||
gpioId_t gpioId;
|
||||
GpioMapIter mapToAddIter = mapToAdd.begin();
|
||||
for(; mapToAddIter != mapToAdd.end(); mapToAddIter++){
|
||||
gpioId = mapToAddIter->first;
|
||||
gpioMapIter = gpioMap.find(gpioId);
|
||||
if(gpioMapIter != mapToAdd.end()){
|
||||
/* An entry for this GPIO already exists. Check if configuration
|
||||
* of direction is equivalent */
|
||||
if (mapToAddIter->second.direction != gpioMapIter->second.direction){
|
||||
sif::error << "LinuxLibgpioIF::checkForConflicts: Detected conflict "
|
||||
<< "for GPIO " << mapToAddIter->first << std::endl;
|
||||
return RETURN_OK;
|
||||
ReturnValue_t LinuxLibgpioIF::checkForConflicts(GpioMap& mapToAdd){
|
||||
ReturnValue_t status = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
for(auto& gpioConfig: mapToAdd) {
|
||||
switch(gpioConfig.second->gpioType) {
|
||||
case(gpio::GpioTypes::GPIOD_REGULAR): {
|
||||
auto regularGpio = dynamic_cast<GpiodRegular*>(gpioConfig.second);
|
||||
if(regularGpio == nullptr) {
|
||||
return GPIO_TYPE_FAILURE;
|
||||
}
|
||||
/* Remove element from map to add because a entry for this GPIO
|
||||
* already exists */
|
||||
mapToAdd.erase(mapToAddIter);
|
||||
result = checkForConflictsRegularGpio(gpioConfig.first, regularGpio);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
status = result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return RETURN_OK;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::checkForConflictsRegularGpio(gpioId_t gpioIdToCheck,
|
||||
GpiodRegular* gpioToCheck) {
|
||||
/* Cross check with private map */
|
||||
gpioMapIter = gpioMap.find(gpioIdToCheck);
|
||||
if(gpioMapIter != gpioMap.end()) {
|
||||
if(gpioMapIter->second->gpioType == gpio::GpioTypes::GPIOD_REGULAR) {
|
||||
auto ownRegularGpio = dynamic_cast<GpiodRegular*>(gpioMapIter->second);
|
||||
if(ownRegularGpio == nullptr) {
|
||||
return GPIO_TYPE_FAILURE;
|
||||
}
|
||||
/* An entry for this GPIO already exists. Check if configuration
|
||||
* of direction is equivalent */
|
||||
if (gpioToCheck->direction != ownRegularGpio->direction){
|
||||
sif::error << "LinuxLibgpioIF::checkForConflicts: Detected conflict for GPIO " <<
|
||||
gpioIdToCheck << std::endl;
|
||||
return RETURN_FAILED;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove element from map to add because a entry for this GPIO
|
||||
* already exists */
|
||||
gpioMap.erase(gpioIdToCheck);
|
||||
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
#ifndef BSP_Q7S_GPIO_LINUXLIBGPIOIF_H_
|
||||
#define BSP_Q7S_GPIO_LINUXLIBGPIOIF_H_
|
||||
#ifndef LINUX_GPIO_LINUXLIBGPIOIF_H_
|
||||
#define LINUX_GPIO_LINUXLIBGPIOIF_H_
|
||||
|
||||
#include <linux/gpio/GpioIF.h>
|
||||
#include <linux/gpio/GpioCookie.h>
|
||||
#include <fsfwconfig/returnvalues/classIds.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
|
||||
class GpioCookie;
|
||||
|
||||
/**
|
||||
* @brief This class implements the GpioIF for a linux based system. The
|
||||
* implementation is based on the libgpiod lib which requires linux 4.8
|
||||
|
@ -16,21 +17,27 @@
|
|||
class LinuxLibgpioIF : public GpioIF, public SystemObject {
|
||||
public:
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::LINUX_LIBGPIO_IF;
|
||||
static const uint8_t gpioRetvalId = CLASS_ID::LINUX_LIBGPIO_IF;
|
||||
|
||||
static const ReturnValue_t DRIVE_GPIO_FAILURE = MAKE_RETURN_CODE(0x2);
|
||||
static constexpr ReturnValue_t UNKNOWN_GPIO_ID =
|
||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 1);
|
||||
static constexpr ReturnValue_t DRIVE_GPIO_FAILURE =
|
||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 2);
|
||||
static constexpr ReturnValue_t GPIO_TYPE_FAILURE =
|
||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 3);
|
||||
static constexpr ReturnValue_t GPIO_INVALID_INSTANCE =
|
||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 4);
|
||||
|
||||
LinuxLibgpioIF(object_id_t objectId);
|
||||
virtual ~LinuxLibgpioIF();
|
||||
|
||||
ReturnValue_t initialize(CookieIF * cookie) override;
|
||||
ReturnValue_t addGpios(GpioCookie* gpioCookie) override;
|
||||
ReturnValue_t pullHigh(gpioId_t gpioId) override;
|
||||
ReturnValue_t pullLow(gpioId_t gpioId) override;
|
||||
ReturnValue_t readGpio(gpioId_t gpioId, int* gpioState) override;
|
||||
|
||||
private:
|
||||
|
||||
/*Holds the information and configuration of all used GPIOs */
|
||||
/* Holds the information and configuration of all used GPIOs */
|
||||
GpioMap gpioMap;
|
||||
GpioMapIter gpioMapIter;
|
||||
|
||||
|
@ -40,8 +47,9 @@ private:
|
|||
* @param gpioId The GPIO ID of the GPIO to drive.
|
||||
* @param logiclevel The logic level to set. O or 1.
|
||||
*/
|
||||
ReturnValue_t driveGpio(gpioId_t gpioId,
|
||||
unsigned int logiclevel);
|
||||
ReturnValue_t driveGpio(gpioId_t gpioId, GpiodRegular* regularGpio, unsigned int logiclevel);
|
||||
|
||||
ReturnValue_t configureRegularGpio(gpioId_t gpioId, GpiodRegular* regularGpio);
|
||||
|
||||
/**
|
||||
* @brief This function checks if GPIOs are already registered and whether
|
||||
|
@ -52,12 +60,15 @@ private:
|
|||
*
|
||||
* @return RETURN_OK if successful, otherwise RETURN_FAILED
|
||||
*/
|
||||
ReturnValue_t checkForConflicts(GpioMap mapToAdd);
|
||||
ReturnValue_t checkForConflicts(GpioMap& mapToAdd);
|
||||
|
||||
ReturnValue_t checkForConflictsRegularGpio(gpioId_t gpiodId, GpiodRegular* regularGpio);
|
||||
|
||||
/**
|
||||
* @brief Performs the initial configuration of all GPIOs specified in the GpioMap mapToAdd.
|
||||
*/
|
||||
ReturnValue_t configureGpios(GpioMap* mapToAdd);
|
||||
ReturnValue_t configureGpios(GpioMap& mapToAdd);
|
||||
|
||||
};
|
||||
|
||||
#endif /* BSP_Q7S_GPIO_LINUXLIBGPIOIF_H_ */
|
||||
#endif /* LINUX_GPIO_LINUXLIBGPIOIF_H_ */
|
||||
|
|
92
linux/gpio/gpioDefinitions.h
Normal file
92
linux/gpio/gpioDefinitions.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
#ifndef LINUX_GPIO_GPIODEFINITIONS_H_
|
||||
#define LINUX_GPIO_GPIODEFINITIONS_H_
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
using gpioId_t = uint16_t;
|
||||
|
||||
namespace gpio {
|
||||
enum Direction {
|
||||
IN = 0,
|
||||
OUT = 1
|
||||
};
|
||||
|
||||
enum GpioOperation {
|
||||
READ,
|
||||
WRITE
|
||||
};
|
||||
|
||||
enum GpioTypes {
|
||||
NONE,
|
||||
GPIOD_REGULAR,
|
||||
CALLBACK
|
||||
};
|
||||
|
||||
static constexpr gpioId_t NO_GPIO = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Struct containing information about the GPIO to use. This is
|
||||
* required by the libgpiod to access and drive a GPIO.
|
||||
* @param chipname String of the chipname specifying the group which contains the GPIO to
|
||||
* access. E.g. gpiochip0. To detect names of GPIO groups run gpiodetect on
|
||||
* the linux command line.
|
||||
* @param lineNum The offset of the GPIO within the GPIO group.
|
||||
* @param consumer Name of the consumer. Simply a description of the GPIO configuration.
|
||||
* @param direction Specifies whether the GPIO should be used as in- or output.
|
||||
* @param initValue Defines the initial state of the GPIO when configured as output.
|
||||
* Only required for output GPIOs.
|
||||
* @param lineHandle The handle returned by gpiod_chip_get_line will be later written to this
|
||||
* pointer.
|
||||
*/
|
||||
class GpioBase {
|
||||
public:
|
||||
|
||||
GpioBase() = default;
|
||||
|
||||
GpioBase(gpio::GpioTypes gpioType, std::string consumer, gpio::Direction direction,
|
||||
int initValue):
|
||||
gpioType(gpioType), consumer(consumer),direction(direction), initValue(initValue) {}
|
||||
|
||||
virtual~ GpioBase() {};
|
||||
|
||||
/* Can be used to cast GpioBase to a concrete child implementation */
|
||||
gpio::GpioTypes gpioType = gpio::GpioTypes::NONE;
|
||||
std::string consumer;
|
||||
gpio::Direction direction = gpio::Direction::IN;
|
||||
int initValue = 0;
|
||||
};
|
||||
|
||||
class GpiodRegular: public GpioBase {
|
||||
public:
|
||||
GpiodRegular(): GpioBase(gpio::GpioTypes::GPIOD_REGULAR, std::string(),
|
||||
gpio::Direction::IN, 0) {};
|
||||
|
||||
GpiodRegular(std::string chipname_, int lineNum_, std::string consumer_,
|
||||
gpio::Direction direction_, int initValue_):
|
||||
GpioBase(gpio::GpioTypes::GPIOD_REGULAR, consumer_, direction_, initValue_),
|
||||
chipname(chipname_), lineNum(lineNum_) {}
|
||||
std::string chipname;
|
||||
int lineNum = 0;
|
||||
struct gpiod_line* lineHandle = nullptr;
|
||||
};
|
||||
|
||||
class GpioCallback: public GpioBase {
|
||||
public:
|
||||
GpioCallback(std::string consumer, gpio::Direction direction_, int initValue_,
|
||||
void (* callback) (gpioId_t gpioId, gpio::GpioOperation gpioOp, int value, void* args),
|
||||
void* callbackArgs):
|
||||
GpioBase(gpio::GpioTypes::CALLBACK, consumer, direction_, initValue_),
|
||||
callback(callback), callbackArgs(callbackArgs) {}
|
||||
|
||||
void (* callback) (gpioId_t gpioId, gpio::GpioOperation gpioOp,
|
||||
int value, void* args) = nullptr;
|
||||
void* callbackArgs = nullptr;
|
||||
};
|
||||
|
||||
|
||||
using GpioMap = std::unordered_map<gpioId_t, GpioBase*>;
|
||||
using GpioMapIter = GpioMap::iterator;
|
||||
|
||||
#endif /* LINUX_GPIO_GPIODEFINITIONS_H_ */
|
|
@ -1,12 +1,13 @@
|
|||
#include "I2cComIF.h"
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <linux/utility/Utility.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
||||
I2cComIF::I2cComIF(object_id_t objectId): SystemObject(objectId){
|
||||
|
@ -14,191 +15,182 @@ I2cComIF::I2cComIF(object_id_t objectId): SystemObject(objectId){
|
|||
|
||||
I2cComIF::~I2cComIF() {}
|
||||
|
||||
ReturnValue_t I2cComIF::initializeInterface(CookieIF * cookie) {
|
||||
ReturnValue_t I2cComIF::initializeInterface(CookieIF* cookie) {
|
||||
|
||||
address_t i2cAddress;
|
||||
std::string deviceFile;
|
||||
address_t i2cAddress;
|
||||
std::string deviceFile;
|
||||
|
||||
if(cookie == nullptr) {
|
||||
return NULLPOINTER;
|
||||
}
|
||||
I2cCookie* i2cCookie = dynamic_cast<I2cCookie*>(cookie);
|
||||
if(i2cCookie == nullptr) {
|
||||
sif::error << "I2cComIF: Invalid I2C Cookie!"
|
||||
<< std::endl;
|
||||
return NULLPOINTER;
|
||||
}
|
||||
if(cookie == nullptr) {
|
||||
sif::error << "I2cComIF::initializeInterface: Invalid cookie!" << std::endl;
|
||||
return NULLPOINTER;
|
||||
}
|
||||
I2cCookie* i2cCookie = dynamic_cast<I2cCookie*>(cookie);
|
||||
if(i2cCookie == nullptr) {
|
||||
sif::error << "I2cComIF::initializeInterface: Invalid I2C cookie!" << std::endl;
|
||||
return NULLPOINTER;
|
||||
}
|
||||
|
||||
i2cAddress = i2cCookie->getAddress();
|
||||
i2cAddress = i2cCookie->getAddress();
|
||||
|
||||
i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress);
|
||||
if(i2cDeviceMapIter == i2cDeviceMap.end()) {
|
||||
size_t maxReplyLen = i2cCookie->getMaxReplyLen();
|
||||
I2cInstance_t i2cInstance = {std::vector<uint8_t>(maxReplyLen), 0};
|
||||
std::pair status = i2cDeviceMap.emplace(i2cAddress, i2cInstance);
|
||||
if (status.second == false) {
|
||||
sif::error << "I2cComIF::initializeInterface: Failed to insert "
|
||||
<< "device with address " << i2cAddress << "to I2C device "
|
||||
<< "map" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sif::error << "I2cComIF: Device with address " << i2cAddress
|
||||
<< "already in use" << std::endl;
|
||||
}
|
||||
i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress);
|
||||
if(i2cDeviceMapIter == i2cDeviceMap.end()) {
|
||||
size_t maxReplyLen = i2cCookie->getMaxReplyLen();
|
||||
I2cInstance_t i2cInstance = {std::vector<uint8_t>(maxReplyLen), 0};
|
||||
auto statusPair = i2cDeviceMap.emplace(i2cAddress, i2cInstance);
|
||||
if (not statusPair.second) {
|
||||
sif::error << "I2cComIF::initializeInterface: Failed to insert device with address " <<
|
||||
i2cAddress << "to I2C device " << "map" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress);
|
||||
if(i2cDeviceMapIter == i2cDeviceMap.end()) {
|
||||
sif::error << "Failure" << std::endl;
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
sif::error << "I2cComIF::initializeInterface: Device with address " << i2cAddress <<
|
||||
"already in use" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t I2cComIF::sendMessage(CookieIF *cookie,
|
||||
const uint8_t *sendData, size_t sendLen) {
|
||||
|
||||
ReturnValue_t result;
|
||||
int fd;
|
||||
std::string deviceFile;
|
||||
ReturnValue_t result;
|
||||
int fd;
|
||||
std::string deviceFile;
|
||||
|
||||
if(sendData == nullptr) {
|
||||
sif::error << "I2cComIF::sendMessage: Send Data is nullptr"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
if(sendData == nullptr) {
|
||||
sif::error << "I2cComIF::sendMessage: Send Data is nullptr"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
if(sendLen == 0) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
if(sendLen == 0) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
I2cCookie* i2cCookie = dynamic_cast<I2cCookie*>(cookie);
|
||||
if(i2cCookie == nullptr) {
|
||||
sif::error << "I2cComIF::sendMessasge: Invalid I2C Cookie!"
|
||||
<< std::endl;
|
||||
return NULLPOINTER;
|
||||
}
|
||||
I2cCookie* i2cCookie = dynamic_cast<I2cCookie*>(cookie);
|
||||
if(i2cCookie == nullptr) {
|
||||
sif::error << "I2cComIF::sendMessage: Invalid I2C Cookie!" << std::endl;
|
||||
return NULLPOINTER;
|
||||
}
|
||||
|
||||
address_t i2cAddress = i2cCookie->getAddress();
|
||||
i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress);
|
||||
if (i2cDeviceMapIter == i2cDeviceMap.end()) {
|
||||
sif::error << "I2cComIF::sendMessage: i2cAddress of Cookie not "
|
||||
<< "registered in i2cDeviceMap" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
address_t i2cAddress = i2cCookie->getAddress();
|
||||
i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress);
|
||||
if (i2cDeviceMapIter == i2cDeviceMap.end()) {
|
||||
sif::error << "I2cComIF::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;
|
||||
}
|
||||
deviceFile = i2cCookie->getDeviceFile();
|
||||
utility::UnixFileHelper fileHelper(deviceFile, &fd, O_RDWR, "I2cComIF::sendMessage");
|
||||
if(fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
||||
return fileHelper.getOpenResult();
|
||||
}
|
||||
result = openDevice(deviceFile, i2cAddress, &fd);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
|
||||
if (write(fd, sendData, sendLen) != (int)sendLen) {
|
||||
sif::error << "I2cComIF::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;
|
||||
if (write(fd, sendData, sendLen) != (int)sendLen) {
|
||||
sif::error << "I2cComIF::sendMessage: Failed to send data to I2C "
|
||||
"device with error code " << errno << ". Error description: "
|
||||
<< strerror(errno) << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t I2cComIF::getSendSuccess(CookieIF *cookie) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF *cookie,
|
||||
size_t requestLen) {
|
||||
size_t requestLen) {
|
||||
ReturnValue_t result;
|
||||
int fd;
|
||||
std::string deviceFile;
|
||||
|
||||
ReturnValue_t result;
|
||||
int fd;
|
||||
std::string deviceFile;
|
||||
if (requestLen == 0) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
if (requestLen == 0) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
I2cCookie* i2cCookie = dynamic_cast<I2cCookie*>(cookie);
|
||||
if(i2cCookie == nullptr) {
|
||||
sif::error << "I2cComIF::requestReceiveMessage: Invalid I2C Cookie!" << std::endl;
|
||||
i2cDeviceMapIter->second.replyLen = 0;
|
||||
return NULLPOINTER;
|
||||
}
|
||||
|
||||
I2cCookie* i2cCookie = dynamic_cast<I2cCookie*>(cookie);
|
||||
if(i2cCookie == nullptr) {
|
||||
sif::error << "I2cComIF::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 << "I2cComIF::requestReceiveMessage: i2cAddress of Cookie not "
|
||||
<< "registered in i2cDeviceMap" << std::endl;
|
||||
i2cDeviceMapIter->second.replyLen = 0;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
address_t i2cAddress = i2cCookie->getAddress();
|
||||
i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress);
|
||||
if (i2cDeviceMapIter == i2cDeviceMap.end()) {
|
||||
sif::error << "I2cComIF::requestReceiveMessage: i2cAddress of Cookie not "
|
||||
<< "registered in i2cDeviceMap" << std::endl;
|
||||
i2cDeviceMapIter->second.replyLen = 0;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
deviceFile = i2cCookie->getDeviceFile();
|
||||
utility::UnixFileHelper fileHelper(deviceFile, &fd, O_RDWR, "I2cComIF::requestReceiveMessage");
|
||||
if(fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
||||
return fileHelper.getOpenResult();
|
||||
}
|
||||
result = openDevice(deviceFile, i2cAddress, &fd);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||
i2cDeviceMapIter->second.replyLen = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
uint8_t* replyBuffer = i2cDeviceMapIter->second.replyBuffer.data();
|
||||
if (read(fd, replyBuffer, requestLen) != static_cast<int>(requestLen)) {
|
||||
sif::error << "I2cComIF::requestReceiveMessage: Reading from I2C "
|
||||
<< "device failed with error code " << errno <<". Description"
|
||||
<< " of error: " << strerror(errno) << std::endl;
|
||||
i2cDeviceMapIter->second.replyLen = 0;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
if (read(fd, replyBuffer, requestLen) != (int)requestLen) {
|
||||
sif::error << "I2cComIF::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;
|
||||
i2cDeviceMapIter->second.replyLen = requestLen;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t I2cComIF::readReceivedMessage(CookieIF *cookie,
|
||||
uint8_t **buffer, size_t* size) {
|
||||
I2cCookie* i2cCookie = dynamic_cast<I2cCookie*>(cookie);
|
||||
if(i2cCookie == nullptr) {
|
||||
sif::error << "I2cComIF::readReceivedMessage: Invalid I2C Cookie!"
|
||||
<< std::endl;
|
||||
return NULLPOINTER;
|
||||
}
|
||||
uint8_t **buffer, size_t* size) {
|
||||
I2cCookie* i2cCookie = dynamic_cast<I2cCookie*>(cookie);
|
||||
if(i2cCookie == nullptr) {
|
||||
sif::error << "I2cComIF::readReceivedMessage: Invalid I2C Cookie!" << std::endl;
|
||||
return NULLPOINTER;
|
||||
}
|
||||
|
||||
address_t i2cAddress = i2cCookie->getAddress();
|
||||
i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress);
|
||||
if (i2cDeviceMapIter == i2cDeviceMap.end()) {
|
||||
sif::error << "I2cComIF::readReceivedMessage: i2cAddress of Cookie not "
|
||||
<< "found in i2cDeviceMap" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
*buffer = i2cDeviceMapIter->second.replyBuffer.data();
|
||||
*size = i2cDeviceMapIter->second.replyLen;
|
||||
address_t i2cAddress = i2cCookie->getAddress();
|
||||
i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress);
|
||||
if (i2cDeviceMapIter == i2cDeviceMap.end()) {
|
||||
sif::error << "I2cComIF::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;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t I2cComIF::openDevice(std::string deviceFile,
|
||||
address_t i2cAddress, int* fileDescriptor) {
|
||||
*fileDescriptor = open(deviceFile.c_str(), O_RDWR);
|
||||
if (*fileDescriptor < 0) {
|
||||
sif::error << "I2cComIF: Opening i2c device failed with error code "
|
||||
<< errno << ". Error description: " << strerror(errno)
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
address_t i2cAddress, int* fileDescriptor) {
|
||||
|
||||
if (ioctl(*fileDescriptor, I2C_SLAVE, i2cAddress) < 0) {
|
||||
sif::error << "I2cComIF: Specifying target device failed with error "
|
||||
<< "code " << errno << ". Error description "
|
||||
<< strerror(errno) << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
if (ioctl(*fileDescriptor, I2C_SLAVE, i2cAddress) < 0) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "I2cComIF: Specifying target device failed with error code " << errno << "."
|
||||
<< std::endl;
|
||||
sif::warning << "Error description " << strerror(errno) << std::endl;
|
||||
#else
|
||||
sif::printWarning("I2cComIF: Specifying target device failed with error code %d.\n");
|
||||
sif::printWarning("Error description: %s\n", strerror(errno));
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef BSP_Q7S_COMIF_I2COMIF_H_
|
||||
#define BSP_Q7S_COMIF_I2COMIF_H_
|
||||
#ifndef LINUX_I2C_I2COMIF_H_
|
||||
#define LINUX_I2C_I2COMIF_H_
|
||||
|
||||
#include "I2cCookie.h"
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
|
@ -45,8 +45,8 @@ private:
|
|||
I2cDeviceMapIter i2cDeviceMapIter;
|
||||
|
||||
/**
|
||||
* @brief This function opens an i2c device and binds the opened file
|
||||
* to a specific i2c address.
|
||||
* @brief This function opens an I2C device and binds the opened file
|
||||
* to a specific I2C address.
|
||||
* @param deviceFile The name of the device file. E.g. i2c-0
|
||||
* @param i2cAddress The address of the i2c slave device.
|
||||
* @param fileDescriptor Pointer to device descriptor.
|
||||
|
@ -56,4 +56,4 @@ private:
|
|||
address_t i2cAddress, int* fileDescriptor);
|
||||
};
|
||||
|
||||
#endif /* BSP_Q7S_COMIF_I2COMIF_H_ */
|
||||
#endif /* LINUX_I2C_I2COMIF_H_ */
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
I2cCookie::I2cCookie(address_t i2cAddress_, size_t maxReplyLen_,
|
||||
std::string deviceFile_) :
|
||||
i2cAddress(i2cAddress_), maxReplyLen(maxReplyLen_), deviceFile(
|
||||
deviceFile_) {
|
||||
i2cAddress(i2cAddress_), maxReplyLen(maxReplyLen_), deviceFile(deviceFile_) {
|
||||
}
|
||||
|
||||
address_t I2cCookie::getAddress() const {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef SAM9G20_COMIF_COOKIES_I2C_COOKIE_H_
|
||||
#define SAM9G20_COMIF_COOKIES_I2C_COOKIE_H_
|
||||
#ifndef LINUX_I2C_I2CCOOKIE_H_
|
||||
#define LINUX_I2C_I2CCOOKIE_H_
|
||||
|
||||
#include <fsfw/devicehandlers/CookieIF.h>
|
||||
#include <string>
|
||||
|
@ -34,4 +34,4 @@ private:
|
|||
std::string deviceFile;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* LINUX_I2C_I2CCOOKIE_H_ */
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
target_sources(${TARGET_NAME} PUBLIC
|
||||
SpiComIF.cpp
|
||||
SpiCookie.cpp
|
||||
)
|
||||
|
||||
|
||||
|
|
294
linux/spi/SpiComIF.cpp
Normal file
294
linux/spi/SpiComIF.cpp
Normal file
|
@ -0,0 +1,294 @@
|
|||
#include "SpiComIF.h"
|
||||
#include "spiDefinitions.h"
|
||||
|
||||
#include <linux/utility/Utility.h>
|
||||
#include <linux/spi/SpiCookie.h>
|
||||
|
||||
#include <fsfw/ipc/MutexFactory.h>
|
||||
#include <fsfw/ipc/MutexHelper.h>
|
||||
|
||||
#include <linux/spi/spidev.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
|
||||
SpiComIF::SpiComIF(object_id_t objectId, GpioIF* gpioComIF): SystemObject(objectId),
|
||||
gpioComIF(gpioComIF) {
|
||||
if(gpioComIF == nullptr) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "SpiComIF::SpiComIF: GPIO communication interface invalid!" << std::endl;
|
||||
#else
|
||||
sif::printError("SpiComIF::SpiComIF: GPIO communication interface invalid!\n");
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
}
|
||||
|
||||
spiMutex = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
ReturnValue_t SpiComIF::initializeInterface(CookieIF *cookie) {
|
||||
SpiCookie* spiCookie = dynamic_cast<SpiCookie*>(cookie);
|
||||
if(spiCookie == nullptr) {
|
||||
return NULLPOINTER;
|
||||
}
|
||||
|
||||
address_t spiAddress = spiCookie->getSpiAddress();
|
||||
|
||||
auto iter = spiDeviceMap.find(spiAddress);
|
||||
if(iter == spiDeviceMap.end()) {
|
||||
size_t bufferSize = spiCookie->getMaxBufferSize();
|
||||
SpiInstance spiInstance = {std::vector<uint8_t>(bufferSize)};
|
||||
auto statusPair = spiDeviceMap.emplace(spiAddress, spiInstance);
|
||||
if (not statusPair.second) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "SpiComIF::initializeInterface: Failed to insert device with address " <<
|
||||
spiAddress << "to SPI device map" << std::endl;
|
||||
#else
|
||||
sif::printError("SpiComIF::initializeInterface: Failed to insert device with address "
|
||||
"%lu to SPI device map\n", static_cast<unsigned long>(spiAddress));
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
/* Now we emplaced the read buffer in the map, we still need to assign that location
|
||||
to the SPI driver transfer struct */
|
||||
spiCookie->assignReadBuffer(statusPair.first->second.replyBuffer.data());
|
||||
}
|
||||
else {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "SpiComIF::initializeInterface: SPI address already exists!" << std::endl;
|
||||
#else
|
||||
sif::printError("SpiComIF::initializeInterface: SPI address already exists!\n");
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
gpioId_t gpioId = spiCookie->getChipSelectPin();
|
||||
if(gpioId != gpio::NO_GPIO) {
|
||||
gpioComIF->pullHigh(gpioId);
|
||||
}
|
||||
|
||||
size_t spiSpeed = 0;
|
||||
spi::SpiMode spiMode = spi::SpiMode::MODE_0;
|
||||
|
||||
SpiCookie::UncommonParameters params;
|
||||
spiCookie->getSpiParameters(spiMode, spiSpeed, ¶ms);
|
||||
|
||||
int fileDescriptor = 0;
|
||||
utility::UnixFileHelper fileHelper(spiCookie->getSpiDevice(), &fileDescriptor, O_RDWR,
|
||||
"SpiComIF::initializeInterface: ");
|
||||
if(fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
||||
return fileHelper.getOpenResult();
|
||||
}
|
||||
|
||||
int retval = ioctl(fileDescriptor, SPI_IOC_WR_MODE, spiSpeed);
|
||||
if(retval != 0) {
|
||||
utility::handleIoctlError("SpiComIF::initializeInterface: Setting SPI mode failed!");
|
||||
}
|
||||
|
||||
retval = ioctl(fileDescriptor, SPI_IOC_WR_MAX_SPEED_HZ, spiSpeed);
|
||||
if(retval != 0) {
|
||||
utility::handleIoctlError("SpiComIF::initializeInterface: Setting SPI speed failed!");
|
||||
}
|
||||
|
||||
/* These flags are rather uncommon */
|
||||
if(params.threeWireSpi or params.noCs or params.csHigh) {
|
||||
uint32_t currentMode = 0;
|
||||
retval = ioctl(fileDescriptor, SPI_IOC_RD_MODE32, ¤tMode);
|
||||
if(retval != 0) {
|
||||
utility::handleIoctlError("SpiComIF::initialiezInterface: Could not read full mode!");
|
||||
}
|
||||
|
||||
if(params.threeWireSpi) {
|
||||
currentMode |= SPI_3WIRE;
|
||||
}
|
||||
if(params.noCs) {
|
||||
/* Some drivers like the Raspberry Pi ignore this flag in any case */
|
||||
currentMode |= SPI_NO_CS;
|
||||
}
|
||||
if(params.csHigh) {
|
||||
currentMode |= SPI_CS_HIGH;
|
||||
}
|
||||
/* Write adapted mode */
|
||||
retval = ioctl(fileDescriptor, SPI_IOC_WR_MODE32, currentMode);
|
||||
if(retval != 0) {
|
||||
utility::handleIoctlError("SpiComIF::initialiezInterface: Could not write full mode!");
|
||||
}
|
||||
}
|
||||
if(params.lsbFirst) {
|
||||
retval = ioctl(fileDescriptor, SPI_IOC_WR_LSB_FIRST, true);
|
||||
if(retval != 0) {
|
||||
utility::handleIoctlError("SpiComIF::initializeInterface: Setting LSB first failed");
|
||||
}
|
||||
}
|
||||
if(params.bitsPerWord != 8) {
|
||||
retval = ioctl(fileDescriptor, SPI_IOC_WR_BITS_PER_WORD, params.bitsPerWord);
|
||||
if(retval != 0) {
|
||||
utility::handleIoctlError("SpiComIF::initializeInterface: "
|
||||
"Could not write bits per word!");
|
||||
}
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t SpiComIF::sendMessage(CookieIF *cookie, const uint8_t *sendData, size_t sendLen) {
|
||||
SpiCookie* spiCookie = dynamic_cast<SpiCookie*>(cookie);
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
if(spiCookie == nullptr) {
|
||||
return NULLPOINTER;
|
||||
}
|
||||
|
||||
if(sendLen > spiCookie->getMaxBufferSize()) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "SpiComIF::sendMessage: Too much data sent, send length" << sendLen <<
|
||||
"larger than maximum buffer length" << spiCookie->getMaxBufferSize() << std::endl;
|
||||
#else
|
||||
sif::printWarning("SpiComIF::sendMessage: Too much data sent, send length %lu larger "
|
||||
"than maximum buffer length %lu!\n", static_cast<unsigned long>(sendLen),
|
||||
static_cast<unsigned long>(spiCookie->getMaxBufferSize()));
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
return DeviceCommunicationIF::TOO_MUCH_DATA;
|
||||
}
|
||||
|
||||
spiCookie->assignWriteBuffer(sendData);
|
||||
spiCookie->assignTransferSize(sendLen);
|
||||
int fileDescriptor = 0;
|
||||
std::string device = spiCookie->getSpiDevice();
|
||||
utility::UnixFileHelper fileHelper(device, &fileDescriptor, O_RDWR,
|
||||
"SpiComIF::sendMessage: ");
|
||||
if(fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
||||
return OPENING_FILE_FAILED;
|
||||
}
|
||||
|
||||
bool fullDuplex = spiCookie->isFullDuplex();
|
||||
int retval = 0;
|
||||
|
||||
gpioId_t gpioId = spiCookie->getChipSelectPin();
|
||||
MutexHelper(spiMutex, timeoutType, timeoutMs);
|
||||
if(gpioId != gpio::NO_GPIO) {
|
||||
/* For now, no support for active high given */
|
||||
gpioComIF->pullLow(gpioId);
|
||||
}
|
||||
|
||||
if(fullDuplex) {
|
||||
/* Initiate a full duplex SPI transfer. */
|
||||
retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), spiCookie->getTransferStructHandle());
|
||||
if(retval != 0) {
|
||||
utility::handleIoctlError("SpiComIF::sendMessage: ioctl error.");
|
||||
result = FULL_DUPLEX_TRANSFER_FAILED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* We write with a blocking transfer here */
|
||||
if (write(fileDescriptor, sendData, sendLen) != static_cast<ssize_t>(sendLen)) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "SpiComIF::sendMessage: Half-Duplex write operation failed!" <<
|
||||
std::endl;
|
||||
#else
|
||||
sif::printWarning("SpiComIF::sendMessage: Half-Duplex write operation failed!\n");
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
result = HALF_DUPLEX_TRANSFER_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if(gpioId != gpio::NO_GPIO) {
|
||||
gpioComIF->pullHigh(gpioId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t SpiComIF::getSendSuccess(CookieIF *cookie) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t SpiComIF::requestReceiveMessage(CookieIF *cookie, size_t requestLen) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
SpiCookie* spiCookie = dynamic_cast<SpiCookie*>(cookie);
|
||||
if(spiCookie == nullptr) {
|
||||
return NULLPOINTER;
|
||||
}
|
||||
|
||||
bool fullDuplex = spiCookie->isFullDuplex();
|
||||
if(fullDuplex) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
std::string device = spiCookie->getSpiDevice();
|
||||
int fileDescriptor = 0;
|
||||
utility::UnixFileHelper fileHelper(device, &fileDescriptor, O_RDWR,
|
||||
"SpiComIF::requestReceiveMessage: ");
|
||||
if(fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
||||
return OPENING_FILE_FAILED;
|
||||
}
|
||||
|
||||
uint8_t* rxBuf = nullptr;
|
||||
size_t readSize = spiCookie->getCurrentTransferSize();
|
||||
result = getReadBuffer(spiCookie->getSpiAddress(), &rxBuf);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
gpioId_t gpioId = spiCookie->getChipSelectPin();
|
||||
MutexHelper(spiMutex, timeoutType, timeoutMs);
|
||||
if(gpioId != gpio::NO_GPIO) {
|
||||
gpioComIF->pullLow(gpioId);
|
||||
}
|
||||
|
||||
if(read(fileDescriptor, rxBuf, readSize) != static_cast<ssize_t>(readSize)) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "SpiComIF::sendMessage: Half-Duplex read operation failed!" << std::endl;
|
||||
#else
|
||||
sif::printWarning("SpiComIF::sendMessage: Half-Duplex read operation failed!\n");
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
result = HALF_DUPLEX_TRANSFER_FAILED;
|
||||
}
|
||||
|
||||
if(gpioId != gpio::NO_GPIO) {
|
||||
gpioComIF->pullHigh(gpioId);
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t SpiComIF::readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) {
|
||||
SpiCookie* spiCookie = dynamic_cast<SpiCookie*>(cookie);
|
||||
if(spiCookie == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
uint8_t* rxBuf = nullptr;
|
||||
ReturnValue_t result = getReadBuffer(spiCookie->getSpiAddress(), &rxBuf);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
*buffer = rxBuf;
|
||||
*size = spiCookie->getCurrentTransferSize();
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t SpiComIF::getReadBuffer(address_t spiAddress, uint8_t** buffer) {
|
||||
if(buffer == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
auto iter = spiDeviceMap.find(spiAddress);
|
||||
if(iter == spiDeviceMap.end()) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
*buffer = iter->second.replyBuffer.data();
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
60
linux/spi/SpiComIF.h
Normal file
60
linux/spi/SpiComIF.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
#ifndef LINUX_SPI_SPICOMIF_H_
|
||||
#define LINUX_SPI_SPICOMIF_H_
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <linux/gpio/GpioIF.h>
|
||||
#include <returnvalues/classIds.h>
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
/**
|
||||
* @brief Encapsulates access to linux SPI driver for FSFW objects
|
||||
* @details
|
||||
* Right now, only full-duplex SPI is supported.
|
||||
* @author R. Mueller
|
||||
*/
|
||||
class SpiComIF: public DeviceCommunicationIF, public SystemObject {
|
||||
public:
|
||||
static constexpr uint8_t spiRetvalId = CLASS_ID::LINUX_SPI_COM_IF;
|
||||
static constexpr ReturnValue_t OPENING_FILE_FAILED =
|
||||
HasReturnvaluesIF::makeReturnCode(spiRetvalId, 0);
|
||||
/* Full duplex (ioctl) transfer failure */
|
||||
static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED =
|
||||
HasReturnvaluesIF::makeReturnCode(spiRetvalId, 1);
|
||||
/* Half duplex (read/write) transfer failure */
|
||||
static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED =
|
||||
HasReturnvaluesIF::makeReturnCode(spiRetvalId, 2);
|
||||
|
||||
SpiComIF(object_id_t objectId, GpioIF* 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:
|
||||
|
||||
struct SpiInstance {
|
||||
std::vector<uint8_t> replyBuffer;
|
||||
};
|
||||
|
||||
GpioIF* gpioComIF = nullptr;
|
||||
|
||||
MutexIF* spiMutex = nullptr;
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
||||
uint32_t timeoutMs = 20;
|
||||
|
||||
using SpiDeviceMap = std::unordered_map<address_t, SpiInstance>;
|
||||
using SpiDeviceMapIter = SpiDeviceMap::iterator;
|
||||
|
||||
SpiDeviceMap spiDeviceMap;
|
||||
|
||||
ReturnValue_t getReadBuffer(address_t spiAddress, uint8_t** buffer);
|
||||
};
|
||||
|
||||
#endif /* LINUX_SPI_SPICOMIF_H_ */
|
99
linux/spi/SpiCookie.cpp
Normal file
99
linux/spi/SpiCookie.cpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
#include "SpiCookie.h"
|
||||
|
||||
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev,
|
||||
const size_t maxSize, spi::SpiMode spiMode, uint32_t spiSpeed): spiAddress(spiAddress),
|
||||
chipSelectPin(chipSelect), spiDevice(spiDev), maxSize(maxSize), spiMode(spiMode),
|
||||
spiSpeed(spiSpeed) {
|
||||
}
|
||||
|
||||
SpiCookie::SpiCookie(address_t spiAddress, std::string spiDev, const size_t maxSize,
|
||||
spi::SpiMode spiMode, uint32_t spiSpeed):
|
||||
SpiCookie(spiAddress, gpio::NO_GPIO, spiDev, maxSize, spiMode, spiSpeed) {
|
||||
}
|
||||
|
||||
void SpiCookie::getSpiParameters(spi::SpiMode& spiMode, uint32_t& spiSpeed,
|
||||
UncommonParameters* parameters) const {
|
||||
spiMode = this->spiMode;
|
||||
spiSpeed = this->spiSpeed;
|
||||
|
||||
if(parameters != nullptr) {
|
||||
parameters->threeWireSpi = uncommonParameters.threeWireSpi;
|
||||
parameters->lsbFirst = uncommonParameters.lsbFirst;
|
||||
parameters->noCs = uncommonParameters.noCs;
|
||||
parameters->bitsPerWord = uncommonParameters.bitsPerWord;
|
||||
parameters->csHigh = uncommonParameters.csHigh;
|
||||
}
|
||||
}
|
||||
|
||||
gpioId_t SpiCookie::getChipSelectPin() const {
|
||||
return chipSelectPin;
|
||||
}
|
||||
|
||||
size_t SpiCookie::getMaxBufferSize() const {
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
address_t SpiCookie::getSpiAddress() const {
|
||||
return spiAddress;
|
||||
}
|
||||
|
||||
std::string SpiCookie::getSpiDevice() const {
|
||||
return spiDevice;
|
||||
}
|
||||
|
||||
void SpiCookie::setThreeWireSpi(bool enable) {
|
||||
uncommonParameters.threeWireSpi = enable;
|
||||
}
|
||||
|
||||
void SpiCookie::setLsbFirst(bool enable) {
|
||||
uncommonParameters.lsbFirst = enable;
|
||||
}
|
||||
|
||||
void SpiCookie::setNoCs(bool enable) {
|
||||
uncommonParameters.noCs = enable;
|
||||
}
|
||||
|
||||
void SpiCookie::setBitsPerWord(uint8_t bitsPerWord) {
|
||||
uncommonParameters.bitsPerWord = bitsPerWord;
|
||||
}
|
||||
|
||||
void SpiCookie::setCsHigh(bool enable) {
|
||||
uncommonParameters.csHigh = enable;
|
||||
}
|
||||
|
||||
void SpiCookie::activateCsDeselect(bool deselectCs, uint16_t delayUsecs) {
|
||||
spiTransferStruct.cs_change = deselectCs;
|
||||
spiTransferStruct.delay_usecs = delayUsecs;
|
||||
}
|
||||
|
||||
void SpiCookie::assignReadBuffer(uint8_t* rx) {
|
||||
if(rx != nullptr) {
|
||||
spiTransferStruct.rx_buf = reinterpret_cast<__u64>(rx);
|
||||
}
|
||||
}
|
||||
|
||||
void SpiCookie::assignWriteBuffer(const uint8_t* tx) {
|
||||
if(tx != nullptr) {
|
||||
spiTransferStruct.tx_buf = reinterpret_cast<__u64>(tx);
|
||||
}
|
||||
}
|
||||
|
||||
spi_ioc_transfer* SpiCookie::getTransferStructHandle() {
|
||||
return &spiTransferStruct;
|
||||
}
|
||||
|
||||
void SpiCookie::setFullOrHalfDuplex(bool halfDuplex) {
|
||||
this->halfDuplex = halfDuplex;
|
||||
}
|
||||
|
||||
bool SpiCookie::isFullDuplex() const {
|
||||
return not this->halfDuplex;
|
||||
}
|
||||
|
||||
void SpiCookie::assignTransferSize(size_t transferSize) {
|
||||
spiTransferStruct.len = transferSize;
|
||||
}
|
||||
|
||||
size_t SpiCookie::getCurrentTransferSize() const {
|
||||
return spiTransferStruct.len;
|
||||
}
|
113
linux/spi/SpiCookie.h
Normal file
113
linux/spi/SpiCookie.h
Normal file
|
@ -0,0 +1,113 @@
|
|||
#ifndef LINUX_SPI_SPICOOKIE_H_
|
||||
#define LINUX_SPI_SPICOOKIE_H_
|
||||
|
||||
#include "spiDefinitions.h"
|
||||
#include <fsfw/devicehandlers/CookieIF.h>
|
||||
#include <linux/gpio/gpioDefinitions.h>
|
||||
#include <linux/spi/spidev.h>
|
||||
|
||||
class SpiCookie: public CookieIF {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Each SPI device will have a corresponding cookie. The cookie is used by the communication
|
||||
* interface and contains device specific information like the largest expected size to be
|
||||
* sent and received and the GPIO pin used to toggle the SPI slave select pin.
|
||||
* @param spiAddress
|
||||
* @param chipSelect Chip select. gpio::NO_GPIO can be used for hardware slave selects.
|
||||
* @param spiDev
|
||||
* @param maxSize
|
||||
*/
|
||||
SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev,
|
||||
const size_t maxReplySize, spi::SpiMode spiMode, uint32_t spiSpeed);
|
||||
|
||||
/**
|
||||
* Like constructor above, but without a dedicated GPIO CS. Can be used for hardware
|
||||
* slave select or if CS logic is performed with decoders.
|
||||
*/
|
||||
SpiCookie(address_t spiAddress, std::string spiDev, const size_t maxReplySize,
|
||||
spi::SpiMode spiMode, uint32_t spiSpeed);
|
||||
|
||||
address_t getSpiAddress() const;
|
||||
std::string getSpiDevice() const;
|
||||
gpioId_t getChipSelectPin() const;
|
||||
size_t getMaxBufferSize() const;
|
||||
/**
|
||||
* True if SPI transfers should be performed in full duplex mode
|
||||
* @return
|
||||
*/
|
||||
bool isFullDuplex() const;
|
||||
|
||||
/**
|
||||
* Set transfer type to full duplex or half duplex. Full duplex is the default setting,
|
||||
* ressembling common SPI hardware implementation with shift registers, where read and writes
|
||||
* happen simultaneosly.
|
||||
* @param fullDuplex
|
||||
*/
|
||||
void setFullOrHalfDuplex(bool halfDuplex);
|
||||
|
||||
/**
|
||||
* This needs to be called to specify where the SPI driver writes to or reads from.
|
||||
* @param readLocation
|
||||
* @param writeLocation
|
||||
*/
|
||||
void assignReadBuffer(uint8_t* rx);
|
||||
void assignWriteBuffer(const uint8_t* tx);
|
||||
/**
|
||||
* Assign size for the next transfer.
|
||||
* @param transferSize
|
||||
*/
|
||||
void assignTransferSize(size_t transferSize);
|
||||
size_t getCurrentTransferSize() const;
|
||||
|
||||
struct UncommonParameters {
|
||||
uint8_t bitsPerWord = 8;
|
||||
bool noCs = false;
|
||||
bool csHigh = false;
|
||||
bool threeWireSpi = false;
|
||||
/* MSB first is more common */
|
||||
bool lsbFirst = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Can be used to explicitely disable hardware chip select.
|
||||
* Some drivers like the Raspberry Pi Linux driver will not use hardware chip select by default
|
||||
* (see https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md)
|
||||
* @param enable
|
||||
*/
|
||||
void setNoCs(bool enable);
|
||||
void setThreeWireSpi(bool enable);
|
||||
void setLsbFirst(bool enable);
|
||||
void setCsHigh(bool enable);
|
||||
void setBitsPerWord(uint8_t bitsPerWord);
|
||||
|
||||
void getSpiParameters(spi::SpiMode& spiMode, uint32_t& spiSpeed,
|
||||
UncommonParameters* parameters = nullptr) const;
|
||||
|
||||
/**
|
||||
* See spidev.h cs_change and delay_usecs
|
||||
* @param deselectCs
|
||||
* @param delayUsecs
|
||||
*/
|
||||
void activateCsDeselect(bool deselectCs, uint16_t delayUsecs);
|
||||
|
||||
spi_ioc_transfer* getTransferStructHandle();
|
||||
private:
|
||||
size_t currentTransferSize = 0;
|
||||
|
||||
address_t spiAddress;
|
||||
gpioId_t chipSelectPin;
|
||||
std::string spiDevice;
|
||||
|
||||
const size_t maxSize;
|
||||
spi::SpiMode spiMode;
|
||||
uint32_t spiSpeed;
|
||||
bool halfDuplex = false;
|
||||
|
||||
struct spi_ioc_transfer spiTransferStruct;
|
||||
UncommonParameters uncommonParameters;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* LINUX_SPI_SPICOOKIE_H_ */
|
15
linux/spi/spiDefinitions.h
Normal file
15
linux/spi/spiDefinitions.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef LINUX_SPI_SPIDEFINITONS_H_
|
||||
#define LINUX_SPI_SPIDEFINITONS_H_
|
||||
|
||||
namespace spi {
|
||||
|
||||
enum SpiMode {
|
||||
MODE_0,
|
||||
MODE_1,
|
||||
MODE_2,
|
||||
MODE_3
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* LINUX_SPI_SPIDEFINITONS_H_ */
|
7
linux/utility/CMakeLists.txt
Normal file
7
linux/utility/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
target_sources(${TARGET_NAME} PUBLIC
|
||||
Utility.cpp
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
52
linux/utility/Utility.cpp
Normal file
52
linux/utility/Utility.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
#include "Utility.h"
|
||||
|
||||
void utility::handleIoctlError(const char* const customPrintout) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
if(customPrintout != nullptr) {
|
||||
sif::warning << customPrintout << std::endl;
|
||||
}
|
||||
sif::warning << "handleIoctlError: Error code " << errno << ", "<< strerror(errno) <<
|
||||
std::endl;
|
||||
#else
|
||||
if(customPrintout != nullptr) {
|
||||
sif::printWarning("%s\n", customPrintout);
|
||||
}
|
||||
sif::printWarning("handleIoctlError: Error code %d, %s\n", errno, strerror(errno));
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
|
||||
}
|
||||
|
||||
utility::UnixFileHelper::UnixFileHelper(std::string device, int* fileDescriptor, int flags,
|
||||
std::string diagnosticPrefix):
|
||||
fileDescriptor(fileDescriptor) {
|
||||
if(fileDescriptor == nullptr) {
|
||||
return;
|
||||
}
|
||||
*fileDescriptor = open(device.c_str(), flags);
|
||||
if (*fileDescriptor < 0) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << diagnosticPrefix <<"Opening device failed with error code " << errno <<
|
||||
"." << std::endl;
|
||||
sif::warning << "Error description: " << strerror(errno) << std::endl;
|
||||
#else
|
||||
sif::printError("%sOpening device failed with error code %d.\n", diagnosticPrefix);
|
||||
sif::printWarning("Error description: %s\n", strerror(errno));
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
openStatus = OPEN_FILE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
utility::UnixFileHelper::~UnixFileHelper() {
|
||||
if(fileDescriptor != nullptr) {
|
||||
close(*fileDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t utility::UnixFileHelper::getOpenResult() const {
|
||||
return openStatus;
|
||||
}
|
||||
|
36
linux/utility/Utility.h
Normal file
36
linux/utility/Utility.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef LINUX_UTILITY_UTILITY_H_
|
||||
#define LINUX_UTILITY_UTILITY_H_
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace utility {
|
||||
|
||||
void handleIoctlError(const char* const customPrintout);
|
||||
|
||||
class UnixFileHelper {
|
||||
public:
|
||||
static constexpr int READ_WRITE_FLAG = O_RDWR;
|
||||
static constexpr int READ_ONLY_FLAG = O_RDONLY;
|
||||
static constexpr int NON_BLOCKING_IO_FLAG = O_NONBLOCK;
|
||||
|
||||
static constexpr ReturnValue_t OPEN_FILE_FAILED = 1;
|
||||
|
||||
UnixFileHelper(std::string device, int* fileDescriptor, int flags,
|
||||
std::string diagnosticPrefix = "");
|
||||
|
||||
virtual~ UnixFileHelper();
|
||||
|
||||
ReturnValue_t getOpenResult() const;
|
||||
private:
|
||||
int* fileDescriptor = nullptr;
|
||||
ReturnValue_t openStatus = HasReturnvaluesIF::RETURN_OK;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* LINUX_UTILITY_UTILITY_H_ */
|
|
@ -11,6 +11,7 @@
|
|||
#include <fsfw/pus/CService200ModeCommanding.h>
|
||||
#include <fsfw/pus/Service17Test.h>
|
||||
#include <fsfw/pus/Service1TelecommandVerification.h>
|
||||
#include <fsfw/pus/Service20ParameterManagement.h>
|
||||
#include <fsfw/pus/Service3Housekeeping.h>
|
||||
#include <fsfw/pus/Service2DeviceAccess.h>
|
||||
#include <fsfw/pus/Service5EventReporting.h>
|
||||
|
@ -78,11 +79,13 @@ void ObjectFactory::produceGenericObjects() {
|
|||
apid::EIVE_OBSW, pus::PUS_SERVICE_9);
|
||||
new Service17Test(objects::PUS_SERVICE_17_TEST, apid::EIVE_OBSW,
|
||||
pus::PUS_SERVICE_17);
|
||||
new Service20ParameterManagement(objects::PUS_SERVICE_20_PARAMETERS, apid::EIVE_OBSW,
|
||||
pus::PUS_SERVICE_20);
|
||||
new CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT,
|
||||
apid::EIVE_OBSW, pus::PUS_SERVICE_200);
|
||||
|
||||
/* Test Device Handler */
|
||||
#if OBSW_ADD_TEST_CODE == 1
|
||||
new TestTask(objects::TEST_TASK);
|
||||
new TestTask(objects::TEST_TASK);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ target_sources(${TARGET_NAME} PUBLIC
|
|||
PDU1Handler.cpp
|
||||
PDU2Handler.cpp
|
||||
ACUHandler.cpp
|
||||
HeaterHandler.cpp
|
||||
SolarArrayDeploymentHandler.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
#include <mission/devices/SolarArrayDeploymentHandler.h>
|
||||
#include <fsfwconfig/devices/powerSwitcherList.h>
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
#include <devices/powerSwitcherList.h>
|
||||
#include <devices/gpioIds.h>
|
||||
|
||||
#include <mission/devices/SolarArrayDeploymentHandler.h>
|
||||
#include <linux/gpio/GpioCookie.h>
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
|
||||
|
||||
SolarArrayDeploymentHandler::SolarArrayDeploymentHandler(object_id_t setObjectId_,
|
||||
object_id_t gpioDriverId_, CookieIF * gpioCookie_, object_id_t mainLineSwitcherObjectId_,
|
||||
uint8_t mainLineSwitch_, gpioId_t deplSA1, gpioId_t deplSA2, uint32_t burnTimeMs) :
|
||||
SystemObject(setObjectId_), gpioDriverId(gpioDriverId_), gpioCookie(gpioCookie_), mainLineSwitcherObjectId(
|
||||
mainLineSwitcherObjectId_), mainLineSwitch(mainLineSwitch_), deplSA1(deplSA1), deplSA2(
|
||||
deplSA2), burnTimeMs(burnTimeMs), actionHelper(this, nullptr) {
|
||||
SystemObject(setObjectId_), gpioDriverId(gpioDriverId_), gpioCookie(gpioCookie_),
|
||||
mainLineSwitcherObjectId(mainLineSwitcherObjectId_), mainLineSwitch(mainLineSwitch_),
|
||||
deplSA1(deplSA1), deplSA2(deplSA2), burnTimeMs(burnTimeMs), actionHelper(this, nullptr) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize,
|
||||
MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||
}
|
||||
|
@ -38,7 +41,7 @@ ReturnValue_t SolarArrayDeploymentHandler::initialize() {
|
|||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
|
||||
result = gpioInterface->initialize(gpioCookie);
|
||||
result = gpioInterface->addGpios(dynamic_cast<GpioCookie*>(gpioCookie));
|
||||
if (result != RETURN_OK) {
|
||||
sif::error << "SolarArrayDeploymentHandler::initialize: Failed to initialize Gpio interface"
|
||||
<< std::endl;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef MISSION_DEVICES_SOLARARRAYDEPLOYMENT_H_
|
||||
#define MISSION_DEVICES_SOLARARRAYDEPLOYMENT_H_
|
||||
|
||||
#include <linux/gpio/GpioIF.h>
|
||||
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
|
@ -9,7 +11,7 @@
|
|||
#include <fsfw/devicehandlers/CookieIF.h>
|
||||
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
|
||||
#include <fsfw/timemanager/Countdown.h>
|
||||
#include <linux/gpio/GpioIF.h>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
/**
|
||||
|
@ -115,7 +117,7 @@ private:
|
|||
gpioId_t deplSA1;
|
||||
gpioId_t deplSA2;
|
||||
|
||||
GpioIF* gpioInterface;
|
||||
GpioIF* gpioInterface = nullptr;
|
||||
|
||||
/** Time duration switches are active to cut the burn wire */
|
||||
uint32_t burnTimeMs;
|
||||
|
|
22
mission/utility/InitMission.h
Normal file
22
mission/utility/InitMission.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef MISSION_UTILITY_INITMISSION_H_
|
||||
#define MISSION_UTILITY_INITMISSION_H_
|
||||
|
||||
#include <fsfw/objectmanager/SystemObjectIF.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
|
||||
namespace initmission {
|
||||
|
||||
void printAddObjectError(const char* name, object_id_t objectId) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "InitMission::printAddError: Adding object " << name << " with object ID 0x"
|
||||
<< std::hex << std::setfill('0') << std::setw(8) << objectId
|
||||
<< " failed!" << std::dec << std::endl;
|
||||
#else
|
||||
sif::printError("InitMission::printAddError: Adding object %s with object ID 0x%08x failed!\n" ,
|
||||
name, objectId);
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* MISSION_UTILITY_INITMISSION_H_ */
|
|
@ -8,14 +8,9 @@
|
|||
#include <array>
|
||||
#include <cstring>
|
||||
|
||||
bool TestTask::oneShotAction = true;
|
||||
MutexIF* TestTask::testLock = nullptr;
|
||||
|
||||
TestTask::TestTask(object_id_t objectId_):
|
||||
SystemObject(objectId_), testMode(testModes::A) {
|
||||
if(testLock == nullptr) {
|
||||
testLock = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
IPCStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
}
|
||||
|
||||
|
@ -24,19 +19,17 @@ TestTask::~TestTask() {
|
|||
|
||||
ReturnValue_t TestTask::performOperation(uint8_t operationCode) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
sif::info << "Hallo EIVE!" << std::endl;
|
||||
testLock ->lockMutex(MutexIF::TimeoutType::WAITING, 20);
|
||||
|
||||
if(oneShotAction) {
|
||||
// Add code here which should only be run once
|
||||
/* Add code here which should only be run once */
|
||||
performOneShotAction();
|
||||
oneShotAction = false;
|
||||
}
|
||||
testLock->unlockMutex();
|
||||
|
||||
// Add code here which should only be run once per performOperation
|
||||
/* Add code here which should only be run once per performOperation */
|
||||
performPeriodicAction();
|
||||
|
||||
// Add code here which should only be run on alternating cycles.
|
||||
/* Add code here which should only be run on alternating cycles. */
|
||||
if(testMode == testModes::A) {
|
||||
performActionA();
|
||||
testMode = testModes::B;
|
||||
|
@ -49,7 +42,7 @@ ReturnValue_t TestTask::performOperation(uint8_t operationCode) {
|
|||
}
|
||||
|
||||
ReturnValue_t TestTask::performOneShotAction() {
|
||||
// Everything here will only be performed once.
|
||||
/* Everything here will only be performed once. */
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
@ -61,12 +54,12 @@ ReturnValue_t TestTask::performPeriodicAction() {
|
|||
|
||||
ReturnValue_t TestTask::performActionA() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
// Add periodically executed code here
|
||||
/* Add periodically executed code here */
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t TestTask::performActionB() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
// Add periodically executed code here
|
||||
/* Add periodically executed code here */
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -48,8 +48,7 @@ protected:
|
|||
private:
|
||||
// Actually, to be really thread-safe, a mutex should be used as well
|
||||
// Let's keep it simple for now.
|
||||
static bool oneShotAction;
|
||||
static MutexIF* testLock;
|
||||
bool oneShotAction = true;
|
||||
StorageManagerIF* IPCStore;
|
||||
};
|
||||
|
||||
|
|
2
tmtc
2
tmtc
|
@ -1 +1 @@
|
|||
Subproject commit 1d5fe4ebc7165c2a4979c5f9be9cfa0324e366fb
|
||||
Subproject commit 2b85ece07195ee905c35b35494bc7a86b94335f5
|
Loading…
Reference in New Issue
Block a user