c programming for interrupts in qnx? - c

client- server communication - client is sender and server is receiver. when the server receives the data on the ethernet interface(UDP) the kernel in the server is triggered. I am using QNX on the server side. server(i.e embedded pc target) is handling interrupts to trigger the embedded pc target (conatining QNX) to gain the attention to execute the newly arrived data.
const struct sigevent *handler1(void *area, int id1)
{
volatile double KernelStartExecutionTime;
struct sigevent *event = (struct sigevent *)area;
KernelStartExecutionTime = GetTimeStamp(); // calculating the time when the kernel //starts executing
measurements[18] = KernelStartExecutionTime ;
//return (NULL);
return event;
}
/*kernel calls attach the interrupt function handler to the hardware interrupt specified by intr(i.e irq) */
// InterruptAttach() : Attach an interrupt handler to an interrupt source
// interrupt source is handler1 for this example
void ISR(void) //void *ISR (void *arg)
{
/* the software must tell the OS that it wishes to associate the ISR with a particular source of interrupts.
* On x86 platforms, there are generally 16 hardware Interrupt Request lines (IRQs) */
volatile int irq = 0; //0 : A clock that runs at the resolution set by ClockPeriod()
struct sigevent event;
event.sigev_notify = SIGEV_INTR;
ThreadCtl (_NTO_TCTL_IO, NULL); // enables the hardware interrupt
id1 = InterruptAttach(irq, &handler1, &event, sizeof(event), 0); // handler1 is the ISR
while(1)
{
InterruptWait( 0, NULL );
InterruptUnmask(irq, id1);
}
InterruptDetach( id1);
}
int main(int argc, char *argv[])
{
ISR(); //function call for ISR
// pthread_create (NULL, NULL, ISR, NULL);
return 0;
}
question:
Should I create a new thread for handling interrupts within the main??

Related

Using DMA controller to transmit UART

