Bootloader appears to be repeating lines of code

Go To Last Post
35 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am working on a simple bootloader project based on boot.h and the Bootloader FAQ from this site. The firmware data is sent from the PC via USB and transmitted to the AVR via i2c.

 

The bootloader appears to be working fine, it receives the correct preliminary data from the PC, but then freezes at the function where it reads the actual firmware data packets.

 

However, I use a function to blink an LED to track down errors like this and if I put this function right before the call to read, the error blink code runs multiple times as if it is wrapped in a loop! Is this even possible? Here's an example:

 

static void updateFirmware(void)
{
    // Get preliminary data and validate
    //...

    command[0] = CMD_SEND_FW_PAGE;

    while (bootStatus != STATUS_BOOT_COMPLETE)
    {
        USBSendMessage(command, SIZE_USB_CMD);

        // Let computer know we have issued a command
        setOutPinHigh();

        // Wait for In Pin High to acknowledge
        timedOut = waitForUSB(1000);
        setOutPinLow();

        if (timedOut)
        {
            continue;		// Go back to top
        }

        errorBlink(2);      // <- The LED will blink at least 4 times
        USBReadMessage(firmwarePacket, SIZE_SEND_FW_PAGE);

        //...
    }
}

// Using the Fleury i2c library
static void USBReadMessage (uint8_t message[], uint16_t size)
{
    uint16_t count = 0;
    uint8_t ACKStatus = 0;

    i2c_start(USB_ADDR + I2C_READ);

    for (count = 0; count < size; count++)
    {
        if (count == (size - 1))
        {
            ACKStatus = i2c_readNak();
        }
        else
        {
            ACKStatus = i2c_readAck();
        }

        message[count] = ACKStatus;
    }

    i2c_stop();
}

If I put that errorBlink() function after the i2c_start() in USBReadMessage(), it blinks the correct amount of times. If I put it after USBReadMessage(), it doesn't blink. Worse, sometimes I've counted up to 20 blinks when it's in front of USBReadMessage()...it's not consistent.

 

Am I nuts? Can code spontaneously wrap itself in a while loop or something? My theory is that the bootloader code is corrupt or I put it at the wrong address or something, but comparing the bootloader code's binary file to the code read off the AVR appears the same, and it appears in the right location.

 

Any clue what this could be??

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Is this a micro that does not have OCD then? Blinking LEDs is all very well but it's about 10,000 million times easier with an ICE !

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sothis wrote:

 i2c_start(USB_ADDR + I2C_READ);

This function returns a status, but you are ignoring it and ASSUMING it worked!

 

jim

 

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you clawson! Yes, it's a 644 and I have a Jtagice3. I have never attempted OCD because I've always used SMD chips; don't you need 10 pins for OCD? Is there any tutorial you can suggest that you like?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That's good advice ki0bk! I do need to look at that. There's a read (prelim info) and a write (command) before that which are successful though.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Whelp, looks like I'm SOL on the on-chip debugging. The 644 only supports JTAG

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Sothis wrote:
don't you need 10 pins for OCD?

Although a 10-pin connector is commonly used, you only occupy 4 pins on the chip:

 

(usually also a RESET connection)

 

 

Is there any tutorial you can suggest that you like?

https://microchipdeveloper.com/atmelice:connecting-atmel-ice-to-a-jtag-target

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, after looking at the board and the Atmega's pinouts for a bit, I was able to successfully solder in scrap component leads to the board and I've got JTAG going. Immediately I see a problem with how to approach this: How to sync the PC code which sends i2c data up with the debugger?

 

Because the AVR's main application handles the initial USB connection and then receives a command from the PC to restart in the bootloader. Surely I can't start debugging in the main app and then pick up the debugger in the bootloader; I'll have to write a bootloader that can stand alone and connect to the USB in place of the main ap for now. Is that how to go about this from here?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

You debug one program at a time. As the bootloader MUST be standalone start with that. When proven you can then treat it as a black box.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you clawson! So I wrote a PC side program to speak to the bootloader directly so I can debug from the start.

 

