There is no TIMER api for setting up the hardware interrupt timers for the Cerb40. I need one, but have no experience writing any native code for this STM32F405 device. (hence the whole use the .netmf concept as far as it goes).
I will need some assistance at the RLPlite code level in dealing with this device.
I installed the Keil uVision software, and followed the RLP demo as far as you can go. The demo does not cover any hardware register access, or interrupts, or even compiling.
So to get started, we have the following .uvproj
timerIRQ.c
// two variables I need to see in .NETMF
bool busy; // prevent read during multi clock data writes (if any)
int dataFromNetMF; // data acquired from the slow .NETMF program, used here at high speed.
void interrupt
timer0_isr(void) // Interrupt Service Routine
{
if(Timer flag is set)
{
set busy flag
..perform code operations based on dataFromNetMF,
and change output pins
unset busy flag
clear interrupt flag
}
}
void InitTimer0(void)
{
set global interrupt enable;
configure timer register and prescaler
enable timer interrupt;
configure output pins;
}
Pretty straightforward stuff. To proceed, I suspect we need an include file that maps the registers to their names for compilation. Beyond that, there may be some syntax for declaring the method name of the IRQ handler.
Well here is the effort so far:
Created a new project, selecting the STM32F40x device from the list. The example asks for some Atmel part, which this isnāt. It does not say āpick your deviceā, but let us make a guess that this is what they mean. Selected ādonāt copy init filesā, god knows what they do.
Then the example says to enter a pair of long hex numbers into the Linker tab, but it says the Cerberus are different. If you go to the link, it gives two other numbers, which I entered like this: (first image).
Then you add a RUN line to the User tab like this:(image 2).
Then I added some code:
int Add(int x) { return x++;} // no sense getting fancy at this stageā¦
Then it says go ahead and build. Results:
Build target 'Target 1ā
compiling timer.cā¦
linkingā¦
timer.axf: Error: L6320W: Ignoring --entry command. Cannot find argument āReset_Handlerā.
timer.axf: Warning: L6320W: Ignoring --first command. Cannot find argument ā__Vectorsā.
Target not created
So is that good or bad? Who knows. Target not created sounds bad. I donāt see any .bin file.
I got some help from the Keil people. Now the basic blank STMF4xx program builds.
You have to edit their default files, and remove references to methods that donāt exist You also need to find your device header file buried in the Keil installationā¦ But after that it at least builds.
In the .map file, I found my Add() method address, and added it to the VS project like this:
byte[] binfile = Resources.GetBytes(Resources.BinaryResources.timer);
AddressSpace.Write(0x2001A000, binfile, 0, binfile.Length);
RLPLite.Procedure RLP_Add = new RLPLite.Procedure(0x2001a27b);
If you try to call the Add method, you get a lot of nothing though. It seems that RLPlite forces you to use a single group of arguments. As such.
int AddOne(void* par0, int * par1, unsigned char * par2)
{
unsigned int x = par1[0];
unsigned int y = x+1;
return y;
}
And once I did that, I got a valid return, and 1+1=2.
Hey, congratulations on your first success. Iāve been working with the Cerb40 almost exclusively since it came out. Thatās not to say that I know a lot about it, just what little I know is mostly about it. Generally, the forum is pretty responsive, so donāt be discouraged. Sometimes the expert you need to see your post is on vacation, deep in a project, whatever. Sometimes, youāll get overwhelming support from the community. It can be hit and miss, but not any more so than ātypicalā tech support in my estimation. Sometimes you get a helpful tech, sometimes you get one you canāt work with, so the Open concept isnāt really any worse.
Wish I could help you, but Iāve yet to delve into RLPLite. I does require you to pass in a buffer and manually decode your parameters from it. I think that is a consequence of (mainly?) using RLP/Lite for handling buffered input so as to avoid buffer overruns with the faster code. Can I ask what you are working on, just out of curiosity? Whatās your background? Assembly and C are far in my past, just because .NET is what I get paid for now. These little .NETMF devices are great, arenāt they? What is it that .NET canāt do for you?
Cheer up buddy, you are sitting with a non-trivial challenge there, and you are showing clear signs of being serious about solving it - and thatās a good start.
In that case I might recommend you trying to split your question into smaller parts, so it would be easier for us (the community) to assist.
The GHI experts are in cases taking a week to answer, but they are standing by.
Also keep in mind that the more of an expert you become, the fewer number of peers or more-experienced people there are in the community and at GHI that can necessarily answer your questions immediately. Case in point: Iām an employee, but youāre already more of an expert than I am in many areas. But like any member of the community, I watch and will try to refer experts to a cause where I know there is a subject matter match-up.
I liked the post from Gus! And agree, there is a lot of reading to do to get you into a solution for this, which might actually be more scary than your avatar!
I was able to configure and toggle a pin. In this case Port C pin PC4.
I looked at Keilās āBlinkyā program, and also the ST Technical Ref Manual for the STMF4xx Doc ID 018909 Rev 3. If ST can blink an LED using SysTick, why canāt I steal it for my interrupt? Why? Because it doesnāt seem to work. Thatās why.
int InitTimer(void* par0, int * par1, unsigned char * par2)
{
SysTick_Config(SystemCoreClock/100); /* Generate Blinky 10ms interrupt */
// GPIO Port Mode Register MODER. 00=input,01=Output 10=Alt function, 11=Analog.
GPIOC->MODER &= ~(3UL << 24); // Clear bits 8&9 of MODER4
GPIOC->MODER |= (1UL << 24); // Set bit 8 of MODER4 to 01=output.
GPIOC->OSPEEDR &= ~(3UL << 24); // clear speed bits. 00=2MHz
GPIOC->PUPDR &= ~(3UL << 24); // clear pull up pull down
GPIOC->PUPDR |= (2UL << 2*4); // set as pull down
GPIOC->BSRRH = 0xFF;// Clear Port C
GPIOC->BSRRL = 0xFF; // Set Port C
return 1;
}
That clears, then sets the port. The Blinky IRQ handler does not toggle the port. Also, I tried to set a global variable in here and get it back in the Add() method, but it returns garbage. So I cannot prove the handler fires. And global variable is returning garbage. Not good.
static int temp=0;
void SysTick_Handler (void) {
static unsigned int toggle=0;
RLPLite does not initialize your global static variables
static int temp=0;
Does not initialize temp to 0, that is why you are getting garbage. I believe the RLPLite documentation mentions this, but I might be wrong I have not read these docs in while.
Your āSysTick_Handlerā will not get called because it is not being linked to the STM32 startup code which defines the weak references for the interrupt handlers. Those weak references where resolved when the firmware was linked. It is a good thing anyway, because, as much as I know you disagreed the last time I mentioned this, wiring interrupts from RLPLite is going to put the NETMF VM into a spin trust meā¦
You will need to look into the firmware to understand what your chances of success are here, if the STM32 is anything like the AT91 firmware the interrupt dispatching is entirely handled by the firmware and any attempt to mess with the handlers is a guaranteed crash. Also keep in mind that the STM32 does not have an interrupt vector per timer, one vector handles a range of timers. At the very least you would need to chain your handler, ie. wire it into the NVIC and then make sure you also call the original handler to make sure that what ever was expected to be done still gets done.
Well that tears it. Crash guaranteed? Iām outta here.
If this OS canāt support even one timer, not one, then I quite literally cannot use it.
Of the 98 projects that I completed in the last 12 months, 96 of them needed an interrupt timer. (I happened to be counting them this week) 10kHz is not exactly fast either.
How bitterly disappointing to lose C#.
My quick test showed a 36kHz loop time in a blank Cerb40 project. You can spare the time and you know it. And for anyone suggesting a PIC on piggyback, youāre fired.
NETMF is not real time, it is just not made for that. Code share and showcase have hundreds of examples of what NETMF can do. This should give you an idea.
But I bet if you had the event driven coding techniques that NETMF offers at your disposal for those projects, then that ratio would have looked significantly different. I come from a PIC and AVR programming background and so far I continue to be blown away how quick and easy it is to do the same kind of things on Gadgeteer. And as far as Iām concerned, adding a small piggyback micro in those rare cases where you need need the speed or fast interrupts is a small sacrifice. Just see it as another Gadgeteer sensor board.
I guess the scary avatar left the building, but I still think he didnt get the point.
I must assume he was working commercially, with about 2-3 days per project. I must also assume they have a huge existing code-base and re-usable stuff built for PIC/AVR where he is working - probably being accumulated over many years (PIC is from 1975).
I dont think Gadgeteer would ever fit his needs.
Seeed didnt get the point either, this a new world of complex software, and we are not locked to any board or specific hardware, we are just locked to our code, and the framework.
How do we change the way people think about this?
Most of you guys probably now Agile software methodologies, which started with a manifesto written by some pretty insightful fellows. http://agilemanifesto.org/
I am wondering if we should team up, and do something like that?
NETMF is just like any other platform or framework. You exchange performance and configurability for ease of use and rapid development. You have to assess possible platforms based on their strengths and weaknesses.
NETMF is really good at writing user interface heavy applications, which need button debouncing, asynchronous programming, and multitasking. I think beginners and hobbyists really struggle writing bare metal C code to do that. I canāt tell you how many times I see posts on forums saying things like āI want an LED to fade between colors and if I press a button for more than two seconds it should turn off.ā That sort of project is nearly impossible for a beginner to do on an Arduino, but they could write it in five minutes in NETMF.
NETMF is really bad at pretending to be an 8-bit microcontroller. Itās really hard to make things happen quickly, or at accurate, regularly scheduled times. Itās no match for an Arduino in that respect. Itās hard for seasoned developers to understand that this platform is fast enough to draw beautiful UIs on full-color TFT displays, yet canāt even manage to wiggle a pin at a few hundred kHz.
Also, one more thing ā looking at the original post again, I realized Iām not entirely sure what the OP was trying to do (or if he even needed a timer?)
Looking at the OPās pseudo-code, it looks like he just wants to be able to speed up his program by running some calculations in native code. This could easily be accomplished using Interops (ugh, or if you prefer, GHIās RLP library). I donāt think he realized you can call C code from NETMF, so he thought heād have to set up a timer to periodically grab data from NETMF and do stuff with it.
I was out of commission last week so I didnāt even notice this post ā I kind of wish I would have; we probably could have helped him if someone would have asked him to explain his project.
For macroscopic timing behavior (tens of milliseconds+), timers can be managed in NETMF, which can then call interop code. For tight timing (nanoseconds or microseconds), you can call nops or HAL_Sleep_Microseconds() in your C code.
@ jay - The OP does seem to be aware that he can use RLPLite to run native code. See post #3 in this thread where the OP managed to execute a native Add function and then indicates the desire to progress with pin toggling.