I can not assign my array in interrupt.
My main.c function is like this:
volatile uint32_t buffer[BUFFER_LENGTH];
int main(void)
{
while(1)
{
sprintf((char*)string,"%u",buffer[0]);
BSP_LCD_DisplayStringAt(250, LINE(9), (uint8_t *)string, LEFT_MODE);
}
}
Interrupt routine is like this:
void EXTI3_IRQHandler(void)
{
buffer[0] = 100;
}
The display always shows 0!
The strange thing is that when I use a variable instead of an array everything works fine!
uint32_t variable;
int main(void)
{
while(1)
{
sprintf((char*)string,"%u",variable);
BSP_LCD_DisplayStringAt(250, LINE(9), (uint8_t *)string, LEFT_MODE);
}
}
void EXTI3_IRQHandler(void)
{
variable = 100;
}
The display shows 100! Why can't I use array in interrupt routine?
Related
Recently, I am trying to use bpf ringbuf in uprobe example of libbpf. But when running, error occurred which is "libbpf: load bpf program failed: Invalid argument". I have no idea why this happened. Could anyone help? Below is my test code.
Kernel space code: uprobe.bpf.c, define a rb struct, and use bpf_ringbuf_reserve in uprobe code block.
#include <linux/bpf.h>
#include <linux/ptrace.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
char LICENSE[] SEC("license") = "Dual BSD/GPL";
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} rb SEC(".maps");
SEC("uprobe/func")
int BPF_KPROBE(uprobe, int a, int b)
{
__u64* e = bpf_ringbuf_reserve(&rb, sizeof(__u64), 0);
if (!e)
return 0;
bpf_printk("UPROBE ENTRY: a = %d, b = %d\n", a, b);
return 0;
}
SEC("uretprobe/func")
int BPF_KRETPROBE(uretprobe, int ret)
{
bpf_printk("UPROBE EXIT: return = %d\n", ret);
return 0;
}
User space code: uprobe.c
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/resource.h>
#include <bpf/libbpf.h>
#include "uprobe.skel.h"
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
{
return vfprintf(stderr, format, args);
}
static void bump_memlock_rlimit(void)
{
struct rlimit rlim_new = {
.rlim_cur = RLIM_INFINITY,
.rlim_max = RLIM_INFINITY,
};
if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) {
fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n");
exit(1);
}
}
/* Find process's base load address. We use /proc/self/maps for that,
* searching for the first executable (r-xp) memory mapping:
*
* 5574fd254000-5574fd258000 r-xp 00002000 fd:01 668759 /usr/bin/cat
* ^^^^^^^^^^^^ ^^^^^^^^
*
* Subtracting that region's offset (4th column) from its absolute start
* memory address (1st column) gives us the process's base load address.
*/
static long get_base_addr() {
size_t start, offset;
char buf[256];
FILE *f;
f = fopen("/proc/self/maps", "r");
if (!f)
return -errno;
while (fscanf(f, "%zx-%*x %s %zx %*[^\n]\n", &start, buf, &offset) == 3) {
if (strcmp(buf, "r-xp") == 0) {
fclose(f);
return start - offset;
}
}
fclose(f);
return -1;
}
static int handle_event(void *ctx, void *data, size_t data_sz)
{
return 0;
}
/* It's a global function to make sure compiler doesn't inline it. */
int uprobed_function(int a, int b)
{
return a + b;
}
int main(int argc, char **argv)
{
struct ring_buffer *rb = NULL;
struct uprobe_bpf *skel;
long base_addr, uprobe_offset;
int err, i;
/* Set up libbpf errors and debug info callback */
libbpf_set_print(libbpf_print_fn);
/* Bump RLIMIT_MEMLOCK to allow BPF sub-system to do anything */
bump_memlock_rlimit();
/* Load and verify BPF application */
skel = uprobe_bpf__open_and_load();
if (!skel) {
fprintf(stderr, "Failed to open and load BPF skeleton\n");
return 1;
}
base_addr = get_base_addr();
if (base_addr < 0) {
fprintf(stderr, "Failed to determine process's load address\n");
err = base_addr;
goto cleanup;
}
/* uprobe/uretprobe expects relative offset of the function to attach
* to. This offset is relateve to the process's base load address. So
* easy way to do this is to take an absolute address of the desired
* function and substract base load address from it. If we were to
* parse ELF to calculate this function, we'd need to add .text
* section offset and function's offset within .text ELF section.
*/
uprobe_offset = (long)&uprobed_function - base_addr;
/* Attach tracepoint handler */
skel->links.uprobe = bpf_program__attach_uprobe(skel->progs.uprobe,
false /* not uretprobe */,
0 /* self pid */,
"/proc/self/exe",
uprobe_offset);
err = libbpf_get_error(skel->links.uprobe);
if (err) {
fprintf(stderr, "Failed to attach uprobe: %d\n", err);
goto cleanup;
}
/* we can also attach uprobe/uretprobe to any existing or future
* processes that use the same binary executable; to do that we need
* to specify -1 as PID, as we do here
*/
skel->links.uretprobe = bpf_program__attach_uprobe(skel->progs.uretprobe,
true /* uretprobe */,
-1 /* any pid */,
"/proc/self/exe",
uprobe_offset);
err = libbpf_get_error(skel->links.uretprobe);
if (err) {
fprintf(stderr, "Failed to attach uprobe: %d\n", err);
goto cleanup;
}
/* Set up ring buffer polling */
rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event, NULL, NULL);
if (!rb) {
err = -1;
fprintf(stderr, "Failed to create ring buffer\n");
goto cleanup;
}
printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` "
"to see output of the BPF programs.\n");
for (i = 0; ; i++) {
err = ring_buffer__poll(rb, 100 /* timeout, ms */);
/* trigger our BPF programs */
fprintf(stderr, ".");
uprobed_function(i, i + 1);
sleep(1);
}
cleanup:
ring_buffer__free(rb);
uprobe_bpf__destroy(skel);
return -err;
}
I have tested my RF96W LoRa boards with the Lolin Boards, it is working fine, But when I started to interface these Lora boards with stm32f030r8t6 based controller, I cant receive any data. Though I have tried to kept SPI configuration according to Lolin boards.
Board Wiring is same as SPI requirements.
Lolin working Code:
#include <SPI.h>
#include <RH_RF95.h>
#define RFM95_CS 15
#define RFM95_RST 16
#define RFM95_INT 5
RH_RF95 rf95(RFM95_CS, RFM95_INT);
void setup()
{
Serial.begin(9600);
while (!Serial) ; // Wait for serial port to be available
rf95.setModemConfig(RH_RF95::Bw125Cr48Sf4096);
while (!rf95.init()) {
Serial.println("LoRa radio init failed");
}
}
void loop()
{
Serial.println("Sending to rf95_server");
uint8_t data[] = "Hello World!";
rf95.send(data, sizeof(data));
rf95.waitPacketSent();
// Now wait for a reply
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
if (rf95.waitAvailableTimeout(3000)) {
// Should be a reply message for us now
if (rf95.recv(buf, &len)) {
Serial.print("got reply: ");
Serial.println((char*)buf);
// Serial.print("RSSI: ");
// Serial.println(rf95.lastRssi(), DEC);
} else {
Serial.println("recv failed");
}
} else {
Serial.println("No reply, is rf95_server running?");
}
// delay(400);
}
STM32F030R8T6 Controller not working code:
#include <stdio.h>
#include <RF95.h>
uint8_t init_failed = 0;
uint8_t Tx_buff[] = "Hello World!";
uint8_t Rx_buff[RH_RF95_MAX_MESSAGE_LEN];
uint8_t rssi_value = 0;
uint16_t len = 0;
void SystemClock_Config(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
// RF95_setModemConfig(Bw125Cr48Sf4096);
if(!RF95_Init()) {
init_failed = 1;
}
while (1) {
// RF95_send(Tx_buff);
// RF95_waitPacketSent();
// if(RF95_available_Timeout(3000)){
// RF95_receive(Rx_buff);
// }
if (RF95_available()) {
if (RF95_receive(Rx_buff)) {
len = sizeof(Rx_buff);
}
if (len) {
uint8_t data[] = "And hello back to you";
RF95_send(data);
RF95_waitPacketSent();
}
}
}
}
For Lolin board library is also from GitHub.
For ST I'm using RFM95 library from GitHub.
I have a simulink model and I made a simple s-function block to add to my model and it works.
The catch if if I copy or use that same s-function twice in my model, when I run it only the last s-function called will do what it's supposed to do, the other will output a 0.
#define S_FUNCTION_NAME DivByZero
#define S_FUNCTION_LEVEL 2
#define NUMBER_OF_INPUTS 1
#define NUMBER_OF_OUTPUTS 1
#include "DivByZero.h"
#include "mex.h"
#if !defined(MATLAB_MEX_FILE)
/*
* This file cannot be used directly
*/
# error This_file_can_be_used_only_during_simulation_inside_Simulink
#endif
float32 DivByZeroInput;
float32 DivByZeroOutput;
const void * inputPorts[NUMBER_OF_INPUTS];
const void * outputPorts[NUMBER_OF_OUTPUTS];
static void mdlInitializeSizes(SimStruct *S)
{
uint8 i;
ssSetNumSFcnParams(S, 0);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S))
{
return; /* Parameter mismatch reported by the Simulink engine */
}
if (!ssSetNumInputPorts(S, NUMBER_OF_INPUTS)) return;
ssSetInputPortWidth(S, 0, 1);
ssSetInputPortDataType(S, 0, SS_SINGLE);
for (i = 0; i < NUMBER_OF_INPUTS; i++)
{
ssSetInputPortDirectFeedThrough(S, i, 1); /* Set direct feedthrough flag */
ssSetInputPortRequiredContiguous(S, i, 1); /*direct input signal access*/
}
if (!ssSetNumOutputPorts(S, NUMBER_OF_OUTPUTS)) return;
ssSetOutputPortWidth(S, 0, 1);
ssSetOutputPortDataType(S, 0, SS_SINGLE);
/* Set Sample Time */
ssSetNumSampleTimes(S, 1);
/* Specify the sim state compliance to be same as a built-in block */
ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE);
ssSetOptions(S, SS_OPTION_ALLOW_PORT_SAMPLE_TIME_IN_TRIGSS);
ssSupportsMultipleExecInstances(S, true); //set so the s-function can be used in a for each subsystem block
}
static void mdlInitializeSampleTimes(SimStruct *S)
{
/* Inherits sample time from the driving block */
ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
ssSetModelReferenceSampleTimeDefaultInheritance(S);
}
#define MDL_START
#if defined(MDL_START)
static void mdlStart(SimStruct *S)
{
uint8 i;
/* Save Input ports */
for (i = 0; i < NUMBER_OF_INPUTS; i++)
{
inputPorts[i] = ssGetInputPortSignal(S, i);
}
/* Save Output ports */
for (i = 0; i < NUMBER_OF_OUTPUTS; i++)
{
outputPorts[i] = ssGetOutputPortRealSignal(S, i);
}
}
#endif
static void mdlOutputs(SimStruct *S, int_T tid)
{
memcpy(&DivByZeroInput, inputPorts[0], sizeof(DivByZeroInput));//gets the input port info
if (fabs(DivByZeroInput) > 0.00001f)
{
DivByZeroOutput = DivByZeroInput;
}
else
{
if (DivByZeroInput >= 0.0f)
{
DivByZeroOutput = 0.00001f;
}
else
{
DivByZeroOutput= -0.00001f;
}
}
memcpy(outputPorts[0], &DivByZeroOutput, sizeof(DivByZeroOutput));//sets the output port
}
static void mdlTerminate(SimStruct *S)
{
/* MODEL TERMINATE */
}
/* END OF TEMPLATE */
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif
The s-function is supposed to provide a simple division by zero protection as you can see from the code.
In the image below, if I delete S-Function1, S-Function will then work as intended.
I tried putting it in a library block and just put 2 library blocks and I got the same result
You are defining these variables:
float32 DivByZeroInput;
float32 DivByZeroOutput;
const void * inputPorts[NUMBER_OF_INPUTS];
const void * outputPorts[NUMBER_OF_OUTPUTS];
These variables are shared across both instances, which means both S-Functions write to the same output addresses.
Side note: Do you really have to use an S-Function? Creating the same from a few native simulink blocks is probably much easier.
I want to make a simple console game using Swift 5. I need to read keyboard input without blocking the game animation (using emojis). The game keeps on going while there's no keyboard input, but will react accordingly if there are ones.
I've seen some example how to do it in other languages such as C and Python. I knew Swift has Darwin module that provide many POSIX functions. However, those C codes seem incompatible with Swift 5.
For example, how to convert the C code below into Swift? There's no FD_ZERO nor FD_SET in Darwin module.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <termios.h>
struct termios orig_termios;
void reset_terminal_mode()
{
tcsetattr(0, TCSANOW, &orig_termios);
}
void set_conio_terminal_mode()
{
struct termios new_termios;
/* take two copies - one for now, one for later */
tcgetattr(0, &orig_termios);
memcpy(&new_termios, &orig_termios, sizeof(new_termios));
/* register cleanup handler, and set the new terminal mode */
atexit(reset_terminal_mode);
cfmakeraw(&new_termios);
tcsetattr(0, TCSANOW, &new_termios);
}
int kbhit()
{
struct timeval tv = { 0L, 0L };
fd_set fds;
FD_ZERO(&fds);
FD_SET(0, &fds);
return select(1, &fds, NULL, NULL, &tv);
}
int getch()
{
int r;
unsigned char c;
if ((r = read(0, &c, sizeof(c))) < 0) {
return r;
} else {
return c;
}
}
int main(int argc, char *argv[])
{
int key;
printf("press a key: ");
fflush(stdout);
set_conio_terminal_mode();
while (1) {
if (kbhit()) {
key = getch();
if (key == 13) {
printf("\n\r");
break;
} else if (key >= 20) {
printf("%c, ", key);
fflush(stdout);
}
}
else {
/* do some work */
printf(".");
usleep(10);
printf(".");
usleep(10);
printf(".");
usleep(10);
printf("\e[3D");
usleep(10);
}
}
reset_terminal_mode();
}
I expect swifty code to do the same thing in Swift.
The termios functions translate almost one-to-one to Swift:
#if os(Linux)
import Glibc
#else
import Darwin
#endif
var orig_termios = termios()
func reset_terminal_mode() {
tcsetattr(0, TCSANOW, &orig_termios)
}
func set_conio_terminal_mode() {
tcgetattr(0, &orig_termios)
var new_termios = orig_termios
atexit(reset_terminal_mode)
cfmakeraw(&new_termios)
tcsetattr(0, TCSANOW, &new_termios)
}
set_conio_terminal_mode()
The problem with select() is that FD_ZERO etc are “non-trivial” macros and not imported into Swift. But you can use poll() instead:
func kbhit() -> Bool {
var fds = [ pollfd(fd: STDIN_FILENO, events: Int16(POLLIN), revents: 0) ]
let res = poll(&fds, 1, 0)
return res > 0
}
An alternative is to use the Dispatch framework. Here is a simple example which might help you get started. A dispatch source is used to wait asynchronously for available input, which is then appended to an array, from where it is retrieved in the getch() function. A serial queue is used to synchronize access to the array.
import Dispatch
let stdinQueue = DispatchQueue(label: "my.serial.queue")
var inputCharacters: [CChar] = []
let stdinSource = DispatchSource.makeReadSource(fileDescriptor: STDIN_FILENO, queue: stdinQueue)
stdinSource.setEventHandler(handler: {
var c = CChar()
if read(STDIN_FILENO, &c, 1) == 1 {
inputCharacters.append(c)
}
})
stdinSource.resume()
// Return next input character, or `nil` if there is none.
func getch() -> CChar? {
return stdinQueue.sync {
inputCharacters.isEmpty ? nil : inputCharacters.remove(at: 0)
}
}
Can someone explain what possible datatype this refers to?
void (*sa_handler)(int)
from signal's man page.
It is a signal handler function in UNIX.
You declare it and then pass it to sigaction() system call.
Here untested code to catch USR1 signal which you can send to you process with kill command:
void my_function(int signal) {
continue_looping = 0;
}
volatile int continue_looping = 1;
int main(void) {
struct sigaction sa;
sigset_t mask;
sa.sa_handler = &my_function;
sa.sa_flags = SA_RESETHAND;
sigfillset(&sa.sa_mask);
sigaction(SIGUSR1, &sa, NULL);
while(continue_looping) {
printf("Hello world\n");
}
return 0;
}
You should be careful when calling any further functions from your action handler. I usually just set a flag there - as in the above example.