ADI BF533 programmable flag interrupt - embedded

When I press PF8 button, I want the blackfin goes into a ISR and the counter increases 1.
I should clear or set a bit which indicates the processor has entered the ISR, but I don't know how to clear it.
My processor is BF533.
Here is my code:
// prototype
EX_INTERRUPT_HANDLER(FlagA_ISR);
volatile int count = 0;
void main(void)
{
// Register FlagA ISR to interrupt vector group 12
register_handler(ik_ivg12, FlagA_ISR);
// set direction of programmable flag PF8 to input
*pFIO_DIR &= ~PF8;
ssync();
// interrupt enable PF8
*pFIO_INEN |= PF8;
ssync();
// give interrupt when FIO_FLAG_D PF8 changes
*pFIO_MASKA_D |= PF8;
ssync();
// Bind FlagA interrupt to IVG12
*pSIC_IAR2 |= 0x00005000; // flag A IVG12
ssync();
// Enable PFA in system interrupt mask register
*pSIC_IMASK = 0x00080000;
ssync();
// enable IVG12 in core interrupt mask register
*pIMASK |= 0x00001000;
ssync();
// wait for interrupt
while(count < 5);
printf("5 interrupts received");
}
EX_INTERRUPT_HANDLER(FlagA_ISR)
{
count++;
// Needed to clear or set a bit to indicate that the processor has entered the ISR
}

I have just figured out how to solve this question.
The PFx are connected to the FIO_FLAG. We can clear our interrupt status by clearing FIO_FLAG.
Here is the code:
*pFIO_FLAG_D &= ~PF8;
ssync();
//or, you can try:
*pFIO_FLAG_C |= PF8;
ssync();

Related

SYS_TICK handler function is not getting called after enabling flags in SysTick Control and Status Register

I'm using STM32F407G-DISC1 board, SYS_TICK handler is not getting called after enabling flags in SysTick Control and Status Register which is at 0xE000E010 memory mapped location. SysTick Reload Value Register value is set to 15999.
void init_systick_timer(uint32_t tick_hz)
{
uint32_t *pSRVR = (uint32_t*)0xE000E014;
uint32_t *pSCSR = (uint32_t*)0xE000E010;
/* calculation of reload value */
uint32_t count_value = (SYSTICK_TIM_CLK/tick_hz)-1;
//Clear the value of SVR
*pSRVR &= ~(0x00FFFFFFFF);
//load the value in to SVR
*pSRVR |= count_value;
//do some settings
*pSCSR |= ( 1 << 1); //Enables SysTick exception request:
*pSCSR |= ( 1 << 2); //Indicates the clock source, processor clock source
//enable the systick
*pSCSR |= ( 1 << 0); //enables the counter
}
void SysTick_Handler(void)
{
}
I would rather recomment to do not reinvent the wheel and use standard STM provided CMSIS headers.
Your way of defining the registers is incorrect. It will not work correctly if decide to read theis values back. Compiler will simple optimize the reads from the memory out. They have to be volatile.
But abstracting from that you need to enable the interrupt in the NVIC controller. Without that the systick timer will only set the pending flag without invoking the handler.

Interrupt handler won't run

