Я делал так, правда на F062 + внешняя XData.
1. Оболочка заливала всю прошивку в XData
2. Потом передавала команду перепрошивки Flash
3. Функция перепрошивки находится верхних адресах Flash, ее задача – вычитать страницу из XData (размер прошивки задается например в переменной в data), записать страницу в Flash.
Если нет внешней XData или не хватает внутренней XData то можно делать так:
1. Передали команду перепрошивки Flash
2. Перешли на ф-н перепрошивки, например с адреса 62K (что бы до него не достала прошивка)
3. Запретили все прерывания
4 .Оболочка передает длину прошивки с страницах
5. Прошивка читает 512 в XData
6. Пишет во Flash страницу
7. Ждет следующую страну
8. Если все страницы записаны переходит на 0x0000 или выполняет аппаратный сброс
Прошивка изначально пишется с ф-н перепрошивки Flash по верхним адресам и заливается программаторам. Последующие версии прошивки (передаваемая пользователям в bin фале) обрезаются, например сам код занимает адреса 0-16K потом нули потом с 62K ф-н перепрошивки. Пишем простейшую прогу которая определит окончания основной проги и обрежет bin файл + еще можно добавить простенькое шифрование (например наложение таблицы) при этом пользователь не сможет поколупатся в прошивке.
Код
------------- Скопировать (записать) данные из XDATA во Flash -----------------
;
; Параметры вызова :
; fUpdateFW - флаг обновлкния Firmware
; wCountCopyByte - кол-во байт для копирования (в формате счетчиков)
; wStartAdr - адрес во Flash начала записи
;
; Возращяемые значения:
; XDATA[0] -> Flash[Adr] - копия в Flash буфера XDATA
;
CSEG AT BOOT_LOADER_ENTRY ; Точка входа в загрузчик (запись во Flash)
write_flash:
;------------------------------- Инициализация --------------------------------
mov buf_ch + 0, #0F4h ; Заполняем буфер ключа, что бы не держать статически 8 байт DATA
mov buf_ch + 1, #0xxh
mov buf_ch + 2, #0xxh
mov buf_ch + 3, #0xxh
mov buf_ch + 4, #0xxh
mov buf_ch + 5, #0xxh
mov buf_ch + 6, #0xxh
mov buf_ch + 7, #0xxh
mov r0, #BUF_CH_ADRESS ; Указатель на буфер ключа
mov a, buf_rd_uart + 2 ; Определяем флаг fUpdateFW
rrc a ; Копируем флаг в флаг переноса
mov IEGF0, c ; Копируем флаг переноса в флаг общего назначения 0
clr a ; Сбросили аккумулятор
clr EA ; Запрещяем все прерывания
mov r2, a ; Определяем адрес в XDATA от куда будем копировать, всегда с 0x0000
mov r3, a
mov r4, buf_rd_uart + 3 ; Определяем кол-во байт для копирования (bCountWriteByte) HI
mov r5, buf_rd_uart + 4 ; LO
mov DPH, buf_rd_uart + 5 ; Определяем адрес во Flash начала записи (wStartAdr)
mov DPL, buf_rd_uart + 6
;------------------------- Стираем первую страницу ----------------------------
mov FLSCL, #081h ; b7 = 1 : FOSE - ждущий таймер модуля Flash-памяти включен (рекомендуемое значение)
; b6 = 0 : FRAE - чтение Flash-памяти происходит по необходимости (рекомендуемое значение)
; b0 = 1 : FLWE - операции записи/стирания Flash-памяти разрешены
mov PSCTL, #003h ; b2 = 0 : SFLE - запрет доступа к сверхоперативному сектору Flash-памяти (00-7f)
; b1 = 1 : PSEE - разрешаем стирать страницу
; b0 = 1 : PSWE - запись во Flash-память программ разрешена (MOVX -> Flash)
movx @dptr, a ; Стираем первую страницу
mov PSCTL, #001h ; Запрещяем стирать страницу
mov r6, DPH ; Сохраняем адрес Flash
mov r7, DPL
mov DPH, r2 ; Востановили адрес XDATA
mov DPL, r3
;--------------------------------- Копирование --------------------------------
write_flash_copy: ; Копируем заданое кол-во байт
movx a, @dptr ; Прочитали 1 байт из XDATA
inc dptr ; Перешли на следующий байт в XDATA
jnb IEGF0, write_flash_copy_no_key ; Переходим дальше если не нужен ключ
write_flash_copy_key: ; Если используем ключ
mov r1, a ; Сохранили считаный закодированый байт
xrl a, @r0 ; Декодируем текущий считаный байт
xch a, r1 ; a = закодированый байт, r1 = раскодированый байт
xrl a, #055h ; На основании закодированого байта находим новый ключ
add a, #0aah
mov @r0, a ; Сохраняем новый ключ
inc r0 ; Переходим на следующий байт ключа
anl 0, #(BUF_CH_ADRESS | 07h) ; Организовали циклический буфкр на 8 байт (0 - это адрес r0)
mov a, r1 ; Востанавливаем раскодированый байт
write_flash_copy_no_key:
mov r2, DPH ; Сохраняем адрес XDATA
mov r3, DPL
mov DPH, r6 ; Востановили адрес Flash
mov DPL, r7
movx @dptr, a ; Сохранили в Flash считайный из XDATA байт
inc dptr ; Перешли на следующий байт в Flash
mov r6, DPH ; Сохраняем адрес Flash
mov r7, DPL
mov a, r7 ; Если Lo(Flash Adr) != 0x00 то не стираем страницу
jnz write_flash_copy_no_erase_page
mov a, r6 ; Если Hi(Flash Adr) нечетное то не стираем страницу
rrc a
jc write_flash_copy_no_erase_page
write_flash_copy_erase_page: ; Стираем текущую страницу
mov PSCTL, #003h ; Разрешаем стирать страницу
movx @dptr, a ; Стираем страницу
mov PSCTL, #001h ; Запрещяем стирать страницу
write_flash_copy_no_erase_page:
mov DPH, r2 ; Востановили адрес XDATA
mov DPL, r3
djnz r5, write_flash_copy ; Копируем все байты
djnz r4, write_flash_copy
;--------------------------------- Завершение ---------------------------------
mov PSCTL, #000h ; b2 = 0 : SFLE - запрет доступа к сверхоперативному сектору Flash-памяти (00-7f)
; b1 = 0 : PSEE - стирание Flash-памяти программ запрещено
; b0 = 0 : PSWE - запись во Flash-память программ запрещена
mov FLSCL, #080h ; b7 = 1 : FOSE - ждущий таймер модуля Flash-памяти включен (рекомендуемое значение)
; b6 = 0 : FRAE - чтение Flash-памяти происходит по необходимости (рекомендуемое значение)
; b0 = 0 : FLWE - операции записи/стирания Flash-памяти запрещены
jb IEGF0, write_flash_update ; Переходим если это было обновление
write_flash_no_update: ; Если это была просто запись во Flash
setb EA ; Разрешаем все прерывания
ret ; Выходим
write_flash_update: ; Если это было обновление
mov RSTSRC, #010h ; b4 = 1 : SWRSF - выполняем программный сброс
;-------------------------------------------------------------------------------