Перейти к содержанию
    

MD-328D (LGT8F328D) зависает при сбросе от WDT

Коллеги, помогите, пожалуйста, с очередной проблемой с MD-328D (LGT8F328D).

Пробую писать код на чистом C без использования Arduino IDE.

Инициализацию МК сделал аналогично загрузчику из Arduino IDE, но при этом не могу понять почему при срабатывании WDT контроллер намертво зависает так что даже не помогает кнопка сброса. Только ресет по питанию. Причем одна и та же программа ведет себя по разному в зависимости от того запускаю я её совместно со своим загрузчиком или загрузчиком из Arduino IDE.

MD-328D (LGT8F328D):

Загрузчик из Arduino IDE + моя программа = корретная работа.

Мой загрузчик + моя программа = зависание при срабатывании WDT.

Моя программа без загрузчика = зависание при срабатывании WDT.

ATmega328P:

Загрузчик из Arduino IDE + моя программа = корретная работа.

Мой загрузчик + моя программа = корретная работа.

Моя программа без загрузчика = корретная работа.

И еще один интересный момент. Если перезагрузку через сброс по WDT заменить на программный сброс (бит SWR в регистре VDTCR), то контроллер перестает зависать.

Также контроллер всегда зависает после перепрошивки по SWD и залитая программа стартует лишь после передергивания питания.

Может кто сталкивался с таким странным поведением данного контроллера?

 

Приложенные файлы:

md328d.rar - загрузчик из Arduino IDE.

MD-328D_AVRMINIBLD.rar - загрузчик под MD-328D.

MD-328D_AVRMINIAPP.rar - программа под MD-328D.

ATmega328_AVRMINIBLD.rar - загрузчик под ATmega328P.

ATmega328_AVRMINIAPP.rar - программа под ATmega328P.

md328d.rar

MD_328D_AVRMINIBLD.rar

ATmega328_AVRMINIBLD.rar

MD_328D_AVRMINIAPP.rar

ATmega328_AVRMINIAPP.rar

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нашел странную закономерность.

Если приведенный ниже код разместить начиная с адреса 0x0000, то он вроде как работает, но если с помощью настроек линкера поменять его размещение, допустим на 0x3000, то код также запускается, но при срабатывании WDT контроллер виснет намертво. На всех пинах слабая подтяжка к питанию и не реагирует на сигнал сброса.

Похоже на некорректную отработку сброса если в момент срабатывания WDT программа находится старше какого-то адреса.

Видимо это какой-то аппаратный баг... :(

 

#include <ina90.h>
#include <iom328p.h>

#include "md328d.h"

#include <stdint.h>
#include <stdbool.h>

#include "main.h"

//-------------------------------------------------------------------
void md8fx8x_init (void) ;

//-------------------------------------------------------------------
void main (void)
{
md8fx8x_init () ;

MCUCR = (1<<PUD) ;

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) ;

LED_PORT |=  (1<<LED_0) ;
__delay_cycles (8000000) ;
LED_PORT &= ~(1<<LED_0) ;
while (1) ;
}
//-------------------------------------------------------------------
void md8fx8x_init (void)
{
__disable_interrupt () ;

__watchdog_reset () ;
WDTCSR |= (1<<WDCE) | (1<<WDE) ;
WDTCSR  = (0<<WDIE) | (0<<WDE) | (0<<WDP3) | (0<<WDP2) | (0<<WDP1) | (0<<WDP0) ;
asm ("nop") ;
asm ("nop") ;
asm ("nop") ;             
asm ("nop") ;
asm ("nop") ;
asm ("nop") ;
asm ("nop") ;
asm ("nop") ;

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) ;

__watchdog_reset () ;
WDTCSR |= (1<<WDCE) | (1<<WDE) ;
WDTCSR  = (0<<WDIE) | (1<<WDE) | (0<<WDP3) | (1<<WDP2) | (1<<WDP1) | (0<<WDP0) ;
asm ("nop") ;
asm ("nop") ;
asm ("nop") ;
asm ("nop") ;
asm ("nop") ;
asm ("nop") ;
asm ("nop") ;
asm ("nop") ;

__enable_interrupt () ;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На всех пинах слабая подтяжка к питанию и не реагирует на сигнал сброса.

Прикольно ! :biggrin:

Просто интересно, чем обусловлено столь пристальное внимание к этому MD-328D ?

Чем он лучше меги?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Прикольно ! :biggrin:

Просто интересно, чем обусловлено столь пристальное внимание к этому MD-328D ?

Чем он лучше меги?