I'm working on an stm32l467 and trying to run an ISR when i push the user-push-button. Everything looks to be setup correctly. I have looked at the registers in the debugger (Keil uV) and everything looks good, but when i push the button I end up in the default handler and can't understand why the handler is not running.
Running in the debugger i can see that when i push the button, i get an interrupt-pending (EXTI->PR1) flag, but the code then jumps to the the default handler. I can't see what i'm missing. I know there are easier ways to setup interrupts using the HAL layer, i'm just trying to understand what registers must be accessed from a low-level.
Can anyone suggest a missing step to this?
#include <stm32l4xx.h>
#define DELAY 1
void delay1Hz(void);
bool buttonInterrupt = false;
int main(void)
{
__disable_irq();
/* Configure the clocks */
RCC->CR &= 0xFFFFFF07; //Clear ~MSIRANGE bits and MSIRGSEL bit
RCC->CR |= 0x00000088; //Set MSI to 16MHz and MSIRGSEL bit
RCC->AHB2ENR |= 0x00000001; //Enable PA5 clocks
/* Enable PA0 for output */
GPIOA->MODER &= 0xFFFFF3FF; //Clear GPIOA[5] MODER bits
GPIOA->MODER |= 0x00000400; //Enable GPIOA[5] for output
RCC->AHB2ENR |= 0x4; //ENABLE GPIOC port clk
GPIOC->MODER &= 0xF3FFFFFF; //Clear GPIOC[13] for input mode
RCC->APB2ENR |= 1; //Enable SYSCFG clk
SYSCFG->EXTICR[3] &= ~0x00F0; //CLEAR_BIT the EXTI[13] bits
SYSCFG->EXTICR[3] |= 0x20; //Enable GPIOC for EXTI[13]
EXTI->IMR1 |= 0x2000; //Unmask EXTI13
EXTI->FTSR1 |= 0x2000; //Enable falling edge trigger on pb
NVIC_EnableIRQ(EXTI15_10_IRQn); //Enable EXTI15-to-10 interrupts
__enable_irq();
for (;;)
{
if(buttonInterrupt == true) {
//flash LED's (doesn't get here)
}
}
}
void initTim2() {
//timer 2 code - not causing a problem
}
void delay1Hz() {
//delay code - not interrupt controlled
}
/* This doesn't run */
void EXTI15_10_IRQHandler(void) {
buttonInterrupt = true;
EXTI->PR1 = 0x2000;
}
Never mind: There seems to be some problem with a delay i have with timer-2. It's not using interrupts, so i'm surprised it's causing trouble. But if i take it out and use a different delay, the interrupt from the above code works fine. It's an odd one.

SPI slaveon DSPIC

Working on DSPIC33FJ128MC804
The problem :
I am completely unable to configura the SPI as slave. SPI Interrupt does never fire. if(SPI2STATbits.SPIRBF || SPI2STATbits.SPIROV) is always evaluated as false too.
I tried
with SSEN enabled and disabled, and many other configurations...
The clock is present and generated by an Arduino Uno as master, the pin mapping has been checked 3 times. This device is not subject to the SPI slave CSn errata of this familly.
Does anyone see what I do wrong ? or have a working example as SLAVE ?
// Setup hardware I/Os configuration
SPI_SLAVE_CSN_TRIS = 1; //input
SPI_SLAVE_CLK_TRIS = 1;
SPI_SLAVE_MOSI_TRIS = 1;
SPI_SLAVE_MISO_TRIS = 0; //output
// Setup remapable pins
SPI_SLAVE_MISO_RPN = _RPOUT_SDO2; // configure RP output
RPINR22bits.SDI2R = SPI_SLAVE_MOSI_RP_NUMBER; //configure inputs
RPINR22bits.SCK2R = SPI_SLAVE_CLK_RP_NUMBER;
RPINR23bits.SS2R = SPI_SLAVE_CSN_RP_NUMBER;
IFS2bits.SPI2IF = 0; // Clear interrupt flag
IEC2bits.SPI2IE = 0; // Disable interrupt
// Baudrate configuration (unused in slave mode )
SPI2CON1bits.PPRE = 0b11; //TODO needed in slave mode ?
SPI2CON1bits.SPRE = 0b110;
SPI2CON1bits.DISSCK = 0; // Internal serial clock
SPI2CON1bits.DISSDO = 0; // SDOx is controlled by the module
SPI2CON1bits.MODE16 = 0; // 8 bit mode //TODO check if 16 bit fit's better
SPI2CON1bits.SMP = 0; // 0 when slave
SPI2CON1bits.CKE = 1; // Emits SDO on SCK falling edge (slave samples on rising)
SPI2CON1bits.CKP = 0; // SCK idle state is LOW level
SPI2CON1bits.SSEN = 1;// CSN pin used for slave mode
SPI2CON1bits.MSTEN = 0; // Slave mode is enabled
//SPI2CON2bits.SPIFSD = 1; //we are not in framed mode
SPI2STATbits.SPIEN = 1; // Enable SPI module
//TODO ISR priority
// Write the SPIx Interrupt Priority Control (SPIxIP) bits in the respective IPCx register to set the interrupt priority
SPI2BUF = 0xf3; // Clear data to be transmitted => for test
IFS2bits.SPI2IF = 0; // Clear interrupt flag
IEC2bits.SPI2IE = 1; // Enable interrupt
SOLVED
The RPN pin fucntions where locked in another part of the code I hadn't written.
I was not aware of this functionnality
I have no experience with SPI in slave mode but in general setting the priority of the interrupt on 16 and 32 bit pic MCUs are not optional, it must be set or the interrupt won't fire, at least that's been my experience. Set the IPCx bits relevant for the peripherals you use.
Try finding a code snippet where an interrupt function is defined and use that as a template. It's generally very similar for every peripheral. UART and maybe also the SPI module has a separate send and receive interrupt vector, both must be defined.
Somewhere in the main function, enable the interrupt and set the priority, at least non zero IIRC:
IEC0bits.AD1IE = 1; // Enable adc interrupt
IPC3bits.AD1IP = 4; // set priority above that of the serial port.
For an ADC I use this to define the interrupt. All you need to change is the _ADC1Interrupt part. See the datasheet and XC16 documentation for the correct function name.
// ADC1 interrupt vector
void __attribute__((__interrupt__(auto_psv))) _ADC1Interrupt(void)
{
if( IFS0bits.AD1IF ) // Check interrupt flag
{
}
IFS0bits.AD1IF = 0; // clear interrupt flag to prevent endless interrupts
}