I have been trying exhaustively to program my STM32F7xx microcontroller to use DMA to transmit to UART. Three things are going on and I cannot explain or understand why this is happening, and hope somebody can help me out with this issue.
In the main while loop, I am printing three interrupt status flags. These flags are set if the corresponding ISR has been called. I added this to check if the ISR was called without adding blocking statements in the ISRs. None of the interrupts, however, are called.
The DMA only transmits 1 sequence of 513 bytes. When I modify the while loop in my main to only contain HAL_UART_Transmit_DMA(&handleUart4, dmxBuffer, 513);, nothing changes, the function is only called/executed once.
In the while loop, I print the status of the ISR flags. After printing, the CPU stops/locks/shutdown/exits the while loop. At first, I thought I was congesting the AHB by using the UART to my terminal and the UART for the DMA controller. I disabled my terminal, and used LEDs, this didn't change anything.
Currently, the only running hypothesis I have is that my CPU somehow has interrupts disabled.
#include "stm32f7xx.h"
#include "mbed.h"
uint8_t dmxBuffer[513];
volatile bool irqA = false;
volatile bool irqB = false;
volatile bool irqC = false;
Serial pc(USBTX, USBRX, 115200);
UART_HandleTypeDef handleUart4;
DMA_HandleTypeDef handleDma;
void initialiseGPIO()
{
GPIO_InitTypeDef GPIO_InitStruct;
__GPIOA_CLK_ENABLE();
/**UART4 GPIO Configuration
PA0 ------> USART4_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void initialiseDMAController()
{
/* DMA controller clock enable */
__DMA1_CLK_ENABLE();
/* Peripheral DMA init*/
handleDma.Instance = DMA1_Stream4;
handleDma.Init.Channel = DMA_CHANNEL_4;
handleDma.Init.Direction = DMA_MEMORY_TO_PERIPH;
handleDma.Init.PeriphInc = DMA_PINC_DISABLE;
handleDma.Init.MemInc = DMA_MINC_ENABLE;
handleDma.Init.PeriphDataAlignment = DMA_MDATAALIGN_BYTE;
handleDma.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
handleDma.Init.Mode = DMA_NORMAL;
handleDma.Init.Priority = DMA_PRIORITY_MEDIUM;
handleDma.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&handleDma);
//Define
__HAL_LINKDMA(&handleUart4,hdmatx,handleDma);
/* DMA interrupt init */
HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
}
void initialiseUart()
{
__UART4_CLK_ENABLE();
handleUart4.Instance = UART4;
handleUart4.Init.BaudRate = 250000;
handleUart4.Init.WordLength = UART_WORDLENGTH_8B;
handleUart4.Init.StopBits = UART_STOPBITS_2;
handleUart4.Init.Parity = UART_PARITY_NONE;
handleUart4.Init.Mode = UART_MODE_TX;
handleUart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
handleUart4.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&handleUart4);
/* Peripheral interrupt init*/
HAL_NVIC_SetPriority(UART4_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(UART4_IRQn);
}
/* This function handles DMA1 stream4 global interrupt. */
void DMA1_Stream4_IRQHandler(void)
{
irqA = true;
HAL_DMA_IRQHandler(&handleDma);
}
/* This function handles the UART4 interups */
void UART4_IRQHandler(void)
{
irqB = true;
HAL_UART_IRQHandler(&handleUart4);
}
//HAL_UART_TxCpltCallback
/* This callback function is called when the DMA successfully transmits all scheduled bytes. */
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
irqC = true;
}
int main(void)
{
/* Reset of all peripherals */
HAL_Init();
//Initialise peripherals
initialiseGPIO();
initialiseDMAController();
initialiseUart();
//Fill buffer with test data
for (int x = 0; x < 100; x++)
{
dmxBuffer[x] = x;
}
//Now instruct the UART peripheral to transmit 513 bytes using the DMA controller.
HAL_UART_Transmit_DMA(&handleUart4, dmxBuffer, 513);
while(1)
{
pc.printf("irqA: %d - irqB: %d - irqC: %d\r\n", irqA, irqB, irqC);
wait_ms(100); //Wait to see if any of the interupt handlers / callback functions are called
//Check if all bytes are sent, if so, retransmit
if (irqC)
{
irqC = false;
HAL_UART_Transmit_DMA(&handleUart4, dmxBuffer, 513);
}
}
}
Check the interrupt vector table
Verify that the vector table does indeed contain a pointer to your handler function, not to some generic placeholder with an infinite loop (that makes the program hang).
Search for the name of the interrupt handler function in the entire source code. Is there any other object or #define that could interfere with the function definition, or the vector table entry?
Change the name of the handler, both the function definition and the vector table entry. Does it still compile? When not, does adding extern "C" to the function prototype help?
Look up the address of the handler in the .map file, and the offset entry for the interrupt in the vector table provided in the Reference Manual (Nested vectored interrupt controller (NVIC) / Interrupt and exception vectors). Check the contents of the compiled program binary file at the given offset. Does it match the address found in the .map file + 1?
Check the value at NVIC->VTOR plus the offset while running the program. It should be the same as the one found in the binary. If not, see that the VTOR register is set to the beginning of the right vector table.

keil rtx osdelay not creating accurate delays

I am working on a board which comprises LPC1768 microcontroller. All I want to do is to create an accurate time delay using osdelay function of CMSIS RTOS API. I have set my systick time tick count to 10000.But when I use osdelay(1000) in my thread, it doesn't creates delay period of 1 second as it should do !
Here is the source code
#include"cmsis_os.h"
#include"lpc17xx.h"
void Thread1 (void const *argument) {
while (1) {
LPC_GPIO2->FIOPIN = 0x00000001;
osDelay(1000);
LPC_GPIO2->FIOPIN = 0x00000000;
osDelay(1000);
}
}
osThreadId main_ID,led_ID1,led_ID2;
osThreadDef(Thread1,osPriorityNormal, 1, 0);
int main (void)
{
SystemInit();
LPC_PINCON->PINSEL4 = 0x00000000;
LPC_GPIO2->FIODIR = 0xffffffff;
osKernelInitialize ();
led_ID1 = osThreadCreate(osThread(Thread1), NULL);
osKernelStart ();
}
Now, my problem is with osdelay(1000) not providing a delay of 1000ms as it should do with systick timer tick value set to 1000.

How to offload NAPI poll function to workqueue