It failed to connect early in the process so I began stepping through the bootloader line by line. It goes through setting up the ports and TWI/i2c fine, but once it enters main's while loop it goes mental. Thinks inputs are high when they aren't, skips a lot of code including setting pin values (IO view shows them as if they were skipped as well). I put the LED blink back in a different spot for good measure and it was blinking 3 times when it should have been 1 but this time in a different spot than before. 

 

The normal application runs fine when I reinstall it, so my guess is that this has something to do with the me installing the bootloader wrong. The code shows up at the correct address (0xF800), OCD, JTAG, SPI & BOOTRST are set with a boot size of 1024 words, address 0x7C00. No lock bits set.

 

Are there any other gotchas with bootloaders? Maybe something with the linked i2c library's build action or something? I'm at a loss.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sothis wrote:
It failed to connect early in the process so I began stepping through the bootloader line by line. It goes through setting up the ports and TWI/i2c fine, but once it enters main's while loop it goes mental. Thinks inputs are high when they aren't, skips a lot of code including setting pin values (IO view shows them as if they were skipped as well). I put the LED blink back in a different spot for good measure and it was blinking 3 times when it should have been 1 but this time in a different spot than before.

Why can't you just put a breakpoint at whatever LED blinking you do and inspect the call stack to see how it got there 2nd and 3rd time? If inputs are read as high when they should not, you could try a simple program that reads input and sets LED depending on value and see how that works. Double check that the pins are not actually configured for some alternate function (like JTAG...).

 

