Cortex M0 doesn't enter sleep mode - sleep

Got a problem with the Atmel SAMB11 on an explained pro Devboard. I've loaded a quite simple example from Atmel, where a 32KHz Timer is initialized to wake up the µC from sleep and turn on a LED. Problem is, the controller doesn't sleep at all. It just activates the LED immediately and doesn't wait for an interrupt.
#include <asf.h>
// Callback Func to enable LED
static void aon_sleep_timer_callback(void)
{
gpio_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);
}
//Configure LED
static void configure_gpio_pins(void)
{
struct gpio_config config_gpio_pin;
gpio_get_config_defaults(&config_gpio_pin);
config_gpio_pin.direction = GPIO_PIN_DIR_OUTPUT;
gpio_pin_set_config(LED_0_PIN, &config_gpio_pin);
gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);
}
// Configure Timer with 10sec to overflow
static void configure_aon_sleep_timer(void)
{
struct aon_sleep_timer_config config_aon_sleep_timer;
aon_sleep_timer_get_config_defaults(&config_aon_sleep_timer);
config_aon_sleep_timer.counter = 320000; // Wait about 10sec
aon_sleep_timer_init(&config_aon_sleep_timer);
}
// Configure Callback and enable Interrupt
static void configure_aon_sleep_timer_callback(void)
{
aon_sleep_timer_register_callback(aon_sleep_timer_callback);
NVIC_EnableIRQ(AON_SLEEP_TIMER_IRQn);
}
int main(void)
{
// Setup Clock, LED and Timer
system_clock_config(CLOCK_RESOURCE_XO_26_MHZ, CLOCK_FREQ_26_MHZ);
configure_gpio_pins();
configure_aon_sleep_timer();
configure_aon_sleep_timer_callback();
// wait for timer to be active
while(!aon_sleep_timer_sleep_timer_active());
// Go to sleep
asm volatile ("wfi");
asm volatile ("nop");
// Enable LED immediately if sleep doesn't work
gpio_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);
while (true) {}
}
Code seems self-explanatory, but the WFI command doesn't work here. Anyone can help?

Just to add to the answer by Prestige Worldwide.
Make sure AO_GPIO0/1/2 are low (pulldown advised), and no AON Sleep Timer interrupt is occuring, as these will wakeup the SAMB11 from ULP.
Also note that the ULP mode does not seem to work as expected while running a debug session over SWD.
I had all kinds of weirds behaviour when running the debug and sleep/waking up, but no problems at all when running the same code while not debugging. Note this was using Atmel ICE. The Xplored board contains EDBG, and this debugger seems to work ok with ULP.
The resume callback has never fired for me, maybe a bug in the ASF. But I do not need it as I can setup all GPIO/devices after the platform wait.

