реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> MD-328D (LGT8F328D) зависает при сбросе от WDT
BSACPLD
сообщение Jul 24 2018, 01:02
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 371
Регистрация: 24-07-05
Из: Москва
Пользователь №: 7 056



Коллеги, помогите, пожалуйста, с очередной проблемой с 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 ( 39.94 килобайт ) Кол-во скачиваний: 9
Прикрепленный файл  MD_328D_AVRMINIBLD.rar ( 58.37 килобайт ) Кол-во скачиваний: 8
Прикрепленный файл  ATmega328_AVRMINIBLD.rar ( 56.9 килобайт ) Кол-во скачиваний: 8
Прикрепленный файл  MD_328D_AVRMINIAPP.rar ( 77.15 килобайт ) Кол-во скачиваний: 8
Прикрепленный файл  ATmega328_AVRMINIAPP.rar ( 73.75 килобайт ) Кол-во скачиваний: 8
 
Go to the top of the page
 
+Quote Post
BSACPLD
сообщение Jul 25 2018, 06:40
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 371
Регистрация: 24-07-05
Из: Москва
Пользователь №: 7 056



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

CODE

#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 () ;
}
Go to the top of the page
 
+Quote Post
zombi
сообщение Jul 25 2018, 08:17
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 076
Регистрация: 10-09-08
Пользователь №: 40 106



Цитата(BSACPLD @ Jul 25 2018, 09:40) *
На всех пинах слабая подтяжка к питанию и не реагирует на сигнал сброса.

Прикольно ! biggrin.gif
Просто интересно, чем обусловлено столь пристальное внимание к этому MD-328D ?
Чем он лучше меги?
Go to the top of the page
 
+Quote Post
BSACPLD
сообщение Jul 25 2018, 08:30
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 371
Регистрация: 24-07-05
Из: Москва
Пользователь №: 7 056



Цитата(zombi @ Jul 25 2018, 11:17) *
Прикольно ! biggrin.gif
Просто интересно, чем обусловлено столь пристальное внимание к этому MD-328D ?
Чем он лучше меги?

Тем что он китайский.
Импортозамещение чтоб его angry.gif
Про AVR от НИИЭТ я знаю, но у него цена совсем не адекватная, поэтому рассматриваю китайские аналоги.
Go to the top of the page
 
+Quote Post
zombi
сообщение Jul 25 2018, 08:58
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 076
Регистрация: 10-09-08
Пользователь №: 40 106



Цитата(BSACPLD @ Jul 25 2018, 11:30) *
Импортозамещение чтоб его angry.gif

Импорт 1 меняем на импорт 2 - странное какое-то ымпортозамещение! biggrin.gif
Думаю что если, в результате выполнения штатных действий процессор ведёт себя не адекватно, то дорога такому чипу в ...
А есть ли нормальная документация на этот проц?
Go to the top of the page
 
+Quote Post
BSACPLD
сообщение Jul 25 2018, 09:15
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 371
Регистрация: 24-07-05
Из: Москва
Пользователь №: 7 056



Цитата(zombi @ Jul 25 2018, 11:58) *
Импорт 1 меняем на импорт 2 - странное какое-то ымпортозамещение! biggrin.gif
Думаю что если, в результате выполнения штатных действий процессор ведёт себя не адекватно, то дорога такому чипу в ...
А есть ли нормальная документация на этот проц?

Есть машинный перевод с китайского на английский.
https://www.google.ru/url?sa=t&source=w...IM6cjlIx8ZPt14_
Go to the top of the page
 
+Quote Post
zombi
сообщение Jul 25 2018, 12:43
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 076
Регистрация: 10-09-08
Пользователь №: 40 106



Цитата(BSACPLD @ Jul 25 2018, 12:15) *
Есть машинный перевод с китайского на английский.

Это гуглится на раз-два.
Я про нормальную документацию спрашивал.
А Вы все остальные узлы процессора проверили?
Только WDT не устраивает?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 25 2018, 12:56
Сообщение #8


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (BSACPLD @ Jul 25 2018, 09:40) *
Видимо это какой-то аппаратный баг... sad.gif
Я не знаю, насколько китайская мега отличается от некитайской, но у оригинальной меги невозможно изменить настройки собаки пока стоит бит WDRF в регистре MCUSR. А он там всегда стоит после сброса по собаке. Более того, предделитель собаки при сбросе тоже сбрасывается в значение "2048 циклов". У вас я сброса WDRF при беглом просмотре не заметил и могу предположить, что после первого сброса по собаке вы ее не выключаете (или из-за сброса предделителя не успеваете выключить) и попадаете в бесконечный цикл сбросов по собаке.

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


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
BSACPLD
сообщение Jul 25 2018, 14:22
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 371
Регистрация: 24-07-05
Из: Москва
Пользователь №: 7 056



Цитата(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 помог sm.gif Точнее помог "найти" проблему. Судя по datasheet он влияет только на WDE, а он у меня всегда в 1.
Дело было в том, что я неправильно прописал в линкере вектор сброса и пока контроллер пытался пробежать огромное количество nop (0xFFFF) WDT снова срабатывал.
На оригинальной меге такого не проявлялось т.к. частота WDT у нее меньше чем у китайского аналога и контроллер успевал пробежать всю память и перенастроить WDT.

UPD2.
Как оказалось проблема решена не до конца sad.gif
Сделал небольшую заглушку в код бутлоадера.
В таком варианте сброс происходит корректно.
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.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 16th April 2024 - 18:51
Рейтинг@Mail.ru


Страница сгенерированна за 0.01499 секунд с 7
ELECTRONIX ©2004-2016