Тем что он китайский.

Импортозамещение чтоб его :angry2:

Про AVR от НИИЭТ я знаю, но у него цена совсем не адекватная, поэтому рассматриваю китайские аналоги.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Импортозамещение чтоб его :angry2:

Импорт 1 меняем на импорт 2 - странное какое-то ымпортозамещение! :biggrin:

Думаю что если, в результате выполнения штатных действий процессор ведёт себя не адекватно, то дорога такому чипу в ...

А есть ли нормальная документация на этот проц?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Импорт 1 меняем на импорт 2 - странное какое-то ымпортозамещение! :biggrin:

Думаю что если, в результате выполнения штатных действий процессор ведёт себя не адекватно, то дорога такому чипу в ...

А есть ли нормальная документация на этот проц?

Есть машинный перевод с китайского на английский.

https://www.google.ru/url?sa=t&source=w...IM6cjlIx8ZPt14_

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть машинный перевод с китайского на английский.

Это гуглится на раз-два.

Я про нормальную документацию спрашивал.

А Вы все остальные узлы процессора проверили?

Только WDT не устраивает?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Видимо это какой-то аппаратный баг... :(
Я не знаю, насколько китайская мега отличается от некитайской, но у оригинальной меги невозможно изменить настройки собаки пока стоит бит WDRF в регистре MCUSR. А он там всегда стоит после сброса по собаке. Более того, предделитель собаки при сбросе тоже сбрасывается в значение "2048 циклов". У вас я сброса WDRF при беглом просмотре не заметил и могу предположить, что после первого сброса по собаке вы ее не выключаете (или из-за сброса предделителя не успеваете выключить) и попадаете в бесконечный цикл сбросов по собаке.

 

Кстати, этот флаг автоматически сбрасывается только по включению питания. Возможно, это объясняет также и то, что ваша программа не реагировала на кнопку сброса. И китайскость процессора тут ни при чем.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это гуглится на раз-два.

Я про нормальную документацию спрашивал.

А Вы все остальные узлы процессора проверили?

Только WDT не устраивает?

Ну тогда можно считать, что нормальной нет...

Проверил External OSC, Soft Reset, GPIO, Timer 0, UART, запись/чтение FLASH.

Особо не гонял, но к данным узлам пока претензий нет.

Что не понравилось:

1. Нет отдельного вектора для загрузчика - нужно немного переделывать бутлоадер.

2. Нет полной бинарной совместимости с ATmega328 - нужно править начальную инициализацию, поэтому туда нельзя залить проекты от которых есть только hex файл.

3. Нет ICSP - нельзя использовать стандартные программаторы/отладчики.

4. После перепрошивки контроллер зависает также как и в случае с WDT - нужно передергивать питание. В оригинальной меге такой проблемы нет - программа стартует сразу после перепрошивки.

 

Я не знаю, насколько китайская мега отличается от некитайской, но у оригинальной меги невозможно изменить настройки собаки пока стоит бит WDRF в регистре MCUSR. А он там всегда стоит после сброса по собаке. Более того, предделитель собаки при сбросе тоже сбрасывается в значение "2048 циклов". У вас я сброса WDRF при беглом просмотре не заметил и могу предположить, что после первого сброса по собаке вы ее не выключаете (или из-за сброса предделителя не успеваете выключить) и попадаете в бесконечный цикл сбросов по собаке.

 

Кстати, этот флаг автоматически сбрасывается только по включению питания. Возможно, это объясняет также и то, что ваша программа не реагировала на кнопку сброса. И китайскость процессора тут ни при чем.

Я пробовал его сбрасывать - не помогает. В оригинальной меге такой проблемы нет. Пока нашел только кривой workaround - настраивать WDT на прерывание и уже в прерывании делать Soft Reset через регистр VDTCR.

 

UPD.

Сброс WDRF в MCUSR помог :) Точнее помог "найти" проблему. Судя по datasheet он влияет только на WDE, а он у меня всегда в 1.

Дело было в том, что я неправильно прописал в линкере вектор сброса и пока контроллер пытался пробежать огромное количество nop (0xFFFF) WDT снова срабатывал.

На оригинальной меге такого не проявлялось т.к. частота WDT у нее меньше чем у китайского аналога и контроллер успевал пробежать всю память и перенастроить WDT.

 

UPD2.

Как оказалось проблема решена не до конца :(

Сделал небольшую заглушку в код бутлоадера.

В таком варианте сброс происходит корректно.

#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) ;
}
//-------------------------------------------------------------------

В таком некорректно.

#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.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...