I have been working on a software based on CMSIS-RTOS and I have a problem with
function osMessageGet. My software consists of four RTOS tasks and two of them
exchange data via osMessageQueue in conjunction with osPool. One task (Task_100ms) is a producer and second task (Task_200ms) is a consumer.
Task_100ms receives data from CAN bus and creates structures containing the received data. The producer allocates memory on pool (flash_pool) using function osPoolAlloc and receives pointer to allocated memory. Producer copies the content of exchanged structure onto the memory block in pool using this pointer and puts copy of this pointer onto the queue (flash_queue) using function osMessagePut (please see the put_program_chunk function code below).
Task_200ms tries to retrieve the pointers from flash_queue using osMessageGet function (please see the program_chunk function code below). As long as the queue is empty consumer waits and everything is OK. Then a first pointer is put onto flash_queue by Task_100ms. Task_200ms calls osMessageGet function and this results in uC reset in case the timeout for osMessageGet is set to osWaitForever. In case the timeout for osMessageGet is set to 0 software reset isn't invoked. But in both cases (timeout equal 0 or osWaitForever) when I step through the code in Eclipse I am not able to achieve the immediately following statement after osMessageGet function call.
Can anybody give me any advice where a cause of my problems could be? I can send
you whole source code if it is needed. Thanks in advance for any suggestions.
BOOL put_program_chunk(main_controller_req_t req){
main_controller_req_t *p_req;
BOOL retval;
BOOL no_memory = FALSE;
/*!!!*/
osStatus status;
uint8_t tmp;
// allocate memory in pool
p_req = (main_controller_req_t *)osPoolAlloc(flash_pool);
if(p_blk == NULL){
printf("No more space in flash pool.\r\n");
}
if(p_req != NULL){
*p_req = req;
// insert the prepared request into the transmission queue
// put the message into the queue
// wait 5 ms?
status = osMessagePut(flash_queue, (uint32_t)(p_req), 5);
/*!!!*/
if(status == osOK){
tmp = 1;
}else{
tmp = 0;
}
}else{
no_memory = TRUE;
}
if(no_memory){
retval = FALSE;
}else{
retval = TRUE;
}
return retval;
}
void program_chunk(void){
osEvent event;
osStatus status;
main_controller_req_t *p_req;
main_controller_req_t req;
pdt_result_t result;
// !!!
uint8_t tmp;
// retrieve the data block from the message queue
event = osMessageGet(flash_queue, 0);
// !!!
tmp++;
/*
if(event.status == osEventMessage){
p_req = ((main_controller_req_t *)(event.value.p));
// copy the content of memory block in receiving pool
req = *p_req;
// free the memory in pool
status = osPoolFree(flash_pool, p_req);
// Normal (=000000) or Boot (=BOOTBL) mode?
if(*req.mode == 0 && *(req.mode + 1) == 0 && *(req.mode + 2) == 0 &&
*(req.mode + 3) == 0 && *(req.mode + 4) == 0 && *(req.mode + 5) == 0){
// Normal mode
// program chunk for the Slot_0 or Slot_1?
if(((req.flash_page_number >= 0x01) && (req.flash_page_number < MAX_AC_PAGE)) ||
((req.flash_page_number == MAX_AC_PAGE) && (req.flash_block_number <= MAX_AC_BLOCK))){
#ifdef APP_DEBUG
printf("AC programming!\r\n");
#endif
// yes - program the retrieved program chunk
result = pdt_app_program_chunk(req.data_block, 32);
// according to the result send the short flash write response message - page and block OK
send_short_flash_load_write_resp((result == PDT_RESULT_OK) ? TRUE : FALSE, FALSE, req.flash_page_number, req.flash_block_number);
// if unsuccessful programming
if(result != PDT_RESULT_OK){
// go into WAIT_TO_FLASH_LOAD_COMPLETE
SetLogicSignal(LGoWtFlshLdCmpl);
}
// program chunk for Motor Controller?
}else if(((req.flash_page_number == MAX_AC_PAGE) && (req.flash_block_number > MAX_AC_BLOCK && req.flash_block_number <= MAX_MC_BLOCK)) ||
((req.flash_page_number > MAX_AC_PAGE) && (req.flash_page_number <= MAX_MC_PAGE))){
#ifdef APP_DEBUG
printf("MC programming!\r\n");
#endif
// yes - program the retrieved program chunk
result = pdt_mc_update_internal_motor_controller_chunk(req.data_block, 32);
// according to the result send the short flash write response message - page and block OK
send_short_flash_load_write_resp((result == PDT_RESULT_OK) ? TRUE : FALSE, FALSE, req.flash_page_number, req.flash_block_number);
// end of the binary?
if((req.flash_page_number == NO_PAGES) && (req.flash_block_number == BLOCKS_IN_PAGE) && result == PDT_RESULT_OK){
result = pdt_mc_update_motor_controller();
// invoke SW reset
result = pdt_app_switch_application();
// if unsuccessful programming
}else if(result != PDT_RESULT_OK){
// go into WAIT_TO_FLASH_LOAD_COMPLETE
SetLogicSignal(LGoWtFlshLdCmpl);
}
// wrong destination address?
}else{
#ifdef APP_DEBUG
printf("Wrong destination address!\r\n");
#endif
// wrong data block destination
send_short_flash_load_write_resp(FALSE, TRUE, req.flash_page_number, req.flash_block_number);
// go into WAIT_TO_FLASH_LOAD_COMPLETE
SetLogicSignal(LGoWtFlshLdCmpl);
}
}
}
*/
}
Related
I have a script reading the serial monitor and looking for an "OK" response. I am able to capture the OK response in a variable named message and print it to the serial monitor, but when I attempt to use the message variable in an if statement it is not performing as expected. When the variable message = OK the statement below is still giving a false. Does anyone know where the issue might be?
if (strcmp (message,"OK") == 0) {
Serial.println("true");
}
else {
Serial.println("false");
}
The complete code:
//#include <HardwareSerial.h>
const unsigned int MAX_MESSAGE_LENGTH = 12;
void setup() {
Serial2.begin(115200,SERIAL_8N1); //open modem serial port
Serial.println("serial ports are open");
}
void loop() {
Serial2.write("AT\r\n");
while (Serial2.available() > 0){
//Create a place to hold the incoming message
static char message[MAX_MESSAGE_LENGTH];
static unsigned int message_pos = 0;
//Read the next available byte in the serial receive buffer
char inByte = Serial2.read();
//Message coming in (check not terminating character) and guard for over message size
if ( inByte != '\n' && (message_pos < MAX_MESSAGE_LENGTH - 1) )
{
//Add the incoming byte to our message
message[message_pos] = inByte;
message_pos++;
}
//Full message received...
else
{
//Add null character to string
message[message_pos] = '\0';
//Print the message (or do other things)
Serial.println("loop");
delay(100);
Serial.println(message);
//Reset for the next message
message_pos = 0;
if (strcmp (message,"OK") == 0) {
Serial.println("true");
}
else {
Serial.println("false");
}
}
}
delay(5000);
}
Serial monitor looks like this:
22:11:51.970 -> serial ports are open
22:12:16.984 -> loop
22:12:17.078 -> AT
22:12:17.078 -> false
22:12:17.078 -> loop
22:12:17.171 -> OK
22:12:17.171 -> false
22:12:17.171 -> loop
22:12:17.266 -> AT
22:12:17.266 -> false
22:12:17.266 -> loop
22:12:17.360 -> OK
22:12:17.360 -> false
The received response is "OK\r\n", so the actual message is "OK\r". It helps for debugging if you temporarily print each received character.
To ignore the echo of the command, insert another strcmp() for it and react accordingly, for example do nothing.
In my project I'm using a global variable but it's not working as expected because it is initialized everytime it's executed and honestly I don't know what could be going on.
The variable is cookingSignalReceived.
The program is structured as follows:
//File Controller.c:
while (1)
{
Controller_Run_State_Machine();
}
void Controller_Run_State_Machine(void)
{
/* start of activity code */
Inputs_ReadSensors();
Comms_CheckReceivedData();
Controller_UpdateSTM();
}
The problem is inside Comms file:
//File Comms.c
uint8_t cookingSignalReceived = 0;
void Comms_CheckReceivedData(void)
{
/* start of activity code */
uint8_t uartDataAvailable = Comms_R_UART0_checkIfDataAvailable();
if (uartDataAvailable == 1)
{
Comms_ParseReceivedCommand();
}
}
void Comms_ParseReceivedCommand(void)
{
/* start of activity code */
/* UserCode{499E2AA6-1F61-4753-9221-77F85E7B5D92}:YjMeKqu95e */
uint8_t CRC_check_OK = 0;
uint8_t* buffer;
/* UserCode{499E2AA6-1F61-4753-9221-77F85E7B5D92} */
Comms_R_UART0_resetFlag_dataAvailable();
buffer = Comms_R_UART0_getBuffer();
CRC_check_OK = Comms_crcCheck(buffer);
if (CRC_check_OK == 1)
{
Comms_processMessage(buffer); //<-- Variable is used in this function
}
}
Global variable is used inside Comms_processMessage(). The issue is that every time that the function is called, the global variable is set to the initial value. Do you find anything strange here?
EDITED:
void Comms_processMessage(uint8_t* buffer)
{
/* UserCode{BCB3B791-2DF9-492b-B53B-6FEB24BD8F77}:eyCoSfmCKb */
uint8_t message = buffer[0];
uint8_t param1 = buffer[1];
uint8_t param2 = buffer[2];
//---------------------------------------------------------------------
// START COOKING 1ST STEP REQUEST
//---------------------------------------------------------------------
if (message == MSG_COOK_1ST && param1 == START_PARAM)
{
// Wait for second frame
cookingSignalReceived = 1;
#ifdef DEBUG
R_UART0_Send("Cook 1st step!!", sizeof(char) * 15);
#endif
}
//---------------------------------------------------------------------
// START COOKING 2ND STEP REQUEST
//---------------------------------------------------------------------
else if (message == MSG_COOK_2ND && param1 == START_PARAM)
{
// Wait for second frame
if (cookingSignalReceived == 1)
{
Controller_signalsBufferEnqueue(cookingSignal);
}
#ifdef DEBUG
R_UART0_Send("Cook 2nd step!!", sizeof(char) * 15);
#endif
}
}
Note that my original idea was to use a local static variable but I was having the same issue so I tried with a global variable.
In certain cases the MCUs restart because unrecoverable errors or bad hardware settings. This should be the problem! A cause of this MCUs behaviour may be also bad pointers management.
I am trying to program the logomatic by sparkfun, and yes I have used their forum with no responses, and having some issues. I am trying to send characters to the UART0 and I want the logomatic to respond with specific characters and not just an echo. For example, I send 'ID?' over the terminal (using RealTerm), and the logomatic sends back '1'. All it will so now is echo.
I am using c with programmers notepad with the WinARM toolchain. The following snippet is from the main.c file. I only included this, because I am fairly certain that this is where my problem lies
void Initialize(void)
{
rprintf_devopen(putc_serial0);
PINSEL0 = 0xCF351505;
PINSEL1 = 0x15441801;
IODIR0 |= 0x00000884;
IOSET0 = 0x00000080;
S0SPCR = 0x08; // SPI clk to be pclk/8
S0SPCR = 0x30; // master, msb, first clk edge, active high, no ints
}
Notice the rprintf_devopen function, below is from the rprintf.c file, and due to my mediocre skills, I do not understand this bit of code. If I comment out the rprintf_devopen in main, the chip never initializes correctly.
static int (*putcharfunc)(int c);
void rprintf_devopen( int(*put)(int) )
{
putcharfunc = put;
}
static void myputchar(unsigned char c)
{
if(c == '\n') putcharfunc('\r');
putcharfunc(c);
}
Now, below is from the serial.c file. So my thought was that I should be able to just call one of these putchar functions in main.c and that it would work, but it still just echoes.
int putchar_serial0 (int ch)
{
if (ch == '\n')
{
while (!(U0LSR & 0x20));
U0THR = CR; // output CR
}
while (!(U0LSR & 0x20));
return (U0THR = ch);
}
// Write character to Serial Port 0 without \n -> \r\n
int putc_serial0 (int ch)
{
while (!(U0LSR & 0x20));
return (U0THR = ch);
}
// Write character to Serial Port 1 without \n -> \r\n
int putc_serial1 (int ch)
{
while (!(U1LSR & 0x20));
return (U1THR = ch);
}
void putstring_serial0 (const char *string)
{
char ch;
while ((ch = *string))
{
putchar_serial0(ch);
string++;
}
}
I have tried calling the different putchar functions in main, also with the rprintf_devopen. Still just echoes. I have altered the putchar functions and still just echoes. I have tried just writing to the U0THR register in main.c and no luck. Keep in mind that I am still a student and my major is electrical engineering, so the only programming classes that I have taken are intro to c, and an intro to vhdl. I am more of a math and physics guy. I was working on this for an internship I was doing. The internship ended, but it just bugs me that I cannot figure this out. Honestly, working on this program taught me more that the c class that I took. Anyways, I appreciate any help that can be offered, and let me know if you want to see the entire code.
Below is an update to the question. This function is in main.c
static void UART0ISR(void)
{
char temp;
trig = 13; //This is where you set the trigger character in decimal, in this case a carriage return.
temp = U0RBR; //U0RBR is the receive buffer on the chip, refer to datasheet.
if(temp == query1[counter1]) //This segment looks for the characters "ID?" from the U0RBR
{ //query1 is defined at the top of the program
counter1++;
if(counter1 >= 3)
{
flag1 = 1; //This keeps track of whether or not query1 was found
counter1 = 0;
stat(1,ON);
delay_ms(50);
stat(1,OFF);
RX_in = 0;
temp = 0;
//rprintf("\n\rtransmission works\n");
putc_serial1(49);
}
}
if(temp == query2[counter2] && flag1 == 1) //This segment looks for "protov?" from the U0RBR, but only after query1 has been found
{
counter2++;
if(counter2 >= 7)
{
flag2 = 1; //This keeps track of whether or not query2 was found
counter2 = 0;
stat(1,ON);
delay_ms(50);
stat(1,OFF);
RX_in = 0;
temp = 0;
putc_serial1(49);
}
}
if(temp == stop[counter3]) //This if segment looks for certain characters in the receive buffer to stop logging
{
counter3++;
if(counter3 >= 2)
{
flagstop = 1; //This flagstop keeps track of whether or not stop was found. When the stop characters are found,
flag1 = 0; //the query1 and query2 flags will be reset. So, in order to log again these queries must be sent again
flag2 = 0; //this may seem obvious, but deserves mention.
counter3 = 0;
stat(1,ON);
delay_ms(500);
stat(1,OFF);
RX_in = 0;
temp = 0;
}
flagstop = 0; //Reset the stop flag in order to wait once again for the query 1&2
}
if(RX_in == 0)
{
memset (RX_array1, 0, 512); // This clears the RX_array to make way for new data
memset (RX_array2, 0, 512);
}
if(RX_in < 512 && flag1 == 1 && flag2 == 1) //We cannot log data until we see both flags 1 & 2 and after we see these flags,
{ //we must then see the trigger character "carriage return"
RX_array1[RX_in] = temp;
RX_in++;
if(temp == trig)
{
RX_array1[RX_in] = 10; // delimiters
log_array1 = 1;
RX_in = 0;
}
}
else if(RX_in >= 512 && flag1 == 1 && flag2 == 1) //This else if is here in case the RX_in is greater than 512 because the RX_arrays are defined to
{ //be of size 512. If this happens we don't want to lose data, so we must put the overflow into another register.
RX_array2[RX_in - 512] = temp;
RX_in++;
RX_array1[512] = 10; // delimiters
RX_array1[512 + 1] = 13;
log_array1 = 1;
if(RX_in == 1024 || temp == trig)
{
RX_array2[RX_in - 512] = 10; // delimiters
log_array2 = 1;
RX_in = 0;
}
}
temp = U0IIR; // have to read this to clear the interrupt
VICVectAddr = 0;
}
I am trying to escape from the main loop if external stop key is pressed.
Currently, communicating AT32UC with ATmega128 through RS485 communication where START and STOP keys are implemented.
RS485 receiver interrupt is called if there is data to be processed in the receiver side where 0x10 = Start and 0x11 = Stop.
My problem is that start and stop keys are recognised well and main loop is continued if start and I would like to terminate the main loop if stop key is pressed.
So I've set the start flag and stop flag accordingly. But, I am struggling with stop(escape) implementation. Below is brief snippets of interrupt routine and main loop.
__attribute__((__interrupt__)) static void rs485RxInterrupt(void)
{
uint32_t data;
static char RxDatalength = 98;
data = AVR32_USART2.RHR.rxchr;
if(data & 0x00000100) // rs485 9 bit check
{
if((data & 0x000000ff) == 0x92) //dsp board address = 0x92
{
rxBuf[0] = data;
addr_flag = true;
rxInCtr = 1;
}
else
{
addr_flag = false;
return;
}
}
else if (addr_flag == true) // if 9 bit is checked
{
rxBuf[rxInCtr++] = data;
if(rxInCtr == 2) // command check
{
if(data < 0x80)
{
if(data==0x10) // start command
{
addr_flag = false; // reset addr flag
start_flag = true;
//RxDatalength = 0;
}
else if(data == 0x11) // stop command
break_flag = true;
}
else if(data >= 0x80)
//gpio_set_pin_high (AVR32_PIN_PA16);
RxDatalength = 3;
}
if ((rxInCtr == RxDatalength) || ((RxDatalength == 98) && (rxInCtr == rxBuf[2]+1))) // end of packet recognition
{
addr_flag = false;
start_flag = true;
}
}
}
int main()
{
......
while(!break_flag)
{
start_flag = false;
while(start_flag == false)
;
gpio_set_pin_high(AVR32_PIN_PA14);
delay_us(40);
gpio_set_pin_low(AVR32_PIN_PA14);
//****** loop stays at this point and I am not giving sync_flag high to
//continue so if I press stop, I want this thing to get out of the main
//while loop!!
// peaksRdy_flag = true;
// SendTx(peaks);
sync_flag = false; // synchronising main with start of the input
while(sync_flag == false)
;
envelopeIndex = 0;
for(uint32_t loop=0; loop<23; loop++) // looping 23 times to cover approx 4.5s
{
//reset counter
sampleCounter = 0;
samplingComplete = false;
//wait for sampling to finish, 256 samples
while (samplingComplete == false)
;
//gpio_set_pin_low(AVR32_PIN_PA15); // main loop indicator
windowing(x);
rms(x); // return ac_rms
//gpio_set_pin_low(AVR32_PIN_PA16); // fft indicator
fft_run(window); // return fft magnitude
//gpio_set_pin_high(AVR32_PIN_PA16);
peak_search(fft_mag);
envelope_output(envelope);
// Function to transmit analysed data through RS485 communication.
//SendTx(peaks);
sprintf(filtResult, "%04d %04d %04d %04d %04d\n", (int)peaks[loop][0], (int)peaks[loop][1], (int)peaks[loop][2], (int)peaks[loop][3],(int)ac_rms);
char *ptr = &filtResult[0];
do
{
c = *ptr;
ptr++;
usart_bw_write_char(&AVR32_USART2, (int)c);
// sendByte(c);
} while (c != '\n');
//gpio_set_pin_high(AVR32_PIN_PA15);
} // outer loop
sprintf(filtResult, "%04d\n", (int)duty);
char *ptr = &filtResult[0];
do
{
c = *ptr;
ptr++;
usart_bw_write_char(&AVR32_USART2, (int)c);
// sendByte(c);
} while (c != '\n');
break;
}//while
}//main
All your flags should be declared volatile.
eg:
volatile int start_flag, sync_flag /*,other_flag ... */;
else the compiler may optimise out checks for their value being changed by code outside the current block.
An external module sends the string "CMD\n" to my program one character at a time through interrupts. It is important to know where in the sequence the module is so that I can troubleshoot. This is the way I'm currently handling tracking of the module:
// Enumeration describing the different states
typedef enum {
BTSTATE_ENTERING_CMD_C, // awaiting "C"
BTSTATE_ENTERING_CMD_M,
BTSTATE_ENTERING_CMD_D,
BTSTATE_ENTERING_CMD_EOL,
BTSTATE_CMD
} btstate_t;
// State variable
btstate_t btstate = BTSTATE_ENTERING_CMD_C;
// function called every time a new character is sent
ISR(USART_RX_vect) {
uint8_t rcv = UDR0; // the received character
if ( btstate == BTSTATE_ENTERING_CMD_C && rcv == 'C') {
btstate = BTSTATE_ENTERING_CMD_M;
} else if ( btstate == BTSTATE_ENTERING_CMD_M && rcv == 'M') {
btstate = BTSTATE_ENTERING_CMD_D;
} else if ( btstate == BTSTATE_ENTERING_CMD_D && rcv == 'D') {
btstate = BTSTATE_ENTERING_CMD_EOL;
} else if ( btstate == BTSTATE_ENTERING_CMD_EOL && rcv == '\n') {
btstate = BTSTATE_CMD;
} else {
// error handling here
}
}
Intuitively, there seems to be a lot of redundancy in the code. Is there a better or more canonical way to achieve the same result?
What about this ? It's pretty readable and easy to modify.
// Enumeration describing the different states
typedef enum {
BTSTATE_ENTERING_CMD_C, // awaiting "C"
BTSTATE_ENTERING_CMD_M,
BTSTATE_ENTERING_CMD_D,
BTSTATE_ENTERING_CMD_EOL,
BTSTATE_CMD
} btstate_t;
// State variable
btstate_t btstate = BTSTATE_ENTERING_CMD_C;
struct cmp
{
btstate_t state;
btstate_t next_state;
uint8_t c;
} t_cmp;
ISR(USART_RX_vect) {
static t_cmp cmp_array[] = {
{BTSTATE_ENTERING_CMD_C, BTSTATE_ENTERING_CMD_M, 'C'},
{BTSTATE_ENTERING_CMD_M, BTSTATE_ENTERING_CMD_D, 'M'},
{BTSTATE_ENTERING_CMD_D, BTSTATE_ENTERING_CMD_EOL, 'D'},
{BTSTATE_ENTERING_CMD_EOL, BTSTATE_CMD, '\n'}
};
static int array_size = sizeof(cmp_array) / sizeof(cmp_array[0]);
uint8_t rcv = UDR0; // the received character
int i;
for (i = 0; i < array_size; ++i)
{
if (btstate == cmp_array[i].state && rcv == cmp_array[i].c)
{
btstate = cmp_array[i].next_state;
break ;
}
}
if (i == array_size)
// error handling here
}
Something like the following will test an incoming stream to confirm that it
matches a string:
static const char leader[] = "CMD\n";
uint8_t btstate = 0;
ISR(USART_RX_vect) {
uint8_t rcv = UDR0;
if (btstate < 4)
{
if (rcv == leader[btstate])
btstate++;
else
{
// error handling here
btstate = 0;
}
}
}
(untested, obviously)
If (btstate == 4) then you've got your leader string and are now receiving
whatever comes after.
An error condition which is not well handled here, which might affect the
design, is where you receive some leading garbage before the correct string.
As things stand, we'll enter into // error handling here and reset btstate,
but if rcv is now equal to the first 'C' that the sender really intended
then we've missed it, and next time around we'll expect 'C' but receive 'M'
and raise yet another error and completely miss the correct string.
Here you have two options. One is to signal the sender to reset itself (which
can be troublesome over high-latency links), and the other is to re-check
(rcv == 'C') in the error handler.
If your command string were "GABBAGABBAHEY", and you were expecting the 'H'
but you instead got 'G', then it's possible that all of the preceeding
characters were sent erroneously, or that some number of characters were sent
deliberately as the prefix of another string (or the current string).
Handling that case, and handling the case of there being multiple possible
strings, requires a structure that can take different paths depending on the
character received. In the case where you do want to tolerate leading garbage,
that structure can loop back on itself -- pointing back to the longest prefix
which matches the current state -- and in that case you don't really want to
build the table by hand.
You've said you know what string you're expecting, so I won't go into all that,
but I thought it worth mentioning for completeness.