Цитата(zombi @ Jul 25 2018, 15:43)
Это гуглится на раз-два.
Я про нормальную документацию спрашивал.
А Вы все остальные узлы процессора проверили?
Только WDT не устраивает?
Ну тогда можно считать, что нормальной нет...
Проверил External OSC, Soft Reset, GPIO, Timer 0, UART, запись/чтение FLASH.
Особо не гонял, но к данным узлам пока претензий нет.
Что не понравилось:
1. Нет отдельного вектора для загрузчика - нужно немного переделывать бутлоадер.
2. Нет полной бинарной совместимости с ATmega328 - нужно править начальную инициализацию, поэтому туда нельзя залить проекты от которых есть только hex файл.
3. Нет ICSP - нельзя использовать стандартные программаторы/отладчики.
4. После перепрошивки контроллер зависает также как и в случае с WDT - нужно передергивать питание. В оригинальной меге такой проблемы нет - программа стартует сразу после перепрошивки.
Цитата(Сергей Борщ @ Jul 25 2018, 15:56)
Я не знаю, насколько китайская мега отличается от некитайской, но у оригинальной меги невозможно изменить настройки собаки пока стоит бит WDRF в регистре MCUSR. А он там всегда стоит после сброса по собаке. Более того, предделитель собаки при сбросе тоже сбрасывается в значение "2048 циклов". У вас я сброса WDRF при беглом просмотре не заметил и могу предположить, что после первого сброса по собаке вы ее не выключаете (или из-за сброса предделителя не успеваете выключить) и попадаете в бесконечный цикл сбросов по собаке.
Кстати, этот флаг автоматически сбрасывается только по включению питания. Возможно, это объясняет также и то, что ваша программа не реагировала на кнопку сброса. И китайскость процессора тут ни при чем.
Я пробовал его сбрасывать - не помогает. В оригинальной меге такой проблемы нет. Пока нашел только кривой workaround - настраивать WDT на прерывание и уже в прерывании делать Soft Reset через регистр VDTCR.
UPD.
Сброс WDRF в MCUSR помог
Точнее помог "найти" проблему. Судя по datasheet он влияет только на WDE, а он у меня всегда в 1.
Дело было в том, что я неправильно прописал в линкере вектор сброса и пока контроллер пытался пробежать огромное количество nop (0xFFFF) WDT снова срабатывал.
На оригинальной меге такого не проявлялось т.к. частота WDT у нее меньше чем у китайского аналога и контроллер успевал пробежать всю память и перенастроить WDT.
UPD2.
Как оказалось проблема решена не до конца
Сделал небольшую заглушку в код бутлоадера.
В таком варианте сброс происходит корректно.
CODE
#include <ina90.h>
#include <iom328p.h>
#include "md328d.h"
#include <stdint.h>
#include <stdbool.h>
#include "main.h"
#include "system.h"
#include "EC_S.h"
//-------------------------------------------------------------------
#define RX_ESC 0
#define RX_ERR 1
#define RX_RST 2
#define RX_OK 3
#define TX_ESC 4
#define TX_ST 5
#define TX_REQ 6
//-------------------------------------------------------------------
void md8fx8x_init (void) ;
//-------------------------------------------------------------------
void UART1_RX (uint8_t* rx_fsm, uint8_t rxAddr, uint8_t* rx_buf, uint16_t rx_size, uint16_t* recive) ;
bool DeleteStuffing (uint8_t* rx_fsm, uint8_t* rx_buf, uint16_t rx_size, uint8_t data, uint16_t* recive) ;
void UART1_TX (uint8_t* tx_fsm, uint8_t txAddr, uint8_t* tx_buf, uint16_t tx_size, uint16_t* transmit) ;
uint8_t InsertStuffing (uint8_t* tx_fsm, uint8_t* tx_buf, uint16_t* transmit) ;
uint16_t Checksum (uint8_t* data, uint16_t nbyte) ;
//-------------------------------------------------------------------
void main (void)
{
static uint8_t uart_fsm = 0 ;
static uint16_t transmit = 0 ;
static uint8_t rx_data[MEM_WR_MAXSIZE+16] ;
static uint16_t rx_size = 0 ;
static uint8_t tx_data[MEM_RD_MAXSIZE+16] ;
static uint16_t tx_size = 0 ;
static uint8_t* swrst_data = (uint8_t*)SWRST_DATA ;
static uint8_t app_delay = APP_DELAY*5 ;
static uint16_t ms_cnt = 0 ;
__disable_interrupt () ;
__watchdog_reset () ;
if (MCUSR & (1<<WDRF))
{
MCUSR &= ~(1<<WDRF) ;
POWER_UP = SW_RESET ;
if (*(swrst_data+1))
{
*(swrst_data+1) = 0 ;
rx_size = 1 ;
rx_data[rx_size++] = 0xEC ;
rx_data[rx_size++] = *(swrst_data+2) ;
rx_data[rx_size++] = *(swrst_data+3) ;
rx_data[rx_size++] = EC_COMMAND_ | EC_WRITE_ ;
rx_data[rx_size++] = LOBYTE(0x000A) ;
rx_data[rx_size++] = HIBYTE(0x000A) ;
rx_data[rx_size++] = 'F' ;
rx_data[rx_size++] = 'L' ;
rx_data[rx_size++] = 'A' ;
rx_data[rx_size++] = 'S' ;
rx_data[rx_size++] = 'H' ;
rx_data[rx_size++] = 'E' ;
rx_data[rx_size++] = 'N' ;
rx_data[rx_size++] = 'A' ;
rx_size -= 1 ;
uart_fsm = (1<<RX_OK) | (1<<RX_RST) ;
}
}
__watchdog_reset () ;
WDTCSR |= (1<<WDCE) | (1<<WDE) ;
WDTCSR = (0<<WDE) | (0<<WDP3) | (0<<WDP2) | (0<<WDP1) | (0<<WDP0) ;
md8fx8x_init () ;
__watchdog_reset () ;
WDTCSR |= (1<<WDCE) | (1<<WDE) ;
WDTCSR = (1<<WDE) | (0<<WDP3) | (1<<WDP2) | (1<<WDP1) | (0<<WDP0) ;
SMCR = (1<<SE) | (0<<SM2) | (0<<SM1) | (0<<SM0) ;
PORTB = (1<<PORTB7) | (1<<PORTB6) | (0<<PORTB5) | (1<<PORTB4) | (1<<PORTB3) | (1<<PORTB2) | (1<<PORTB1) | (1<<PORTB0) ;
DDRB = (0<<PORTB7) | (0<<PORTB6) | (1<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0) ;
PORTC = (1<<PORTC6) | (1<<PORTC5) | (1<<PORTC4) | (1<<PORTC3) | (1<<PORTC2) | (1<<PORTC1) | (1<<PORTC0) ;
DDRC = (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0) ;
PORTD = (1<<PORTD7) | (1<<PORTD6) | (1<<PORTD5) | (1<<PORTD4) | (1<<PORTD3) | (1<<PORTD2) | (1<<PORTD1) | (1<<PORTD0) ;
DDRD = (0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (1<<PORTD1) | (0<<PORTD0) ;
UBRR0 = Fosc/(8*BAUD)-1 ;
UCSR0C = (0<<UMSEL01) | (0<<UMSEL00) | (0<<UPM01) | (0<<UPM00) | (0<<USBS0) | (1<<UCSZ01) | (1<<UCSZ00) | (0<<UCPOL0) ;
UCSR0A = (1<<U2X0) | (0<<MPCM0) ;
UCSR0B = (0<<RXCIE0) | (0<<TXCIE0) | (0<<UDRIE0) | (1<<RXEN0) | (1<<TXEN0) | (0<<UCSZ02) | (0<<TXB80) ;
TCCR0B = 0 ;
TCNT0 = 0 ;
OCR0A = 250-1 ;
TIFR0 = (1<<OCF0A ) | (1<<OCF0B ) | (1<<TOV0 ) ;
GTCCR = (1<<PSRSYNC) ;
TCCR0A = (1<<WGM01) | (0<<WGM00) ;
TCCR0B = (0<<WGM02) | (0<<CS02) | (1<<CS01) | (1<<CS00) ;
LED_PORT |= (1<<LED_0) ;
__delay_cycles (8000000) ;
LED_PORT &= ~(1<<LED_0) ;
while (1) ;
__enable_interrupt () ;
while (true)
{
__watchdog_reset () ;
if (TIFR0 & (1<<OCF0A))
{
TIFR0 = (1<<OCF0A) ;
ms_cnt++ ;
if (ms_cnt >= 200)
{
ms_cnt = 0 ;
app_delay -= 1 ;
LED_PORT ^= (1<<LED_0) ;
}
}
UART1_RX (&uart_fsm, EC_ADDRESS, rx_data, sizeof(rx_data), &rx_size) ;
if ((uart_fsm & (1<<RX_OK)) && !(uart_fsm & (1<<TX_REQ)))
{
uart_fsm &= ~(1<<RX_OK) ;
app_delay = APP_DELAY*5 ;
if (EC_PACKET (rx_data+1, rx_size, tx_data+1, &tx_size) == 0)
{
uart_fsm |= (1<<TX_REQ) ;
}
}
UART1_TX (&uart_fsm, EC_ADDRESS, tx_data, tx_size, &transmit) ;
if (POWER_UP == RESET_REQ)
{
while (uart_fsm & (1<<TX_REQ))
UART1_TX (&uart_fsm, EC_ADDRESS, tx_data, tx_size, &transmit) ;
__delay_cycles (const10ms) ;
*(swrst_data+0) = POWER_UP ;
*(swrst_data+1) = 0 ;
__disable_interrupt () ;
__watchdog_reset () ;
WDTCSR |= (1<<WDCE) | (1<<WDE) ;
WDTCSR = (1<<WDE) | (0<<WDP3) | (0<<WDP2) | (0<<WDP1) | (0<<WDP0) ;
while (true) ;
}
if (POWER_UP == GOTO_APP || app_delay == 0)
{
while (uart_fsm & (1<<TX_REQ))
UART1_TX (&uart_fsm, EC_ADDRESS, tx_data, tx_size, &transmit) ;
__delay_cycles (const10ms) ;
__disable_interrupt () ;
TCCR0B = 0 ;
TCNT0 = 0 ;
OCR0A = 0 ;
TIFR0 = (1<<OCF0A ) | (1<<OCF0B ) | (1<<TOV0 ) ;
LED_PORT &= ~(1<<LED_0) ;
while (EECR & (1<<EEPE)) ;
IVBASE = (FLASH_BASEADDRESS / 2) >> 8 ;
MCUCR |= (1<<IVCE) ;
MCUCR |= (1<<IVSEL) ;
void (*App)(void) ;
App = (void (*)(void))(FLASH_BASEADDRESS / 2) ;
*(swrst_data+0) = POWER_UP ;
*(swrst_data+1) = 0 ;
App () ;
}
}
}
//-------------------------------------------------------------------
void md8fx8x_init (void)
{
TKCSR = 0x00 ;
// enable 1KB E2PROM
ECCR = 0x80 ;
ECCR = 0x40 ;
// switch to external crystal
PMCR = 0x80 ;
PMCR = 0x37 ;
__delay_cycles (100) ;
CLKPR = 0x80 ;
CLKPR = 0x00 ;
__delay_cycles (100) ;
}
//-------------------------------------------------------------------
void UART1_RX (uint8_t* rx_fsm, uint8_t rxAddr, uint8_t* rx_buf, uint16_t rx_size, uint16_t* recive)
{
if ((*rx_fsm) & (1<<RX_OK))
{
return ;
}
if ((*rx_fsm) & (1<<RX_RST))
{
*rx_fsm &= ~((1<<RX_RST) | (1<<RX_ESC)) ;
*recive = 0 ;
}
if (!(UCSR0A & (1<<RXC0)))
{
return ;
}
uint8_t uart_data = UDR0 ;
if (DeleteStuffing (rx_fsm, rx_buf, rx_size, uart_data, recive))
{
return ;
}
if ((*rx_fsm) & (1<<RX_ERR))
{
*rx_fsm &= ~((1<<RX_ERR) | (1<<RX_ESC)) ;
*recive = 0 ;
return ;
}
if ((*recive) < 3)
{
*recive = 0 ;
return ;
}
if (rx_buf[0] != 0xFF)
{
if (rx_buf[0] != rxAddr)
{
*recive = 0 ;
return ;
}
}
uint16_t checksum = Checksum(rx_buf+0, (*recive)-2) ;
if (checksum != MAKEWORD(rx_buf[(*recive)-2], rx_buf[(*recive)-1]))
{
*recive = 0 ;
return ;
}
*recive -= 3 ;
*rx_fsm |= (1<<RX_OK) | (1<<RX_RST) ;
}
//-------------------------------------------------------------------
bool DeleteStuffing (uint8_t* rx_fsm, uint8_t* rx_buf, uint16_t rx_size, uint8_t data, uint16_t* recive)
{
switch (data)
{
case EC_FEND:
{
*rx_fsm &= ~(1<<RX_ESC) ;
if ((*recive) > 0)
return false ;
break ;
}
case EC_FESC:
{
*rx_fsm |= (1<<RX_ESC) ;
break ;
}
default:
{
if ((*recive) < rx_size)
{
if ((*rx_fsm) & (1<<RX_ESC))
{
if (data == EC_TFEND)
rx_buf[(*recive)++] = EC_FEND ;
else if (data == EC_TFESC)
rx_buf[(*recive)++] = EC_FESC ;
else
rx_buf[(*recive)++] = data ;
}
else
{
rx_buf[(*recive)++] = data ;
}
}
else
{
*rx_fsm |= (1<<RX_ERR) ;
}
*rx_fsm &= ~(1<<RX_ESC) ;
}
}
return true ;
}
//-------------------------------------------------------------------
void UART1_TX (uint8_t* tx_fsm, uint8_t txAddr, uint8_t* tx_buf, uint16_t tx_size, uint16_t* transmit)
{
if (!((*tx_fsm) & (1<<TX_REQ)))
{
return ;
}
if (!(UCSR0A & (1<<UDRE0)))
{
return ;
}
if (!((*tx_fsm) & (1<<TX_ST)))
{
*tx_fsm |= (1<<TX_ST) ;
*tx_fsm &= ~(1<<TX_ESC) ;
*transmit = 0 ;
tx_buf[0] = txAddr ;
uint16_t checksum = Checksum (tx_buf+0, tx_size+1) ;
tx_buf[tx_size+1] = LOBYTE(checksum) ;
tx_buf[tx_size+2] = HIBYTE(checksum) ;
UDR0 = EC_FEND ;
if (!(UCSR0A & (1<<UDRE0)))
{
return ;
}
}
while ((*transmit) < (tx_size + 3))
{
uint8_t uart_data = InsertStuffing (tx_fsm, tx_buf, transmit) ;
UDR0 = uart_data ;
if (!(UCSR0A & (1<<UDRE0)))
{
return ;
}
}
UDR0 = EC_FEND ;
*tx_fsm &= ~((1<<TX_REQ) | (1<<TX_ST) | (1<<TX_ESC)) ;
}
//-------------------------------------------------------------------
uint8_t InsertStuffing (uint8_t* tx_fsm, uint8_t* tx_buf, uint16_t* transmit)
{
switch (tx_buf[(*transmit)])
{
case EC_FEND:
{
if (!((*tx_fsm) & (1<<TX_ESC)))
{
*tx_fsm |= (1<<TX_ESC) ;
return EC_FESC ;
}
*tx_fsm &= ~(1<<TX_ESC) ;
(*transmit)++ ;
return EC_TFEND ;
}
case EC_FESC:
{
if (!((*tx_fsm) & (1<<TX_ESC)))
{
*tx_fsm |= (1<<TX_ESC) ;
return EC_FESC ;
}
*tx_fsm &= ~(1<<TX_ESC) ;
(*transmit)++ ;
return EC_TFESC ;
}
default:
{
}
}
return tx_buf[(*transmit)++] ;
}
//-------------------------------------------------------------------
uint16_t Checksum (uint8_t* data, uint16_t nbyte)
{
uint16_t i ;
uint32_t sum ;
sum = 0 ;
for (i=0 ; i<nbyte ; i++)
{
if (i & 1)
sum += ((uint32_t)data[i]) << 8 ;
else
sum += ((uint32_t)data[i]) ;
}
while ((sum >> 16) & 0x0000FFFF)
sum = (sum & 0x0000FFFF) + ((sum >> 16) & 0x0000FFFF) ;
sum = ~sum ;
sum &= 0x0000FFFF ;
return ((uint16_t)sum) ;
}
//-------------------------------------------------------------------
В таком некорректно.
CODE
#include <ina90.h>
#include <iom328p.h>
#include "md328d.h"
#include <stdint.h>
#include <stdbool.h>
#include "main.h"
#include "system.h"
#include "EC_S.h"
//-------------------------------------------------------------------
#define RX_ESC 0
#define RX_ERR 1
#define RX_RST 2
#define RX_OK 3
#define TX_ESC 4
#define TX_ST 5
#define TX_REQ 6
//-------------------------------------------------------------------
void md8fx8x_init (void) ;
//-------------------------------------------------------------------
void UART1_RX (uint8_t* rx_fsm, uint8_t rxAddr, uint8_t* rx_buf, uint16_t rx_size, uint16_t* recive) ;
bool DeleteStuffing (uint8_t* rx_fsm, uint8_t* rx_buf, uint16_t rx_size, uint8_t data, uint16_t* recive) ;
void UART1_TX (uint8_t* tx_fsm, uint8_t txAddr, uint8_t* tx_buf, uint16_t tx_size, uint16_t* transmit) ;
uint8_t InsertStuffing (uint8_t* tx_fsm, uint8_t* tx_buf, uint16_t* transmit) ;
uint16_t Checksum (uint8_t* data, uint16_t nbyte) ;
//-------------------------------------------------------------------
void main (void)
{
static uint8_t uart_fsm = 0 ;
static uint16_t transmit = 0 ;
static uint8_t rx_data[MEM_WR_MAXSIZE+16] ;
static uint16_t rx_size = 0 ;
static uint8_t tx_data[MEM_RD_MAXSIZE+16] ;
static uint16_t tx_size = 0 ;
static uint8_t* swrst_data = (uint8_t*)SWRST_DATA ;
static uint8_t app_delay = APP_DELAY*5 ;
static uint16_t ms_cnt = 0 ;
__disable_interrupt () ;
__watchdog_reset () ;
if (MCUSR & (1<<WDRF))
{
MCUSR &= ~(1<<WDRF) ;
POWER_UP = SW_RESET ;
if (*(swrst_data+1))
{
*(swrst_data+1) = 0 ;
rx_size = 1 ;
rx_data[rx_size++] = 0xEC ;
rx_data[rx_size++] = *(swrst_data+2) ;
rx_data[rx_size++] = *(swrst_data+3) ;
rx_data[rx_size++] = EC_COMMAND_ | EC_WRITE_ ;
rx_data[rx_size++] = LOBYTE(0x000A) ;
rx_data[rx_size++] = HIBYTE(0x000A) ;
rx_data[rx_size++] = 'F' ;
rx_data[rx_size++] = 'L' ;
rx_data[rx_size++] = 'A' ;
rx_data[rx_size++] = 'S' ;
rx_data[rx_size++] = 'H' ;
rx_data[rx_size++] = 'E' ;
rx_data[rx_size++] = 'N' ;
rx_data[rx_size++] = 'A' ;
rx_size -= 1 ;
uart_fsm = (1<<RX_OK) | (1<<RX_RST) ;
}
}
__watchdog_reset () ;
WDTCSR |= (1<<WDCE) | (1<<WDE) ;
WDTCSR = (0<<WDE) | (0<<WDP3) | (0<<WDP2) | (0<<WDP1) | (0<<WDP0) ;
md8fx8x_init () ;
__watchdog_reset () ;
WDTCSR |= (1<<WDCE) | (1<<WDE) ;
WDTCSR = (1<<WDE) | (0<<WDP3) | (1<<WDP2) | (1<<WDP1) | (0<<WDP0) ;
SMCR = (1<<SE) | (0<<SM2) | (0<<SM1) | (0<<SM0) ;
PORTB = (1<<PORTB7) | (1<<PORTB6) | (0<<PORTB5) | (1<<PORTB4) | (1<<PORTB3) | (1<<PORTB2) | (1<<PORTB1) | (1<<PORTB0) ;
DDRB = (0<<PORTB7) | (0<<PORTB6) | (1<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0) ;
PORTC = (1<<PORTC6) | (1<<PORTC5) | (1<<PORTC4) | (1<<PORTC3) | (1<<PORTC2) | (1<<PORTC1) | (1<<PORTC0) ;
DDRC = (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0) ;
PORTD = (1<<PORTD7) | (1<<PORTD6) | (1<<PORTD5) | (1<<PORTD4) | (1<<PORTD3) | (1<<PORTD2) | (1<<PORTD1) | (1<<PORTD0) ;
DDRD = (0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (1<<PORTD1) | (0<<PORTD0) ;
UBRR0 = Fosc/(8*BAUD)-1 ;
UCSR0C = (0<<UMSEL01) | (0<<UMSEL00) | (0<<UPM01) | (0<<UPM00) | (0<<USBS0) | (1<<UCSZ01) | (1<<UCSZ00) | (0<<UCPOL0) ;
UCSR0A = (1<<U2X0) | (0<<MPCM0) ;
UCSR0B = (0<<RXCIE0) | (0<<TXCIE0) | (0<<UDRIE0) | (1<<RXEN0) | (1<<TXEN0) | (0<<UCSZ02) | (0<<TXB80) ;
TCCR0B = 0 ;
TCNT0 = 0 ;
OCR0A = 250-1 ;
TIFR0 = (1<<OCF0A ) | (1<<OCF0B ) | (1<<TOV0 ) ;
GTCCR = (1<<PSRSYNC) ;
TCCR0A = (1<<WGM01) | (0<<WGM00) ;
TCCR0B = (0<<WGM02) | (0<<CS02) | (1<<CS01) | (1<<CS00) ;
LED_PORT |= (1<<LED_0) ;
__delay_cycles (8000000) ;
LED_PORT &= ~(1<<LED_0) ;
while (!(LED_PORT & (1<<LED_0))) ;
__enable_interrupt () ;
while (true)
{
__watchdog_reset () ;
if (TIFR0 & (1<<OCF0A))
{
TIFR0 = (1<<OCF0A) ;
ms_cnt++ ;
if (ms_cnt >= 200)
{
ms_cnt = 0 ;
app_delay -= 1 ;
LED_PORT ^= (1<<LED_0) ;
}
}
UART1_RX (&uart_fsm, EC_ADDRESS, rx_data, sizeof(rx_data), &rx_size) ;
if ((uart_fsm & (1<<RX_OK)) && !(uart_fsm & (1<<TX_REQ)))
{
uart_fsm &= ~(1<<RX_OK) ;
app_delay = APP_DELAY*5 ;
if (EC_PACKET (rx_data+1, rx_size, tx_data+1, &tx_size) == 0)
{
uart_fsm |= (1<<TX_REQ) ;
}
}
UART1_TX (&uart_fsm, EC_ADDRESS, tx_data, tx_size, &transmit) ;
if (POWER_UP == RESET_REQ)
{
while (uart_fsm & (1<<TX_REQ))
UART1_TX (&uart_fsm, EC_ADDRESS, tx_data, tx_size, &transmit) ;
__delay_cycles (const10ms) ;
*(swrst_data+0) = POWER_UP ;
*(swrst_data+1) = 0 ;
__disable_interrupt () ;
__watchdog_reset () ;
WDTCSR |= (1<<WDCE) | (1<<WDE) ;
WDTCSR = (1<<WDE) | (0<<WDP3) | (0<<WDP2) | (0<<WDP1) | (0<<WDP0) ;
while (true) ;
}
if (POWER_UP == GOTO_APP || app_delay == 0)
{
while (uart_fsm & (1<<TX_REQ))
UART1_TX (&uart_fsm, EC_ADDRESS, tx_data, tx_size, &transmit) ;
__delay_cycles (const10ms) ;
__disable_interrupt () ;
TCCR0B = 0 ;
TCNT0 = 0 ;
OCR0A = 0 ;
TIFR0 = (1<<OCF0A ) | (1<<OCF0B ) | (1<<TOV0 ) ;
LED_PORT &= ~(1<<LED_0) ;
while (EECR & (1<<EEPE)) ;
IVBASE = (FLASH_BASEADDRESS / 2) >> 8 ;
MCUCR |= (1<<IVCE) ;
MCUCR |= (1<<IVSEL) ;
void (*App)(void) ;
App = (void (*)(void))(FLASH_BASEADDRESS / 2) ;
*(swrst_data+0) = POWER_UP ;
*(swrst_data+1) = 0 ;
App () ;
}
}
}
//-------------------------------------------------------------------
void md8fx8x_init (void)
{
TKCSR = 0x00 ;
// enable 1KB E2PROM
ECCR = 0x80 ;
ECCR = 0x40 ;
// switch to external crystal
PMCR = 0x80 ;
PMCR = 0x37 ;
__delay_cycles (100) ;
CLKPR = 0x80 ;
CLKPR = 0x00 ;
__delay_cycles (100) ;
}
//-------------------------------------------------------------------
void UART1_RX (uint8_t* rx_fsm, uint8_t rxAddr, uint8_t* rx_buf, uint16_t rx_size, uint16_t* recive)
{
if ((*rx_fsm) & (1<<RX_OK))
{
return ;
}
if ((*rx_fsm) & (1<<RX_RST))
{
*rx_fsm &= ~((1<<RX_RST) | (1<<RX_ESC)) ;
*recive = 0 ;
}
if (!(UCSR0A & (1<<RXC0)))
{
return ;
}
uint8_t uart_data = UDR0 ;
if (DeleteStuffing (rx_fsm, rx_buf, rx_size, uart_data, recive))
{
return ;
}
if ((*rx_fsm) & (1<<RX_ERR))
{
*rx_fsm &= ~((1<<RX_ERR) | (1<<RX_ESC)) ;
*recive = 0 ;
return ;
}
if ((*recive) < 3)
{
*recive = 0 ;
return ;
}
if (rx_buf[0] != 0xFF)
{
if (rx_buf[0] != rxAddr)
{
*recive = 0 ;
return ;
}
}
uint16_t checksum = Checksum(rx_buf+0, (*recive)-2) ;
if (checksum != MAKEWORD(rx_buf[(*recive)-2], rx_buf[(*recive)-1]))
{
*recive = 0 ;
return ;
}
*recive -= 3 ;
*rx_fsm |= (1<<RX_OK) | (1<<RX_RST) ;
}
//-------------------------------------------------------------------
bool DeleteStuffing (uint8_t* rx_fsm, uint8_t* rx_buf, uint16_t rx_size, uint8_t data, uint16_t* recive)
{
switch (data)
{
case EC_FEND:
{
*rx_fsm &= ~(1<<RX_ESC) ;
if ((*recive) > 0)
return false ;
break ;
}
case EC_FESC:
{
*rx_fsm |= (1<<RX_ESC) ;
break ;
}
default:
{
if ((*recive) < rx_size)
{
if ((*rx_fsm) & (1<<RX_ESC))
{
if (data == EC_TFEND)
rx_buf[(*recive)++] = EC_FEND ;
else if (data == EC_TFESC)
rx_buf[(*recive)++] = EC_FESC ;
else
rx_buf[(*recive)++] = data ;
}
else
{
rx_buf[(*recive)++] = data ;
}
}
else
{
*rx_fsm |= (1<<RX_ERR) ;
}
*rx_fsm &= ~(1<<RX_ESC) ;
}
}
return true ;
}
//-------------------------------------------------------------------
void UART1_TX (uint8_t* tx_fsm, uint8_t txAddr, uint8_t* tx_buf, uint16_t tx_size, uint16_t* transmit)
{
if (!((*tx_fsm) & (1<<TX_REQ)))
{
return ;
}
if (!(UCSR0A & (1<<UDRE0)))
{
return ;
}
if (!((*tx_fsm) & (1<<TX_ST)))
{
*tx_fsm |= (1<<TX_ST) ;
*tx_fsm &= ~(1<<TX_ESC) ;
*transmit = 0 ;
tx_buf[0] = txAddr ;
uint16_t checksum = Checksum (tx_buf+0, tx_size+1) ;
tx_buf[tx_size+1] = LOBYTE(checksum) ;
tx_buf[tx_size+2] = HIBYTE(checksum) ;
UDR0 = EC_FEND ;
if (!(UCSR0A & (1<<UDRE0)))
{
return ;
}
}
while ((*transmit) < (tx_size + 3))
{
uint8_t uart_data = InsertStuffing (tx_fsm, tx_buf, transmit) ;
UDR0 = uart_data ;
if (!(UCSR0A & (1<<UDRE0)))
{
return ;
}
}
UDR0 = EC_FEND ;
*tx_fsm &= ~((1<<TX_REQ) | (1<<TX_ST) | (1<<TX_ESC)) ;
}
//-------------------------------------------------------------------
uint8_t InsertStuffing (uint8_t* tx_fsm, uint8_t* tx_buf, uint16_t* transmit)
{
switch (tx_buf[(*transmit)])
{
case EC_FEND:
{
if (!((*tx_fsm) & (1<<TX_ESC)))
{
*tx_fsm |= (1<<TX_ESC) ;
return EC_FESC ;
}
*tx_fsm &= ~(1<<TX_ESC) ;
(*transmit)++ ;
return EC_TFEND ;
}
case EC_FESC:
{
if (!((*tx_fsm) & (1<<TX_ESC)))
{
*tx_fsm |= (1<<TX_ESC) ;
return EC_FESC ;
}
*tx_fsm &= ~(1<<TX_ESC) ;
(*transmit)++ ;
return EC_TFESC ;
}
default:
{
}
}
return tx_buf[(*transmit)++] ;
}
//-------------------------------------------------------------------
uint16_t Checksum (uint8_t* data, uint16_t nbyte)
{
uint16_t i ;
uint32_t sum ;
sum = 0 ;
for (i=0 ; i<nbyte ; i++)
{
if (i & 1)
sum += ((uint32_t)data[i]) << 8 ;
else
sum += ((uint32_t)data[i]) ;
}
while ((sum >> 16) & 0x0000FFFF)
sum = (sum & 0x0000FFFF) + ((sum >> 16) & 0x0000FFFF) ;
sum = ~sum ;
sum &= 0x0000FFFF ;
return ((uint16_t)sum) ;
}
//-------------------------------------------------------------------
Разница только в том, что первом случае компилятор оптимизирует часть кода, но по логике работы заглушки программа до оптимизируемой части никогда не должна доходить.
UPD3.
Кажется разобрался.
При оптимизации кода выбрасывался кусок начальной инициализации переменных. Без оптимизации WDT успевал сработать пока происходила инициализация переменных перед стартом main(). Пока решил проблему добавив свой кастомный startup код где первыми строками идет сброс и отключение WDT.