What does this error mean?
Hi. The problem is described here. I would like to know is it possible that modbus is not working because of that error? Thank you.
Can you provide a zipped folder that contains everything needed to reproduce the issue? or code that reproduces it and a link to get the versions of any libraries needed to reproduce the issue? The only time I see that error was when I tried to set optimizing to somethjign other than size, and it blew up all my handoptimized assembly. (that's why that option was removed, yasee)
What I meant when I asked for everything needed is not copies of my core but copies of all the libraries needed to make your code compile.
You have included none of them, so none of your code compiles because ModbusRTUSlave.h is not found.
I do not waste time trying to find out what version of the library you are using, because there's no way to know. ModbusRTUSlave.h doesn't uniquely identify what version of who's fork of the library you're using it, and every single time I've tried to "figure out" what library version they were using, it's always been the wrong one. So that is a no-exceptions rule - I am manifestly incapable of divining what version of the library you used (in fact, there are numerous of examples of libraries that differ in everything except name. Totally different API, everything except name and purpose have no similarities.), so if a problem requires me to compile code in order to debug it I need the library files
My apologies of being a bid thick. Anyway, I have figured out that this is something to do with the software serial. I have changed my prototype to hardware serial pins and it is working fine. Since I define Modbus to software serial, getting this error again. ModbusRTUSlave.zip
I have not been successful in determining why the linker is failing to compile in necessary code
The problem is caused by the need to handle the following corner case:
- Interrupts are disabled (1A) or execution is occurring within an interrupt (1B).
- There is 1 or more character currently in the ring buffer waiting to be transferred
- The user calls flush().
Absent some countermeasure, because interrupts not enabled (either another normal priority interrupt is running, or globally disabled), the ISR to load the next character to send into the USART won't fire, and you would wait forever in flush because the buffer will never finish sending.
The original code from Arduino worked only in 1B, and:
- Recorded the current setting for the priority interrupt vector
- Elevated the USART ISR to Priority 1 (Oh they are not seriously doing this...)
- Waited until the transmit buffer was empty (my god, they really are)
- Restored the original setting for the priority interrupt vector. (well at least they did this right)
- Contained a race condition that could hang the system at high baud rates. Appeared to be a can't-happen which under some conditions did happen. (and did the "not crashing" part wrong)
Understanding of the phenomenon was insufficient to demonstrate that any particular speed and baud rate could not manifest this issue (He didn't have a clue why it crashed! "That code was not worth understanding following the recognition that the bug was there, and the code needed to be refactored with a flamethrower. It was easily the upper speedlimit for the USART, and would have been even without the race condition.
This was reimplemented initially by polling, and manually calling the ISR, continuing the inefficient conventions of standard Arduino and pure C, which is what had been done in classic AVRs and worked. This was the pre-ASM version of the USART code.
I think I implemented a bunch of the extended features around then, because I had all three ISRs by the time I did the ASM (The TXC ISR is used in half-duplex mode to turn on the receiver when done transmitting, because we don't want to receive our own output, and "proper" use, using the loopback for collision detection, I'm not sure I see a suitably general way to pull that off, and I don't really have much desire to). At this point, the ISRs were still the speedlimit for the USART.
Subsequently, as I became more familiar with asm, and started looking at my listings, I was aghast at how bloated the implementations of both big ISRs came out. This was due to the fact that a function was called within the ISR. Adds like 28 words and 1.5x that many clocks to the ISR, minimum. The whole thing was reimplemented. Each ISR is naked; pushes a register onto the stack, loads the number of the peripheral into that address and then jumps to the isr, which is a naked, used function containing only inline asm. It then carries out the prologue, body and epilogue, and ends in a 'reti' to return from the interrupt. This first used the compiled output as the ASM (this alone yields savings when 2 or more UARTs are in use), but as I said, the compiler output was abysmal. Pieces were excised and optimized. TXC was trivial, RXC wasn't bad (though it had a couple of bugs for a while). DRE was fine when flush didn't have to work, but the same fix as above was not possible because we didn't have a function to call, cause half the point of doing the asm was to not have any function calls involved. Instead, I did essentially the same thing I did in the entry to the asm The necessary piece of code is part of Serial.flush(), which in your case for reasons unclear is not being compiled in, so it chokes when it tries to compile DRE. Adding a call to Serial.flush() somewhere in the main code prevents the compiler from optimizing away the part that DRE needs. I'm looking into ways to prevent this issue.
I don't know why in this case, but when checking dependencies, the compiler just forgot about DRE... ..... Wasn't there a song about people who do that, or who act like it? Wasn't sympathetic to them as I recall...