Possibly try stripping down the bootloader code as much as you can until you see that it behaves correctly (or doesn't). 

 

I am guessing software issue here (uninitialized pointer, out of range indexing, etc) but guessing is not very helpful.

/Jakob Selbing

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sothis wrote:
Maybe something with the linked i2c library's build action or something?
BTW are you rebuilding the library from source code or are you linking object files only?

/Jakob Selbing

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jaksel wrote:

Why can't you just put a breakpoint at whatever LED blinking you do and inspect the call stack to see how it got there 2nd and 3rd time? If inputs are read as high when they should not, you could try a simple program that reads input and sets LED depending on value and see how that works. Double check that the pins are not actually configured for some alternate function (like JTAG...).

Thank you jaksel! Since the USB connection to the device was handled by the main application, I had to rewrite the connection process into the bootloader. When the connection process didn't work (same code as in the main app and works), I tried to debug that and saw it jumping around. It didn't occur to try the breakpoint on the LED... I'll try these suggestions and report back!

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jaksel wrote:

BTW are you rebuilding the library from source code or are you linking object files only?

From source code, not object files.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, so fails all around.

 

1. This latest LED flash thing was my error; I called it in the i2c_start function to trace that process and forgot about it. Previous problems weren't that because I was searching for forgotten calls with Find & Replace.

2. I tried using the LED to trace pin values (if bit_is_set) and it jumps right over it.

3. Call Stack isn't showing me much of anything, just the current line of code that is executing.

 

Just for a proper illustration, here's what I have:
 

int main (void)
{
	#define BOOT_READY 10
	
	uint8_t startStatus = BOOT_READY;			// Used to get startup status to decide to update or start normally
	uint8_t cpuIsReady = FALSE;					// Flag for when the USB is ready to update FW

	cli();				// Disable Interrupts
	bootInit();			// Initialize bootloader (Pins)
	i2c_init();			// Initializes the i2c bus
	
	// Enter main loop
	while(1)
	{
		/* Listen for USB handshake */
		if(bit_is_set(PIND, USB_IN_PIN))			// Check if USB wants to talk
		{
			PORTA |= 1<<PINA5;
			usb_Handshake();
		}
		
		// If handshake was successful, see what USB wants
		if (handshakeStatus == USB_HS_HANDSHAKE)
		{
			cpuIsReady = usb_GetCommand();		
			
			if (cpuIsReady)
			{
				startStatus = START_BOOT;
			}
			
			handshakeStatus = USB_HS_RESET;
		}
		
		if(bit_is_clear(PIND, USB_IN_PIN))
		{
			setOutPinLow();
		}
	}
}

static void usb_Handshake (void)
{
	setOutPinHigh();						// Set USB Out pin (High)
	handshakeStatus = USB_HS_HANDSHAKE;		// Handshake complete
}

static void setOutPinHigh(void)
{
	PORTD |= USB_OUT_MASK;
}

static void usb_GetFirmwareVersionCommand(uint8_t command)
{
	uint8_t msg[4];

	msg[0] = FW_MAJOR_VER;
	msg[1] = FW_MINOR_VER;
	msg[2] = FW_PATCH_VER;
	msg[3] = FW_BUILD_VER;
	
	// Send Firmware Version to USB controller
	USBSendMessage(msg, 4);
}
		

But when I use Step Into to see what is going on, this is what happens:
 

int main (void)
{
    cli();				// Disable Interrupts
    bootInit();         // <- Goes line-by-line in function
    i2c_init();         // <- Goes line-by-line in function
    
    uint8_t startStatus = BOOT_READY;	// Above cli();
    
    handshakeStatus = USB_HS_HANDSHAKE;		// Inside usb_handshake()
    
    startStatus = START_BOOT;               // Back in main
    
    msg[3] = FW_BUILD_VER;         // usb_GetFirmwareVersionCommand()
    
    PORTA |= 1<<PINA5;             // Back in main
    
    //NOTE: The code above is the LED. It is not on after this like it should be
    
    PORTD |= USB_OUT_MASK;         // In setOutPinHigh()
    
    handshakeStatus = USB_HS_HANDSHAKE;		// Back in usb_handshake
    
    //...No point to keep going

I only included usb_GetFirmwareVersionCommand() in the actual code view to show that there's no call to it, yet we are seeing "msg[3] = FW_BUILD_VER;" from it.

 

One interesting thing is that the code will debug the above path each time unless I change the code, in which case it will change the order slightly.

 

crying

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sothis wrote:
1. This latest LED flash thing was my error; I called it in the i2c_start function to trace that process and forgot about it. Previous problems weren't that because I was searching for forgotten calls with Find & Replace.

How do you know there aren't other unwanted modifications in your code lying around? You definitely should start using some version control system if you're not already using one.

Sothis wrote:
2. I tried using the LED to trace pin values (if bit_is_set) and it jumps right over it.

Your code looks inconsistent. My suggestion is to do something like this (pseudo code):

LED=off;
if (input_is_on())
 LED=on;

This is just to check that the MCU can properly read the pin's input state properly.

 

Sothis wrote:
One interesting thing is that the code will debug the above path each time unless I change the code, in which case it will change the order slightly.

That is at least something positive. The seemingly "random" stepping could be due to optimization.

 

So what if you try to reduce the code to a minimum working example that still exhibits the issue?

/Jakob Selbing

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jaksel wrote:

How do you know there aren't other unwanted modifications in your code lying around? You definitely should start using some version control system if you're not already using one.

Very good question. Since this was my first trial run, I suspected the problem was procedural which is why I used the LED to trace the path the code is taking. So the LED blink is the only code sprinkled around like that. Which is NOT to say there's not errors and bugs, haha, just that that type of mistake shouldn't be elsewhere. 

 

I am using git but this is v0.0.0.1 essentially.

 

jaksel wrote:

That is at least something positive. The seemingly "random" stepping could be due to optimization.

Ya, last night I found a great tutorial written by clawson about this exact thing (code jumping around during debugging). I was kind of bummed because that would mean it's a dead end, but I did more experiments last night showed the same weird behavior during runtime.

 

jaksel wrote:

So what if you try to reduce the code to a minimum working example that still exhibits the issue?

This is my goal for today. I tried to fake this yesterday by commenting out stuff, but today I'm just going to start a new project and see what happens.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quick thought: Could git actually cause this behavior or similar? I've also had unexplained crashes in my PC side project where VS couldn't find references to files that were where they always were. This started when I installed git. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can seriously screw up your life using Git but on the whole it works well as long as you know what you are doing.

 

To be honest I've re-read the thread and so far I have no idea what the problem is that you are trying to describe. What exactly do you think is wrong?

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

You can seriously screw up your life using Git but on the whole it works well as long as you know what you are doing.

 

Lol. Are any version control protocols better/safer than Git? I got bit once by reverting to a previous version that would build but the current problem (reference not found to files clearly in the project) followed to the reverted version. Then I couldn't find the way to undo the revert.

 

clawson wrote:

To be honest I've re-read the thread and so far I have no idea what the problem is that you are trying to describe. What exactly do you think is wrong?

Haha, my apologies, clearly my own confusion is a factor there.

 

What is wrong is simply when I ran the bootloader, it worked up until I sent the first packet, so I tried to track down what was happening. Poured over and over the logic and sequence of steps, found nothing obvious. But then when I used my errorBlink function (should be called traceBlink really), the number of times certain lines of code were being executed seemed impossible. Subsequent attempts to trace the path the code was taking added more confusion because in certain cases I can't find a link from pt A to pt b, so the way code is executing it looks as if someone shuffled the binary file. That's really where I'm stuck and was wondering if that was possible and how to track it down.

 

Even right before I started over, a simplified/heavily commented version seemed to show both jumping over lines of code and code executing in functions that couldn't be called.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Sothis wrote:
...I suspected the problem was procedural which is why I used the LED to trace the path the code is taking. So the LED blink is the only code sprinkled around like that. Which is NOT to say there's not errors and bugs, haha, just that that type of mistake shouldn't be elsewhere. 

My point is that when working with code, especially when debugging and doing all sorts of investigating modifications, you need to be able to tell which modifications exist at a certain point. The modifications would be with respect to some "latest and greatest" version. It sounds like you are trying to do everything in one initial version, including debugging stuff. It is better to make one version, working or not, then try to fix stuff that is not working one step at a time.

 

Sothis wrote:
This is my goal for today. I tried to fake this yesterday by commenting out stuff, but today I'm just going to start a new project and see what happens.
Don't just start over -- take the existing code and remove a little bit at a time until you see some change in behavior.

/Jakob Selbing

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sothis wrote:
Are any version control protocols better/safer than Git?

I find SVN more "straightforward".

 

The Big Thing with Git is to support large, widely distributed teams. This adds a level of complexity which is of (almost?) zero benefit if it's just you & your own code.

 

YMMV

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jaksel wrote:
...It sounds like you are trying to do everything in one initial version, including debugging stuff. It is better to make one version, working or not, then try to fix stuff that is not working one step at a time.

Ah I see! Yup, that's exactly what I did!

jaksel wrote:
Don't just start over -- take the existing code and remove a little bit at a time until you see some change in behavior.

That is what I did up until Sat night, but even with just that simple function I was getting really weird results. 

if (bit_is_set(PIND, USB_IN_PIN))
{
    PORTA ^= 1<<PINA5;
    usb_Handshake();
}

This would not toggle the LED. But:

if (bit_is_set(PIND, USB_IN_PIN))
{
    PORTA ^= 1<<PINA5;
    usb_Handshake();
    errorBlink(1); // Toggles PINA5
}

Both the LED would blink and stay on from the toggle! The only explanation for this is aliens.

 

And don't worry, I didn't really start over, just started a new project and copied bits back in at a time. Interestingly, that section of code was the first I put back in and so far, the alien has yet to appear.

Last Edited: Tue. Mar 31, 2020 - 03:07 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
The Big Thing with Git is to support large, widely distributed teams. This adds a level of complexity which is of (almost?) zero benefit if it's just you & your own code.

Thank you awneil! I'll look into SVN.

 

Ya, it's just me so I don't even need to have the online repo or all of that stuff. Really I just need a way to track versions, maybe the occasional branch, and it would be nice to be able to look at any previous version's entire project, as if I had just been copying the entire project to a new folder, say "Bootloader v1" then "Bootloader v2", etc. I haven't figured out how to do that with Git yet.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You're adding 2 things too many in your code.

 

What if you do just this:

if (bit_is_set(PIND, USB_IN_PIN))
{
   PORTA |= 1<<PINA5;
}
else
{
   PORTA &= ~(1<<PINA5);
}

Just to be able to show whether you can properly read an input (which you claimed you cannot).

/Jakob Selbing

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One thing that confuses me is that this code is peppered with calls to usb_this() and usb_that() yet as far as I can tell this is not a USB chip and there is no USB stack involved here (if there were then the complecity of such a thing can certainly complicate things - for example USB would almost certainly imply interrupts and then you would be faced with interrupt handling in a bootloader and IVSEL and so on). As far as I know the PC-AVR link is actually that the PC has a USB-I2C interface and then the I2c is connected to the I2C of the AVR. So in the AVR there is no "USB" it's all I2C and the functions are all just prefixed usb_*() because it's talking about data that starts its path across a PC(USB) to I2C link but that actually arrives in the AVR purely by I2C (much simpler than USB). is that the case or have I misunderstood?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jaksel wrote:
Just to be able to show whether you can properly read an input (which you claimed you cannot).

Ok, I think I see what is going on here, it's a timing/sequence issue. I tried your code in the original and it worked; I can see a little blip like expected. To make sure I wasn't losing it, I slightly modified it to this:

if(bit_is_set(PIND, USB_IN_PIN))
{
    PORTA ^= (1<<PINA5);
}

This should toggle the LED each time I set the pin high, but the first time I saw a blip, the second time the LED turned on, and I wasn't able to get the LED to blip or turn off from there.

 

But, on the PC side, the handshake code sets it's pin high then delays for a short period and checks to see if the AVR responded by setting it's pin high, and repeats this a few times. So with the above code being the only thing in a while loop, the USB_IN_PIN is being evaluated for 1. Raising the Out pin initially, 2. The delay, 3. The check for a response. That probably explains the aliens as the delays in errorBlink() were preventing multiple evaluations of USB_IN_PIN.

 

I'll run with this today and see what happens, but at least something is making sense. Thank you jaksel!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
As far as I know the PC-AVR link is actually that the PC has a USB-I2C interface and then the I2c is connected to the I2C of the AVR. So in the AVR there is no "USB" it's all I2C and the functions are all just prefixed usb_*() because it's talking about data that starts its path across a PC(USB) to I2C link but that actually arrives in the AVR purely by I2C (much simpler than USB). is that the case or have I misunderstood?

Yes, that is correct, there's a USB-I2C interface and I'm just prefixing usb_ to the functions that use the chip. The USB_IN_PIN and USB_OUT_PINs referenced are GPIO on the USB interface as well.

 

My attempt to simplify everything was to use those 2 pins to communicate that either the PC wants the AVR for something, or vice versa, then the devices will read/write based on the step they are currently on. I thought this would make this extremely easy in lieu of doing it solely based on USB to I2C communication but it's confusing working on two devices at once!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Sothis wrote:
This should toggle the LED each time I set the pin high, but the first time I saw a blip, the second time the LED turned on, and I wasn't able to get the LED to blip or turn off from there.

First time doing what?

 

So we can conclude that your conclusion regarding input pins not being read properly was wrong? See how easy it is to check such an assumption.

 

Sothis wrote:
But, on the PC side, the handshake code sets it's pin high then delays for a short period and checks to see if the AVR responded by setting it's pin high, and repeats this a few times. So with the above code being the only thing in a while loop, the USB_IN_PIN is being evaluated for 1. Raising the Out pin initially, 2. The delay, 3. The check for a response. That probably explains the aliens as the delays in errorBlink() were preventing multiple evaluations of USB_IN_PIN.

What you are saying is that when code is doing a delay loop, it is blocked from doing other stuff (like checking pins). Not very surprising! :)

/Jakob Selbing

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

Which is why you should NEVER develop two ends of a communication link at the same time. Use something known/working at one end and develop against that. When you have you then have something new that is known/working that you can develop against at the other end.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jaksel wrote:
First time doing what?

Setting the USB_IN_PIN high via that handshake function described earlier.

 

jaksel wrote:
So we can conclude that your conclusion regarding input pins not being read properly was wrong? See how easy it is to check such an assumption.

Ya, it looks that way. I think the big lesson here is that when you have 'complete' code and begin testing it, the problems can be anywhere. Deconstructing to isolate the problem becomes harder because, you have code on both sides (PC and AVR) that is really designed for when things are working, so if you aren't careful, then it's easy to overlook things. But if you go the other way, from simple to complex, you get a chance to prove things as you go, i.e., "OK, I know the USB_IN_PIN does in fact go high, so it's gotta be this new thing I just added".

 

jaksel wrote:
What you are saying is that when code is doing a delay loop, it is blocked from doing other stuff (like checking pins). Not very surprising! :)

