Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sending message from ISR does not work #63

Closed
koija opened this issue Nov 6, 2023 · 1 comment
Closed

Sending message from ISR does not work #63

koija opened this issue Nov 6, 2023 · 1 comment

Comments

@koija
Copy link

koija commented Nov 6, 2023

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=...)
at /rustc/44f5180584404d18058cbbf224c55255db4fdcbb/library/core/src/result.rs:1090
#4 0x0800abf0 in freertos_rust::hooks::vAssertCalled (file_name_ptr=0x1cd, line=134272464)
at src/hooks.rs:31
#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)
at /home/chkolli/.cargo/registry/src/index.crates.io-6f17d22bba15001f/freertos-rust-0.1.2/src/freertos/shim.c:24
#9 0x0800ac78 in freertos_rust::allocator::{impl#0}::alloc (self=0x800ce70, layout=...)
at src/allocator.rs:16
#10 0x08000228 in ::
::__rg_alloc (arg0=8, arg1=1) at src/main.rs:25
#11 0x0800ad7a in alloc::alloc::alloc ()
at /rustc/44f5180584404d18058cbbf224c55255db4fdcbb/library/alloc/src/alloc.rs:95
#12 alloc::alloc::Global::alloc_impl (self=0x2001fe1c, layout=..., zeroed=false)
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_growalloc::alloc::Global (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);
            }
        }
    });
}
@koija
Copy link
Author

koija commented Nov 6, 2023

Closed as invalid.

@koija koija closed this as completed Nov 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant