I'm trying to implement this logic in STM8S103F3:
1) Controller wait for external interurpts on GPIOC (high by default) after initialization.
2.1) external interrupt triggered: if PIN5 of GPIOC is low, turn test led on, and start timer for 5s.
2.2) external interrupt triggered: if PIN5 of GPIOC is high, turn test led off and stop timer.
3) timer interrupt triggered: turn test led off.
My code:
#include "stm8s.h"
#include "stm8s_gpio.h"
#include "stm8s_exti.h"
#include "stm8s_tim1.h"
void tim1_update_handler() __interrupt(11)
{
GPIO_WriteHigh(GPIOB, GPIO_PIN_5);
TIM1_ClearITPendingBit(TIM1_IT_UPDATE);
}
void portc_ext_int_handler() __interrupt(5)
{
uint8_t state = GPIO_ReadInputData(GPIOC);
if (state & GPIO_PIN_5) // PORTC pin 5 high, default state, button not pressed.
{
TIM1_SetCounter(0);
TIM1_Cmd(ENABLE);
}
else // Button pressed.
{
GPIO_WriteLow(GPIOB, GPIO_PIN_5);
TIM1_Cmd(DISABLE);
}
}
int main(void)
{
disableInterrupts();
GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_Init(GPIOC, GPIO_PIN_ALL, GPIO_MODE_IN_PU_IT);
EXTI_DeInit();
EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOC, EXTI_SENSITIVITY_RISE_FALL);
TIM1_TimeBaseInit(2000, TIM1_COUNTERMODE_UP, 5000, 0);
TIM1_SelectOnePulseMode(TIM1_OPMODE_SINGLE);
TIM1_ITConfig(TIM1_IT_UPDATE, ENABLE);
enableInterrupts();
while (1)
{
wfi();
}
}
External interrupt is triggered fine, but timer interrupt does not triggers.
What i'm doing wrong with timer, and how i can gix it?
Bit late with this,but possibly it is because of the interrupt priority, which by default is set to NOT interrupt an ISR already in progress. Changing the ITC_xxx registers allows setting these priorities so one IRQ can interrupt another, which is what you need with the timer.
Related
Imagine the following program written in C:
void handler(int signo) {
write(STDOUT_FILENO, "handler\n", 8);
}
int main() {
signal(SIGUSR1, handler);
kill(getpid(), SIGUSR1);
write(STDOUT_FILENO, "after kill\n", 11);
}
If I run this program in Linux, is it possible the output is as follow:
after kill
handler
I tried many times, and the above result didn't appear.
If the SIGINT signal is delivered to the process after the puts("looping"); statement, then it will print the string "handler1" in the handle1 function. When the kill function returns, the output depends on when the SIGUSR1 signal will be delivered to the process. I think you can use the sigsuspend function to make sure it's what you want. By the way, before kill function returns, at least an unblocked signal is delivered to the process.
The following code outputs what you want and you need to block the SIGUSR1 signal first.
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void handler(int signo) {
write(STDOUT_FILENO, "handler\n", 8);
}
int main() {
sigset_t newmask, oldmask;
sigemptyset( &newmask );
sigaddset( &newmask, SIGUSR1 );
signal(SIGUSR1, handler);
// block the SIGUSR1 signal
sigprocmask ( SIG_BLOCK, &newmask, &oldmask );
kill(getpid(), SIGUSR1);
write(STDOUT_FILENO, "after kill\n", 11);
// reset the signal mask
sigprocmask ( SIG_SETMASK, &oldmask, NULL );
}
puts is not good inside signals handlers. Read signal(7), puts is not async-signal-safe. You should use write(2) inside a signal handler (not puts).
You have edited your question to use write instead of puts
And if you insist in wrongly using puts you should at least call fflush. But both are wrong inside signal handlers.
(Don't forget that stdoutis buffered)
BTW, it might happen (notably in multi-threaded application, where the signal handler is not running in the same thread that kill(2)-s the signal) that the signal handler is invoked after returning of kill
I'm not sure that you are guaranteed that the signal handler of a single-threaded process is returning before kill, even if I believe that would happen on most Linux kernels. What you should be sure is that the signal handler would eventually be called (but you cannot be sure on when exactly). Also, a kernel is permitted to lose some signals (e.g. if an external thing or process is sending a lot of same signals). So called POSIX real-time signals are the exception, not the norm (see also this)
If you have an event loop (e.g. around poll(2)) and accept to have Linux-specific code
you could consider using signalfd(2) and polling it inside your event loop.
I am porting a device driver from QNX to Linux. In QNX, the old driver used a pthread with an infinite loop to monitor for the occurrence of an interrupt, rather than registering a true interrupt handler. To try to demonstrate the efficacy of using register_irq() instead of a dedicated polling thread, I wrote two drivers in Linux. The relevant code for each is shown below and the question is at the bottom.
IRQ
Write the handler
irqreturn_t timing_interrupt_handler(int irq, void *dev_id) {
u32 test;
/* read device interrupt command/status register */
test = ioread32(timing_card[3].base);
/* sanity check that the device reported the interrupt */
if ( test & (1 << 2) ) {
/* clear interrupt status */
iowrite32( 0x0d, timing_card[3].base);
/* toggle digital output line */
test = ioread32(timing_card[2].base);
if ( test & 0x01 )
iowrite32(test & ~0x1, timing_card[2].base);
else
iowrite32(test | 0x1, timing_card[2].base);
}
return IRQ_HANDLED;
}
Register the handler
rc = request_irq(irq_line, timing_interrupt_handler,
IRQF_SHARED, "timing", timing_card);
if ( rc ) {
printk(KERN_ALERT "Failed to register irq %d\n", irq_line);
return rc;
}
POLLING THREAD
Write the thread function
int poll_irq(void *data) {
u32 test;
/* until module unload */
while ( !kthread_should_stop() ) {
/* read device interrupt command/status register */
test = ioread32(timing_card[3].base);
/* sanity check that the device reported the interrupt */
if ( test & (1 << 2) ) {
/* clear interrupt status */
iowrite32( 0x0d, timing_card[3].base);
/* toggle digital output line */
test = ioread32(timing_card[2].base);
if ( test & 0x01 )
iowrite32(test & ~0x1, timing_card[2].base);
else
iowrite32(test | 0x1, timing_card[2].base);
}
else
usleep_range(9, 11);
}
return 0;
}
Begin the thread
kthread = kthread_create(poll_irq, 0x0, "poll_IRQ_test");
wake_up_process(kthread);
THE QUESTION
When I put two traces on an oscilloscope - one monitoring the card's digital input (which would trigger the interrupt) and one monitoring the card's digital output (which would react to the interrupt) I can measure the reaction time to an event.
The first "proper" method, registering an IRQ, takes approximately 80 microseconds.
The second method, running an infinite thread, takes approximately 15-30 microseconds.
What gives? The benefit of the first is that it doesn't waste as much processing power, but why does response time suffer so dramatically? How bad is it, really, to have this polling thread? How could one go about investigating and eventually demonstrating the extra toll the polling thread puts on the CPU?
Thanks for your time!
Best
Scott
The interrupt response time is affected by the time your system (whatever it is) needs to deliver the interrupt, and by the time your CPU (whatever it is) needs to wake up from some power-saving sleeping mode.
The polling thread eats both CPU time and power.
To measure them, use something like top or powertop, or measure the power consumption directly on the hardware.
In a linux kernel driver, I would like to repeat indefinitely the following sequence:
at time T, a hardware IRQ is enabled
between time T and T + "around" 15ms, the IRQ callback can be reached if the IRQ is triggered. I say around because I'm not using an RT kernel and if it's 14 or 16ms, it's fine. In the IRQ callback, I need to write down get cpu_clock(0) and call wake_up_interruptible. The timeout needs to be killed. The whole process needs to be started again within 5ms.
if by T + "around" 15ms, the IRQ has not been triggered, I need to execute some other code. The IRQ should be disabled then. The whole process needs to be started again within 5ms.
Therefore, by T + "around" 20ms, in worst case, the whole process needs to be started again.
Note that if the IRQ is physically triggered at 18ms, too bad, "I missed the train". I will catch another hardware trigger at the next sequence.
While testing, I was doing something along the following pseudo-code:
INIT_DELAYED_WORK(&priv->work, driver_work);
INIT_DELAYED_WORK(&priv->timeout, driver_timeout);
request_irq(priv->irq, driver_interrupt, IRQF_TRIGGER_RISING, "my_irq", priv);
then:
queue_delayed_work(priv->workq, &priv->work, 0ms);
static void driver_work(struct work_struct *work) {
queue_delayed_work(priv->workq, &priv->timeout, 15ms);
priv->interruptCalled = 0;
enable_irq(priv->irq);
}
Then:
static irqreturn_t driver_interrupt(int irq, void *_priv) {
disable_irq_nosync(priv->irq);
priv->interruptCalled = 1;
cancel_delayed_work(&priv->timeout);
priv->stamp = cpu_clock(0);
wake_up_interruptible(&driver_wait);
queue_delayed_work(priv->workq, &priv->work, 5ms);
return IRQ_HANDLED;
}
And:
static void driver_timeout(struct work_struct *work) {
if (priv->interruptCalled == 0) {
disable_irq_nosync(priv->irq);
//Do other small cleanup
queue_delayed_work(priv->workq, &priv->work, 5ms);
}
}
I'm trying to write a robust but simple driver. Is this a proper implementation? How can I improve this implementation?
Answering my own question: the problem is that queue_delayed_work is based on jiffies. Or 5ms is not possible as HZ=100 (1 jiffy = 10ms). HR timer brought a good solution.
I have a couple of tasks to do with arduino but one of them takes very long time, so I was thinking to use threads to run them simultaneously.
I have an Arduino Mega
[Update]
Finally after four years I can install FreeRTOS in my arduino mega. Here is a link
In short: NO.
But you may give it a shot at:
http://www.kwartzlab.ca/2010/09/arduino-multi-threading-librar/
(Archived version: https://web.archive.org/web/20160505034337/http://www.kwartzlab.ca/2010/09/arduino-multi-threading-librar
Github: https://github.com/jlamothe/mthread
Not yet, but I always use this Library with big projects:
https://github.com/ivanseidel/ArduinoThread
I place the callback within a Timer interrupt, and voilá! You have pseudo-threads running on the Arduino...
Just to make this thread more complete: there are also protothreads which have very small memory footprint (couple bytes if I remember right) and preserve variables local to thread; very handy and time saving (far less finite state machines -> more readable code).
Examples and code:
arduino-class / ProtoThreads wiki
Just to let you know what results you may expect: serial communication # 153K6 baudrate with threads for: status diodes blinking, time keeping, requested functions evaluation, IO handling and logic and all on atmega328.
Not real threading but TimedActions are a good alternative for many uses
http://playground.arduino.cc/Code/TimedAction#Example
Of course, if one task blocks, the others will too, while threading can let one task freeze and the others will continue...
No you can't but you can use Timer interrupt.
Ref : https://www.teachmemicro.com/arduino-timer-interrupt-tutorial/
The previous answer is correct, however, the arduino generally runs pretty quick, so if you properly time your code, it can accomplish tasks more or less simultaneously.
The best practice is to make your own functions and avoid putting too much real code in the default void loop
You can use arduinos
It is designed for Arduino environment. Features:
Only static allocation (no malloc/new)
Support context switching when delaying execution
Implements semaphores
Lightweight, both cpu and memory
I use it when I need to receive new commands from bluetooth/network/serial while executing the old ones and the old ones have delay in them.
One thread is the sever thread that does the following loop:
while (1) {
while ((n = Serial.read()) != -1) {
// do something with n, like filling a buffer
if (command_was_received) {
arduinos_create(command_func, arg);
}
}
arduinos_yield(); // context switch to other threads
}
The other is the command thread that executes the command:
int command_func(void* arg) {
// move some servos
arduinos_delay(1000); // wait for them to move
// move some more servos
}
Arduino does not support multithread programming.
However there have been some workarounds, for example the one in this project (you can install it also from the Arduino IDE).
It seems you have to define the schedule time yourself while in a real multithread environment it is the OS that decides when to execute tasks.
Alternatively you can use protothreads
The straight answer is No No No!. There are some alternatives but you can't expect a perfect multi threading functionality from an arduino mega. You can use arduino due or lenado for multithreading like below-
void loop1(){
}
void loop2(){
}
void loop3(){
}
Normally, I handle those types of cases in backend. You can run the main code in a server while using Arduino to just collect inputs and show outputs. In such cases I would prefer nodemcu which has built in wifi.
Thread NO!
Concurrent YES!
You can run different tasks concurrently with FreeRTOS library.
https://www.arduino.cc/reference/en/libraries/freertos/
void TaskBlink( void *pvParameters );
void TaskAnalogRead( void *pvParameters );
// Now set up two tasks to run independently.
xTaskCreate(
TaskBlink
, (const portCHAR *)"Blink" // A name just for humans
, 128 // Stack size
, NULL
, 2 // priority
, NULL );
xTaskCreate(
TaskAnalogRead
, (const portCHAR *) "AnalogRead"
, 128 // This stack size can be checked & adjusted by reading Highwater
, NULL
, 1 // priority
, NULL );
void TaskBlink(void *pvParameters) // This is a task.
{
(void) pvParameters;
// initialize digital pin 13 as an output.
pinMode(13, OUTPUT);
for (;;) // A Task shall never return or exit.
{
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
}
}
void TaskAnalogRead(void *pvParameters) // This is a task.
{
(void) pvParameters;
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
for (;;)
{
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// print out the value you read:
Serial.println(sensorValue);
vTaskDelay(1); // one tick delay (15ms) in between reads for stability
}
}
Just take care!
When different tasks tried to reach variables at the same time, like i2c communication line or sd card module. Use Semaphores and mutexes
https://www.geeksforgeeks.org/mutex-vs-semaphore/.
Arduino does not supports threading. However, you can do the next best thing and structure your code around state machines running in interleaving.
While there are lots of ways to implement your tasks as state machines, I recommend this library (https://github.com/Elidio/StateMachine). This library abstracts most of the process.
You can create a state machine as a class like this:
#include "StateMachine.h"
class STATEMACHINE(Blink) {
private:
int port;
int waitTime;
CREATE_STATE(low);
CREATE_STATE(high);
void low() {
digitalWrite(port, LOW);
*this << &STATE(high)<< waitTime;
}
void high() {
digitalWrite(port, HIGH);
*this << &STATE(low)<< waitTime;
}
public:
Blink(int port = 0, int waitTime = 0) :
port(port),
waitTime(waitTime),
INIT_STATE(low),
INIT_STATE(high)
{
pinMode(port, OUTPUT);
*this << &STATE(low);
}
};
The macro STATEMACHINE() abstracts the class inheritances, the macro CREATE_STATE() abstracts the state wrapper creation, the macro INIT_STATE() abstracts method wrapping and the macro STATE() abstracts state wrapper reference within the state machine class.
State transition is abstracted by << operator between the state machine class and the state, and if you want a delayed state transition, all you have to do is to use that operator with an integer, where the integer is the delay in millisseconds.
To use the state machine, first you have to instantiate it. Declaring an reference to the class in global space while instantiating it with new on setup function might do the trick
Blink *led1, *led2, *led3;
void setup() {
led1 = new Blink(12, 300);
led2 = new Blink(11, 500);
led3 = new Blink(10, 700);
}
Then you run the states on loop.
void loop() {
(*led2)();
(*led1)();
(*led3)();
}
I've blocked, and then waited for a signal via the following code:
sigset_t set;
sigfillset(&set); // all signals
sigprocmask(SIG_SETMASK, &set, NULL); // block all signals
siginfo_t info;
int signum = sigwaitinfo(&set, &info); // wait for next signal
struct sigaction act;
sigaction(signum, NULL, &act); // get the current handler for the signal
act.sa_handler(signum); // invoke it
The last line generates a segmentation fault, as the handler is set to SIG_DFL (defined as 0). How can I manually invoke the default handler if it's set to SIG_DFL or SIG_IGN? Also note that SIG_IGN is defined as 1.
As you discovered you cannot invoke SIG_DFL and SIG_IGN per se. However, you can more-or-less mimic their behavior.
Briefly, imitating normal signal disposition would be:
quite easy for user-defined sa_handlers
easy enough for SIG_IGN, with the caveat that you'd need to waitpid() in the case of CHLD
straightforward but unpleasant for SIG_DFL, re-raising to let the kernel do its magic.
Does this do what you want?
#include <signal.h>
#include <stdlib.h>
/* Manually dispose of a signal, mimicking the behavior of current
* signal dispositions as best we can. We won't cause EINTR, for
* instance.
*
* FIXME: save and restore errno around the SIG_DFL logic and
* SIG_IGN/CHLD logic.
*/
void dispatch_signal(const int signo) {
int stop = 0;
sigset_t oset;
struct sigaction curact;
sigaction(signo, NULL, &curact);
/* SIG_IGN => noop or soak up child term/stop signals (for CHLD) */
if (SIG_IGN == curact.sa_handler) {
if (SIGCHLD == signo) {
int status;
while (waitpid(-1, &status, WNOHANG|WUNTRACED) > 0) {;}
}
return;
}
/* user defined => invoke it */
if (SIG_DFL != curact.sa_handler) {
curact.sa_handler(signo);
return;
}
/* SIG_DFL => let kernel handle it (mostly).
*
* We handle noop signals ourselves -- "Ign" and "Cont", which we
* can never intercept while stopped.
*/
if (SIGURG == signo || SIGWINCH == signo || SIGCONT == signo) return;
/* Unblock CONT if this is a "Stop" signal, so that we may later be
* woken up.
*/
stop = (SIGTSTP == signo || SIGTTIN == signo || SIGTTOU == signo);
if (stop) {
sigset_t sig_cont;
sigemptyset(&sig_cont);
sigaddset(&sig_cont, SIGCONT);
sigprocmask(SIG_UNBLOCK, &sig_cont, &oset);
}
/* Re-raise, letting the kernel do the work:
* - Set exit codes and corefiles for "Term" and "Core"
* - Halt us and signal WUNTRACED'ing parents for "Stop"
* - Do the right thing if we forgot to handle any special
* signals or signals yet to be introduced
*/
kill(getpid(), signo);
/* Re-block CONT, if needed */
if (stop) sigprocmask(SIG_SETMASK, &oset, NULL);
}
UPDATE
(in response to OP's excellent questions)
1: does this slot in after the sigwaitinfo?
Yes. Something like:
... block signals ...
signo = sigwaitinfo(&set, &info);
dispatch_signal(signo);
2: Why not raise those signals handled by SIG_IGN, they'll be ignored anyway
It's slightly more efficient to noop in userspace than by three syscalls (re-raise, unmask, re-mask). Moreover, CHLD has special semantics when SIG_IGNored.
3: Why treat SIGCHLD specially?
Originally (check answer edits) I didn't -- re-raised it in the SIG_IGN case,
because IGNored CHLD signals tell the kernel to automatically reap children.
However, I changed it because "natural" CHLD signals carry information about
the terminated process (at least PID, status, and real UID).
User-generated CHLD signals don't carry the same semantics, and, in my testing,
IGNoring them doesn't cause 2.6 to autoreap queued zombies whose SIGCHLD
was "missed." So, I do it myself.
4: Why are "stop" related signals unblocking CONT. Will not invoking the default handler for CONT unstop the process?
If we're stopped (not executing) and CONT is blocked, we will never receive the
signal to wake us up!
5: Why not call raise instead of the kill line you've given?
Personal preference; raise() would work, too.
I see 2 mistakes in your code :
1) You should reverse the last two lines like this :
act.sa_handler(signum);
sigaction(signum, NULL, &act);
2) You must pass a function handler to the fiedl sa_handler instead of a int. The prototype of the function shoudl look like this :
/**
*some where in you code
*/
void handler (int signal){ /*your code*/}
/**
*
*/
act.sa_handler = handler;
If you want the default handler to be invoked, you should set the field sa_handler to SIG_DFL and it should work.
I'm not aware of the way to do it.
Only suggestion I have is to look into the man 7 signal and perform manually the action according the table you see there. Ign is nothing. Core is call to abort(). Term is _exit().
Of course you can also set signal handler back to SIG_DFL and then kill(getpid(),THE_SIG) (or its equivalent raise(THE_SIG)). (I personally do not like raise because on some systems it might produce some messages on stderr.)