smfsw / cqueue Goto Github PK
View Code? Open in Web Editor NEWQueue handling library (written in plain c)
License: BSD 3-Clause "New" or "Revised" License
Queue handling library (written in plain c)
License: BSD 3-Clause "New" or "Revised" License
Hello sir, at first thank you for your library!
I know that you recommended to use pop/push functions carefully when put them in interrupt handlers. But in my application (controller STM32F103C8T6) I want to push CAN frames in RX queue in interrupt (when receiving new frame) and pop in main while
loop. The application protocol (UAVCAN) is responsible for assembly of CAN frames in appropriate transfer.
I declare next FIFO queue (as global variable):
Queue_t canrx_queue;
The problem is that sometimes I get wrong (corrupt) data after doing q_pop
(this happens in approximately 50-60% of cases). This function is placed in main loop:
void receive_transfers(CanardInstance *const canard)
{
CanardFrame rxf;
CanardTransfer transfer;
if (q_isEmpty(&canrx_queue))
{
return;
}
q_pop(&canrx_queue, &rxf); // <---- this rxf frame has corrupt payload sometimes
const int8_t result = canardRxAccept2(canard, &rxf, 0, &transfer, NULL);
if (result < 0)
{
usart2::usart_send_string("HERE!!!\n");
// An error has occurred: either an argument is invalid or we've ran out of memory.
return;
}
else if (result == 1)
{
// usart2::usart_send_string("HERE!\n");
process_received_transfer(&transfer);
canard->memory_free(canard, (void *)transfer.payload);
}
else
{
uint8_t *check = (uint8_t *)rxf.payload;
uint8_t check_var = *check;
usart2::usart_send_int(check_var, true);
// GREEN_LED_ON;
// GREEN_LED_OFF;
}
}
This is how I put frames in FIFO in the interrupt:
extern "C"
{
void USB_LP_CAN1_RX0_IRQHandler(void)
{
if ((CAN1->RF0R & CAN_RF0R_FMP0) || (CAN1->RF1R & CAN_RF1R_FMP1))
{
uint32_t extended_can_id;
size_t payload_size;
uint8_t payload[8] = {0};
bxCANPop(0, &extended_can_id, &payload_size, payload);
CanardFrame rxf = {timer2::get_micros(), extended_can_id, payload_size, payload};
q_push(&canrx_queue, &rxf);
}
}
}
Note that I have tried to invoke q_pop
function right after q_push
in the above interrupt handler: everything was fine (payload was correct). Also note that this interrupt is invoked with 1 second period.
The CanardFrame
is defined as follows:
typedef struct
{
/// For RX frames: reception timestamp.
/// For TX frames: transmission deadline.
/// The time system may be arbitrary as long as the clock is monotonic (steady).
CanardMicrosecond timestamp_usec;
/// 29-bit extended ID. The bits above 29-th shall be zero.
uint32_t extended_can_id;
/// The useful data in the frame. The length value is not to be confused with DLC!
/// If the payload is empty (payload_size = 0), the payload pointer may be NULL.
/// For RX frames: the library does not expect the lifetime of the pointee to extend beyond the point of return
/// from the API function. That is, the pointee can be invalidated immediately after the frame has been processed.
/// For TX frames: the frame and the payload are allocated within the same dynamic memory fragment, so their
/// lifetimes are identical; when the frame is freed, the payload is invalidated.
/// A more detailed overview of the dataflow and related resource management issues is provided in the API docs.
size_t payload_size;
const void* payload;
} CanardFrame;
What am I doing wrong?
Hi,
my use case is accumulation of daily rainfall data in a FIFO.
I get the accumulated rainfall data from a sensor at a rate of e.g. 30 minutes. While I'm at the same day as the previous record, I would like to update the last entry pushed to the queue. After the day has changed, I would like to push a new record to the queue.
Two solution come into my mind:
q_delPrev()
), then push new recordq_update()
)Is this function of general interest? Which way would you prefer? Any suggestions on the naming?
Thanks in advance!
Regards
Matthias
When I installed v1.6 of this library using the Arduino IDE, it did not include the function q_peekIdx
.
I cloned this repository directly, and put it in place of the directory libraries/cQueue
, and the function is now available and works.
I'm not sure this is a problem the dev here can deal with, but I thought I should record it somewhere.
Hi,
I'd like to have a variant of q_init() which uses a statically allocated chunk of memory.
Basically, it should be sufficient to replace
q->queue = (uint8_t *) malloc(size);
by
q->queue = (uint8_t *) buf;
where uint8_t * buf is passed as a parameter.
The reason for my request is, that I would like to store the buffer and the queue_t structure in the ESP32's non-volatile RAM (RTC RAM), e.g.
RTC_DATA_ATTR Queue_t weather_logger;
typedef struct strRec {
float temperature;
float humidity;
float pressure;
} Rec;
// FIFO for 24 hours; updated every hour
RTC_DATA_ATTR Rec weather_logger_data[24] ;
What do you think?
Best regards
Matthias
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.