I am working with YRDKRL78 G13 board. I am using IAR v.2.20 for compiler and ı have created a C++ project on it. And I am using one framework. Anyway I have implemented all my codes and which is working correctly but after 2 minutes IAR is giving information as "The Application is aborted" and "Program exit is reached." I am really confuse about it I used very large stack as 512 and near is 1024 far is the 4096.
Here is my main.cpp
#include "System.h"
extern "C"
{
#include "r_cg_macrodriver.h"
}
#pragma location = "OPTBYTE"
__root const uint8_t opbyte0 = 0x7EU;
#pragma location = "OPTBYTE"
__root const uint8_t opbyte1 = 0xFFU;
#pragma location = "OPTBYTE"
__root const uint8_t opbyte2 = 0xE8U;
#pragma location = "OPTBYTE"
__root const uint8_t opbyte3 = 0x85U;
/* Set security ID */
#pragma location = "SECUID"
__root const uint8_t secuid[10] =
{0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U};
void main(void)
{
System::SystemInstance().SYS_vInit();
System::SystemInstance().SYS_vStart();
System::SystemInstance().SYS_vRun();
while(1)
{
;
}
}
And here is the iar output. IAR Output Console
If somebody faced like this problem or if somebody has got any solution or idea could you please share with me here
Thanks for the help :)
EDIT:
#rjp Firstly thanks for response. I am using special framework on my board which Quantum leaps. these 3 functions are calling framwork functions and SYS_vRUN is calling endless loop
int_t QF::run(void) {
onStartup(); // startup callback
// the combined event-loop and background-loop of the QV kernel
for (;;) {
R_WDT_Restart();
RepaintLCD();
delay_ms(50); /* Leave some room for the system to respond */
QF_INT_DISABLE();
if (QV_readySet_.notEmpty()) {
uint_fast8_t p = QV_readySet_.findMax();
QMActive *a = active_[p];
QF_INT_ENABLE();
// perform the run-to-completion (RTS) step...
// 1. retrieve the event from the AO's event queue, which by this
// time must be non-empty and The "Vanialla" kernel asserts it.
// 2. dispatch the event to the AO's state machine.
// 3. determine if event is garbage and collect it if so
//
QEvt const *e = a->get_();
a->dispatch(e);
gc(e);
}
else {
// QV::onIdle() must be called with interrupts DISABLED because
// the determination of the idle condition (no events in the
// queues) can change at any time by an interrupt posting events
// to a queue. QV::onIdle() MUST enable interrupts internally,
// perhaps at the same time as putting the CPU into a power-saving
// mode.
QP::QV::onIdle();
}
}
}
End I searched all code for exit() function there is no any. But you mentioned another issue about assertion. here you can see assertion macro and custome implemented assertion function.
#define Q_ASSERT_ID(id_, test_) ((test_) \
? (void)0 : Q_onAssert(&Q_this_module_[0], (int_t)(id_)))
Function;
void Q_onAssert(char const Q_ROM * const file, int line) {
// implement the error-handling policy for your application!!!
QF_INT_DISABLE(); // disable all interrupts
// cause the reset of the CPU...
//WDTCTL = WDTPW | WDTHOLD;
//__asm(" push &0xFFFE");
// return from function does the reset
}
EDIT2:
Most dynamic memory processes are done in the LedFactory Class.
Header
/*
* LedFactory.h
*
* Created on: Aug 3, 2016
* Author: Dev
*/
#ifndef APPLICATION_LED_LEDFACTORY_H_
#define APPLICATION_LED_LEDFACTORY_H_
#include "LedController.h"
class LedFactory {
public:
typedef enum{
LED1,
LED2,
LED3,
LED4,
LED5,
LED6,
}LedTypes;
public:
LedFactory();
virtual ~LedFactory();
LedController * FirstLedFactory(LedTypes ledtype);
LedController * SecondLedFactory(LedTypes ledtype);
LedController * ThirdLedFactory(LedTypes ledtype);
LedController * FourthLedFactory(LedTypes ledtype);
LedController * FifthLedFactory(LedTypes ledtype);
LedController * SixthLedFactory(LedTypes ledtype);
public:
static LedFactory& instance();
};
#endif /* APPLICATION_LED_LEDFACTORY_H_ */
Source file.
/*
* LedFactory.cpp
*
* Created on: Aug 3, 2016
* Author: Dev
*/
#include <LedFactory.h>
#include "FirstLed.h"
#include "SecondLed.h"
#include "ThirdLed.h"
#include "FourthLed.h"
#include "FifthLed.h"
#include "SixthLed.h"
LedFactory::LedFactory() {
// TODO Auto-generated constructor stub
}
LedFactory::~LedFactory() {
// TODO Auto-generated destructor stub
}
LedFactory& LedFactory::instance()
{
static LedFactory instance;
return instance;
}
LedController * LedFactory::FirstLedFactory(LedTypes ledtype)
{
if(ledtype == (LedTypes)LED1)
{
return new FirstLed;
}
return NULL;
}
LedController * LedFactory::SecondLedFactory(LedTypes ledtype)
{
if(ledtype == (LedTypes)LED2)
return new SecondLed;
return NULL;
}
LedController * LedFactory::ThirdLedFactory(LedTypes ledtype)
{
if(ledtype == (LedTypes)LED3)
{
return new ThirdLed;
}
return NULL;
}
LedController * LedFactory::FourthLedFactory(LedTypes ledtype)
{
if(ledtype == (LedTypes)LED4)
{
return new FourthLed;
}
return NULL;
}
LedController * LedFactory::FifthLedFactory(LedTypes ledtype)
{
if(ledtype == (LedTypes)LED5)
{
return new FifthLed;
}
return NULL;
}
LedController * LedFactory::SixthLedFactory(LedTypes ledtype)
{
if(ledtype ==(LedTypes)LED6)
{
return new SixthLed;
}
return NULL;
}
Should I remove that class for increase the dynamic allocation memory issue ?
Or how can I fix this class ?
Problem has been solved. Main reason was the dynamic memory allocation processes which is used at the factory class.
Related
I've sort of programmed myself into a corner and in the process, realized that I am really lacking in my understanding of c++ function pointers as well as virtual functions. The goal is to implement a temperature controller on a raspberry pi. I won't go into detail on the other components as they are not relevant. I am currently working on the button controller. This is more of an architecture question.
TempCtrl is the main class that calls all others. It also calls the ButtonController::addButton() to register buttons, and contains the callbacks.
ButtonCtrl reads the gpio registers and cycles through the registered buttons stored in a vector of type Button.
Button class was supposed to be a very simple container which had nothing other than an integer specifying the gpio, and callbacks. This is where the problem is.
I've never really done anything like this before, but I wanted something really clean. Basically, once I finish the button controller I wanted to be able to leave it alone unless I was adding functionality. For this reason, I wanted callback functions to be defined in the TempCtrl Function.
So far this has not worked. I'm sure my syntax is off if it is even possible. I would also be interested in alternative ways of achieving this.
Code below. I only posted the relevant headers, and the buttoncontroller.cpp as there is quite a lot of code. I will be glad to post more code if more information is needed, so please just ask:
button.hpp
#ifndef BUTTON_HPP
#define BUTTON_HPP
#include <ctime>
#include <cstdint>
#define HOLDTIME 500 // milliseconds
class TempCtrl;
enum State_E
{
BP_LOW,
BP_HIGH
};
class Button
{
public:
Button(
uint8_t _gpio,
void(TempCtrl::*)(),
void(TempCtrl::*)(),
void(TempCtrl::*)());
~Button();
void update(State_E newValue);
uint8_t getGpio() const;
private:
void (TempCtrl::*onFallingEdge)();
void (TempCtrl::*onLongHold)();
void (TempCtrl::*onRisingEdge)();
uint8_t gpio;
State_E state;
time_t timeStamp;
};
#endif /* BUTTON_HPP */
buttonprocessor.hpp
#ifndef BUTTONPROCESSOR_HPP
#define BUTTONPROCESSOR_HPP
#include "button.hpp"
#include <cstdint>
#include <vector>
#define GPIO_MAX 53
#define BLOCK_SIZE (4*1024)
#define GPLEV0 13
#define GPLEV1 14
#define SCAN_RATE 100 // milliseconds
class ButtonProcessor
{
public:
ButtonProcessor();
virtual ~ButtonProcessor();
bool init();
bool shutdown();
size_t addButton(Button button);
void startEventLoop(bool &terminate);
private:
int fd;
volatile uint32_t *gpio_base;
std::vector<Button> buttonDb;
};
#endif /* BUTTONPROCESSOR_HPP */
tempctrl.hpp
#ifndef TEMPCTRL_HPP
#define TEMPCTRL_HPP
#include "button.hpp"
#include "lcdscreen.hpp"
#include "buttonprocessor.hpp"
#include <cstdlib>
#include <vector>
#include <string>
#include <time.h>
#include <cstring>
#include <memory>
#define W1_DEV_ROOT "/sys/bus/w1/devices/w1_bus_master1/"
#define W1_SLAVE_COUNT W1_DEV_ROOT "w1_master_slave_count"
#define W1_SLAVES W1_DEV_ROOT "w1_master_slaves"
#define POLL_FREQ 1000
/***********************************************
* A structure for holding a single data point *
* of temperature in degrees celsius, as well *
* as the temp probe ID and a time stamp. *
************************************************/
struct TempStruct
{
time_t ts;
std::string id;
float temp;
};
enum TScale_E
{
CELSIUS,
FARENHEIT,
KELVIN,
RANKINE,
MAX_VALUE_TSCALE
};
#define DEFAULT_TEMP_SCALE FARENHEIT
enum InputMode_E
{
SETPOINT,
LOAD_PROFILE,
PID_TUNE,
MAX_VALUE_INPUT_MODE
};
class TempCtrl
{
public:
TempCtrl();
virtual ~TempCtrl();
/***********************************************
* Fetches the current time from the specified *
* temperature controller, and stores the *
* returned value with time stamp and device *
* id, in the tempStruct array.
************************************************/
void getTemp(int);
void setTempScale(TScale_E);
void lcdToggleEnable(int bits);
void wait(size_t seconds);
void printTemp(enum TScale_E);
std::vector<std::string> slavesArr;
std::vector<TempStruct> tempStruct;
TScale_E tempScaleVal = CELSIUS;
int fd;
// These should not be public
void onFallingEdge();
void onLongHold();
void onRisingEdge();
private:
void lcdInit();
uint8_t tempInit(void);
/***********************************************
* exclusive access to atomic safe lcdscreen *
* manipulation. Logic is completely decoupled *
************************************************/
std::unique_ptr<LcdScreen> mLcdScreen;
/***********************************************
* The responsibility of the button processor *
* is to detect edge changes in for specified *
* GPIO's, determine the type of press and call *
* the relavant callback. *
************************************************/
std::unique_ptr<ButtonProcessor> mButtonProcessor;
};
#endif /* TEMPCTRL_HPP */
buttonprocessor.cpp
#include "button.hpp"
Button::Button(
uint8_t _gpio,
void(TempCtrl::*_onFallingEdge)(),
void(TempCtrl::*_onLongHold)(),
void(TempCtrl::*_onRisingEdge)())
: state(BP_LOW),
timeStamp(time(NULL)),
onFallingEdge(_onFallingEdge),
onLongHold(_onLongHold),
onRisingEdge(_onRisingEdge)
{
}
Button::~Button()
{
}
void Button::update(State_E newValue)
{
if(
newValue != state &&
state == BP_HIGH) // Rising edge
{
timeStamp = time(NULL);
state = newValue;
// ((Button*)this)->Button::onRisingEdge();
}
else if(
state == BP_HIGH &&
newValue == state &&
((time(NULL) - timeStamp) > HOLDTIME)) // Long Hold
{
timeStamp = time(NULL);
state = newValue;
// ((Button*)this)->Button::onLongHold();
}
else if(
newValue != state &&
state == BP_LOW) // Falling edge
{
timeStamp = time(NULL);
state = newValue;
TempCtrl.(*((Button*)this)->Button::onFallingEdge());
//onFallingEdge();
}
}
uint8_t Button::getGpio() const
{
return gpio;
}
I am tasked with implementing a many-to-many thread manager in C++. I've got most of it more or less down, but I'm having serious problems with swapcontext in my uthread_yield() method. Here's the code
/*
* uthread.cpp
*
* Created on: Oct 12, 2016
* Author: michael
*/
#include "uthread.h"
#include <semaphore.h>
#include <pthread.h>
#ifndef STDIO_H_
#include <stdio.h>
#endif
namespace std {
/*
* Initializes all the variables and allocates memory when needed
*/
int uthread::maxThreads;
int uthread::currentThreads;
pthread_mutex_t uthread::mapMutex;
pthread_mutex_t uthread::qMutex;
pthread_mutex_t uthread::threadMutex;
map<int,UserThread*>* uthread::threadMap;
priority_queue<UserThread*>* uthread::threadQueue;
void uthread::uthread_init(int numKernelThreads) {
pthread_mutex_t tester;
pthread_mutex_init(&tester,NULL);
uthread::maxThreads=numKernelThreads;
uthread::currentThreads=0;
pthread_mutex_init(&threadMutex,NULL);
pthread_mutex_init(&qMutex,NULL);
pthread_mutex_init(&mapMutex,NULL);
threadQueue= new priority_queue<UserThread*>;
threadMap=new map<int,UserThread*>;
}
int uthread::uthread_create(void (* func)( )) {
//Create ucontext to be used in in
ucontext_t* ucp=(ucontext_t*)malloc(sizeof(ucontext_t));
getcontext(ucp);
ucp->uc_stack.ss_sp=(void*)malloc(16384);
ucp->uc_stack.ss_size=16384;
makecontext(ucp, func, 0); //make the context for a thread running func
//Create UserThread
time_t currTime;
time(&currTime);
UserThread* newThread=new UserThread(ucp,currTime);
//Thread Creation Logic
pthread_mutex_lock(&threadMutex);
if (currentThreads>=maxThreads) {
pthread_mutex_unlock(&threadMutex);
pthread_mutex_lock(&qMutex);
threadQueue->push(newThread);
pthread_mutex_unlock(&qMutex);
return 0;
}
else {
int (*execute)(void *)= (int (*)(void *)) func;
int tid=clone(execute,ucp->uc_stack.ss_sp,CLONE_VM|CLONE_FILES,NULL);
if (tid==-1) { //clone failed
pthread_mutex_unlock(&threadMutex);
return -1;
}
currentThreads++;
pthread_mutex_unlock(&threadMutex);
/*
* Map tid -> UserThread in thread map
*/
threadMap->insert(pair<int,UserThread*>(tid,newThread));
pthread_mutex_unlock(&mapMutex);
return 0;
}
return -1;
}
void uthread::uthread_exit() {
/*
* Get the corresponding UserThread object from the map
*/
printf("Start Exit \n");
int threadID=syscall(SYS_gettid) ;
pthread_mutex_lock(&mapMutex);
if (threadMap->find(threadID)==threadMap->end()) { //Cannot find map;
pthread_mutex_lock(&threadMutex);
currentThreads--;
pthread_mutex_unlock(&threadMutex);
exit(0);
}
printf("Getting Curr Thread\n");
UserThread* currThread= threadMap->at(threadID);
pthread_mutex_unlock(&mapMutex);
pthread_mutex_lock(&qMutex);
if (threadQueue->empty()) { //No items on queue, delete memory references and exit
printf("Queue is Empty");
pthread_mutex_unlock(&qMutex);
pthread_mutex_lock(&mapMutex);
threadMap->erase(threadID);
pthread_mutex_unlock(&mapMutex);
pthread_mutex_lock(&threadMutex);
currentThreads--;
pthread_mutex_unlock(&threadMutex);
delete currThread;
exit(0);
}
else { //Remove and delete memory reference to old thread, set context to new thread
printf("Swapping Queue\n");
UserThread* newThread=threadQueue->top();
threadQueue->pop();
pthread_mutex_unlock(&qMutex);
pthread_mutex_lock(&mapMutex);
threadMap->insert(pair<int,UserThread*>(threadID,newThread)); //Update Map
pthread_mutex_unlock(&mapMutex);
printf("Deleting Current Thread\n");
delete currThread;
printf("Setting Context\n");
setcontext(newThread->ucp);
printf("set context failed\n");
}
}
void uthread::uthread_yield() {
printf("Start Yield \n");
int threadID=syscall(SYS_gettid) ;
pthread_mutex_lock(&mapMutex);
UserThread* currThread= threadMap->at(threadID);
pthread_mutex_unlock(&mapMutex);
pthread_mutex_lock(&qMutex);
if (threadQueue->empty()) {
printf("Queue is empty\n");
pthread_mutex_unlock(&qMutex);
return;
}
else {
printf("Queue Not Empty\n");
currThread->updateRuntime(time(NULL)); //updates run time account for time it's been on thread
UserThread* highestPriority=threadQueue->top();
if (highestPriority->getRunTime()>currThread->getRunTime()) { //highestPriority is lower priority than currently running thread
printf("lowest runtime is running\n");
pthread_mutex_unlock(&qMutex);
return;
}
else {
printf("SwapContext\n");
threadQueue->pop();
threadQueue->push(currThread);
pthread_mutex_unlock(&qMutex);
pthread_mutex_lock(&mapMutex);
threadMap->insert(pair<int,UserThread*>(threadID,highestPriority)); //Update Map reference
pthread_mutex_unlock(&mapMutex);
//Swaps contexts
swapcontext(currThread->ucp,highestPriority->ucp);
printf("Swapcontext Failed\n");
}
}
}
int uthread::startThread(void* arg ) {
printf("Thread Cloned\n");
pthread_mutex_lock(&mapMutex);
int threadID=syscall(SYS_gettid) ;
UserThread* currThread= threadMap->at(threadID);
pthread_mutex_unlock(&mapMutex);
setcontext(currThread->ucp);
return 0;
}
}
And this is the code of my corresponding UserThread object:
/*
* UserThread.cpp
*
* Created on: Oct 12, 2016
* Author: michael
*/
#include "UserThread.h"
/*
* Constructor. UCP is taken in as well as start time
* Run time initialized to 0
*
*/
UserThread::UserThread(ucontext_t *ucp,time_t st) {
this->ucp=ucp;
this->startTime=(time_t*)malloc(sizeof(time_t));
this->runTime=(double*)malloc(sizeof(double));
*startTime=st;
*runTime=0;
}
/**
* Deconstructor
*/
UserThread::~UserThread() {
//free(ucp->uc_stack.ss_sp);
//free(ucp);
free(startTime);
free(runTime);
}
/*
* adds the running time in seconds (as a double) to the current running time. Also updates the start time
*/
void UserThread::updateRuntime(time_t currTime) {
double diffTime=difftime(currTime,*startTime);
*runTime=*runTime+diffTime;
*startTime=currTime;
}
/*
* Just Updates the start time
*/
void UserThread::updateStartTime(time_t newTime) {
*startTime=newTime;
}
/*
* getter
*/
double UserThread::getRunTime() {
double rTime=*runTime;
return rTime;
}
/*
* getter
*/
time_t UserThread::getStartTime() {
return *startTime;
}
/*
* THIS IS REVERSED ON PURPOSE. C++ runs a maximum priority queue by default
* by overloading the < operator backwards, that isn't an issue. Sketchy? Yes
* Also functional
*/
bool UserThread::operator <(UserThread* t2) {
return this->getRunTime() > t2->getRunTime();
}
uthread_yield() will correctly work once for each thread, then fail. Any idea why this is? I've stared at this code for hours and at this point I'm out of ideas.
It's not actually failing: it's just printing your failure message. Your yield implementation finishes with:
swapcontext(currThread->ucp, highestPriority->ucp);
printf("Swapcontext Failed\n");
So the yielding thread swaps away after swapcontext(), which is fine - but when that thread is later swapped back to, it will return from swapcontext() and unconditionally execute the printf(). You need:
if (swapcontext(currThread->ucp, highestPriority->ucp) == -1) {
printf("Swapcontext Failed\n");
/* You need to fix up your queue and map here to account for the
* failure to context switch, and then probably loop back and look
* for another candidate thread to swap to. */
}
I also noticed that your uthread_create() function accesses the map and unlocks mapMutex without locking the mutex first.
You're mixing pthreads functions with the bare clone() syscall, which is unsupported. Use pthread_create() / pthread_exit() for managing the underlying threads. One way to do this is by having thread created by pthread_create() start at a scheduling function that pulls the thread to run from your queue:
void* uthread::newThread(void* arg)
{
pthread_mutex_lock(&qMutex);
if (threadQueue->empty()) {
printf("No thread to start.\n");
return NULL;
}
UserThread* highestPriority = threadQueue->top();
threadQueue->pop();
pthread_mutex_unlock(&qMutex);
int threadID = syscall(SYS_gettid);
pthread_mutex_lock(&mapMutex);
threadMap->insert(pair<int,UserThread*>(threadID,highestPriority)); //Update Map reference
pthread_mutex_unlock(&mapMutex);
setcontext(highestPriority->ucp);
printf("setcontext() Failed\n");
return NULL;
}
...then you can simplify uthread_create() by always pushing the new user thread onto the queue, and only conditionally creating the underlying thread:
// ... start of uthread_create() up to creating new UserThread ...
pthread_mutex_lock(&qMutex);
threadQueue->push(newThread);
pthread_mutex_unlock(&qMutex);
//Thread Creation Logic
pthread_mutex_lock(&threadMutex);
if (currentThreads < maxThreads) {
pthread_t new_pthread;
if (pthread_create(*new_pthread, NULL, uthread::newThread, NULL) != 0) {
printf("New pthread creation failed.\n");
} else {
currentThreads++;
}
}
pthread_mutex_unlock(&threadMutex);
return 0;
By the way, it seems that you're using the threadMap just as a way to implement thread-local-storage: you could instead use the built-in pthreads thread-local-storage API (pthread_key_create() / pthread_setspecific() / pthread_getspecific()).
I'm trying to access a custom IP block from GNU Radio [ZedBoard] using /dev/mem. I tested the code routine writing and doing iterative reading from /dev/mem from a local c file. The code running directly from the console correctly sets the registers and reads the correct values back.
I made a custom GNU Radio block using this code but when executing the grc flow python script I receive the error that /dev/mem was not accessible.
I know that this is NOT a safe way to interact with the device and am working on a driver to replace this. Currently I need this to work for testing and development. I went so far as to change permissions to /dev/mem to 777, I added my local user (Linaro) to the kmem group as well. I execute the python file for the flowgraph using sudo as well.
What am I overlooking? Thank you.
edit: Adding the output error is : "Permission Denied" if run from sudo after chmod 777 /dev/mem the error is : "Operation not permitted"
/* -*- c++ -*- */
/*
* Copyright 1970 <+YOU OR YOUR COMPANY+>.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "qpskModulator_impl.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#define READ 0
#define WRITE 1
#define SAMPLES 64
#define INPUT_WIDTH 32
int memmap_fpga(int direction, char * address, float value);
namespace gr {
namespace fpga_accelerators {
qpskModulator::sptr
qpskModulator::make()
{
return gnuradio::get_initial_sptr
(new qpskModulator_impl());
}
/*
* The private constructor
*/
qpskModulator_impl::qpskModulator_impl()
: gr::block("qpskModulator",
gr::io_signature::make(1, 1, sizeof(float)),
gr::io_signature::make(2, 2, sizeof(short)))
{}
/*
* Our virtual destructor.
*/
qpskModulator_impl::~qpskModulator_impl()
{
}
void
qpskModulator_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
{
ninput_items_required[0] = noutput_items;
ninput_items_required[1] = noutput_items;
}
int
qpskModulator_impl::general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const float *in = (const float *) input_items[0];
short *out0 = (short *) output_items[0]; // I CHANNEL
short *out1 = (short *) output_items[1]; // Q CHANNEL
short data_valid;
const float BLANK = 0;
float GO = 1;
//int hwI_mod[SAMPLES*INPUT_WIDTH/2];
//int hwQ_mod[SAMPLES*INPUT_WIDTH/2];
int i;
char * DATA_IN_ADDR = "0x43c00004";
char * GO_ADDR = "0x43c00000";
char * DATA_OUT_ADDR = "0x43c00008";
char * DATA_VALID_ADDR = "0x43c0000C";
// transfer input array and size to FPGA
memmap_fpga(WRITE, DATA_IN_ADDR, *in);
memmap_fpga(WRITE, GO_ADDR, GO); // assert go
GO = 0;
memmap_fpga(WRITE, GO_ADDR, GO); // reset go value
data_valid = 0;
while (data_valid == 0) {
data_valid = memmap_fpga(READ, DATA_VALID_ADDR, BLANK);
}
// read the outputs back from the FPGA
unsigned temp_dataout;
unsigned y;
for (i=0; i < SAMPLES*INPUT_WIDTH/2 - 8; i++)
{
temp_dataout = memmap_fpga(READ, DATA_OUT_ADDR, BLANK);
out0[i] = temp_dataout & 0xfff; // I channel
y = out0[i] >> 11;
if (y == 1)
out0[i] = out0[i] - 4096;
out1[i] = (temp_dataout >> 12) & 0xfff;
y = out1[i] >> 11;
if (y == 1)
out1[i] = out1[i] - 4096;
//printf("%d: HW: I_mod = %d and Q_mod = %d\n", i, hwI_mod[i], hwQ_mod[i]);
}
// Do <+signal processing+>
// Tell runtime system how many input items we consumed on
// each input stream.
consume_each (noutput_items);
// Tell runtime system how many output items we produced.
return noutput_items;
}
} /* namespace fpga_accelerators */
} /* namespace gr */
int memmap_fpga(int direction, char * address, float value){
unsigned gpio_addr = strtoul(address, NULL, 0);
/* DEBUG INFO
printf("address: %08x\n",gpio_addr);
if (direction == IN)
printf("direction: IN\n");
else
printf("direction: OUT\n");
printf("value: %d\n",value);
*/
int fd;
unsigned page_addr, page_offset;
void *ptr;
unsigned page_size=sysconf(_SC_PAGESIZE);
short temp_value;
if (gpio_addr == 0) {
printf("GPIO physical address is required.\n");
return -1;
}
/* Open /dev/mem file */
fd = open ("/dev/mem", O_RDWR);
if (fd < 1) {
printf("Couldn't open /dev/mem\n");
return -1;
}
/* mmap the device into memory */
page_addr = (gpio_addr & (~(page_size-1)));
page_offset = gpio_addr - page_addr;
ptr = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, page_addr);
if (direction == READ) {
/* Read value from the device register */
temp_value = *((unsigned *)(ptr + page_offset));
//printf("gpio dev-mem test: input: %08x\n",temp_value);
munmap(ptr, page_size);
return(temp_value);
} else {
/* Write value to the device register */
*((unsigned *)(ptr + page_offset)) = value;
munmap(ptr, page_size);
//printf("Wrote to register\n");
}
munmap(ptr, page_size);
return 0;
}
Two things:
You open and memmap the same file for Read/Write access multiple times, without closing it in between – that's a recipe for disaster. Maybe you're just running out of file descriptors (there's a limit on that). Actually reading the errno (you should be doing that!!) would tell you the reason.
Then: Even opening and closing the file repeatedly is a bad idea, performance wise– just open and mmap it once in the constructor. There's no advantage reopening it constantly.
I'm writing a new Agent which can be used in one host connected with at least four node.
And the host with traffic generator will send packet to client,after a delay
it will be sended to host again. And the information calculation will be in host.
However, in my test.tcl (only two nodes) the packet receive in client seems didn't
send back to host.
Could somebody give me a hand?
Did the send function any obvious wrong?
Should I assign the ip header or the target_ or anything variables to send back my packet?
AgentCPU.h
#ifndef ns_cpu_h
#define ns_cpu_h
#include <tclcl.h>
#include "agent.h"
#include "config.h"
#include "packet.h"
#include "trafgen.h"
#define SAMPLERATE 8000
struct hdr_task {
int total_time;
int size_;
int number;
int& size() { return size_;}
static int offset_;
inline static int& offset() { return offset_; }
inline static hdr_task* access (const Packet* p) {
return (hdr_task*) p->access(offset_);
}
};
class AgentCPU : public Agent {
public:
AgentCPU();
virtual void recv(Packet *, Handler *);
virtual void sendmsg(int nbytes, const char *flags = 0);
private:
double busy_time_;
float execute_time_;
float execute_time_exp;
double record_packet_Time_;
int npkts_;
};
#endif
AgentCPU.cc
#include "AgentCPU.h"
#include "packet.h"
#include "random.h"
#include "ip.h"
int hdr_task::offset_;
static class TASKHeaderClass : public PacketHeaderClass {
public:
TASKHeaderClass()
:PacketHeaderClass("PacketHeader/TASKHEAD",sizeof(hdr_task)) {
bind_offset(&hdr_task::offset_);
}
} class_task_hdr;
static class CPUClass : public TclClass {
public:
CPUClass() : TclClass("Agent/AgentCPU") {}
TclObject* create(int, const char*const*) {
return (new AgentCPU());
}
} class_cpu_agent;
AgentCPU::AgentCPU() : Agent(PT_TASK)
{
npkts_=0;
record_packet_Time_=0.0;
bind("packetSize_",&size_);
bind("record_packet_Time_",&record_packet_Time_);
bind("npkt_",&npkts_);
}
void AgentCPU::sendmsg(int nbytes, const char* flags)
{
Packet *pkt =allocpkt();
test++;
hdr_cmn *ch = hdr_cmn::access(pkt);
hdr_ip *iph= hdr_ip::access(pkt);
hdr_task *task= hdr_task::access(pkt);
task->number=Random::exponential(5000);
task->state=0;
task->total_time=0;
target_->recv(pkt);
idle();
}
void AgentCPU::recv(Packet* pkt, Handler*)
{
hdr_task *task= hdr_task::access(pkt);
if(task->state==1)
{
if(task->number >2500)
{
task -> total_time += 2500;
task -> number -=2500;
task -> state=0;
// printf("exe 2500 and the packet exe number is %d\n",task->number);
target_->recv(pkt, (Handler*)0);
}
else
{
task ->total_time += task->number ;
task ->number =0;
++npkts_;
record_packet_Time_+= task ->total_time;
Tcl& tcl =Tcl::instance();
Packet::free(pkt);
}
}
else if (task->state==0)
{
int hold_time =Random::exponential(2000);
task->total_time += hold_time;
task->state=1;
Scheduler& s =Scheduler::instance();
double delay = Random::exponential(0.2);
s.schedule(target_,pkt,delay);
}
}
I had tried to modyfied the saddr() and daddr() field in ip header
when I traced the recv packet two field , and the value is 0 and 1
I think they are represent the two node.
So I exchange the two value so the src address and the dest address will exchange
and the packet will be send back to host.
But it results in Seg fault ..
I have solved this problem
I added ip header for the packet I received
hdr_ip* ip=hdr_ip::access(pkt);
ip.daddr()=1; // this int represent the node in your tcl script
However, I have another problem
It will crash when use my tcl script
after use valgrind , the program which can help you detect the memory leak
I know how stupid this question is ,
I guess is the trace format cause this error
ie. I didnt impelment the correct "Trace::format" for my new Packet type
And I didnt comment the trace file code in my tcl script like this
set nf [open out.nam w]
$nf nametrace-all $nf
...
...
And when I comment these code (include the procedure "finish")
All things work! The packet can send to specified node And no Segment Fault
Hope this can help someone who has the same question like me
I have very weird problem with a library I am creating. The library will be used to communicate between Arduino modules using XBee Series 1 modules. Library is very simple wrapper library around Arduino XBee library.
I have one function that reads received packet and sends it back. At the moment it is implemented as a simple "echo" service - the function just displays the data received and sends it back to per-defined address.
At the moment I have three versions of this function, out of which one is not working.
A function taking no arguments: void processPacket()
A function taking structure as a value as an argument: void processPacket(valuesStruct valuesStructData) - THIS VERSION OF THE FUNCTION IS NOT WORKING!
A function taking pointer to the structure as an argument: void processPacket(valuesStruct* valuesStructData)
At this moment I noticed strange behavior in the 2nd version of the function. I do nothing with the passed argument - the content of all three functions is the same. In 2nd case the function reads wrong values from received XBee packet. In the 1st and 3rd case the function performs correctly.
Code:
ExampleLib.h
#ifndef ExampleLib_h
#define ExampleLib_h
#include "Arduino.h"
#include <XBee.h>
#define ADDRESS_BROADCAST 0xffff
#define ADDRESS_PC 0x3333
typedef struct
{
int valA;
int valB;
int valC;
} valuesStruct;
class ExampleLib
{
public:
ExampleLib();
void setSerial(Stream &serial);
boolean tryReceivePacket();
void processPacket();
// THIS FUNCTION IS NOT WORKING!
void processPacket(valuesStruct valuesStructData);
void processPacket(valuesStruct* valuesStructData);
private:
XBee xbee;
Rx16Response rx16;
};
#endif
ExampleLib.cpp
The value read in line byte* packetData = rx16.getData(); is wrong when we trigger processPacket(valuesStruct valuesStructData) function. In other cases the behavior is correct.
#include "Arduino.h"
#include <XBee.h>
#include "ExampleLib.h"
ExampleLib::ExampleLib()
{
xbee = XBee();
rx16 = Rx16Response();
}
void ExampleLib::setSerial(Stream &serial)
{
xbee.setSerial(serial);
}
boolean ExampleLib::tryReceivePacket()
{
xbee.readPacket();
if (xbee.getResponse().isAvailable()) {
// got something
if (xbee.getResponse().getApiId() == RX_16_RESPONSE) {
// got a rx packet
xbee.getResponse().getRx16Response(rx16);
return true;
}
else {
return false;
}
}
else if (xbee.getResponse().isError()) {
//nss.print("Error reading packet. Error code: ");
//nss.println(xbee.getResponse().getErrorCode());
// or flash error led
return false;
}
return false;
}
void ExampleLib::processPacket()
{
byte* packetData = rx16.getData();
byte dataLength = rx16.getDataLength();
Serial.print("START L:");
Serial.println(dataLength);
for (int i = 0; i < dataLength; i++) {
Serial.print(packetData[i]);
Serial.print(" - ");
}
Serial.println("END");
//16-bit addressing: Enter address of remote XBee, typically the coordinator
Tx16Request tx = Tx16Request(ADDRESS_PC, packetData, sizeof(packetData));
xbee.send(tx);
}
void ExampleLib::processPacket(valuesStruct valuesStructData)
{
processPacket();
}
void ExampleLib::processPacket(valuesStruct* valuesStructData)
{
processPacket();
}
Arduino sketch
#include <XBee.h>
#include <ExampleLib.h>
ExampleLib exampleLibObj = ExampleLib();
void setup()
{
Serial.begin(9600);
exampleLibObj.setSerial(Serial);
}
void loop()
{
boolean isPacketReceived = exampleLibObj.tryReceivePacket();
if (isPacketReceived) {
// leave only one section, the rest should be commented
//Section 1: working
exampleLibObj.processPacket();
//Section 2: not working
// valuesStruct test;
// test.valA = 0;
// test.valB = 0;
// test.valC = 0;
// exampleLibObj.processPacket(test);
//Section 3: working
// valuesStruct* test;
// test->valA = 0;
// test->valB = 0;
// test->valC = 0;
// exampleLibObj.processPacket(test);
}
}
I am really puzzled why in this one case function is performing differently. Looking forward to any suggestions to that issue.
Thanks,
Michal
Are you sure it isn't your section 3 that's causing problems? Because you're declaring a pointer to a structure, but not allocating memory for that structure.
You'd typically write your code like this:
valuesStruct test;
test.valA = 0;
test.valB = 0;
test.valC = 0;
//Section 2: not working
exampleLibObj.processPacket(test);
//Section 3: working
exampleLibObj.processPacket(&test);
But you also wouldn't typically pass a structure to a function -- you'd pass a pointer to that structure. There really isn't a need for your second sample.