How does Contiki OS process external interrupts?

It is possible to wake sensor nodes on external interrupts that are generated by peripheral sensors. The following explains how Contiki OS handles external interrupts. In case of the ATmega128RFA1 the external interrupts INT0 to INT4 are able to wake the MCU even from deep sleep.
an overview over processes and interupts in contiki is here:
https://github.com/contiki-os/contiki/wiki/Processes
http://de.slideshare.net/DingxinXu/contiki-introduction-iifrom-what-to-how
http://senstools.gforge.inria.fr/doku.php?id=os:contiki
contiki utilizes the ISR vectors of the MCU
this example is for ATmega128RFA1. the external interrupt is INT0 on PD0 (pin 25)
in the ISR the only action is to poll an associated contiki process. Internally this sends a poll request to the process. The process catches the poll request and then executes the calculations associated with the external interrupt. This proceeding prevents long lasting calculations in the ISR.
ISR :
ISR(INT0_vect)
{
process_poll(&extern_interupt_process);
PRINTF("interrupt was triggered on INT0... \n");
}
to enable the external interupts on INT0:
EIMSK = 0xb00000000; //disable interrupts before changing EICRA
EICRA |= 0xb00000011; //EICRA 0000|0011 rising edge triggers interrupt int0
EIMSK |= 0xb00000001; // enable INT0 (datasheet p. 219 ff)
process :
PROCESS(extern_interupt_process, "external_interrupt_process");
PROCESS_THREAD(extern_interupt_process, ev, data)
{
PROCESS_BEGIN();
while(1) {
PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
// process data here
}
PROCESS_END();
}
use autostart_process() to start the extern_interrupt_process or start it manually in contiki-main.c
if the sensor has an open collector output activate the internal pull-up resistor and set the interrupt control register to trigger an interrupt on low-level (see this: wiring a sensor with open collector output)
DDRD &= 0xb00000000; // PD0 as input
PORTD |= 0xb00000001; // enable internal pull-up on PD0
EIMSK &= 0xb00000000; //disable interrupts before changing EICRA
EICRA &= 0xb00000000; //EICRA 0000|0000 low-level triggers interrupt on int0
EIMSK |= 0xb00000001; // enable INT0` (datasheet p. 219 ff)
http://en.wikipedia.org/wiki/Open collector

Cortex M-0: Simple external interrupt

I'm trying to set up an external interrupt on my LPC812 uC. I've made the following code
#include "LPC8xx.h"
#define RLED 7 // red LED
bool pause = false;
void PININT0_IRQHandler(void)
{
pause = !pause;
}
int main(void) {
LPC_GPIO_PORT->DIR0 |= 1<<RLED; // set pin as output
LPC_GPIO_PORT->SET0 = 1<<RLED;
NVIC_EnableIRQ(PININT0_IRQn);
while (1)
{
if(!pause)
{
LPC_GPIO_PORT->CLR0 = 1<<RLED;
}
}
}
But it isn't working. Am I missing something?
I'm not familiar with NXP MCUs.
But at least place break piont inside PININT0_IRQHandler, to understand clearly that interrupt is not generated.
Also it will be nice to clear interrupt flag inside handler.
Some peripherals need interrupt permission in peripheral registers in addition to NVIC setup.
Did you setup input pin somewhere?
Your code only initialize GPIO 7 pin as output.