I'm working with linux 3.3, Ethernet driver for smsc911x. and I want to move the NAPI poll function to workqueue.
My questions are :
1. How do I pass the NAPI poll function arguments to the work_struct?
2. How do I get the NAPI poll function arguments back from the work_struct? (related to Q.1 above)
3. How can I return the npackets value to the original NAPI poll function caller?
Here are some explanations :
Current NAPI poll function reads recevie FIFO directly which I want to change to do it with DMA controller. For this DMA, I trigger DMA, sleep with wait_event_interruptible, and get woken up by DMA's ISR with wake_up_interruptible. As you know, NAPI poll function is in interrupt context (softirq) so I cannot sleep there for DMA completion. I want to move the NAPI poll function(reading RX FIFO) to waitqueue(process context) usnig a work_struct.
The problem is, NAPI poll function is called by the kernel with two arguments : struct napi_struct *napi and int budget.
I want to pass those argument to the work_struct and queue the work_struct to the workqueue (using queue_work function).
the work_struct looks like below. (include/linux/workqueue.h)
struct work_struct {
atomic_long_t data;
struct list_head entry;
work_func_t func;
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
I take that atomic_long_t data is for passing the argument to the work_struct. how can I pass the arguments to the work_struct?
I tried this (I added in the structure for device driver struct smsc911x_data a member struct work_struct rx_work for passing the work.) :
struct work_arg { // a new struct for pass the arguments
struct napi_struct *napi;
int budget;
};
/* NAPI poll function */
static int smsc911x_poll(struct napi_struct *napi, int budget) {
struct smsc911x_data *pdata =
container_of(napi, struct smsc911x_data, napi);
struct net_device *dev = pdata->dev;
int npackets = 0;
if (enable_rx_use_dma == 1) { // when using DMA for FIFO read
prom_printf("moving it to workqueue\n");
struct work_arg *p;
p = kzalloc(sizeof(struct work_arg), GFP_KERNEL);
p->napi = napi;
p->budget = budget;
pdata->rx_work.data = (atomic_long_t) p; // <== THIS LINE
prom_printf("queue work, with napi = %x, budget = %d\n", napi, budget);
queue_work(rx_work_workqueue, &pdata->rx_work); // smsc911x_poll_work } else {
-- original NAP poll function, reads FIFO until it's empty and enables the RX interrupt and
-- keeps the number of processed packets to npackets.
return npackets;
}
For "THIS LINE" above, I'm getting error during compile.
with pdata->rx_work.data = p; , I get error: incompatible types when assigning to type 'atomic_long_t' from type 'struct work_arg *'
with pdata->rx_work.data = (atomic_long_t) p; , I get error: conversion to non-scalar type requested.
Also, in the new work function, How can I extract the original argments? I tried this below which gives me errors.
/* New work function called by the default worker thread */ static int smsc911x_poll_work(struct work_struct *work) {
struct smsc911x_data *pdata =
container_of(work, struct smsc911x_data, rx_work);
struct net_device *dev = pdata->dev;
int npackets = 0;
struct napi_struct *napi = (struct work_struct *)work->data.napi; // <== THIS LINE
int budget = (struct work_struct *)work->data.budget; // <== THIS LINE ..
}
From the above 'THIS LINE's, I get erros below.
error: 'atomic_long_t' has no member named 'napi'
error: 'atomic_long_t' has no member named 'budget'
and I don't know how to pass the return value to the original NAPI poll functino caller.
I'm not sure if this kind of conversion (from NAPI poll to workqueue) is possible.
Sorry for the long questions but any help will be greatly appreciated.
ADD : Because struct smsc911x_data has both struct napi napi; and struct work_struct rx_work; as members, I can easily obtain the struct napi *napi from work_struct *work (an argument of work function) by :
struct smsc911x_data *pdata =
container_of(work, struct smsc911x_data, rx_work); struct napi_struct *napi = &pdata.napi;
so maybe I can just pass the int budget through a new member value in struct smsc911x_data. I sill want to know the correct practice for this case.
How do I pass the NAPI poll function arguments to the work_struct?
Just create new structure, which embed work_struct and add your arguments into it:
struct my_work {
struct work_struct base_work;// Embedded work_struct
struct napi_struct *napi; // Your arguments
int budget;
};
static int smsc911x_poll(struct napi_struct *napi, int budget) {
struct my_work* p = kmalloc(sizeof(*p), GFP_ATOMIC /* Flag usable for interrupt context */);
INIT_WORK(&p->base_work, smsc911x_poll_work); // Initialize underliying structure.
p->budget = budget; // Initialize your members
p->napi = napi;
...
}
How do I get the NAPI poll function arguments back from the work_struct? (related to Q.1 above)
Use container_of:
static int smsc911x_poll_work(struct work_struct *work) {
struct my_work* p = container_of(work, struct my_work, base_work);
...
}
How can I return the npackets value to the original NAPI poll function caller?
As I understand from description(see, e.g., http://www.linuxfoundation.org/collaborate/workgroups/networking/napi) this function should process packets which are ready. And this processing should be done within function itself, without deferring to workqueue or similar.
This approach seems very ineffective since you need two interrupts, one when packet is received, and one when DMA tansfer is done.
I think this it the way of working of DMA capable network interfaces:
When packet(s) arrive, Socket Buffers are already allocated and mapped to DMA memory buffer, and DMA is armed.
Packet is transferred from NIC to Socket Buffer through DMA
NIC raises hardware interrupt (when DMA transfer is done).
Hardware interrupt handler schedules packet receiving software interrupt (SOFTIRQ)
SOFTIRQ does NAPI poll() for further processing.
NAPI poll() process packets in DMA buffers and and passes it to upper layers as sk_buff and initializes new DMA buffers. if all packets (quota) are processed, IRQ is enabled and NAPI is told to stop polling.

how to handle interrupts in qnx?

/*kernel calls attach the interrupt function handler to the hardware interrupt specified by intr(i.e irq) */
// InterruptAttach() : Attach an interrupt handler to an interrupt source
// interrupt source is handler1 for this example
void ConfigureISR(void) //void *ISR (void *arg)
{
/* the software must tell the OS that it wishes to associate the ISR with a particular source of //interrupts. On x86 platforms, there are generally 16 hardware Interrupt Request lines (IRQs) */
StartInterruptTime = GetTimeStamp(); //startTime of the interrupt
volatile int irq = 7; //0 : A clock that runs at the resolution set by ClockPeriod()
ThreadCtl (_NTO_TCTL_IO, NULL); // enables the hardware interrupt
id1 = InterruptAttach(irq, &ISR, NULL, 0, 0); // ISR is the interrupt service routine
//sleep(20);
}
int main ()
{
ConfigureISR();
return 1;
}
I created a interrupt handler on the server side to handle the interrupt from the client side. but the above code is breaking at the interrupt attach function call. could someone tell me why is it breaking ?? Is it the right way to handle interrupts in user application.

Interrupt timer stuck when run parallel with while(1)

first code:
//------------------------------------------------------------------------------
/// Interrupt handlers for TC interrupts. Toggles the state of LEDs
//------------------------------------------------------------------------------
char token = 0;
void TC0_IrqHandler(void) {
volatile unsigned int dummy;
dummy = AT91C_BASE_TC0->TC_SR;
if(token == 1) {
PIO_Clear(&leds[0]);
PIO_Set(&leds[1]);
token = 0;
}
else {
PIO_Set(&leds[0]);
PIO_Clear(&leds[1]);
token = 1;
}
}
//------------------------------------------------------------------------------
/// Configure Timer Counter 0 to generate an interrupt every 250ms.
//------------------------------------------------------------------------------
void ConfigureTc(void) {
unsigned int div;
unsigned int tcclks;
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_TC0; // Enable peripheral clock
TC_FindMckDivisor(1, BOARD_MCK, &div, &tcclks); // Configure TC for a 4Hz frequency and trigger on RC compare
TC_Configure(AT91C_BASE_TC0, tcclks | AT91C_TC_CPCTRG);
AT91C_BASE_TC0->TC_RC = (BOARD_MCK / div) / 1; // timerFreq / desiredFreq
IRQ_ConfigureIT(AT91C_ID_TC0, 0, TC0_IrqHandler); // Configure and enable interrupt on RC compare
AT91C_BASE_TC0->TC_IER = AT91C_TC_CPCS;
IRQ_EnableIT(AT91C_ID_TC0);
printf(" -- timer has started \n\r");
TC_Start(AT91C_BASE_TC0);
}
it's just interrupt timer and it's event (handler) but when I run some
while(1) {
// action
after ConfigureTc() it both cycle and interrupt timer are freezes... Why could that be? Should I add another timer and avoid while(1) ?
while(1) {
printf("hello");
}
-- this breaks (freeze) loops (yes, if I don't use timer it works as it must)
I'll venture an actual answer here. IME, 99% of the time my boards 'go out' with no response on any input and no 'heartbeat' LED-flash from the low-priority 'blinky' thread, the CPU has flown off to a prefetch or data abort handler. These handlers are entered by interrupt and most library-defined default handlers do not re-enable interrupts, so stuffing the entire system. Often, they're just endless loops and, with interrupts disabled, that's the end of the story:(
I have changed my default handlers to output suitable 'CRITICAL ERROR' messages to the UART, (by polling it - the OS/interrupts are stuft!).

Resources