USBaspLoader and ATmega32
Posted: Mon Jul 28, 2008 12:41 pm
Hello, everybody. I got a trouble with usbasploader and atmega32. I wired D+ to PD3(INT1), D- to PD6, jumper to PD7. My board doen't recognized by pc. I have added some code to main.c, so i can see when controller is rebooting and so on. I see, that after board starts it behaves ok, it recognizes the jumper position and so on. But when PC is sending anything over D+ line - the board reboots. I read MCUCSR register and it is filled by zeroes after such reboot. If i disable interrupt handling board dont reboots, but doesn't work too. I have added some asm code to interrupt handler, but that code never executes.
I think that after an interrupt on D+ controller jumps not to INT1 handler, but to 0 or other place. The datasheet says that INT1 vector position is BOOTLOADER_START+0x04, INT0 - +0x02 and so on. But i did avr-objdump -d main.bin and saw that INT1 vector was placed at +0x08 position.
I built my project with latest gcc-avr in Gnetoo Linux and with winavr gcc-3.4.6 - results are absolutly same. Also i tried to simulate atmega32 in Proteus, but it reboots after any activity on D+ line.
I use 5V power source, tried to solder zener diodes(3V6), pull-down resistor(1M1) to D+, but that didn't help. Tried to use another atmega32, but results stay the same. I googled for a long time, but nothing helps
Unfortunatly, i cant debug avr-usb driver, because my usart over max232 don't works too I'll try to use INT0 tomorrow.
Here are relevant parts of my project:
usbconfig.h:
#define USB_INTR_CFG MCUCR
#define USB_INTR_CFG_SET ((1 << ISC10) | (1 << ISC11))
#define USB_INTR_CFG_CLR 0
#define USB_INTR_ENABLE GICR
#define USB_INTR_ENABLE_BIT INT1
#define USB_INTR_PENDING GIFR
#define USB_INTR_PENDING_BIT INTF1
#define USB_INTR_VECTOR SIG_INTERRUPT1 //tried SIG_INTERRUPT0 to place handler at +0x04 address, but no success
bootloaderconfig.h:
#define USB_CFG_IOPORTNAME D
#define USB_CFG_DMINUS_BIT 6
#define USB_CFG_DPLUS_BIT 3
#define JUMPER_BIT 7
static inline void bootLoaderInit(void)
{
PORTD |= (1 << JUMPER_BIT); /* activate pull-up */
//if(!(MCUCSR & (1 << EXTRF))) /* If this was not an external reset, ignore */
// leaveBootloader();
MCUCSR = 0; /* clear all reset flags for next time */
}
Makefile:
F_CPU = 16000000
DEVICE = atmega32
BOOTLOADER_ADDRESS = 7800
FUSEOPT = $(FUSEOPT_168)
LOCKOPT = -U lock:w:0x2f:m
PROGRAMMER = -c stk500v2 -P avrdoper
# PROGRAMMER contains AVRDUDE options to address your programmer
FUSEOPT_32 = -U hfuse:w:0xc0:m -U lfuse:w:0x8f:m
FUSEOPT_8 = -U hfuse:w:0xc0:m -U lfuse:w:0x9f:m
FUSEOPT_88 = -U hfuse:w:0xd6:m -U lfuse:w:0xdf:m -U efuse:w:0x00:m
FUSEOPT_168 = -U hfuse:w:0xd6:m -U lfuse:w:0xdf:m -U efuse:w:0x00:m
main.c:
/* DEBUG */
// enable PB1 as output
#define LED1_INIT DDRD|=_BV(PD4)
// // led on, pin=0
#define LED1_OFF PORTD&=~_BV(PD4)
// // led off, pin=1
#define LED1_ON PORTD|=_BV(PD4)
// enable PB1 as output
#define LED2_INIT DDRD|=_BV(PD5)
// // led on, pin=0
#define LED2_OFF PORTD&=~_BV(PD5)
// // led off, pin=1
#define LED2_ON PORTD|=_BV(PD5)
int main(void)
{
LED1_INIT;
LED2_INIT;
LED1_ON;
LED2_ON;
_delay_ms(200);
/* initialize */
bootLoaderInit();
odDebugInit();
DBG1(0x00, 0, 0);
#ifndef NO_FLASH_WRITE
GICR = (1 << IVCE); /* enable change of interrupt vectors */
GICR = (1 << IVSEL); /* move interrupts to boot flash section */
#endif
if(bootLoaderCondition()){
uint i = 0;
initForUsbConnectivity();
do{
LED2_OFF;
usbPoll();
#if BOOTLOADER_CAN_EXIT
if(requestBootLoaderExit){
if(--i == 0)
break;
}
#endif
}while(bootLoaderCondition()); /* main event loop */
}
LED1_OFF;
_delay_ms(200);
leaveBootloader();
return 0;
}
/*
After start we see 2 leds, wait 200ms. If led2 is on and led1 - off it means that bootloader condition don't met. If led1 is on and led2 is off - we are in main loop. So if we reboot somewhere during this loop we will see two leds on again.
*/
main.bin:
main.bin: file format elf32-avr
Disassembly of section .text:
00007800 <__vectors>:
7800: 0c 94 53 3c jmp 0x78a6 <__init>
7804: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7808: 0c 94 8d 3c jmp 0x791a <__vector_2>
780c: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7810: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7814: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7818: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
781c: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7820: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7824: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7828: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
782c: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7830: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7834: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7838: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
783c: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7840: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7844: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7848: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
784c: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7850: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
********************************************
0000791a <__vector_2>:
791a: cf 93 push r28
791c: cf b7 in r28, 0x3f ; 63
791e: cf 93 push r28
00007920 <waitForJ>:
7920: 86 9b sbis 0x10, 6 ; 16
7922: fe cf rjmp .-4 ; 0x7920 <waitForJ>
****************************************************
I think that after an interrupt on D+ controller jumps not to INT1 handler, but to 0 or other place. The datasheet says that INT1 vector position is BOOTLOADER_START+0x04, INT0 - +0x02 and so on. But i did avr-objdump -d main.bin and saw that INT1 vector was placed at +0x08 position.
I built my project with latest gcc-avr in Gnetoo Linux and with winavr gcc-3.4.6 - results are absolutly same. Also i tried to simulate atmega32 in Proteus, but it reboots after any activity on D+ line.
I use 5V power source, tried to solder zener diodes(3V6), pull-down resistor(1M1) to D+, but that didn't help. Tried to use another atmega32, but results stay the same. I googled for a long time, but nothing helps
Unfortunatly, i cant debug avr-usb driver, because my usart over max232 don't works too I'll try to use INT0 tomorrow.
Here are relevant parts of my project:
usbconfig.h:
#define USB_INTR_CFG MCUCR
#define USB_INTR_CFG_SET ((1 << ISC10) | (1 << ISC11))
#define USB_INTR_CFG_CLR 0
#define USB_INTR_ENABLE GICR
#define USB_INTR_ENABLE_BIT INT1
#define USB_INTR_PENDING GIFR
#define USB_INTR_PENDING_BIT INTF1
#define USB_INTR_VECTOR SIG_INTERRUPT1 //tried SIG_INTERRUPT0 to place handler at +0x04 address, but no success
bootloaderconfig.h:
#define USB_CFG_IOPORTNAME D
#define USB_CFG_DMINUS_BIT 6
#define USB_CFG_DPLUS_BIT 3
#define JUMPER_BIT 7
static inline void bootLoaderInit(void)
{
PORTD |= (1 << JUMPER_BIT); /* activate pull-up */
//if(!(MCUCSR & (1 << EXTRF))) /* If this was not an external reset, ignore */
// leaveBootloader();
MCUCSR = 0; /* clear all reset flags for next time */
}
Makefile:
F_CPU = 16000000
DEVICE = atmega32
BOOTLOADER_ADDRESS = 7800
FUSEOPT = $(FUSEOPT_168)
LOCKOPT = -U lock:w:0x2f:m
PROGRAMMER = -c stk500v2 -P avrdoper
# PROGRAMMER contains AVRDUDE options to address your programmer
FUSEOPT_32 = -U hfuse:w:0xc0:m -U lfuse:w:0x8f:m
FUSEOPT_8 = -U hfuse:w:0xc0:m -U lfuse:w:0x9f:m
FUSEOPT_88 = -U hfuse:w:0xd6:m -U lfuse:w:0xdf:m -U efuse:w:0x00:m
FUSEOPT_168 = -U hfuse:w:0xd6:m -U lfuse:w:0xdf:m -U efuse:w:0x00:m
main.c:
/* DEBUG */
// enable PB1 as output
#define LED1_INIT DDRD|=_BV(PD4)
// // led on, pin=0
#define LED1_OFF PORTD&=~_BV(PD4)
// // led off, pin=1
#define LED1_ON PORTD|=_BV(PD4)
// enable PB1 as output
#define LED2_INIT DDRD|=_BV(PD5)
// // led on, pin=0
#define LED2_OFF PORTD&=~_BV(PD5)
// // led off, pin=1
#define LED2_ON PORTD|=_BV(PD5)
int main(void)
{
LED1_INIT;
LED2_INIT;
LED1_ON;
LED2_ON;
_delay_ms(200);
/* initialize */
bootLoaderInit();
odDebugInit();
DBG1(0x00, 0, 0);
#ifndef NO_FLASH_WRITE
GICR = (1 << IVCE); /* enable change of interrupt vectors */
GICR = (1 << IVSEL); /* move interrupts to boot flash section */
#endif
if(bootLoaderCondition()){
uint i = 0;
initForUsbConnectivity();
do{
LED2_OFF;
usbPoll();
#if BOOTLOADER_CAN_EXIT
if(requestBootLoaderExit){
if(--i == 0)
break;
}
#endif
}while(bootLoaderCondition()); /* main event loop */
}
LED1_OFF;
_delay_ms(200);
leaveBootloader();
return 0;
}
/*
After start we see 2 leds, wait 200ms. If led2 is on and led1 - off it means that bootloader condition don't met. If led1 is on and led2 is off - we are in main loop. So if we reboot somewhere during this loop we will see two leds on again.
*/
main.bin:
main.bin: file format elf32-avr
Disassembly of section .text:
00007800 <__vectors>:
7800: 0c 94 53 3c jmp 0x78a6 <__init>
7804: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7808: 0c 94 8d 3c jmp 0x791a <__vector_2>
780c: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7810: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7814: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7818: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
781c: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7820: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7824: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7828: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
782c: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7830: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7834: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7838: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
783c: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7840: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7844: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7848: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
784c: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
7850: 0c 94 6e 3c jmp 0x78dc <__bad_interrupt>
********************************************
0000791a <__vector_2>:
791a: cf 93 push r28
791c: cf b7 in r28, 0x3f ; 63
791e: cf 93 push r28
00007920 <waitForJ>:
7920: 86 9b sbis 0x10, 6 ; 16
7922: fe cf rjmp .-4 ; 0x7920 <waitForJ>
****************************************************