Jump to content

    

Avratmega

Новичок
  • Content Count

    2
  • Joined

  • Last visited

Community Reputation

0 Обычный
  1. Добрый вечер. Есть С++ проект с классами использующими виртуальными функции под Atmega2560, версия IAR 7.10.4 . Стал для этого проекта делать бутлоадер, который будет размещаться в NRWW секции (адреса 0x1F000-0x1FFFF). Так как библиотеки на С++ то делаю на них. При сборе проекта возникает ошибка: Ругается на код: SystemTimer* SystemTimer::_instance = NULL; SystemTimer::SystemTimer() : _cachedMsValue(0), _cachedTccrb(0), _cachedTcnt(0), _type(ITimer::PERIODIC) { _instance = this; } Конфигурация в .xcl файле: Насколько я понимаю, значение указателя на таблицу виртуальных функций стало 3 байта вместо 2. Но IAR генерирует код для 2-х байтных указателей. В настройках рантайма стоит __vtable_memory = __nearflash думаю что в этом проблема, но как поменять не знаю. Есть идеи как побороть?
  2. Всем привет! Работаю с EEPROM ST m24512 по i2c интерфейсу мк msp430f5510. Запись происходит нормально , но чтении происходит только один раз , при последующих чтениях зависает i2c. Чтение работает с использованием DMA согласно эраташиту, I2C в режиме сингл мастер. Исходный код написан в IAR v5. Вот пример: ---------------------- i2c_dma.asm-------------------------------------------------------------------- #define I2C_SPEED 100000 #define SPEED_COEFF SYS_CLOCK/I2C_SPEED // коэф равен 240 24Мгц/100Кгц PUBLIC I2C_Init // ф-я инициализации I2c PUBLIC Get_I2C_ptr // функция возвращает указатель на буффер i2c PUBLIC I2C_StartTrans // функция осуществляет транзакцию на i2c шине PUBLIC i2c_state RSEG DATA i2c_ptr: DS16 1 // // указатель на текущий считываемый / записываемый байт i2c_buffer: DS8 EEPROM_PAGE_SIZE+2 // буффер I2C размером 128+2 = 129 байт i2c_length: DS8 1 // количество байт для приема/передачи i2c_state: DS8 1 // байт состояния i2c i2c_last_error: DS8 1 // байт последней ошибки i2c RSEG CODE /**********************************/ // инициализация i2c extern void I2C_Init(void); /***********************************/ I2C_Init: bis.b #UCSWRST,&UCB1CTL1 mov.b #UCSWRST+UCSSEL_2+UCTR,&UCB1CTL1 mov.b #UCMST+UCMODE_3,&UCB1CTL0 bis.b #BIT1+BIT2,&P4OUT bis.b #BIT1+BIT2,&P4REN bic.b #BIT1+BIT2,&P4DIR bis.b #BIT1+BIT2,&P4SEL mov.b #LOW(SPEED_COEFF),&UCB1BR0 mov.b #HIGH(SPEED_COEFF),&UCB1BR1 bic.b #UCSWRST,&UCB1CTL1 clr.b &UCB1IFG bis.b #UCNACKIE+UCALIE+UCTXIE,&UCB1IE clr.b &i2c_last_error mov.b #I2C_IDLE,&i2c_state mov #DMA0TSEL_22,&DMACTL0 // 22 тригер на DMA 0 mov #DMARMWDIS,&DMACTL4 mov #DMADT_0+DMADSTINCR_3+DMASRCINCR_0+DMADSTBYTE+DMASRCBYTE+DMAIE,&DMA0CTL // режим сингл трансфер movx.a #UCB1RXBUF,&DMA0SA // исходный адресс это UCB1RXBUF movx.a #i2c_buffer,&DMA0DA // адресс назначения - буффер reta /******************************************************************************** ****/ // функция обработки транзакции на i2c ; extern signed char I2C_StartTrans(char addr,char count,char state); /******************************************************************************** *****/ ;in R12- адресс устройства на i2c шине ;in R13 - число байт для транзакции ;in R14- состояние (нужен рестарт после транзакции или нет) ;out R12 - выход , код ошибки I2C_StartTrans: mov.b #S_OK,&i2c_last_error mov.b R13,&i2c_length mov #i2c_buffer,&i2c_ptr clr.b &UCB1IFG bit.b #BIT0,R12 // проверяем младший бит в адрессе если 0 - то осуществляем запись , если 1 то чтение jz __i2cstart0 /********************************************************************/ // receive /*********************************************************************/ mov.b #I2C_RECEIVE,&i2c_state bic.b #UCTR,&UCB1CTL1 mov R13,&DMA0SZ // запихиваем количество байт для чтения в DMA0SZ bis #DMAEN,&DMA0CTL // разрешаем DMA jmp __i2cstart03 /********************************************************************/ // transmit /******************************************************************/ __i2cstart0: mov.b #I2C_TRANSMIT,&i2c_state bis.b #UCTR,&UCB1CTL1 __i2cstart03: bis.b R14,&i2c_state rrc R12 and.b #0x7F,R12 mov R12,&UCB1I2CSA // UCB1I2CSA = R12 >> 1 bis.b #UCTXSTT,&UCB1CTL1 // начинаем транзакцию - посылаем старт __i2cstart02: _WDR_a // сброс ватчдога cmp.b #I2C_IDLE,&i2c_state // ждем пока i2c_state == I2C_IDLE jne __i2cstart02 __uuip: bit.b #UCTXNACK+UCTXSTP+UCTXSTT,&UCB1CTL1 jnz __uuip mov.b &i2c_last_error,R12 reta /*****************************************************************/ // возвращает указатель на буффер i2c ; extern char* Get_I2C_ptr(void); /*****************************************************************/ ; R12 - указатель на буффер i2c Get_I2C_ptr: cmp.b #I2C_IDLE,&i2c_state jne Get_I2C_ptr mov #i2c_buffer,R12 reta /*****************************************************************/ // обработчик прерывания i2c /***************************************************************/ I2C_INT: add &UCB1IV,PC reti jmp ALIFG_ISR ; artbitration lost jmp NACKIFF_ISR ; nack return jmp STTIFG_ISR ; start received jmp STPIFG_ISR ; stop received jmp RXIFG_ISR ; data received TXIFG_ISR: ; transmit buffer empty tst.b &i2c_length // пока i2c_length != 0 то шлем байты из буффера jnz __i2ctxifg0 bic.b #UCTXIFG,&UCB1IFG // если i2c_length == 0 то i2c_state = I2C_IDLE и проверяем нужен ли рестарт, если не нужен просто выходим из // интерапта bit.b #I2C_ENABLE_RESTART,&i2c_state mov.b #I2C_IDLE,&i2c_state jnz __i2ctxifg_ex bis.b #UCTXSTP,&UCB1CTL1 reti __i2ctxifg0: push.w r12 mov &i2c_ptr,r12 mov.b @R12+,&UCB1TXBUF mov R12,&i2c_ptr dec.b &i2c_length pop.w r12 __i2ctxifg_ex: reti // если арбитраж потерян (не нужно в синглмастере) ALIFG_ISR: mov.b #I2C_ARBITRATION_LOST,&i2c_last_error jmp __inti2c0 // если принят NACK возвращаем код ошибки NACKIFF_ISR: mov.b #I2C_NACK_RETURN,&i2c_last_error __inti2c0: clr.b &UCB1IFG mov.b #I2C_IDLE,&i2c_state bis.b #UCTXSTP,&UCB1CTL1 reti STTIFG_ISR: STPIFG_ISR: reti RXIFG_ISR: // не используем так как есть DMA reti COMMON INTVEC ORG USCI_B1_VECTOR DW I2C_INT END ---------------------- dma.asm-------------------------------------------------------------------- EXTERN i2c_state EXTERN I2C_Init RSEG CODE /***************************************************************************/ // обработчик прерывания от DMA вызывается когда прочитано нужно число байт /***************************************************************************/ DMA_HANDLER: add &DMAIV,PC reti jmp DMA0_HND jmp DMA1_HND jmp DMA2_HND reti reti reti reti reti DMA0_HND: bic.b #UCRXIFG,&UCB1IFG // UCB1IFG &= ~UCRXIFG mov.b #I2C_IDLE,&i2c_state // i2c_state = I2C_IDLE bis.b #UCTXNACK+UCTXSTP,&UCB1CTL1 // формируем NACK и стоп __uuuu: bit.b #UCBBUSY,&UCB1STAT // ждем освобождения i2c jnz __uuuu // calla #I2C_Init // !!!!! костыль , если его воткнуть то прием будет работать иначе будет работать только один раз DMA1_HND: DMA2_HND: reti COMMON INTVEC ORG DMA_VECTOR DW DMA_HANDLER END ----------------------------------------------------------eeprom.c----------------------------------------------------------------------------------- extern signed char I2C_StartTrans(uchar addr, uchar count, char state); extern char* Get_I2C_ptr(void); // addr - адресс считывания // ptr - указатель куда скопировать прочитанное // count - количество байт нужное считать char eeprom_read_bytes(ushort addr,uchar* ptr, uchar count) { char hr; uchar* ptr2; if(count > EEPROM_PAGE_SIZE) // проверяем количество байт - должно быть меньше чем буффер i2c return EEPROM_IVALID_SIZE; ptr2 = Get_I2C_ptr(); // получаем указатель на буффер i2c *ptr2 = (BYTE)(addr >> 8); // запихиваем в буффер адресс (16 бит) *(ptr2+1) = (BYTE)(addr&0x00FF); hr = I2C_StartTrans(EERPOM_I2C_ADDR&WRITE_OP,2,RESTART_AFTER_TRANSACTION); // отправляем в eeprom адресс и //генерируем рестарт hr = I2C_StartTrans(EERPOM_I2C_ADDR|READ_OP,count,STOP_AFTER_TRANSACTION); // считываем в буффер count байт из //eeprom и генерирует стоп memcpy_m(ptr,ptr2,count) ; // копируем из буффера i2c в ptr return hr; // возвращаем код ошибки } Уже 2 неделю никак не могу толком настроить i2c. Хотя софтварная эмуляция функций (i2c на портах) I2C_StartTrans и I2c_init работает без проблем. ТАкже работает без проблем если после каждого чтения переинициализировать i2c.