I have been working on a project in which the analog values are sampled at a particular frequency and stored in an array. Then the value will be sent to user application ESP32 using BLE. But I got stuck in this error.
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:1443
(xQueueGenericReceive)- assert failed! abort() was called at PC
0x4008e1d5 on core 1
Backtrace: 0x40091b38:0x3ffe0b20 0x40091d69:0x3ffe0b40
0x4008e1d5:0x3ffe0b60 0x400d1a2d:0x3ffe0ba0 0x4008e525:0x3ffe0be0
Rebooting... ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0,
SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:1044
load:0x40078000,len:8896 load:0x40080400,len:5816 entry 0x400806ac
I am Using Esp32arduino and FreeRTOS for programming. The error is in the semaphore from the interrupt but I couldn't be able to find out exact solution. Please help me out guys.
#include <ArduinoJson.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#if CONFIG_FREERTOS_UNICORE
static const BaseType_t app_cpu = 0;
#else
static const BaseType_t app_cpu = 1;
#endif
//ADC Related Global Variables
static const uint16_t timer_divider = 80;
static const uint64_t timer_max_count = 1000;
static const int adc_pin = A0;
static const int BUF_SIZE = 1000;
static int buf[BUF_SIZE];
int Buff_Len = 0;
static int Read = 0;
static int Write = 0;
static int count = 0;
static float avg = 0;
int i = 0;
int BLE_flag = 0;
String cmd;
static hw_timer_t *timer = NULL;
static uint16_t val;
static int count1 = 0;
static SemaphoreHandle_t bin_sem = NULL;
static SemaphoreHandle_t bin_sem2 = NULL;
static portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
//ADC Related Global Variables
//BLE Global Variable
char Reading[4];
BLEServer *pServer = NULL;
BLECharacteristic *pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
//Declaration BLE necessary Classes
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
class MyServerCallbacks:public BLEServerCallbacks
{
void onConnect (BLEServer * pServer)
{
deviceConnected = true;
};
void onDisconnect (BLEServer * pServer)
{
deviceConnected = false;
}
};
//BLE Global Variables
//Task Section
void IRAM_ATTR onTimer ()
{
//sampling
xSemaphoreGiveFromISR (bin_sem2, &task_woken);
if (task_woken)
{
portYIELD_FROM_ISR ();
}
}
void move_to_Queue (void *parameters)
{
while (1)
{
xSemaphoreTake (bin_sem2, portMAX_DELAY);
if (Buff_Len == BUF_SIZE || count1 > 2000)
{
Serial.println ("Buffer is full");
xSemaphoreGive (bin_sem);
}
else
{
// storing the instantaneous sample value to buffer
}
}
}
void BLE_Task (void *parameters)
{
while (1) {
xSemaphoreTake (bin_sem, portMAX_DELAY);
Serial.println ("BLE");
// sending the data\lu
delay (10); // bluetooth stack will go into congestion, if too many packets are sent
}
}
Serial.println ();
}
}
void setup ()
{
// put your setup code here, to run once:
Serial.begin (115200);
vTaskDelay (1000 / portTICK_PERIOD_MS);
//BLE Declarations
BLEDevice::init ("UART Service");
pServer = BLEDevice::createServer ();
pServer->setCallbacks (new MyServerCallbacks ());
BLEService *pService = pServer->createService (SERVICE_UUID);
pTxCharacteristic = pService->createCharacteristic (CHARACTERISTIC_UUID_TX,
BLECharacteristic::
PROPERTY_NOTIFY);
pTxCharacteristic->addDescriptor (new BLE2902 ());
pService->start ();
pServer->getAdvertising ()->start ();
Serial.println ("Waiting a client connection to notify...");
//BLE Declaration
//ADC Semaphore and Timer Declarations
bin_sem = xSemaphoreCreateBinary ();
bin_sem2 = xSemaphoreCreateBinary ();
if (bin_sem == NULL || bin_sem2 == NULL)
{
Serial.println ("Could not create semaphore");
ESP.restart ();
}
xTaskCreatePinnedToCore (move_to_Queue,
"move_to_Queue", 1024, NULL, 2, NULL, app_cpu);
xTaskCreatePinnedToCore (BLE_Task,
"BLE_Task", 2048, NULL, 2, NULL, app_cpu);
timer = timerBegin (0, timer_divider, true);
// Provide ISR to timer (timer, function, edge)
timerAttachInterrupt (timer, &onTimer, true);
// At what count should ISR trigger (timer, count, autoreload)
timerAlarmWrite (timer, timer_max_count, true);
// Allow ISR to trigger
timerAlarmEnable (timer);
vTaskDelete (NULL);
}
void loop ()
{
// put your main code here, to run repeatedly:
}
`
Whole code: https://pastebin.com/K8ppkG28
Thanks in advance guys
First, look at my code (very simple, just to test)
struct task_struct *test_task;
int test_func(void *arg)
{
uint64_t cur = 0; //current time
uint64_t last = 0; //last time
while(!kthread_should_stop())
{
cur = get_cycle();
if (cur - last > 2410000000)
{
printk(KERN_INFO "this time: %llu\n", cur);
last = cur;
}
}
return 0;
}
void run_thread(void)
{
struct sched_param param;
param.sched_priority = 1;
test_task = kthread_create(&test_func, NULL, "MY_test");
kthread_bind(test_task, 2); //just use cpu 2
sched_setscheduler(test_task, SCHED_RR, ¶m);
wake_up_process(test_task);
printk(KERN_INFO"OK, Kernel Thread : %s, Running\n", test_task->comm);
}
static int __init test_init(void)
{
run_thread();
return 0;
}
static void __exit test_exit(void)
{
kthread_stop(test_task);
}
module_init(test_init);
module_exit(test_exit);
These are all code, The problem occurs when I remove this module, the system would crash.
I think it should be a problem on my understanding of the core processes, please help gets advice, thank you!
Please forgive me for this chinese english....
I've a function I wrote in order to run a given function on all processors. It works perfectly well in all cases except the following case:
When I try to use it within a kprobe that I registered.
Here's some code:
static DEFINE_MUTEX(entryMutex);
static struct kretprobe my_kprobe = {
.entry_handler = (kprobe_opcode_t *) NULL,
.handler = (kprobe_opcode_t *) process_entry_callback,
.maxactive = 1000,
.data_size = 0
};
static int driver_init(void)
{
my_kprobe.kp.addr = (kprobe_opcode_t*)kallsyms_lookup_name("sys_execve");
if ((ret = register_kretprobe(&my_kprobe)) < 0)
return -1;
return 0;
}
void foo(void* nothing)
{
printk("In foo\n");
}
static int process_entry_callback(struct kretprobe_instance* instance, struct pt_regs* regs)
{
mutex_lock(&entryMutex);
for(int i = 0; i < 4; ++i) // assumes there are 4 processors
run_func(foo, NULL, i);
mutex_unlock(&entryMutex);
return 0;
}
void run_func_wrap(struct function_data* data)
{
data->func(data->context);
wake_up_process(data->waiting_task);
*(data->condition) = TRUE;
}
void run_func(SCHEDULED_FUNC func, void *context, int processor)
{
struct function_data data;
struct task_struct* th;
BOOLEAN condition = FALSE;
wait_queue_head_t queue;
init_waitqueue_head(&queue);
data.func = func;
data.waiting_task = current;
data.context = context;
data.condition = &condition;
th = kthread_create(sched_func_wrap, &data, "th");
kthread_bind(th, processor);
wake_up_process(th);
wait_event(queue, condition);
}
F
After the call to 'run_func' in process_entry_callback I can no longer run any programs. Every time I start a new program it just stuck. After a while I get 'processor lockup' warning in the system log.
I suspect that it has something to do with the IRQ levels.
Any suggestions ?
EDIT:
It also happens when using the following function:
smp_call_function_single
which can be found in smp.c # the Linux kernel source code.
instead of my function:
run_func
Hello I am learning how to use the Uart by using interrupts in Nios and I am not sure how to start. I have made it in polling, but I am not sure how to start using interrupts.
Any help would be appreciated
Here is my code
#include <stdio.h> // for NULL
#include <sys/alt_irq.h> // for irq support function
#include "system.h" // for QSYS defines
#include "nios_std_types.h" // for standard embedded types
#define JTAG_DATA_REG_OFFSET 0
#define JTAG_CNTRL_REG_OFFSET 1
#define JTAG_UART_WSPACE_MASK 0xFFFF0000
#define JTAG_UART_RV_BIT_MASK 0x00008000
#define JTAG_UART_DATA_MASK 0x000000FF
volatile uint32* uartDataRegPtr = (uint32*)JTAG_UART_0_BASE;
volatile uint32* uartCntrlRegPtr = ((uint32*)JTAG_UART_0_BASE +
JTAG_CNTRL_REG_OFFSET);
void uart_SendByte (uint8 byte);
void uart_SendString (uint8 * msg);
//uint32 uart_checkRecvBuffer (uint8 *byte);
uint32 done = FALSE;
void uart_SendString (uint8 * msg)
{
int i = 0;
while(msg[i] != '\0')
{
uart_SendByte(msg[i]);
i++;
}
} /* uart_SendString */
void uart_SendByte (uint8 byte)
{
uint32 WSPACE_Temp = *uartCntrlRegPtr;
while((WSPACE_Temp & JTAG_UART_WSPACE_MASK) == 0 )
{
WSPACE_Temp = *uartCntrlRegPtr;
}
*uartDataRegPtr = byte;
} /* uart_SendByte */
uint32 uart_checkRecvBuffer (uint8 *byte)
{
uint32 return_value;
uint32 DataReg = *uartDataRegPtr;
*byte = (uint8)(DataReg & JTAG_UART_DATA_MASK);
return_value = DataReg & JTAG_UART_RV_BIT_MASK;
return_value = return_value >> 15;
return return_value;
} /* uart_checkRecvBuffer */
void uart_RecvBufferIsr (void* context)
{
} /* uart_RecvBufferIsr */
int main(void)
{
uint8* test_msg = (uint8*)"This is a test message.\n";
//alt_ic_isr_register ( ); // used for 2nd part when interrupts are enabled
uart_SendString (test_msg);
uart_SendString ((uint8*)"Enter a '.' to exist the program\n\n");
while (!done)
{
uint8 character_from_uart;
if (uart_checkRecvBuffer(&character_from_uart))
{
uart_SendByte(character_from_uart);
}
// do nothing
} /* while */
uart_SendString((uint8*)"\n\nDetected '.'.\n");
uart_SendString((uint8*)"Program existing....\n");
return 0;
} /* main */
I am suppose to use the uart_RecvBufferIsr instead of uart_checkRecvBuffer. How can tackle this situation?
You will need to register your interrupt handler by using alt_ic_isr_register(), which will then be called when an interrupt is raised. Details can be found (including some sample code) in this NIOS II PDF document from Altera.
As far as modifying your code to use the interrupt, here is what I would do:
Remove uart_checkRecvBuffer();
Change uart_RecvBufferIsr() to something like (sorry no compiler here so can't check syntax/functioning):
volatile uint32 recv_flag = 0;
volatile uint8 recv_char;
void uart_RecvBufferIsr(void *context)
{
uint32 DataReg = *uartDataRegPtr;
recv_char = (uint8)(DataReg & JTAG_UART_DATA_MASK);
recv_flag = (DataReg & JTAG_UART_RV_BIT_MASK) >> 15;
}
The moral of the story with the code above is that you should keep your interrupts as short as possible and let anything that is not strictly necessary to be done outside (perhaps by simplifying the logic I used with the recv_char and recv_flag).
And then change your loop to something like:
while (!done)
{
if (recv_flag)
{
uart_SendByte(recv_byte);
recv_flag = 0;
}
}
Note that there could be issues with what I've done depending on the speed of your port - if characters are received too quickly for the "while" loop above to process them, you would be losing some characters.
Finally, note that I declared some variables as "volatile" to prevent the compiler from keeping them in registers for example in the while loop.
But hopefully this will get you going.
I handle SIGSEGV by code:
int C()
{
int *i = NULL;
*i = 10; // Crash there
}
int B()
{
return C();
}
int A()
{
return B();
}
int main(void)
{
struct sigaction handler;
memset(&handler,0,sizeof(handler));
handler.sa_sigaction = handler_func;
handler.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV,&handler,NULL);
return(C());
}
Where handler code are:
static int handler_func(int signal, siginfo_t info, void* rserved)
{
const void* stack[MAX_DEPTH];
StackCrowlState state;
state.addr = stack;
state.count = MAX_DEPTH;
_Unwind_Reason_Code code = _Unwind_Backtrace(trace_func,&state);
printf("Stack trace count: %d, code: %d\n",MAX_DEPTH - state.count, code);
kill(getpid(),SIGKILL);
}
static _Unwind_Reason_Code trace_func(void* context, void* arg)
{
StackCrowlState *state = (StackCrowlState *)arg;
if(state->count>0)
{
void *ip = (void *)_Unwind_GetIP(context);
if(ip)
{
state->addr[0] = ip;
state->count--;
state->addr++;
}
}
return(_URC_NO_REASON);
}
But trace_func where called only once, and shows only on _Unwind_Backtrace calls. Is it possible to get stacktrace of code which cause SIGSEGV signal using _Unwind_Backtrace?
thnx
If you want to use particularly _Unwind_Context(), you can do it like this (the code is 32-bit ARM specific):
struct BacktraceState {
const ucontext_t* signal_ucontext;
size_t address_count = 0;
static const size_t address_count_max = 30;
uintptr_t addresses[address_count_max] = {};
BacktraceState(const ucontext_t* ucontext) : signal_ucontext(ucontext) {}
bool AddAddress(uintptr_t ip) {
// No more space in the storage. Fail.
if (address_count >= address_count_max)
return false;
// Reset the Thumb bit, if it is set.
const uintptr_t thumb_bit = 1;
ip &= ~thumb_bit;
// Ignore null addresses.
// They sometimes happen when using _Unwind_Backtrace()
// with the compiler optimizations,
// when the Link Register is overwritten by the inner
// stack frames.
if (ip == 0)
return true;
// Ignore duplicate addresses.
// They sometimes happen when using _Unwind_Backtrace()
// with the compiler optimizations,
// because we both add the second address from the Link Register
// in ProcessRegisters() and receive the same address
// in UnwindBacktraceCallback().
if (address_count > 0 && ip == addresses[address_count - 1])
return true;
// Finally add the address to the storage.
addresses[address_count++] = ip;
return true;
}
};
void ProcessRegisters(
_Unwind_Context* unwind_context, BacktraceState* state) {
assert(state);
assert(unwind_context);
const ucontext_t* signal_ucontext = state->signal_ucontext;
assert(signal_ucontext);
const sigcontext* signal_mcontext = &(signal_ucontext->uc_mcontext);
assert(signal_mcontext);
_Unwind_SetGR(unwind_context, REG_R0, signal_mcontext->arm_r0);
_Unwind_SetGR(unwind_context, REG_R1, signal_mcontext->arm_r1);
_Unwind_SetGR(unwind_context, REG_R2, signal_mcontext->arm_r2);
_Unwind_SetGR(unwind_context, REG_R3, signal_mcontext->arm_r3);
_Unwind_SetGR(unwind_context, REG_R4, signal_mcontext->arm_r4);
_Unwind_SetGR(unwind_context, REG_R5, signal_mcontext->arm_r5);
_Unwind_SetGR(unwind_context, REG_R6, signal_mcontext->arm_r6);
_Unwind_SetGR(unwind_context, REG_R7, signal_mcontext->arm_r7);
_Unwind_SetGR(unwind_context, REG_R8, signal_mcontext->arm_r8);
_Unwind_SetGR(unwind_context, REG_R9, signal_mcontext->arm_r9);
_Unwind_SetGR(unwind_context, REG_R10, signal_mcontext->arm_r10);
_Unwind_SetGR(unwind_context, REG_R11, signal_mcontext->arm_fp);
_Unwind_SetGR(unwind_context, REG_R12, signal_mcontext->arm_ip);
_Unwind_SetGR(unwind_context, REG_R13, signal_mcontext->arm_sp);
_Unwind_SetGR(unwind_context, REG_R14, signal_mcontext->arm_lr);
_Unwind_SetGR(unwind_context, REG_R15, signal_mcontext->arm_pc);
// Program Counter register aka Instruction Pointer will contain
// the address of the instruction where the crash happened.
// UnwindBacktraceCallback() will not supply us with it.
state->AddAddress(signal_mcontext->arm_pc);
// UnwindBacktraceCallback() does not always supply us with
// the return address of the frame where the crash happened.
// Sometimes Link Register will contain this address
// (noticed when compiling with Clang without optimization),
// but LR may also contain address of some previously visitied frame
// (noticed when compiling with GCC without optimization),
// or LR may contain null address
// (noticed when compiling with Clang with optimization).
// These heuristics are unreliable.
#if __clang__
state->AddAddress(signal_mcontext->arm_lr);
#endif
}
_Unwind_Reason_Code UnwindBacktraceCallback(
struct _Unwind_Context* unwind_context, void* state_voidp) {
assert(unwind_context);
assert(state_voidp);
BacktraceState* state = (BacktraceState*)state_voidp;
assert(state);
// On the first UnwindBacktraceCallback() call,
// set registers to _Unwind_Context and BacktraceState.
if (state->address_count == 0) {
ProcessRegisters(unwind_context, state);
return _URC_NO_REASON;
}
uintptr_t ip = _Unwind_GetIP(unwind_context);
bool ok = state->AddAddress(ip);
if (!ok)
return _URC_END_OF_STACK;
return _URC_NO_REASON;
}
void CaptureBacktrace(BacktraceState* state) {
assert(state);
_Unwind_Backtrace(UnwindBacktraceCallback, state);
}
void SigActionHandler(int sig, siginfo_t* info, void* ucontext) {
const ucontext_t* signal_ucontext = (const ucontext_t*)ucontext;
assert(signal_ucontext);
BacktraceState backtrace_state(signal_ucontext);
CaptureBacktrace(&backtrace_state);
// Do something with the backtrace - print, save to file, etc.
}
But I am advising you to not use _Unwind_Context(), but instead use precompiled libunwind for 32-bit ARM, bundled with modern Android NDKs (at sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libunwind.a) and with all LLVM. You will have to use use libc++ (LLVM STL). How to do it, is demonstrated in this my answer, you'd have to combine the examples here.
https://stackoverflow.com/a/50027799/1016580
If you use libstdc++ (GNU STL), you could use the Dar Hoo's solution:
https://stackoverflow.com/a/48593413/1016580
You want to backtrace from the signal triggering function, but you backtrace from the signal handler function. That's two different stacks. (Note, the SA_ONSTACK flag in sigaction is irrelevant to your question.)
To find the stack pointer of the of the triggering function, use the third parameter of the handler, i.e. void *rserved. You can reference to the answer in this question: Getting the saved instruction pointer address from a signal handler
better you use backtrace and backtrace_symbols_fd to get a stacktrace from a signal handler.
You may use __gnu_Unwind_Backtrace instead. Example for ARM32:
typedef struct
{
uintptr_t r[16];
} core_regs;
typedef struct
{
uintptr_t demand_save_flags;
core_regs core;
} phase2_vrs;
extern "C" _Unwind_Reason_Code __gnu_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument, phase2_vrs * entry_vrs);
int AndroidGetBackTraceWithContext(VOID **stack, UINT32 size, ucontext_t *ctx)
{
ANDROID_UNWIND_STATE state;
state.count = size;
state.stack = stack;
// First call stack is current pc
state.stack[0] = (VOID *)ctx->uc_mcontext.arm_pc;
state.stack++;
state.count--;
phase2_vrs pre_signal_state;
pre_signal_state.demand_save_flags = 0;
pre_signal_state.core = *reinterpret_cast<const core_regs*>(&(ctx->uc_mcontext.arm_r0));
// Return value is of no use and might be wrong on some systems
__gnu_Unwind_Backtrace(DmpAndroidUnwindCallback, &state, &pre_signal_state);
return size - state.count;
}