How do I wake the core from sleep upon receiving data on the USART while using the ASF USART driver? Since we’re using the ASF peripheral drivers, I know the drivers handle all of the DMA interrupts and I’m not supposed to make my own handlers for them. How can I wake up the core if it’s in sleep mode when the DMA buffer is changed/or handle the characters as soon as they come in? Just not quite sure about how to merge the two functionalities together. It seems to me right now that there’s not really a way to do this without polling the freertos_usart_read_packet() function and seeing what the return value is. I assume the only way to do this is to modify the ASF driver for my application?
In answering I’m making two assumptions:
You are using the “FreeRTOS peripheral control” ASF functions that are included in the ASF, rather than the ASF functions that don’t use FreeRTOS functionality.
You are placing the CPU into sleep mode using the FreeRTOS tickless idle feature.
If so, then I’m not sure you have to do anything because FreeRTOS handles the sleep modes for you.
The peripheral control functions have a mode that allows you to enter the Blocked state (so the task is not running or consuming and CPU time) while it is waiting for a character to be received. If all the FreeRTOS tasks are blocked then the tickless idle mode will automatically put the CPU into a sleep mode. By default that is the lightest sleep mode, so the DMA will still be running. When the DMA receives more data the DMA end interrupt will bring the CPU out of sleep mode, at which point FreeRTOS will start running again, unblock your task, and away you go…
Very cool, I didn’t realize that but it makes perfect sense. At this time I am not using tickless idle.
- Is tickless idle necessary for this to work? (we have considered using it in a similar application but it’s not necessary that we sleep the chip at this time)
The peripheral control functions have a mode that allows you to enter the Blocked state (so the task is not running or consuming and CPU time) while it is waiting for a character to be received.
- Is this “mode” something that is automatically handled inside the freertos_usart_serial_read_packet() function or is there something I need to do to enable it? Also, what would I use as a blocking condition? I do have the semaphore that is created on freertos_usart_serial_init but my understanding is that it’s only for waiting until the resource is no longer in use by another task/operation.
Tickless idle is optional and generally only used by systems where power consumption is a concern. It is not related to the FreeRTOS peripheral control functions inside the ASF - it just turns the tick off and sleeps when it sees there is nothing to do. When the task using the ASF functions are blocked on a semaphore, there is nothing to do until the semaphore is available, the scheduler recognises this (assuming tickless idle is turned on) and sleeps.
So do I need to create a separate semaphore for the read function? How is this different from the notification_semaphore in the write_async function? My understanding is that the notification_sempahore is only for writes. Or is it for accessing the USART altogether?
Reads can be blocking too. Take a look at the examples in the ASF (search for “freertos peripheral control” in the wizard) and also in the app note: http://www.atmel.com/images/doc42049.pdf
So perhaps if I want to be able to read and write at any time without delay (including read when woken from sleep state by interrupt) then would this make sense:
- A task dedicated to reading the USART and processing incoming data
- A task dedicated to writing to the USART with a queue of char* to bring data to write in from other sources
It doesn’t seem that having both of these in the same task makes sense since one will be blocking and prevent the other from running most of the time.
Do you have a better/another suggestion?
Also, I just want to ask/point out that pursuant to a previous point of my questions - the init function only takes a Usart* argument… not a Uart* argument to work with the UART peripherals. Can I cast this or will it cause any issues you’re aware of?
The two peripherals are distinct, with different registers, so unfortunately you can’t just cast one to the other.
You can write to the USART form any task, it is not necessary to have a task dedicated to this. The semaphores and notification systems ensure access to the USART is serialised. You don’t need to block when writing to the UART as you can return from the write function before the data has been sent - with the notification semaphore letting you know when the data has actually been sent. You may need to block when accessing the UART if another task is already using it though - that mechanism is built into the write function.
only takes a Usart* argument… not a Uart* argument to work with the UART peripherals
Are you aware of any way to make the included FreeRTOS functions work with the UART peripheral in addition to the USART peripheral?
From memory the UART and USART are two distinct IPs on the device, with
different registers, etc., so unfortunately no you can’t cast one to the
It would need to be implemented separately just like the existing TWI, USART and SPI modules are implemented separately. Although it could probably be heavily based on the existing USART module.
Gotcha. Will do. Any idea if Atmel is planning on doing this soon? I really don’t want to do it on my own and then find out they did it in a month or two.
Also - I don’t see the USART’s CTS/RTS and other signals being asserted. I assume this simply isn’t built into the existing module and is something I have to do myself as well?
i looked into the document http://www.atmel.com/images/doc42049.pdf . There are different initialisation APIs to use spi and twi. I am not using these APIs instead i am using standard initialisation and other APis for twi interface. Can this be a factor of twim not working in freeetos?
my initialisation: init_test()
from the document: freertos_twi_if freertos_twi_master_init( Twi *p_twi,
const freertos_peripheral_options_t * const freertos_driver_parameters )
If you are using the send and receive functions described in doc42049.pdf then you must also use the initialisation functions described in the same document.
If you are using the standard asf send and receive functions then you must also use the standard asf initialisation functions. The standard asf functions are not necessarily going to be as multi-tasking friendly - for example they may poll bits rather than use events. Normally the standard asf functions use global interrupt disable and enable for critical sections, whereas FreeRTOS uses priority masking, so the two will not interfere with each other.
Ok i understood. In my case there is a twi communication between a chip and a master board (sam4l xplained pro), as a task in FREERTOS then there will be transmit interrupt , recieve interrupt and nack interrupt. But after transmit interrupt, device goes to infinite sleep instead of disabling transmit interrupt and acknowledging recieve interrupt in freertos.When the same thing done under standalone program everything runs normal and device communicates normal. Then what could be the possible reason that do this change in functionality . As you said asf functions use global interrupts so freertos should execute the task as usual while using asf functions. Correct me if i am missing something obvious.
What do you mean by “goes into infinite sleep”? The chip is going into a low power mode and not coming out?
No i haven’t done anything for interrupt priorities. I have just added a task and that task wants to read chip registers by calling driver apis thats it.
No i am not writing my own interrupts routines. These routines are provided as a driver for twim read, write or NACK by atmel .
Yes there is a low power flag in the driver where it goes and not coming out.
No i haven’t done anything for interrupt priorities. I have just added a task
and that task wants to read chip registers by calling driver apis thats it.
Please follow the instructions on the pages already linked as you must set the interrupt priorities for reliable operation. I strongly recommend using a recent version of FreeRTOS (7.6.0 or later) with configASSERT() defined as that will check the interrupt priorities for you.