The WFI call works, it just receives an interrupt almost immediately after it is called, which causes the WFI call to stop blocking and then execution continues to the next line.
You could safely remove everything below // Go to sleep which would allow the main function to return. The AON timer would still execute its callback. However, there are a couple of potential downsides to this approach:
This would not allow the SAMB11 to transition to a lower power mode.
This removes your while-loop at the end of main. In its current state, the while-loop isn't needed, but you might have plans to add code to it later.
Here is an example that configures the AON, configures the SAMB11 to use low power modes, and then loops waiting for platform and/or BLE events. Currently there are no events for the loop to receive. If you want the loop to receive events then you could modify the AON callback to post an event with the at_ble_event_user_defined_post function or modify main() to configure the BLE module before entering the loop.
Use the ASF Wizard to add any of the BLE modules to your project in order to compile this example.
#include <asf.h>
#include "platform.h"
// Configure LED
static void configure_gpio_pins(void)
{
struct gpio_config config_gpio_pin;
gpio_get_config_defaults(&config_gpio_pin);
config_gpio_pin.direction = GPIO_PIN_DIR_OUTPUT;
gpio_pin_set_config(LED_0_PIN, &config_gpio_pin);
gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);
}
// Callback Func to toggle LED
static bool led_is_on = false;
static void aon_sleep_timer_callback(void)
{
configure_gpio_pins();
if(led_is_on) {
gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);
led_is_on = false;
} else {
gpio_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);
led_is_on = true;
}
}
// Configure Timer to fire periodically
static void configure_aon_sleep_timer(void)
{
struct aon_sleep_timer_config config_aon_sleep_timer;
aon_sleep_timer_get_config_defaults(&config_aon_sleep_timer);
config_aon_sleep_timer.counter = 32000; // Wait about 1 sec
config_aon_sleep_timer.mode = AON_SLEEP_TIMER_RELOAD_MODE;
aon_sleep_timer_init(&config_aon_sleep_timer);
}
// Configure Callback and enable Interrupt
static void configure_aon_sleep_timer_callback(void)
{
aon_sleep_timer_register_callback(aon_sleep_timer_callback);
NVIC_EnableIRQ(AON_SLEEP_TIMER0_IRQn);
}
int main(void)
{
// Setup Clock
system_clock_config(CLOCK_RESOURCE_XO_26_MHZ, CLOCK_FREQ_26_MHZ);
plf_drv_status plf_status;
if((plf_status = platform_driver_init()) == STATUS_SUCCESS) {
// Setup LED and Timer
configure_gpio_pins();
configure_aon_sleep_timer();
configure_aon_sleep_timer_callback();
// wait for timer to be active
while(!aon_sleep_timer_sleep_timer_active());
// Go to sleep
release_sleep_lock();
while(true) {
// Replace platform_event_wait with at_ble_event_get if you would like to read the received event.
plf_status = platform_event_wait(0);
}
}
}
Regarding WFI, the following example shows how to turn off most of the interrupts and use WFI to block main(). The LED will toggle every time an interrupt is received. I don't recommend using this as I'm not sure why these interrupts are enabled initially. This is just intended to show how WFI can block on a SAMB11.
#include <asf.h>
#include "platform.h"
// Configure LED
static void configure_gpio_pins(void)
{
struct gpio_config config_gpio_pin;
gpio_get_config_defaults(&config_gpio_pin);
config_gpio_pin.direction = GPIO_PIN_DIR_OUTPUT;
gpio_pin_set_config(LED_0_PIN, &config_gpio_pin);
gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);
}
// Callback Func to toggle LED
static bool led_is_on = false;
static void toggle_led(void)
{
configure_gpio_pins();
if(led_is_on) {
gpio_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE);
led_is_on = false;
} else {
gpio_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);
led_is_on = true;
}
}
int main(void)
{
// Setup Clock
system_clock_config(CLOCK_RESOURCE_XO_26_MHZ, CLOCK_FREQ_26_MHZ);
// Clear all interrupts.
NVIC->ICER[0] = 0xFFFFFFFF;
// During testing, interrupts were received about once per second; stopped receiving interrupts (LED stopped flashing) after about 2 minutes.
int loop_count = 0;
while(true) {
__WFI();
toggle_led();
}
}

Related

Linux device driver for a Smart Card IC module

I have a smart card IC module, and I want to create a Linux device driver for it. This module is using SPI as the controlling line and has an interrupt line to indicate whether a card is ready. I know how to create a SPI device in Linux kernel and how to read data in the kernel when the interruption happens. But I have no idea on how to transfer the data to the user space (maybe need to create a device node for it), and how to give the user space a interruption to notify it. Does anyone have some suggestion?
One way you can go about this is by creating a devfs entry and then having the interested process open that device and receive asynchronous notification from the device driver using fasync.
Once you have the notification in user space you can notify other interested processes by any means you deem fit.
I am writing a small trimmed down example illustrating this feature.
On the driver side
/* Appropriate headers */
static int myfasync(int fd, struct file *fp, int on);
static struct fasync_struct *fasyncQueue;
static struct file_operations fops =
{
.open = charDriverOpen,
.release = charDriverClose,
.read = charDriverRead,
.write = charDriverWrite,
.unlocked_ioctl = charDriverCtrl,
// This will be called when the FASYNC flag is set
.fasync = myfasync,
};
static int __init charDriverEntry()
{
// Appropriate init for the driver
// Nothing specific needs to be done here with respect to
// fasync feature.
}
static int myfasync(int fd, struct file *fp, int on)
{
// Register the process pointed to by fp to the list
// of processes to be notified when any event occurs
return fasync_helper(fd, fp, 1, &fasyncQueue);
}
// Now to the part where we want to notify the processes listed
// in fasyncQueue when something happens. Here in this example I had
// implemented the timer. Not getting in to the details of timer func
// here
static void send_signal_timerfn(unsigned long data)
{
...
printk(KERN_INFO "timer expired \n");
kill_fasync(&fasyncQueue, SIGIO, POLL_OUT);
...
}
On the user land process side
void my_notifier(int signo, siginfo_t *sigInfo, void *data)
{
printf("Signal received from the driver expected %d got %d \n",SIGIO,signo);
}
int main()
{
struct sigaction signalInfo;
int flagInfo;
signalInfo.sa_sigaction = my_notifier;
signalInfo.sa_flags = SA_SIGINFO;
sigemptyset(&signalInfo.sa_mask);
sigaction(SIGIO, &signalInfo, NULL);
int fp,i;
fp = open("/dev/myCharDevice",O_RDWR);
if (fp<0)
printf("Failed to open\n");
/*New we will own the device so that we can get the signal from the device*/
// Own the process
fcntl(fp, F_SETOWN, getpid());
flagInfo = fcntl(fp, F_GETFL);
// Set the FASYNC flag this triggers the fasync fops
fcntl(fp, F_SETFL, flagInfo|FASYNC);
...
}
Hope this clears things up.
For more detailed reading I suggest you read this

