From 595b30cbe50efb165ccea9c8ee369013df1b5069 Mon Sep 17 00:00:00 2001 From: Leon Krieg Date: Mon, 30 Sep 2024 19:45:02 +0200 Subject: [PATCH 01/11] Update Makefile settings for new chip architecture --- Makefile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 54c2073..9c3d331 100644 --- a/Makefile +++ b/Makefile @@ -9,12 +9,10 @@ # ============================================================================== VERBOSE := false -#ARCH := m1284p -ARCH := m32 +ARCH := m1284p #FREQ := 18432000UL FREQ := 8000000UL -#MCU := atmega1284p -MCU := atmega32a +MCU := atmega1284p ASP := usbasp CC := avr-gcc LD := $(CC) From 68050b62264f0f3cee51ce257b7edddc695a03d0 Mon Sep 17 00:00:00 2001 From: Leon Krieg Date: Mon, 30 Sep 2024 19:46:38 +0200 Subject: [PATCH 02/11] Update module 'memory' to run on atmega1284p hardware --- src/common/memory.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/common/memory.c b/src/common/memory.c index a691c1a..8680081 100644 --- a/src/common/memory.c +++ b/src/common/memory.c @@ -189,14 +189,14 @@ static void ReadBlock(int n, mem_block_t *out) static void WriteRaw(int addr, byte data) { - // The EEMWE bit determines whether setting EEWE to - // one causes the EEPROM to be written. When EEMWE - // is set, setting EEWE within four clock cycles + // The EEMPE bit determines whether setting EEPE to + // one causes the EEPROM to be written. When EEMPE + // is set, setting EEPE within four clock cycles // will write data to the EEPROM at the selected // address. - // If EEMWE is zero, setting EEWE will have no - // effect. When EEMWE has been written to one by + // If EEMPE is zero, setting EEPE will have no + // effect. When EEMPE has been written to one by // software, hardware clears the bit to zero after // four clock cycles. @@ -206,33 +206,40 @@ static void WriteRaw(int addr, byte data) // If an interrupt routine accessing the EEPROM is // interrupting another EEPROM Access, the EEAR or - // EEDR reGister will be modified, causing the + // EEDR register will be modified, causing the // interrupted EEPROM Access to fail. // It is recommended to have the Global Interrupt // Flag cleared during all the steps to avoid these // problems. + // When the write access time has elapsed, the EEPE + // bit is cleared by hardware. The user software can + // poll this bit and wait for a zero before writing + // the next byte. When EEPE has been set, the CPU is + // halted for two cycles before the next instruction + // is executed. + // No interrupts during EEPROM write ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { // Wait until ready - while (EECR & BIT(EEWE)); + while (EECR & BIT(EEPE)); // The EEPROM Address Registers – EEARH and - // EEARL – specify the EEPROM address in the - // 1024bytes EEPROM space. The EEPROM data - // bytes are addressed linearly between 0 - // and 1023. The initial value of EEAR is - // undefined. A proper value must be written - // before the EEPROM may be accessed. + // EEARL specify the EEPROM address in the + // 512/1K/2K/4Kbytes EEPROM space. The EEPROM + // data bytes are addressed linearly between 0 + // and 511/1023/2047/4096. The initial value + // of EEAR is undefined. A proper value must be + // written before the EEPROM may be accessed. EEAR = addr; EEDR = data; // Write to address - EECR |= BIT(EEMWE); - EECR |= BIT(EEWE); + EECR |= BIT(EEMPE); + EECR |= BIT(EEPE); } } @@ -256,7 +263,7 @@ static byte ReadRaw(int addr) ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { // Wait until ready - while (EECR & BIT(EEWE)); + while (EECR & BIT(EEPE)); EEAR = addr; From 685a73e202a600c862f002e670e5e27409aa9924 Mon Sep 17 00:00:00 2001 From: Leon Krieg Date: Mon, 30 Sep 2024 20:58:13 +0200 Subject: [PATCH 03/11] Update module 'watchdog' to run on atmega1284p hardware --- src/common/watchdog.c | 120 ++++++++++++++++++++++-------------------- src/common/watchdog.h | 2 +- 2 files changed, 65 insertions(+), 57 deletions(-) diff --git a/src/common/watchdog.c b/src/common/watchdog.c index 3c8091b..fc610af 100644 --- a/src/common/watchdog.c +++ b/src/common/watchdog.c @@ -6,103 +6,111 @@ void WDT_Enable(void) { Info("Enabling watchdog timer..."); - // WDTCR: Watchdog Timer Control Register + // WDTCSR: Watchdog Timer Control Register - // 7 6 5 4 3 2 1 0 - // – – - WDTOE WDE WDP2 WDP1 WDP0 + // 7 6 5 4 3 2 1 0 + // WDIF WDIE WDP3 WDCE WDE WDP2 WDP1 WDP0 - // When the WDE is written to logic one, the - // Watchdog Timer is enabled, and if the WDE is - // written to logic zero, the Watchdog Timer - // function is disabled. + // WDP3:0: Watchdog Timer Prescaler + // The WDP3:0 bits determine the Watchdog Timer + // prescaling when the Watchdog Timer is running. + // The different prescaling values and their + // corresponding time-out periods are - // WDP2, WDP1, WDP0: Watchdog Timer Prescaler - // The WDP2, WDP1, and WDP0 bits determine the - // Watchdog Timer prescaling when the Watchdog - // Timer is enabled. The different prescaling - // values and their corresponding Timeout - // Periods are: + // WDP3 WDP2 WDP1 WDP0 Cycles Timeout5V + // 0 0 0 0 2K 16ms + // 0 0 0 1 4K 32ms + // 0 0 1 0 8K 64ms + // 0 0 1 1 16K 125ms + // 0 1 0 0 32K 250ms + // 0 1 0 1 64K 500ms + // 0 1 1 0 128K 1000ms + // 0 1 1 1 256K 2000ms + // 1 0 0 0 512K 4000ms + // 1 0 0 1 1024K 8000ms - // WDP2 WDP1 WDP0 Cycles Timeout3V Timeout5V - // 0 0 0 16K 17.10ms 16.30ms - // 0 0 1 32K 34.30ms 32.50ms - // 0 1 0 64K 68.50ms 65.00ms - // 0 1 1 128K 0.14s 0.13s - // 1 0 0 256K 0.27s 0.26s - // 1 0 1 512K 0.55s 0.52s - // 1 1 0 1,024K 1.10s 1.00s - // 1 1 1 2,048K 2.20s 2.10s - - // WDTOE: Watchdog Turn-off Enable This bit must - // be set when the WDE bit is written to logic zero. - // Otherwise, the Watchdog will not be disabled. - // Once written to one, hardware will clear this - // bit after four clock cycles. + // WDCE: Watchdog Change Enable + // This bit is used in timed sequences for changing + // WDE and prescaler bits. To clear the WDE bit, + // and/or change the prescaler bits, WDCE must be + // set. Once written to one, hardware will clear + // WDCE after four clock cycles. // 00001111: Watchdog enabled, 2sec timeout - WDTCR = BIT(WDE) | BIT(WDP2) | BIT(WDP1) | BIT(WDP0); + WDTCSR = BIT(WDE) | BIT(WDP2) | BIT(WDP1) | BIT(WDP0); } void WDT_SetTimeoutFlag(byte flag) { + // Currently only support for a maximum of 2 seconds + // timeout because there is no need for more and the + // bit location of WDP3 requires conditional logic. + + // The sequence for clearing WDE and changing timeout + // configuration is as follows: + + // 1. In the same operation, write a logic one to the + // Watchdog change enable bit (WDCE) and WDE. A logic + // one must be written to WDE regardless of the + // previous value of the WDE bit. + + // 2. Within the next four clock cycles, write the WDE + // and Watchdog prescaler bits (WDP) as desired, but + // with the WDCE bit cleared. This must be done in one + // operation. + flag = CLAMP(flag, 7, 0); Info("Setting watchdog prescalar to %02X...", flag); - // Clear timer prescalar flags - WDTCR &= 0xF8; // 11111000 - - WDTCR |= flag; + // Disable interrupts + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + WDTCSR = BIT(WDCE) | BIT(WDE); + // Set new timer prescalar flag + WDTCSR = (WDTCSR & 0xC8) | flag; // C8=11001000 + } } +// XXX: COMMENTS UPDATED! bool WDT_HasTriggered(void) { bool isreset; // To make use of the Reset Flags to identify a reset // condition, the user should read and then reset the - // MCUCSR as early as possible in the program. If the + // MCUSR as early as possible in the program. If the // register is cleared before another reset occurs, // the source of the reset can be found by examining // the Reset Flags. - // MCUCSR: MCU Control and Status Register - // The MCU Control and Status Register provides - // information on which reset source caused an MCU - // Reset. + // MCUSR: MCU Status Register + // The MCU Status Register provides information on + // which reset source caused an MCU reset. - // 7 6 5 4 3 2 1 0 - // JTD ISC2 – JTRF WDRF BORF EXTRF PORF + // 7 6 5 4 3 2 1 0 + // - - – JTRF WDRF BORF EXTRF PORF // Is watchdog reset flag set? - isreset = ((MCUCSR & BIT(WDRF)) != 0); + isreset = ((MCUSR & BIT(WDRF)) != 0); // XXX: Reset flag detection should be a separate // module to handle the different types. - MCUCSR = 0; + MCUSR = 0; return isreset; } void WDT_Disable(void) { - // WDE can only be cleared if the WDTOE bit has - // logic level one. To disable an enabled watchdog - // timer, the following procedure must be followed: + // See WDT_SetTimeoutFlag for an explanation of the + // necessary sequence for clearing WDE and changing + // timeout configuration. - // 1. In the same operation, write a logic one to - // WDTOE and WDE. A logic one must be written to WDE - // even though it is set to one before the disable - // operation starts. - - // 2. Within the next four clock cycles, write a - // logic 0 to WDE. This disables the watchdog. - - // No interrupts while we set WDTCR; + // Disable interrupts ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { - WDTCR = BIT(WDTOE) | BIT(WDE); - WDTCR = 0; + WDTCSR = BIT(WDCE) | BIT(WDE); + WDTCSR = 0; } } diff --git a/src/common/watchdog.h b/src/common/watchdog.h index 9c55baa..0efcb40 100644 --- a/src/common/watchdog.h +++ b/src/common/watchdog.h @@ -8,7 +8,7 @@ #define WDT1000 0x6 // 1000 ms #define WDT500 0x5 // 500 ms #define WDT250 0x4 // 250 ms -#define WDT100 0x3 // 100 ms +#define WDT125 0x3 // 125 ms #define WDT64 0x2 // 64 ms #define WDT32 0x1 // 32 ms #define WDT16 0x0 // 16 ms From c3dc289d5f02437de0c46fff35c05fe3cd786e42 Mon Sep 17 00:00:00 2001 From: Leon Krieg Date: Mon, 30 Sep 2024 21:43:40 +0200 Subject: [PATCH 04/11] Update module 'usart' to run on atmega1284p hardware --- src/bus/usart.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/bus/usart.c b/src/bus/usart.c index 6f579ee..7f15677 100644 --- a/src/bus/usart.c +++ b/src/bus/usart.c @@ -25,11 +25,11 @@ int USART_Init(void) txhead = 0; txtail = 0; - UCSRB = BIT(RXCIE); // Handle RXC interrupts - UCSRB |= BIT(RXEN) | BIT(TXEN); // Enable RX and TX circuitry - UCSRC = BIT(URSEL) | BIT(UCSZ0) | BIT(UCSZ1); // Using 8-bit chars - UBRRH = (USART_BAUD_PRESCALE >> 8); // Set baud rate upper byte - UBRRL = USART_BAUD_PRESCALE; // Set baud rate lower byte + UCSR0B = BIT(RXCIE0); // Handle RXC interrupts + UCSR0B |= BIT(RXEN0) | BIT(TXEN0); // Enable RX and TX circuitry + UCSR0C = BIT(USBS0) | BIT(UCSZ00) | BIT(UCSZ01); // 8-bit data, 2-bit stop + UBRR0H = (USART_BAUD_PRESCALE >> 8); // Set baud rate upper byte + UBRR0L = USART_BAUD_PRESCALE; // Set baud rate lower byte return 0; } @@ -57,16 +57,16 @@ void USART_Putc(char ch) txhead = head; // Enable interrupt - UCSRB |= BIT(UDRIE); + UCSR0B |= BIT(UDRIE0); } // INT: Rx complete -ISR(USART_RXC_vect) +ISR(USART0_RX_vect) { short head; byte data; - data = UDR; // Next byte ready + data = UDR0; // Next byte ready // Wrap around if end of buffer reached head = (rxhead + 1) & USART_RXBUF_MASK; @@ -80,7 +80,7 @@ ISR(USART_RXC_vect) } // INT: Data register empty -ISR(USART_UDRE_vect) +ISR(USART0_UDRE_vect) { short tail; @@ -88,10 +88,10 @@ ISR(USART_UDRE_vect) if (txhead != txtail) { // Write next byte to data register tail = (txtail + 1) & USART_TXBUF_MASK; - UDR = txbuf[tail]; + UDR0 = txbuf[tail]; txtail = tail; } else { // Disable interrupt - UCSRB &= ~BIT(UDRIE); + UCSR0B &= ~BIT(UDRIE0); } } From ac7cd8a96bae12848052a7b8ba80ad1b9b375e6e Mon Sep 17 00:00:00 2001 From: Leon Krieg Date: Mon, 30 Sep 2024 22:04:53 +0200 Subject: [PATCH 05/11] Update module 'pwm' to run on atmega1284p hardware --- src/bus/pwm.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/src/bus/pwm.c b/src/bus/pwm.c index 58050ff..d1bf1ba 100644 --- a/src/bus/pwm.c +++ b/src/bus/pwm.c @@ -1,23 +1,15 @@ #include "common.h" #include "bus/pwm.h" +// TODO: Add documentation for timer3: TCCR3A, TCCR3B, etc. + int PWM_Init(void) { // PD4: PWM NF-12 Fan Peltier Hot Side // PD5: PWM NF-A8 Fan Peltier Cold Side // PD7: PWM NF-R8 Fan Heating Element - // ATMega32A does not have more than two outputs for the - // 16-bit timer and the other 8-bit timers don't have modes - // where the value of TOP can be changed. We can only get - // 25 KHz with software PWM on this chip as far as I know. - - // The 328P would allow us to use OCR2A as top but with - // 8-bit this gives us a really low duty step size of 2.5%. - // Ideal would be two 16-bit timers with two outputs each. - DDRD |= BIT(PD4) | BIT(PD5) | BIT(PD7); - // PORTD &= ~BIT(PD7); // Turn off PD7 // TCCR1A Timer1 Control Register A // 7 6 5 4 3 2 1 0 @@ -90,18 +82,13 @@ int PWM_Init(void) TCCR1B = BIT(WGM12) | BIT(WGM13) | BIT(CS10); ICR1 = PWM_CYCLE_TOP; // 8000 MHz / 25000 KHz + TCCR3A = BIT(WGM31) | BIT(COM3A1) | BIT(COM3B1); + TCCR3B = BIT(WGM32) | BIT(WGM33) | BIT(CS30); + ICR3 = PWM_CYCLE_TOP; // 8000 MHz / 25000 KHz + OCR1B = FAN01_MIN_DUTY; // PD4 OCR1A = FAN02_MIN_DUTY; // PD5 - - // TIMER2: Fast mode, non-inverting, top=0xFF, prescale /8 - // TOP set to 8000000 (f_cpu) / 8 (prescale) / 25000 (f_pwm) - 1 - - TCCR2 = BIT(WGM20) | BIT(WGM21) | BIT(COM21) | BIT(CS21); - OCR2 = 255; // XXX: OCR2A=TOP OCR2B=duty - - // TCCR2 = 0; // Normal operation - // OCR2 = FAN03_MIN_DUTY; // PD7 - // PORTD &= ~BIT(PD7); // Low + OCR2A = FAN03_MIN_DUTY; // PD7 return 0; } @@ -125,6 +112,6 @@ void PWM_SetValue(int port, int value) switch (port) { case PD4: OCR1B = n; break; case PD5: OCR1A = n; break; - case PD7: OCR2 = n; break; + case PD7: OCR2A = n; break; } } From b0f08967c7e8dd1b2e2ed4e2abf7277adb636dc8 Mon Sep 17 00:00:00 2001 From: Leon Krieg Date: Mon, 30 Sep 2024 22:18:36 +0200 Subject: [PATCH 06/11] Change ARCH and MCU settings to match chip signature --- Makefile | 4 ++-- src/bus/pwm.c | 1 - src/main.c | 17 +++-------------- 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 9c3d331..c854174 100644 --- a/Makefile +++ b/Makefile @@ -9,10 +9,10 @@ # ============================================================================== VERBOSE := false -ARCH := m1284p +ARCH := m1284 #FREQ := 18432000UL FREQ := 8000000UL -MCU := atmega1284p +MCU := atmega1284 ASP := usbasp CC := avr-gcc LD := $(CC) diff --git a/src/bus/pwm.c b/src/bus/pwm.c index d1bf1ba..7b60a9d 100644 --- a/src/bus/pwm.c +++ b/src/bus/pwm.c @@ -59,7 +59,6 @@ int PWM_Init(void) // Register, these bits control the counting sequence of // the counter, the source for maximum (TOP) counter // value, and what type of waveform generation to be used. - // See page 115 of the ATMega32A data sheet for all modes. // Mode WGM13 WGM12 WGM11 WGM10 Timer Mode TOP // 14 1 1 1 0 Fast PWM ICR1 diff --git a/src/main.c b/src/main.c index 18ffd34..a9a01d3 100644 --- a/src/main.c +++ b/src/main.c @@ -12,7 +12,6 @@ // TODO: Config header for chip specifics like EEPROM size. // TODO: Check thermistor conversion results /w thermometer. // TODO: Implement primary state machine for update loop. -// TODO: Migrate to ATMega 1284P-PU for 2nd 16-bit timer. // TODO: Use 18.432MHz quarz crystal, burn required fuses. // TODO: Implement optional CRC8 sensor measurement check. // TODO: Proper error handling and recovery (after testing). @@ -108,19 +107,9 @@ static int Init(void) // MOS_Enable(MOS01); // Peltier // MOS_Disable(MOS02); // Heating - // Only FAN01 and FAN02 are receiving the correct - // frequency (25 KHz) right now. The 16-bit timer on - // the ATMega32A has two outputs so it would require - // software PWM to have a variable frequency on PD7. - - // A simple implementation will take up around 30-50 - // percent of CPU time. Faster approaches are quite - // complicated so it might be worth it to switch to - // something like an ATmega328PB. - - PWM_SetValue(FAN01, 50); // Fan Peltier Hot side - PWM_SetValue(FAN02, 50); // Fan Peltier Cold Side - // PWM_SetValue(FAN03, 20); // Fan Heating + PWM_SetValue(FAN01, 50); // Fan Peltier Hot side + PWM_SetValue(FAN02, 50); // Fan Peltier Cold Side + PWM_SetValue(FAN03, 50); // Fan Heating // The I2C_SetChannel command changes the channel // setting of the PCA9546 I2C multiplexer. Any From 23765aae8a815c2b1e20a62f90625662c702df5b Mon Sep 17 00:00:00 2001 From: Leon Krieg Date: Mon, 30 Sep 2024 22:35:37 +0200 Subject: [PATCH 07/11] Increase available memory to 4096 bytes --- src/common/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/memory.c b/src/common/memory.c index 8680081..eb5c82a 100644 --- a/src/common/memory.c +++ b/src/common/memory.c @@ -4,7 +4,7 @@ #include #include -#define MEM_SIZE 1024 +#define MEM_SIZE 4096 #define MEM_START 0x00 #define MEM_BLOCK_SIZE ((int) sizeof(mem_block_t)) #define MEM_MAX_BLOCKS (MEM_SIZE / MEM_BLOCK_SIZE) From bc14a5653ca23b50e127d7ff4e3a731e349a7a8c Mon Sep 17 00:00:00 2001 From: Leon Krieg Date: Tue, 1 Oct 2024 00:16:20 +0200 Subject: [PATCH 08/11] Burn fuse for external crystal at 16K CK and 65ms --- Makefile | 4 ++-- src/bus/usart.c | 2 +- src/main.c | 15 ++++++++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index c854174..a48e271 100644 --- a/Makefile +++ b/Makefile @@ -57,8 +57,8 @@ flash: $(TARGET) $(E) "[AVD] Flashing..." $(Q) $(AVD) -l $(LOGFILE) \ -c $(ASP) -p $(ARCH) \ - -U lfuse:w:0xff:m \ - -U hfuse:w:0x91:m \ + -U lfuse:w:0xFF:m \ + -U hfuse:w:0xD2:m \ -U flash:w:$< .PHONY: clean diff --git a/src/bus/usart.c b/src/bus/usart.c index 7f15677..156bf7d 100644 --- a/src/bus/usart.c +++ b/src/bus/usart.c @@ -27,7 +27,7 @@ int USART_Init(void) UCSR0B = BIT(RXCIE0); // Handle RXC interrupts UCSR0B |= BIT(RXEN0) | BIT(TXEN0); // Enable RX and TX circuitry - UCSR0C = BIT(USBS0) | BIT(UCSZ00) | BIT(UCSZ01); // 8-bit data, 2-bit stop + UCSR0C = BIT(UCSZ01) | BIT(UCSZ00); // 8-bit data, 1-bit stop, no parity UBRR0H = (USART_BAUD_PRESCALE >> 8); // Set baud rate upper byte UBRR0L = USART_BAUD_PRESCALE; // Set baud rate lower byte diff --git a/src/main.c b/src/main.c index a9a01d3..ed56b0b 100644 --- a/src/main.c +++ b/src/main.c @@ -57,6 +57,16 @@ static int Init(void) Info("Initializing..."); + // FIXME: Something is wrong here: + // - AVRDUDE sometimes fails to verify flash. + // - UART sometimes stops working. + // - External crystal problems? + // - Power supply problems? + // - Wrong fuses? Unlikely. + // - Bootloader problems? + + return 0; + // The watchdog timer is clocked from a separate // on-chip oscillator which runs at 1 MHz. Eight // different clock cycle periods can be selected @@ -232,10 +242,13 @@ int main(void) for (;;) { WDT_Reset(); - Update(); + Info("UPDATE"); + continue; + // Update(); WDT_Reset(); Sleep(1000); } + UNUSED(Update); return 0; } From 598540c9d9bedb89d323f60d56c1be7cc62f446c Mon Sep 17 00:00:00 2001 From: Leon Krieg Date: Tue, 1 Oct 2024 05:31:54 +0200 Subject: [PATCH 09/11] Skip bootloader and use internal oscillator without CKDIV8 --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index a48e271..871de73 100644 --- a/Makefile +++ b/Makefile @@ -57,8 +57,10 @@ flash: $(TARGET) $(E) "[AVD] Flashing..." $(Q) $(AVD) -l $(LOGFILE) \ -c $(ASP) -p $(ARCH) \ - -U lfuse:w:0xFF:m \ - -U hfuse:w:0xD2:m \ + -U lfuse:w:0xC2:m \ + -U hfuse:w:0x9F:m \ + -U efuse:w:0xFF:m \ + -U lock:w:0xFF:m \ -U flash:w:$< .PHONY: clean From 93590f7b7575605f9ff5d3b0cd172a32c22a0185 Mon Sep 17 00:00:00 2001 From: Leon Krieg Date: Tue, 1 Oct 2024 15:05:50 +0200 Subject: [PATCH 10/11] Add makefile target for running in simulated environment --- Makefile | 12 +++++++++--- src/main.c | 7 +------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 871de73..247bd1b 100644 --- a/Makefile +++ b/Makefile @@ -12,12 +12,13 @@ VERBOSE := false ARCH := m1284 #FREQ := 18432000UL FREQ := 8000000UL -MCU := atmega1284 +MCU := atmega1284p ASP := usbasp CC := avr-gcc LD := $(CC) OBJCOPY := avr-objcopy AVD := avrdude +SIM := simavr MKDIR := mkdir -p RMR := rm -rf GIT := git @@ -49,8 +50,13 @@ DEPENDS := $(FILES:%.c=$(TMPDIR)/%.d) # AUXILIARY TARGETS (AND FUSE SETTINGS) # ============================================================================== -.PHONY: all -all: flash +# .PHONY: all +# all: flash + +.PHONY: run +run: $(TARGET) + $(E) "[SIM] $<" + $(Q) $(SIM) -m $(MCU) -f $(FREQ) $< .PHONY: flash flash: $(TARGET) diff --git a/src/main.c b/src/main.c index ed56b0b..a12020f 100644 --- a/src/main.c +++ b/src/main.c @@ -65,8 +65,6 @@ static int Init(void) // - Wrong fuses? Unlikely. // - Bootloader problems? - return 0; - // The watchdog timer is clocked from a separate // on-chip oscillator which runs at 1 MHz. Eight // different clock cycle periods can be selected @@ -242,13 +240,10 @@ int main(void) for (;;) { WDT_Reset(); - Info("UPDATE"); - continue; - // Update(); + Update(); WDT_Reset(); Sleep(1000); } - UNUSED(Update); return 0; } From 5a726f5d4859d27d3dd92233c3827f928cb50b67 Mon Sep 17 00:00:00 2001 From: Leon Krieg Date: Tue, 1 Oct 2024 15:47:31 +0200 Subject: [PATCH 11/11] Clear WDRF flag and set WDCE before enabling watchdog --- Makefile | 14 +++++++------- src/common/watchdog.c | 18 ++++++++++++++---- src/main.c | 8 -------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index 247bd1b..488eee3 100644 --- a/Makefile +++ b/Makefile @@ -50,13 +50,8 @@ DEPENDS := $(FILES:%.c=$(TMPDIR)/%.d) # AUXILIARY TARGETS (AND FUSE SETTINGS) # ============================================================================== -# .PHONY: all -# all: flash - -.PHONY: run -run: $(TARGET) - $(E) "[SIM] $<" - $(Q) $(SIM) -m $(MCU) -f $(FREQ) $< +.PHONY: all +all: flash .PHONY: flash flash: $(TARGET) @@ -69,6 +64,11 @@ flash: $(TARGET) -U lock:w:0xFF:m \ -U flash:w:$< +.PHONY: run +run: $(TARGET) + $(E) "[SIM] $<" + $(Q) $(SIM) -m $(MCU) -f $(FREQ) $< + .PHONY: clean clean: $(E) "[REM] $(TARGET)" diff --git a/src/common/watchdog.c b/src/common/watchdog.c index fc610af..e3463d6 100644 --- a/src/common/watchdog.c +++ b/src/common/watchdog.c @@ -36,8 +36,17 @@ void WDT_Enable(void) // set. Once written to one, hardware will clear // WDCE after four clock cycles. - // 00001111: Watchdog enabled, 2sec timeout - WDTCSR = BIT(WDE) | BIT(WDP2) | BIT(WDP1) | BIT(WDP0); + // Setting WDCE before enabling the watchdog should + // not be necessary according to the data sheet but + // it does not seem to work otherwise. + + // Disable interrupts + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + MCUSR &= ~BIT(WDRF); + WDTCSR = BIT(WDCE) | BIT(WDE); + // 00001111: Watchdog enabled, 2sec timeout + WDTCSR = BIT(WDE) | BIT(WDP2) | BIT(WDP1) | BIT(WDP0); + } } void WDT_SetTimeoutFlag(byte flag) @@ -65,13 +74,13 @@ void WDT_SetTimeoutFlag(byte flag) // Disable interrupts ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + WDT_Reset(); WDTCSR = BIT(WDCE) | BIT(WDE); // Set new timer prescalar flag - WDTCSR = (WDTCSR & 0xC8) | flag; // C8=11001000 + WDTCSR = BIT(WDE) | flag; } } -// XXX: COMMENTS UPDATED! bool WDT_HasTriggered(void) { bool isreset; @@ -109,6 +118,7 @@ void WDT_Disable(void) // Disable interrupts ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + WDT_Reset(); WDTCSR = BIT(WDCE) | BIT(WDE); WDTCSR = 0; } diff --git a/src/main.c b/src/main.c index a12020f..a9a01d3 100644 --- a/src/main.c +++ b/src/main.c @@ -57,14 +57,6 @@ static int Init(void) Info("Initializing..."); - // FIXME: Something is wrong here: - // - AVRDUDE sometimes fails to verify flash. - // - UART sometimes stops working. - // - External crystal problems? - // - Power supply problems? - // - Wrong fuses? Unlikely. - // - Bootloader problems? - // The watchdog timer is clocked from a separate // on-chip oscillator which runs at 1 MHz. Eight // different clock cycle periods can be selected