at /rustc/44f5180584404d18058cbbf224c55255db4fdcbb/library/alloc/src/alloc.rs:177
13 0x0800b156 in alloc::alloc::{impl#1}::allocate (self=0x2001fe1c, layout=...)
at /rustc/44f5180584404d18058cbbf224c55255db4fdcbb/library/alloc/src/alloc.rs:237
14 0x0800b318 in alloc::raw_vec::finish_grow (new_layout=...,
current_memory=..., alloc=0x2001fe1c)
at /rustc/44f5180584404d18058cbbf224c55255db4fdcbb/library/alloc/src/raw_vec.rs:476
15 0x0800b69a in alloc::raw_vec::RawVec<u8, alloc::alloc::Global>::grow_amortized<u8, alloc::alloc::Global> (self=0x2001fe1c, len=0, additional=1)
at /rustc/44f5180584404d18058cbbf224c55255db4fdcbb/library/alloc/src/raw_vec.rs:405
16 0x0800b752 in alloc::raw_vec::RawVec<u8, alloc::alloc::Global>::reserve_for_push<u8, alloc::alloc::Global> (self=0x2001fe1c, len=0)
at /rustc/44f5180584404d18058cbbf224c55255db4fdcbb/library/alloc/src/raw_vec.rs:303
17 0x0800b83e in alloc::vec::Vec<u8, alloc::alloc::Global>::push<u8, alloc::alloc::Global> (
self=0x2001fe1c, value=35)
at /rustc/44f5180584404d18058cbbf224c55255db4fdcbb/library/alloc/src/vec/mod.rs:1840
18 0x0800a7d6 in freertos_rust::utils::str_from_c_string (str=0x358) at src/utils.rs:59
19 0x0800abe0 in freertos_rust::hooks::vAssertCalled (file_name_ptr=0x358, line=134272464)
at src/hooks.rs:31
20 0x080040ac in vPortValidateInterruptPriority ()
at FreeRTOS-Kernel/portable/GCC/ARM_CM4F/port.c:856
21 0x08004996 in xQueueGenericSendFromISR (xQueue=0x20000140 <ucHeap+8>, pvItemToQueue=0x2001ff5e,
pxHigherPriorityTaskWoken=0x0, xCopyPosition=0) at FreeRTOS-Kernel/queue.c:1119
22 0x080027da in freertos_rs_queue_send_isr (queue=0x20000140 <ucHeap+8>, item=0x2001ff5e,
xHigherPriorityTaskWoken=0x0)
at /home/chkolli/.cargo/registry/src/index.crates.io-6f17d22bba15001f/freertos-rust-0.1.2/src/freertos/shim.c:244
23 0x08001af6 in freertos_rust::queue::Queue::send_from_isr (self=0x200001a8 <ucHeap+112>,
context=0x2001ff98, item=1)
at /home/chkolli/.cargo/registry/src/index.crates.io-6f17d22bba15001f/freertos-rust-0.1.2/src/queue.rs:54
The reason for this is vAssertCalled function that attempts to allocate memory to create a String.
If I remove the corresponding lines from vAssertCalled, my program does not panic but the waiting thread is never woken up. The reason for this is that listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) call in xQueueGenericSendFromISR always returns pdTRUE.
My code (STM32F411RE):
#![no_std]
#![no_main]
////////////////////////////////////////////////////////////////////////////////
use core::cell::RefCell;
use core::ops::DerefMut;
use core::ops::Deref;
use cortex_m::interrupt::Mutex;
use cortex_m_rt::entry;
use freertos_rust::*;
use panic_halt as _;
use stm32f4xx_hal;
use stm32f4xx_hal::gpio::{GpioExt};
use stm32f4xx_hal::interrupt;
use stm32f4xx_hal::pac::USART1;
use stm32f4xx_hal::prelude::*;
use stm32f4xx_hal::serial::{Config, Event, Serial};
extern crate alloc;
use alloc::sync::Arc;
////////////////////////////////////////////////////////////////////////////////
// Global allocator for memory allocations.
#[global_allocator]
static GLOBAL: FreeRtosAllocator = FreeRtosAllocator;
// Required by USART1 interrupt handler
static UART_SERVICE_CHANNEL: Mutex<RefCell<Option<Serial<USART1>>>> =
Mutex::new(RefCell::new(None));
static UART_MESSAGE_QUEUE: Mutex<RefCell<Option<Arc<Queue<u8>>>>> = Mutex::new(RefCell::new(None));
////////////////////////////////////////////////////////////////////////////////
#[entry]
fn main() -> ! {
let dp = stm32f4xx_hal::pac::Peripherals::take().unwrap();
let rcc = dp.RCC.constrain();
let clocks = rcc
.cfgr
.sysclk(100.MHz())
.hclk(100.MHz())
.pclk1(50.MHz())
.pclk2(100.MHz())
.freeze();
let gpioa = dp.GPIOA.split();
let pin_service_channel_tx = gpioa.pa9.into_alternate();
let pin_service_channel_rx = gpioa.pa10.into_alternate();
let service_channel_uart = dp
.USART1
.serial(
(pin_service_channel_tx, pin_service_channel_rx),
Config::default()
.baudrate(115200.bps())
.wordlength_8()
.parity_none(),
&clocks,
)
.unwrap()
.with_u8_data();
cortex_m::interrupt::free(|cs| {
UART_SERVICE_CHANNEL
.borrow(cs)
.replace(Some(service_channel_uart))
});
let uart_message_queue = Arc::new(Queue::<u8>::new(4).unwrap());
// To be used from the uart interrupt handler.
cortex_m::interrupt::free(|cs| {
UART_MESSAGE_QUEUE
.borrow(cs)
.replace(Some(uart_message_queue.clone()))
});
Task::new()
.name("uart_rx")
.stack_size(1024)
.priority(TaskPriority(5))
.start(move || {
// Enable service channel uart and then proceed to wait for data.
cortex_m::interrupt::free(|cs| {
if let Some(ref mut uart) = UART_SERVICE_CHANNEL.borrow(cs).borrow_mut().deref_mut()
{
uart.listen(Event::Rxne);
unsafe {
// Enable USART1 interrupt in NVIC
cortex_m::peripheral::NVIC::unmask(stm32f4xx_hal::interrupt::USART1);
}
}
});
loop {
let _ = uart_message_queue.receive(Duration::infinite());
cortex_m::interrupt::free(|cs| {
if let Some(ref mut uart) =
UART_SERVICE_CHANNEL.borrow(cs).borrow_mut().deref_mut()
{
if let Ok(byte) = uart.read() {
// Do something with the received byte.
}
}
});
}
})
.unwrap();
FreeRtosUtils::start_scheduler();
}
#[interrupt]
fn USART1() {
cortex_m::interrupt::free(|cs| {
if let Some(ref mut uart) = UART_SERVICE_CHANNEL.borrow(cs).borrow_mut().deref_mut() {
if uart.is_rx_not_empty() {
let _ = UART_MESSAGE_QUEUE
.borrow(cs)
.borrow()
.deref()
.as_ref()
.unwrap()
.send_from_isr(&mut InterruptContext::new(), 1);
}
}
});
}
Sending a message from an ISR through send_from_isr method does not work, but instead it causes panic:
(gdb) bt
0 panic_halt::panic (_info=0x2001f8ac) at src/lib.rs:32
1 0x0800bf94 in core::panicking::panic_fmt () at library/core/src/panicking.rs:64
2 0x0800c0be in core::result::unwrap_failed () at library/core/src/result.rs:1750
3 0x0800bb7e in core::result::Result<alloc::string::String, freertos_rust::base::FreeRtosError>::unwrap<alloc::string::String, freertos_rust::base::FreeRtosError> (self=...)
4 0x0800abf0 in freertos_rust::hooks::vAssertCalled (file_name_ptr=0x1cd, line=134272464)
5 0x08003f24 in vPortEnterCritical () at FreeRTOS-Kernel/portable/GCC/ARM_CM4F/port.c:461
6 0x08002d0c in xTaskResumeAll () at FreeRTOS-Kernel/tasks.c:2193
7 0x08003a52 in pvPortMalloc (xWantedSize=16) at FreeRTOS-Kernel/portable/MemMang/heap_4.c:287
8 0x080026c6 in freertos_rs_pvPortMalloc (xWantedSize=8)
9 0x0800ac78 in freertos_rust::allocator::{impl#0}::alloc (self=0x800ce70, layout=...)
10 0x08000228 in ::_::__rg_alloc (arg0=8, arg1=1) at src/main.rs:25
11 0x0800ad7a in alloc::alloc::alloc ()
12 alloc::alloc::Global::alloc_impl (self=0x2001fe1c, layout=..., zeroed=false)
13 0x0800b156 in alloc::alloc::{impl#1}::allocate (self=0x2001fe1c, layout=...)
14 0x0800b318 in alloc::raw_vec::finish_grow (new_layout=...,
15 0x0800b69a in alloc::raw_vec::RawVec<u8, alloc::alloc::Global>::grow_amortized<u8, alloc::alloc::Global> (self=0x2001fe1c, len=0, additional=1)
16 0x0800b752 in alloc::raw_vec::RawVec<u8, alloc::alloc::Global>::reserve_for_push<u8, alloc::alloc::Global> (self=0x2001fe1c, len=0)
17 0x0800b83e in alloc::vec::Vec<u8, alloc::alloc::Global>::push<u8, alloc::alloc::Global> (
18 0x0800a7d6 in freertos_rust::utils::str_from_c_string (str=0x358) at src/utils.rs:59
19 0x0800abe0 in freertos_rust::hooks::vAssertCalled (file_name_ptr=0x358, line=134272464)
20 0x080040ac in vPortValidateInterruptPriority ()
21 0x08004996 in xQueueGenericSendFromISR (xQueue=0x20000140 <ucHeap+8>, pvItemToQueue=0x2001ff5e,
22 0x080027da in freertos_rs_queue_send_isr (queue=0x20000140 <ucHeap+8>, item=0x2001ff5e,
23 0x08001af6 in freertos_rust::queue::Queue::send_from_isr (self=0x200001a8 <ucHeap+112>,
The reason for this is vAssertCalled function that attempts to allocate memory to create a String.
If I remove the corresponding lines from vAssertCalled, my program does not panic but the waiting thread is never woken up. The reason for this is that listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) call in xQueueGenericSendFromISR always returns pdTRUE.
My code (STM32F411RE):