kfree_skb() after skb_dequeue() freezes linux kernel

I'm implementing flow control in a custom protocol in the linux kernel. When I receive an ACK, I want to remove the acked packets from the write queue. Here's some code
for(i = (ack->sequence - qp->first_unack); i>0&&sk->sk_write_queue.qlen>0; i++){
skb_del = skb_dequeue(&sk->sk_write_queue);
qp->first_unack++;
kfree_skb(skb_del);
}
I get a kernel freeze from this code. Everything works well however, when I comment out the kfree(skb_del). Any ideas why is this happening? How else can I free up the memory?
As the skbs are queued to the socket you can use already provided socket APIs;
sk_eat_skb(struct sock *sk, struct sk_buff *skb, bool copied_early) // copied_ealy = 0
For more details you can track tcp_recvmsg, there properly you will get the impementation flow
Moreove why you are using custom APIS from the queuing/dequeuing loop on your own. Just go through the include/net/sock.h I hope you will get necessary details
This is probably because of double freeing skb_del.
Theoretically, before calling kfree_skb(skb_del) you can check the value of skb_del->users by doing refcount_read(&skb_del->users), and if skb_del->users is 0, then it means that skb_del has already been freed.
In practice, the kfree_skb() function doesn't set skb_del->users to 0 when skb_del is finally released (due to some optimization considerations), so after skb_del will be release it would stay 1, and you won't be able to know if skb_del has been released or not.
If you are still curious if this is a double-free issue and you are fine with making some changes in the skbuff infrastructure (just for this investigation) then we need to modify some skbuff functions.
WARNING: It's very easy to cause the kernel to crash when playing with this function, so be careful. But these modification works (in this way I've found a double-free of skb). Keep in mind that this is a suggestion only for investigating the double-free issue, and I've no idea if these modifications will effect your system in the long-run.
We'll modify the following functions (based on kernel v5.9.1):
skb_unref() // from include/linux/skbuff.h
__kfree_skb() // from net/core/skbuff.c
kfree_skb() // from net/core/skbuff.c
consume_skb() // from net/core/skbuff.c
Original skb_unref()
static inline bool skb_unref(struct sk_buff *skb)
{
if (unlikely(!skb))
return false;
if (likely(refcount_read(&skb->users) == 1))
smp_rmb();
else if (likely(!refcount_dec_and_test(&skb->users)))
return false;
return true;
}
Modified skb_unref()
static inline bool skb_unref(struct sk_buff *skb)
{
if (unlikely(!skb))
return false;
if (likely(refcount_read(&skb->users) == 1)) {
smp_rmb();
refcount_set(&skb->users, 0);
} else if (likely(!refcount_dec_and_test(&skb->users))) {
return false;
}
return true;
}
Original __kfree_skb()
void __kfree_skb(struct sk_buff *skb)
{
skb_release_all(skb);
kfree_skbmem(skb);
}
Modified __kfree_skb()
void __kfree_skb(struct sk_buff *skb)
{
if (!skb_unref(skb))
return;
skb_release_all(skb);
kfree_skbmem(skb);
}
Original kfree_skb()
void kfree_skb(struct sk_buff *skb)
{
if (!skb_unref(skb))
return;
trace_kfree_skb(skb, __builtin_return_address(0));
__kfree_skb(skb);
}
Modified kfree_skb()
void kfree_skb(struct sk_buff *skb)
{
//if (!skb_unref(skb))
// return;
trace_kfree_skb(skb, __builtin_return_address(0));
__kfree_skb(skb);
}
Original consume_skb()
void consume_skb(struct sk_buff *skb)
{
if (!skb_unref(skb))
return;
trace_consume_skb(skb);
__kfree_skb(skb);
}
Modified consume_skb()
void consume_skb(struct sk_buff *skb)
{
//if (!skb_unref(skb))
// return;
trace_consume_skb(skb);
__kfree_skb(skb);
}
Good luck in the investigation.
May god will be with you.

How to detect application terminate in kernel extension, Mac OS X

I am looking for an approach to detect application quit (e.g. cmd-q) in kernel space for processing in a network kernel extension.
More precisely:
While a process (e.g. terminal ping) is held in an IOLockSleep(... THREAD_ABORTSAFE), ctrl-c is able to release the lock.
Asking the proc_issignal(), it responses the sigmask(SIGINT).
Now I am looking for a way to detect another process quit, e.g. firefox (menu bar: Application quit (cmd-q)).
Here is what I tried:
#define FLAG(X) ((dispatch_source_get_data(src) & DISPATCH_PROC_##X) ? #X" " : "")
struct ProcessInfo {
int pid;
dispatch_source_t source;
};
// function called back on event
void process_termination_event(struct ProcessInfo* procinfo) {
dispatch_source_t src = procinfo->source;
printf("process_termination_event: %d \n", procinfo->pid);
printf("flags: %s%s\n", FLAG(EXIT), FLAG(SIGNAL));
dispatch_source_cancel(procinfo->source);
}
// function called back when the dispatch source is cancelled
void process_termination_finalize(struct ProcessInfo* procinfo) {
printf("process_termination_finalize: %d \n", procinfo->pid);
dispatch_release(procinfo->source);
}
// Monitor a process by pid, for termination
void MonitorTermination(int pid) {
struct ProcessInfo* procinfo = (struct ProcessInfo*)malloc(sizeof(struct ProcessInfo));
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t dsp = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, pid, DISPATCH_PROC_EXIT|DISPATCH_PROC_SIGNAL, queue);
procinfo->pid = pid;
procinfo->source = dsp;
dispatch_source_set_event_handler_f(procinfo->source, (dispatch_function_t)process_termination_event);
dispatch_source_set_cancel_handler_f(procinfo->source, (dispatch_function_t)process_termination_finalize);
dispatch_set_context(procinfo->source, procinfo);
dispatch_resume(procinfo->source);
}
int main(int argc, const char * argv[])
{
for (int i = 0; i < argc; ++i) {
pid_t pid = atoi(argv[i]);
printf("MonitorTermination: %d\n", pid);
fflush(stdout);
MonitorTermination(pid);
}
CFRunLoopRun();
return 0;
}
The process_termination_event will not invoke after cmd-q as explained above. Even after force quit.
The process itself is held in a loop within the network kernel extension function:
errno_t KEXT::data_out(void *cookie, socket_t so, const struct sockaddr *to, mbuf_t *data, mbuf_t *control, sflt_data_flag_t flags)
{
// at this point I would like to detect the app quit/termination signal.
while(PROCESS_IS_NOT_TEMINATING); // <-- pseudo code, actually held with IOLockSleep...
return 0;
}
I would really appreciate any help! Thanks in advance.
It may not be the way you've been thinking, but if you're in the kernel space, then I assume you're writing a kernel extension (kext). With a kernel extension, you can monitor Vnodes for executing applications. You may be able to use the File Scope instead.
In conjunction with a user-level application (daemon), the kext notifies the daemon that a process has begun execution and then monitors the termination of the launched application from the user-level daemon, using Grand Central Dispatch functions. If required, the user-application can notify the kext of the terminated app.
To monitor the termination from a user-level application, you can do something like this when you're notified of an application being executed: -
// pid and path provided from vNode scope kext...
void UserLevelApp::MonitorProcessTermination(int pid, const QString &path)
{
ProcessInfo* procinfo = new ProcessInfo;
procinfo->pid = pid;
procinfo->path = path;
procinfo->context = this;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t dsp = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, pid, DISPATCH_PROC_EXIT, queue);
dispatch_source_set_event_handler_f(dsp, (dispatch_function_t)process_termination_event);
dispatch_source_set_cancel_handler_f(dsp, (dispatch_function_t)process_termination_finalize);
procinfo->source = dsp;
dispatch_set_context(dsp, procinfo);
dispatch_resume(dsp);
}
// app terminated call-back function
void UserLevelApp::process_termination_event(struct ProcessInfo* procinfo)
{
dispatch_source_cancel(procinfo->source);
// example of how to use the context to call a class function
procinfo->context->SomeClassFunction(procinfo->pid, procinfo->path);
qDebug("App Terminated: %d, %s\n", procinfo->pid, procinfo->path.toUtf8().data());
}
// finalize callback function
void UserLevelApp::process_termination_finalize(struct ProcessInfo* procinfo)
{
dispatch_release(procinfo->source);
delete procinfo;
}
So each launched application, notified by the kext, has an event handler associated with it and when the application terminates, you get called back in the registered functions process_termination_event and process_termination_finalize
Whilst this method requires an associated user-level daemon application with the kext, that's not such a bad thing from a security and stability point of view.

Push Button press not detected in AVR

I have written a code that detects a button press, first time the button is pressed a LED glows and when next time it is pressed , the LED should switch off, in the same way if third time it is pressed the LED should again glow.
The problem is , the controller is able to detect the button press but instead of switching on the LED for long time, it just momentarily switches it ON then it again switches OFF. And further button presses are not detected.
Below is the code:
#include <avr/io.h>
#include <avr/delay.h>
void glow();
void off();
void switchScan();
int main()
{
DDRA=0x02; // 0000 0010 --> BIT 0=connected to switch whose other pin is connected to ground,, and BIT 1 is connected to LED with other pin of led connected to ground
PORTA=0x01; // 0000 0001---> Switch Input pulled up and LED output pulled down
while(1)
{
switchScan();
}
return 0;
}
void glow()
{
PORTA=PORTA|(1<<1);
}
void off()
{
PORTA=PORTA&(~(1<<1));
}
void switchScan()
{
static int counter=0;
if(~(PINA & 0x01))
{
counter++;
if(counter < 2)
glow();
else
{
counter--;
off();
}
}
}
The logic in your switchScan() function is flawed. glow() will only be executed one single time. See code comments:
void switchScan() {
static int counter=0;
if (~(PINA & 0x01)) {
counter++;
// 1st button press: counter will be 1
// 2nd and all following button presses: counter will be 2
if (counter < 2)
// can only be called once!
glow();
else {
// counter will always go from 2 to 1 at this point
counter--;
off();
}
}
}
However, you should also consider the de-bouncing that Brett mentioned in the comments.

Stopping an epoll runloop with kthread_stop

I'm using epoll in a kernel module.
I'm creating a kthread on module_init, and I want to stop it on module_exit.
However, this thread is always almost waiting in epoll_wait.
In my exit function, how can I stop the created thread even if it's waiting in epoll_wait?
This is my attempt, but every now and then it hangs, I assume because the interrupt doesn't get to the thread before kthread_stop does.
struct task_struct *thread;
bool should_stop = false;
static int __init init(void) {
thread = kthread_run(run, NULL, "hora");
return 0;
}
static void __exit exit(void) {
l("end");
should_stop = true;
force_sig(SIGUSR1, thread);
l("kthread_stop");
kthread_stop(thread);
l("ended");
}
int run(void *data) {
...
while (true) {
int nfd = epoll_wait(epfd, events, MAX_EVENTS, -1);
l("got event");
if (should_stop) {
l("should_stop");
break;
}
...
}
...
l("closed");
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) {
schedule();
set_current_state(TASK_INTERRUPTIBLE);
}
set_current_state(TASK_RUNNING);
l("exiting");
return 0;
}
The output is:
end
kthread_stop
got event
should_stop
closed
exiting
ended
I've looked into eventfd as an alternative to sending a signal, but it's quite a bit of work (only a couple of eventfd functions are exported) and I don't know for sure whether it'll solve this.
Any insights and help much appreciated.

Resources