rezident 0 11 октября, 2011 Опубликовано 11 октября, 2011 · Жалоба Нет, Сергей, как сделать "перемещаемые" вектора прерываний я лично понимаю. Для пользовательского приложения "аппаратные" вектора прерываний как таковые вообще не используются. Пишутся лишь функции-обработчики прерываний, адреса которых "раскладываются" в таблицу переходов, расположенную в ОЗУ. У ТС же возник вопрос по совмещению двух проектов/прошивок в одном кристалле и вызове одного из другого. Как я понял, ты предлагаешь замещать вектор сброса тем, который генерируется при компиляции именно бутлоадера. А то содержимое вектора RESET, которое компилируется в пользовательском приложении из прошивки выкинуть, использовав его лишь как адрес для старта приложения. Так? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 12 октября, 2011 Опубликовано 12 октября, 2011 · Жалоба Нет, Сергей, как сделать "перемещаемые" вектора прерываний я лично понимаю. Для пользовательского приложения "аппаратные" вектора прерываний как таковые вообще не используются. Пишутся лишь функции-обработчики прерываний, адреса которых "раскладываются" в таблицу переходов, расположенную в ОЗУ.Верно. И раскладывает их туда загрузчик перед тем, как запустить приложение. И берет он их из таблицы, которая расположена в фиксированном месте приложения. И таблицей этой является содержимое сегмента INTVEC приложения. У ТС же возник вопрос по совмещению двух проектов/прошивок в одном кристалле и вызове одного из другого. Как я понял, ты предлагаешь замещать вектор сброса тем, который генерируется при компиляции именно бутлоадера. А то содержимое вектора RESET, которое компилируется в пользовательском приложении из прошивки выкинуть, использовав его лишь как адрес для старта приложения. Так?Зачем же выбрасывать и замещать? Пусть он лежит в таблице векторов приложения. Тогда загрузчик точно будет знать, откуда его брать. Вот смотрите, я в сообщении №26 давал пример. Вот структура таблицы векторов приложения, т.е. полное содержимое сегмента INTVEC приложения: __attribute__ ((section(".app_vectors"))) struct { void *Vectors[INT_VECTORS_COUNT - 1]; void (*ResetVector)(); } Application; Тут и все вектора прерываний и вектор сброса. Вот загрузчик копирует эту таблицу в ОЗУ, в то место, откуда берут адреса функции-трамплины: uint_fast8_t i = INT_VECTORS_COUNT - 1; // do not copy reset vector while(i--) { InterruptVectors[i] = Application.Vectors[i]; } А вот из этой же таблицы берется адрес, на который надо перейти для старта приложения: Application.ResetVector(); А "железный" вектор RESET указывает на старт загрузчика. Тогда и приложение знает, как запустить загрузчик - адрес его точки входа всегда лежит в ячейках по адресу 0xFFFE. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KARLSON 1 12 октября, 2011 Опубликовано 12 октября, 2011 · Жалоба А что делает запись ((void(*)() )0x2200)();? Если после программировании в бутлоадере с помощью этой записи обратиться к инструкции по адресу 0x2200 ( от куда и начинается приложение) старт приложения с инициализацией произойдёт? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 12 октября, 2011 Опубликовано 12 октября, 2011 · Жалоба А что делает запись ((void(*)() )0x2200)();?Вызов функции вида void func(void), расположенной по адресу 2200. Если после программировании в бутлоадере с помощью этой записи обратиться к инструкции по адресу 0x2200 ( от куда и начинается приложение) старт приложения с инициализацией произойдёт?Если по адресу 0x2200 расположена первая инструкция стартапа. Если же там располагается указатель на адрес точки входа (как было бы, если бы там располагался) вектор сброса, то запись должна была бы быть несколько иной: ((void(**)() )0x2200)(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KARLSON 1 13 октября, 2011 Опубликовано 13 октября, 2011 (изменено) · Жалоба Захотел я сделать прошивку с переходами между приложениями пока без использовании прерываний: приложение 1 #include "io430.h" void main( void ) { // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; P1DIR = BIT0; P1OUT = BIT0; char j=0; unsigned int k = 40000, z=2; while(1) { for(unsigned int i=0; i<k; i++); for(unsigned int i=0; i<z; i++); P1OUT ^= BIT0; ++j; if(j == 30) { ((void(*)() )0x2200)(); } } } xcl файл приложения 1 // ----------------------------------------------- // Read/write memory // -Z(DATA)DATA16_I,DATA16_Z,DATA16_N,DATA16_HEAP+_DATA16_HEAP_SIZE=1100-20FF -Z(DATA)CODE_I -Z(DATA)CSTACK+_STACK_SIZE# // ------------------------------------- // Constant data // -Z(CONST)DATA16_C,DATA16_ID,DIFUNCT,CHECKSUM=2100-FFBF // ------------------------------------- // Code // -Z(CODE)CSTART,ISR_CODE,CODE_ID=EC00-FFBF -P(CODE)CODE=EC00-FFBF // ------------------------------------- // Interrupt vectors // -Z(CODE)INTVEC=FFC0-FFFF -Z(CODE)RESET=FFFE-FFFF прошивка приложения 1 @EC00 31 40 00 21 B0 12 0C EC B0 12 4E EC 0A 12 0B 12 08 12 B2 40 80 5A 20 01 D2 43 22 00 D2 43 21 00 4A 43 3B 40 40 9C 28 43 0B 3C 1F 53 0F 98 FD 2B D2 E3 21 00 5A 53 7A 90 1E 00 02 20 B0 12 00 22 0F 43 01 3C 1F 53 0F 9B FD 2B 0F 43 EF 3F 30 40 52 EC 30 40 56 EC FF 3F @FFFE 00 EC приложение 2 #include "io430.h" void main( void ) { // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; P1DIR = BIT0; P1OUT = BIT0; char j=0; unsigned int k = 65535, z=65535; while(1) { for(unsigned int i=0; i<k; i++); for(unsigned int i=0; i<z; i++); P1OUT ^= BIT0; ++j; if(j == 30) { ((void(*)() )0xEC00)(); } } } xcl файл приложения 2 // ----------------------------------------------- // Read/write memory // -Z(DATA)DATA16_I,DATA16_Z,DATA16_N,DATA16_HEAP+_DATA16_HEAP_SIZE=1100-20FF -Z(DATA)CODE_I -Z(DATA)CSTACK+_STACK_SIZE# // ------------------------------------- // Constant data // -Z(CONST)DATA16_C,DATA16_ID,DIFUNCT,CHECKSUM=2200-9FBF // ------------------------------------- // Code // -Z(CODE)CSTART,ISR_CODE,CODE_ID=2200-9FBF -P(CODE)CODE=2200-9FBF // ------------------------------------- // Interrupt vectors // -Z(CODE)INTVEC=9FC0-9FFF -Z(CODE)RESET=9FFE-9FFF прошивка приложения 2 @2200 31 40 00 21 B0 12 0C 22 B0 12 4C 22 0A 12 0B 12 08 12 B2 40 80 5A 20 01 D2 43 22 00 D2 43 21 00 4A 43 3B 43 38 43 0B 3C 1F 53 0F 98 FD 2B D2 E3 21 00 5A 53 7A 90 1E 00 02 20 B0 12 00 EC 0F 43 01 3C 1F 53 0F 9B FD 2B 0F 43 EF 3F 30 40 50 22 30 40 54 22 FF 3F @9FFE 00 22 q общая прошивка @2200 31 40 00 21 B0 12 0C 22 B0 12 4C 22 0A 12 0B 12 08 12 B2 40 80 5A 20 01 D2 43 22 00 D2 43 21 00 4A 43 3B 43 38 43 0B 3C 1F 53 0F 98 FD 2B D2 E3 21 00 5A 53 7A 90 1E 00 02 20 B0 12 00 EC 0F 43 01 3C 1F 53 0F 9B FD 2B 0F 43 EF 3F 30 40 50 22 30 40 54 22 FF 3F @9FFE 00 22 @EC00 31 40 00 21 B0 12 0C EC B0 12 4E EC 0A 12 0B 12 08 12 B2 40 80 5A 20 01 D2 43 22 00 D2 43 21 00 4A 43 3B 40 40 9C 28 43 0B 3C 1F 53 0F 98 FD 2B D2 E3 21 00 5A 53 7A 90 1E 00 02 20 B0 12 00 22 0F 43 01 3C 1F 53 0F 9B FD 2B 0F 43 EF 3F 30 40 52 EC 30 40 56 EC FF 3F @FFFE 00 EC q Прошил. Вроде работает. Первая прошивка часто моргает (~3Гц), затем переходит на вторую прошивку, моргает медленно (~1.5 Гц). И так бесконечно. Я всё правильно сделал? Есть ли минусы? Кстати, Сергей, пробовал делать переход на адрес вектора ((void(**)() )0x9FFE)(); в одном и ((void(**)() )0xFFFE)(); в другом приложении. Компилятор ругнулся на эти записи "Error[Pe109]: expression must have (pointer-to-) function type " perehod_po_prilogeniyam.rar Изменено 13 октября, 2011 пользователем KARLSON Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 13 октября, 2011 Опубликовано 13 октября, 2011 · Жалоба Кстати, Сергей, пробовал делать переход на адрес вектора ((void(**)() )0x9FFE)(); в одном и ((void(**)() )0xFFFE)(); в другом приложении. Компилятор ругнулся на эти записи "Error[Pe109]: expression must have (pointer-to-) function type "Да, это я лопухнулся. (*((void(**)() )0xFFFE))(); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kurt 0 21 октября, 2011 Опубликовано 21 октября, 2011 · Жалоба Мои пять копеек. Вариант, если в устройстве есть внешняя память (в моем случае AT45DB или FRAM33). Посредством основной программы по существующему протоколу связи заливаем образ прошивки во внешнюю память (с проверкой версии прошивки, аппаратуры, контрольных сумм и пр.). Затем передаем управление ассемблерной процедуре, которая копирует себя в ОЗУ и затем оттуда быстро и тупо копирует образ из внешней памяти во FLASH. Исходник для msp430f2x и at45db: #include <msp430.h> #include "hardware_config.h" #include "fwupdate.h" // Forward declarations of segments. RSEG CSTACK:DATA:NOROOT RSEG DATA16_I:DATA:NOROOT MODULE FW_UPDATE_ROUTINES PUBLIC fw_at45_update WD_EXT_STB MACRO xor.b #(1<<PIN_WD_STROBE), &WD_EXT_PORT ENDM AT45_ENABLE MACRO bic.b #(1<<PIN_AT45_CS), &AT45_CS_PORT ENDM AT45_DISABLE MACRO bis.b #(1<<PIN_AT45_CS), &AT45_CS_PORT ENDM SPI_WRITE MACRO N mov.b N, r12 call r8 ENDM RSEG CODE fw_at45_update dint nop mov.w #(WDTPW|WDTHOLD), &WDTCTL ftg_w_ready bit #BUSY, &FCTL3 jnz ftg_w_ready mov #SFE(CSTACK), sp // copy to RAM mov.w #FW_INIT, r12 mov.w #SFE(DATA16_I), r14 push.w r14 copy_2_ram: mov.w @r12+, 0(r14) incd.w r14 cmp.w #FW_UPDATE_END, r12 jnc copy_2_ram ret FW_INIT WD_EXT_STB // Init DCO mov.b &CALBC1_12MHZ,&BCSCTL1 // Set DCO to 12MHz clr.b &BCSCTL2 // MCLK = SMCLK = DCOCLK mov.b &CALDCO_12MHZ,&DCOCTL mov.w #(FWKEY|FSSEL_1|FN5), &FCTL2 // Flash clock = MCLK/35 ~ 360kHz // configure SPI module mov.b #(UCSSEL_2|UCSWRST), &UCB1CTL1 // SMCLK mov.b #(UCMST|UCSYNC|UCMSB|UCCKPL), &UCB1CTL0 // 3-pin, 8-bit SPI master mov.b #1, &UCB1BR0 mov.b #0, &UCB1BR1 bic.b #(1<<2), &P5DIR bis.b #((1<<1)|(1<<3)), &P5DIR bis.b #((1<<1)|(1<<2)|(1<<3)), &P5SEL // P5.1,2,3 option select bic.b #UCSWRST, &UCB1CTL1 // Initialize USCI state machine // configure AT45DB AT45_DISABLE mov #(SFE(DATA16_I) + (spi_wr-FW_INIT)), R8 // R8 = &spi_write // wait for ready at45db wait_at45db AT45_ENABLE SPI_WRITE #0x57 SPI_WRITE #0x00 AT45_DISABLE bit.b #(1<<7), r12 jnc wait_at45db // erase main memory mov.w #3, r12 // erase cycles count meras_loop mov.w #(FWKEY | MERAS), &FCTL1 // Set Mass Erase bit mov.w #(FWKEY), &FCTL3 // Clear Lock bit mov.w #0xFFFF, &fw_at45_update // write stuff byte to flash meras_wait bit #BUSY, &FCTL3 jnz meras_wait dec.w r12 jnz meras_loop WD_EXT_STB // at45db start read AT45_ENABLE SPI_WRITE #0xE8 // Continues Array Read(Legacy Command) SPI_WRITE #0x00 // upper part of page address SPI_WRITE #0x04 // lower part of page address and MSB of int.page adr. mov.b #0, R12 call r8 // LSB byte of internal page address call r8 // perform 4 dummy writes call r8 // in order to initiate DataFlash call r8 // address pointers call r8 // -- mov.w #FW_FIRST_ADDR, r14 mov.w #FWKEY,&FCTL3 // Clear LOCK prg_blocks WD_EXT_STB mov.w #(FWKEY|BLKWRT|WRT),&FCTL1 // Enable block write prg_bytes SPI_WRITE #0x00 // Read byte from dataflash mov.b r12, 0(r14) // Write location prg_wait bit #WAIT, &FCTL3 // Test WAIT jz prg_wait // Loop while WAIT=0 inc.w r14 // Point to next byte jz prg_finish bit.b #0x3F, r14 // end of block (addr % 0x40) == 0 jne prg_bytes mov.w #(FWKEY|WRT), &FCTL1 // Set BLKWRT=0 prg_busy bit #BUSY, &FCTL3 jnz prg_busy jmp prg_blocks prg_finish mov.w #(FWKEY|WRT), &FCTL1 // Set BLKWRT=0 prg_finb bit #BUSY, &FCTL3 jnz prg_finb mov.w #FWKEY, &FCTL1 // Clear WRT bit mov.w #(FWKEY|LOCK), &FCTL3 // Set Lock Bit AT45_DISABLE mov.w #0, &WDTCTL // RESET! spi_wr bit.b #UCB1TXIFG, &UC1IFG jnc spi_wr mov.b r12, &UCB1TXBUF ?w_txend: bit.b #UCB1RXIFG, &UC1IFG jnc ?w_txend mov.b &UCB1RXBUF, r12 ret FW_UPDATE_END ENDMOD END Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться