![](https://electronix.ru/forum/uploads/set_resources_23/84c1e40ea0e759e3f1505eb1788ddf3c_pattern.png)
![](https://electronix.ru/forum/uploads/set_resources_23/84c1e40ea0e759e3f1505eb1788ddf3c_default_photo.png)
BSACPLD
Свой-
Постов
912 -
Зарегистрирован
-
Посещение
-
Победитель дней
5
Весь контент BSACPLD
-
Китайские ПЛИС
BSACPLD ответил irinamiros тема в Среды разработки - обсуждаем САПРы
Мы уже месяц пытаемся договорится с GOWIN о поставках. Цитата нашего отдела снабжения: "GOWIN на поверку оказался матёрой военщиной, и пока они готовы продать продукцию, но с полным контролем на всех циклах, начиная от нашего обучения там и заканчивая их представителями при проведении работ." На таких условиях они естественно идут лесом. Так что GOWIN, к сожалению, не вариант :( -
Китайские ПЛИС
BSACPLD ответил irinamiros тема в Среды разработки - обсуждаем САПРы
Народ, а кто-нибудь слышал про следующих производителей ПЛИС? http://www.isilicontek.com/FPGA1 http://www.alta-gate.com/products.aspx?lan...;id=61&p=14 Реально ли их купить в России и достать документацию на английском языке? -
Проблемы с Xilinx AMM AXI Bridge
BSACPLD опубликовал тема в Работаем с ПЛИС, области применения, выбор
Коллеги, помогите, пожалуйста, решить проблему. Сделал Block Design, но он почему-то не работает. Сигнал waitrequest на любой из шин Avalon всегда в 1. Если принудительно выставить write или read, то waitrequest переключает в 0 и дает записать/считать некоторое количество данных, но после этого возвращается в 1 и намертво зависает. P.S. Hardware Manager пишет, что контроллер успешно проходит калибровку, так что видимо дело в остальной части схемы. -
На всех альтеровских ПЛИС в момент конфигурирования все выводы в третьем состоянии со слабой подтяжкой (20-50кОм) к VCCIO. Возможно, что в 5576ХС эта подтяжка не реализована, поэтому приведены требования на внешние резисторы. Попробуйте померить напряжение на каком-либо входе у не сконфигурированной ПЛИС и сразу станет ясно нужна внешняя подтяжка или нет.
-
Продолжаю изучать китайские МК :) Пришли недавно LGT8F328D в виде чипов и LGT8F328P в виде отладочных плат. Вариант с буквой D шьётся через скетч LarduinoISP без проблем, а вот P зависает при вызове функции SWD_UnLock (swd_drv.c) т.к. она всегда возвращает 0. Нет ли случайно у кого-нибудь информации о различиях в алгоритме прошивки данных контроллеров или где купить оригинальный программатор SWDICE?... LarduinoISP_master.zip
-
Ну тогда можно считать, что нормальной нет... Проверил 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.
-
Есть машинный перевод с китайского на английский. https://www.google.ru/url?sa=t&source=w...IM6cjlIx8ZPt14_
-
Тем что он китайский. Импортозамещение чтоб его :angry2: Про AVR от НИИЭТ я знаю, но у него цена совсем не адекватная, поэтому рассматриваю китайские аналоги.
-
Нашел странную закономерность. Если приведенный ниже код разместить начиная с адреса 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 () ; }
-
Коллеги, помогите, пожалуйста, с очередной проблемой с 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
-
Кажись разобрался как решить проблему :) Сравнив заголовочные файлы для MD-328D и LGT8F328D я пришел к выводу что это один и тот же камень. Ну или они настолько похожи, что я не заметил разницу :) А раз так, то можно использовать скетч превращающий ардуино в программатор для LGT8F328D и для MD-328D. Алгоритм действий такой: 1. Скачиваем LarduinoISP с github и ArduinoUploader с просторов интернета. 2. Загружаем в ардуино скетч LarduinoISP. 3. Подключаем VCC, GND, D10 на PC6/RESET, D12 на PE2/SWD и Pull-Up резистор 1.1кОм, D13 на PE0/SWC. 4. Загружаем с помощью ArduinoUploader нужный нам hex. 5. Передергиваем питание прошитого контроллера. Не знаю почему, но прошитая программа стартовала лишь после этого.
-
Можно поподробнее как Вы это делали? Ранее не имел дело ни с ардуино, ни с SWD.
-
Коллеги, подскажите, пожалуйста, доводилось ли кому-нибудь работать с MD-328D (китайский аналог ATmega328P)? Купил себе сегодня плату с данным контроллером чисто на поиграться. Попробовал зашить указав в программаторе ATmega328P, но тут меня ждал облом - по SPI он не шьется. В документации есть упоминание про SWD, но каким программатором шить, там не сказано.
-
Версия 15. soft_AVR_v15_beta.rar
-
Не вариант. Каналов много + нужно перестраивать за 1 такт 200МГц, так что только SERDES.
-
В пределах такта 200МГц, т.е. 5нс = 4 шага.
-
Блин. Слона то я и не приметил... У них на DevKit speed grade 2 запаян. Похоже придется изобретать свой SERDES на связке логика + ODDR с тактированием от 400МГц... Хотя я так однажды уже делал для Arria GX... Непосредственно 800МГц мне не нужно. Мне нужно подстраивать фазу выходного сигнала с шагом 1.25нс.
-
Питание 1.8В. HR Клок заведен как дифф. пара на GCLK.
-
У меня здесь немного другая проблема. SERDES работает на выход и используется для грубой подстройки фазы выходного сигнала. Точную подстройку я делаю через ODELAY. Проблема с Pulse Width именно со стороны выскочастотного клока заходящего на SERDES. Именно на него ругается Timing Analyzer. Клоки для SERDES: IBUFDS #( .DQS_BIAS("FALSE") // (FALSE, TRUE) ) ibufds_clk_800MHz ( .I (clk_800MHz_p), .IB (clk_800MHz_n), .O (clk_800MHz) ) ; BUFGCE_DIV #( .BUFGCE_DIVIDE (4), .IS_CE_INVERTED (1'b0), .IS_CLR_INVERTED (1'b0), .IS_I_INVERTED (1'b0) ) bufg_clk_sys ( .I (clk_800MHz), .CE (1'b1), .CLR (1'b0), .O (clk_sys) ) ; BUFGCE_DIV #( .BUFGCE_DIVIDE (1), .IS_CE_INVERTED (1'b0), .IS_CLR_INVERTED (1'b0), .IS_I_INVERTED (1'b0) ) bufg_clk_io ( .I (clk_800MHz), .CE (1'b1), .CLR (1'b0), .O (clk_io) ) ;
-
Я здесь пытаюсь использовать OSERDESE3. Он может работать 4x или 8x.
-
Немного странно, т.к. даже на Cyclone IV я без проблем получал 800МГц без всяких ухищрений. А здесь намного более шустрый чип. Под динамической подстройкой Вы имели ввиду фазовые соотношения между низкочастотным и высокочастотным клоком?
-
Kintex UltraScale SERDES
BSACPLD опубликовал тема в Работаем с ПЛИС, области применения, выбор
Коллеги, пытаюсь запустить SERDES на 800МГц, но никак не могу победить разваливающиеся времянки. Тактирование SERDES сделал от внешнего клока. И выскочастотный и низкочастотный клоки получаю посредством примитивов BUFGCE_DIV. В документации Xilinx вроде именно так и рекомендуют делать. Частоты вроде небольшие, но чтобы я ни пробовал писать в констрейнах, все время получаю ругань на Pulse Width. Прошу совета у товарицей имеющих опыт запуска этих SERDES на подобные или более высокие частоты. -
Стр. 36 табл. 33. ds892_kintex_ultrascale_data_sheet.pdf
-
В datasheet написано от 200 до 800МГц. Я могу завести туда и 200 и 400 и 800, поэтому и возник вопрос о том, какое значение лучше выставить.
-
Kintex UltraScale ODELAY3
BSACPLD опубликовал тема в Работаем с ПЛИС, области применения, выбор
Коллеги, подскажите, пожалуйста, исходя из каких соображений нужно выбирать опорную частоту для ODELAY3? Просто чтобы была кратна системной частоте или есть какие-либо нюансы?