I am writing a GUI for a small monochromatic display and I want to update the data on the screen every second.
The data is stored in a redis database and I am trying to coordinate using pthread, libev, and asynchronous hiredis calls.
My plan is to have a thread that pulls new data from the database every second and store a local copy for quick access.
Another thread that updates the screen will access that data at will without having to wait for database access.
First question, is my approach correct?
Second question, why am I having trouble polling the database every second? I think I can switch to a synchronous method and get it to work but is that the right approach?
Here is the relevant code:
int main(int argc, char *argv[])
{
pthread_t dataThread;
pthread_t guiThread;
pthread_create(&dataThread, NULL, dataHandler, NULL);
pthread_create(&guiThread, NULL, guiHandler, NULL);
while (true)
{
sleep(10);
}
return 0;
}
In the following, if I move ev_loop(EV_DEFAULT_ 0); inside the while loop after the redisAsync commands my callback gets called for the first loop but never again. The way it sits, my callback never gets called.
void* dataHandler(void *ptr)
{
m_ctx = redisAsyncConnect("127.0.0.1", 6379);
if (m_ctx->err) {
printf("Redis async connection failed. Error: %s\n", m_ctx->errstr);
exit(-1);
}
redisLibevAttach(EV_DEFAULT_ m_ctx);
redisAsyncSetConnectCallback(m_ctx,connectCallback);
redisAsyncSetDisconnectCallback(m_ctx,disconnectCallback);
ev_loop(EV_DEFAULT_ 0);
while (true)
{
int result;
result = redisAsyncCommand(m_ctx, updateCallback, (char*)"data1", "HGET data1 data");
printf("result: %d\n", result);
result = redisAsyncCommand(m_ctx, updateCallback, (char*)"data2", "HGET data2 data");
printf("result: %d\n", result);
//ev_loop(EV_DEFAULT_ 0); <- this will work one time
}
redisAsyncDisconnect(m_ctx);
return 0;
}
void updateCallback(redisAsyncContext *c, void *r, void *privdata)
{
redisReply *reply = (redisReply*)r;
if (reply == NULL) return;
printf("%s: %s\n", (char*)privdata, reply->str);
}
void* guiHandler(void *ptr)
{
while (true)
{
// Update the GUI accordingly
sleep(1);
}
}
Firstly, I would recommend you to read the manual for libev before using it :
http://man7.org/linux/man-pages/man3/event.3.html
Now for your code,
ev_loop function will start an event loop that you only "feed" it with 2 HGET operations.
In order to add more operations you need to add attach events for the event loop but I'm not sure it will be the right approach for you case.
If the purpose of your thread is just to fetch the db every X seconds why are you using the async approach at all? IMO just use the hiredis sync API
Related
Not important:
I am doing a project to integrate a bluetooth module into a car radio pioneer. I understand perfectly well that it's easier to buy a new one =) but it's not interesting. At the moment, the byproduct was an adapter on arduino of resistor buttons, which the pioneer did not understand. The same adapter also controls the bluetooth board, it can switch the track forward and backward (there is no button on the steering wheel for pause). Now I want the bluetooth to turn on only in AUX mode. But there is a problem, which mode can be understood only by reading the signal from the SPI bus of the commutation microcircuit. I was able to read this data using arduino nano. I do not have an analyzer, but it is not necessary that I would understand something additional with it.
Essence of the question:
Using the scientific poke method, I found sequences indicating the launch of a particular mode, for example:
10110011
1
111
1000000
I'm sure I'm doing it wrong, but in the meantime I get duplicate results. But, when I try to detect them using IF, the nano speed is not enough and the chip starts to pass data.
#include "SPI.h"
bool flag01, flag02, flag03, flag11, flag12, flag13, flag31, flag32, flag33;
void setup (void)
{
Serial.begin(9600);
pinMode(MISO, OUTPUT);
SPCR |= _BV(SPE);
SPI.attachInterrupt();
}
// Вызываем функцию обработки прерываний по вектору SPI
// STC - Serial Transfer Comlete
ISR(SPI_STC_vect)
{
// Получаем байт из регистра данных SPI
byte c = SPDR;
Serial.println(c, BIN);
if (c == 0b1) {
Serial.println("1 ok");
flag11 = true;
} else {
flag11 = false;
}
if (c == 0b11 && flag11) {
Serial.println("11 ok");
flag12 = true;
} else {
flag12 = false;
flag11 = false;
}
if (c == 0b1100000 && flag11 && flag12) {
Serial.println("1100000 ok");
flag13 = true;
} else {
flag13 = false;
flag12 = false;
flag11 = false;
}
}
void loop(void)
{}
I myself am scared to look at this code, but I cannot think of anything better. It seems like I heard about some kind of buffer, but I don't know how to screw it to this solution. After all, the data packets go with dropping the CS signal and I can’t figure out how to determine the beginning and end of the packet from the commands in order to write it to a buffer or array and only then go through it with a comparison.
I will be grateful if someone will tell me at least in which direction to move.
There is also esp8266, but there is a limitation on the size of a data packet of 32 bits in a slave mode and I do not know how to get around it correctly.
So, actually the question.
How can I optimize the code so that the arduino has time to process the data and I can catch the pattern?
Perhaps, if we implement reading of data of arbitrary length on esp8266, or at least fill them to the required length, it would help me. But I still can't figure it out with the spi.slave library.
First you should keep your ISR as short as possible, certainly don't use Serial print inside the ISR.
Secondly, if you don't know exactly how long the data is, then you need to have a buffer to capture the data and try to determine the data length first before you trying to analysis it.
volatile uint8_t byteCount = 0;
volatile bool dataReady = false;
byte data[32];
// SPI interrupt routine
ISR (SPI_STC_vect)
{
data[byteCount++] = SPDR;
dataReady = true;
}
void setup (void)
{
// your SPI and Serial setup code
}
void loop (void)
{
// for determine the data stream length
if (dataReady) {
Serial.println(byteCount);
dataReady = false;
}
}
Once you know how long the data stream is (let assumed it is 15-byte long), you can then change your sketch slightly to capture the data and analysis it.
volatile uint8_t byteCount = 0;
volatile bool dataReady = false;
byte data[32];
// SPI interrupt routine
ISR (SPI_STC_vect)
{
data[byteCount++] = SPDR;
if (byteCount == 15)
dataReady = true;
}
void loop (void)
{
if (dataReady) {
dataReady = false;
// do your analysis here
}
}
What I'm trying to do is fairly simple. Transmit through DMA and wait till it gets transmitted. And then receive and wait till it is received.
When I comment out the receive part(including the call back), it is going into the transmit complete call back function. But when I un-comment the receive portion, it is not going into the tx cplt call back and it is directly going into the receive cplt callback. And when I check the receive buffer I'm not getting what I expected(obviously). What could have gone wrong?
I'm using Atollic True Studio V 9.0 , CubeMx v5.1.0, STM32F407VG-DISC1 board and enabled DMA for UART2.
I've tried sending char buffer through UART DMA and receive it. It seems it is not transmitting at all as it is not going into txCplt call back. And it is directly going into Rxcplt call back.
uint8_t tx_arr[10], rx_arr[10];
__IO ITStatus UartReady = RESET;
int main(void)
{
int i = 0;
for(i = 0; i<10; i++)
rx_arr[i] = 0;
for(i = 0; i<10; i++)
tx_arr[i] = i*2;
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART6_UART_Init();
MX_USART2_UART_Init();
while (1)
{
if( HAL_UART_Transmit_DMA(&huart2, (uint8_t*)tx_arr, 10)!= HAL_OK )
{
Error_Handler();
}
while(UartReady != SET)
{
}
UartReady = RESET;
if( HAL_UART_Receive_DMA(&huart2, (uint8_t*)rx_arr, 10)!= HAL_OK )
{
Error_Handler();
}
while(UartReady != SET)
{
}
UartReady = RESET;
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
UartReady = SET;
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
UartReady = SET;
}
I expect the rx_arr will get filled by 0,2,4,6,...18 but it is getting filled with junk
As this looks to me, the reason is that you are using the same flag variable from both ISRs, both times doing busy waiting in your main loop.
If you uncomment both handler actions, you will sooner or later end up with a race condition where both handlers put their "SET" value quickly one by one - before the main loop waits for it. Then, the main loop "consumes" this flag by setting the variable back to "RESET". A few lines later, the other waiting loop comes and isn't served (because both ISRs ran earlier and only left a single "SET" value, one overwriting the other). Then, your main loop is stuck.
In order to verify my assumption, you can activate a one-sided watchdog before entering into the main loop, and trigger it every main loop cycle. If the main loop gets stuck as I assume, you will detect that the reset cause points to the watchdog afterwards.
So in class, we learned about semaphores and stuff and our professor let us know that this code below would be handy to learn for our exam. Unfortunately our exam is on Friday, and whole list of excuses, i just need to be able to understand this code for the exam and for future cases. I understand that the mutex_t is a lock system and the cond_t is a condition system in which signals get passed through sema_P and sema_V (if the value is 0, race condition occurs and the thread is locked out by cond_wait until another thread increases the value and is unlocked by cond_signal), but why does a lock need to get passed around? Why is there a mutex_lock and mutex_unlock in both decrementer P() and incrementer V()? How does this work with the threads and the conditions (cont_t)?
typedef struct
{
pthread_mutex_t lock;
pthread_cond_t wait;
int value;
} sema;
void pthread_sema_init(sema *s, int count)
{
s->value = count;
pthread_cond_init(&(s->wait),NULL);
pthread_mutex_init(&(s->lock),NULL);
return;
}
void pthread_sema_P(sema *s)
{
pthread_mutex_lock(&(s->lock));
s->value--;
if(s->value < 0) {
pthread_cond_wait(&(s->wait),&(s->lock));
}
pthread_mutex_unlock(&(s->lock));
return;
}
void pthread_sema_V(sema *s)
{
pthread_mutex_lock(&(s->lock));
s->value++;
if(s->value <= 0) {
pthread_cond_signal(&(s->wait));
}
pthread_mutex_unlock(&(s->lock));
}
The mutex sema.lock is there to protect the shared variable sema.value, ensuring that only one thread accesses that value at a time. Both pthread_sema_P() and pthread_sema_V() must take the lock because they both access sema.value.
That implementation of sempahores is buggy, by the way - it doesn't handle spurious wakeups (a "spurious wakeup" is where pthread_cond_wait() wakes up despite not being signalled - this is allowed by the spec).
A more traditional implementation might be:
void pthread_sema_P(sema *s)
{
pthread_mutex_lock(&s->lock);
while (s->value < 1) {
pthread_cond_wait(&s->wait, &s->lock);
}
s->value--;
pthread_mutex_unlock(&s->lock);
}
void pthread_sema_V(sema *s)
{
pthread_mutex_lock(&s->lock);
s->value++;
pthread_cond_signal(&s->wait);
pthread_mutex_unlock(&s->lock);
}
I'm writing a serial communication wrapper class in Objective-C. To list all serial available modems and setup the connection I'm using pretty much the same code as used in this example project by Apple.
I could read and write the ways apple does it. But I want to implement a loop on a second thread and write to the stream if a NSString *writeString longer 0 and read after write if bytes are available.
I got writing working quite straight forward. I just used the write function declared in unistd.h.
Reading will not work. Whenever I call read(), the function hangs and my loop does not proceed.
Here is the code used in my loop:
- (void)runInCOMLoop {
do {
// write
} while (bytesWritten < strlen([_writeString UTF8String]));
NSMutableString *readString = [NSMutableString string];
ssize_t bytesRead = 0;
ssize_t readB = 0;
char buffer[256];
do {
readB = read(_fileDescriptor, &buffer, sizeof(buffer));
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this function hangs
bytesRead += readB;
if (readB == -1 {
// error
}
else if (readB > 0) {
if(buffer[bytesRead - 1] == '\r' ]] buffer[bytesRead - 1] == '\n') {
break;
}
[readString appendString:[NSString stringWithUTF8String:buffer]];
}
} while (readB > 0);
What am I doing wrong here?
read() will block if there is nothing to read. Apple probably has their own of doing things, but you can use select() to see if there is anything to read on _fileDescriptor. Google around for examples on how to use select.
Here's one link on StackOverflow:
Can someone give me an example of how select() is alerted to an fd becoming "ready"
This excerpt from the select man is pertains:
To effect a poll, the timeout argument should be
non-nil, pointing to a zero-valued timeval structure. Timeout is not
changed by select(), and may be reused on subsequent calls, however it is
good style to re-initialize it before each invocation of select().
You can set the non-blocking flag (O_NONBLOCK) on the file descriptor using fcntl() to keep read() from waiting for data, but if you do that, you have to continuously poll looking for data, which is obviously bad from a CPU usage standpoint. As Charlie Burns' answer explains, the best solution is to use select() which will allow your program to efficiently wait until there is some data to be read on the port's file descriptor. Here's some example code taken from my own Objective-C serial port class, ORSSerialPort (slightly modified):
fd_set localReadFDSet;
FD_ZERO(&localReadFDSet);
FD_SET(self.fileDescriptor, &localReadFDSet);
timeout.tv_sec = 0;
timeout.tv_usec = 100000; // Check to see if port closed every 100ms
result = select(localPortFD+1, &localReadFDSet, NULL, NULL, &timeout);
if (!self.isOpen) break; // Port closed while select call was waiting
if (result < 0) {
// Handle error
}
if (result == 0 || !FD_ISSET(localPortFD, &localReadFDSet)) continue;
// Data is available
char buf[1024];
long lengthRead = read(localPortFD, buf, sizeof(buf));
NSData *readData = nil;
if (lengthRead>0) readData = [NSData dataWithBytes:buf length:lengthRead];
Note that select() indicates that data is available by returning. So, your program will sit suspended at the select() call while no data is available. The program is not hung, that's how it's supposed to work. If you need to do other things while select() is waiting, you should put the select() call on a different queue/thread from the other work you need to do. ORSSerialPort does this.
My Run Loop Observer is written as follows:
void observerCallback(CFRunLoopObserverRef observer,
CFRunLoopActivity activity, void* info)
{
println("%u", activity);
}
//-----------------------------
void InstallObserver()
{
CFRunLoopObserverRef myObserver = NULL;
int myActivities = kCFRunLoopEntry;
myObserver = CFRunLoopObserverCreate(NULL, myActivities, YES,
/* repeat */ 0, &observerCallback, NULL);
if (myObserver)
{
CFRunLoopAddObserver(CFRunLoopGetCurrent(), myObserver,
kCFRunLoopCommonModes);
}
}
Every time I press any key in my Application the observerCallback is called 4 times.
The question is:
How can I obtain key code inside observerCallback?
Thanks.
Based on the comments on your question, you want a local event monitor, AKA:
+[NSEvent addLocalMonitorForEventsMatchingMask:handler:]
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSEvent_Class/Reference/Reference.html#//apple_ref/occ/clm/NSEvent/addLocalMonitorForEventsMatchingMask:handler: