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

BSACPLD

Свой
  • Публикаций

    379
  • Зарегистрирован

  • Посещение

Репутация

0 Обычный

Информация о BSACPLD

  • Звание
    Местный
  • День рождения 16.06.1986

Контакты

  • Сайт
    http://www.mcu-cpld.narod.ru
  • ICQ
    0

Информация

  • Город
    Москва

Посетители профиля

3 224 просмотра профиля
  1. Заработало :) Я сам себе злобный буратино :) Копировал preloader не в тот раздел sd карты. Остался только вопрос почему linux пишет сразу во все gpio хотя я прописал linux,default-trigger = "heartbeat"; только для GPIO53.
  2. Пробовал через loanio. Такой вариант вообще не работает. Пробовал на GPIO54, 55, 56. Т.е. сам linux стартует, но переключать пины настроенные как loanio не получается (на oe подавал 1, out выводил на кнопки). Причем если GPIO54 настроить как gpio, то он начинает работать. 55 и 56 не удалось заставить работать ни как gpio, ни как loanio. Подозреваю, что дело в некорректной настройке pinmux в preloader. Пробовал собирать preloader как в 15.1, так и в 18.0. Результат один и тот же. u-boot также пересобирал. Где-то читал, что вроде начиная с 13.1 loanio и gpio окончательно поломали. Так ли это? Во всяком случае очень похоже, т.к. при чтении регистров GENERALIO7 (GPIO55, 0xFFD0849C) и GENERALIO8 (GPIO56, 0xFFD084A0) для варианта gpio возвращается 1, хотя согласно документации там должен быть 0. При этом для GENERALIO6 (GPIO54, 0xFFD08498), который работает, как и положено, возвращается 0.
  3. Написал программу для тестирования GPIO. dts переделал так чтобы система моргала только GPIO53 (linux,default-trigger = "heartbeat"). Остальными GPIO управляет моя программа. #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <fcntl.h> #include <sys/types.h> #include <sys/mman.h> #include <unistd.h> #include <errno.h> int main() { int fd = 0; void *fpga_leds = 0; void *hps_leds = 0; try { fd = open( "/dev/mem", O_RDWR | O_SYNC ); if(fd < 0) throw "mem open error"; printf("fpga_leds\n"); fpga_leds = (mmap(0, (16/4), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xFF203000)); if(fpga_leds == MAP_FAILED) throw "fpga_leds mmap error"; for(int i=0 ; i<(16/4) ; i++) { uint32_t a = *(((uint32_t*)fpga_leds) + i); printf("0x%08X\n", a); } *(((uint32_t*)fpga_leds) + 0) = 0x0000000F; usleep(1000000); *(((uint32_t*)fpga_leds) + 0) = 0x00000000; usleep(1000000); *(((uint32_t*)fpga_leds) + 0) = 0x0000000A; usleep(500000); *(((uint32_t*)fpga_leds) + 0) = 0x00000005; usleep(500000); *(((uint32_t*)fpga_leds) + 0) = 0x0000000A; usleep(500000); *(((uint32_t*)fpga_leds) + 0) = 0x00000005; usleep(500000); *(((uint32_t*)fpga_leds) + 0) = 0x0000000F; printf("\n"); usleep(1000000); printf("hps_leds\n"); hps_leds = (mmap(0, (120/4), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xFF709000)); if(hps_leds == MAP_FAILED) throw "hps_leds mmap error"; for(int i=0 ; i<(120/4) ; i++) { uint32_t a = *(((uint32_t*)hps_leds) + i); printf("0x%08X\n", a); } for(int i=0 ; i<32 ; i++) { *(((uint32_t*)hps_leds) + 0) = 1 << i; usleep(500000); } *(((uint32_t*)fpga_leds) + 0) = 0x00000000; *(((uint32_t*)hps_leds) + 0) = 0xFFFFFFFF; usleep(500000); printf("\n"); } catch(const char* msg) { printf("\n%s\n", msg); } if(fd != 0) close(fd); return 0; } GPIO со стороны FPGA отображенные в память процессора работают нормально, а вот со стороны HPS удается зажечь только первые 2 из 4. И ещё странный эффект. После того как я записываю 1 в GPIO54 он должен непрерывно гореть, но он сбрасывается после того как система моргнет GPIO53. P.S. Описание регистров и их адреса я брал вот отсюда: https://www.intel.com/content/www/us/en/programmable/hps/cyclone-v/hps.html#topic/sfo1410069909712.html#sfo1410069909712
  4. Очередные грабли. Пересобрал preloader и u-boot. Подправил dts и сделал из него dtb. Закинул все это дело на SD карту, но проект заработал не так как я ожидал. GPIO53, 54, 55, 56 настроены как GPIO. I2C0 отключен. Светодиоды прописаны следующим образом: Для HPS. leds { compatible = "gpio-leds"; hps0 { label = "hps_led0"; gpios = <0x33 0x18 0x0>; linux,default-trigger = "heartbeat"; }; hps1 { label = "hps_led1"; gpios = <0x33 0x19 0x0>; linux,default-trigger = "heartbeat"; }; hps2 { label = "hps_led2"; gpios = <0x33 0x1a 0x0>; linux,default-trigger = "heartbeat"; }; hps3 { label = "hps_led3"; gpios = <0x33 0x1b 0x0>; linux,default-trigger = "heartbeat"; }; }; Для FPGA. leds { compatible = "gpio-leds"; fpga0 { label = "fpga_led0"; gpios = <0x31 0x0 0x0>; linux,default-trigger = "heartbeat"; }; fpga1 { label = "fpga_led1"; gpios = <0x31 0x1 0x0>; linux,default-trigger = "heartbeat"; }; fpga2 { label = "fpga_led2"; gpios = <0x31 0x2 0x0>; linux,default-trigger = "heartbeat"; }; fpga3 { label = "fpga_led3"; gpios = <0x31 0x3 0x0>; linux,default-trigger = "heartbeat"; }; }; По идее все светодиоды должны моргать одновременно, но: 1) 2 и 3 светодиоды на HPS вообще не моргают. Причем это именно те GPIO на которые в изначальном проекте был выведен I2C0. Я его отключил, но они все равно не работают. 2) Светодиоды на HPS и FPGA переключаются по очереди. Что я делаю не так?
  5. UPD. Нашел в чем была проблема с переназначением светодиода на уже имеющийся GPIO. В u-boot.scr неправильно указал имя файла.
  6. А если система в QSYS не менялась и есть свободный GPIO, достаточно просто пересобрать dtb? Просто я пробовал вообще убрать светодиод из dts чтобы его отключить, но даже с пересобранным dtb он продолжил моргать.
  7. Есть отладочная плата с Altera SoC у которой светодиод, задействованный в linux (моргает при загрузке/работе HPS), выведен на GPIO53. Хочу вывести его на другой GPIO. Подскажите, пожалуйста, как его правильно переназначить. Пробовал вручную править dts, а затем собирать его в dtb, но это не сработало.
  8. Может временный глюк форума? Сейчас проверил, все скачивается.
  9. Мы у них пытались не платы купить, а самые большие чипы семейства Arora. Причем не одну штуку, а наладить контакт для постоянной закупки их чипов для всех наших проектов. Результат как я написал выше :(
  10. Мы уже месяц пытаемся договорится с GOWIN о поставках. Цитата нашего отдела снабжения: "GOWIN на поверку оказался матёрой военщиной, и пока они готовы продать продукцию, но с полным контролем на всех циклах, начиная от нашего обучения там и заканчивая их представителями при проведении работ." На таких условиях они естественно идут лесом. Так что GOWIN, к сожалению, не вариант :(
  11. Народ, а кто-нибудь слышал про следующих производителей ПЛИС? http://www.isilicontek.com/FPGA1 http://www.alta-gate.com/products.aspx?lan...;id=61&p=14 Реально ли их купить в России и достать документацию на английском языке?
  12. Коллеги, помогите, пожалуйста, решить проблему. Сделал Block Design, но он почему-то не работает. Сигнал waitrequest на любой из шин Avalon всегда в 1. Если принудительно выставить write или read, то waitrequest переключает в 0 и дает записать/считать некоторое количество данных, но после этого возвращается в 1 и намертво зависает. P.S. Hardware Manager пишет, что контроллер успешно проходит калибровку, так что видимо дело в остальной части схемы.
  13. На всех альтеровских ПЛИС в момент конфигурирования все выводы в третьем состоянии со слабой подтяжкой (20-50кОм) к VCCIO. Возможно, что в 5576ХС эта подтяжка не реализована, поэтому приведены требования на внешние резисторы. Попробуйте померить напряжение на каком-либо входе у не сконфигурированной ПЛИС и сразу станет ясно нужна внешняя подтяжка или нет.
  14. Продолжаю изучать китайские МК :) Пришли недавно LGT8F328D в виде чипов и LGT8F328P в виде отладочных плат. Вариант с буквой D шьётся через скетч LarduinoISP без проблем, а вот P зависает при вызове функции SWD_UnLock (swd_drv.c) т.к. она всегда возвращает 0. Нет ли случайно у кого-нибудь информации о различиях в алгоритме прошивки данных контроллеров или где купить оригинальный программатор SWDICE?... LarduinoISP_master.zip
  15. MD-328D (LGT8F328D) зависает при сбросе от WDT

    Ну тогда можно считать, что нормальной нет... Проверил External OSC, Soft Reset, GPIO, Timer 0, UART, запись/чтение FLASH. Особо не гонял, но к данным узлам пока претензий нет. Что не понравилось: 1. Нет отдельного вектора для загрузчика - нужно немного переделывать бутлоадер. 2. Нет полной бинарной совместимости с ATmega328 - нужно править начальную инициализацию, поэтому туда нельзя залить проекты от которых есть только hex файл. 3. Нет ICSP - нельзя использовать стандартные программаторы/отладчики. 4. После перепрошивки контроллер зависает также как и в случае с WDT - нужно передергивать питание. В оригинальной меге такой проблемы нет - программа стартует сразу после перепрошивки. Я пробовал его сбрасывать - не помогает. В оригинальной меге такой проблемы нет. Пока нашел только кривой 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.