From Scratch Timer Interrupt Handler for a Cerb40

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.

Anyone with experience, please chime in.

Ahhā€¦ no help from the peanut gallery eh? Nice.

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.

Suggestions from the gallery at this point?

No progress today.

Has anyone ever gotten external code to run on the Cerb40?

Maybe it just doesnā€™t work?

1 Like

Still Johnny No-Help, eh? Thanks so much.

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.

Moving on to toggling a pinā€¦

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.

Personally, I think people are just scared of his avatar :wink:

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!

Thanks for the vote of confidence.

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 << 2
4); // Set bit 8 of MODER4 to 01=output.
GPIOC->OSPEEDR &= ~(3UL << 24); // clear speed bits. 00=2MHz
GPIOC->PUPDR &= ~(3UL << 2
4); // 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;

if(toggle==0)
{
GPIOC->BSRRH = 0xFF; // low
toggle=1;
}
else
{
GPIOC->BSRRL = 0xFF; // high
toggle=0;
}
temp=100;
}

Hopefully one of you know whats wrong with this simple INT approach? Otherwise I will move on to the more complex configuring of TIM2 and the NVIC.

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.

Thanks for the good info, Taylor.

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.

Too bad, really.

Bye.

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.

2 Likes

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?

The Agile hardware manifesto - sounds cool.

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.

1 Like

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 Thanks for your elaborate explanations.

I think I did try to have him modularize and explain his project.

@ 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.