- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I need to put a few lines of code in an interrupt service routine (ISR) to print the value in a variable at the time of the interrupt. Timing is not critical, this is just a test to check an operation. I have a CY8CKIT-059 board and use a counter (Counter_3X) to create the interrupt. Here is the ISR
* Place your includes, defines and code here
********************************************************************************/
/* `#START Counter_3X_Done_intc` */
extern void Counter_3X_Stop(); //Stop Counter_3X
extern uint16 charindex; //Value from main program
char strMsg3X[30]; //Set up array for characters to print
sprintf(strMsg3X,"CharIndex = %u\r\n",charindex); //Line 34
int UART_1_PutString(strMsg3X); //Line 35
/* `#END` */
The first line (Line 34 in boldface) produces the Build error, "expected ')' before string constant" and when I hover over the string, the cursor shows "expected identifier".
When I hover over Line 35, I read the following, "a parameter list without types is only allowed in a function definition." I have no idea what this means.
I have attached an image of the error and warning messages. All I need is a way to display a value on a terminal for tests. No printing will occur in the finished code. If you can suggest an alternate way to accomplish my testing goal, I welcome your ideas. Thank you. --Jon
Solved! Go to Solution.
- Labels:
-
PSoC 5LP
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
So I tested it by myself using CY8CKIT-059.
I emulated your project with following schematic.
To make it work, I needed to modify the ISR as
(part of Counter_3X_Done.c)
============================
CY_ISR(Counter_3X_Done_Interrupt)
{
#ifdef Counter_3X_Done_INTERRUPT_INTERRUPT_CALLBACK
Counter_3X_Done_Interrupt_InterruptCallback();
#endif /* Counter_3X_Done_INTERRUPT_INTERRUPT_CALLBACK */
/* Place your Interrupt code here. */
/* `#START Counter_3X_Done_Interrupt` */
// #include "project.h"
// #include "stdio.h"
extern void Counter_3X_Stop() ;
extern void Counter_3X_ReadStatusRegister(void) ;
extern uint16 charindex ;
char strMsg3X[30] ;
Counter_3X_Done_ClearPending() ;
Counter_3X_ReadStatusRegister() ;
sprintf(strMsg3X, "CharIndex = %u\r\n", charindex) ;
UART_1_PutString(strMsg3X) ;
/* `#END` */
}
============================
and the main.c
============================
#include "project.h"
#include "stdio.h"
uint16 charindex = 0 ;
char str[128] ; /* print buffer */
void print(char *str)
{
UART_1_PutString(str) ;
}
void init_hardware(void)
{
UART_1_Start() ;
Counter_3X_Done_ClearPending() ;
Counter_3X_Done_Start() ;
Counter_3X_WriteCounter(0) ;
Counter_3X_Init() ;
Counter_3X_Enable() ;
CyGlobalIntEnable; /* Enable global interrupts. */
}
void splash(void)
{
sprintf(str, "PSoC LP5 Interrupt Test A (%s %s)\r\n", __DATE__, __TIME__) ;
print(str) ;
}
int main(void)
{
init_hardware() ;
splash() ;
for(;;) {
charindex++ ;
CyDelay(100) ;
}
}
============================
And the Tera Term log was
So anyway, the project seems to be working.
But as I wrote earlier, having sprintf(), PutString() in ISR is not recommend because of a couple of reasons (IMHO)
(1) They usually take rather long time, where an ISR is expected return as soon as possible.
(2) They tend to allocate and/or move memory, which is also not good for an ISR, in some MCU it causes hang.
Meantime, in general, I don't want touch "system generated source/header", for example
"Counter_3X_Done.c" in this case.
I'd rather use Counter_3X_Done_StartEx() instead of Counter_3X_Done_Start()
so that I can prepare the ISR in my source files.
In the following example, "counter_done_isr()".
I rewrote the program as below.
I used Counter_3X_Done_StartEx(),
and in the ISR I only saved charindex to a variable "value_at_int"
and print it in the main loop.
Note: Please forgive me for using sprintf() instead of snprintf() 😜
main.c
============================
#include "project.h"
#include "stdio.h"
volatile uint16_t value_at_int = 0 ;
volatile int counter_done_flag = 0 ;
uint16_t charindex = 0 ;
char str[128] ; /* print buffer */
void print(char *str)
{
UART_1_PutString(str) ;
}
CY_ISR(counter_done_isr)
{
Counter_3X_ReadStatusRegister() ;
Counter_3X_Done_ClearPending() ;
counter_done_flag = 1 ;
value_at_int = charindex ;
}
void init_hardware(void)
{
UART_1_Start() ;
Counter_3X_Done_ClearPending() ;
Counter_3X_Done_StartEx(counter_done_isr) ;
Counter_3X_WriteCounter(0) ;
Counter_3X_Init() ;
Counter_3X_Enable() ;
CyGlobalIntEnable; /* Enable global interrupts. */
}
void splash(void)
{
sprintf(str, "PSoC LP5 Interrupt Test B (%s %s)\r\n", __DATE__, __TIME__) ;
print(str) ;
}
int main(void)
{
init_hardware() ;
splash() ;
for(;;) {
charindex++ ;
if (counter_done_flag) {
counter_done_flag = 0 ;
sprintf(str, "charindex = %d\n", value_at_int) ;
print(str) ;
}
CyDelay(100) ;
}
}
============================
The Tera Term Log was
moto
P.S. Attached are
int_test_190605A printing in the ISR
int_test_190605B printing in the main loop
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
In general, using print type function in an isr is not recommended.
Having said that, what I could notice was
> int UART_1_PutString(strMsg3X); //Line 35
should be
< UART_1_PutString(strMsg3X); //Line 35
Would you let me know, what kind of error(s) you will get after modifying the above?
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jon,
Moto is correct. The general principle I learned long ago is to only perform the bare minimum in ISRs. Basically just gather the data and/or turn on something quickly. What ever the ISR was truly intended for. All other time intensive operations should be done at the higher-level Application SW. sprintf()s and PutString() functions are time intensive and will probably use quite a bit of stack. Inside an ISR, you've already used a bit a stack to get there.
If more processing is needed after executing an ISR, then set a signal (RAM flag for example) so that the Application task level can pick up the signal can execute the additional operations.
Len
PS: I recommend using snprintf() instead of sprintf(). snprintf() is an ANSI-safe function. It prevents string buffer overruns.
"Engineering is an Art. The Art of Compromise."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
So I tested it by myself using CY8CKIT-059.
I emulated your project with following schematic.
To make it work, I needed to modify the ISR as
(part of Counter_3X_Done.c)
============================
CY_ISR(Counter_3X_Done_Interrupt)
{
#ifdef Counter_3X_Done_INTERRUPT_INTERRUPT_CALLBACK
Counter_3X_Done_Interrupt_InterruptCallback();
#endif /* Counter_3X_Done_INTERRUPT_INTERRUPT_CALLBACK */
/* Place your Interrupt code here. */
/* `#START Counter_3X_Done_Interrupt` */
// #include "project.h"
// #include "stdio.h"
extern void Counter_3X_Stop() ;
extern void Counter_3X_ReadStatusRegister(void) ;
extern uint16 charindex ;
char strMsg3X[30] ;
Counter_3X_Done_ClearPending() ;
Counter_3X_ReadStatusRegister() ;
sprintf(strMsg3X, "CharIndex = %u\r\n", charindex) ;
UART_1_PutString(strMsg3X) ;
/* `#END` */
}
============================
and the main.c
============================
#include "project.h"
#include "stdio.h"
uint16 charindex = 0 ;
char str[128] ; /* print buffer */
void print(char *str)
{
UART_1_PutString(str) ;
}
void init_hardware(void)
{
UART_1_Start() ;
Counter_3X_Done_ClearPending() ;
Counter_3X_Done_Start() ;
Counter_3X_WriteCounter(0) ;
Counter_3X_Init() ;
Counter_3X_Enable() ;
CyGlobalIntEnable; /* Enable global interrupts. */
}
void splash(void)
{
sprintf(str, "PSoC LP5 Interrupt Test A (%s %s)\r\n", __DATE__, __TIME__) ;
print(str) ;
}
int main(void)
{
init_hardware() ;
splash() ;
for(;;) {
charindex++ ;
CyDelay(100) ;
}
}
============================
And the Tera Term log was
So anyway, the project seems to be working.
But as I wrote earlier, having sprintf(), PutString() in ISR is not recommend because of a couple of reasons (IMHO)
(1) They usually take rather long time, where an ISR is expected return as soon as possible.
(2) They tend to allocate and/or move memory, which is also not good for an ISR, in some MCU it causes hang.
Meantime, in general, I don't want touch "system generated source/header", for example
"Counter_3X_Done.c" in this case.
I'd rather use Counter_3X_Done_StartEx() instead of Counter_3X_Done_Start()
so that I can prepare the ISR in my source files.
In the following example, "counter_done_isr()".
I rewrote the program as below.
I used Counter_3X_Done_StartEx(),
and in the ISR I only saved charindex to a variable "value_at_int"
and print it in the main loop.
Note: Please forgive me for using sprintf() instead of snprintf() 😜
main.c
============================
#include "project.h"
#include "stdio.h"
volatile uint16_t value_at_int = 0 ;
volatile int counter_done_flag = 0 ;
uint16_t charindex = 0 ;
char str[128] ; /* print buffer */
void print(char *str)
{
UART_1_PutString(str) ;
}
CY_ISR(counter_done_isr)
{
Counter_3X_ReadStatusRegister() ;
Counter_3X_Done_ClearPending() ;
counter_done_flag = 1 ;
value_at_int = charindex ;
}
void init_hardware(void)
{
UART_1_Start() ;
Counter_3X_Done_ClearPending() ;
Counter_3X_Done_StartEx(counter_done_isr) ;
Counter_3X_WriteCounter(0) ;
Counter_3X_Init() ;
Counter_3X_Enable() ;
CyGlobalIntEnable; /* Enable global interrupts. */
}
void splash(void)
{
sprintf(str, "PSoC LP5 Interrupt Test B (%s %s)\r\n", __DATE__, __TIME__) ;
print(str) ;
}
int main(void)
{
init_hardware() ;
splash() ;
for(;;) {
charindex++ ;
if (counter_done_flag) {
counter_done_flag = 0 ;
sprintf(str, "charindex = %d\n", value_at_int) ;
print(str) ;
}
CyDelay(100) ;
}
}
============================
The Tera Term Log was
moto
P.S. Attached are
int_test_190605A printing in the ISR
int_test_190605B printing in the main loop