I had searched in the Discussion Forum for the whole moring but I couldn't find the right way to solve the problem I met,so I send this message hoping you guys can help me!Thanks in advance:-)My problem is as follows: 1.I want to define a macro,which is similar like function.It will be used in my communction interrupt service routine(so you can see that why I don't choose to call a function to realize it) 2.here's the definition of this macro: #define Macro_TestRxEnd(sbit Header_flag,uchar Header,uchar Tailer) \ { \ Return_flag = 0; \ if (!Header_flag) \ { \ if (Rxbuf == Header) \ { \ Header_flag = 1; \ ptRxBuf++; \ } \ else \ { ptRxBuf = xBuf; } \ else \ { \ if (Rxbuf == Tailer) \ { Return_flag = 1; } \ } 3.then the compile result is : Error C304: Bad Macro Parameter List so can anyone help me find out the right way to define such a long macro? I'm waiting for your good ideas earnestly!
Remember that a macro is implemented by text substitution - a macro parameter list doesn't need (or accept) data types.
"Remember that a macro is implemented by text substitution - a macro parameter list doesn't need (or accept) data types." And being a text substitution, one must be aware of the gotcha using brace-enclosed multi-statements macros in if/else clauses that don't use braces. Multi-statement macro definitions should envelope those multiple statements in do{}while(0) See: http://www.eskimo.com/~scs/C-faq/q10.4.html
:-)I'm so happy to see so many engineers take part in the discussion and raise many new ideas,thank you.And apologies for the length of time it has taken me to cknowledge your help.OK,Here's some of my points after reading your respondence: 1.First of all,I'd like to give an example to explain more about: It will be used in my communction interrupt service routine(so you can see that why I don't choose to call a function to realize it) Whether I write program in C or in assemble,I'll always try to avoid calling a function in ISR routine,the main reason is to avoid the overflow of SP(stack).As you know,the resource of microprocessor is limited,especially the ability of multi-level nesting.For example: the main program calls the display function --->the display calls read EEPROM function to read back data to LCD buffer--->the read EEPROM calls the bottom I2C sub-functions to get the data--->imagine the communcion ISR occurs at this time,then if use call other functions in ISR routine, you can see the nesting is so multi-level(of ourse,different microprocessers vary in this property). Now can you understand my point?If still puzzled,respondence is welcomed:-) 2.Secondly,the reason "why a macor" is that: there're 3 kinds of frame mode in the communication protocol.Let me put it like this:frame A/ frame B/frame C each frame has their own frame header and tailer.So in the ISR, void ISR_ROUTINE(void) { ....... switch(framemode) { case A: Macro_TestRxEnd(AHeader_flag, A_Header, A_Tailer); break; case B: Macro_TestRxEnd(BHeader_flag, B_Header, B_Tailer); break; case C: Macro_TestRxEnd(CHeader_flag, C_Header, C_ Tailer); break; default: break; } ...... } So that's why not just write it as straight code!! 3.Remember that a macro is implemented by text substitution - a macro parameter list doesn't need (or accept) data types. Yes, that's true. 4.Thanks Dan Henry for the link :http://www.eskimo.com/~scs/C-faq/q10.4.html .It helps a lot:-)If your guys don't mind,I suggest that let's forget all other things only for 1minute except putting focus on finding the right way to write a multi-statement macro that can be successfully compiled.So I'll try this define way later(because I'm now busy in writing back of your warmhearted respondence:-) 5.Thanks Andy Neil for your advice:-) There is a general rule-of-thumb that one should try to keep Interrupt Service Routines (ISRs) "small" - meaning that the amount of code executed during the interrupt service should be minimised.Putting your code into a Macro will not help in this respect! From the above point 2,you can see that in this case,the macro here not affect much in the ISR "small" rule.Of cource,I'll re-think about the best way to realize it:-) 6.Lastly,thank you again for everyone who take time to reply.The above is my personal points of view,and if any questions,please feel free to respond:-)
I work on 32-bit RISC systems with vast amounts of memory and stack space, but I mostly work on very small 4-bit and 8-bit systems with very limited amounts of memory and stack space. For example some PICs have an 8-level hardware return stack and some have only 2 levels, so I am very familiar with call/interrupt nesting awareness and using memory efficiently. That said, I think you are being a bit too conservative in this regard with respect to an 8051-based system. If you are that tight on memory then you could be destined for trouble despite your efforts to save a call from within an ISR. Give your ISR room to breathe. Don't get me wrong, I eschew unnecessary calls from ISRs too, but I also don't obscure my code by using macros (inappropriately) either. By "obscure", I mean that your protocol frame tests are not that complex and by using macros (at least as you have presented them) you are actually doing yourself and your successors a disservice by obscuring direct data object manipulation and side effects. Let's say you fix the macro parameter typing, you are still using "xBuf", "Rxbuf", "ptRxBuf", and "Return_flag" inside the macro, hiding their use from a reader. In this case you are much better off just laying it all out explicitly in the ISR so that one can see exactly what is being used and affected. Keeping ISRs small refers to keeping the execution paths short and overall time spent in the ISR short. You could have a mile-long switch/case statement in your ISR with each case having a simple body and it would be considered "small". So look again, switch on "framemode", a few conditional statements, and you're done! That's "small".
View all questions in Keil forum