- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I use NEEK CycloneIII (CP3C25). App is quite simple it turns on the led corresponding the push button pressed (see code below). I copied irq handler procedure from standard binary_counter.c example and it doesn't work unless I put some delay at the end of handler. When I comment delay in the handler and debug my app it works fine, but when I run app in hardware it doesn't work. Any ideas why the app doesn't run propelry?
# include <stdio.h># include "system.h"# include "alt_types.h"# include "sys/alt_irq.h"# include "altera_avalon_pio_regs.h"
//#include <unistd.h>
/* A variable to hold the value of the button pio edge capture register. */
volatile int edge_capture;
/* button IRQ function */
static void handle_button_interrupts(void* context, alt_u32 id)
{
/* Cast context to edge_capture's type. It is important that this be
* declared volatile to avoid unwanted compiler optimization.
*/
int delay;
volatile int* edge_capture_ptr = (volatile int*) context;
/* Store the value in the Button's edge capture register in *context. */
*edge_capture_ptr = IORD_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE);
/* Reset the Button's edge capture register. */
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE, 0);
//now optional delay is commented
/*delay=0x0;
while (delay<100000)
{
delay++;
}
*/
}
/* Initialize the button_pio. */
static void init_button_pio()
{
/* Recast the edge_capture pointer to match the alt_irq_register() function
* prototype. */
void* edge_capture_ptr = (void*) &edge_capture;
/* Enable all 4 button interrupts. */
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTON_PIO_BASE, 0xf);
/* Reset the edge capture register. */
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE, 0x0);
/* Register the interrupt handler. */
alt_irq_register( BUTTON_PIO_IRQ, edge_capture_ptr,
handle_button_interrupts );
}
static void handle_button_press(alt_u8 type)
{
/* Button press actions while counting. */
if (type == 'r')
{
IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, ~edge_capture);
}
}
int main()
{
IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 0xf);
while (1)
{
if(edge_capture!=0)
{
handle_button_press('r');
}
}
return 0;
}
Link Copied
8 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Some remarks:
I can't see the init_button_pio() call in main. Anyway I think you have it, otherwise the code won't work in neither case, delay or not. Try to directly assign edge_capture in interrupts handler, instead of using the context pointer. Did you enable edge capture register for your PIO in SOPC builder? If not, probably the interrupt would continuously retrigger when button is pressed and this could explain the behaviour you are observing.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Just a question, why do you not call the function init_button_pio in your main ? Because, like this, I would say it should do nothing since you do not initialize the interrupt. Jérôme- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Also, the main program seems to copy the 'edge capture' value to the leds whenever the value is non-zero. This may not be what you had in mind!
Once set, nothing probably zeros it either. Outputting a counter to the leds might be more informative.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I haven't looked at your code closely but this sounds an awful lot like a simple button bounce issue. A common way to account for button bounce is to simply add a delay after first detecting the button press.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Thanks to everybody for advises. I tried to put IOWR_ALTERA_AVALON_PIO_DATA(...) in the handler, but it didn't help either. One thing I noticed that in a debug mode when i press button once there is a number of interrups occur. Can it be because of the button bounce?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This code works fine even with such delay in the handler. Without this delay I noticed only quick flash on the corresponding led.
Unfortunately, I still don't understand the core of the problem:(
/*
* "Hello World" example.
*
* This example prints 'Hello from Nios II' to the STDOUT stream. It runs on
* the Nios II 'standard', 'full_featured', 'fast', and 'low_cost' example
* designs. It runs with or without the MicroC/OS-II RTOS and requires a STDOUT
* device in your system's hardware.
* The memory footprint of this hosted application is ~69 kbytes by default
* using the standard reference design.
*
* For a reduced footprint version of this template, and an explanation of how
* to reduce the memory footprint for a given application, see the
* "small_hello_world" template.
*
*/
# include <stdio.h># include "system.h"# include "alt_types.h"# include "sys/alt_irq.h"# include "altera_avalon_pio_regs.h"
//#include <unistd.h>
/* A variable to hold the value of the button pio edge capture register. */
volatile int edge_capture;
/* button IRQ function */
static void handle_button_interrupts(void* context, alt_u32 id)
{
int delay;
IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, ~IORD_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE));
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE, 0);
delay=0x1;
while (delay<1)
{
delay++;
}
}
/* Initialize the button_pio. */
static void init_button_pio()
{
/* Recast the edge_capture pointer to match the alt_irq_register() function
* prototype. */
void* edge_capture_ptr = (void*) &edge_capture;
/* Enable all 4 button interrupts. */
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTON_PIO_BASE, 0xf);
/* Reset the edge capture register. */
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE, 0x0);
/* Register the interrupt handler. */
alt_irq_register( BUTTON_PIO_IRQ, edge_capture_ptr,
handle_button_interrupts );
}
int main()
{
printf("Hello from Nios II!\n");
init_button_pio();
IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 0xf);
while (1);
return 0;
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Try just displaying a binary count on the LEDs, this should increment once per button push. The usleep call should take care of debounce.
# include "unistd.h" //provides usleep function unsigned int gCount //global counter static void handle_button_interrupts(void* context, alt_u32 id) { gCount++; IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, (gCount & 0x0F)); usleep(1000); //wait for 1 ms before clearing the button IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE, 0); } in init_button_pio() add the line "gCount = 0;" This should show a binary count on the LEDs that increments each time the interrupt occurs.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Tried to display increment. That's what i got.
1. If I put usleep before IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE, 0); it is incremented twice per button push. 2. If I put usleep after clearing function it is incremented once per button push. So i conclude the delay after clearing edge_capture reg is necessary.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page