eRPC on stm32f7 #699
Replies: 28 comments
-
Yes, likely! I'm looking to replace our rather underdocumented and unmaintained XPCC protocol with something more standardized. eRPC looks very useful for that purpose, especially with a modm transport layer port! |
Beta Was this translation helpful? Give feedback.
-
Well I can't really say that erpc is superior, but it's lightweight enough and there are a lot of people doing stuff with it currently.
The problem is, that as far as I can see, ERPC expects drivers for the transport layers to be included in the transport as well. I rather hate the idea of writing transport layers for:
My next step would be to implement a generic UserChannelTransport, which utilizes callbacks from the user code to allow whatever driver behavior or action with the incoming or outgoing data. Because we are planning to use ERPC and modm heavily in the future, I'll do some further development and will post possible use-cases/results here :) |
Beta Was this translation helpful? Give feedback.
-
Yeah, modm is a little too low level in that regard, we have very different interfaces for each peripheral and even separate types per instance. I typically create a higher-level virtual interface that is then implemented via template class wrapper, but it's not the best solution. See |
Beta Was this translation helpful? Give feedback.
-
well my idea was to just do something like this: class erpc::UserChannel{
// erpc transport api
isConnected(){}
readCallback(uint8_t* data, uint32_t size){
// implement whatever protocol you want
// and do whatever to read some data and fill the data* object
// could be CAN, UART, etc
}
write()
// implement whatever protocol you want
// and do whatever to write some data
// could be CAN, UART, etc
};
int main()
{
erpc::UserChannel A();
// init erpc and stuff ...
transport = erpc::UserChannelTransport_init(&A)
// do stuff to further initialize erpc things
} so it is probably similar enough to your suggestion (correct me if im wrong). Would you rather implement every protocol as a device wrapper and push that into erpc then? What is |
Beta Was this translation helpful? Give feedback.
-
Yes, of course. I just wanted to give you context how we solved it in the past.
Ideally the eRPC repo would not be modified and instead you would store a modified copy in modm and copy that instead via lbuild. But I'm not sure exactly how much changes are required, perhaps a real fork of eRPC is required instead of a few patches.
The base class contains state continuations for running 2 coroutine functions in parallel without nesting. See https://modm.io/reference/module/modm-processing-resumable The alternative is |
Beta Was this translation helpful? Give feedback.
-
That depends on what we would want to do. There are no changes necessary except for the "modm transport layer" but even that could be added to the original erpc via lbuild (and these changes are either part of modm or come from wherever). I'm gonna play around and see where this leads me :) |
Beta Was this translation helpful? Give feedback.
-
@salkinium is there a working example of https://modm.io/reference/module/modm-processing-protothread/ ? And the UART example you gave does not contain a means to instantiate and "use" that thing either (at least i could not find one). So I have no idea what do do with it :) |
Beta Was this translation helpful? Give feedback.
-
https://github.com/modm-io/modm/blob/develop/examples/stm32f4_discovery/protothreads/ |
Beta Was this translation helpful? Give feedback.
-
@rleh PT_WAIT_UNTIL(timeout.isExpired()); blocks indefinitely |
Beta Was this translation helpful? Give feedback.
-
Are you running the unmodified example on a STM32F4 Discovery board? |
Beta Was this translation helpful? Give feedback.
-
I just tested the code on an STM32F407 Discovery Board: Works perfectly! |
Beta Was this translation helpful? Give feedback.
-
My LED example still blocks Edited: fixed errors #pragma once
#include <modm/board.hpp>
#include <modm/processing/protothread.hpp>
using Led1 = Board::LedGreen;
using Led2 = Board::LedBlue;
class BlinkingLight : public modm::pt::Protothread
{
public:
bool
run()
{
PT_BEGIN();
Led1::setOutput();
Led2::setOutput();
while (true){
timeout.restart(100ms);
Led1::toggle();
Led2::toggle();
PT_WAIT_UNTIL(timeout.isExpired());
MODM_LOG_ERROR<< "NEVER REACH" << modm::endl;
}
PT_END();
}
private:
modm::ShortTimeout timeout;
};
BlinkingLight light;
int main()
{
Board::initialize();
Board::LedRed::setOutput();
while(true){
light.run();
Board::LedRed::toggle();
modm::delay(200ms);
}
return 0;
}
|
Beta Was this translation helpful? Give feedback.
-
Please provide more information for others to be able to reproduce the error, at least the target (dev board or MCU) your build setup and the I can't reproduce you example, even after adding the necessary includes
because some code is missing:
|
Beta Was this translation helpful? Give feedback.
-
I created an example and tested it successfully on a Nucleo-F767ZI: 9554d61 |
Beta Was this translation helpful? Give feedback.
-
After removing the |
Beta Was this translation helpful? Give feedback.
-
I found the problem: |
Beta Was this translation helpful? Give feedback.
-
I cant really find anything, any ideas on what could disrupt modm timers? |
Beta Was this translation helpful? Give feedback.
-
Probably related to the SysTick timer (hardware) and modm|s system clock. Have you checked if the system clock still works? |
Beta Was this translation helpful? Give feedback.
-
from https://docs.modm.io/develop/api/stm32l486zgt7/group__modm__architecture__clock.html while(true)
{
const auto start = modm::PreciseClock::now();
modm::delay(100ms);
const auto duration = modm::PreciseClock::now() - start;
MODM_LOG_DEBUG << "Function took " << duration << modm::endl;
} output:
|
Beta Was this translation helpful? Give feedback.
-
compared to
when i do not add <modules>
<module>modm:erpc</module>
</modules> |
Beta Was this translation helpful? Give feedback.
-
Does eRPC touch any SysTick registers? Perhaps it defines the |
Beta Was this translation helpful? Give feedback.
-
It doesn't look like: https://github.com/kikass13/erpc/search?q=SysTick But maybe FreeRTOS (dependency of the erpc module) causes the trouble...? |
Beta Was this translation helpful? Give feedback.
-
I can confirm: Adding the module |
Beta Was this translation helpful? Give feedback.
-
yes, i had freertos as a module dependency in my erpc module.lb which probably caused these problems (in the sense that i included freertos accidentally as well) |
Beta Was this translation helpful? Give feedback.
-
after removing the (useless) freertos dependency (i used freeRtos in my erpc example before and that worked with server + client) in from protothread example, the erpc server + led pthreads can run succesfully |
Beta Was this translation helpful? Give feedback.
-
@salkinium @rleh is the use of protothreads even possible without writing intrusive code into erpc ? aka: is it possible to have a protothread and do a (wait for/yielding) loop somwhere internally without stealing the program control?
obviously that does not work, what happens is:
|
Beta Was this translation helpful? Give feedback.
-
No. Resumable Functions and the C++20 coroutines are language solutions and therefore require all caller function signature to "upgrade" to the async syntax. You've stumbled across the main problem with this approach: Calling a async function from inside a sync function. The only solution is to convert your code to explicit polling, ie. periodically polling a sync function like We want to introduce stackful fibers into modm as an alternative, see #439. I need to find the time to finish it though… |
Beta Was this translation helpful? Give feedback.
-
UpdateThe stm32F7 example i am using (using freerots tasks) can be seen here (it was set to public by my orga): The modm fork containing the erpc module is here:
Other StuffThere is also a proper FreeRtos Thread wrapper class construct in the example (if someone is interested) :)
#include <modm/processing/rtos.hpp>
class TaskBase {
public:
TaskHandle_t handle_;
~TaskBase() {
vTaskDelete(handle_);
return;
}
};
class Task : public TaskBase {
public:
Task(char const*name, unsigned portBASE_TYPE priority, unsigned portSHORT stackDepth=configMINIMAL_STACK_SIZE) {
xTaskCreate(&taskfun, (const char*)name, stackDepth, this, priority, &handle_);
}
virtual void task() = 0;
static void taskfun(void* param) {
static_cast<Task *>(param)->task();
vTaskDelete(static_cast<Task *>(param)->handle_);
}
};
class ModmTask : public Task {
public:
ModmTask(char const*name, unsigned portBASE_TYPE priority, unsigned portSHORT stackDepth=configMINIMAL_STACK_SIZE)
: Task(name, priority, stackDepth){
MODM_LOG_INFO << "[System *] Task '" << name << "' created" << modm::endl;
updateStatus();
}
~ModmTask(){
MODM_LOG_INFO << "[System #] Task '" << status_.pcTaskName << "' removed" << modm::endl;
}
static void taskfun(void* param) {
static_cast<Task *>(param)->task();
vTaskDelete(static_cast<Task *>(param)->handle_);
}
public:
void sleep(TickType_t ticks){
vTaskDelay(ticks);
}
void updateStatus()
{
/* Use the handle to obtain further information about the task. */
vTaskGetInfo(
/* The handle of the task being queried. */
this->handle_,
/* The TaskStatus_t structure to complete with information on xTask. */
&this->status_,
/* Include the stack high water mark value in the
TaskStatus_t structure. */
pdTRUE,
/* Include the task state in the TaskStatus_t structure. */
eInvalid
);
}
public:
TaskStatus_t status_;
private:
}; and heres an example Task (blink led) using it #include <modm/board.hpp>
#include <utils/Task.hpp>
template <class Gpio, int SleepTime>
class LedTask : public ModmTask{
public:
LedTask() : ModmTask("LedTask", 6)
{}
void task()
{
Gpio::setOutput();
while (true)
{
sleep(SleepTime * MILLISECONDS);
Gpio::toggle();
{
static modm::rtos::Mutex lm;
modm::rtos::MutexGuard m(lm);
}
}
}
}; |
Beta Was this translation helpful? Give feedback.
-
Hi,
i wanted to let you know that eRPC is working with modm. I have changed erpc slightly and created an example which utilizes local FIFOs (could be any other protocol) and freertos to do RPC's.
My plan for the future is to implement a transport layer for CAN, UART and Ethernet, all of them utilizing the driver stuff modm already provides.
First question:
Is this of some use to anyone?
Beta Was this translation helpful? Give feedback.
All reactions