In Minix 3.1.2a I've a struct "struct proc" where the PCB of any process stored,
but I've a problem when adding new attribute "p_currenthash" in the code below to this struct. I can't change its value except using a constant defined by #define directive; otherwise, the system stops responding. For clarity here is the structure:
struct proc {
struct stackframe_s p_reg; /* process' registers saved in stack frame */
#if (CHIP == INTEL)
reg_t p_ldt_sel; /* selector in gdt with ldt base and limit */
struct segdesc_s p_ldt[2+NR_REMOTE_SEGS]; /* CS, DS and remote segments */
#endif
#if (CHIP == M68000)
/* M68000 specific registers and FPU details go here. */
#endif
proc_nr_t p_nr; /* number of this process (for fast access) */
struct priv *p_priv; /* system privileges structure */
short p_rts_flags; /* process is runnable only if zero */
short p_misc_flags; /* flags that do suspend the process */
char p_priority; /* current scheduling priority */
char p_max_priority; /* maximum scheduling priority */
char p_ticks_left; /* number of scheduling ticks left */
char p_quantum_size; /* quantum size in ticks */
struct mem_map p_memmap[NR_LOCAL_SEGS]; /* memory map (T, D, S) */
clock_t p_user_time; /* user time in ticks */
clock_t p_sys_time; /* sys time in ticks */
struct proc *p_nextready; /* pointer to next ready process */
struct proc *p_caller_q; /* head of list of procs wishing to send */
struct proc *p_q_link; /* link to next proc wishing to send */
message *p_messbuf; /* pointer to passed message buffer */
int p_getfrom_e; /* from whom does process want to receive? */
int p_sendto_e; /* to whom does process want to send? */
sigset_t p_pending; /* bit map for pending kernel signals */
char p_name[P_NAME_LEN]; /* name of the process, including \0 */
int p_endpoint; /* endpoint number, generation-aware */
#if DEBUG_SCHED_CHECK
int p_ready, p_found;
#endif
char p_currenthash; /* hash */
};
Now, suppose I want to set its value. Initially I use the constant defined below.
#define NONE -1
register struct proc *rp;
rp->p_currenthash=NONE;
That works fine, but this: rp->p_currenthash=0 ; will cause the program to stop responding.
Any suggestions will be appreciated
Here's the main initialization in main():
/* Start the ball rolling. */
struct boot_image *ip; /* boot image pointer */
register struct proc *rp; /* process pointer */
register struct priv *sp; /* privilege structure pointer */
register int i, s;
int hdrindex; /* index to array of a.out headers */
phys_clicks text_base;
vir_clicks text_clicks, data_clicks;
reg_t ktsb; /* kernel task stack base */
struct exec e_hdr; /* for a copy of an a.out header */
/* Initialize the interrupt controller. */
intr_init(1);
/* Clear the process table. Anounce each slot as empty and set up mappings
* for proc_addr() and proc_nr() macros. Do the same for the table with
* privilege structures for the system processes.
*/
for (rp = BEG_PROC_ADDR, i = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++i) {
rp->p_rts_flags = SLOT_FREE; /* initialize free slot */
rp->p_nr = i; /* proc number from ptr */
rp->p_currenthash=NONE;
rp->p_endpoint = _ENDPOINT(0, rp->p_nr); /* generation no. 0 */
(pproc_addr + NR_TASKS)[i] = rp; /* proc ptr from number */
}
for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) {
sp->s_proc_nr = NONE; /* initialize as free */
sp->s_id = i; /* priv structure index */
ppriv_addr[i] = sp; /* priv ptr from number */
}
/* Set up proc table entries for processes in boot image. The stacks of the
* kernel tasks are initialized to an array in data space. The stacks
* of the servers have been added to the data segment by the monitor, so
* the stack pointer is set to the end of the data segment. All the
* processes are in low memory on the 8086. On the 386 only the kernel
* is in low memory, the rest is loaded in extended memory.
*/
/* Task stacks. */
ktsb = (reg_t) t_stack;
for (i=0; i < NR_BOOT_PROCS; ++i) {
ip = &image[i]; /* process' attributes */
rp = proc_addr(ip->proc_nr); /* get process pointer */
ip->endpoint = rp->p_endpoint; /* ipc endpoint */
rp->p_max_priority = ip->priority; /* max scheduling priority */
rp->p_priority = ip->priority; /* current priority */
rp->p_quantum_size = ip->quantum; /* quantum size in ticks */
rp->p_ticks_left = ip->quantum; /* current credit */
strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set process name */
(void) get_priv(rp, (ip->flags & SYS_PROC)); /* assign structure */
priv(rp)->s_flags = ip->flags; /* process flags */
priv(rp)->s_trap_mask = ip->trap_mask; /* allowed traps */
priv(rp)->s_call_mask = ip->call_mask; /* kernel call mask */
priv(rp)->s_ipc_to.chunk[0] = ip->ipc_to; /* restrict targets */
if (iskerneln(proc_nr(rp))) { /* part of the kernel? */
if (ip->stksize > 0) { /* HARDWARE stack size is 0 */
rp->p_priv->s_stack_guard = (reg_t *) ktsb;
*rp->p_priv->s_stack_guard = STACK_GUARD;
}
ktsb += ip->stksize; /* point to high end of stack */
rp->p_reg.sp = ktsb; /* this task's initial stack ptr */
text_base = kinfo.code_base >> CLICK_SHIFT;
/* processes that are in the kernel */
hdrindex = 0; /* all use the first a.out header */
} else {
hdrindex = 1 + i-NR_TASKS; /* servers, drivers, INIT */
}
/* The bootstrap loader created an array of the a.out headers at
* absolute address 'aout'. Get one element to e_hdr.
*/
phys_copy(aout + hdrindex * A_MINHDR, vir2phys(&e_hdr),
(phys_bytes) A_MINHDR);
/* Convert addresses to clicks and build process memory map */
text_base = e_hdr.a_syms >> CLICK_SHIFT;
text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT;
if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0; /* common I&D */
data_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT;
rp->p_memmap[T].mem_phys = text_base;
rp->p_memmap[T].mem_len = text_clicks;
rp->p_memmap[D].mem_phys = text_base + text_clicks;
rp->p_memmap[D].mem_len = data_clicks;
rp->p_memmap[S].mem_phys = text_base + text_clicks + data_clicks;
rp->p_memmap[S].mem_vir = data_clicks; /* empty - stack is in data */
/* Set initial register values. The processor status word for tasks
* is different from that of other processes because tasks can
* access I/O; this is not allowed to less-privileged processes
*/
rp->p_reg.pc = (reg_t) ip->initial_pc;
rp->p_reg.psw = (iskernelp(rp)) ? INIT_TASK_PSW : INIT_PSW;
/* Initialize the server stack pointer. Take it down one word
* to give crtso.s something to use as "argc".
*/
if (isusern(proc_nr(rp))) { /* user-space process? */
rp->p_reg.sp = (rp->p_memmap[S].mem_vir +
rp->p_memmap[S].mem_len) << CLICK_SHIFT;
rp->p_reg.sp -= sizeof(reg_t);
}
/* Set ready. The HARDWARE task is never ready. */
if (rp->p_nr != HARDWARE) {
rp->p_rts_flags = 0; /* runnable if no flags */
lock_enqueue(rp); /* add to scheduling queues */
} else {
rp->p_rts_flags = NO_MAP; /* prevent from running */
}
/* Code and data segments must be allocated in protected mode. */
alloc_segments(rp);
}
register struct proc *rp;
rp->p_currenthash=NONE;
rp is an uninitialized pointer; it isn't pointing to a valid struct proc object, and so dereferencing it leads to undefined behavior. The fact that this didn't crash when assigning -1 was pure luck. (bad luck, because it misled you to believe you were doing something meaningful)
acutually the problem not solved ,first the "p_currenthash" initialized in the main as shown above ,later in a function called pic_proc ,i've this code :
register struct proc **xpp; /* iterate over queue */
register struct proc *rp; /* process to run */
int q;
for (q=0; q < NR_SCHED_QUEUES; q++)
{
if ( (rp = rdy_head[q]) != NIL_PROC)
{
for (xpp = &rdy_head[q]; *xpp != NIL_PROC; xpp = &(*xpp)->p_nextready)
{
if ((*xpp)->p_currenthash==NONE)
{
pick_val++;
}
}
}
}
that code works fine ,no inside the if if i changed the attribute "p_currenthash" the problem ocuured as bellow:
register struct proc **xpp; /* iterate over queue */
register struct proc *rp; /* process to run */
int q;
for (q=0; q < NR_SCHED_QUEUES; q++)
{
if ( (rp = rdy_head[q]) != NIL_PROC)
{
for (xpp = &rdy_head[q]; *xpp != NIL_PROC; xpp = &(*xpp)->p_nextready)
{
if ((*xpp)->p_currenthash==NONE)
{
pick_val++;
(*xpp)->p_currenthash=1;
}
}
}
}
i really can't realize the problem.
Related
I've been trying to process speech on a stm32f407ve development board for some time now, which makes me wonder if the ADC is really set up to precisely sample the values. CMSIS FFT Functions. But when I try to couple it with the ADC in continuous conversion to sample a sine signal, it doesn't seem to sample well periodically. I put a sine signal into it from a frequency test of a 1khz sine wave from an internet video with a plug that I take out of some headphones, which by the way I already tested that it works correctly with an oscilloscope. So... this one from the development board is obviously not from a DSP but its ADC should work correctly for this type of application? Here is my code, obviously I made sure that the test was emitting voltage before the debug.
#include "main.h"
#include "arm_math.h"
#include "arm_const_structs.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
#define Fs 4096;
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
/* USER CODE BEGIN PV */
#define SIGNAL_BUFFER_LENGTH 4096
float signalBuffer[2*SIGNAL_BUFFER_LENGTH];
float fftBuffer[2*SIGNAL_BUFFER_LENGTH];
float magnitudes[SIGNAL_BUFFER_LENGTH];
/* USER CODE END PV */
uint32_t k;
uint32_t cont1,cont2;
uint32_t start;
uint32_t stopi;
uint32_t delta;
float32_t maxValue; /* Max FFT value is stored here */
uint32_t maxIndex;
float frecuencia=10.0;
float32_t Ts;
float tiempo;
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
#define ARM_CM_DEMCR (*(uint32_t*)0xE000EDFC)
#define ARM_CM_DWT_CTRL (*(uint32_t*)0xE0001000)
#define ARM_CM_DWT_CYCCNT (*(uint32_t*)0xE0001004)
if(ARM_CM_DWT_CTRL !=0){
ARM_CM_DEMCR |= 1<<24;
ARM_CM_DWT_CYCCNT =0;
ARM_CM_DWT_CTRL |= 1<<0;
}
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
/* USER CODE BEGIN 2 */
Ts=1.0/(float)Fs;
HAL_ADC_Start(&hadc1);
for(k=0;k<2*SIGNAL_BUFFER_LENGTH;k+=2 )
{
signalBuffer[k]=HAL_ADC_GetValue(&hadc1);
}
k++;
//signalBuffer[0]=0;
//start= ARM_CM_DWT_CYCCNT;
arm_cfft_f32(&arm_cfft_sR_f32_len4096,signalBuffer,0,1);
signalBuffer[0]=0;
arm_cmplx_mag_f32(signalBuffer,magnitudes,4096);
arm_max_f32(magnitudes, 4096, &maxValue, &maxIndex);
//stopi = ARM_CM_DWT_CYCCNT;
//delta=stopi-start;
//tiempo=delta/8.0E07*1000.0;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
You are just calling the function to take a single reading over and over in a loop. There is no reason to think that each pass through this loop will take the same amount of time. You need to set the ADC to be triggered from a timer in order to have some kind of reproducible sample rate.
In general the internal ADC is not of suitable quality for audio use. There is an external audio codec fitted to this board, look at the example projects in the Stm32CubeF4 package.
I'm new to programming with Matrox (MIL) and C++. I've been wanting to use a camera to its limit (120 Hz frame rate). I'm currently using MIL through Microsoft Visual Studio to program the camera. How my program works currently is using MdigProcess to acquire and save each image using a separate function. However, this slows down the camera to roughly 10Hz since it calls the function every time the to save the image in a buffer when it is ready. If I don't save the images, then the camera works fine. But I won't have any data :/
I am thinking of having the images (100 images for now) in the buffers first once, then save them. Is there a way to do that? Here is my attempt:
#include <mil.h>
#include <stdlib.h>
/* Number of images in the buffering grab queue.
Generally, increasing this number gives a better real-time grab.
*/
#define BUFFERING_SIZE_MAX 5
/* User's processing function prototype. */
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void*
HookDataPtr);
/* User's processing function hook data structure. */
typedef struct
{
MIL_ID MilDigitizer;
MIL_ID MilImageDisp;
MIL_INT ProcessedImageCount;
} HookDataStruct;
/* Main function. */
/* ---------------*/
int MosMain(void)
{
MIL_ID MilApplication;
MIL_ID MilSystem;
MIL_ID MilDigitizer;
MIL_ID MilDisplay; /* Display identifier. */
MIL_ID MilImageDisp; /* Display Image buffer identifier. */
MIL_ID MilGrabBufferList[BUFFERING_SIZE_MAX] = { 0 };
MIL_INT MilGrabBufferListSize;
MIL_INT ProcessFrameCount = 0, ProcessFrameMissed = 0, ProcessFrameCorrupted = 0;
MIL_DOUBLE ProcessFrameRate = 0;
MIL_DOUBLE FrameRate; // Initializes the FrameRate variable as double
HookDataStruct UserHookData;
MappAlloc(M_NULL, M_DEFAULT, &MilApplication); /* This initializes the MIL library. M_NULL means no cluster manager will be used. M_DEFAULT means reported error message will be displayed. */
MsysAlloc(M_SYSTEM_RAPIXOCL, M_DEFAULT, M_DEFAULT, &MilSystem); /* This allocates a MIL system*/
MdispAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_DEFAULT, &MilDisplay); /* M_WINDOWED means it will display at a separate window*/
MdigAlloc(MilSystem, M_DEV0, MIL_TEXT("C:\\Users\\fluids-student\\Documents\\JAI 5000 PMCL.dcf"), M_DEFAULT, &MilDigitizer);
/* Allocate a monochrome display buffer. */
MbufAlloc2d(MilSystem, 2560, 2048, 8 + M_UNSIGNED, M_IMAGE + M_DISP + M_GRAB + M_PROC, &MilImageDisp);
MbufClear(MilImageDisp, M_BLACK);
/* Display the image buffer. */
MdispSelect(MilDisplay, MilImageDisp);
/* This inquires the frame rate */
MdigInquire(MilDigitizer, M_SELECTED_FRAME_RATE, &FrameRate);
MosPrintf(MIL_TEXT("The frame rate is # %0.2f fps.\n"), FrameRate);
/* Print a message. */
MosPrintf(MIL_TEXT("\nMULTIPLE BUFFERED PROCESSING.\n"));
MosPrintf(MIL_TEXT("-----------------------------\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to start acquisition.\n\n"));
/* Grab continuously on the display and wait for a key press. */
MdigGrabContinuous(MilDigitizer, MilImageDisp);
MosGetch();
/* Halt continuous grab. */
MdigHalt(MilDigitizer);
/* Allocate the grab buffers and clear them. */
MappControl(M_DEFAULT, M_ERROR, M_PRINT_DISABLE);
for (MilGrabBufferListSize = 0; MilGrabBufferListSize < BUFFERING_SIZE_MAX;
MilGrabBufferListSize++)
{
MbufAlloc2d(MilSystem,
MdigInquire(MilDigitizer, M_SIZE_X, M_NULL),
MdigInquire(MilDigitizer, M_SIZE_Y, M_NULL),
8L + M_UNSIGNED,
M_IMAGE + M_GRAB + M_PROC,
&MilGrabBufferList[MilGrabBufferListSize]);
if (MilGrabBufferList[MilGrabBufferListSize])
MbufClear(MilGrabBufferList[MilGrabBufferListSize], 0xFF);
else
break;
}
MappControl(M_DEFAULT, M_ERROR, M_PRINT_ENABLE);
/* Initialize the user's processing function data structure. */
UserHookData.MilDigitizer = MilDigitizer;
UserHookData.MilImageDisp = MilImageDisp;
UserHookData.ProcessedImageCount = 0;
/* Start the processing. The processing function is called with every frame grabbed. */
MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize,
M_SEQUENCE + M_COUNT(100), M_DEFAULT, ProcessingFunction, &UserHookData);
/* Here the main() is free to perform other tasks while the processing is executing. */
/* --------------------------------------------------------------------------------- */
/* Stop the processing. */
MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize,
M_STOP, M_DEFAULT, ProcessingFunction, &UserHookData);
/* Print statistics. */
MdigInquire(MilDigitizer, M_PROCESS_FRAME_COUNT, &ProcessFrameCount);
MdigInquire(MilDigitizer, M_PROCESS_FRAME_RATE, &ProcessFrameRate);
MdigInquire(MilDigitizer, M_PROCESS_FRAME_MISSED, &ProcessFrameMissed);
MdigInquire(MilDigitizer, M_PROCESS_FRAME_CORRUPTED, &ProcessFrameCorrupted);
MosPrintf(MIL_TEXT("\n\n%d frames grabbed at %.1f frames/sec (%.1f ms/frame).\n"),
(int)ProcessFrameCount, ProcessFrameRate, 1000.0 / ProcessFrameRate);
MosPrintf(MIL_TEXT("%ld frames missed.\n"), ProcessFrameMissed);
MosPrintf(MIL_TEXT("%ld frames corrupted.\n"), ProcessFrameCorrupted);
MosPrintf(MIL_TEXT("Press <Enter> to end.\n\n"));
MosPrintf(MIL_TEXT("BufferListSize = %d\n"), MilGrabBufferListSize);
MosGetch();
/* Free the grab buffers. */
while (MilGrabBufferListSize > 0)
MbufFree(MilGrabBufferList[--MilGrabBufferListSize]);
/* Free display buffer. */
MbufFree(MilImageDisp);
/* Release defaults. */
MdigFree(MilDigitizer);
MdispFree(MilDisplay);
MsysFree(MilSystem);
MappFree(MilApplication);
return 0;
}
/* User's processing function called every time a grab buffer is ready. */
/* -------------------------------------------------------------------- */
/* Local defines. */
#define STRING_LENGTH_MAX 20
#define STRING_POS_X 20
#define STRING_POS_Y 20
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr)
{
HookDataStruct* UserHookDataPtr = (HookDataStruct*)HookDataPtr;
MIL_ID ModifiedBufferId;
MIL_TEXT_CHAR Text[STRING_LENGTH_MAX] = { MIL_TEXT('\0'), };
MIL_TEXT_CHAR junkoutput[STRING_LENGTH_MAX] = { MIL_TEXT('\0'), };
/* Retrieve the MIL_ID of the grabbed buffer. */
MdigGetHookInfo(HookId, M_MODIFIED_BUFFER + M_BUFFER_ID, &ModifiedBufferId);
/* Increment the frame counter. */
UserHookDataPtr->ProcessedImageCount++;
/* Print and draw the frame count (remove to reduce CPU usage). */
MosPrintf(MIL_TEXT("Acquiring frame #%d.\r"), (int)UserHookDataPtr->ProcessedImageCount);
MosSprintf(Text, STRING_LENGTH_MAX, MIL_TEXT("%d"),
(int)UserHookDataPtr->ProcessedImageCount);
/* Execute the processing and update the display. */
MbufCopy(ModifiedBufferId, UserHookDataPtr->MilImageDisp); // Remove comment to see the image acquisition. Will slow down the frame rate/ acquisition time
/* Create file name base on the index of the frame that is being processed */
MosSprintf(Text, STRING_LENGTH_MAX, MIL_TEXT("Image%03li.png"), UserHookDataPtr->ProcessedImageCount); // 0-adds zeroes to the naming, 3- three places, l-long integer, i-signed decimal integer
/* Save image to disk */
MbufSave(Text, UserHookDataPtr->MilImageDisp);
return 0;
}
Thanks for all the help I can get!
I'd like to run a simple neural network model which uses Keras on a Rasperry microcontroller. I get a problem when I use a layer. The code is defined like this:
#include "main.h"
#include <string.h>
#include "tensorflow/lite/micro/kernels/micro_ops.h"
#include "tensorflow/lite/micro/micro_error_reporter.h"
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/micro/micro_mutable_op_resolver.h"
#include "tensorflow/lite/version.h"
#include "my_model.h"
/* Private variables
TIM_HandleTypeDef htim16;
UART_HandleTypeDef huart2;
/* USER CODE BEGIN PV */
// TFLite globals
namespace {
tflite::ErrorReporter* error_reporter = nullptr;
const tflite::Model* model = nullptr;
tflite::MicroInterpreter* interpreter = nullptr;
TfLiteTensor* model_input = nullptr;
TfLiteTensor* model_output = nullptr;
// Create an area of memory to use for input, output, and other TensorFlow
// arrays. You'll need to adjust this by compiling, running, and looking
// for errors.
constexpr int kTensorArenaSize = 2 * 1024;
__attribute__((aligned(16)))uint8_t tensor_arena[kTensorArenaSize];
} // namespace
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_TIM16_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code
/* USER CODE BEGIN 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
char buf[50];
int buf_len = 0;
TfLiteStatus tflite_status;
uint32_t num_elements;
uint32_t timestamp;
float y_val;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_TIM16_Init();
/* USER CODE BEGIN 2 */
// Start timer/counter
HAL_TIM_Base_Start(&htim16);
// Set up logging (modify tensorflow/lite/micro/debug_log.cc)
static tflite::MicroErrorReporter micro_error_reporter;
error_reporter = µ_error_reporter;
// Say something to test error reporter
error_reporter->Report("STM32 TensorFlow Lite test");
// Map the model into a usable data structure
model = tflite::GetModel(my_model);
if (model->version() != TFLITE_SCHEMA_VERSION)
{
error_reporter->Report("Model version does not match Schema");
while(1);
}
// Pull in only needed operations (should match NN layers). Template parameter
// <n> is number of ops to be added. Available ops:
// tensorflow/lite/micro/kernels/micro_ops.h
static tflite::MicroMutableOpResolver<1> micro_op_resolver;
// Add dense neural network layer operation
tflite_status = micro_op_resolver.AddBuiltin(
tflite::BuiltinOperator_FULLY_CONNECTED,
tflite::ops::micro::Register_FULLY_CONNECTED());
if (tflite_status != kTfLiteOk)
{
error_reporter->Report("Could not add FULLY CONNECTED op");
while(1);
}
// Build an interpreter to run the model with.
static tflite::MicroInterpreter static_interpreter(
model, micro_op_resolver, tensor_arena, kTensorArenaSize, error_reporter);
interpreter = &static_interpreter;
// Allocate memory from the tensor_arena for the model's tensors.
tflite_status = interpreter->AllocateTensors();
if (tflite_status != kTfLiteOk)
{
error_reporter->Report("AllocateTensors() failed");
while(1);
}
// Assign model input and output buffers (tensors) to pointers
model_input = interpreter->input(0);
model_output = interpreter->output(0);
// Get number of elements in input tensor
num_elements = model_input->bytes / sizeof(float);
buf_len = sprintf(buf, "Number of input elements: %lu\r\n", num_elements);
HAL_UART_Transmit(&huart2, (uint8_t *)buf, buf_len, 100);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// Fill input buffer (use test value)
for (uint32_t i = 0; i < num_elements; i++)
{
model_input->data.f[i] = 2.0f;
}
// Get current timestamp
timestamp = htim16.Instance->CNT;
// Run inference
tflite_status = interpreter->Invoke();
if (tflite_status != kTfLiteOk)
{
error_reporter->Report("Invoke failed");
}
// Read output (predicted y) of neural network
y_val = model_output->data.f[0];
// Print output of neural network along with inference time (microseconds)
buf_len = sprintf(buf,
"Output: %f | Duration: %lu\r\n",
y_val,
htim16.Instance->CNT - timestamp);
HAL_UART_Transmit(&huart2, (uint8_t *)buf, buf_len, 100);
// Wait before doing it again
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
When I run the program I got this compilation problem:
../Core/Src/main.cpp: In function 'int main()':
../Core/Src/main.cpp:181:57: error: no matching function for call to 'tflite::MicroMutableOpResolver<1>::AddBuiltin(tflite::BuiltinOperator, TfLiteRegistration*)'
tflite::ops::micro::Register_FULLY_CONNECTED());
^
In file included from ../Core/Src/main.cpp:31:0:
STM32CubeIDE/workspace_1.3.0/sine/tensorflow_lite/tensorflow/lite/micro/micro_mutable_op_resolver.h:470:16: note: candidate: TfLiteStatus tflite::MicroMutableOpResolver<tOpCount>::AddBuiltin(tflite::BuiltinOperator, const TfLiteRegistration&, tflite::MicroOpResolver::BuiltinParseFunction) [with unsigned int tOpCount = 1; TfLiteStatus = TfLiteStatus; TfLiteRegistration = TfLiteRegistration; tflite::MicroOpResolver::BuiltinParseFunction = TfLiteStatus (*)(const tflite::Operator*, tflite::BuiltinOperator, tflite::ErrorReporter*, tflite::BuiltinDataAllocator*, void**)]
TfLiteStatus AddBuiltin(tflite::BuiltinOperator op,
^~~~~~~~~~
STM32CubeIDE/workspace_1.3.0/sine/tensorflow_lite/tensorflow/lite/micro/micro_mutable_op_resolver.h:470:16: note: candidate expects 3 arguments, 2 provided
make: *** [Core/Src/subdir.mk:37: Core/Src/main.o] Error 1
"make -j2 all" terminated with exit code 2. Build might be incomplete.
I'm not sure which third parameter I have to insert for FULLY_CONNECTED() or if there is another problem.
I think I were running into a version mismatch between the TFlite for Micro Python library used to generate the model and the TFlite for Micro C/C++ library used to run inference. I solved the problem using this:
static tflite::MicroMutableOpResolver<1> micro_op_resolver;
tflite_status = micro_op_resolver.AddFullyConnected();
I had the same problem, man.
I want to transplant tflite to the development board of CEVA. There is no problem in compiling. In the process of running, there is also an error in AddBuiltin(full_connect).
At present, the only possible situation I guess is that some devices can not support tflite.
Did you check if the FULLY_CONNECTED operator is listed in the micro_ops.h header file? The header file contains a list of registration methods for a user to pick if their model requires the operator.
I had the same problem during compilation and discovered I was missing the method TfLiteRegistration Register_FULLY_CONNECTED() .
Good morning everyone,
I am currently working on a data acquisition project, where I have to read sensors (at around 10 kHz) and transmit the data via Wi-Fi and the MQTT-protocol. I am using an ESP32 for both of these tasks.
One core is doing the sensor reading and the other core does the transmitting stuff. I also use the FreeRTOS for this.
Now, I want to pass the data as efficient as possible between the task. Currently I'm using the xQueue function built in the FreeRtos. I pass pointers in the Queue which point to an array, where one datapackage is stored.
Task one:
*sensor reading*
for(xx)
{
data_array[x] = sensor_data;
}
if {packageSize == 120}
{
xQueueSend(Queue1, &data_pointer, 0);
}
________________________
Task two:
if( uxQueueMessagesWaiting(Queue1) >= 1)
{
xQueueReceive(Queue1, &received_pointer, 0);
memcpy(data_send, received_pointer, packageSize);
* MQTT-Client sending data_send *
}
You see, my problem isn't the creation of the array with different pointers. The sensor reading task needs to create an array for every package, without overwritting the previous one.
My initial idea was to use the new and delete combination but it gave me strange results.
Is there any way I can change the location of the array on the memory at every loop of task one?
EDIT:
/* general variables*/
const int len = 150;
uint8_t data_received[len];
uint8_t data_send[len];
uint8_t *queue_pointer = 0;
uint8_t *received_pointer = 0;
uint8_t *to_delete_pointer = 0;
uint8_t dummy_data = 0;
int v = 0;
/* multithreading variables */
TaskHandle_t SPI_COM;
TaskHandle_t WIFI;
QueueHandle_t buffer_daten;
/* --------------------- Fake-SPI-Kommunikation auf Core 1 -------------------- */
void SPI_COM_code(void *pvParameters)
{
for (;;)
{
while (v <= 10000)
{
//queue_pointer = new int[len]; // creates a new array
queue_pointer = data_received;
queue_pointer[dummy_data] = dummy_data;
dummy_data++;
delayMicroseconds(100); // Dummy-Interrupt
if (dummy_data == len - 1)
{
dummy_data = 0;
xQueueSend(buffer_daten, &queue_pointer, 0);
v++;
}
}
}
}
/* --------------------- WiFi-Übertragung auf Core 0 --------------------- */
void WIFI_code(void *pvParameters)
{
for (;;)
{
//MQTT_connect();
if (uxQueueMessagesWaiting(buffer_daten) > 0)
{
xQueueReceive(buffer_daten, &received_pointer, 0);
to_delete_pointer = received_pointer;
memcpy(data_send, received_pointer, len);
// Data gets published by MQTT-Client
delayMicroseconds(12);
//delete[] to_delete_pointer; // deletes array, which was send
}
}
}
/* ----------------------------------- Setup ---------------------------------- */
void setup()
{
disableCore0WDT(); // <----- MÖGLICHE PROBLEMQUELLE
Serial.begin(115200);
buffer_daten = xQueueCreate(1000, sizeof(int));
xTaskCreatePinnedToCore(
SPI_COM_code, /* Task function. */
"SPI_COM", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&SPI_COM, /* Task handle to keep track of created task */
1); /* pin task to core 0 */
delay(500);
xTaskCreatePinnedToCore(
WIFI_code, /* Task function. */
"WIFI", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
2, /* priority of the task */
&WIFI, /* Task handle to keep track of created task */
0); /* pin task to core 1 */
delay(500);
}
void loop()
{
}
I would suggest you use a RTOS Message Buffers for this task
With this functions you could copy your array into the buffer and the second task could get it, when the data is available.
In both cases the consumer task should use the timeout '0' to request the data.
If the MQTT task is faster than the data acquisition (and it should be or your buffers will overflow sooner or later) this will lead to invalid pointers:
xQueueReceive(buffer_daten, &received_pointer, 0);
If the is no data available the function will return immediately giving you an invalid received_pointer.
You should either check the return value of xQueueReceive or set the timeout to portMAX_DELAY.
I am trying to write a piece of code using the perf_event_open syscall. But I don't understand the real difference between id and stream_id fields in the structure returned in my memory map.
This structure is like this one (from the man page of perf_event_open) :
struct {
struct perf_event_header header;
u64 sample_id; /* if PERF_SAMPLE_IDENTIFIER */
u64 ip; /* if PERF_SAMPLE_IP */
u32 pid, tid; /* if PERF_SAMPLE_TID */
u64 time; /* if PERF_SAMPLE_TIME */
u64 addr; /* if PERF_SAMPLE_ADDR */
u64 id; /* if PERF_SAMPLE_ID */
u64 stream_id; /* if PERF_SAMPLE_STREAM_ID */
u32 cpu, res; /* if PERF_SAMPLE_CPU */
u64 period; /* if PERF_SAMPLE_PERIOD */
struct read_format v;
/* if PERF_SAMPLE_READ */
u64 nr; /* if PERF_SAMPLE_CALLCHAIN */
u64 ips[nr]; /* if PERF_SAMPLE_CALLCHAIN */
u32 size; /* if PERF_SAMPLE_RAW */
char data[size]; /* if PERF_SAMPLE_RAW */
u64 bnr; /* if PERF_SAMPLE_BRANCH_STACK */
struct perf_branch_entry lbr[bnr];
/* if PERF_SAMPLE_BRANCH_STACK */
u64 abi; /* if PERF_SAMPLE_REGS_USER */
u64 regs[weight(mask)];
/* if PERF_SAMPLE_REGS_USER */
u64 size; /* if PERF_SAMPLE_STACK_USER */
char data[size]; /* if PERF_SAMPLE_STACK_USER */
u64 dyn_size; /* if PERF_SAMPLE_STACK_USER &&
size != 0 */
u64 weight; /* if PERF_SAMPLE_WEIGHT */
u64 data_src; /* if PERF_SAMPLE_DATA_SRC */
u64 transaction; /* if PERF_SAMPLE_TRANSACTION */
u64 abi; /* if PERF_SAMPLE_REGS_INTR */
u64 regs[weight(mask)];
/* if PERF_SAMPLE_REGS_INTR */
};
The man page give me this explanation :
id If PERF_SAMPLE_ID is enabled, a 64-bit unique ID is included. If the event is a member of an event group, the group leader ID is returned. This ID is the same as the one returned by PERF_FORMAT_ID.
stream_id If PERF_SAMPLE_STREAM_ID is enabled, a 64-bit unique ID is included. Unlike PERF_SAMPLE_ID the actual ID is returned, not the group leader. This ID is the same as the one returned by PERF_FORMAT_ID.
But the problem is here: the documentation seems to be incoherent.
Have I missed something ?
Thanks for your attention.
The main reason for the presence of PERF_SAMPLE_STREAM_ID is to maintain event IDs of inherited counters. While the PERF_SAMPLE_ID will contain the event ID of the parent counters. (if there is any parent-child relationship).
Inherited counters are those counters which are allotted to child tasks, originating from the parent task which is being profiled (unless the flag --no-inherit is being passed to perf command).
This detail is described in this old commit.
Looking at the latest source code here,
if (sample_type & (PERF_SAMPLE_ID | PERF_SAMPLE_IDENTIFIER))
data->id = primary_event_id(event);
if (sample_type & PERF_SAMPLE_STREAM_ID)
data->stream_id = event->id;
....
/*
* If we inherit events we want to return the parent event id
* to userspace.
*/
static u64 primary_event_id(struct perf_event *event)
{
u64 id = event->id;
if (event->parent)
id = event->parent->id;
return id;
}
The above snippet of code clearly distinguishes between the two members of the structure. This is irrespective of whether the event is a group leader or not.
Also, it is important to note that, all the events in a group will also compute/use this primary_event_id function. This can be seen here. So, all the events in a group will contain the id of the group leader.