So what is a better way to do this? Because we definitely need to give the AVR a bit of time to respond since there will be a USB delay and the AVR is much slower. On the PC I was using TaskCompletionSource, basically async/await (pseudocode to give the idea):

Task<bool> DeviceHandshakePC()
{
    SetOutPinHigh();
    
    while (count <= 10)
    {
        Task.Delay(1);
        
        GetInPinState();
        
        if(IN_PIN_HIGH)     // AVR Responded
        {
            SetOutPinLow();
            return true;
        }
        
        count++;
    }
    
    // AVR did not respond
    SetOutPinLow();         
    return false;
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Which is why you should NEVER develop two ends of a communication link at the same time. Use something known/working at one end and develop against that. When you have you then have something new that is known/working that you can develop against at the other end.

I see. Ya, this is my first attempt at anything outside of chip to chip communication like an IO expander. I guess there the one end (target chip) IS known to be working, huh?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Sothis wrote:
So what is a better way to do this? Because we definitely need to give the AVR a bit of time to respond since there will be a USB delay and the AVR is much slower. On the PC I was using TaskCompletionSource, basically async/await (pseudocode to give the idea)...

Now I'm confused! You wrote earlier:

Sothis wrote:
That probably explains the aliens as the delays in errorBlink() were preventing multiple evaluations of USB_IN_PIN.

Weren't you talking about the AVR here? 

 

If the AVR is doing a blocking delay (i.e. a call to delay_ms() or similar) it will be busy doing that and cannot react to any polled input pin changes. It can however do other stuff using interrupts but this was not the case here AFAIK.

 

This is the reason why you should avoid blocking delays. Use hardware timers and state machines instead.

/Jakob Selbing

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jaksel wrote:
Now I'm confused! You wrote earlier:

Crap, I am too. 

jaksel wrote:
Weren't you talking about the AVR here? 

My point was that the errorBlink() function is a bit of an anomaly because it won't be there normally, just for testing. But in practice, we will still need delays of some sort to make this work. So I was just asking what it looks like to write a function that delays without using delays, and what else the CPU could be doing during that time? The reason I gave the PC-side code was just to illustrate that because it's async/await the delay shouldn't block, but how do we do the AVR-side code to match that? The timers and state machines makes sense though.

 

I assume when we use timers and state machines (only did this once without realizing it was called something), we break it up based on function? For instance, the handshake sm would keep track of where it is in the handshake process, but another section would keep track of where we are in the firmware update sequence (send preliminary data, updating, calculating checksum, etc)?

My apologies, I obviously care about fixing the problem, but I also like to learn the right ways to do stuff as well! Thank you!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sothis wrote:
My point was that the errorBlink() function is a bit of an anomaly because it won't be there normally, just for testing.
You shouldn't view testing and debugging as an anomaly - they are in fact a big part of application development. Design your code to allow testing and debugging instead.

 

Sothis wrote:
I assume when we use timers and state machines (only did this once without realizing it was called something), we break it up based on function? For instance, the handshake sm would keep track of where it is in the handshake process, but another section would keep track of where we are in the firmware update sequence (send preliminary data, updating, calculating checksum, etc)?
Yes, exactly.

 

/Jakob Selbing