Serial Problem
Moderators: RoccoMarco, lbednarz, tfAteba
Serial Problem
Hi Giovanni,
i have an a questions . I write my first program using task using your fantastic os , but i have a doubt .
So The program is simple , this is the code :
#include "ch.h"
#include "hal.h"
#include "test.h"
/*
* Red LED blinker thread, times are in milliseconds.
*/
static WORKING_AREA(waThread1, 128);
static msg_t Thread1(void *arg) {
(void)arg;
while (TRUE) {
palClearPad(IOPORT2, 7);
//sdAsynchronousWrite(&SD1,"CIAO",4);
chThdSleepMilliseconds(500);
palSetPad(IOPORT2, 7);
chThdSleepMilliseconds(500);
}
}
// USART thread, processes GPS inputs
static WORKING_AREA(waThread2, 512);
static msg_t Thread2(void *arg) {
(void)arg;
char c;
while (TRUE)
{
c = chIOGet(&SD1);
switch(c)
{
case '1':
sdWrite(&SD1,"Recived 1\n\r",11);
break;
case '2':
sdWrite(&SD1,"Recived 2\n\r",11);
break;
case '3':
sdWrite(&SD1,"Recived 3\n\r",11);
break;
case '4':
sdWrite(&SD1,"Recived 4\n\r",11);
break;
case '5':
sdWrite(&SD1,"Recived 5\n\r",11);
break;
default:
sdWrite(&SD1,"NO AVAILABLE\n\r",15);
menu();
}
}
}
/*
* Application entry point.
*/
int menu(void)
{
sdWrite(&SD1,"MP32 Testing Program Choose your test\n\r",40);
sdWrite(&SD1,"1) Test Radio Input\n\r",21);
sdWrite(&SD1,"2) Test PWM Output \n\r",21);
sdWrite(&SD1,"3) Read Anag Input (ANX)\n\r",27);
sdWrite(&SD1,"4) Read Anag Input (SPI)\n\r",27);
sdWrite(&SD1,"5) Read Anag Input (I2c)\n\r",27);
sdWrite(&SD1,"6) Read Barometer (I2c)\n\r",27);
sdWrite(&SD1,"7) Read GPS (Ser2)\n\r",27);
}
int main(void) {
/*
* System initializations.
* - HAL initialization, this also initializes the configured device drivers
* and performs the board-specific initializations.
* - Kernel initialization, the main() function becomes a thread and the
* RTOS is active.
*/
halInit();
chSysInit();
/*
* Activates the serial driver 2 using the driver default configuration.
*/
sdStart(&SD1, NULL);
/*
* Creates the blinker thread.
*/
chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
/*
* Creates the Serial1 Recive Thread.
*/
chThdCreateStatic(waThread2, sizeof(waThread2), NORMALPRIO, Thread2, NULL);
menu();
/*
* Normal main() thread activity, in this demo it does nothing except
* sleeping in a loop and check the button state.
*/
while (TRUE) {
//chThdSleepMilliseconds(5000);
}
}
But when the thread2 call the menu some time i don't see some character in my terminal ...
Do you have some idea ? Problem with variable definition or passing ?
In the next day i start to write some Howto and tutorial on your hal for customers of MP32 . I hope that they decide to sue your OS on my board.
Onother request is but in your api there's a function that return the number of byte available in the buffer ? In the documentation i don't found it.
The last question is : I need to remap a external Xtal to different pin XTAL_REMAP , how is possible to do that in your OS ?
Regards
Roberto
i have an a questions . I write my first program using task using your fantastic os , but i have a doubt .
So The program is simple , this is the code :
#include "ch.h"
#include "hal.h"
#include "test.h"
/*
* Red LED blinker thread, times are in milliseconds.
*/
static WORKING_AREA(waThread1, 128);
static msg_t Thread1(void *arg) {
(void)arg;
while (TRUE) {
palClearPad(IOPORT2, 7);
//sdAsynchronousWrite(&SD1,"CIAO",4);
chThdSleepMilliseconds(500);
palSetPad(IOPORT2, 7);
chThdSleepMilliseconds(500);
}
}
// USART thread, processes GPS inputs
static WORKING_AREA(waThread2, 512);
static msg_t Thread2(void *arg) {
(void)arg;
char c;
while (TRUE)
{
c = chIOGet(&SD1);
switch(c)
{
case '1':
sdWrite(&SD1,"Recived 1\n\r",11);
break;
case '2':
sdWrite(&SD1,"Recived 2\n\r",11);
break;
case '3':
sdWrite(&SD1,"Recived 3\n\r",11);
break;
case '4':
sdWrite(&SD1,"Recived 4\n\r",11);
break;
case '5':
sdWrite(&SD1,"Recived 5\n\r",11);
break;
default:
sdWrite(&SD1,"NO AVAILABLE\n\r",15);
menu();
}
}
}
/*
* Application entry point.
*/
int menu(void)
{
sdWrite(&SD1,"MP32 Testing Program Choose your test\n\r",40);
sdWrite(&SD1,"1) Test Radio Input\n\r",21);
sdWrite(&SD1,"2) Test PWM Output \n\r",21);
sdWrite(&SD1,"3) Read Anag Input (ANX)\n\r",27);
sdWrite(&SD1,"4) Read Anag Input (SPI)\n\r",27);
sdWrite(&SD1,"5) Read Anag Input (I2c)\n\r",27);
sdWrite(&SD1,"6) Read Barometer (I2c)\n\r",27);
sdWrite(&SD1,"7) Read GPS (Ser2)\n\r",27);
}
int main(void) {
/*
* System initializations.
* - HAL initialization, this also initializes the configured device drivers
* and performs the board-specific initializations.
* - Kernel initialization, the main() function becomes a thread and the
* RTOS is active.
*/
halInit();
chSysInit();
/*
* Activates the serial driver 2 using the driver default configuration.
*/
sdStart(&SD1, NULL);
/*
* Creates the blinker thread.
*/
chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
/*
* Creates the Serial1 Recive Thread.
*/
chThdCreateStatic(waThread2, sizeof(waThread2), NORMALPRIO, Thread2, NULL);
menu();
/*
* Normal main() thread activity, in this demo it does nothing except
* sleeping in a loop and check the button state.
*/
while (TRUE) {
//chThdSleepMilliseconds(5000);
}
}
But when the thread2 call the menu some time i don't see some character in my terminal ...
Do you have some idea ? Problem with variable definition or passing ?
In the next day i start to write some Howto and tutorial on your hal for customers of MP32 . I hope that they decide to sue your OS on my board.
Onother request is but in your api there's a function that return the number of byte available in the buffer ? In the documentation i don't found it.
The last question is : I need to remap a external Xtal to different pin XTAL_REMAP , how is possible to do that in your OS ?
Regards
Roberto
- Giovanni
- Site Admin
- Posts: 14891
- Joined: Wed May 27, 2009 8:48 am
- Has thanked: 1202 times
- Been thanked: 996 times
Re: Serial Problem
Hi,
I work under ChibiOS with the STM32, and I have some difficulties with the serial driver.
A - What happen if the the Rx buffer overflow (buffer to small wrt incoming data)? How to prevent/handle Rx Buffer overflow ?
B - I would like to use the receiving Interrupt on serial port 4. Does anyone would have a sample code ?
Now, I use the code below which is not optimized.
while(TRUE)
{
size_t qSize = chQSizeI(&(&SD4)->iqueue); //Rx Buffer Size
size_t qSpace = chQSpaceI(&(&SD4)->iqueue); //Rx Buffer Space
ByteAvailable = qSize-qSpace; //Available bytes to be read
if(ByteAvailable>0)//Read ByteAvailable
{
sdRead(&SD4, (uint8_t*)&Rx, ByteAvailable);
...
}
chThdSleepMilliseconds(50); //Thread Sample time
}
Best
Cyrille
I work under ChibiOS with the STM32, and I have some difficulties with the serial driver.
A - What happen if the the Rx buffer overflow (buffer to small wrt incoming data)? How to prevent/handle Rx Buffer overflow ?
B - I would like to use the receiving Interrupt on serial port 4. Does anyone would have a sample code ?
Now, I use the code below which is not optimized.
while(TRUE)
{
size_t qSize = chQSizeI(&(&SD4)->iqueue); //Rx Buffer Size
size_t qSpace = chQSpaceI(&(&SD4)->iqueue); //Rx Buffer Space
ByteAvailable = qSize-qSpace; //Available bytes to be read
if(ByteAvailable>0)//Read ByteAvailable
{
sdRead(&SD4, (uint8_t*)&Rx, ByteAvailable);
...
}
chThdSleepMilliseconds(50); //Thread Sample time
}
Best
Cyrille
- Giovanni
- Site Admin
- Posts: 14891
- Joined: Wed May 27, 2009 8:48 am
- Has thanked: 1202 times
- Been thanked: 996 times
Re: Serial Problem
Hi Cyrille,
About your questions, there are only several possible ways to make the buffer not overflow:
1) Read the data fast enough.
2) Implement a protocol that ensures that data is not sent until explicitly requested.
3) As a mitigation measure you may increase the buffer size in halconf.h.
About your code, if you need to just read the data present in the buffer, the easiest way is to use
sdReadTimeout(&SD4, buf, sizeof(buf), TIME_IMMEDIATE);
The above function returns just the data present in the buffer and does not block. Note that the serial driver generates an event when data is available in the buffer so you don't have to use the interrupt handler directly. You may do the following in your thread:
1) Register the thread on the SD4 event source (chIOGetEventSource(), chEvtRegister()).
2) Wait for the event (chEvtWaitOne()).
3) Read the flags associated to the event (chIOGetAndClearFlags()).
5) If an error flag is specified the process the error (the possible flags are specified in the serial driver documentation, see SD_PARITY_ERROR and following).
4) If a IO_INPUT_AVAILABLE flag is present then read all the data in the buffer (sdReadTimeout(...,, TIME_IMMEDIATE)).
5) Process the data.
6) Repeat from point 2.
The above solution allows to read and process data continuously.
Giovanni
About your questions, there are only several possible ways to make the buffer not overflow:
1) Read the data fast enough.
2) Implement a protocol that ensures that data is not sent until explicitly requested.
3) As a mitigation measure you may increase the buffer size in halconf.h.
About your code, if you need to just read the data present in the buffer, the easiest way is to use
sdReadTimeout(&SD4, buf, sizeof(buf), TIME_IMMEDIATE);
The above function returns just the data present in the buffer and does not block. Note that the serial driver generates an event when data is available in the buffer so you don't have to use the interrupt handler directly. You may do the following in your thread:
1) Register the thread on the SD4 event source (chIOGetEventSource(), chEvtRegister()).
2) Wait for the event (chEvtWaitOne()).
3) Read the flags associated to the event (chIOGetAndClearFlags()).
5) If an error flag is specified the process the error (the possible flags are specified in the serial driver documentation, see SD_PARITY_ERROR and following).
4) If a IO_INPUT_AVAILABLE flag is present then read all the data in the buffer (sdReadTimeout(...,, TIME_IMMEDIATE)).
5) Process the data.
6) Repeat from point 2.
The above solution allows to read and process data continuously.
Giovanni
Re: Serial Problem
Hi Giovanni,
Thanks for your last reply.
I'm a beginner with ChibiOS.
So how to :
1) Register the thread on the SD4 event source (chIOGetEventSource(), chEvtRegister()).
I have tried the following code, but after the thread creation I don't know how to continue.
static Thread *ThreadGPS;
ThreadGPS = chThdCreateStatic(waThreadGPS, sizeof(waThreadGPS), NORMALPRIO, ThreadGPS, NULL);
EventListener s4EventListener;
chEvtRegister(??(ThreadGPS), &s4EventListener, 0);
2) Wait for the event (chEvtWaitOne()).
3) Read the flags associated to the event (chIOGetAndClearFlags()).
Do you have a sample code?
Thanks a lot
Cyrille
Thanks for your last reply.
I'm a beginner with ChibiOS.
So how to :
1) Register the thread on the SD4 event source (chIOGetEventSource(), chEvtRegister()).
I have tried the following code, but after the thread creation I don't know how to continue.
static Thread *ThreadGPS;
ThreadGPS = chThdCreateStatic(waThreadGPS, sizeof(waThreadGPS), NORMALPRIO, ThreadGPS, NULL);
EventListener s4EventListener;
chEvtRegister(??(ThreadGPS), &s4EventListener, 0);
2) Wait for the event (chEvtWaitOne()).
3) Read the flags associated to the event (chIOGetAndClearFlags()).
Do you have a sample code?
Thanks a lot
Cyrille
- Giovanni
- Site Admin
- Posts: 14891
- Joined: Wed May 27, 2009 8:48 am
- Has thanked: 1202 times
- Been thanked: 996 times
Re: Serial Problem
Hi Cyrille,
It is the thread that needs to wait for events that has to register using chEvtRegister().
Try the following (note not tested, I just wrote an example):
Giovanni
It is the thread that needs to wait for events that has to register using chEvtRegister().
Try the following (note not tested, I just wrote an example):
Code: Select all
msg_t my_thread(void *p) {
EventListener s4EventListener;
(void)p;
chEvtRegister(chIOGetEventSource(&SD4), &s4EventListener, 1);
while (TRUE) {
ioflags_t flags;
chEvtWaitOne(EVENT_MASK(1));
flags = chIOGetAndClearFlags(&SD4);
if (flags & IO_INPUT_AVAILABLE) {
/* Data available read here.*/
}
if (flags & IO_OUTPUT_EMPTY) {
/* Data sent, you may transmit from here.*/
}
if (flags & (SD_PARITY_ERROR | SD_FRAMING_ERROR | SD_OVERRUN_ERROR |
SD_NOISE_ERROR | SD_BREAK_DETECTED)) {
/* Some receive error happened.*/
}
}
}
Giovanni
Re: Serial Problem
Giovanni,
I have tested your code.A GPS is connected to SD4. I have added some "printf" on SD1 to see if the code works when data arrived on SD4, but nothing (even before the While(true) : the "tread init" is not sent!)
It is may be my thread creation int the main or ...?
Thanks
Cyrille
I have tested your code.A GPS is connected to SD4. I have added some "printf" on SD1 to see if the code works when data arrived on SD4, but nothing (even before the While(true) : the "tread init" is not sent!)
It is may be my thread creation int the main or ...?
Code: Select all
int main (void)
{
...
static Thread *ThreadGPS;
ThreadGPS = chThdCreateStatic(waThreadGPS, sizeof(waThreadGPS), NORMALPRIO, ThreadGPS, NULL);
...
}
static msg_t ThreadGPS(void *p) {
EventListener s4EventListener;
sdWrite(&SD1,"thread init\r\n",17);
(void)p;
chEvtRegister(chIOGetEventSource(&SD4), &s4EventListener, 1);
while (TRUE) {
ioflags_t flags;
chEvtWaitOne(EVENT_MASK(1));
flags = chIOGetAndClearFlags(&SD4);
if (flags & IO_INPUT_AVAILABLE) {
/* Data available read here.*/
sdWrite(&SD1,"OK\r\n",16);
}
if (flags & IO_OUTPUT_EMPTY) {
/* Data sent, you may transmit from here.*/
}
if (flags & (SD_PARITY_ERROR | SD_FRAMING_ERROR | SD_OVERRUN_ERROR |
SD_NOISE_ERROR | SD_BREAK_DETECTED)) {
/* Some receive error happened.*/
sdWrite(&SD1,"Error\r\n",16);
}
}
}Thanks
Cyrille
- Giovanni
- Site Admin
- Posts: 14891
- Joined: Wed May 27, 2009 8:48 am
- Has thanked: 1202 times
- Been thanked: 996 times
Re: Serial Problem
You have both a variable and a function with the same name ThreadGPS.
Are you sure the thread really starts? try placing a breakpoint.
Giovanni
Are you sure the thread really starts? try placing a breakpoint.
Giovanni
Re: Serial Problem
Hi,
In what exact circumstances does this line unlock the thread (where can I find it in the documentation) ?
Who do I make sure that "chEvtWaitOne(EVENT_MASK(1));" unlocks when I want to send data ?
Best regards,
Dave
chEvtWaitOne(EVENT_MASK(1));
In what exact circumstances does this line unlock the thread (where can I find it in the documentation) ?
if (flags & IO_OUTPUT_EMPTY) {
/* Data sent, you may transmit from here.*/
Who do I make sure that "chEvtWaitOne(EVENT_MASK(1));" unlocks when I want to send data ?
Best regards,
Dave
- Giovanni
- Site Admin
- Posts: 14891
- Joined: Wed May 27, 2009 8:48 am
- Has thanked: 1202 times
- Been thanked: 996 times
Re: Serial Problem
It does not work that way, The transmission event is generated when the transmission buffer becomes empty (transition from non-empty to empty), you may transmit in any moment if there is space in the buffer.
Depending on the timeout parameter of sdWriteTimeout() the function blocks when there is no space (TIME_INFINITE) or returns immediately (TIME_IMMEDIATE).
Giovanni
Depending on the timeout parameter of sdWriteTimeout() the function blocks when there is no space (TIME_INFINITE) or returns immediately (TIME_IMMEDIATE).
Giovanni