├── AVRISP_mk2.f ├── AVR_instructions.set ├── AVRset.f ├── CP866.f ├── ISPprog.f ├── ISProtocol.f ├── KOI8-R.f ├── README.md ├── SFIFO.f ├── STK500.pdf ├── USB01.f ├── USB1.f ├── USB_const.f ├── USBprog.f ├── USBtiny.f ├── USBtiny1.f ├── WIN1251.f ├── XPROGprotocol.f ├── Xprog.f ├── asmAVR.f ├── bitsAVR.f ├── buffers.f ├── chips ├── ATtiny24-44-84.ff ├── ATtiny441-841.ff ├── chips.sublime-project ├── chips.sublime-workspace ├── m168a.ff ├── m168pa.ff ├── m328.ff ├── m48.ff ├── m48pa.ff ├── m8.ff ├── m88.ff ├── m88pa.ff ├── regName.ff ├── tn13.ff ├── tn15.ff ├── tn2313.ff ├── tn2313A.ff ├── tn24.ff ├── tn25.ff ├── tn26.ff ├── tn261.ff ├── tn4313.ff ├── tn44.ff ├── tn441.ff ├── tn45.ff ├── tn84.ff ├── tn841.ff ├── tn85.ff ├── x16A4U.ff ├── x256A3BU.ff ├── x32A4U.ff └── xModules.ff ├── colortest.f ├── data.f ├── disAVR.f ├── examples ├── 1-helloLed.f └── TM-Led │ ├── tmLed.asm │ └── tmLed.f ├── fraction.f ├── fuses.f ├── intel-hex.f ├── labels.f ├── libs ├── CRC24asm.f ├── CRC8asm.f ├── CRCx.f ├── LMT01_LUT.f ├── USBtinySPI.f ├── USBtynySPI_.f ├── bootloader │ ├── BootLoader.f │ ├── BootLoader.odt │ └── TinyBoot.f ├── console_codes.f ├── eeprom.f ├── map.f ├── mtask-r.f ├── mtask.f ├── pFIFO.f ├── serial.f ├── spf.log ├── spf.log1 ├── subProg.f ├── tables.f ├── time.f └── timers.f ├── opcodes.f ├── prog.f ├── programmers.f ├── sborAVR.f ├── selectAVR.f ├── spf.log ├── spforth.lang ├── toolbox.f ├── tools ├── boot ├── ee! ├── iwbt ├── iwusb └── prog ├── tstcmd.f ├── tstdis.f ├── Дополнительные команды ассемблера2.odt ├── ПамятьAVR ├── ПирамидаAVR.txt └── План AVR /AVRISP_mk2.f: -------------------------------------------------------------------------------- 1 | 2 | 3 | MARKER ALLDROP \ для удаления нижеследующего 4 | 5 | 256 TO size-rBuf \ размер буфера чтения, может быть 1-256, ограничено протоколом 6 | size-rBuf 2* VALUE szUBuf \ размер буфера пакетов 7 | 0 VALUE UBuf \ буфер пакетов, внутри которого размещен буфер чтения rBuf 8 | \ буфер (со счетчиком) приема и передачи 9 | szUBuf ALLOCATE THROW TO UBuf 10 | VARIABLE Tred \ количество байт пересылки 11 | 12 | 13 | HEX 14 | \ определители AVRISP_mk2 15 | 03eb CONSTANT AVRISP_mk2_Vid 16 | 2104 CONSTANT AVRISP_mk2_Pid 17 | 18 | 0 VALUE EPin 19 | 0 VALUE EPout 20 | 0 VALUE EPoutSize 21 | 22 | \ 0 VALUE EPout 23 | \ 80 EP# OR VALUE EPin \ libusb 0x82 или для JUNGO 0x83 24 | \ 0 VALUE EPin \ JUNGO 0x83 25 | 26 | 27 | : SetEPoutSize ( endpoint_descriptor -- ) \ установить размер EP 28 | wMaxPacketSize c@ TO EPoutSize 29 | ; 30 | 31 | : SetEpAdr ( ) \ установить адреса конечных точек по дескрипторам 32 | (( dev &CnfDesc )) libusb_get_active_config_descriptor errorUSB 33 | CnfDesc *interface @ @ bNumEndpoints c@ \ количество конечных точек 34 | IF 35 | CnfDesc *interface @ @ *endpoint @ DUP bEndpointAddress C@ \ первый адрес 36 | DUP 0x80 AND IF TO EPin DROP ELSE TO EPout SetEPoutSize THEN 37 | CnfDesc *interface @ @ *endpoint @ libusb_endpoint_descriptor + DUP bEndpointAddress C@ \ второй адрес 38 | DUP 0x80 AND IF TO EPin DROP ELSE TO EPout SetEPoutSize THEN 39 | THEN 40 | ; 41 | 42 | DECIMAL 43 | 44 | 0 TO USB_TIMEOUT 45 | 46 | UBuf szUBuf 0 fill \ очистка буфера 47 | \ UBuf szUBuf dump cr 48 | : >bulk> ( -- ) 49 | EPin 0= IF SetEpAdr THEN 50 | (( hand EPout UBuf Tred @ Tred USB_TIMEOUT )) libusb_bulk_transfer errorusb \ передать 51 | \ нулевой завершающий пакет, если нужно 52 | Tred @ EPoutSize mod 0= if (( hand EPout UBuf 0 Tred USB_TIMEOUT )) libusb_bulk_transfer errorusb then 53 | (( hand EPin UBuf szUBuf Tred USB_TIMEOUT )) libusb_bulk_transfer errorusb \ принять 54 | ; 55 | 56 | : UBuf> ( --) \ передать/принять буфер 57 | >bulk> 58 | ; 59 | : clrbuf ( ) \ чистка буфера 60 | 0 Tred ! ; 61 | : c>buf ( c --) \ запомнить символ 62 | UBuf Tred @ + c! 63 | Tred 1+! 64 | ; 65 | : shwBuf ( ) 66 | UBuf Tred @ dump SPACE Tred @ . 67 | ; 68 | 69 | 70 | 71 | \ осуществить программирование 72 | ProgInterface ISPprog = [IF] S" ~iva/AVR/ISPprog.f" INCLUDED [THEN] 73 | ProgInterface PDIprog = [IF] S" ~iva/AVR/Xprog.f" INCLUDED [THEN] 74 | 75 | AVRISP_mk2_Vid AVRISP_mk2_Pid findUSBprog 76 | EndedLoop <> 77 | [IF] 78 | UBuf FREE THROW \ освободить память 79 | ALLDROP \ и забыть все это 80 | [THEN] 81 | 82 | -------------------------------------------------------------------------------- /CP866.f: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivanivanovo/AVR/58ee10856bcf813c3895b71387ff21304bc7ddea/CP866.f -------------------------------------------------------------------------------- /ISPprog.f: -------------------------------------------------------------------------------- 1 | 2 | S" ~iva/AVR/ISProtocol.f" INCLUDED 3 | 4 | 5 | : cmd>buf ( cmd1 cmd2 cmd3 cmd4 -- ) 6 | >R >R >R c>buf R> c>buf R> c>buf R> c>buf 7 | ; 8 | 9 | : signOn ( ) 10 | clrbuf 11 | CMD_SIGN_ON c>buf 12 | UBuf> 13 | Tred @ 3 > 14 | IF UBuf 3 + Tred @ 3 - TYPE CR THEN 15 | ; 16 | 17 | 18 | :NONAME ( ) \ ввод режима программирования 19 | clrbuf 20 | CMD_ENTER_PROGMODE_ISP c>buf 21 | 200 DUP TO USB_TIMEOUT c>buf \ тамаут команды (ms) 22 | 100 c>buf \ задержка на стабилизацию pin (ms) 23 | 25 c>buf \ задержка на выполнение команды (ms) 24 | 32 c>buf \ количество циклов синхронизации 25 | 0 c>buf \ задержка между байтами (ms) 26 | 0x53 c>buf \ проверочный байт, 0x53-AVR 0x69-AT89xx 27 | 3 c>buf \ номер проверочного байта в ответе, 0-без проверки, 3-AVR, 4-AT89 28 | #Programming_Enable cmd>buf 29 | UBuf> 30 | ProgInterfaceS TYPE CR 31 | ; IS ProgEn \ <====================================================== 32 | 33 | :NONAME ( ) \ выход из режима программирования 34 | clrbuf 35 | CMD_LEAVE_PROGMODE_ISP c>buf 36 | 1 1 c>buf c>buf 37 | UBuf> 38 | ; IS PowerDown \ <====================================================== 39 | 40 | :NONAME ( ) \ очистка чипа 41 | clrbuf 42 | CMD_CHIP_ERASE_ISP c>buf 43 | C" TwdErase" FIND \ таймаут определен? 44 | IF EXECUTE ELSE DROP 20 THEN c>buf 45 | 1 c>buf \ проверочный метод 46 | #Chip_Erase cmd>buf 47 | UBuf> 48 | ." Чип очищен." CR 49 | ; IS EraseChip \ <====================================================== 50 | 51 | :NONAME ( # -- byte ) 52 | clrbuf 53 | CMD_READ_SIGNATURE_ISP c>buf 54 | 4 c>buf 55 | #Read_Signature_Byte cmd>buf 56 | UBuf> 57 | UBuf 2 + c@ 58 | ; IS SignatureByte@ \ <====================================================== 59 | 60 | : LoadAddress ( addr --) \ указать начальный адрес для чтения или записи 61 | \ ." LOAD_ADDRESS: 0x" DUP .HEX cr 62 | AsWord? IF 2/ THEN \ перевести адрес байта в адрес слова 63 | clrbuf 64 | CMD_LOAD_ADDRESS c>buf 65 | |4 c>buf c>buf c>buf c>buf 66 | UBuf> 67 | ; 68 | 69 | FALSE VALUE WritePage? \ флаг готовности к записи страницы 70 | 71 | : ModeByte ( -- ) \ составить байт режима программирования 72 | SizePage 73 | IF \ страничный доступ 74 | 0x41 \ контроль по опросу RDY/BSY 75 | 0x80 WritePage? AND OR 76 | ELSE \ запись по словам или байтам 77 | 2 \ контроль по времени 78 | THEN 79 | c>buf 80 | ; 81 | 82 | : Buf! ( buf sbuf -- n) \ записать буфер 83 | \ cr .S ." <== Buf!!" cr 84 | \ buf - откуда и скока (sbuf) взять 85 | >R ( n) 86 | clrbuf 87 | M_WRITE \ команда записи куда-то 88 | R@ |2 c>buf c>buf \ размер данных 89 | ModeByte 90 | TwP c>buf 91 | SizePage IF PageM! ELSE ByteM! THEN 92 | UBuf Tred @ + R@ CMOVE R@ Tred +! \ положить данные в буфер передачи 93 | \ shwBuf cr 94 | UBuf> 95 | R> 96 | ; 97 | 98 | 99 | 100 | \ ========== FLASH =================================== 101 | \ ['] ByteFlash! IS ByteM! 102 | \ ['] PageFlash! IS PageM! 103 | \ ['] FLASH_WRITE IS M_WRITE 104 | \ ['] FLASH_READ IS M_READ 105 | 106 | :NONAME ( ) 107 | cmd0_Load_Program_Memory_Page c>buf 108 | cmd0_Write_Program_Memory_Page c>buf 109 | cmd0_Read_Program_Memory c>buf 110 | 0 0 c>buf c>buf 111 | ; DUP IS ByteFlash! IS PageFlash! 112 | 113 | :NONAME ( -- ) 114 | CMD_PROGRAM_FLASH_ISP c>buf 115 | ; IS FLASH_WRITE 116 | 117 | :NONAME ( -- n) \ читает память с текущего адреса, возвращает число принятых байт 118 | \ ." FLASH_READ" cr 119 | clrbuf 120 | CMD_READ_FLASH_ISP c>buf 121 | size-rBuf DUP |2 c>buf c>buf 122 | cmd0_Read_Program_Memory c>buf \ Read Program Memory, Low byte 123 | UBuf> ( -- size-rBuf) 124 | ; IS FLASH_READ 125 | 126 | \ ========== EPROM =================================== 127 | \ ['] ByteEPROM! IS ByteM! 128 | \ ['] PageEPROM! IS PageM! 129 | \ ['] EEPROM_WRITE IS M_WRITE 130 | \ ['] EEPROM_READ IS M_READ 131 | 132 | \ DEFER EEPROM_WRITE \ IS M_WRITE 133 | :NONAME ( -- ) 134 | \ .S ." EEPROM_WRITE" CR 135 | CMD_PROGRAM_EEPROM_ISP c>buf 136 | ; IS EEPROM_WRITE 137 | 138 | \ DEFER EEPROM_READ \ IS M_READ 139 | :NONAME ( -- n) \ читает память с текущего адреса, возвращает число принятых байт 140 | \ ." EEPROM_READ" cr 141 | clrbuf 142 | CMD_READ_EEPROM_ISP c>buf 143 | size-rBuf DUP |2 c>buf c>buf 144 | cmd0_Read_EEPROM_Memory c>buf 145 | UBuf> ( -- size-rBuf) 146 | ; IS EEPROM_READ 147 | :NONAME ( ) 148 | \ .S ." PageEPROM!" CR 149 | cmd0_Load_EEPROM_Memory_Page c>buf 150 | cmd0_Write_EEPROM_Memory_Page c>buf 151 | cmd0_Read_EEPROM_Memory c>buf 152 | 0 0 c>buf c>buf 153 | ; IS PageEPROM! 154 | :NONAME ( ) 155 | \ .S ." ByteEPROM!" CR 156 | cmd0_Write_EEPROM_Memory c>buf 157 | 0 c>buf 158 | 0 c>buf 159 | 0 0 c>buf c>buf 160 | ; IS ByteEPROM! 161 | 162 | : chunk ( u - u') \ кусок для записи 163 | DUP size-rbuf > \ не более размера буфера передачи 164 | IF \ остаток для записи больше размера передачи 165 | DROP size-rbuf FALSE \ Не последний пакет 166 | ELSE \ остаток помещается в передачу 167 | TRUE \ последний пакет для записи 168 | THEN TO WritePage? 169 | ; 170 | 171 | :NONAME ( a u adrW -- ) \ прогрузить и записать u байт 172 | \ .S ." 177 | WHILE 178 | 2DUP chunk \ сколько будем писать за раз 179 | Buf! \ загрузить в буфер чипа ( a u n) 180 | >R SWAP R@ + SWAP R> - \ a'=a+n u'=u-n 181 | REPEAT 2DROP \ 182 | \ .S ." >Byte!" CR 183 | ; IS Byte! 184 | :NONAME ( a u adrW -- n) \ прогрузить и записать страницу 185 | \ .S ." Page!" 186 | SWAP SizePage MIN SWAP \ не более станицы 187 | OVER >R Byte! R> 188 | ; IS Page! \ <================================================================= 189 | 190 | :NONAME ( adr -- n) \ читает память с adr, возвращает число принятых байт 191 | \ ." Memo@" cr 192 | LoadAddress 193 | M_READ 194 | szUBuf MIN 195 | UBuf 2 + TO rBuf 196 | ; IS Memo@ \ <============================================================= 197 | 198 | 199 | \ ========== FUSE =================================== 200 | [WITHOUT?] TwdFuse 5 CONSTANT TwdFuse [THEN] 201 | 202 | \ DEFER #Fuse@ ( # -- u) \ прочитать байт № 203 | :NONAME ( # -- u) \ прочитать байт № 204 | clrbuf 205 | CMD_READ_FUSE_ISP c>buf 206 | 4 c>buf 207 | DUP 0 = 208 | IF DROP #Read_Fuse_bits 209 | ELSE DUP 1 = 210 | IF DROP #Read_Fuse_High_bits 211 | ELSE DUP 2 = 212 | IF DROP #Read_Extended_Fuse_bits 213 | ELSE . S" <-Неверный номер #Fuse@." :[ 214 | THEN 215 | THEN 216 | THEN 217 | cmd>buf UBuf> 218 | Tred @ 4 = 219 | IF UBuf 2 + C@ 220 | ELSE S" Не удалось прочитать фузы." :[ 221 | THEN 222 | ; IS #Fuse@ \ <============================================================= 223 | 224 | \ DEFER #Fuse! ( u # -- ) \ записать байт № 225 | :NONAME ( u # -- ) \ записать байт № 226 | 2DUP #Fuse@ <> 227 | IF \ не равны 228 | DUP ." FUSE_" 1 .R ." : " 229 | clrbuf CMD_PROGRAM_FUSE_ISP c>buf 230 | DUP 0 = 231 | IF OVER #Write_Fuse_bits ELSE 232 | DUP 1 = 233 | IF OVER #Write_Fuse_High_bits ELSE 234 | DUP 2 = 235 | IF OVER #Write_Extended_Fuse_bits ELSE 236 | DROP S" <-Неверный номер #Fuse!" :[ 237 | THEN THEN THEN 238 | cmd>buf UBuf> 239 | TwdFuse PAUSE \ время на запись 240 | \ u # 241 | #Fuse@ <> 242 | IF S" Запись не удалась." :[ 243 | ELSE ." изменен" 244 | THEN CR 245 | ELSE 2DROP 246 | THEN 247 | ; IS #Fuse! \ <============================================================= 248 | 249 | 250 | \ ========== LOCK =================================== 251 | \ DEFER LockBits@ ( -- u) 252 | :NONAME ( -- u) 253 | clrbuf 254 | CMD_READ_LOCK_ISP c>buf 255 | 4 c>buf 256 | #Read_Lock_bits cmd>buf 257 | UBuf> 258 | Tred @ 4 = 259 | IF UBuf 2 + C@ 260 | ELSE S" Не удалось прочитать блокировочные биты." :[ THEN 261 | ; IS LockBits@ \ <============================================================ 262 | 263 | \ DEFER LockBits! ( u 0 -- ) 264 | :NONAME ( u 0 -- ) 265 | DROP 266 | clrbuf 267 | CMD_PROGRAM_LOCK_ISP c>buf 268 | #Write_Lock_bits cmd>buf 269 | UBuf> 270 | 10 PAUSE 271 | LockBits@ 272 | ." LOCK MODE:" INVERT 0xFF AND . 273 | CR 274 | ; IS LockBits! \ <============================================================ 275 | 276 | :NONAME ( # -- byte) \ прочитать калибровочный байт # 277 | clrbuf 278 | CMD_READ_OSCCAL_ISP c>buf 279 | 4 c>buf 280 | #Read_Calibration_Byte cmd>buf 281 | UBuf> 282 | UBuf 2 + C@ 283 | ; IS CalibrationByte@ 284 | 285 | 286 | 287 | -------------------------------------------------------------------------------- /ISProtocol.f: -------------------------------------------------------------------------------- 1 | 2 | DECIMAL 3 | \ \ 0 1 2 3 4 | 5 | #def #Programming_Enable 0xAC 0x53 0x00 0x00 6 | #def #Chip_Erase ( Program Memory/EEPROM) 0xAC 0x80 0x00 0x00 7 | #def #RDY/BSY 0xF0 0x00 0x00 0x00 \ =byte out 8 | \ Load Extended Address byte 0x4D 0x00 Ext-adr 0x00 9 | 10 | #def (<->) ( b a c -- c aH aL b) -ROT byte-split SWAP ROT \ чехарда на стеке 11 | 12 | \ Load Program Memory Page, High byte 0x48 adrMSB adrLSB byte 13 | #def #Load_Program_Memory_Page,High_byte ( byte adr -- ) 0x48 (<->) \ byte 14 | \ Load Program Memory Page, Low byte 0x40 adrMSB adrLSB byte 15 | 0x40 CONSTANT cmd0_Load_Program_Memory_Page 16 | #def #Load_Program_Memory_Page,Low_byte ( byte adr -- ) 0x40 (<->) \ byte 17 | \ Write Program Memory Page 0x4C adrMSB adrLSB 0x00 18 | 0x4C CONSTANT cmd0_Write_Program_Memory_Page 19 | #def #Write_Program_Memory_Page ( adrB -- ) 0x4C SWAP byte-split SWAP 0x00 20 | \ Read Program Memory, High byte 0x28 adrMSB adrLSB byte out 21 | \ Read Program Memory, Low byte 0x20 adrMSB adrLSB byte out 22 | 0x20 CONSTANT cmd0_Read_Program_Memory 23 | 24 | 25 | \ Write EEPROM Memory 0xC0 0x00 00aaaaaa byte in 26 | 0xC0 CONSTANT cmd0_Write_EEPROM_Memory 27 | #def #Write_EEPROM_Memory ( byte adr -- ) 0xC0 (<->) \ byte 28 | \ Load EEPROM Memory Page (page access) 0xC1 0x00 0000000aa byte 29 | 0xC1 CONSTANT cmd0_Load_EEPROM_Memory_Page 30 | \ Write EEPROM Memory Page (page access) 0xC2 0x00 00aaaa00 0x00 31 | 0xC2 CONSTANT cmd0_Write_EEPROM_Memory_Page 32 | #def #Write_EEPROM_Memory_Page ( adr -- ) 0xC2 0x00 ROT ( adr) 0x00 33 | \ Read EEPROM Memory 0xA0 0x00 00aaaaaa byte out 34 | 0xA0 CONSTANT cmd0_Read_EEPROM_Memory 35 | 36 | #def #Write_Lock_bits ( b --) 0xAC 0xE0 ROT 0 SWAP \ =byte in 37 | #def #Write_Fuse_bits ( b --) 0xAC 0xA0 ROT 0 SWAP \ =byte in 38 | #def #Write_Fuse_High_bits ( b --) 0xAC 0xA8 ROT 0 SWAP \ =byte in 39 | #def #Write_Extended_Fuse_bits ( b --) 0xAC 0xA4 ROT 0 SWAP \ =byte in 40 | 41 | #def #Read_Lock_bits 0x58 0x00 0x00 0x00 \ =byte out 42 | #def #Read_Signature_Byte ( a -- b) 0x30 0x00 ROT ( a) 0x00 \ =byte out 43 | #def #Read_Fuse_bits 0x50 0x00 0x00 0x00 \ =byte out 44 | #def #Read_Fuse_High_bits 0x58 0x08 0x00 0x00 \ =byte out 45 | #def #Read_Extended_Fuse_bits 0x50 0x08 0x00 0x00 \ =byte out 46 | 47 | #def #Read_Calibration_Byte ( a -- b) 0x38 0x00 ROT ( a) 0x00 \ =byte out 48 | 49 | \ Версия вторая 50 | \ *** [ Константы основных команд ] *** 51 | #def CMD_SIGN_ON 0x01 \ 52 | #def CMD_SET_PARAMETER 0x02 \ 53 | #def CMD_GET_PARAMETER 0x03 \ 54 | #def CMD_OSCCAL 0x05 \ 55 | #def CMD_LOAD_ADDRESS 0x06 \ 56 | #def CMD_FIRMWARE_UPGRADE 0x07 \ 57 | #def CMD_RESET_PROTECTION 0x0A \ 58 | \ *** [ Константы команд ISP ] *** 59 | #def CMD_ENTER_PROGMODE_ISP 0x10 \ 60 | #def CMD_LEAVE_PROGMODE_ISP 0x11 \ 61 | #def CMD_CHIP_ERASE_ISP 0x12 \ 62 | #def CMD_PROGRAM_FLASH_ISP 0x13 \ 63 | #def CMD_READ_FLASH_ISP 0x14 \ 64 | #def CMD_PROGRAM_EEPROM_ISP 0x15 \ 65 | #def CMD_READ_EEPROM_ISP 0x16 \ 66 | #def CMD_PROGRAM_FUSE_ISP 0x17 \ 67 | #def CMD_READ_FUSE_ISP 0x18 \ 68 | #def CMD_PROGRAM_LOCK_ISP 0x19 \ 69 | #def CMD_READ_LOCK_ISP 0x1A \ 70 | #def CMD_READ_SIGNATURE_ISP 0x1B \ 71 | #def CMD_READ_OSCCAL_ISP 0x1C \ 72 | #def CMD_SPI_MULTI 0x1D \ 73 | 74 | \ *** [ Константы состояния ] *** 75 | #def STATUS_CMD_OK 0x00 \ успешное завершение (Success), команда выполнилась успешно. 76 | \ Предупреждения (Warnings) 77 | #def STATUS_CMD_TOUT 0x80 \ Истек таймаут команды. 78 | #def STATUS_RDY_BSY_TOUT 0x81 \ Истек таймаут опроса вывода готовности/занятости (RDY/nBSY pin). 79 | #def STATUS_SET_PARAM_MISSING 0x82 \ Команда установки параметра устройства потерпела ошибку в процессе выполнения. 80 | \ Ошибки (Errors) 81 | #def STATUS_CMD_FAILED 0xC0 \ Команда завершилась с ошибкой. 82 | #def STATUS_CMD_UNKNOWN 0xC9 \ Неизвестная команда. 83 | \ Статус 84 | #def STATUS_ISP_READY 0x00 \ 85 | #def STATUS_CONN_FAIL_MOSI 0x01 \ 86 | #def STATUS_CONN_FAIL_RST 0x02 \ 87 | #def STATUS_CONN_FAIL_SCK 0x04 \ 88 | #def STATUS_TGT_NOT_DETECTED 0x10 \ 89 | #def STATUS_TGT_REVERSE_INSERTED 0x20 \ 90 | \ *** [ Константы параметров ] *** 91 | #def PARAM_BUILD_NUMBER_LOW 0x80 \ Номер сборки firmware, младший байт. R 92 | #def PARAM_BUILD_NUMBER_HIGH 0x81 \ Номер сборки firmware, старший байт. R 93 | #def PARAM_HW_VER 0x90 \ Версия аппаратуры. R 94 | #def PARAM_SW_MAJOR 0x91 \ Номер версии firmware главного управляющего MCU, байт мажор. R 95 | #def PARAM_SW_MINOR 0x92 \ Номер версии firmware главного управляющего MCU, байт минор. R 96 | #def PARAM_VTARGET 0x94 \ Напряжение питания цели (target, программируемый микроконтроллер). RW 97 | #def PARAM_SCK_DURATION 0x98 \ Длительность периода ISP SCK. R 98 | #def PARAM_RESET_POLARITY 0x9E \ Полярность сигнала сброс - на каком логическом уровне он активен, лог. 0 или лог. 1. W 99 | #def PARAM_STATUS_TGT_CONN 0xA1 \ Состояние подключения к target. R 100 | #def PARAM_DISCHARGEDELAY 0xA4 \ Задержка с состоянием сигнала сброса в высоком сопротивлении. W 101 | -------------------------------------------------------------------------------- /KOI8-R.f: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivanivanovo/AVR/58ee10856bcf813c3895b71387ff21304bc7ddea/KOI8-R.f -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AVR 2 | forth-assembler for AVR 3 | 4 | Чтоб воспользоваться этим инструментом: 5 | 1. нужно иметь на компе линукс (у меня Ubuntu) и установленный spf4, разумеется для линукса. 6 | 2. при необходимости скачать папку devel с наработками сообщества spf4. 7 | 3. создать внутри devel папку ~iva и клонировать туда AVR. 8 | 9 | После этого должен нормально собраться пример из папки ~iva/AVR/examples командой: 10 | spf4 1-helloLed.f 11 | 12 | Далее делается по образу и подобию. Основное, что и как делается, описано в файле "Дополнительные команды ассемблер2.odt" 13 | -------------------------------------------------------------------------------- /SFIFO.f: -------------------------------------------------------------------------------- 1 | \ создание и работа со строчными буферами FIFO 2 | \ структура буфера: 3 | \ name--v адрес начала буфера 4 | \ size, idxR, idxW, u[____],u[_________],... 5 | \ \_idxR____/ смещение от адреса idxR до счетчика первой несчитанной строки 6 | \ \_idxW__________________/ смещение от адреса idxW до свободного места 7 | 8 | 4 CELLS CONSTANT costSFIFO \ дополнительный размер для служебного пользования 9 | 10 | : AidxR ( buf -- adr_idxR) 11 | 1 CELLS + 12 | ; 13 | : AidxW ( buf -- adr_idxW) 14 | 2 CELLS + 15 | ; 16 | : clrSFIFO ( buf --) \ очистка буфера 17 | >R 18 | 2 CELLS R@ AidxR ! \ начальное смещение чтения 19 | 1 CELLS R> AidxW ! \ начальное смещение записи 20 | ; 21 | : checkSize ( u buf -- f) \ f=false, если u байт не поместятся в buf 22 | DUP @ \ size 23 | SWAP AidxW @ ROT + 24 | < ABORT" Перполнение буфера SFIFO." 25 | ; 26 | 27 | 28 | 29 | 30 | 31 | 32 | : SFIFO: ( size "name"-- ) \ создание строчного буфера FIFO, размером size 33 | CREATE DUP costSFIFO + ALLOCATE THROW >R 34 | R@ , \ адрес выделенной памяти под буфер 35 | R@ ! \ запомнить size 36 | R> clrSFIFO 37 | ( "name" --> adr) 38 | DOES> @ 39 | ; 40 | 41 | : SFIFO! ( adr u buf -- ) \ положить строку adr u в буфер SFIFO buf 42 | 2DUP checkSize \ проверить возможность записи 43 | ( adr u buf ) 44 | AidxW DUP >R ( adr u adr_idxW) DUP @ + ( adr u adr') ALIGNED 45 | 2DUP ! ( adr u adr') \ записать u 46 | CELL+ 2DUP + >R SWAP CMOVE \ записать в буфер 47 | R> R@ - R> ! \ сдвинуть указатель записи 48 | ; 49 | 50 | : SFIFO@ ( buf -- adr u) \ вернуть очередную строку из буфера, если буфер пуст adr=buf, u=0 51 | DUP AidxR @ \ сравнить указатели 52 | OVER AidxW @ 53 | > 54 | IF DUP clrSFIFO 0 \ буфер пуст 55 | ELSE 56 | AidxR DUP >R @ \ idxR (R:adr_idxR) 57 | R@ + DUP CELL+ SWAP @ \ adr u 58 | 2DUP + R@ - ALIGNED R> ! \ сдвинуть указатель чтения 59 | THEN 60 | ; 61 | 62 | 63 | 64 | \eof 65 | 64 SFIFO: tt 66 | 64 SFIFO: tt1 67 | tt 64 dump cr 68 | hex 69 | S" 12345" tt sfifo! 70 | S" abcdefg" tt sfifo! 71 | tt 40 dump cr cr 72 | tt sfifo@ type 73 | tt 40 dump cr cr 74 | tt sfifo@ type 75 | tt 40 dump cr 76 | -------------------------------------------------------------------------------- /STK500.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivanivanovo/AVR/58ee10856bcf813c3895b71387ff21304bc7ddea/STK500.pdf -------------------------------------------------------------------------------- /USB01.f: -------------------------------------------------------------------------------- 1 | 2 | \ минимальная реализация работы с USB 3 | [WITHOUT?] USB_TYPE_STANDARD S" ~iva/AVR/USB_const.f" INCLUDED [THEN] 4 | 5 | DECIMAL 6 | 7 | USE libusb-0.1.so.4 \ libusb.so \ используем библиотеку libusb 0.1 8 | 9 | \ usb_init(); \ инициализирует USB библиотеку 10 | \ usb_find_busses(); \ ищет все доступные USB шины, возвращает число изменений в подключениях с последнего вызова функции 11 | \ usb_find_devices(); \ ищет все доступные USB устройства, возвращает число изменений в подключениях с последнего вызова функции 12 | \ usb_open(*dev) \ возвращает ручку устройства 13 | \ usb_close(*udev) \ закрывает устройство, 0 - нормально, <0 - ошибка 14 | \ usb_control_msg(ручка, тип_запроса, код_запроса, значение, индекс, адрес_буфера, размер_буфера, таймаут) \ посылка управляющего сообщения, возвращает число записаных/считаных байт, если <0 - ошибка 15 | \ int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout); 16 | \ usb_strerror() \ возвращает строку ASCIIZ с описанием ошибки 17 | \ 18 | 0 VALUE hdev \ ручка программатора 19 | 20 | 21 | : printErrorUSB ( ) 22 | (( )) usb_strerror ASCIIZ> TYPE CR 0 TO hdev ; 23 | 24 | : initUSB ( -- *bus) \ инициализирует библиотеку, ищет шины и устройства, 25 | \ возвращает адрес структуры usb_bus 26 | (( )) usb_init DROP \ 0< IF ." init:" printErrorUSB ABORT THEN 27 | (( )) usb_find_busses DROP \ 0< IF ." bus:" printErrorUSB ABORT THEN 28 | (( )) usb_find_devices DROP \ 0< IF ." dev:" printErrorUSB ABORT THEN 29 | (( )) usb_get_busses \ возвращает адрес структуры usb_bus 30 | \ DUP 0< IF ." getBus:" printErrorUSB ABORT THEN 31 | ; 32 | \ ползанье по структурам 33 | : .next ( *bus|*devices -- *bus'|*devices'|0) @ ; \ адрес следующей структуры 34 | : .prev ( *bus|*devices -- *bus'|*devices'|0) CELL+ @ ; \ адрес предыдущей структуры 35 | : .name ( *bus|*devices -- *str) \ адрес строки 36 | 2 CELLS + ; 37 | : maxLenStr ( -- u ) \ максимальная длина строки 38 | PATH_MAX 1+ ; 39 | : .devices ( *bus -- *devices) \ адрес структуры devices 40 | .name maxLenStr + ALIGNED @ ; 41 | : .descriptor ( *dev -- *descriptor) \ адрес дескриптора из структуры dev 42 | .name maxLenStr + ALIGNED CELL+ ; 43 | : .idVendor ( *dev -- u ) \ VID в структуре dev.descriptor 44 | 8 + W@ ; 45 | : .idProduct ( *dev -- u ) \ PID в структуре dev.descriptor 46 | 10 + W@ ; 47 | 48 | 0 value BusName 49 | : findDevice ( .idVendor .idProduct -- dev|0) \ искать устройство по id 50 | 2>R ( R: .idVendor .idProduct ) 51 | initUSB ( *bus) 52 | BEGIN DUP \ цикл по всем шинам 53 | DUP .name to BusName 54 | .devices ( *bus *devices) 55 | BEGIN DUP \ цикл по всем устройствам на шине 56 | \ cr ." bus: " BusName ASCIIZ> type DUP ." dev: " .name ASCIIZ> type 57 | .descriptor 58 | DUP .idVendor SWAP .idProduct \ получить .idVendor и .idProduct 59 | \ ." VID/PID: " OVER .hex ." /" DUP .hex 60 | 2R@ ROT = -ROT = AND \ сравнить с искомыми 61 | IF 2R> 2DROP NIP EXIT THEN \ НАЙДЕН 62 | .next ?DUP 63 | WHILE \ cr ." --dev" 64 | REPEAT 65 | .next DUP 66 | WHILE \ cr ." ==bus" 67 | REPEAT 2R> 2DROP ; \ НЕ найден 68 | -------------------------------------------------------------------------------- /USB1.f: -------------------------------------------------------------------------------- 1 | 2 | \ минимальная реализация работы с libUSB-1.0 3 | [WITHOUT?] USB_TYPE_STANDARD S" ~iva/AVR/USB_const.f" INCLUDED [THEN] 4 | [WITHOUT?] LIBUSB_LOG_LEVEL_INFO S" ~iva/AVR/libusbx_structures.f" INCLUDED [THEN] 5 | 6 | DECIMAL 7 | \ USE libusb-1.0.so.0 \ используем библиотеку libusb 1.0 8 | USE libusb-1.0.so \ используем библиотеку libusb 1.0 9 | VARIABLE &ctx 0 &ctx ! \ переменная контекст 10 | #def ctx &ctx @ 11 | VARIABLE &listDev \ переменная указывающая на список USB устройств в системе 12 | #def listDev &listDev @ 13 | VARIABLE &hand 14 | #def hand &hand @ 15 | VARIABLE &CnfDesc 16 | #def CnfDesc &CnfDesc @ 17 | 18 | 19 | 0 VALUE USB_TIMEOUT \ No default USB Timeout 20 | LIBUSB_LOG_LEVEL_INFO VALUE dbgLevel \ отладочный уровень 21 | 22 | libusb_device_descriptor ALLOCATE THROW VALUE DevDesc \ взяли память из кучи под один экземпляр struct 23 | 24 | \ libusb_config_descriptor ALLOCATE THROW VALUE CnfDesc \ взяли память из кучи под один экземпляр struct 25 | \ libusb_interface_descriptor ALLOCATE THROW VALUE InDesc \ взяли память из кучи под один экземпляр struct 26 | \ 27 | \ 0 28 | \ CELL -- *altsetting \ указатель на массив struct libusb_interface_descriptor 29 | \ CELL -- num_altsetting 30 | \ CONSTANT libusb_interface 31 | \ libusb_interface ALLOCATE THROW VALUE interface \ взяли память из кучи под один экземпляр struct 32 | \ libusb_endpoint_descriptor ALLOCATE THROW VALUE EpDesc \ взяли память из кучи под один экземпляр struct 33 | \ 34 | \ (( &ctx )) libusb_init DROp \ libusb_init(&ctx); 35 | \ (( ctx &listDev )) libusb_get_device_list \ count = libusb_get_device_list(ctx, &listDev) 36 | \ cr . cr 37 | \ \ libusb_get_device_descriptor(device, &desc) 38 | \ desc libusb_device_descriptor dump 39 | \ cr 40 | 41 | : errorUSB ( u -- ) \ обработка ошибок 42 | ?DUP LIBUSB_SUCCESS = IF EXIT THEN 43 | DUP LIBUSB_ERROR_IO = ABORT" libusb - ошибка ввода-вывода." 44 | DUP LIBUSB_ERROR_INVALID_PARAM = ABORT" libusb - неверные параметры." 45 | DUP LIBUSB_ERROR_ACCESS = ABORT" libusb - отказано в доступе." 46 | DUP LIBUSB_ERROR_NO_DEVICE = ABORT" libusb - устройство отключено." 47 | DUP LIBUSB_ERROR_NOT_FOUND = ABORT" libusb - объект не найден." 48 | DUP LIBUSB_ERROR_BUSY = ABORT" libusb - ресурс занят." 49 | DUP LIBUSB_ERROR_TIMEOUT = ABORT" libusb - время вышло." 50 | DUP LIBUSB_ERROR_OVERFLOW = ABORT" libusb - переполнение приемного буфера." 51 | DUP LIBUSB_ERROR_PIPE = ABORT" libusb - ошибка канала." 52 | DUP LIBUSB_ERROR_INTERRUPTED = ABORT" libusb - операция прервана." 53 | DUP LIBUSB_ERROR_NO_MEM = ABORT" libusb - нехватает памяти." 54 | DUP LIBUSB_ERROR_NOT_SUPPORTED = ABORT" libusb - неизвестная ошибка." 55 | ABORT" libusb - неизвестная ошибка." 56 | ; 57 | : tickErr ( n - n) \ выделить ошибки 58 | DUP 0< IF errorUSB then 59 | ; 60 | : initUSB ( -- u) \ начало работы с библиотекой 61 | \ u=число обнаруженных устройств 62 | ctx 0= 63 | if (( &ctx )) libusb_init errorUSB 64 | (( ctx dbgLevel )) libusb_set_debug DROP \ включить отладочную информацию 65 | then 66 | (( ctx &listDev )) libusb_get_device_list \ получить список всех устройств 67 | ; 68 | 69 | : findDevice ( .idVendor .idProduct -- dev|0) \ искать первое устройство с указанными id 70 | initUSB 71 | IF ctx -ROT 3 <( )) libusb_open_device_with_vid_pid 72 | ELSE 0 THEN 73 | ; 74 | 0 VALUE dev \ текущее устройство 75 | VARIABLE VPid VARIABLE _Vid \ Vid Pid в одном флаконе 76 | CREATE ListDevs 16 CELLS ALLOT \ мешок искомых устройств 77 | 78 | : findDevices ( .idVendor .idProduct -- n|0) \ искать все устройства по id 79 | VPid 2! 80 | 0 initUSB 81 | 0 ?DO \ цикл по найденым устройствам 82 | listDev I CELLS + @ TO dev 83 | (( dev DevDesc )) libusb_get_device_descriptor errorUSB 84 | \ I . DevDesc DUP idVendor w@ .hex ." /" idProduct w@ .hex dev 6 cells + @ . 85 | DevDesc idVendor w@ DevDesc idProduct w@ 86 | VPid 2@ D= 87 | IF dev OVER CELLS ListDevs + ! 1+ \ положить устройство в мешок 88 | THEN 89 | LOOP 90 | ; 91 | 92 | : devs ( # -- dev|0) \ достать устройство # из мешка 93 | CELLS listDevs + @ 94 | ; 95 | 96 | :NONAME 97 | (( hand )) libusb_close errorUSB \ закрыть 98 | ; IS closeUsbDev 99 | 100 | : usb_control> ( reqid val index -- n) 101 | >R >R >R 102 | hand \ ручка 103 | EPread \ тип запроса 104 | 2 <( R> R> R> rbuf size-rbuf USB_TIMEOUT )) libusb_control_transfer tickErr 105 | \ код запроса 106 | \ значение 107 | \ индекс 108 | ; 109 | 110 | 0x63 NEGATE CONSTANT EndedLoop 111 | 112 | : RunUSBprog ( -- err ) \ 113 | \ err - код завершения chip!! 114 | (( dev &hand )) libusb_open errorUSB \ открыть 115 | ." Programmer: " 116 | hand DevDesc iProduct w@ 2 <( pad 20 )) libusb_get_string_descriptor_ascii tickErr 117 | PAD SWAP TYPE ." - " \ выдать имя программатора 118 | 119 | ['] chip!! CATCH DUP 0= \ попробовать его использовать 120 | IF (( hand )) libusb_close errorUSB THEN \ закрыть 121 | ; 122 | 123 | ( jjjiikk; 124 | ) 125 | : findUSBprog ( vid pid -- err) \ ищет USB-програматоры 126 | 0 -ROT \ код завершения по умолчанию 127 | VPid 2! 128 | USBdevs 0 129 | ?DO 130 | listDev I CELLS + @ TO dev 131 | (( dev DevDesc )) libusb_get_device_descriptor errorUSB 132 | DevDesc idVendor w@ DevDesc idProduct w@ 133 | VPid 2@ D= 134 | IF 135 | RunUSBprog \ отработать по найденному устройству 136 | EndedLoop = IF DROP EndedLoop LEAVE THEN \ досрочный выход по требованию 137 | THEN 138 | LOOP 139 | ; 140 | 141 | \eof 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | \ 0x403 0x6001 finddevices .( Найдено FTDI: ) . cr \ FTDI 152 | \ 0x1781 0x0c9f finddevices .( Найдено usbTiny: ) . cr \ usbTiny 153 | .( ====================================== ) cr 154 | 0x03eb 0x2104 finddevices .( Найдено: ) . .( AVR ISP mkII )cr \ AVR ISP mkII 155 | (( 0 devs &hand )) libusb_open errorUSB \ открыть из мешка 156 | \ (( hand 2 ubuf 8 tred 50 )) libusb_bulk_transfer errorUSB ubuf 10 dump cr tred @ . cr 157 | \ (( hand 82 ubuf 8 tred 50 )) libusb_bulk_transfer errorUSB ubuf 10 dump cr tred @ . cr 158 | 159 | 160 | 161 | \eof 162 | (( 0 devs devdesc )) libusb_get_device_descriptor errorUSB devdesc idVendor w@ .hex 163 | (( ctx LIBUSB_LOG_LEVEL_INFO )) libusb_set_debug 164 | (( 0 devs )) libusb_get_device_speed . \ узнать скорость 165 | (( 1 devs )) libusb_get_device_address . \ узнать адрес 166 | 167 | (( dev &hand )) libusb_open errorUSB \ открыть 168 | (( 0 devs &hand )) libusb_open errorUSB \ открыть из мешка 169 | (( hand 0 )) libusb_kernel_driver_active tickErr . \ проверить наличие системного драйвера на интерфейсе 0 170 | (( hand true )) libusb_set_auto_detach_kernel_driver errorUSB \ автоотключение-подключение системного драйвера 171 | 172 | (( hand )) libusb_reset_device errorUSB 173 | 174 | (( hand 2 pad 1 pad 50 )) libusb_bulk_transfer errorUSB 175 | (( hand 2 UBuf 8 tred 50 )) libusb_bulk_transfer errorUSB 176 | 177 | (( hand )) libusb_close errorUSB \ закрыть 178 | 179 | (( list )) libusb_free_device_list . 180 | 181 | (( ctx )) libusb_exit . 182 | -------------------------------------------------------------------------------- /USB_const.f: -------------------------------------------------------------------------------- 1 | \ констатнты и структуры USB 2 | \ книга: 3 | \ Агуров П.В. Интерфейсы USB. Практика использования и программирования. --СПб.: БХВ-Петербург, 2004. - 576с.:ил. 4 | \ ISBN 5-94157-202-6 5 | DECIMAL 6 | 4096 CONSTANT PATH_MAX \ из linux/limits.h 7 | 8 | HEX 9 | 10 | \ стандартные типы дескрипторов 11 | 0001 CONSTANT USB_DEVICE_DESCRIPTOR_TYPE \ стандартный дескриптор устройства 12 | 0002 CONSTANT USB_CONFIGURATION_DESCRIPTOR_TYPE \ стандартный дескриптор конфигурации 13 | 0003 CONSTANT USB_STRING_DESCRIPTOR_TYPE \ стандартный дескриптор строки 14 | 0004 CONSTANT USB_INTERFACE_DESCRIPTOR_TYPE \ стандартный дескриптор интерфейса 15 | 0005 CONSTANT USB_ENDPOINT_DESCRIPTOR_TYPE \ стандартный дескриптор конечной точки 16 | 17 | \ дополнительные типы дескрипторов 18 | 0006 CONSTANT DEVICE_QUALIFIER \ уточняющий дескриптор устройства 19 | 0007 CONSTANT OTHER_SPEED_CONFIGURATION \ дескриптор дополнительной конфигурации 20 | 0008 CONSTANT INTERFACE_POWER \ дескриптор управления питанием интерфейса 21 | 0009 CONSTANT OTG \ дескриптор OTG 22 | 000A CONSTANT DEBUG \ дескриптор отладочный 23 | 000B CONSTANT INTERFACE_ASSOCIATION \ дополнительный дескриптор интерфейса 24 | 25 | \ Тип запроса, битовая маска 26 | \ bmRequestType 1 байт [7..0] \ согласно Агуров стр.97 27 | \ [7] направление передачи 28 | 0080 CONSTANT USB_ENDPOINT_IN \ от устройства к хосту 29 | 0000 CONSTANT USB_ENDPOINT_OUT \ от хоста к устройству 30 | \ [6:5] коды типа запросов 31 | 0000 CONSTANT USB_TYPE_STANDARD \ (0x00 << 5) стандартный запрос 32 | 0020 CONSTANT USB_TYPE_CLASS \ (0x01 << 5) специфический запрос для данного класса 33 | 0040 CONSTANT USB_TYPE_VENDOR \ (0x02 << 5) специфический запрос изготовителя 34 | 0060 CONSTANT USB_TYPE_RESERVED \ (0x03 << 5) зарезервирован 35 | \ [4:0] код получателя 36 | 0000 CONSTANT USB_RECIP_DEVICE \ устройство 37 | 0001 CONSTANT USB_RECIP_INTERFACE \ интерфейс 38 | 0002 CONSTANT USB_RECIP_ENDPOINT \ конечная точка 39 | 0003 CONSTANT USB_RECIP_OTHER \ другой 40 | 41 | \ Коды запросов 42 | \ Стандартные запросы 43 | 0000 CONSTANT USB_REQ_GET_STATUS \ см. Агуров стр.97 44 | 0001 CONSTANT USB_REQ_CLEAR_FEATURE 45 | \ 0x02 зарезервировано 46 | 0003 CONSTANT USB_REQ_SET_FEATURE 47 | \ 0x04 зарезервировано 48 | 0005 CONSTANT USB_REQ_SET_ADDRESS 49 | 0006 CONSTANT USB_REQ_GET_DESCRIPTOR 50 | 0007 CONSTANT USB_REQ_SET_DESCRIPTOR 51 | 0008 CONSTANT USB_REQ_GET_CONFIGURATION 52 | 0009 CONSTANT USB_REQ_SET_CONFIGURATION 53 | 000A CONSTANT USB_REQ_GET_INTERFACE 54 | 000B CONSTANT USB_REQ_SET_INTERFACE 55 | 000C CONSTANT USB_REQ_SYNCH_FRAME 56 | 57 | USB_ENDPOINT_IN USB_TYPE_VENDOR OR USB_RECIP_DEVICE OR CONSTANT EPread 58 | USB_ENDPOINT_OUT USB_TYPE_VENDOR OR USB_RECIP_DEVICE OR CONSTANT EPwrite 59 | 60 | \ дескрипторы начинаются как правило одинаково, вот это начало и вынесено отдельно, 61 | \ что бы не повторяться 62 | \ типичное начало дескрипторов 63 | 0 64 | 1 -- bLength \ размер этого дескриптора в байтах 65 | 1 -- bDescriptorType \ тип дескриптора (USB_xx_DESCRIPTOR_TYPE) 66 | CONSTANT head_usb_descriptor 67 | 68 | \ типичное начало длинных дескрипторов 69 | head_usb_descriptor 70 | 2 -- wTotalLength \ общий объем данных (в байтах) возвращаемый для данного дескриптора 71 | CONSTANT head_usb_long_descriptor 72 | 73 | 74 | 75 | \ стандартный дескриптор USB устройства 76 | head_usb_descriptor 77 | 2 -- bcdUSB \ номер верси спецификации USB в формате BCD 78 | 1 -- bDeviceClass \ код класса USB-устройства 79 | 1 -- bDeviceSubClass \ код подкласса USB-устройства 80 | 1 -- bDeviceProtocol \ код протокола USB-устройства 81 | 1 -- bMaxPacketSize0 \ максимальный размер пакета для нулевой конечной точки 82 | 2 -- idVendor \ идентификатор производителя 83 | 2 -- idProduct \ идентификатор продукта 84 | 2 -- bcdDevice \ номер версии USB-устройства в формате BCD 85 | 1 -- iManufacturer \ индекс дескриптора строки, описывающей изготовителя 86 | 1 -- iProduct \ индекс дескриптора строки, описывающей продукт 87 | 1 -- iSerialNumber \ индекс дескриптора строки, содержащей серийный номер USB-устройства 88 | 1 -- bNumConfigurations \ количество возможных конфигураций USB-устройства 89 | CONSTANT usb_device_descriptor 90 | 91 | \ стандартный дескриптор конфигурации USB 92 | head_usb_long_descriptor 93 | 1 -- bNumInterfaces \ количество интерфейсов, поддерживаемой данной конфигурации 94 | 1 -- bConfigurationValue \ идентификатор конфигурации, используемой при вызове SET_CONFIGURATION для установки данной конфигурации 95 | 1 -- iConfiguration \ индекс дескриптора строки, описывающей данную конфигурацию 96 | 1 -- bmAttributes \ характеристики конфигурации 97 | 1 -- MaxPower \ код мощности (квант=2мА), потребляемой USB-устройством от шины 98 | CONSTANT usb_config_descriptor 99 | 100 | \ стандартный дескриптор интерфейса USB 101 | head_usb_descriptor 102 | 1 -- bInterfaceNumber \ номер данного интерфейса (нумеруется с 0) в наборе интерфейсов, поддерживаемых в данной конфигурации 103 | 1 -- bAlternateSetting \ альтернативный номер интерфейса 104 | 1 -- bNumEndpoints \ число конечных точек для этого интерфейса без учета нулевой конечной точки 105 | 1 -- bInterfaceClass \ код класса интерфейса 106 | 1 -- bInterfaceSubClass \ код подкласса интерфейса 107 | 1 -- bInterfaceProtocol \ код протокола интерфейса 108 | 1 -- iInterface \ индекс дескриптора строки, описывающейинтерфейс 109 | CONSTANT usb_interface_descriptor 110 | 111 | \ стандартный дескриптор USB конечной точки 112 | head_usb_descriptor 113 | 1 -- bEndpointAddress \ код адреса конечной точки 114 | 1 -- bAttributes \ атрибуты конечной точки 115 | 2 -- wMaxPacketSize \ максимальный размер пакета для конечной точки 116 | 1 -- bInterval \ интервал опроса (в миллисекундах) конечной точки при передачи данных 117 | CONSTANT usb_endpoint_descriptor 118 | 119 | \ дескриптор строки 120 | head_usb_descriptor 121 | 80 2* -- bString \ строка из N байт или N/2 символов Unicode 122 | CONSTANT usb_string_descriptor 123 | 124 | 125 | DECIMAL 126 | -------------------------------------------------------------------------------- /WIN1251.f: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivanivanovo/AVR/58ee10856bcf813c3895b71387ff21304bc7ddea/WIN1251.f -------------------------------------------------------------------------------- /XPROGprotocol.f: -------------------------------------------------------------------------------- 1 | 2 | DECIMAL 3 | 0x50 CONSTANT CMD_XPROG \ 4 | 0x51 CONSTANT CMD_XPROG_SETMODE \ 5 | \ Команды XPROMG 6 | 0x01 CONSTANT XPRG_CMD_ENTER_PROGMODE 7 | 0x02 CONSTANT XPRG_CMD_LEAVE_PROGMODE 8 | 0x03 CONSTANT XPRG_CMD_ERASE 9 | 0x04 CONSTANT XPRG_CMD_WRITE_MEM 10 | 0x05 CONSTANT XPRG_CMD_READ_MEM 11 | 0x06 CONSTANT XPRG_CMD_CRC 12 | 0x07 CONSTANT XPRG_CMD_SET_PARAM 13 | \ Типы памяти 14 | 1 CONSTANT XPRG_MEM_TYPE_APPL 15 | 2 CONSTANT XPRG_MEM_TYPE_BOOT 16 | 3 CONSTANT XPRG_MEM_TYPE_EEPROM 17 | 4 CONSTANT XPRG_MEM_TYPE_FUSE 18 | 5 CONSTANT XPRG_MEM_TYPE_LOCKBITS 19 | 6 CONSTANT XPRG_MEM_TYPE_USERSIG 20 | 7 CONSTANT XPRG_MEM_TYPE_PRODSIG 21 | 22 | 8 CONSTANT XPRG_MEM_TYPE_DATAMEM 23 | 24 | \ Типы очистки 25 | 1 CONSTANT XPRG_ERASE_CHIP 26 | 2 CONSTANT XPRG_ERASE_APP 27 | 3 CONSTANT XPRG_ERASE_BOOT 28 | 4 CONSTANT XPRG_ERASE_EEPROM 29 | 5 CONSTANT XPRG_ERASE_APP_PAGE 30 | 6 CONSTANT XPRG_ERASE_BOOT_PAGE 31 | 7 CONSTANT XPRG_ERASE_EEPROM_PAGE 32 | 8 CONSTANT XPRG_ERASE_USERSIG 33 | \ Флаги режима записи 34 | \ 0 CONSTANT XPRG_MEM_WRITE_ERASE 35 | \ 1 CONSTANT XPRG_MEM_WRITE_WRITE 36 | \ Типы CRC 37 | 1 CONSTANT XPRG_CRC_APP 38 | 2 CONSTANT XPRG_CRC_BOOT 39 | 3 CONSTANT XPRG_CRC_FLASH 40 | \ \ Коды ошибки 41 | \ 0 CONSTANT XPRG_ERR_OK 42 | \ 1 CONSTANT XPRG_ERR_FAILED 43 | \ 2 CONSTANT XPRG_ERR_COLLISION 44 | \ 3 CONSTANT XPRG_ERR_TIMEOUT 45 | \ \ Параметры XPROG разного размера 46 | \ \ 4-байтные адреса 47 | \ 0x01 CONSTANT XPRG_PARAM_NVMBASE 48 | \ \ 2-байтный размер страницы 49 | \ 0x02 CONSTANT XPRG_PARAM_EEPPAGESIZE 50 | \ 0x03 CONSTANT XPRG_PARAM_NVMCMD_REG 51 | \ 0x04 CONSTANT XPRG_PARAM_NVMCSR_REG 52 | \ 0x05 CONSTANT XPRG_PARAM_UNKNOWN_1 53 | 54 | 0x00 CONSTANT XPRG_PROTOCOL_PDI 55 | 0x01 CONSTANT XPRG_PROTOCOL_JTAG 56 | 0x02 CONSTANT XPRG_PROTOCOL_TPI 57 | 58 | \ 2 CONSTANT XPRG_PAGEMODE_WRITE \ (1 << 1) 59 | \ 1 CONSTANT XPRG_PAGEMODE_ERASE \ (1 << 0) 60 | -------------------------------------------------------------------------------- /Xprog.f: -------------------------------------------------------------------------------- 1 | 2 | S" XPROGprotocol.f" INCLUDED 3 | 4 | 0x0800000 CONSTANT PDI_Flash_Base \ смещение флеш памяти в пространстве PDI 5 | 0x08C0000 CONSTANT PDI_EPPROM_Base 6 | 0x08E0200 CONSTANT PDI_Prod_Signature_Base 7 | 0x08E0400 CONSTANT PDI_User_Signature_Base 8 | 0x08F0020 CONSTANT PDI_Fuse_Base 9 | 0x1000000 CONSTANT PDI_Data_Mem_Base 10 | 11 | \ : ErrorS. ( u --) \ обработать ошибки 12 | \ ?DUP 13 | \ IF 14 | \ DUP XPRG_ERR_FAILED = IF S" Команда завершилась с ошибкой" THEN 15 | \ DUP XPRG_ERR_COLLISION = IF S" Коллизия" THEN 16 | \ DUP XPRG_ERR_TIMEOUT = IF S" Таймаут истек" THEN 17 | \ TYPE CR THROW 18 | \ THEN 19 | \ ; 20 | : XprogErr? ( -- u ) \ проверить статус завершения команды 21 | UBuf 2+ C@ 22 | ; 23 | : XPROG_SETMODE \ установить режим программирования 24 | clrbuf 25 | CMD_XPROG_SETMODE c>buf 26 | ProgInterface PDIprog = IF XPRG_PROTOCOL_PDI ELSE 27 | ProgInterface TPIprog = IF XPRG_PROTOCOL_TPI ELSE 28 | TRUE ABORT" Выбранный протокол не поддерживается." 29 | THEN THEN c>buf 30 | UBuf> 31 | UBuf 1+ C@ ABORT" Не удалось установить режим программирования" 32 | 33 | ; 34 | 35 | :NONAME ( ) \ ввод режима программирования 36 | XPROG_SETMODE 37 | clrbuf 38 | CMD_XPROG c>buf 39 | XPRG_CMD_ENTER_PROGMODE c>buf 40 | UBuf> 41 | XprogErr? ABORT" Не удалось войти войти в режим программирования" 42 | ProgInterfaceS TYPE CR 43 | ; IS ProgEn \ <====================================================== 44 | 45 | :NONAME ( ) \ выход из режима программирования 46 | clrbuf 47 | CMD_XPROG c>buf 48 | XPRG_CMD_LEAVE_PROGMODE c>buf 49 | UBuf> 50 | ; IS PowerDown \ <====================================================== 51 | 52 | : PDIoffset ( adr mem -- adr') \ преревести адрес в пространство PDI 53 | DUP XPRG_MEM_TYPE_APPL = IF PDI_Flash_Base ELSE 54 | DUP XPRG_MEM_TYPE_BOOT = IF PDI_Flash_Base BOOT.START + ELSE 55 | DUP XPRG_MEM_TYPE_EEPROM = IF PDI_EPPROM_Base ELSE 56 | DUP XPRG_MEM_TYPE_FUSE = IF PDI_Fuse_Base ELSE 57 | DUP XPRG_MEM_TYPE_LOCKBITS = IF PDI_Fuse_Base FUSE.SIZE + 1+ ELSE 58 | DUP XPRG_MEM_TYPE_USERSIG = IF PDI_User_Signature_Base ELSE 59 | DUP XPRG_MEM_TYPE_PRODSIG = IF PDI_Prod_Signature_Base ELSE 60 | DUP XPRG_MEM_TYPE_DATAMEM = IF PDI_Data_Mem_Base ELSE 61 | TRUE ABORT" Неизвестный тип памяти" 62 | THEN THEN THEN THEN THEN THEN THEN THEN 63 | NIP + 64 | ; 65 | : ErasedMem? ( erase -- typeMem ) \ определить тип стираемой памяти 66 | DUP XPRG_ERASE_CHIP = IF XPRG_MEM_TYPE_APPL ELSE 67 | DUP XPRG_ERASE_APP = IF XPRG_MEM_TYPE_APPL ELSE 68 | DUP XPRG_ERASE_BOOT = IF XPRG_MEM_TYPE_BOOT ELSE 69 | DUP XPRG_ERASE_EEPROM = IF XPRG_MEM_TYPE_EEPROM ELSE 70 | DUP XPRG_ERASE_APP_PAGE = IF XPRG_MEM_TYPE_APPL ELSE 71 | DUP XPRG_ERASE_BOOT_PAGE = IF XPRG_MEM_TYPE_BOOT ELSE 72 | DUP XPRG_ERASE_EEPROM_PAGE = IF XPRG_MEM_TYPE_EEPROM ELSE 73 | DUP XPRG_ERASE_USERSIG = IF XPRG_MEM_TYPE_USERSIG ELSE 74 | TRUE ABORT" Непонятный тип памяти" 75 | THEN THEN THEN THEN THEN THEN THEN THEN 76 | NIP 77 | ; 78 | : ReadMem ( adr u mem -- adr' u ) 79 | \ adr - откуда читать, u - сколько, mem - тип памяти 80 | \ adr' - адрес куда положено прочитанное 81 | clrbuf CMD_XPROG c>buf XPRG_CMD_READ_MEM c>buf 82 | DUP >R c>buf \ тип памяти 83 | SWAP R> PDIoffset 84 | |4 c>buf c>buf c>buf c>buf \ адрес в чипе 85 | DUP |2 c>buf c>buf \ размер 86 | UBuf> XprogErr? ABORT" Не удалось прочитать из памяти." 87 | UBuf 3 + SWAP 88 | ; 89 | : EraseMem ( adr erase -- ) \ стирание заданной памяти 90 | clrbuf CMD_XPROG c>buf XPRG_CMD_ERASE c>buf 91 | DUP c>buf \ тип стираемой памяти 92 | ErasedMem? PDIoffset |4 c>buf c>buf c>buf c>buf \ адрес в чипе 93 | UBuf> XprogErr? ABORT" Стирка не задалась." 94 | ; 95 | 0 CONSTANT ModeLoadPage 96 | 2 CONSTANT ModeWritePage 97 | ModeLoadPage VALUE PageMode \ запись станицы при 2 или 3 98 | : WriteMem ( adr u adrW mem -- ) \ записать в mem по adr u байт 99 | clrbuf CMD_XPROG c>buf XPRG_CMD_WRITE_MEM c>buf 100 | DUP >R c>buf \ тип памяти 101 | PageMode c>buf \ битовое поля работы со страницей 102 | R> PDIoffset |4 c>buf c>buf c>buf c>buf \ адрес PDI 103 | ( adr u ) 104 | DUP |2 c>buf c>buf \ размер 105 | TUCK UBuf Tred @ + SWAP CMOVE Tred +! 106 | \ shwbuf cr 107 | UBuf> XprogErr? ABORT" Запись чой-то не задалась." 108 | ; 109 | 110 | :NONAME ( ) \ стирание чипа 111 | 0 XPRG_ERASE_CHIP EraseMem 112 | C" TwdErase" FIND \ таймаут определен? 113 | IF EXECUTE ELSE DROP 20 THEN 114 | PAUSE ." Чип очищен." CR 115 | ; IS EraseChip 116 | \ ========== CRC ===================================== 117 | : memCRC ( mem -- CRC) \ подсчет CRC памяти 118 | clrbuf CMD_XPROG c>buf XPRG_CMD_CRC c>buf 119 | c>buf 120 | UBuf> XprogErr? ABORT" Ошибка чтения CRC" 121 | UBuf 3 + @ 122 | ; 123 | 124 | \ ========== FLASH =================================== 125 | \ ['] ByteFlash! IS ByteM! 126 | \ ['] PageFlash! IS PageM! 127 | \ ['] FLASH_WRITE IS M_WRITE 128 | :NONAME ( ) 129 | XPRG_MEM_TYPE_APPL 130 | ; IS FLASH_WRITE 131 | \ ['] FLASH_READ IS M_READ 132 | :NONAME ( adr -- adr' n) \ читать EPROM с адреса adr 133 | size-rBuf XPRG_MEM_TYPE_APPL ReadMem 134 | ; IS FLASH_READ 135 | 136 | VARIABLE TmpByte \ адрес записываемого байта 137 | 138 | \ WriteMem ( adr u adrW mem -- ) 139 | 140 | \ ========== EPROM =================================== 141 | \ ['] ByteEPROM! IS ByteM! 142 | \ ['] PageEPROM! IS PageM! 143 | \ ['] EEPROM_WRITE IS M_WRITE 144 | :NONAME ( ) 145 | XPRG_MEM_TYPE_EEPROM 146 | ; IS EEPROM_WRITE 147 | \ ['] EEPROM_READ IS M_READ 148 | :NONAME ( adr -- adr' n) \ читать EPROM с адреса adr 149 | size-rBuf XPRG_MEM_TYPE_EEPROM ReadMem 150 | ; IS EEPROM_READ 151 | 152 | :NONAME ( adr -- n) \ читает память с adr, возвращает число принятых байт 153 | M_READ SWAP TO rBuf 154 | szUbuf MIN 155 | ; IS Memo@ 156 | 157 | : Buf! ( a u adrW -- n) \ прогрузить и записать буфер 158 | OVER size-rbuf > \ не более размера буфера передачи 159 | IF \ остаток для записи больше размера передачи 160 | NIP size-rbuf SWAP 161 | ModeLoadPage 162 | ELSE \ остаток помещается в передачу 163 | ModeWritePage 164 | THEN TO PageMode 165 | OVER >R M_WRITE WriteMem R> 166 | ; 167 | 168 | :NONAME ( a u adrW -- n) \ прогрузить и записать страницу 169 | SWAP SizePage MIN DUP >R SWAP \ не более станицы 170 | BEGIN \ кусочная запись в размер буфера 171 | 3DUP Buf! \ a u adrW n 172 | >R 173 | R@ + ROT R@ + ROT R> - ROT 174 | OVER 0= 175 | UNTIL 176 | 2DROP DROP R> \ n 177 | ; IS Page! 178 | 179 | \ ========== FUSE =================================== 180 | \ DEFER #Fuse@ ( # -- u) \ прочитать байт № 181 | :NONAME ( # -- u) \ прочитать байт № 182 | 1 XPRG_MEM_TYPE_FUSE ReadMem 183 | DROP C@ 184 | ; IS #Fuse@ \ <============================================================= 185 | 186 | :NONAME ( u # -- ) \ записать 1 байт # 187 | \ .s ." <#Fuse@ " cr 188 | 2DUP #Fuse@ <> 189 | IF \ не равны 190 | DUP ." FUSE_" 1 .R ." : " 191 | >R TmpByte ! TmpByte 1 R@ 192 | XPRG_MEM_TYPE_FUSE WriteMem 193 | TwdFuse PAUSE \ время на запись 194 | TmpByte C@ R> #Fuse@ <> 195 | IF S" Запись не подтверждена." :[ 196 | ELSE ." изменен" 197 | THEN CR 198 | ELSE 2DROP 199 | THEN 200 | ; IS #Fuse! \ <============================================================= 201 | \ ========== LOCK =================================== 202 | \ DEFER LockBits@ ( -- u) 203 | :NONAME ( -- u) 204 | 0 1 XPRG_MEM_TYPE_LOCKBITS ReadMem 205 | DROP C@ 206 | ; IS LockBits@ \ <============================================================ 207 | 208 | :NONAME ( u 0 -- ) \ записать 1 байт 0 209 | >R TmpByte ! TmpByte 1 R> 210 | XPRG_MEM_TYPE_LOCKBITS WriteMem 211 | 10 PAUSE 212 | LockBits@ 213 | ." LOCK MODE:" INVERT 0xFF AND . 214 | CR 215 | ; IS LockBits! \ <============================================================ 216 | 217 | :NONAME ( # -- byte) \ прочитать калибровочный байт # 218 | 1 XPRG_MEM_TYPE_PRODSIG ReadMem 219 | DROP C@ 220 | ; IS CalibrationByte@ 221 | 222 | MCU.DEVID0 CONSTANT DeviceSignature 223 | :NONAME ( # -- byte) \ прочитать калибровочный байт # 224 | DeviceSignature + 1 XPRG_MEM_TYPE_DATAMEM ReadMem 225 | DROP C@ 226 | ; IS SignatureByte@ 227 | -------------------------------------------------------------------------------- /asmAVR.f: -------------------------------------------------------------------------------- 1 | \ #! /home/ivanov/spf-4.20/spf4 2 | DECIMAL 3 | \ ассемблер для AVR 4 | \ автор: ~iva дата: 8.03.2010 ревизия:0 5 | \ ======== ИНФО ================================================================ 6 | \ 7 | \ ======== ЗАДАЧИ ============================================================== 8 | \ принять текст и интерпретировать его как форт-ассемблер AVR 9 | \ ======== ПОДКЛЮЧАЕМЫЕ ФАЙЛЫ и слова нужные не только здесь =================== 10 | S" ~iva/AVR/disAVR.f" INCLUDED \ дизассемблер и другие 11 | \ ======== КОНСТАНТЫ И ПЕРЕМЕННЫЕ ============================================== 12 | VARIABLE CODING? \ счётчик состояния кодирования 13 | 0 CODING? ! 14 | \ ======== СЛУЖЕБНЫЕ СЛОВА ДЛЯ ОПРЕДЕЛЕНИЯ ГЛАВНЫХ СЛОВ ======================== 15 | 16 | 17 | : >codebuf ( u --) 18 | DUP TRUE 16 LSHIFT AND 19 | IF WORD-SPLIT W>Seg W>Seg 20 | ELSE W>Seg 21 | THEN ; 22 | 23 | : operand-exe ( j*x operator op# -- i*x) \ выполнить обработчик операнда 24 | ASM! 25 | op.exec @ EXECUTE ; 26 | : operand! ( j*x operator op# -- i*x) 27 | 2DUP op.mask @ TO MASKA operand-exe 28 | ; 29 | : comby ( j*x -- i*x) 30 | operator @ ?DUP \ взять из operator адрес статьи ПРЕдыдущего оператора 31 | \ если не 0, то 32 | IF DUP 0< 33 | IF \ псевдокоманда! 34 | 0 operator ! \ взял-выкинул ДО выполнения (защита от рекурсии) 35 | NEGATE EXECUTE 36 | ELSE \ команда ассемблера 37 | \ выполнить его слова-обработчики операндов, 38 | DUP >R 2 operand! R@ 1 operand! 39 | \ получить клише, 40 | R> clishe @ 41 | f-2W 16 AND LSHIFT \ если широкий - сдвинуть клише 42 | \ скрестить результат с клише, 43 | \ и записать в codebuf 44 | _code OR >codebuf 45 | 0 TO _code FALSE TO f-2W 46 | 0 operator ! \ взял-выкинул ПОСЛЕ выполнения (защита от рекурсии) 47 | THEN 48 | THEN 49 | ; 50 | :NONAME ( j*x operator -- i*x) \ на стеке лежат операнды!!! 51 | \ выполнить отложенный оператор 52 | \ отложить текущий оператор до отработки его опреандов 53 | >R 54 | BEGIN \ выполнять comby, до тех пор пока operator не равен 0 55 | operator @ 56 | WHILE 57 | comby 58 | REPEAT 59 | R> operator ! \ текущую команду отложить для последующей обработки 60 | ; IS coder 61 | 62 | : FILTER ( adr u -- adr' u') \ изменить строку 63 | DUP 0 > 64 | IF OVER + SWAP 65 | DO I C@ 66 | DUP [CHAR] , = 67 | IF DROP BL EMIT>S \ баним запятые пробелом 68 | ELSE \ DUP [CHAR] - = IF BL EMIT>S THEN \ пробел ПЕРЕД минусом \ он и так сам получается 69 | DUP EMIT>S ( копируем символ) 70 | [CHAR] + = IF BL EMIT>S THEN \ пробел ПОСЛЕ плюса 71 | THEN 72 | LOOP 73 | S@ \ 2dup type cr 74 | ELSE DROP 0 75 | THEN 76 | ; 77 | \ ======== ГЛАВНЫЕ СЛОВА ======================================================= 78 | \ : (@) ; \ нечто, что уже лежит на стеке. 79 | \ Используется для отметки мест параметров в макросах с параметрами. 80 | 81 | : C[ ( --) \ включить фильтрацию 82 | 0 coder 83 | CODING? @ 0= IF S \ подготовить место 89 | SOURCE >IN @ OVER >IN ! /STRING \ взять остаток строки из входного потока и передвинуть указатель 90 | FILTER 91 | EVALUATE 92 | S>DROP \ освободить место 93 | REFILL 94 | WHILE REPEAT 95 | THEN 96 | ; 97 | 98 | VARIABLE codeDep \ контроль изменения глубины стека 99 | IF -1 CODING? +! THEN 103 | CODING? @ 0 = IF DASSM> THEN \ отключить словарь ассемблирования 104 | ; 105 | : C; ]C \ завершить кодирование 106 | DEPTH codeDep @ - 107 | DUP 0 < ABORT" В коде нехватает операндов." 108 | ABORT" В коде лишние операнды." 109 | ; 110 | 111 | WARNING @ FALSE WARNING ! 112 | : NOTFOUND ( adr u -- ) \ попытка обработать ненайденное слово, как внутреннюю метку 113 | 2DUP + 1- C@ [CHAR] : = \ двоеточие в конце? 114 | IF \ да - делаем маркер 115 | 2>R \ отложить строку с именем 116 | ]C \ завершить предыдущий оператор 117 | MarkType finger 2R> 1- !label(S): \ маркер с именем без двоеточия в конце 118 | 0 THROW \ разрешение исключения 119 | C[ 120 | ELSE NOTFOUND THEN 121 | ; 122 | WARNING ! 123 | DASSM> 124 | 125 | : CODE ( <"Name"> --) \ начать новое определение именем "Name" 126 | CODING? @ ABORT" Предыдущее определение не завершено." 127 | DEPTH codeDep ! \ запомнить глубину стека 128 | CodeType label: C[ 129 | ; 130 | 131 | \ ======== ТЕСТЫ И ПРИМЕРЫ ===================================================== 132 | \ HEX 133 | \ ALSO DASSM 134 | \ SAVE-VOCS VOCS 32 DUMP CR 135 | \ PREVIOUS PREVIOUS DEFINITIONS ORDER 136 | \ RESTORE-VOCS ORDER 137 | 138 | \ CR DECIMAL S" tst-tn26.asm" INCLUDED \ CATCH . CR 139 | \ SEG @ wender dis \ 140 | \ CR CR SEE-CODE ara 141 | 142 | -------------------------------------------------------------------------------- /buffers.f: -------------------------------------------------------------------------------- 1 | \ имя проекта: буферные инструменты 2 | \ автор:~iva дата:2010 ревизия:1 3 | \ ======== ИНФО ================================================================ 4 | \ Система управления буферами (сегментами памяти). Нужно создать их и описать 5 | \ слова для доступа к ним, с соблюдением всех ограничений. 6 | \ При создании задаются: 7 | \ начальный размер (>0) 8 | \ максимальный размер (0-без ограничения); 9 | \ определяются: 10 | \ свободный указатель (finger), 11 | \ указатель конца записи (wender). 12 | \ 0 <= свободный указатель < указатель конца записи < максимальный размер. 13 | \ 14 | \ Указатель записи содержит адрес первого свободного байта куда можно писать, 15 | \ его можно читать, но нельзя изменять. Свободный указатель используется словами 16 | \ доступа для записи и для чтения, его можно и читать и изменять в пределах 17 | \ определяемых операцией 18 | \ (от 0, до чтение: <указатель конца записи 19 | \ запись: =указатель конца записи) 20 | \ При каждой операции записи или чтения свободный указатель(finger) смещается на 21 | \ величину зависящую от порции записи/чтения, если при записи finger пререходит 22 | \ за указатель конца записи, последний смещается на ту же величину, так что в 23 | \ итоге finger всегда меньше или равен указателю конца записи. 24 | \ Если при записи происходит выход за пределы отведенной памяти, то последняя 25 | \ увеличивается кратно текущему размеру, до тех пор пока не упрется 26 | \ в максимальный размер определенный при создании буфера. 27 | \ -----------------структура seg------------------------------------------------ 28 | \ max size createSeg: ROM-SEG 29 | \ ------------------------------------------------------------------------------ 30 | \ adr CELL имя 31 | \ size CELL seg-size 32 | \ lim CELL seg-lim 33 | \ finger CELL seg-finger 34 | \ wender CELL seg-wender 35 | \ labels CELL seg-labels 36 | \ name STR seg-name 37 | \ ------------------------------------------------------------------------------ 38 | \ ======== ЗАДАЧИ ============================================================== 39 | \ ======== ПОДКЛЮЧАЕМЫЕ ФАЙЛЫ и слова нужные не только здесь =================== 40 | S" ~iva/AVR/opcodes.f" INCLUDED \ для работы описанием кодов операции и другое 41 | \ ======== КОНСТАНТЫ И ПЕРЕМЕННЫЕ ============================================== 42 | 0 VALUE SEG \ ссылка на структуру текущего сегмента 43 | \ ======== СЛУЖЕБНЫЕ СЛОВА ДЛЯ ОПРЕДЕЛЕНИЯ ГЛАВНЫХ СЛОВ ======================== 44 | : seg-size ( -- adr) \ актуальный размер буфера 45 | SEG CELL+ ; 46 | : seg-lim ( -- u) \ лимит буфера 47 | seg-size CELL+ @ ; 48 | : seg-finger ( -- adr) \ адрес свободного указателя 49 | seg-size 2 CELLS + ; 50 | : seg-wender ( -- adr) \ указатель конца записи 51 | seg-finger CELL+ ; 52 | : seg-labels ( -- adr) \ адрес начала цепочки меток в текущем сегменте 53 | seg-wender CELL+ ; 54 | : seg-name ( -- adr) \ адрес строки с именем сегмента 55 | seg-labels CELL+ ; 56 | : ?seg ( -- ) \ показать имя текущего сегмента 57 | seg-name COUNT TYPE ; 58 | : resize? ( u --) \ нужно ли и возможно ли изменение размера сегмента? 59 | seg-size @ OVER < 60 | \ попытка расширить сегмент 61 | IF seg-lim ?DUP IF OVER < ABORT" Выход за ограничитель сегмента." THEN 62 | seg-size @ OVER SWAP / 1+ seg-size @ * 63 | seg-lim ?DUP IF MIN THEN 64 | \ u new 65 | SEG @ OVER RESIZE THROW SEG ! seg-size ! 66 | THEN 67 | DROP 68 | ; 69 | : preWrite ( u -- ) \ проверка возможности записи u байт 70 | seg-finger @ + DUP resize? 71 | seg-wender @ MAX seg-wender ! 72 | ; 73 | : finger! ( u --) \ установить указатель 74 | DUP resize? 75 | seg-finger ! 76 | ; 77 | : ORG ( u -- ) \ установить указатель сегмента 78 | finger! ; 79 | 80 | : finger> ( u --) \ передвинуть указатель на u байт 81 | seg-finger @ + finger! ; 82 | \ ======== ГЛАВНЫЕ СЛОВА ======================================================= 83 | : createSeg: ( limit size "name"--) 84 | >IN @ >R 85 | CREATE DUP >R ALLOCATE THROW , R> , , 0 , 0 , 0 , 86 | R> >IN ! BL WORD COUNT str! \ имя сегмента 87 | ; 88 | : fingerA ( -- adr) \ адрес указателя для чтения/записи 89 | SEG @ seg-finger @ + ; 90 | : wenderA ( -- adr ) \ адрес адреса свободного байта для записи 91 | SEG @ seg-wender @ + ; 92 | : finger ( -- n) \ указатель для чтения/записи 93 | seg-finger @ ; 94 | : wender ( -- n ) \ адрес свободного байта для записи 95 | seg-wender @ ; 96 | : preRead ( n --) \ проверка возможности чтения 97 | finger + wender > ABORT" Незаписано." 98 | ; 99 | 100 | : fingerAlign ( -- ) \ выровнять указатель на чёт 101 | finger DUP 1 AND + finger! ; 102 | 103 | : >Seg ( n --) \ записать ячейку в буфер 104 | CELL preWrite 105 | fingerA ! CELL finger> ; 106 | : W>Seg ( n --) \ записать слово в буфер 107 | 2 preWrite 108 | fingerA W! 2 finger> ; 109 | : C>Seg ( n --) \ записать байт в буфер 110 | 1 preWrite 111 | fingerA C! 1 finger> ; 112 | \ : B>Seg ( f # --) \ запись бита #=(0..31) 113 | \ 8 CELLS 1- AND 1 SWAP LSHIFT 114 | \ fingerA @ SWAP 115 | \ ROT IF OR ELSE INVERT AND THEN fingerA ! 116 | \ ; 117 | : B>Seg ( f # --) \ запись бита #=(0..) 118 | 8 CELLS /MOD >R 1 SWAP LSHIFT 119 | fingerA R> CELLS + DUP >R @ SWAP 120 | ROT IF OR ELSE INVERT AND THEN R> ! 121 | ; 122 | 123 | : Seg> ( -- n) \ считать ячейку из буфера 124 | CELL preRead 125 | fingerA @ CELL finger> ; 126 | : Seg>W ( -- n) \ считать слово из буфера 127 | 2 preRead 128 | fingerA W@ 2 finger> ; 129 | : Seg>C ( -- n) \ считать байт из буфера 130 | 1 preRead 131 | fingerA C@ 1 finger> ; 132 | : Seg>B ( # -- f) \ чтение бита #=(0..31) 133 | 8 CELLS 1- AND 134 | fingerA @ SWAP RSHIFT 1 AND 0= 0= ; 135 | : SegA ( n -- addr) \ выдать реальный адрес смещения n 136 | SEG @ + ; 137 | \ ======== ТЕСТЫ И ПРИМЕРЫ ===================================================== 138 | \ 30 22 createSeg: ROM-SEG 139 | \ ROM-SEG TO SEG 140 | \ HEX 141 | \ ROM-SEG 7 CELLS DUMP CR 142 | \ SEG @ 40 DUMP CR 143 | \ 1 >Seg TRUE 3 B>Seg SEG @ 10 DUMP CR 144 | 145 | -------------------------------------------------------------------------------- /chips/chips.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "path": "." 6 | }, 7 | { 8 | "path": "/home/ivanov/IvaMobi2/Person/Job/Projects/EnSol/ensol/beq/libs/fasm/~iva/AVR/chips" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /chips/regName.ff: -------------------------------------------------------------------------------- 1 | \ стандартные имена регистров GPIO 2 | GPIO.0 3 | DUP 0 + PORT: GPIO0 4 | DUP 1 + PORT: GPIO1 5 | DUP 2 + PORT: GPIO2 6 | DUP 3 + PORT: GPIO3 7 | DUP 4 + PORT: GPIO4 8 | DUP 5 + PORT: GPIO5 9 | DUP 6 + PORT: GPIO6 10 | DUP 7 + PORT: GPIO7 11 | DUP 8 + PORT: GPIO8 12 | DUP 9 + PORT: GPIO9 13 | DUP 10 + PORT: GPIOA 14 | DUP 11 + PORT: GPIOB 15 | DUP 12 + PORT: GPIOC 16 | DUP 13 + PORT: GPIOD 17 | DUP 14 + PORT: GPIOE 18 | 15 + PORT: GPIOF 19 | 20 | \ стандартные имена регистров CPU 21 | CPU. 22 | DUP 0x04 + PORT: CCP \ Configuration Change Protection 23 | DUP 0x08 + PORT: RAMPD \ Ramp D 24 | DUP 0x09 + PORT: RAMPX \ Ramp X 25 | DUP 0x0A + PORT: RAMPY \ Ramp Y 26 | DUP 0x0B + PORT: RAMPZ \ Ramp Z 27 | DUP 0x0C + PORT: EIND \ Extended Indirect Jump 28 | DUP 0x0D + PORT: SPL \ Stack Pointer Low 29 | DUP 0x0E + PORT: SPH \ Stack Pointer High 30 | 0x0F + PORT: SREG \ Status Register 31 | 32 | 33 | -------------------------------------------------------------------------------- /chips/tn13.ff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivanivanovo/AVR/58ee10856bcf813c3895b71387ff21304bc7ddea/chips/tn13.ff -------------------------------------------------------------------------------- /chips/tn24.ff: -------------------------------------------------------------------------------- 1 | \ *************************************************************************** 2 | \ device ATtiny44 3 | \ *************************************************************************** 4 | DECIMAL 5 | \ ***************************************************************************** 6 | \ Data Memory Declarations 7 | \ ***************************************************************************** 8 | HEX[ 9 | 03F CONSTANT IOEND \ 256 bytes I/O 10 | 00DF CONSTANT RAMEND \ byte 11 | 003FF CONSTANT FLASHEND \ word (2byte) 12 | 0 CONSTANT XRAMEND \ Last External RAM Location 13 | 007F CONSTANT E2END \ Last EEPROM Location 14 | 0060 CONSTANT SRAM_START 15 | ]HEX 16 | 16 CONSTANT PAGESIZE \ number of WORDS in a page 17 | 18 | S" ATtiny24-44-84.fs" INCLUDED 19 | 20 | -------------------------------------------------------------------------------- /chips/tn44.ff: -------------------------------------------------------------------------------- 1 | \ *************************************************************************** 2 | \ device ATtiny44 3 | \ *************************************************************************** 4 | DECIMAL 5 | \ ***************************************************************************** 6 | \ Data Memory Declarations 7 | \ ***************************************************************************** 8 | HEX[ 9 | 03F CONSTANT IOEND \ 256 bytes I/O 10 | 015F CONSTANT RAMEND \ byte 11 | 007FF CONSTANT FLASHEND \ word (2byte) 12 | 0 CONSTANT XRAMEND \ Last External RAM Location 13 | 00FF CONSTANT E2END \ Last EEPROM Location 14 | 0060 CONSTANT SRAM_START 15 | ]HEX 16 | 32 CONSTANT PAGESIZE \ number of WORDS in a page 17 | 18 | S" ~iva/AVR/chips/ATtiny24-44-84.ff" INCLUDED 19 | 20 | -------------------------------------------------------------------------------- /chips/tn441.ff: -------------------------------------------------------------------------------- 1 | 2 | \ ************************************************************************* 3 | \ * A P P L I C A T I O N N O T E F O R T H E A V R F A M I L Y 4 | \ * 5 | \ * Number : AVR000 6 | \ * File Name : tn441def.inc 7 | \ * Title : Register/Bit Definitions for the ATtiny441 8 | \ * Created : 2015-06-25 09:38 9 | \ * Version : 1.00 10 | \ * Support e-mail : avr@atmel.com 11 | \ * Target MCU : ATtiny441 12 | \ * 13 | \ * DESCRIPTION 14 | \ * When including this file in the assembly program file, all I/O register 15 | \ * names and I/O register bit names appearing in the data book can be used. 16 | \ * In addition, the six registers forming the three data pointers X, Y and 17 | \ * Z have been assigned names XL \ ZH. Highest RAM address for Internal 18 | \ * SRAM is also defined 19 | \ * 20 | \ ************************************************************************* 21 | DECIMAL 22 | 23 | \ ***** SPECIFY DEVICE *************************************************** 24 | \ device ATtiny441 25 | 0x1E9215 CONSTANT device_SIGNATURE 26 | 27 | \ #pragma AVRPART CORE CORE_VERSION V2 28 | \ #pragma AVRPART CORE NEW_INSTRUCTIONS lpm rd,z+ 29 | 30 | \ ***** DATA MEMORY DECLARATIONS ***************************************** 31 | 0x0000 CONSTANT FLASHSTART \ Note: Word address 32 | 0x07FF CONSTANT FLASHEND \ Note: Word address 33 | 0x0010 CONSTANT FLASHPAGESIZE \ bytes 34 | 0x0008 CONSTANT PAGESIZE \ Words 35 | 0x0040 CONSTANT FLASHERASESIZE \ bytes 36 | 0x0020 CONSTANT ERASESIZE \ Words 37 | 0x00FF CONSTANT IOEND \ 38 | 0x0100 CONSTANT SRAM_START \ 39 | 256 CONSTANT SRAM_SIZE \ 40 | 0x01FF CONSTANT RAMEND \ 41 | 0x00FF CONSTANT E2END \ 42 | 0x00FF CONSTANT EEPROMEND \ 43 | 8 CONSTANT EEADRBITS \ 44 | 0x0000 CONSTANT XRAMEND \ 45 | 46 | \ #pragma AVRPART MEMORY PROG_FLASH 4096 47 | \ #pragma AVRPART MEMORY INT_SRAM SIZE 256 48 | \ #pragma AVRPART MEMORY INT_SRAM START_ADDR 0x100 49 | \ 50 | \ #pragma AVRPART MEMORY EEPROM 256 51 | 52 | S" ~iva/AVR/chips/ATtiny441-841.ff" INCLUDED 53 | -------------------------------------------------------------------------------- /chips/tn84.ff: -------------------------------------------------------------------------------- 1 | \ *************************************************************************** 2 | \ device ATtiny44 3 | \ *************************************************************************** 4 | DECIMAL 5 | \ ***************************************************************************** 6 | \ Data Memory Declarations 7 | \ ***************************************************************************** 8 | HEX[ 9 | 03F CONSTANT IOEND \ 256 bytes I/O 10 | 025F CONSTANT RAMEND \ byte 11 | 00FFF CONSTANT FLASHEND \ word (2byte) 12 | 0 CONSTANT XRAMEND \ Last External RAM Location 13 | 01FF CONSTANT E2END \ Last EEPROM Location 14 | 0060 CONSTANT SRAM_START 15 | ]HEX 16 | 32 CONSTANT PAGESIZE \ number of WORDS in a page 17 | 18 | S" ATtiny24-44-84.ff" INCLUDED 19 | 20 | -------------------------------------------------------------------------------- /chips/tn841.ff: -------------------------------------------------------------------------------- 1 | 2 | \ ************************************************************************* 3 | \ * A P P L I C A T I O N N O T E F O R T H E A V R F A M I L Y 4 | \ * 5 | \ * Number : AVR000 6 | \ * File Name : tn841def.inc 7 | \ * Title : Register/Bit Definitions for the ATtiny441 8 | \ * Created : 2015-06-25 09:38 9 | \ * Version : 1.00 10 | \ * Support e-mail : avr@atmel.com 11 | \ * Target MCU : ATtiny841 12 | \ * 13 | \ * DESCRIPTION 14 | \ * When including this file in the assembly program file, all I/O register 15 | \ * names and I/O register bit names appearing in the data book can be used. 16 | \ * In addition, the six registers forming the three data pointers X, Y and 17 | \ * Z have been assigned names XL \ ZH. Highest RAM address for Internal 18 | \ * SRAM is also defined 19 | \ * 20 | \ ************************************************************************* 21 | DECIMAL 22 | 23 | \ ***** SPECIFY DEVICE *************************************************** 24 | \ device ATtiny441 25 | 0x1E9315 CONSTANT device_SIGNATURE 26 | 27 | \ #pragma AVRPART CORE CORE_VERSION V2 28 | \ #pragma AVRPART CORE NEW_INSTRUCTIONS lpm rd,z+ 29 | 30 | \ ***** DATA MEMORY DECLARATIONS ***************************************** 31 | 0x0000 CONSTANT FLASHSTART \ Note: Word address 32 | 0x0FFF CONSTANT FLASHEND \ Note: Word address 33 | 0x0010 CONSTANT FLASHPAGESIZE \ bytes 34 | 0x0008 CONSTANT PAGESIZE \ Words 35 | 0x0040 CONSTANT FLASHERASESIZE \ bytes 36 | 0x0020 CONSTANT ERASESIZE \ Words 37 | 0x00FF CONSTANT IOEND \ 38 | 0x0100 CONSTANT SRAM_START \ 39 | 512 CONSTANT SRAM_SIZE \ 40 | 0x01FF CONSTANT RAMEND \ 41 | 0x01FF CONSTANT E2END \ 42 | 0x01FF CONSTANT EEPROMEND \ 43 | 8 CONSTANT EEADRBITS \ 44 | 0x0000 CONSTANT XRAMEND \ 45 | 46 | \ #pragma AVRPART MEMORY PROG_FLASH 8192 47 | \ #pragma AVRPART MEMORY INT_SRAM SIZE 512 48 | \ #pragma AVRPART MEMORY INT_SRAM START_ADDR 0x100 49 | \ 50 | \ #pragma AVRPART MEMORY EEPROM 512 51 | 52 | S" ~iva/AVR/chips/ATtiny441-841.ff" INCLUDED 53 | -------------------------------------------------------------------------------- /colortest.f: -------------------------------------------------------------------------------- 1 | \ color fortAsmAVR 2 | true 3 | false 4 | 0x 123a 5 | 0x123 6 | 0x1a23 7 | #123 8 | $12d 9 | $0abc 0X012a 10 | 11 | if 12 | else 13 | then 14 | 15 | if_b 16 | if_nb 17 | if= 18 | if0 19 | if_c 20 | if_nc 21 | if_nn if_n if_z 22 | if< 23 | if<> 24 | 25 | until_b 26 | while_b 27 | wait0 28 | wait_b 29 | while 30 | begin 31 | again 32 | until 33 | \eof gjgjgj eof\ 34 | rcall ff 35 | rjmp aa 36 | icall .. 37 | ijmp .. 38 | goto aa 39 | call aa 40 | jmp aa 41 | INCLUDED 42 | S" teste" included 43 | vector> 1 44 | teste 51 | abort" dftrd" 52 | postpone aas 53 | char qq 54 | code AAA 55 | : Ini 56 | begin again 57 | ?do fff loop 58 | C[ 59 | ]c 60 | is AAA 61 | :NONAME 62 | -------------------------------------------------------------------------------- /data.f: -------------------------------------------------------------------------------- 1 | \ слова для работы с данными, таблицы, строки, константы и пр. 2 | 3 | : AS> ( adr u -- ) \ скопировать данные в текущий сегмент, 4 | \ запомнить под именем name 5 | DataType label: 6 | \ DUP 1 AND + \ увеличить до чётного количества байт 7 | OVER + SWAP DO I C@ C>Seg LOOP 8 | fingerAlign 9 | ; 10 | 11 | : str> ( adr u --) \ скопировать данные в текущий сегмент 12 | \ как строку со счетчиком 13 | DataType label: 14 | DUP C>SEG 15 | OVER + SWAP DO I C@ C>Seg LOOP 16 | fingerAlign 17 | ; 18 | 19 | \ манипуляции с байтами на стеке 20 | : |4 ( u --b0 b1 b2 b3 ) \ рассыпать число на 4 байта ( младший ниже по стеку) 21 | WORD-SPLIT SWAP BYTE-SPLIT ROT BYTE-SPLIT 22 | ; 23 | : |3 ( u -- b0 b1 b2 ) \ рассыпать число на 3 байта ( младший ниже по стеку) 24 | |4 DROP 25 | ; 26 | : |2 ( u -- b0 b1 ) \ рассыпать число на 2 байта ( младший ниже по стеку) 27 | BYTE-SPLIT 28 | ; 29 | 30 | 0 VALUE Deepold \ хранилище глубины стека 31 | : t{ DEPTH TO Deepold ; 32 | : }bytes DataType label: DEPTH Deepold - 0 SWAP 1- DO I ROLL C>Seg -1 +LOOP fingerAlign ; 33 | : }words DataType label: DEPTH Deepold - 0 SWAP 1- DO I ROLL W>Seg -1 +LOOP fingerAlign ; 34 | : }cells DataType label: DEPTH Deepold - 0 SWAP 1- DO I ROLL >Seg -1 +LOOP fingerAlign ; 35 | 36 | \ применение 37 | \ t{ 1 2 3 4 }bytes Счёт \ под именем Счёт в текущем сегменте запишутся байты 38 | 39 | 40 | -------------------------------------------------------------------------------- /disAVR.f: -------------------------------------------------------------------------------- 1 | \ дизассемблер AVR 2 | \ автор: ~iva 2010 3 | \ ревизия: декабрь 2011 = вывод -> надо всё переписать... бяка, хоть работает 4 | 5 | \ ======== ИНФО ================================================================ 6 | \ Все инструкции для данного микроконтроллера упаковываются в связанную цепочку 7 | \ структур opcodes. Эти структуры используются для ассемблирования и дизассе- 8 | \ мблирования. Доступ к любой структуре возможен двумя спообами: 9 | \ а) по имени команды (при подключенном словаре DASSM) 10 | \ b) через переменную opcodes, которая указывает на начало цепи opcodes 11 | \ ======== ЗАДАЧИ ============================================================== 12 | \ Нужно дизассемблировать область памяти заданную адресом и длинной, в надежде 13 | \ что там находится бинарный код микроконтроллера семейства AVR-8. 14 | \ Полученный листинг (текст с мнемониками) записывается в указанный файл. 15 | \ ======== ПОДКЛЮЧАЕМЫЕ ФАЙЛЫ и слова нужные не только здесь =================== 16 | S" ~iva/AVR/AVRset.f" INCLUDED \ настройка на AVR и другое 17 | 18 | \ ======== КОНСТАНТЫ И ПЕРЕМЕННЫЕ ============================================== 19 | \ ======== СЛУЖЕБНЫЕ СЛОВА ДЛЯ ОПРЕДЕЛЕНИЯ ГЛАВНЫХ СЛОВ ======================== 20 | \ ========== слова для дизасемблирования ======================================= 21 | \ ============================================================================== 22 | 23 | 0 VALUE CurLabelName \ c-adr имени метки 24 | 0 VALUE CurLabelValue \ смещение метки в сегменте 25 | 0 VALUE CurLabelType \ тип метки 26 | 8 VALUE LenDump \ стандартная длина строки дампа 27 | 0 VALUE WordLabelValue \ показывать смещение в словах 28 | 29 | : ClearCurLabel ( --) \ очистка текущих значений 30 | 0 TO CurLabelName \ c-adr имени метки 31 | 0 TO CurLabelValue \ смещение метки в сегменте 32 | 0 TO CurLabelType \ тип метки 33 | ; 34 | : SetCurLabel ( label --) 35 | DUP label-value @ TO CurLabelValue 36 | DUP label-name TO CurLabelName \ имя 37 | label-type @ TO CurLabelType \ тип 38 | ; 39 | 40 | : SkipMarks ( label--label') \ пропустить внутренние метки 41 | DUP 0= IF EXIT THEN 42 | BEGIN DUP label-type @ MarkType = WHILE @ REPEAT 43 | ; 44 | : DownLabel ( val -- label-1 |0 ) \ найти метку ниже текущей позиции, 0 если нету 45 | >R 46 | labels BEGIN DUP @ SkipMarks DUP IF label-value @ R@ > THEN WHILE @ REPEAT 47 | labels OVER = IF DROP 0 THEN 48 | R> DROP 49 | ; 50 | : UpLabel ( val -- label+1 |0 ) \ найти метку выше или равную текущей позиции, 0 если нету 51 | DownLabel DUP IF @ THEN 52 | ; 53 | VARIABLE PozStr \ текущая позиция в строке 54 | TRUE VALUE AddrOpcode? \ нужен-ли адрес и опкод? пока да 55 | 5 CONSTANT SizeAreaVAL 56 | 4 CONSTANT SizeAreaOpcode 57 | 12 CONSTANT SizeAreaLabel 58 | 0 VALUE PozVal 59 | SizeAreaVAL 3 + VALUE PozOp 60 | PozOp SizeAreaOpcode 2* 2+ + VALUE PozLabel 61 | PozLabel SizeAreaLabel + VALUE PozMnemo 62 | 63 | : .Label: ( -- ) \ напечатать имя метки в поле шириной n 64 | CurLabelName 65 | IF CurLabelName COUNT TYPE ." :" 66 | CurLabelName COUNT SYMBOLS 1+ PozStr +! 67 | 0 TO CurLabelName \ печатать только один раз 68 | THEN 69 | ; 70 | : NewString ( ) \ начать новую строку 71 | CR 0 PozStr ! 72 | ; 73 | 74 | ( 75 | 00412 F7E9 BRNE m59 76 | 00414 EF8F LDI R24,255 77 | 00416 9380 00A4 STS iwAddr,R24 78 | 0041A E1ED LDI zL,29 79 | 0041C 8200 m60: ST Z,R0 80 | ) 81 | : GoPoz ( p -- ) \ перейти на позицию 82 | PozStr @ - DUP SPACES 83 | DUP 0 > IF PozStr +! ELSE DROP THEN 84 | ; 85 | : TypeLabel ( ) \ напечатать метку 86 | PozLabel GoPoz 87 | .Label: 88 | ; 89 | : TypeVal ( val -- ) \ напечатать смещение 90 | AddrOpcode? 91 | IF PozVal GoPoz 92 | WordLabelValue IF 2/ THEN \ смещение в байтах или в словах 93 | SizeAreaVAL HEX[ .0R ]HEX SPACE 94 | SizeAreaVAL 1+ PozStr +! 95 | ELSE DROP THEN 96 | ; 97 | : TypeOpcode ( opcode -- ) 98 | AddrOpcode? 99 | IF PozOp GoPoz 100 | SizeAreaOpcode HEX[ .0R ]HEX SPACE 101 | SizeAreaOpcode 1+ PozStr +! 102 | ELSE DROP THEN 103 | ; 104 | : TypeStrDump ( val # -- ) 105 | ?DUP 106 | IF 107 | OVER TypeVal 108 | \ метка 109 | TypeLabel PozMnemo GoPoz ." .db " 110 | ( val #) SWAP SEG @ + SWAP ( adr # ) 111 | TUCK 0 112 | DO \ цикл по байта 113 | C@+ DUP <# 0 #S #> TYPE ." ," \ печатать байты 114 | PAD I + ! \ запоминать символы 115 | LOOP DROP 116 | ( # ) 117 | \ строка 118 | LenDump OVER - 3 * 2+ SPACES 119 | ." ; " PAD SWAP TYPE_ASCII 120 | NewString \ CR 121 | ELSE DROP 122 | THEN 123 | ; 124 | : AsTable ( val u -- ) 125 | ?DUP 126 | IF LenDump /MOD \ количество полных строк (длиной LenDump) и хвост (S 160 | OVER mnemo COUNT 6 n+>S \ напечатать мнемонику команды 161 | запятая OFF \ перед первым операндом запятую не ставить 162 | \ проверить ширину масок операндов 163 | OVER DUP 1 op.mask @ SWAP 2 op.mask @ OR 164 | 0xFFFF > 165 | \ взять добавку самостоятельно 166 | IF W@+ 167 | DUP TypeOpcode \ допечатать опкод, если нужен 168 | opcode 16 LSHIFT OR TO opcode 169 | THEN 170 | \ выполнить операнды с проверкой 171 | OVER 1 OperandToken ( adr' xtop ) CATCH >R 172 | запятая ON \ после первого операнда запятую уже можно ставить 173 | OVER 2 OperandToken CATCH R> OR 174 | ( adr' adr-link' adr" flag ) 175 | WHILE DROP S>DROP \ cr ." оборот" cr 176 | REPEAT NIP NIP 177 | ; 178 | : AsCode ( val u --) 179 | DIS/ASM >R \ запомнить режим 180 | DIS! \ режим дизассемблирования 181 | OVER + SWAP 182 | ?DO ( ) 183 | I DUP label-find ?DUP IF SetCurLabel THEN 184 | DUP TypeVal \ напечатать адрес-смещение, если нужен 185 | SEG @ + \ текщий адрес ( adr0 ) 186 | DUP @ TypeOpcode \ напечатать опкод, если нужен 187 | ( adr0 ) 188 | DUP DeCombo 189 | ( adr0 adr") 190 | TypeLabel 191 | ( adr0 adr") 192 | \ напечатать команду и операнды 193 | PozMnemo GoPoz S@ TYPE S>DROP 194 | NewString \ CR \ закрыть строку 195 | ( adr0 adr+ ) 196 | SWAP - \ вычисление сдвига по адресу 197 | +LOOP ( ) 198 | R> TO DIS/ASM \ востановить режим 199 | ; 200 | : (dis) ( val u -- ) \ дизассемблировать область памяти 201 | CurLabelType CodeType = 202 | CurLabelType MarkType = OR 203 | IF AsCode ELSE AsTable THEN 204 | ; 205 | \ ======== ГЛАВНЫЕ СЛОВА ======================================================= 206 | : Val_ ( val -- val'|0) \ дизасемблировать от смещения val, до следующей метки 207 | \ оформить текущее определение 208 | DUP label-find ?DUP IF SetCurLabel ELSE ClearCurLabel THEN 209 | \ найти следующую метку определения 210 | DUP \ (val val ) 211 | BEGIN 2+ \ val' 212 | DUP wender < 213 | WHILE 214 | DUP label-find ?DUP 215 | IF label-type @ MarkType = ELSE TRUE THEN 216 | WHILE REPEAT THEN 217 | \ вычислить размер текущего определения 218 | ( val val') TUCK OVER - ( val' val n ) 219 | \ дизасемблировать текущее определение 220 | (dis) 221 | ; 222 | 223 | : val? ( val -- ) \ показать определение 224 | ROM[ 225 | Val_ DROP 226 | CR \ после участка кода идёт пустая строка, как визуальный разделитель 227 | ]ROM 228 | ; 229 | : vectors? ( -- ) \ распечатать поле векторов прерываний 230 | ROM[ 0 val? ]ROM 231 | ; 232 | \ : WATH? ( -- ) \ опознать name и распечатать 233 | \ \ искать имя во всех сегментах 234 | \ name>label ?DUP 235 | \ IF label-value @ val? 236 | \ ELSE ." Нет такой метки в " ?seg ." ." 237 | \ THEN 238 | \ ; 239 | : [LIST] ( val1 valLast -- ) \ дизассемблировать от val1 до valLast 240 | ROM[ 241 | SWAP 242 | BEGIN Val_ 2DUP > \ пока не добрались до valLast 243 | WHILE CR REPEAT 2DROP 244 | ]ROM 245 | 246 | ; 247 | : LISTING ( --) \ дизассемблировать всё 248 | 0 wender [LIST] 249 | ; 250 | 251 | : see ( val -- ) \ показать ассемблер 252 | FALSE TO AddrOpcode? 253 | PozLabel PozMnemo 254 | 0 TO PozLabel SizeAreaLabel TO PozMnemo 255 | ROT val? 256 | TO PozMnemo TO PozLabel 257 | TRUE TO AddrOpcode? 258 | ; 259 | : seeAll ( -- ) \ показать ассемблер программы 260 | FALSE TO AddrOpcode? 261 | PozLabel PozMnemo 262 | 0 TO PozLabel SizeAreaLabel TO PozMnemo 263 | LISTING 264 | TO PozMnemo TO PozLabel 265 | TRUE TO AddrOpcode? 266 | ; 267 | \ ======== ТЕСТЫ И ПРИМЕРЫ ===================================================== 268 | 269 | 270 | -------------------------------------------------------------------------------- /examples/1-helloLed.f: -------------------------------------------------------------------------------- 1 | \ первая программа на форт-ассемблере AVR 2 | \ маленькая, но с большими коментариями 3 | 4 | \ =================================================================================== 5 | \ для начала скажем spf чем ему придется работать 6 | S" ~iva/AVR/asmAVR.f" INCLUDED \ ассемблер, дизассемблер и другое 7 | \ этот файл в свою очередь подгрузит остальные файлы 8 | \ 9 | \ теперь объясним с каким микроконтроллером будем иметь дело 10 | \ в качестве ID используется сигнатура чипа 11 | \ это удобно, так как программатор сможет проверить ее 12 | 0x9207 CONSTANT device \ Процессор ATtiny44 13 | \ а теперь загрузим данные по выбранноу чипу 14 | S" ~iva/AVR/selectAVR.f" INCLUDED \ набор команд для данного микроконтроллера 15 | DECIMAL \ просто чтобы быть уверенными, что работаем в десятичной системе счисления 16 | \ итого 4 строки и spf стал экспертом по программированию AVR на ассемблере 17 | 18 | \ =================================================================================== 19 | \ далее уже сам проект 20 | \ задача: зажечь светодиодик подключенный к одной из ножек МК 21 | 22 | \ =================================================================================== 23 | \ начнем с того, что объясним к какой именно ножке подключен светодиодик 24 | BitsIn PortA \ он подключен к порту А 25 | 4 #BitIs Red \ к 4 выводу, т.е. к PA4 26 | 27 | \ начнем "работу" 28 | code Bip \ обзовем главное слово как Bip 29 | begin \ начало бесконечного цикла 30 | _/ Red \ включить светодиодик 31 | nop \ ничего не делать 1 такт 32 | \_ Red \ погасить СД 33 | again \ завернуть цикл на начало 34 | c; 35 | \ работа есть, но действий не будет видно, так как нужный вывод 36 | \ не переведен для работы на выход, то есть чип не инициализирован 37 | \ исправим это упущение 38 | code ini 39 | ldi r,{b Red } mov ddrA,r \ теперь светодиодик подключен к ВЫХОДУ 40 | rjmp Bip \ и можно переходить к основному циклу 41 | c; 42 | 0 VECTOR> ini \ тут мы объясняем, что после старта нужно 43 | \ сразу переходить к инициализации 44 | \ все! 45 | \ теперь можем посмотреть, что накомпилировали 46 | listing \ выдаст весь листинг 47 | \ Bip val? \ только код этого слова 48 | \ Bip val_ val? \ этого и следующего за ним 49 | 50 | \ теперь загрузим программу в микроконтроллер 51 | HEX-SAVE helloLed.hex \ выложим скомпилированную прошивку 52 | \ для стороннего программатора или для истории 53 | \ либо, если есть программатор USBtiny или AVRISP_mk2 54 | \ сразу прошьем чип командой 55 | chip! \ по этой команде будет произведена запись flash, EEPROM, Fuses и Lock, но... 56 | \ если подключен программатор, 57 | \ к программатору подключен МК, 58 | \ его сигнатура соответствует device 59 | \ flash, EEPROM, Fuses и Lock были изменены, относительно тех данных, что уже 60 | \ прописаны в чипе. 61 | \ В остальных случаях слово chip! ничего не делает, даже не ругается. 62 | \ Если все пройдет удачно, то светодиодик засветится, а осциллограф 63 | \ покажет, что он еще и моргает. -------------------------------------------------------------------------------- /examples/TM-Led/tmLed.asm: -------------------------------------------------------------------------------- 1 | .DEVICE ATtiny2313A 2 | .include "tn2313Adef.inc" 3 | .equ NextTimer=96 4 | 5 | RJMP main 6 | RETI 7 | RETI 8 | RETI 9 | RETI 10 | RETI 11 | RETI 12 | RETI 13 | RETI 14 | RETI 15 | RETI 16 | RETI 17 | RETI 18 | RETI 19 | RETI 20 | RETI 21 | RETI 22 | RETI 23 | RETI 24 | RETI 25 | RETI 26 | 27 | Time: IN R24,TIFR 28 | SBRS R24,0 29 | RET 30 | LDS R24,NextTimer 31 | INC R24 32 | MOV R25,R24 33 | CPI R24,2 34 | BRNE m0 35 | CLR R25 36 | m0: STS NextTimer,R25 37 | BRNE m1 38 | LDI R25,1 39 | OUT TIFR,R25 40 | m1: LDI R29,0 41 | LDI R28,97 42 | m2: DEC R24 43 | BREQ m3 44 | ADIW R28,4 45 | RJMP m2 46 | m3: LD R24,Y 47 | LDD R25,Y+1 48 | SBIW R24,1 49 | BRCS m4 50 | ST Y,R24 51 | STD Y+1,R25 52 | BRNE m4 53 | LDD R30,Y+2 54 | LDD R31,Y+3 55 | IJMP 56 | m4: RET 57 | 58 | FreeSlot: CLT 59 | LDI R29,0 60 | LDI R28,97 61 | m5: LD R24,Y 62 | LDD R25,Y+1 63 | OR R24,R25 64 | BREQ m7 65 | ADIW R28,4 66 | LDI R25,0 67 | LDI R24,105 68 | CP R28,R24 69 | CPC R29,R25 70 | BRCC m6 71 | RJMP m5 72 | m6: SET 73 | m7: RET 74 | 75 | FindSlot: CLT 76 | LDI R29,0 77 | LDI R28,97 78 | m8: LDD R24,Y+2 79 | LDD R25,Y+3 80 | CP R30,R24 81 | CPC R31,R25 82 | BREQ m10 83 | ADIW R28,4 84 | LDI R25,0 85 | LDI R24,105 86 | CP R28,R24 87 | CPC R29,R25 88 | BRCC m9 89 | RJMP m8 90 | m9: RJMP FreeSlot 91 | m10: RET 92 | 93 | Delay_: POP R31 94 | POP R30 95 | RCALL FindSlot 96 | BRTS m11 97 | STD Y+2,R30 98 | STD Y+3,R31 99 | ST Y,R26 100 | STD Y+1,R27 101 | m11: RET 102 | 103 | Mig: SBI PORTB,1 104 | LDI R27,0 105 | LDI R26,1 106 | RCALL Delay_ 107 | CBI PORTB,1 108 | RET 109 | 110 | Migni: RCALL Mig 111 | LDI R27,0 112 | LDI R26,50 113 | RCALL Delay_ 114 | RJMP Migni 115 | 116 | main: CLR R3 117 | SBI ACSR,7 118 | SBI DDRB,1 119 | LDI R24,19 120 | OUT OCR0A,R24 121 | LDI R24,2 122 | OUT TCCR0A,R24 123 | OUT TCNT0,R3 124 | LDI R24,5 125 | OUT TCCR0B,R24 126 | RCALL Migni 127 | m12: RCALL Time 128 | RJMP m12 129 | -------------------------------------------------------------------------------- /examples/TM-Led/tmLed.f: -------------------------------------------------------------------------------- 1 | 2 | \ знакомство форта с AVR 3 | S" ~iva/AVR/asmAVR.f" INCLUDED \ ассемблер, дизассемблер и другое 4 | 0x 910A CONSTANT device \ Процессор ATtiny2313 5 | S" ~iva/AVR/selectAVR.f" INCLUDED \ набор команд для данного микроконтроллера 6 | DECIMAL 7 | \ далее уже сам проект 8 | 1000000 CONSTANT CLK \ тактовая частота 9 | 10 | \ ====================== ПОРТЫ ================================================ 11 | BitsIn PortB 12 | 1 #BitIs GRN \ выход для зеленого светодиода 13 | BitsIn ddrB 14 | 1 #BitIs dGRN \ выход для зеленого светодиода 15 | 16 | \ ====================== РЕГИСТРЫ ============================================= 17 | r3 register: (0) \ хранилище нуля 18 | 19 | \ ====================== библиотеки =========================================== 20 | #def sek 50 * chskTime \ перевод секунд в тики таймера 21 | #def mnt 60 * sek \ перевод минут в тики таймера 22 | 2 CONSTANT #timers 23 | #def TIFR0 TIFR 24 | S" ~iva/AVR/libs/timers.f" INCLUDED 25 | 26 | \ ====================== подпрограммы ========================================= 27 | code Mig \ мигни разок 28 | _/ GRN ldiW X,1 sek 32 / rcall Delay: \_ GRN 29 | ret c; 30 | 31 | \ ====================== подзадачи ============================================ 32 | code Migni 33 | \ постоянно мигать 34 | begin 35 | rcall Mig ldiW X,1 sek rcall Delay: \ индикация режима 36 | again 37 | c; 38 | 39 | \ ====================== главный ============================================== 40 | code main [IF] .( Частота таймера0 недостижима :() CR QUIT [THEN] 51 | mov OCR0A,r 52 | ldi r,{b WGM01 } mov TCCR0A,r \ режим CTC 53 | mov TCNT0,(0) \ обнулить таймер0 54 | ldi r,{b CS02 CS00 } mov TCCR0B,r \ 1024 55 | rcall Migni \ запуск задачи мигания 56 | begin \ рабочий цикл 57 | rcall time 58 | again 59 | c; 60 | \ main val? 61 | 62 | 63 | HEX-SAVE tmLed.hex \ выложим скомпилированную прошивку 64 | chip! 65 | \ ============ прошивка чипа! ================================================= 66 | \ SzCntrl 67 | CodeType label: EndBootable 68 | finger CONSTANT EndApp 69 | 70 | .( ROM =) EndBootable . cr 71 | .( RAM =) RAM[ finger ]RAM SRAM_START - . cr 72 | -------------------------------------------------------------------------------- /fraction.f: -------------------------------------------------------------------------------- 1 | \ fraction действия над простыми дробями 2 | \ дроби представляются парой целых чисел, 3 | \ порядок на стеке: числитель знаменатель -- 4 | 5 | : (.) ( u -- ) \ печать числа без пробела в конце 6 | 0 <# #S #> TYPE ; 7 | : NOD ( u1 u2 -- u) \ наибольший общий делитель 8 | \ ." ." 9 | TUCK MOD ?DUP IF RECURSE ELSE EXIT THEN ; 10 | 11 | : NORM ( u1 u2 -- u3 u4) \ нормализация дроби 12 | 2DUP NOD ( u1 u2 d) 13 | ROT OVER / 14 | -ROT / ; 15 | : ./, ( ч з --) \ печать дроби 16 | DUP 1 = 17 | IF DROP . \ целое число 18 | ELSE SWAP (.) ." /" (.) 19 | THEN ; 20 | : ./. ( ч з --) \ печать дроби с пробелом 21 | ./, SPACE ; 22 | : /. ( ч з --) \ печать нормализованной дроби 23 | NORM ./. ; 24 | : INT/. ( ч з --) \ печать дроби с выделенной целой частью 25 | DUP -ROT /MOD 26 | ?DUP 27 | IF OVER 28 | IF ." [" (.) ." +" SWAP NORM ./, ." ]" 29 | ELSE . 2DROP \ остаток=0 30 | THEN 31 | ELSE SWAP /. \ целое=0 32 | THEN ; 33 | : /+ ( ч1 з1 ч2 з2 -- сумма-дробь ) 34 | ROT DUP >R -ROT DUP R> = \ сравнение знаменателей 35 | IF DROP ROT + SWAP \ частный случай, знаменатели равны 36 | ELSE ROT 2DUP * >R ROT * >R * R> + R> \ общий случай 37 | THEN ; 38 | : /- ( ч1 з1 ч2 з2 -- разность-дробь ) 39 | ROT DUP >R -ROT DUP R> = \ сравнение знаменателей 40 | IF DROP ROT - SWAP \ частный случай, знаменатели равны 41 | ELSE ROT 2DUP * >R ROT * >R * R> - R> \ общий случай 42 | THEN ; 43 | : /* ( ч1 з1 ч2 з2 -- произведение-дробь ) 44 | ROT * >R * R> ; 45 | : /: ( ч1 з1 ч2 з2 -- частное-дробь ) 46 | SWAP /* ; 47 | 48 | 49 | -------------------------------------------------------------------------------- /fuses.f: -------------------------------------------------------------------------------- 1 | \ слова для работы с фузами и локами 2 | VARIABLE FdepL \ для замера глубины 3 | 4 | : FUSE{ ( ) \ начало работы с фузами 5 | FUSE[ DEPTH FdepL ! \ подключить словарь и запомнить текущую глубину стека 6 | ; 7 | : LOCK{ ( ) \ начало работы с локами 8 | LOCK[ DEPTH FdepL ! \ подключить словарь и запомнить текущую глубину стека 9 | ; 10 | DEFER [1/0] 11 | : }=x ( j*x -- ) \ поименованые биты установить/сбросить в [1/0] 12 | BEGIN 13 | DEPTH FdepL @ - 0 > 14 | WHILE 15 | label-find DUP 16 | IF 17 | label-value @ [1/0] SWAP B>Seg 18 | ELSE 19 | TRUE ABORT" Неизвестный бит." 20 | THEN 21 | REPEAT 22 | RESTORE-VOCS RESTORE-SEGMENT ; 23 | 24 | :NONAME 1 ; \ установить младший бит 25 | : }=1 ( j*x -- ) \ поименованые биты установить в 1 26 | LITERAL IS [1/0] }=x ; 27 | 28 | :NONAME 0 ; \ обнулить младший бит 29 | : }=0 ( j*x -- ) \ поименованые биты сбросить в 0 30 | LITERAL IS [1/0] }=x ; 31 | 32 | : Fuses? ( ) \ показать фузы которые будут записаны 33 | \ # name = bit 34 | FUSE[ labels-map ]FUSE ; 35 | : Locks? ( ) \ показать локи которые будут записаны 36 | \ # name = bit 37 | LOCK[ labels-map ]LOCK ; 38 | 39 | 40 | \ eof 41 | 42 | -------------------------------------------------------------------------------- /intel-hex.f: -------------------------------------------------------------------------------- 1 | \ слова для работы с файлами в формате intel-HEX 2 | \ автор: ~iva 2009 3 | 4 | \ ======== ИНФО ================================================================ 5 | ( Каждая запись представляет собой ASCII-строку файла. 6 | Одна строка – одна запись. 7 | Общий формат записей 8 | ----------------------------------------------------- 9 | «:» 1байт 2байта 1байт RECLEN_байт 1байт 10 | ----------------------------------------------------- 11 | v v v v v v 12 | ^маркер записи 13 | ^количество байт в поле данных 14 | RECLEN 15 | ^смещение 16 | ^тип записи 17 | 00 - данные 18 | 01 - конец файла 19 | 02 - адрес сегмента 20 | 03 - сегментный адрес старта 21 | 04 - линейный адрес 22 | 05 - линейный адрес старта 23 | ^данные 24 | ^контрольная сумма. 25 | сумма всех байт записи, 26 | исключая «:», по модулю 256 27 | должна быть равной нулю 28 | Пример: 29 | :100000001BC6189518951895189518951895D9C563 30 | :10 0010 00 18951895189518951895189518951895 78 31 | :00000001FF 32 | ) 33 | 34 | \ ======== ЗАДАЧИ ============================================================== 35 | \ 1-ая задача: 36 | \ нужно открыть файл, прочитать его с контролем, разместить данные в буфере 37 | \ : LOAD-AS-HEX ( c-adr u -- ) c-adr u - это строка с именем файла 38 | \ : HEX-LOAD ( "имя-файла" -- ) 39 | 40 | \ 2-ая задача: 41 | \ сохранить данные из текущего сегмента в файл в hex-формате 42 | \ : SAVE-AS-HEX ( c-adr u -- ) c-adr u - это строка с именем файла 43 | \ : HEX-SAVE ( "имя-файла" -- ) 44 | 45 | \ ======== ПОДКЛЮЧАЕМЫЕ ФАЙЛЫ и слова нужные не только здесь =================== 46 | VOCABULARY INTEL-HEX 47 | SAVE-VOCS 48 | ALSO INTEL-HEX DEFINITIONS 49 | 50 | \ ======== КОНСТАНТЫ И ПЕРЕМЕННЫЕ ============================================== 51 | 0 VALUE fid \ идентификатор файла 52 | 50 VALUE len \ максимальная длина строки 53 | CREATE bstr len ALLOT \ буфер для приема строки 54 | 55 | \ ======== СЛУЖЕБНЫЕ СЛОВА ДЛЯ ОПРЕДЕЛЕНИЯ ГЛАВНЫХ СЛОВ ======================== 56 | : число ( c-adr i -- c-adr+i u2) 57 | \ возвращает число записанное i символами в строке c-adr 58 | 0 -ROT 0 -ROT >NUMBER THROW \ ABORT" Ошибка преобразования числа." 59 | -ROT D>S 60 | ; 61 | 62 | : HEX>число ( c-adr n -- c-adr+n u) 63 | \ читает n символов из c-adr, возвращает число им соответствующее и 64 | \ увеличивает адрес 65 | HEX[ 66 | ['] число CATCH \ чтобы вернуться и востановить систему счисления 67 | IF ]HEX .S CR TRUE ABORT" Ошибка преобразования числа." THEN 68 | ]HEX ; 69 | : BYTE>STR ( b -- c-adr u) \ преобразует байт в 2-х символьную строку, 70 | \ согласно текущей системы счисления 71 | 0 <# # # #> 72 | ; 73 | : BYTE>S ( b -- ) \ помещает байт в символьном виде в S-строку, 74 | BYTE>STR +>S 75 | ; 76 | : проверить_запись ( c-adr u -- |ABORT ) 77 | \ проверяет признак записи, контрольную сумму и преобразовывает символьное 78 | \ представление байт в числовое. 79 | \ пишет результат преобразования в строку по исходному адресу c-adr 80 | OVER C@ [CHAR] : <> ABORT" Ошибка формата записи." \ проверка ":" 81 | \ c-adr u 82 | OVER 1+ 0 ROT \ c-adr c-adr CS=0 u 83 | 2/ 0 DO \ c-adr1 c-adr2 CS 84 | SWAP \ c-adr1 CS c-adr2 85 | 2 HEX>число >R \ c-adr1 CS c-adr2+2 R:byte 86 | ROT R@ OVER C! \ CS c-adr2+2 c-adr1 R:byte 87 | 1+ \ CS c-adr2+2 c-adr1+1 R:byte 88 | ROT >R SWAP \ c-adr1+1 c-adr2+2 R:byte CS 89 | R> R> + \ c-adr1+1 c-adr2+2 CS 90 | LOOP 91 | 255 AND ABORT" Ошибка контрольной суммы строки." 92 | 2DROP 93 | ; 94 | : Reclen ( -- RECLEN) 95 | bstr C@ ; 96 | : Offset ( -- OFFSET) 97 | bstr 1+ C@ 8 LSHIFT 98 | bstr 2 + C@ 99 | + ; 100 | : Tipe ( -- TIPE) 101 | bstr 3 + C@ ; 102 | : a-Dat ( -- a-adr) 103 | bstr 4 + ; 104 | : не_последняя? ( -- TRUE | FALSE) 105 | \ читает заголовок записи, flag TRUE если это не последняя запись 106 | \ если это данные, то возвращает число байт данных, 107 | \ иначе только 0 и true 108 | Tipe 0 = IF Reclen TRUE EXIT THEN \ T=0 'данные' 109 | Tipe 1 = IF FALSE EXIT THEN \ T=1 'последняя запись' 110 | Tipe 5 > ABORT" Неизвестный тип записи" \ T>5 ругаемся 111 | 0 TRUE \ T=2...5 игнорируем 112 | ; 113 | 114 | : в_сегмент ( n -- ) 115 | IF \ размещение данных в буфере 116 | Offset ORG \ по адресу смещения 117 | a-Dat Reclen \ c-adr reclen 118 | OVER + SWAP DO I C@ C>Seg LOOP 119 | THEN ; 120 | 121 | : закрыть_файл ( -- ) 122 | fid CLOSE-FILE THROW ; 123 | 124 | \ =========== ГЛАВНЫЕ СЛОВА ==================================================== 125 | PREVIOUS DEFINITIONS ALSO INTEL-HEX 126 | : Hex2Bin ( c-adr u -- c-adr u/2) \ преобразование HEX-строки в бинарную 127 | 2/ 2DUP OVER SWAP 128 | OVER + SWAP 129 | ?DO \ c-adr' 130 | 2 HEX>число \ c-adr' n 131 | I C! 132 | LOOP DROP 133 | ; 134 | 135 | : LOAD-AS-HEX ( c-adr u -- ) 136 | \ загрузить файл с именем в c-adr u в текущий сегмент 137 | R/O OPEN-FILE THROW TO fid 138 | BEGIN 139 | bstr DUP len 2 - fid READ-LINE THROW DROP \ считать_запись 140 | проверить_запись 141 | не_последняя? 142 | WHILE \ данные 143 | в_сегмент 144 | REPEAT 145 | закрыть_файл 146 | ; 147 | : HEX-LOAD ( "имя-файла" -- ) 148 | BL WORD COUNT LOAD-AS-HEX 149 | ; 150 | : SAVE-AS-HEX ( c-adr u -- ) 151 | \ сохранить текщий сегмент в файл с именем в строке c-adr u 152 | \ файл создается или перезаписывается без вопросов 153 | W/O CREATE-FILE ABORT" Ошибка создания файла." TO fid 154 | HEX[ 155 | 0 finger! 156 | BEGIN \ цикл по строкам 157 | S" :" >S \ старт записи 158 | wender finger - 16 MIN DUP >R BYTE>S \ RECLEN 159 | finger 256 /MOD DUP >R BYTE>S DUP >R BYTE>S \ OFFSET 160 | S" 00" +>S \ TIPE 161 | R> R> + R@ + \ CS 162 | \ цикл по байтам 163 | R> 0 \ RECLEN 0 164 | DO \ CS 165 | >R Seg>C DUP >R \ byte R:CS byte 166 | BYTE>S \ R:CS byte 167 | R> R> + \ CS' 168 | LOOP 169 | 255 AND 256 SWAP - BYTE>S 170 | S@ fid WRITE-LINE THROW S>DROP 171 | wender finger = \ пока wender > finger 172 | UNTIL 173 | ]HEX 174 | S" :00000001FF" fid WRITE-LINE THROW \ последняя запись 175 | fid CLOSE-FILE THROW 176 | ; 177 | : HEX-SAVE ( "имя-файла" -- ) 178 | BL WORD COUNT SAVE-AS-HEX ; 179 | RESTORE-VOCS 180 | \ ========= ТЕСТЫ И ПРИМЕРЫ ==================================================== 181 | \ S" prog.hex" LOAD-AS-HEX 182 | \ HEX-SAVE PROG.HEX 183 | \ RAM 184 | \ HEX-LOAD tst.hex 185 | \ HEX-SAVE TST.HEX 186 | \ ROM 187 | \ HEX-SAVE PROG2.HEX 188 | 189 | \ BYE 190 | 191 | -------------------------------------------------------------------------------- /libs/CRC24asm.f: -------------------------------------------------------------------------------- 1 | \ ====== прерывания не должны изменять эти регистры =========================== 2 | \ ====== или использовать их как константы ==================================== 3 | WARNING @ 4 | WARNING OFF 5 | #def iByte r16 \ счетчик/текущий байт ================================ 6 | #def rPol r17 \ полином ============================================= 7 | WARNING ! 8 | \ ============================================================================= 9 | \ подсчёт контрольной суммы CRC24, сдвиг влево 10 | \ 0x864CFB \ полином 11 | \ 0xB704CE \ начальное значение 12 | code CRC24flash ( Z=adr R=u -- Z=adr+u NUM[0..2]=CRC24 ) 13 | \ вход: адрес строки (Z) и ее счётчик (R) 14 | push iByte push rPol 15 | ldi rPol,0xB7 mov Num2,rPol \ начальное значение 16 | ldi rPol,0x04 mov Num1,rPol \ начальное значение 17 | ldi rPol,0xCE mov Num0,rPol \ начальное значение 18 | begin \ цикл по байтам 19 | LPM iByte,Z+ eor Num2,iByte \ получить новый байт 20 | ldi iByte,8 21 | for \ цикл по битам 22 | lsl Num0 rol Num1 rol Num2 23 | if_c ldi rPol,0x86 eor Num2,rPol 24 | ldi rPol,0x4C eor Num1,rPol 25 | ldi rPol,0xFB eor Num0,rPol 26 | then 27 | next iByte 28 | sbiW R,1 29 | wait0 30 | pop rPol pop iByte 31 | ret c; 32 | 33 | \ CRC24flash val? 34 | 35 | 36 | \eof 37 | code tstCRC 38 | \ ldiW Z,CRC24flash ldiW R,tstCRC CRC24flash - 39 | ldiW Z,0 ldiW R,Sign 40 | rcall CRC24flash 41 | mov r16,Num0 42 | mov r17,Num1 43 | mov r18,Num2 44 | ret c; -------------------------------------------------------------------------------- /libs/CRC8asm.f: -------------------------------------------------------------------------------- 1 | \ ====== прерывания не должны изменять эти регистры =========================== 2 | \ ====== или использовать их как константы ==================================== 3 | #def iByte r0 \ счётчик байт ============================================ 4 | #def rPol r1 \ полином ================================================= 5 | \ ============================================================================= 6 | \ подсчёт контрольной суммы CRC8 (x^8+x^5+x^4+1), сдвиг влево 7 | code CRC8 ( y=adr r=u -- y=adr+u r=CRC8 ) 8 | \ вход: адрес строки (Y) и ее счётчик (r) 9 | \ прим: CRC8 работает до 15 байт данных 10 | \ обнаружение одинарных, двойных, тройных и всех нечетных ошибок 11 | push iByte push rPol push rH 12 | ldi rH,Polynomial mov rPol,rH 13 | mov iByte,r \ iByte=число байт в строке 14 | ldi r,0xAC \ начальное значение (CRC8 от FF при стартовом 0) 15 | for \ цикл по байтам 16 | ld rH,y+ eor r,rH \ получить новый байт 17 | ldi rH,8 18 | for \ цикл по битам 19 | lsl r if_c eor r,rPol then 20 | next rH 21 | next iByte 22 | pop rH pop rPol pop iByte 23 | ret c; 24 | 25 | 26 | -------------------------------------------------------------------------------- /libs/CRCx.f: -------------------------------------------------------------------------------- 1 | \ Варианты вычисления CRC при битовом и байтовом доступе 2 | \ Начальный значения при том и другом доступе различны для сходимости результатов 3 | 4 | 5 | 6 | 0x31 CONSTANT Polynomial8 7 | \ класический вариант 8 | : CRC8f ( adr u -- crc8) \ подсчет контрольной суммы 9 | OVER + SWAP 10 | 0xFF -ROT \ \ начальное значение №1 11 | \ 0xAC -ROT \ \ начальное значение №2 12 | do \ цикл по байтам 13 | I C@ XOR 14 | 8 0 do \ цикл по битам 15 | 1 LSHIFT 16 | DUP 0x100 AND 17 | if Polynomial8 XOR then 18 | loop 19 | loop 20 | 0xFF AND 21 | ; 22 | \ S" 123456789" CRC8f .uhex .( <---CRC8f) cr 23 | \ S" 1" CRC8f .uhex .( <---CRC8f) cr 24 | \ S" 123456789" 2DUP + 0x0 SWAP C! 1+ CRC8f .uhex .( <---CRC8f) cr 25 | \ S" 123456789" 2DUP + 0xF7 SWAP C! 1+ CRC8f .uhex .( <---CRC8f) cr 26 | 27 | \ вариант который показывает причину разницы 28 | : CRC8f' ( adr u -- crc8) \ подсчет контрольной суммы 29 | 1+ 30 | OVER + SWAP 31 | 0xff -ROT \ -------------------------! 32 | do \ цикл по байтам 33 | 8 0 do \ цикл по битам 34 | 1 LSHIFT 35 | DUP 0x100 AND 36 | if Polynomial8 XOR then 37 | loop 38 | I C@ XOR 39 | loop 40 | 0xFF AND 41 | ; 42 | \ S" 123456789" CRC8f' .uhex .( <---CRC8f') cr 43 | 44 | \ вариант класический, но с измененным начальным значением 45 | \ для сосвместимости с битовым доступом 46 | : CRC8f" ( adr u -- crc8) \ подсчет контрольной суммы 47 | OVER + SWAP 48 | 0xAC -ROT \ -------------------------! 49 | do \ цикл по байтам 50 | I C@ XOR 51 | 8 0 do \ цикл по битам 52 | 1 LSHIFT 53 | DUP 0x100 AND 54 | if Polynomial8 XOR then 55 | loop 56 | loop 57 | 0xFF AND 58 | ; 59 | \ S" 123456789" CRC8f" .uhex .( <---CRC8f") cr 60 | 61 | VARIABLE shiftByte 62 | \ битовый вариант, реализует класическое деление полиномов 63 | : CRC8b ( adr u -- crc8) \ подсчет контрольной суммы 64 | OVER + SWAP 65 | \ 0xFC -ROT \ начальное значение №1 66 | 0xFF -ROT \ начальное значение №2 67 | do \ цикл по байтам 68 | I C@ shiftByte C! 69 | 8 0 do \ цикл по битам 70 | 1 LSHIFT 71 | shiftByte C@ 1 LSHIFT DUP shiftByte C! 0x100 AND if 1+ then 72 | DUP 0x100 AND 73 | if Polynomial8 XOR then 74 | loop 75 | loop 76 | 8 0 do \ цикл по 0 битам 77 | 1 LSHIFT 78 | DUP 0x100 AND 79 | if Polynomial8 XOR then 80 | loop 81 | 0xFF AND 82 | ; 83 | \ S" 123456789" CRC8b .uhex .( <---CRC8b) cr 84 | \ S" 123456789" 2DUP + 0x0 SWAP C! 1+ CRC8b .uhex .( <---CRC8b) cr 85 | 86 | VARIABLE _CRC_ \ регистр CRC 87 | VARIABLE _MASK_ \ маска старшего бита 88 | VARIABLE _Poly_ \ полином 89 | 90 | : CRC< abort" Больше байта!" 42 | scaleK \ масштабный коэффициент 43 | OVER /mod >R OVER 2/ < 0= 1 AND R> + \ деление с округлением результата 44 | word-split abort" Больше слова!" 45 | byte-split 46 | ; 47 | \ таблица соответствий 48 | t{ 26 d# 181 d# 338 d# 494 d# 651 d# 808 d# 966 d# \ -50... +10 49 | 1125 d# 1284 d# 1443 d# 1602 d# 1762 d# 1923 d# 2084 d# \ +20... +80 50 | 2245 d# 2407 d# 2569 d# 2731 d# 2893 d# 3057 d# 3218 d# \ +90... +150 51 | }bytes dLUT 52 | \ dLUT hex[ see ]hex cr 53 | \ dLUT see cr 54 | \ из исходного числа вычитать каждое значение из таблицы, 55 | \ пока не получится отрицательное число rest 56 | \ Celsius=(i-5)*10 - |rest|*10/Di - общая формула 57 | \ i - позиция в таблице [0..20] 58 | \ Di - дельта i-тая 59 | \ Celsius=(i-5)*10 - |rest|*Ki - расчетная формула 60 | \ Ki - i-тый коэффициент 61 | #def ii*5 c[ mov rH,ii lsl ii lsl ii add ii,rH ]c 62 | #def ii*10 c[ lsl ii mov rH,ii lsl ii lsl ii add ii,rH ]c 63 | 64 | #def tH r0 65 | #def rA X 66 | #def rB r 67 | code M16*8 ( rA rb -- A*B ) \ 16-ти и 8-ми разрядные сомножители, 24-разрядный результат 68 | \ rA - номер младшего регистра пары первого сомножителя 69 | \ rb - байт второго сомножителя 70 | \ результат замещает сомножители 71 | \ старший->rA младший->rb 72 | pushW tH \ служебная пара 73 | push ii 74 | clrW tH ldi ii,8 lsr rB 75 | for 76 | if_c addW tH,rA then rorW tH ror rB 77 | next ii 78 | movW rA,tH 79 | pop ii popW tH 80 | ret c; 81 | 82 | #def X*r rcall M16*8 83 | OutData 1 = 84 | [IF] \ выдача результата в 1/100 градусах Цельсия 85 | code Celsius100 ( R=RAW -- R=Celsius) \ перевод в градусы Цельсия 86 | clr ii ldiW Z,dLUT 87 | begin LPM x,Z sub r,x sbc rH,(0) \ проход по dLUT 88 | while_nb C inc ii adiW Z,stepTbl repeat 89 | neg r \ положительное число которое надо умножить на k и вычесть 90 | adiW Z,1 LPM x,Z+ LPM xH,Z \ X=k 91 | X*r \ Xr=вычитаемое (B) 92 | \ xH=b3 xL=b2 r=b1 - 24 бита 93 | push xH push x push r 94 | mov r,ii ldiW X,1000 X*r \ xr=ii*1000 95 | ldi rH,5000 (LB) sub r,rH 96 | ldi rH,5000 (HB) sbc x,rH 97 | \ xr=уменьшаемое (A) (ii*1000-5000)=(ii-5)*1000 98 | \ x=a3 r=a2 - 16 бит 99 | pop rH neg rH \ rH=a1-b0 (a0=0) 100 | pop rH sbc r,rH \ r=a2-b2-c 101 | pop rH sbc x,rH \ x=a3-b3-c 102 | mov rH,x \ R=A-B (16 бит) 103 | ret c; 104 | #def Celsius c[ rcall Celsius100 ]c 105 | [THEN] 106 | OutData 2 = 107 | [IF] \ выдача результата в градусах Цельсия в формате 1.8.7 108 | code Celsius1.8.7 ( R=RAW -- R=Celsius) \ перевод в градусы Цельсия 109 | clr ii ldiW Z,dLUT 110 | begin LPM x,Z sub r,x sbc rH,(0) \ проход по dLUT 111 | while_nb C inc ii adiW Z,stepTbl repeat 112 | subi ii,5 ii*5 \ ii=старший байт целой части в формате 1.8.7 113 | neg r \ положительное число которое надо умножить на k и вычесть 114 | adiW Z,1 LPM x,Z+ LPM xH,Z \ X=k 115 | X*r \ X=вычитаемое 116 | neg xL sbc ii,xH 117 | mov rH,ii mov r,x 118 | ret c; 119 | #def Celsius c[ rcall Celsius1.8.7 ]c 120 | [THEN] 121 | 122 | [ELSE] #def Celsius \ ничего не делать 123 | [THEN] 124 | 125 | finger StartLMT01_LUT - . .( <==== Размер LMT01_LUT) CR -------------------------------------------------------------------------------- /libs/USBtinySPI.f: -------------------------------------------------------------------------------- 1 | \ попытка сделать библиотеку 2 | \ нужно определить 3 | \ 1) Регистры: (из младших) rin, rout 4 | \ (r16 или старше) 5 | \ 2) Пин: 6 | \ 3) Флаг: fTransfert, fLink 7 | \ 4) "У" как указатель буфера 8 | BitsIn yl 9 | 2 #BitIs b4 \ бит заполнения буфера 10 | 11 | : finger8 finger 7 + 7 true xor and org ; \ перенос фингера на кратную позицию 12 | \ выделение памяти для буфера приёма/передачи 13 | ram[ 14 | finger8 8 take InBufOut \ для приёма и выдачи ( Адрес буфера должен быть кратен 8.) 15 | ]ram 16 | 17 | \ ============ прерывания! =============================== 18 | code USItransfertint 19 | in rin,sreg push rin 20 | in rin,USIDR \ принять байт из приёмника 21 | out USIDR,rout \ отдать байт передатчику 22 | set_b USIOIF \ погасить флаг 23 | st rin,y+ \ сохранить принятое в буфере 24 | ldd rout,y+3 \ подготовить байт для передачи 25 | if_b b4 26 | clr_b b4 set_b fTransfert \ признак конца передачи 27 | then 28 | pop rin out sreg,rin 29 | reti 30 | c; 31 | USI_OVFaddr vector> USItransfertint 32 | 33 | \ ============ подпрограммы ============================== 34 | code CheckLink \ тестирование связи 35 | \ в случае приёма правильной последовательности чисел, сформировать ответ 36 | \ и получив верный ответ - считать связь установленной. 37 | \ разрыв связи не фиксируется, флаг обнуляется только через RESET. 38 | in r,InBufOut cpi r,24 39 | if= in r,InBufOut 1+ cpi r,36 40 | if= in r,InBufOut 2+ cpi r,66 41 | if= in r,InBufOut 3 + cpi r,129 42 | if= 43 | ldi r,129 out USIDR,r 44 | ldi r,66 out rout,r 45 | ldi r,36 out InBufOut 4 +,r 46 | ldi r,24 out InBufOut 5 +,r 47 | else cpi r,153 48 | if= set_b fLink 49 | 50 | then 51 | then 52 | then 53 | then 54 | then 55 | ret c; 56 | code Answer \ ответ на запрос 57 | in r,InBufOut 58 | cpi r,0 59 | if= \ читать 60 | in r,InBufOut 1+ 61 | cpi r,1 ( 0 1 adrL adrH) 62 | if= \ выдать по адресу RAM 63 | in xL,InBufOut 2 + 64 | in xH,InBufOut 3 + 65 | ld r,x+ out USIDR,r 66 | ld r,x+ out rout,r 67 | ld r,x+ out InBufOut 4 +,r 68 | ld r,x out InBufOut 5 +,r 69 | else 70 | then 71 | else cpi r,1 ( 1 byte addrL addrH ) 72 | if= \ писать в RAM 73 | in xL,InBufOut 2 + 74 | in xH,InBufOut 3 + 75 | in r,InBufOut 1 + 76 | st x,r 77 | then 78 | then 79 | 80 | ret c; 81 | 82 | code Transfert? 83 | skip_b fTransfert ret \ ничего нет - выход 84 | clr_b fTransfert 85 | if_nb fLink 86 | rcall CheckLink 87 | else \ обработка запроса, подготовка ответа 88 | rcall Answer 89 | then 90 | ret c; 91 | 92 | 93 | 94 | \ ============ отладочные инструменты ==================== 95 | : tryConnect ( -- f ) \ истина если коннект успешен 96 | TRUE 97 | 40 0 98 | do 99 | 24 36 66 129 usb>spi drop \ запрос коннекта 100 | 100 pause 101 | 0 0 0 0 usb>spi \ получение ответа 102 | drop \ 4 = 103 | rbuf @ 405029505 <> 104 | if DROP FALSE LEAVE then 105 | loop 106 | ; 107 | SCK_MIN value SCKnow \ текущая скорость тактирования 108 | 0 VALUE OnLine \ флаг усановленной связи 109 | : RESETup ( -- ) \ 110 | SCKnow 0 powerup 50 pause 111 | SCKnow 1 powerup 100 pause 112 | \ cr SCKnow . 113 | ." ." \ прогрессор 114 | ; 115 | : OnDebug ( -- ) 116 | SCK_MIN to SCKnow 117 | begin 118 | RESETup tryConnect 0= 119 | while 120 | SCKnow SCK_MAX < 121 | while 122 | SCKnow 2* SCK_MAX min to SCKnow 123 | repeat 124 | powerdown ." Не удалось установить связь." cr exit 125 | then 126 | 24 36 66 153 usb>spi drop \ установить в чипе флаг линка 127 | TRUE TO OnLine \ установить в отладчике флаг линка 128 | ." Связь установлена, SCK=" SCKnow . cr 129 | ; 130 | : cmdAddr ( cmd0 cmd1 addrL addrH -- n) \ послать команду с адресом и 131 | \ получить ответ на предыдущий запрос 132 | online 0= if ondebug then 133 | usb>spi ; 134 | 135 | : NamedBuf ( adr n --) \ показать принятые байты с их именами 136 | \ adr - адрес первого байта в чипе, n - количество принятых байт 137 | 0 do ( adr') 138 | dup I + label>name type ." =" rbuf i + c@ . 139 | loop drop 140 | ; 141 | : fromRAM ( adr -- ) \ запросить данные по адресу из ОЗУ 142 | RAM[ 143 | 0 1 rot dup >r byte-split cmdAddr drop \ отправить запрос 144 | 0 1 r@ byte-split cmdAddr \ получить ответ 145 | r> swap NamedBuf 146 | ]RAM 147 | ; 148 | \ : aaa PCMSK fromRAM ; 149 | \ : ada TadcL fromRAM ; 150 | \ 200 pause OnDebug 151 | 152 | 153 | -------------------------------------------------------------------------------- /libs/USBtynySPI_.f: -------------------------------------------------------------------------------- 1 | #! /home/ivanov/spf-4.20/spf4 2 | \ знакомство форта с AVR 3 | S" AVR/asmAVR.f" INCLUDED \ ассемблер, дизассемблер и другое 4 | 0x 9108 CONSTANT device \ Процессор ATtiny25 5 | S" AVR/selectAVR.f" INCLUDED \ набор команд для данного микроконтроллера 6 | DECIMAL 7 | \ далее уже сам проект 8 | 9 | 4000000 CONSTANT cpuCLK \ тактовая частота 10 | 11 | \ описание флагов 12 | BitsIn GPIOR0 \ флаги 13 | _BitIs fCap \ 1=capture, 0=free 14 | _BitIs fMaster 15 | _BitIs fAlarm 16 | _BitIs fSync 17 | _BitIs fTx 18 | BitsIn GPIOR1 \ флаги USIdebuger 19 | _BitIs fLink 20 | _BitIs fTransfert 21 | 22 | \ описание портов 23 | BitsIn PinB 24 | 2 #BitIs bid \ пин шины данных 25 | 26 | BitsIn PortB 27 | 4 #BitIs Alarm \ временно, для индикации СД 28 | 29 | \ описание регистров 30 | \ === общего назначения ==== 31 | \ r0 register: 32 | \ r1 register: 33 | \ r2 register: 34 | \ r3 register: 35 | \ r4 register: 36 | \ r5 register: 37 | \ r6 register: 38 | \ r7 register: 39 | r8 register: sADC 40 | \ r9 register: sADCh 41 | r10 register: rin 42 | r11 register: rout 43 | r12 register: rADC 44 | \ r13 register: rADCh 45 | r14 register: iSreg 46 | r15 register: idat 47 | \ === загрузочные ==== 48 | r16 register: iStBit 49 | r17 register: stByte 50 | \ r18 register: 51 | \ r19 register: 52 | \ r20 register: 53 | \ r21 register: 54 | \ r22 register: 55 | \ r23 register: 56 | 57 | \ === пары ==== 58 | \ r24,r25 как R 59 | \ X register: 60 | \ Y register: указатель буфера приёма-передач 61 | BitsIn yl 62 | 2 #BitIs b4 63 | \ r29 - 64 | \ r30,r31 как указатель Z, доступ к памяти и косвенный вызов подпрограмм 65 | 66 | eprom[ 67 | \ 1 take CrtByte 68 | ]eprom 69 | 70 | ram[ SRAM_START org 71 | \ allot_w stEve1 72 | 7 array InBufOut \ для приёма и выдачи 73 | InBufOut 7 AND [IF] cr .( Адрес буфера InBufOut дложен быть кратен 8.) quit [then] 74 | ]ram 75 | \ ============ таблицы =================================== 76 | 77 | \ ============ прерывания! =============================== 78 | TCNT0 PORT: TCNTi 79 | OCR0A PORT: OCRi 80 | OVF0addr constant iOVaddr 81 | OC0Aaddr constant iCompAddr 82 | PCI0addr constant iEdgeAddr 83 | \ S" iware.f" INCLUDED \ подключить библиотеку i-ware 84 | 85 | code USItransfertint 86 | in rin,USIDR 87 | out USIDR,rout 88 | set_b USIOIF 89 | st rin,y+ 90 | ldd rout,y+3 91 | if_b b4 clr_b b4 set_b fTransfert then 92 | reti c; 93 | USI_OVFaddr vector> USItransfertint 94 | 95 | code ADCint \ преобразование завершено 96 | inW rADC,ADCl \ принять результат 97 | \ add sADC,rADC add sADC 1+,rADC 1+ \ усреднение 98 | \ lsr sADC 1+ ror sADC 99 | set_b ADSC \ запустить новое измерение 100 | reti c; 101 | ADCCaddr vector> ADCint 102 | 103 | \ ============ подпрограммы ============================== 104 | code CheckLink \ тестирование связи 105 | \ в случае приёма правильной последовательности чисел, сформировать ответ 106 | \ и получив верный ответ - считать связь установленной. 107 | \ разрыв связи не фиксируется, флаг обнуляется только через RESET. 108 | in r,InBufOut cpi r,24 109 | if= in r,InBufOut 1+ cpi r,36 110 | if= in r,InBufOut 2+ cpi r,66 111 | if= in r,InBufOut 3 + cpi r,129 112 | if= 113 | ldi r,129 out USIDR,r 114 | ldi r,66 out rout,r 115 | ldi r,36 out InBufOut 4 +,r 116 | ldi r,24 out InBufOut 5 +,r 117 | else cpi r,153 118 | if= set_b fLink 119 | set_b alarm 120 | else clr_b alarm then 121 | then 122 | then 123 | then 124 | then 125 | ret c; 126 | code Answer \ ответ на запрос 127 | in r,InBufOut cpi r,0 128 | if= in r,InBufOut 1+ cpi r,1 129 | if= \ выдать по адресу RAM 130 | in xL,InBufOut 2 + 131 | in xH,InBufOut 3 + 132 | ld r,x+ out USIDR,r 133 | ld r,x+ out rout,r 134 | ld r,x+ out InBufOut 4 +,r 135 | ld r,x out InBufOut 5 +,r 136 | then 137 | then 138 | 139 | ret c; 140 | \ ============ программа ================================= 141 | code main 142 | \ nop 143 | begin 144 | if_b fTransfert 145 | clr_b fTransfert 146 | if_nb fLink 147 | rcall CheckLink 148 | else \ обработка запроса, подготовка ответа 149 | rcall Answer 150 | then 151 | then 152 | again 153 | 154 | c; 155 | \ ============ инициализация! ============================ 156 | 163 | CODE Ini 164 | in r,MCUSR \ определить причину сброса 165 | if_b rPORF \ если по включению 166 | \ обнулить_память 167 | clr r0 ldiw y,SRAM_START ldiw z,RAMend IOEND - 168 | begin st y+,r0 sbiw z,1 wait0 169 | \ обнулить_регистры 170 | ldi z,zl 1- 171 | begin st z,r0 sbiw z,1 wait0 172 | then 173 | \ установка тактовой частоты 174 | ldi r,{b CLKPCE } out CLKPR,r 175 | ldi r,1 out CLKPR,r \ 8M/2=4M 176 | \ иницировать указатель стека 177 | ldiW r,RAMEND outW spl,r 178 | \ настройки USIdeb 179 | ldiW y,InBufOut \ указатель на буфер приёма передачи дебагера 180 | \ общая настройка 181 | ldi r,{b ACD } out ACSR,r \ отключить аналоговый компаратор 182 | \ настройка выходов 183 | ldi r,{b alarm PB1 } out ddrb,r 184 | ldi r,{b PB0 } out portb,r \ подтянуть вход 185 | \ прерывания PCINT 186 | ldi r,{b bid } out PCMSK,r \ разрешить прерывания только от пина шины данных 187 | ldi r,{b PCIE } out GIMSK,r \ разрешить PCINT 188 | \ USI как Slave SPI 189 | ldi r,{b USIOIE USIWM0 USICS1 } out USICR,r \ прерывание, 3-ware, внешний строб позитив 190 | set_b USIOIF \ сбросить флаг переполнения 191 | \ настройка таймеров 192 | \ собака, 193 | \ таймер0, для i-ware 194 | ldi r, {b CS00 } out TCCR0B,r \ clk=clk 195 | ldi r,{b TOIE0 } out TIMSK,r \ разрешить прерывание по переполнению t0 196 | \ таймер1 197 | \ таймер2 198 | \ настройка АЦП 199 | \ ldi r,12 out admux,r \ ref=Vcc in=1.1 200 | ldi r,{b REFS1 } 15 + out admux,r \ ref=1.1V in=TemperSens 201 | ldi r,{b ADEN ADIE } 7 + out ADCSRA,r \ clk/128 202 | set_b ADSC \ старт 203 | sei 204 | goto main 205 | C; 206 | 0 VECTOR> Ini 207 | cr 208 | HEX-save boot.hex 209 | \ ============ прошивка чипа! ============================ 210 | fuse{ ckdiv8 SUT0 }=1 \ эти фузы будут разпрограммированы 211 | \ fuse{ SUT0 }=1 \ эти фузы будут разпрограммированы 212 | fuse{ EESAVE SUT1 }=0 \ эти фузы будут запрограммированы 213 | \ lock{ lb1 lb2 }=0 \ чип будет залочен 214 | \ lock{ lb1 lb2 }=1 \ чип будет разлочен 215 | chip! \ записать всё 216 | 217 | .( ага ) wender . CR 218 | .s cr 219 | \ see-all 220 | \ labels-maps 221 | \ see-code SPItransfert 222 | 223 | \ ============ отладочные инструменты ==================== 224 | : tryConnect ( -- f ) \ истина если коннект успешен 225 | TRUE 226 | 10 0 227 | do 228 | 24 36 66 129 usb>spi drop \ запрос коннекта 229 | 20 pause 230 | 0 0 0 0 usb>spi \ получение ответа 231 | drop \ 4 = 232 | rbuf @ 405029505 <> 233 | if DROP FALSE LEAVE then 234 | loop 235 | ; 236 | SCK_MIN value SCKnow \ текущая скорость тактирования 237 | 0 VALUE OnLine \ флаг усановленной связи 238 | : RESETup ( -- ) \ 239 | SCKnow 0 powerup 50 pause 240 | SCKnow 1 powerup 100 pause 241 | ." ." \ прогрессор 242 | ; 243 | : OnDebug ( -- ) 244 | SCK_MIN to SCKnow 245 | begin 246 | RESETup tryConnect 0= 247 | while 248 | SCKnow SCK_MAX < 249 | while 250 | SCKnow 2* SCK_MAX min to SCKnow 251 | repeat 252 | powerdown ." Не удалось установить связь." cr exit 253 | then 254 | 24 36 66 153 usb>spi drop \ установить в чипе флаг линка 255 | TRUE TO OnLine \ установить в отладчике флаг линка 256 | ." Связь установлена, SCK=" SCKnow . cr 257 | ; 258 | : cmdAddr ( cmd0 cmd1 addrL addrH -- n) \ послать команду с адресом и получить ответ на предыдущий запрос 259 | online 0= if ondebug then 260 | usb>spi ; 261 | 262 | : NamedBuf ( adr n --) \ показать принятые байты с их именами 263 | \ adr - адрес первого байта в чипе, n - количество принятых байт 264 | 0 do ( adr') 265 | dup I + label>name type ." =" rbuf i + c@ . 266 | loop drop 267 | ; 268 | : fromRAM ( adr -- ) \ запросить данные по адресу из ОЗУ 269 | RAM[ 270 | 0 1 rot dup >r byte-split cmdAddr drop \ отправить запрос 271 | 0 1 r@ byte-split cmdAddr \ получить ответ 272 | r> swap NamedBuf 273 | ]RAM 274 | ; 275 | : aaa PCMSK fromRAM ; 276 | : ada sADC fromRAM ; 277 | \ 200 pause OnDebug 278 | \ see-code main 279 | \ bye 280 | 281 | -------------------------------------------------------------------------------- /libs/bootloader/BootLoader.f: -------------------------------------------------------------------------------- 1 | \ загрузчик 2 | [NOT?] ESC> [IF] S" console_codes.f" INCLUDED [THEN] 3 | [NOT?] 2VARIABLE [IF] S" lib/include/double.f" INCLUDED [THEN] 4 | 5 | 0 VALUE OnBoot \ начало загружаемой области 6 | 0 VALUE OffBoot \ конец загружаемой области 7 | 8 CONSTANT WDatMax \ максимальный размер пакета данных, четное, [2..10] 8 | 9 | \ ==================== либы ========================================================== 10 | 11 | \ =============== система программирования =================================== 12 | 13 | \ структура для сборки пакета программирования 14 | 0 15 | 1 -- prgS \ семафор программирования 16 | 1 -- cmd \ флаги команды 17 | 1 -- ZLpoint \ адрес записи младший байт 18 | 1 -- ZHpoint \ адрес записи старший байт 19 | 1 -- ZEpoint \ адрес записи дополнительный старший байт 20 | WDatMax -- Wdat \ WDatMax байт данных 21 | CONSTANT StructPrg 22 | 23 | DEFER Boot> ( adr u --) \ отправка пакета 24 | 25 | 26 | : Boot>. ( adr u --) \ показка пакетов 27 | OVER C@ ." prg: " HEX[ 2 .0R ]HEX ." | " \ prg 28 | OVER 1+ C@ \ cmd 29 | DUP [ {b fRst } ] LITERAL AND IF ." r" ELSE ." ." THEN 30 | DUP [ {b fWrt } ] LITERAL AND IF ." w" ELSE ." ." THEN 31 | [ {b fMsk } ] LITERAL AND IF ." s" ELSE ." ." THEN 32 | ." | " 33 | 2 /STRING 34 | 0 -ROT 35 | OVER + SWAP 36 | DO I C@ HEX[ 2 .0R ]HEX SPACE 37 | DUP 2 = IF ." |" SPACE THEN 38 | 1+ 39 | LOOP DROP 40 | CR 41 | ; 42 | 43 | 2VARIABLE fprgWad \ adr u полученного пыжа, u используется как флаг 44 | : 2off ( adr --) \ обнулить двойную переменную 45 | 0 0 ROT 2! 46 | ; 47 | : 2on ( adr --) \ установить двойную переменную 48 | -1 -1 ROT 2! 49 | ; 50 | fprgWad 2off 51 | 52 | : WaitPrgWad ( --) \ ждать пыжика от программируемого чипа 53 | fprgWad @ IF exit THEN \ не ждать 54 | getMs \ засечь время 55 | begin \ контроль времени ожидания 56 | getMs OVER 300 + < 57 | while 58 | fprgWad 2@ \ проверить получение 59 | sizePrgWad = IF DUP THEN 60 | until 61 | 1+ W@ 62 | SigLoader <> ABORT" Требуется замена загрузчика!" 63 | fprgWad 2off \ погасить его 64 | ." ." \ показать получение 65 | else ABORT" Нет ответа!" 66 | then DROP 67 | ; 68 | 69 | : Boot[ ( --) \ пометить начало загружаемой области 70 | finger TO OnBoot 71 | ; 72 | : ]Boot ( --) \ пометить конец загружаемой области 73 | finger TO OffBoot 74 | ; 75 | 76 | : +fcmd ( fMask --) \ установить флаги в команде 77 | S@ DROP cmd DUP C@ \ fMask adr cmd 78 | ROT OR SWAP C! 79 | ; 80 | 81 | : adrZ! ( adr -- ) \ установить адрес 82 | |3 ROT EMIT>S SWAP EMIT>S EMIT>S 83 | ; 84 | 0 VALUE defoltCMD 85 | : [Boot]? ( adr --f) \ проверка попадания adr внутрь загружаемой области 86 | OnBoot OffBoot 1- BETH 87 | ; 88 | : filling? ( adr src n -- f) \ продолжать заполнение? 89 | WDatMax < \ adr src f' \ 90 | IF ( adr src) OVER [Boot]? = 91 | IF ( adr) PAGESIZEb MOD ELSE DROP FALSE THEN 92 | ELSE 2DROP FALSE THEN 93 | ; 94 | : PackFill ( adr --adr' n ) \ пакет заполнения 95 | DUP [Boot]? >R \ adr R:(src) 96 | 0 97 | BEGIN \ adr n 98 | R@ IF OVER SegA C@ ELSE [ {b fMsk } ] LITERAL +fcmd 0 THEN \ adr n b 99 | EMIT>S 100 | 1+ SWAP 1+ SWAP \ adr+1 n+1 101 | OVER PAGESIZEb MOD 0= IF [ {b fWrt } ] LITERAL +fcmd THEN \ записать заполненную страницу 102 | \ условие 103 | 2DUP R@ SWAP filling? 104 | WHILE \ пока mod(adr), src-неизменился 105 | REPEAT 106 | R> DROP 107 | \ adr' n 108 | ; 109 | 110 | : HeadPack>S ( --) \ шапка пакета программирования 111 | NEW>S 112 | prgCMD01 EMIT>S 113 | defoltCMD EMIT>S 114 | ; 115 | : Pages! ( --) \ записать все страницы 116 | \ выровнять загружаемую область по страницам 117 | OnBoot PAGESIZEb / PAGESIZEb * \ adrPstart 118 | OffBoot PAGESIZEb /mod SWAP IF 1+ THEN PAGESIZEb * \ adrPstart adrPend 119 | OVER - \ adr0 u 120 | \ adr0 выровнен на начало первой страницы 121 | \ u кратно PAGESIZEb 122 | BEGIN DUP WHILE \ пока есть данные 123 | HeadPack>S \ шапка пакета 124 | OVER adrZ! 125 | \ тело пакета 126 | \ adr u 127 | SWAP PackFill \ u adr' n 128 | ROT SWAP - \ adr' u' 129 | fprgWad 2off \ что-б ждал пыжика 130 | S@ Boot> S>DROP \ отправка пакета 131 | REPEAT 132 | 2DROP 133 | ; 134 | 135 | : PingBoot ( -- ) \ проверочный пакет программатора 136 | 0 TO defoltCMD \ простая запись 137 | HeadPack>S 0 adrZ! 138 | fprgWad 2off \ что-б ждал пыжика 139 | S@ Boot> \ отправка пакета 140 | S>DROP 141 | ; 142 | : [Vect] ( --) \ загрузка области векторов 143 | OnBoot OffBoot 144 | 0 TO OnBoot ROM_FREE TO OffBoot 145 | ['] Pages! CATCH -ROT 146 | TO OffBoot TO OnBoot 147 | THROW 148 | ; 149 | : [VBoot] ( --) \ загрузка векторов загрузчика 150 | SEG 151 | BOOT-SEG TO SEG [Vect] 152 | TO SEG 153 | ; 154 | : [Boot] ( -- ) \ загрузка помеченной области 155 | Pages! 156 | ; 157 | 158 | : GoBoot ( adr --) \ выход из загрузчика по adr 159 | defoltCMD >R 160 | [ {b fRst } ] LITERAL TO defoltCMD 161 | HeadPack>S 162 | 2/ adrZ! 163 | fprgWad 2on \ что-б не ждал пыжика 164 | S@ Boot> S>DROP \ отправка пакета 165 | R> TO defoltCMD 166 | ; 167 | 168 | : Boot! ( --) \ полная загрузка 169 | \ проверить активности загрузчик в чипе 170 | PingBoot 171 | CR 172 | \ проверить пересечение с критической областью 173 | crtBootA OnBoot OffBoot BETH 174 | crtBootB OnBoot OffBoot BETH 175 | OR ABORT" В загружаемой области находится критический код загрузчика!" 176 | \ загрузка 177 | OffBoot OnBoot - 178 | S" [35m" ESC> 179 | ." ************************************" CR 180 | ." * Booting! *" CR 181 | ." * Размер для загрузки: " 5 .R ." байт. *" CR 182 | ." ************************************" CR 183 | 0 TO defoltCMD \ простая запись 184 | [VBoot] CR \ вектора загрузчика 185 | [Boot] CR \ загрузка помеченной области 186 | [Vect] CR \ вектора основной программы 187 | ." *************** END ****************" CR 188 | defoltText 189 | \ не всегда корректно идти на 0 190 | \ 0 GoBoot \ переход на основную программу 191 | ; 192 | 193 | : 4>S ( u--) 194 | |4 195 | >R >R >R 196 | EMIT>S 197 | R> EMIT>S 198 | R> EMIT>S 199 | R> EMIT>S 200 | ; 201 | : VSBoot! ( VerSign adr --) \ выход из загрузчика по adr 202 | NEW>S 203 | prgCMD01 EMIT>S 204 | [ {b fRst } ] LITERAL EMIT>S 205 | 2/ adrZ! \ адрес программы для записи сигнатуры 206 | 4>S \ данные=сигнатура 207 | fprgWad 2on \ что-б не ждал пыжика 208 | S@ Boot> \ отправка пакета 209 | S>DROP 210 | ; 211 | : _Boot! ( u -- ) 212 | 4>S 213 | fprgWad 2on \ что-б не ждал пыжика 214 | S@ Boot> S>DROP \ отправка пакета 215 | Boot! 216 | ; 217 | : SignBoot! ( VerSign -- ) \ загрузка групповая 218 | NEW>S prgVsig EMIT>S 219 | _Boot! 220 | ; 221 | : UIDBoot! ( UID -- ) \ загрузка индивидуальная 222 | NEW>S prgUID EMIT>S 223 | _Boot! 224 | ; 225 | -------------------------------------------------------------------------------- /libs/bootloader/BootLoader.odt: -------------------------------------------------------------------------------- 1 | /home/ivanov/IvaMobi2/Person/Job/Projects/EnSol/BootLoader.odt -------------------------------------------------------------------------------- /libs/bootloader/TinyBoot.f: -------------------------------------------------------------------------------- 1 | \ BootLoader 2 | \ без привязки к системе связи 3 | 4 | \ нужно объявить буферы приема и предачи 5 | \ #def inBoot iwFifoIn \ буфер из которого загрузчик читает пакеты 6 | \ #def outBoot iwFifOut \ буфер куда загрузчик пишет пакеты 7 | \ и подпрограмы 8 | \ #def iniSysLink iwIni \ инициализация буферов и связи 9 | \ #def BootPac> iwTransmitter \ подпрограмма передачи 10 | 11 | finger constant StartBoot \ маркер начала библиотеки загрузчика 12 | 13 | BitsIn rH ( aka cmd) 14 | 0 #BitIs fMsk \ флаг разностных данных 15 | 1 #BitIs fWrt \ флаг записи 16 | 2 #BitIs fRst \ флаг перезагрузки 17 | 18 | \ структура пакета программирования 19 | #def (sx) 1 \ семафор 20 | #def (cmd) (sx) 1 + \ команда 21 | #def (zL) (sx) 2 + \ адрес, младший 22 | #def (zH) (sx) 3 + \ адрес, старший 23 | #def (rP) (sx) 4 + \ адрес, дополнительный 24 | #def (d) (sx) 5 + \ данные 25 | 26 | \ 27 | 28 | BitsIn r0 ( aka SPMCSR) 29 | 7 AND #BitIs rSPMEN 30 | 31 | \ !!!!!!!!!!!!!!! критическое место !!!!!!!!!!!!!!!! 32 | finger CONSTANT crtBootA 33 | code do_WP ( Z=addrPage -- r=action Z=addrPage ) 34 | ldi r,{b PGERS SPMEN } 35 | _wp: rcall 0 \ очистить страницу 36 | ldi r,{b PGWRT SPMEN } \ записать страницу 37 | c; \ ----v 38 | code do_SPM ( r=action Z=addr r0:r1=data -- r=action Z=addr r0:r1=x) 39 | \ прерывания должны быть уже запрещены!!! 40 | \ выполнить инструкцию SPM 41 | mov SPMCSR,r SPM 42 | begin mov r0,SPMCSR wait_nb rSPMEN 43 | ret c; \ do_SPM val? 44 | finger _wp org c[ rcall do_SPM ]c org 45 | \ do_WP val_ val? 46 | \ !!!!!!!!!!!!!!! критическое место !!!!!!!!!!!!!!!! 47 | finger CONSTANT crtBootB 48 | 49 | 50 | 0 VALUE adrPrgWad 51 | #def ldZPrgWad c[ ldiW Z,adrPrgWad ]c 52 | code Flash2RAM ( Z=AddrFlash Y=AddrRam r=n --) 53 | \ скопировать n байт из Flash в RAM 54 | for lpm r0,Z+ st Y+,r0 next r 55 | ret c; 56 | 57 | [NOT?] KillDog 58 | [IF] 59 | code KillDog \ отключить собаку 60 | wdr cli \ обязательно, иначе иногда может не сработать 61 | ldi r,{b WDCE WDE } out WDTCR,r 62 | out WDTCR,(0) 63 | ret c; 64 | [THEN] 65 | code prgWad> ( -- ) \ пыж прогамматора 66 | ldi r,4 ldiW Y,outBoot rcall WtakeBuf 67 | if_t ret then 68 | st Y+,r \ запись n в голову пакета 69 | ldZ: ldZPrgWad rcall Flash2RAM 70 | ldiW Y,outBoot goto WendBufP \ передвинуть индекс записи 71 | c; \ prgWad> val? 72 | 73 | code >BootPac ( -- ) \ обработка входящих пакетов программатора 74 | ldiW Y,inBoot rcall RsizeBufP if0 ret then 75 | rcall RaddrBufP \ получить адрес пакета 76 | ldd rH,y+(sx) \ получить семафор 77 | cpi rH,prgCMD01 78 | if= ldd rH,y+(cmd) \ cmd 79 | rcall KillDog \ защита от случайного пакета ввода режима программирования 80 | \ получить адрес 81 | ldd zL,y+(zL) ldd zH,y+(zH) 82 | [FOUND?] RAMPZ [IF] ldd r0,y+(rP) mov RAMPZ,r0 [THEN] 83 | ( Z=adr Y->Pac rH=cmd ) \ команда и данные для flash 84 | ld ii,Y \ ii=размер пакета 85 | adiw Y,(d) \ Y->data 86 | skip_nb fRst icall \ мягкий выход (код НЕ зависит от положения) 87 | subi ii,sizePrgPac sizeCRC + \ размер поля данных в байтах 88 | lsr ii \ ii=количество данных, в словах 89 | if \ Y->data 90 | \ положить данные из пакета в буфер записи страницы 91 | begin 92 | ld r0,Y+ ld r1,Y+ 93 | if_b fMsk \ если пришли разностные данные 94 | lpm r,Z+ eor r0,r \ обратить их 95 | lpm r,Z eor r1,r 96 | sbiw Z,1 97 | then 98 | ldi r,{b SPMEN } rcall do_SPM \ записать во временный буфер 99 | dec ii 100 | while 101 | adiw Z,2 102 | repeat 103 | then 104 | skip_nb fWrt rcall do_WP \ стереть и записать атомарно 105 | sei 106 | rcall prgWad> 107 | then 108 | ldiW Y,inBoot goto RendBufP 109 | c; 110 | 111 | \ ============ инициализация! ============================ 112 | code iniBoot \ стартовая инициализация 113 | \ инициализация регистровых констант 114 | \ инициализировать систему связи 115 | rcall iniSysLink 116 | sei c; \ iniBoot val_ 117 | code BootLoader 118 | \ цикл ожидания команд 119 | begin 120 | rcall >BootPac \ проверить и принять пакет 121 | rcall BootPac> \ проверить и запустить передачу 122 | again 123 | c; \ val? 124 | 0 VECTOR> iniBoot 125 | finger CONSTANT EndBoot 126 | sizePrgWad take (prgWad) fingerAlign \ выровнять указатель на случай нечетного sizePrgWad 127 | (prgWad) TO adrPrgWad \ образ пыжа 128 | 129 | EndBoot StartBoot - sizePrgWad + CONSTANT SizeBoot 130 | 131 | 0 CONSTANT StartCRCboot \ начало контролируемой области загрузчика 132 | EndBoot StartCRCboot - CONSTANT SizeLoader \ размер загрузчика 133 | StartCRCboot SegA SizeLoader CRC16 CONSTANT SigLoader \ сигнатура полного загрузчика 134 | 135 | finger \ сигнатура и CRC теперь известны, 136 | ldZ org ldZPrgWad 137 | (prgWad) org \ помещаем реальные данные в код 138 | prgWad C>SEG 139 | SigLoader W>SEG 140 | (prgWad) SegA 3 crc8b C>SEG 141 | org 142 | \ prgWad> val? 143 | \ (prgWad) HEX[ val? ]HEX 144 | 145 | FUSE{ SELFPRGEN }=0 \ разрешить самопрограммирование 146 | PAGESIZE 2* CONSTANT PAGESIZEb \ размер страницы в байтах 147 | 148 | \ Запомнить вектора для загрузчика 149 | ROM_FREE DUP createSeg: BOOT-SEG 150 | 0 SegA \ откуда 151 | BOOT-SEG @ \ куда 152 | ROM_FREE \ скока 153 | CMOVE \ скопировать 154 | 155 | SigLoader .hex .( <--SigLoader) cr 156 | SizeBoot . .( <==== размер чисто загрузчика) cr 157 | SizeLoader sizePrgWad + . .( <==== полный размер загрузчика) cr 158 | -------------------------------------------------------------------------------- /libs/console_codes.f: -------------------------------------------------------------------------------- 1 | \ \ Атрибуты ============= 2 | \ 0 нормальный режим 3 | \ 1 жирный 4 | \ 4 подчеркнутый 5 | \ 5 мигающий 6 | \ 7 инвертированные цвета 7 | \ 8 невидимый 8 | \ \ цвет текста =================== 9 | \ 30 черный 10 | \ 31 красный 11 | \ 32 зеленый 12 | \ 33 желтый 13 | \ 34 синий 14 | \ 35 пурпурный 15 | \ 36 голубой 16 | \ 37 белый 17 | \ \ цвет фона ============= 18 | \ 40 черный 19 | \ 41 красный 20 | \ 42 зеленый 21 | \ 43 желтый 22 | \ 44 синий 23 | \ 45 пурпурный 24 | \ 46 голубой 25 | \ 47 белый 26 | 27 | 0x1B CONSTANT ESC 28 | : ESC> ( adr u --) \ отправить ESCAPE-последовательность 29 | ESC EMIT TYPE 30 | ; 31 | : defoltText \ вернуть обычные настройки 32 | S" [0m" ESC> 33 | ; 34 | 35 | \eof 36 | Примеры использования: 37 | S" [31;1;4m" ESC> \ красный, жирный, подчеркнутый 38 | 39 | 40 | -------------------------------------------------------------------------------- /libs/eeprom.f: -------------------------------------------------------------------------------- 1 | \ работа с EEPROM 2 | \ 3 | finger CONSTANT StartEeprom 4 | 5 | code e2RW ( c ADDR t -- c' ADDR+1 ) \ запись в EPROM 6 | \ r0 Z r0 Z 7 | \ t=0 запись 8 | \ t=1 чтение 9 | begin wait_nb eepe \ ждать готовности 10 | [FOUND?] eearH [IF] out eearH,Zh [THEN] \ установка адреса 11 | [FOUND?] eearL [IF] out eearL,zL [ELSE] out eear,zL [THEN] \ установка адреса 12 | adiW Z,1 13 | if_t \ чтение 14 | set_b eere 15 | in r0,eedr 16 | else \ запись 17 | out eedr,r0 \ установка байта 18 | mov r0, SREG cli \ запретить прерывания 19 | set_b eempe set_b eepe \ запись 20 | mov SREG,r0 \ вернуть как было 21 | then 22 | ret c; \ e2RW val? 23 | 24 | 25 | code RAM2EE ( X=AddrRam Z=AddrE2 r=n --) \ 26 | \ скопировать n байт из RAM в EEPROM 27 | \ портит r0 28 | clt 29 | for ld r0,x+ 30 | rcall e2RW 31 | next r 32 | ret c; 33 | 34 | code EE2RAM ( Z=AddrE2 X=AddrRam r=n --) 35 | \ скопировать n байт из EEPROM в RAM 36 | \ портит r0 37 | set 38 | for 39 | rcall e2RW st x+,r0 40 | next r 41 | ret c; 42 | 43 | finger StartEeprom - . .( <==== размер eeprom.f) CR 44 | 45 | -------------------------------------------------------------------------------- /libs/map.f: -------------------------------------------------------------------------------- 1 | \ ============================ создание файла карты памяти ==================== 2 | : FormatDef ( adr u x -- adr' u') \ сделать строку #define ... 3 | HEX[ 4 | -ROT S" #define " >S +>S S" 0x" +>S 5 | 4 ,0R +>S 0xD emit>S S@ S>DROP 6 | ]HEX 7 | ; 8 | 0 VALUE hfid 9 | : typeF ( adr u -- ) \ печатать в файл 10 | hfid WRITE-LINE THROW 11 | ; 12 | 13 | : RAM_map ( adr u --) \ создать заголовочный файл с адресами переменных 14 | \ adr u - строка с базовым именем 15 | >S [CHAR] _ EMIT>S 16 | SDUP S" RAM_map.h" +>S 17 | 0 emit>S S@ W/O CREATE-FILE THROW TO hfid S>DROP 18 | SDUP 19 | S" Ram" +>S 20 | S@ AddrRam FormatDef TypeF S>DROP 21 | \ относительный адреса переменных 22 | RAM[ 23 | labels 24 | BEGIN @ DUP WHILE 25 | DUP label-type @ DataType = 26 | IF SDUP 27 | DUP label-name COUNT +>S 28 | DUP label-value @ AddrRam - 29 | \ или Абсолютные 30 | DUP 0 < IF AddrRam + S" _A" +>S THEN 31 | S@ ROT FormatDef TypeF 32 | S>DROP 33 | THEN 34 | REPEAT DROP 35 | ]RAM 36 | S>DROP 37 | hfid CLOSE-FILE THROW 38 | 0 TO hfid 39 | ; 40 | 41 | 42 | -------------------------------------------------------------------------------- /libs/mtask-r.f: -------------------------------------------------------------------------------- 1 | \ мультизадачность, удобно использовать для ожидания события без подвисания программы 2 | \ iva 18.02.2013 3 | \ когда задача вызывает Ago! в списке задач сохраняется адрес возврата в эту задачу 4 | \ и управление передается в задачу вызвавшую текущую задачу 5 | \ когда вызывается Ago@, управление прередается в очередную задачу из списка задач 6 | \ индексы Rid и Wid играют в догонялки в кольцевом буфере, если Rid догнал Wid, значит все отложенные задачи выполнены, 7 | \ если Wid догнал Rid - значит буфер мал и отложенные задачи пропадают 8 | \ ==================== ресурсы ============================================== 9 | \ (...r15) register: (0) \ 0 в регистре 10 | \ (...r15) register: tRid \ индекс чтения списка задач 11 | \ (...r15) register: tWid \ индекс записи списка задач 12 | \ 8 constant taskSize \ размер списка задач, кольцевой буфер (кратен степени двойки) 13 | \ ============================================================================ 14 | 15 | RAM[ taskSize take Tasks \ список адресов отложенных задач, кольцевой буфер (кратен степени двойки) 16 | ]RAM 17 | 18 | code Ago! ( ) \ запомнить адрес возврата 19 | \ используются регистры: R, X, XH 20 | \ портится SREG 21 | \ 17 тактов + ret 22 | mov r,tWid \ получить индекс списка задач 23 | ldiW X,Tasks add xL,tWid adc xH,(0) \ получить адрес свободного места 24 | addi r,2 andi r,taskSize 1- mov tWid,r \ сдвинуть индекс записи 25 | pop r st x+,r pop r st x+,r \ сохранить адрес возврата в списке задач 26 | ret c; \ возврат в задачу вызвавшую отложенную 27 | \ ago! val? 28 | 29 | code Ago@ ( ) \ вызвать отложенную задачу 30 | \ используются регистры: R, RH, X, XH 31 | \ портится SREG 32 | \ 5 или 22 такта + ret 33 | \ получить индексы списка задач 34 | mov r,tRid cp tRid,tWid if= ret then \ нет отложенных задач 35 | ldiW X,Tasks add xL,r adc xH,(0) \ получить адрес места 36 | addi r,2 andi r,taskSize 1- mov tRid,r \ сохранит индекс 37 | ld rH,x+ ld rL,x+ pushW r \ подменить адрес возврата 38 | ret c; \ возврат в отложенную задачу 39 | \ Ago@ val? 40 | 41 | -------------------------------------------------------------------------------- /libs/mtask.f: -------------------------------------------------------------------------------- 1 | \ мультизадачность, удобно использовать для ожидания события без подвисания программы 2 | \ iva 18.02.2013 3 | \ когда задача вызывает Ago! в списке задач сохраняется адрес возврата в эту задачу 4 | \ и управление передается в задачу вызвавшую текущую задачу 5 | \ когда вызывается Ago@, управление прередается в очередную задачу из списка задач 6 | \ индексы mtRid и mtWid играют в догонялки в кольцевом буфере, если mtRid догнал mtWid, значит все отложенные задачи выполнены, 7 | \ если mtWid догнал mtRid - значит буфер мал и отложенные задачи пропадают 8 | \ если список задач пуст выставляется флаг Т, в противном случае сбрасывается. 9 | \ Это можно использовать для засыпания проца. 10 | \ ==================== ресурсы ============================================== 11 | \ (...r15) register: (0) \ 0 в регистре 12 | \ 8 constant taskSize \ размер списка задач, кольцевой буфер (кратен степени двойки) 13 | \ ============================================================================ 14 | 15 | RAM[ 1 take mtRid \ индекс чтения 16 | 1 take mtWid \ индекс записи 17 | taskSize take ListTasks \ список адресов отложенных задач, кольцевой буфер (кратен степени двойки) 18 | ]RAM 19 | 20 | code mtIni ( ) \ подготовка к работе 21 | mov mtRid,(0) mov mtWid,(0) \ обнулить индексы 22 | ret c; 23 | code Ago! ( ) \ запомнить адрес возврата 24 | \ используются регистры: R, X, XH 25 | \ портится SREG 26 | \ 17 тактов + ret 27 | mov r,mtWid \ получить индекс списка задач 28 | ldiW X,ListTasks add xL,r adc xH,(0) \ получить адрес свободного места 29 | addi r,2 andi r,taskSize 1- mov mtWid,r \ сдвинуть индекс записи 30 | pop r st x+,r pop r st x,r \ сохранить адрес возврата в списке задач 31 | ret c; \ возврат в задачу вызвавшую отложенную 32 | \ ago! val? 33 | 34 | code Ago@ ( -- T) \ вызвать отложенную задачу, T=1 если ничего не отложено 35 | \ используются регистры: R, RH, X, XH 36 | \ портится SREG 37 | \ 6 или 23 такта + ret 38 | \ получить индексы списка задач 39 | mov r,mtRid mov rH,mtWid cp r,rH if= set ret then \ нет отложенных задач 40 | clt \ список не пуст 41 | ldiW X,ListTasks add xL,r adc xH,(0) \ получить адрес места 42 | addi r,2 andi r,taskSize 1- mov mtRid,r \ сохранит индекс 43 | ld rH,x+ ld rL,x pushW r \ подменить адрес возврата 44 | ret c; \ возврат в отложенную задачу 45 | \ Ago@ val? 46 | 47 | -------------------------------------------------------------------------------- /libs/pFIFO.f: -------------------------------------------------------------------------------- 1 | \ пакетные кольцевые буферы FIFO с хвостиком 2 | \ ревизия 11 окт 2016 3 | \ хвостик нужен, чтобы избежать фрагментации пакетов 4 | \ структура буферов (определяется писателем): 5 | \ имя---v 6 | \ чистый размер кольцевого буфера, под данные 7 | \ индексЧтения=смещение от начала буфера до размера непрочитаного пакета 8 | \ индексЗаписи=смещение от начала свободной области буфера 9 | \ размерПакета1, байт1пакета1, .., байтN1пакета1, 10 | \ размерПакета2, байт1пакета2, ..........., байтN2пакета2, 11 | \ ... 12 | \ размерПакетаX, байт1пакетаX, ........, байтNXпакетаX, 13 | \ ..........последний_байт кольца буфера 14 | \ хвостик, куда пишутся байты последнего пакета, вылезающего за пределы кольца 15 | \ размер хвостика должен быть больше или равен максимальному размеру пакета 16 | 17 | \ полный размер буфера в памяти = размер_кольца+размер_хвоста+3 байта 18 | \ имя---v имя+3---v 19 | \ Size,Rid,Wid:Body... 20 | \ имя буфера указывает на байт размера буфера 21 | \ 22 | \ ==== сервисные утилиты ===================== 23 | \ BufP: ( size "name" --) \ выделить память под пакетный буфер 24 | \ ==== рабочие утилиты ===================== 25 | \ IniBufP ( Y=addrBuf r=Size -- Y=addrBuf r=Size ) \ инициация буфера 26 | \ RsizeBufP ( Y=addrBuf -- Y=addrBuf r=u Z) \ сколько места есть для чтения 27 | \ WsizeBufP ( Y=addrBuf -- Y=addrBuf r=u Z) \ сколько места есть для записи 28 | \ WaddrBufP ( Y=addrBuf -- Y=addrPac ) \ выдать адрес W пакета 29 | \ RaddrBufP ( Y=addrBuf -- Y=addrPac ) \ выдать адрес R пакета 30 | \ WriteBufP ( Y=addrBuf r=b rH=n -- Y=addrBuf r=b rH=n t) \ записать байт в позицию n(>0) последнего пакет буфера 31 | \ ReadBufP ( Y=addrBuf rH=n -- Y=addrBuf rH=n r=byte t c) \ выдать n-ый[1..N] байт из текущего пакета 32 | \ WendBufP ( Y=addrBuf -- Y=addrBuf) \ переместить индекс W за пакет 33 | \ RendBufP ( Y=addrBuf -- Y=addrBuf) \ переместить индекс R за пакет 34 | \ WtakeBuf ( Y=addrBuf r=u -- Y=addrPack|Buf r=u t ) \ зарезервировать для прямой записи u байт в буфере addrBuf 35 | 36 | #def BufP \ либа загружена 37 | Finger VALUE StartLibBufP \ учет размера кода 38 | \ ==== макросы ============================= 39 | #def add_Yr add yL r adc yH (0) \ сложить регистровую пару с регистром 40 | #def sub_Yr sub yL r sbc yH (0) \ вычесть регистровую пару с регистром 41 | #def add_YrH add yL rH adc yH (0) \ сложить регистровую пару с регистром 42 | #def sub_YrH sub yL rH sbc yH (0) \ вычесть регистровую пару с регистром 43 | 44 | #def (S) 0 45 | #def (R) 1 46 | #def (W) 2 47 | #def (B) 3 48 | 49 | 50 | : BufP: ( size "name" --) \ выделить память под пакетный буфер 51 | MaxSizePack + 3 + take \ +хвост +3 байта под индексы S, R, W 52 | ; 53 | 54 | code IniBufP ( Y=addrBuf r=Size -- Y=addrBuf r=Size ) \ инициация буфера 55 | st Y,r std Y+(R),(0) std Y+(W),(0) \ очистить и образмерить 56 | ret c; 57 | 58 | 59 | 60 | code RsizeBufP ( Y=addrBuf -- Y=addrBuf r=u sreg.Z) \ сколько места есть для чтения 61 | push rH 62 | ldd r,Y+(W) ldd rH,Y+(R) 63 | sub r,rH if_c ldd rH,Y+(S) add r,rH then 64 | pop rH 65 | ret c; 66 | 67 | code WsizeBufP ( Y=addrBuf -- Y=addrBuf r=u sreg.Z) \ сколько места есть для записи 68 | rcall RsizeBufP 69 | push rH 70 | ldd rH,Y+(S) dec rH sub rH,r mov r,rH 71 | pop rH 72 | \ показывает на 1 меньше, чтобы было куда перенести W 73 | \ W не должно сесть на R 74 | ret c; 75 | 76 | 77 | code WaddrBufP ( Y=addrBuf -- Y=addrPac ) \ выдать адрес W пакета 78 | push r 79 | ldd r,Y+(W) c; \ ----v 80 | code _addrBufP 81 | add_Yr adiw Y,(B) 82 | pop r 83 | ret c; 84 | code RaddrBufP ( Y=addrBuf -- Y=addrPac ) \ выдать адрес R пакета 85 | push r 86 | ldd r,Y+(R) rjmp _addrBufP c; \ ---^ 87 | 88 | code WtakeBuf ( Y=addrBuf r=u -- Y=addrPack|Buf r=n t ) 89 | \ зарезервировать для прямой записи u байт в буфере addrBuf 90 | \ t=0 Y=addrPack 91 | \ t=1 Y=addrBuf - отказ 92 | set \ пессимистический прогноз 93 | cpi r,MaxSizePack 1+ \ контроль размера пакета 94 | if< \ контроль размера пакета 95 | push rH 96 | mov rH,r \ rH=r=u 97 | rcall WsizeBufP cp rH,r \ u-size 98 | mov r,rH \ r=rH=u 99 | pop rH 100 | if< ( u0) последнего пакет буфера 105 | \ последний записанный байт определяет размер всего пакета 106 | \ т.е. размер пакета равен последнему n 107 | \ t=1 - нет места для записи 108 | pushW Y 109 | push r 110 | mov r,rH rcall WtakeBuf \ проверка возможности записи 111 | pop r 112 | if_nT \ можно 113 | st Y,rH \ записать n в голову пакета 114 | add_YrH st Y,r \ записать байт 115 | then 116 | popW Y 117 | ret c; 118 | 119 | code ReadBufP ( Y=addrBuf rH=n -- Y=addrBuf rH=n r=byte t c ) \ выдать n-ый[1..N] байт из текущего пакета 120 | \ t=1 это последний байт пакета 121 | \ c=1 перелет за пределы пакета 122 | clt \ оптимистический прогноз 123 | pushW Y 124 | ldd r,Y+(R) add_Yr ldd r,Y+(B) \ r=N 125 | add_YrH 126 | cp r,rH if= set then \ n=N=>T=1 127 | ldd r,Y+(B) \ r=byte(n) 128 | popW Y 129 | ret c; 130 | 131 | 132 | code _endBufP ( r=Idx -- r=Idx') 133 | push rH 134 | add_Yr ldd rH,Y+(B) sub_Yr \ rH=n r=Idx Y=addrBuf 135 | add r,rH \ Idx+N=x 136 | ldd rH,Y+(S) cp rH,r if_c sub r,rH then 137 | inc r 138 | pop rH 139 | ret c; 140 | 141 | code WendBufP ( Y=addrBuf -- Y=addrBuf ) \ переместить индекс W за пакет 142 | push r 143 | ldd r,Y+(W) rcall _endBufP 144 | std Y+(W),r \ r=W' 145 | pop r 146 | ret c; \ WendBufP val? 147 | 148 | code RendBufP ( Y=addrBuf -- Y=addrBuf ) \ переместить индекс R за пакет 149 | push r 150 | ldd r,Y+(R) rcall _endBufP 151 | std Y+(R),r \ r=R' 152 | pop r 153 | ret c; 154 | 155 | 156 | \ eof 157 | finger StartLibBufP - . .( <==== размер либы pFIFO[кольцевого+]) cr 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /libs/spf.log: -------------------------------------------------------------------------------- 1 | .e isn't unique (/home/ivanov/spf-4.20/lib/include/float2.f) 2 | Exception #-2003 at: /home/ivanov/IvaMobi2/Person/Job/Projects/RF-16/DRF7020/prog/AVR/libs/tables.f:21:9: 3 | NEW>S 4 | ^ -2003 слово или файл не найден 5 | -------------------------------------------------------------------------------- /libs/tables.f: -------------------------------------------------------------------------------- 1 | S" lib/include/float.f" INCLUDED 2 | \ вычисление таблиц 3 | S" 3.141592653E0" >FLOAT 0= THROW FCONSTANT PI 4 | PI FDUP F+ FCONSTANT 2PI 5 | 6 | : S>F ( n --) ( F: -- r) 7 | S>D D>F ; 8 | : F>S ( -- n) ( F: r -- ) 9 | F>D D>S ; 10 | : Sin ( n m --) ( F: -- r) \ энный отсчёт из m отсчётов по кругу 360град. 11 | 2PI S>F F/ 12 | S>F F* FSIN 13 | ; 14 | : SinPi ( n m --) ( F: -- r) \ энный отсчёт из m отсчётов за полпериода. 15 | PI S>F F/ 16 | S>F F* FSIN 17 | ; 18 | : [Sin] ( min max -- ) ( F: r1-- r2) \ min<=r2<=max 19 | OVER - 2/ DUP S>F F* + S>F F+ ; 20 | : TabSin ( min max # -- adr u ) \ выдать # значений [синуса] 21 | NEW>S 22 | DUP 0 23 | DO I OVER Sin >R 2DUP [Sin] R> FROUND F>S 24 | PAD C! PAD 1 +>S 25 | LOOP DROP 2DROP S@ S>DROP ; 26 | 27 | : TabSinPi ( Max # -- adr u ) \ выдать # значений полупериода [синуса] 28 | NEW>S 29 | DUP 0 30 | DO I 1+ OVER SinPi OVER s>f F* FROUND F>S 31 | PAD C! PAD 1 +>S 32 | LOOP 2DROP S@ S>DROP 33 | ; 34 | 35 | : TabMeandr ( min max # -- adr u ) \ выдать # значений [меандра] 36 | NEW>S 37 | DUP 0 38 | DO ( min max #) i over 2/ > if over else rot dup >r -rot r> then 39 | PAD C! PAD 1 +>S 40 | LOOP DROP 2DROP S@ S>DROP ; 41 | 42 | : [Tre] ( min max -- ) ( F: r1-- r2) \ min<=r2<=max 43 | over - s>f f* s>f f+ ; 44 | 45 | : Tre ( n m --) ( F: -- r) \ энный отсчёт из m отсчётов [0/n\m] 46 | over 4 * s>f dup s>f f/ ( F: 4n/m) 47 | 2DUP 4 / > 48 | if 3 * 4 / > 49 | IF 4 S>F F- 50 | ELSE 2 s>f fswap f- 51 | THEN 52 | ELSE 2DROP 53 | then \ fdup f. 54 | ; 55 | : TabTre ( min max # -- adr u ) \ выдать # значений [треугольник] 56 | NEW>S 57 | DUP 0 58 | DO i over tre >R 2DUP [Sin] R> FLOOR F>S 59 | PAD C! PAD 1 +>S 60 | LOOP DROP 2DROP S@ S>DROP ; 61 | : Pil ( n m --) ( F: -- r) \ энный отсчёт из m отсчётов [0/n|m] 62 | swap s>f s>f f/ 63 | \ fdup f. 64 | ; 65 | : TabPil ( min max # -- adr u ) \ выдать # значений [пила] 66 | NEW>S 67 | DUP 0 68 | DO i over Pil >R 2DUP [tre] R> FROUND F>S 69 | PAD C! PAD 1 +>S 70 | LOOP DROP 2DROP S@ S>DROP ; 71 | 72 | : F^ ( r1 r2 -- r1^r2 ) \ возведение в степень 73 | FSWAP FLN F* Fexp 74 | ; 75 | : _TabExp_ ( a b n -- ) ( Str: table) \ выдать экспоненту как таблицу из n точек от а<>0 до b 76 | \ если ab - спадающая экспонента 78 | \ если a=b - горизонтальная прямая 79 | \ y(i)=a*(b/a)^(i/n), где i=[0..n] 80 | -ROT 2DUP 2>R OVER s>f s>f s>f F/ ( D: n) ( F: a b/a) 81 | DUP 1 s>f s>f F/ F^ \ ( D: n) ( F: a (b/a)^1/n ) 82 | FSWAP 83 | 2R> 84 | > IF FDUP FROUND f>s PAD C! PAD 1 +>S 85 | 1 86 | ELSE 0 THEN 87 | DO FOVER F* FDUP FROUND f>s PAD C! PAD 1 +>S 88 | LOOP FDROP FDROP 89 | ; 90 | : TabExp ( a b n -- adr u ) \ выдать экспоненту как таблицу из n точек от а<>0 до b 91 | NEW>S _TabExp_ S@ S>DROP ; 92 | 93 | : _TabLog_ ( a b n -- ) ( Str: table) \ выдать логарифмичеускую кривую как таблицу из n точек от а<>0 до b 94 | \ 0R OVER - s>f R> \ (D: a n ) ( F: b-a) 101 | DUP s>f FLN F/ \ ( F: (b-a)/ln(n)) 102 | 0 DO \ (D: a n ) ( F: (b-a)/ln(n)) 103 | I 1+ s>f FLN FOVER F* FROUND f>s 104 | OVER + 105 | PAD C! PAD 1 +>S 106 | LOOP FDROP DROP 107 | ; 108 | : TabLog ( a b n -- adr u ) \ выдать логарифмичеускую кривую как таблицу из n точек от а<>0 до b 109 | NEW>S _TabLog_ S@ S>DROP ; 110 | : TabLog\ ( a b n -- adr u ) \ выдать логарифмичеускую кривую как таблицу из n точек от а>b до b 111 | NEW>S 112 | -ROT SWAP ROT 113 | _TabLog_ 114 | S@ NEW>S ( adr n ) 115 | 0 SWAP 1- DO ( adr ) 116 | DUP I + C@ PAD C! PAD 1 +>S 117 | -1 +LOOP DROP 118 | S@ 119 | S>DROP 120 | S>DROP ; 121 | 122 | : TabPiano ( min max # -- adr u) \ выдать огибающую звука фортепиано (типа) 123 | 3DUP 124 | NEW>S _TabExp_ S@ DROP >R 125 | NEW>S _TabLog_ R> S@ \ adr1 adr2 n 126 | NEW>S 127 | 0 SWAP 1- DO ( adr1 adr2 ) 128 | 2DUP I + C@ SWAP I + C@ + 2/ PAD C! PAD 1 +>S 129 | -1 +LOOP 2DROP 130 | S@ S>DROP S>DROP S>DROP 131 | ; 132 | 133 | : TabLin ( a b n -- adr u ) \ выдать линию как таблицу из n точек от а<>0 до b 134 | \ если ab - спадающая линия 136 | \ если a=b - горизонтальная линия 137 | \ y(i)=a+i*(b-a)/(n-1), где i=[0..n-1] 138 | NEW>S 139 | DUP >R 1- s>f 140 | OVER - s>f FSWAP F/ 141 | s>f FSWAP \ (F: a (b-a)/(n-1) 142 | R> 0 DO 143 | FOVER FOVER 144 | I s>f F* F+ FROUND 145 | FROUND f>s PAD C! PAD 1 +>S 146 | LOOP FDROP FDROP S@ S>DROP 147 | ; 148 | : see-tab ( adr u --) 149 | 0 -ROT 150 | OVER + SWAP 151 | DO I C@ 4 .R 1+ DUP 16 = IF CR DROP 0 THEN LOOP DROP CR ; 152 | 153 | \ ========= формирование кода для семисегментрного индикатора ================== 154 | HERE 9 ALLOT constant str7seg \ резервирование места для строки расположения сегментов 155 | 156 | : map7Seg ( --) \ запомнить расположение сегментов в байте 157 | BL WORD COUNT str7seg ! str7seg 1+ 8 CMOVE 158 | ; 159 | map7Seg ABCDEFGH \ нормальное расположение сегментов в байте, нулевой бит СЛЕВА 160 | 161 | : symFind ( sym adr u -- n) \ n позиция символа sym в строке adr u 162 | 0 -rot 163 | over + swap 164 | do \ sym j 165 | over i c@ = if leave else 1+ then 166 | loop 167 | nip ; 168 | 169 | : cod7s ( addr u -- byte) \ преобразовать строку в код семисегментного индикатора 170 | 0 -rot 171 | over + swap 172 | do 173 | i c@ str7Seg count symfind dup 7 > abort" сегмент не найден" 174 | 1 swap lshift + 175 | loop ; 176 | : (0) S" ABCDEF" cod7s ; \ 0 177 | : (1) S" BC" cod7s ; \ 1 178 | : (2) S" ABGED" cod7s ; \ 2 179 | : (3) S" ABGCD" cod7s ; \ 3 180 | : (4) S" FGBC" cod7s ; \ 4 181 | : (5) S" AFGCD" cod7s ; \ 5 182 | : (6) S" AFGCDE" cod7s ; \ 6 183 | : (7) S" ABC" cod7s ; \ 7 184 | : (8) S" ABCDEFG" cod7s ; \ 8 185 | : (9) S" ABCDFG" cod7s ; \ 9 186 | 187 | : (A) S" ABCEFG" cod7s ; \ A 188 | : (B) S" CDEFG" cod7s ; \ B 189 | : (C) S" ADEF" cod7s ; \ C 190 | : (D) S" BCDEG" cod7s ; \ D 191 | : (E) S" ADEFG" cod7s ; \ E 192 | : (F) S" AEFG" cod7s ; \ F 193 | 194 | : (t) S" FGED" cod7s ; \ t 195 | : (r) S" EG" cod7s ; \ r 196 | : (n) S" CGE" cod7s ; \ n 197 | : (.) S" H" cod7s ; \ . 198 | : () 0 ; \ пусто 199 | 200 | : (cod7s) ( -- byte) \ взять строку из входного потока, преобразовать 201 | BL WORD COUNT cod7s ; 202 | \ (cod7s) FGED ( t) \ пример использования 203 | : (0-9) ( -- коды от 0 до 9 ) 204 | (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) ; 205 | : (0-F) ( -- коды от 0 до F ) 206 | (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (A) (B) (C) (D) (E) (F) ; 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /libs/time.f: -------------------------------------------------------------------------------- 1 | \ про время 2 | 3 | CREATE TimeVal 2 cells allot 4 | CREATE TimeZone 2 cells allot 5 | 0 6 | CELL -- _sec \ секунды 0 до 59 7 | CELL -- _min \ минуты 0 до 59 8 | CELL -- _hour \ часы от 0 до 23 9 | CELL -- _mday \ день месяца от 1 до 31 10 | CELL -- _mon \ месяц от 0 до 11 11 | CELL -- _year \ число лет, прошедших с 1900 12 | CELL -- _wday \ Число дней, прошедших с воскресенья, от 0 до 6 13 | CELL -- _yday \ Количество дней, прошедших с 1 января, от 0 до 365 14 | CELL -- _isdst \ Значение флага положительно, если "летнее" время учитывается, 0, если нет, и отрицательно, если информация недоступна. 15 | CELL -- _gmtoff \ Seconds east of UTC 16 | CELL -- _zone \ Timezone abbreviation 17 | CONSTANT size_tm 18 | 19 | size_tm ALLOCATE THROW VALUE tm 20 | 21 | : getTime ( -- usec sec ) \ получить системное время 22 | (( TimeVal TimeZone )) gettimeofday THROW 23 | TimeVal 2@ 24 | ; 25 | : getMs ( -- ms ) \ выдать текущие милисекунды 26 | getTime 3600 24 * mod 1000 * swap 1000 / + 27 | ; 28 | 29 | : ctime ( UTC -- adr u) \ преобразовать число секунд в строку даты-времени 30 | 0 SWAP TimeVal 2! 31 | (( TimeVal )) ctime ASCIIZ> 32 | 1- ; 33 | : localtime ( UTC -- adr ) \ разместить дату-время в календарной структуре 34 | 0 SWAP TimeVal 2! 35 | (( timeval tm )) localtime_r 36 | ; 37 | : time.ms ( ) \ показать текущее время с десятками милисекунд 38 | gettime localtime DROP 39 | tm _hour @ 2 .0R ." :" 40 | tm _min @ 2 .0R ." :" 41 | tm _sec @ 2 .0R ." ." 42 | 1000 / 3 .0R 43 | ; 44 | \ getTime NIP gmtime @ . 45 | 46 | \ date -d @1399364718 47 | \ Вт. мая 6 12:25:18 MSK 2014 48 | 49 | \ (( S" date -d @1399364718" )) system 50 | \ Вт. мая 6 12:25:18 MSK 2014 51 | \ (( timeval )) ctime ASCIIZ> TYPE 52 | \ (( timeval )) gmtime возвращает структуру 53 | -------------------------------------------------------------------------------- /libs/timers.f: -------------------------------------------------------------------------------- 1 | \ подсистема таймеров 2 | \ iva 26.04.2017 3 | \ после объявление константы #timers 4 | \ 4 CONSTANT #timers \ количество слотов для таймеров 5 | \ в системе будет доступно указанное количество таймеров 6 | \ сработавший таймер деактивируется и освобождается, 7 | \ если требуется периодичность программа в точке перехода 8 | \ должна заново активировать свободный таймер 9 | \ (см. примеры в конце файла) 10 | \ если запрошено тамеров больше, чем есть, запрос отклоняется 11 | \ без уведомления 12 | \ для проверки наличия свободных таймеров можно вызвать FreeSlot 13 | \ iva 9.12.2017 14 | \ если есть таймер с такой-же точкой возврата, то Delay: переустанавит 15 | \ его время 16 | \ можно освободить таймер, отменить действие (0 Delay:) 17 | 18 | \ установки секунд и минут зависят от тактирования таймера 19 | \ поэтому задаются в основной программе 20 | \ #def sek 16 * chskTime \ перевод секунд в тики таймера 21 | \ #def mnt 60 * sek \ перевод минут в тики таймера 22 | 23 | 24 | finger CONSTANT startTimres 25 | 0 26 | 2 -- timeOn \ декрементный счетчик тиков 27 | 2 -- point \ точка перехода после срабатывания таймера 28 | CONSTANT sizeTimers 29 | RAM[ 1 take NextTimer \ следующий таймер для проверки 30 | sizeTimers #timers * take Timers \ таймеры 31 | ]RAM 32 | 33 | 34 | BitsIn r ( aka TIFR0) 35 | #BitIs rOCF0A 36 | 37 | : chskTime ( u -- u) \ проверка возможности установки тайма 38 | DUP 0xFFFF > ABORT" Слишком большой период." 39 | ; 40 | 41 | code Time \ вызывать переодически в главном цикле 42 | mov r,TIFR0 skip_b rOCF0A ret 43 | \ сработал флаг основного периода таймера 44 | mov r,NextTimer inc r mov rH,r 45 | cpi r,#timers 46 | if= clr rH then mov NextTimer,rH \ счетчик таймеров 47 | if= ldi rH,{b OCF0A } mov TIFR0,rH then \ сбросить флаг после проверки всех таймеров 48 | \ проверить таймеры, по одному за вызов 49 | ldiW Y,Timers \ Y->0-timer 50 | begin dec r while adiW Y,sizeTimers repeat \ переход к нужному таймеру 51 | ldd rL,Y+0 timeOn ldd rH,Y+1 timeOn 52 | sbiw R,1 \ декремент текущего счетчика 53 | if_nC std Y+0 timeOn,rL std Y+1 timeOn,rH \ сохранить его 54 | if0 ldd zL,Y+0 point ldd zH,Y+1 point ijmp \ перейти на точку 55 | then 56 | then 57 | ret c; 58 | 59 | code FreeSlot ( --Y=addr t) \ получить адрес свободного таймера 60 | \ t=0 Y=addrSlot 61 | \ t=1 Y=addrOver 62 | clt 63 | ldiW Y,Timers 64 | begin ldd rL,Y+0 timeOn ldd rH,Y+1 timeOn or rL,rH while \ пропускаем активные 65 | adiW Y,sizeTimers \ берем следующий 66 | ldiW R,Timers sizeTimers #timers * + 67 | cpW Y,R while_b C \ пока не кончатся слоты 68 | repeat set then \ выход если все слоты заняты 69 | ret c; 70 | 71 | code FindSlot ( Z=Point -- Y=addr t ) \ найти слот с такой-же точкой возврата 72 | \ или свободный 73 | \ t=0 Y=addrSlot 74 | \ t=1 Y=addrOver 75 | clt 76 | ldiW Y,Timers 77 | begin ldd rL,Y+0 point ldd rH,Y+1 point cpW Z,R while \ пропускаем иные 78 | adiW Y,sizeTimers \ берем следующий 79 | ldiW R,Timers sizeTimers #timers * + 80 | cpW Y,R while_b C \ пока не кончатся слоты 81 | repeat goto FreeSlot then \ поискать свободный слот 82 | ret c; 83 | 84 | code Delay: ( X=delay R:adr -- ) \ запомнить задержку и адрес возврата 85 | popW Z \ Z=adr, невозврат в случае неудачи 86 | rcall FindSlot \ найти такой-же слот или свободный слот 87 | if_nT \ и заполнить его 88 | std Y+0 point,zL std Y+1 point,zH 89 | std Y+0 timeOn,xL std Y+1 timeOn,xH 90 | then 91 | ret c; 92 | 93 | finger startTimres - . 94 | .( <==== размер timres.f ) cr 95 | 96 | 97 | \eof \ примеры использования 98 | code WaitGoodMorning \ пример однократного срабатывания 99 | ldiW X,4 sek rcall Delay: \ объявление времени таймера 100 | \ сюда будет переход по срабатыванию таймера 101 | if_nb fOn 102 | ldiW Z,GoodBye rcall goPack 103 | then 104 | ret c; 105 | 106 | code Migni \ пример переодичной работы 107 | begin 108 | ldiW X,1 sek rcall Delay: 109 | if_b heat \_ heat else _/ heat then 110 | again 111 | c; 112 | -------------------------------------------------------------------------------- /opcodes.f: -------------------------------------------------------------------------------- 1 | \ структура opcodes 2 | \ автор: ~iva дата: 2010 ревизия: 1 3 | \ ======== ИНФО ================================================================ 4 | \ структура opcodes 5 | \ ============================================================================== 6 | \ cmd: ADC Rd, Rr ; ---v Opcode: 000111rdddddrrrr 7 | \ ============================================================== слова доступа== 8 | \ adr поле связи (link) CELL обязательно @ 9 | \ 000111000000000 клише CELL обязательно clishe 10 | \ 111111000000000 маска CELL обязательно mask 11 | \ u"ADC" шаблон C-STRING обязательно mnemo 12 | \ u"Rd" id1 C-STRING обязательно 1 op.id 13 | \ 000000111110000 маска 1 оператора CELL обязательно 1 op.mask 14 | \ xt0 слово-обработчик CELL обязательно 1 op.exec 15 | \ u"Rr" id1 C-STRING обязательно 2 op.id 16 | \ 000001000001111 маска 2 оператора CELL обязательно 2 op.mask 17 | \ xt1 слово-обработчик CELL обязательно 2 op.exec 18 | \ ======== ЗАДАЧИ ============================================================== 19 | \ ======== ПОДКЛЮЧАЕМЫЕ ФАЙЛЫ и слова нужные не только здесь =================== 20 | S" ~iva/AVR/toolbox.f" INCLUDED \ инструментальные слова 21 | 22 | 23 | \ ======== КОНСТАНТЫ И ПЕРЕМЕННЫЕ ============================================== 24 | VOCABULARY DASSM \ словарь для команд ассемблера 25 | VARIABLE opcodes \ начало цепного списка opcodes 26 | \ ======== СЛУЖЕБНЫЕ СЛОВА ДЛЯ ОПРЕДЕЛЕНИЯ ГЛАВНЫХ СЛОВ ======================== 27 | : RESTORE-VOCS ; 29 | \ ============ слова навигации в структуре opcodes ============================= 30 | : clishe ( adr-link -- adr-clishe) \ дать адрес клише команды 31 | CELL+ ; 32 | : mask ( adr-link -- adr-mask) \ дать адрес маски команды 33 | clishe CELL+ ; 34 | : mnemo ( adr-link -- adr-str) \ дать адрес строки со счетчиком = мнемоника 35 | mask CELL+ ; 36 | \ ------------------------------------------------------------------------------ 37 | : op.id ( adr-link № -- adr-id) \ дать адрес идентификатора №-ого операнда 38 | SWAP mnemo COUNT + 39 | BEGIN ( # adr-op.id) 40 | SWAP 1- ?DUP 41 | WHILE 42 | SWAP COUNT + 2 CELLS + 43 | REPEAT ; 44 | : op.mask ( adr-link № -- adr-mask) \ дать адрес маски №-ого операнда 45 | op.id COUNT + ; 46 | : op.exec ( adr-link № -- adr-exec) \ дать адрес xt обработчика №-ого операнда 47 | op.mask CELL+ ; 48 | \ ============ слова для создания структуры opcodes ============================ 49 | : <<- ( adr --) DUP @ 1 LSHIFT SWAP ! \ сдвинуть на 1 разряд переменную 50 | ; 51 | [WITHOUT?] 1+! \ если в системе не определено, то определим 52 | : 1+! ( adr --) DUP @ 1+ SWAP ! ; \ увеличить переменную на 1 53 | [THEN] 54 | : op.mask<<- ( adr-link --) \ сдвинуть на 1 разряд маски операндов opcode-s 55 | \ взвести цикл по операндам 56 | 3 1 DO \ adr-link 57 | DUP I op.mask <<- 58 | LOOP 59 | DROP ; 60 | : <<< ( adr-link --) \ сдвинуть на 1 разряд все маски структуры opcode-s 61 | >R 62 | R@ clishe <<- 63 | R@ mask <<- 64 | R> op.mask<<- 65 | ; 66 | : искать-id ( char adr-opcode -- № TRUE | CHAR FALSE) 67 | \ искать в текущем opcode операнд с id=char 68 | SWAP >R \ запомнить char 69 | 3 BEGIN 1- DUP 70 | WHILE ( adr-op #) 71 | 2DUP op.id R@ SWAP COUNT OVER + SWAP 72 | DO ( adr-op # char) 73 | I C@ OVER = IF DROP 0 LEAVE THEN 74 | LOOP 0= IF NIP TRUE R> DROP EXIT THEN 75 | REPEAT R> FALSE 76 | ; 77 | : operands ( char --) \ обработать операнд с id=char 78 | \ если есть => отметить текущую позицию единичкой 79 | \ если такого нет => ругаться 80 | opcodes @ искать-id 81 | IF opcodes @ SWAP op.mask 1+! \ отметить 82 | ELSE ABORT" символ не найден." 83 | THEN 84 | ; 85 | 86 | : -comma ( u-adr -- u'-adr) \ убрать замыкающую запятую 87 | DUP >R 88 | COUNT + 1- C@ [CHAR] , = IF R@ C@ 1- R@ C! THEN 89 | R> ; 90 | : пусто ; \ пустое слово для отсутствующих операндов 91 | : -op ( --) S" нет" str! 0 , ['] пусто , ; \ нет операнда 92 | : next-op ( -- c-adr f) 93 | BL WORD -comma DUP 94 | COUNT S" ;" COMPARE 95 | ; 96 | : save-op ( c-adr --) \ создать запись операнда 97 | DUP COUNT str! \ id операнда 98 | 0 , \ маска операнда 99 | FIND 0= -321 AND THROW \ вылет, если не найдено слово-обработчик 100 | , ; \ обработчик операнда 101 | 102 | \ =========== сервисные слова для просмотра структуры ========================== 103 | : CMD> ( adr-link --) \ показать структуру 104 | ." ================================" CR 105 | BIN[ DUP clishe @ 32 .0R ." <-клише" CR 106 | DUP mask @ 32 .0R ." <-маска" CR 107 | DUP mnemo COUNT TYPE CR 108 | 3 1 DO 109 | DUP I op.id COUNT TYPE CR \ id оператора 110 | DUP I op.mask @ 32 .0R CR \ его маска 111 | DUP I op.exec @ HEX[ 8 .0R ]HEX CR \ его обработчик 112 | LOOP DROP 113 | ]BIN 114 | ." ================================" CR ; 115 | \ пример использования 116 | \ c[ ' sbrc >body cmd> ]c 117 | 118 | : #CMD> ( n --) \ показать n-ую структуру, считая от последнего введенного 119 | opcodes SWAP 120 | 0 DO @ LOOP 121 | CMD> ; 122 | : listCMD ( -- ) \ показать список введённых команд 123 | opcodes 124 | BEGIN 125 | @ >R 126 | R@ mnemo COUNT TYPE SPACE 127 | R@ 1 op.id COUNT 2DUP S" нет" COMPARE 128 | IF TYPE 129 | R@ 2 op.id COUNT 2DUP S" нет" COMPARE 130 | IF ." , " TYPE ELSE 2DROP THEN 131 | ELSE 2DROP THEN CR 132 | R@ clishe @ R@ mask @ OR 133 | R> SWAP 134 | WHILE REPEAT 135 | DROP 136 | ; 137 | 138 | \ ======== ГЛАВНЫЕ СЛОВА ======================================================= 139 | DEFER coder 140 | 141 | : cmd: ( <"name" text;> --) 142 | >IN @ 143 | \ команды создаются в словаре DASSM 144 | opcodes @ HERE opcodes ! , \ ввести в цепь 145 | \ opcodes теперь указывает на текущее определение \ link 146 | 65536 , 65536 , \ клише, маска 147 | ( по умолчанию 0x10000, т.е. на 1 больше 0xFFFF, 148 | это позволит описывать псевдокоманды, не имеющих opcode) 149 | >IN ! BL WORD COUNT str! \ мнемоника 150 | 0 BEGIN next-op WHILE save-op 1+ REPEAT DROP \ запись операндов 151 | 2 SWAP - \ скольких нет? 152 | BEGIN DUP 0 > WHILE -op 1- REPEAT DROP \ запись отсутствующих 153 | DOES> coder 154 | ; 155 | : Opcode: ( "bits-symbols" -- ) \ разобрать код операции на составляющие 156 | BL WORD COUNT \ adr u 157 | OVER + SWAP \ подготовка цикла 158 | DO \ цикл по символам строки (I указатель на символ) 159 | opcodes @ <<< 160 | I C@ 161 | DUP [CHAR] 0 = 162 | IF opcodes @ mask 1+! DROP 163 | ELSE 164 | DUP [CHAR] 1 = 165 | IF opcodes @ mask 1+! opcodes @ clishe 1+! DROP 166 | ELSE operands 167 | THEN 168 | THEN 169 | LOOP 170 | ; 171 | : ext: ( "bits-symbols" -- ) \ расширить код операции с учетом новой информации 172 | \ расширяются только маски операндов, так как "опознание" происходит 173 | \ в любом случае по маш.слову (16 бит), а выделение операндов из кода 174 | \ операции - по полному коду (16 или 32 бита (если есть расширение)) 175 | BL WORD COUNT \ adr u 176 | OVER + SWAP \ подготовка цикла 177 | DO \ цикл по символам строки (I указатель на символ) 178 | opcodes @ op.mask<<- \ сдвинуть маски операндов 179 | I C@ operands 180 | LOOP 181 | ; 182 | \ ======== ТЕСТЫ И ПРИМЕРЫ ===================================================== 183 | 184 | -------------------------------------------------------------------------------- /prog.f: -------------------------------------------------------------------------------- 1 | [FOUND?] TheProg [IF] \eof [THEN] 2 | 3 | DECIMAL 4 | 5 | \ 64 CONSTANT size-rbuf \ размер буфера 6 | \ CREATE rbuf size-rbuf ALLOT \ буфер чтения 7 | 8 | 0 VALUE size-rbuf \ размер буфера 9 | 0 VALUE rBuf \ адрес буфера чтения 10 | 11 | 0 VALUE EndMemory \ последний адрес памяти 12 | 0 VALUE SizePage \ размер страницы в байтах 13 | 10 VALUE TwP \ таймаут для записи страницы 14 | 0 VALUE AsWord? \ индикатор доступа по словам(по парам байт) 15 | 16 | 17 | DEFER powerup ( ) \ занять чип 18 | DEFER powerdown ( ) \ освободить 19 | DEFER ProgEn ( -- ) \ включить режим программирования 20 | 21 | DEFER FLASH_WRITE \ IS M_WRITE 22 | DEFER FLASH_READ \ IS M_READ 23 | DEFER PageFlash! \ записать страницу Programm Memory 24 | DEFER ByteFlash! ( byte adr -- ) \ записать байт в Programm Memory 25 | 26 | DEFER EEPROM_WRITE \ IS M_WRITE 27 | DEFER EEPROM_READ \ IS M_READ 28 | DEFER PageEPROM! ( adr -- ) \ записать страницу EEPROM 29 | DEFER ByteEPROM! ( byte adr -- ) \ записать байт в EEPROM 30 | 31 | DEFER Page! ( a u adrW -- n) \ записать страницу 32 | 33 | 34 | 35 | DEFER Memo@ ( adr -- n) \ читает память с adr, возвращает число принятых байт 36 | DEFER closeUsbDev ( -- ) \ закрыть устройство 37 | 38 | DEFER SignatureByte@ ( # -- byte ) 39 | DEFER CalibrationByte@ ( # -- byte) 40 | DEFER LockBits@ ( -- u) 41 | DEFER LockBits! ( u 0 -- ) 42 | DEFER #Fuse@ ( # -- u) \ прочитать байт № 43 | DEFER #Fuse! ( u # -- ) \ записать байт № 44 | DEFER EraseChip ( ) 45 | 46 | 47 | DEFER M_READ \ чтение из памяти 48 | DEFER M_WRITE \ запись в память 49 | DEFER PageM! \ запись в станичную память 50 | DEFER ByteM! \ запись байта в память 51 | 52 | 53 | : :( ( --) \ завершить работу с программатором 54 | CR ." :(" CR powerdown closeUsbDev QUIT 55 | ; 56 | 57 | : :[ ( adr u -- ) \ завершить работу с программатором и сказать почему 58 | TYPE :( 59 | ; 60 | 61 | : Signature@ ( -- u) 62 | 0 SignatureByte@ DUP 0x1E = 63 | IF DROP 1 SignatureByte@ 8 LSHIFT 2 SignatureByte@ OR 64 | ELSE .HEX S" Чип не от ATMEL." :[ THEN 65 | ; 66 | 67 | : DUMPchip ( adr u -- ) \ распечатать дамп из памяти чипа 68 | ?DUP IF 69 | HEX[ 0 -ROT \ счетчик строк, убрать 70 | OVER DUP Memo@ 1- OVER + SWAP \ заполнить буфер данными из чипа 71 | 2SWAP OVER + SWAP 72 | DO ( stline к н ) \ 73 | I 0x100 MOD 0= IF CR THEN \ горизонтальный блоковый интервал 74 | \ в начале строки напечатать адрес 75 | \ именно из-за этого адреса нельзя воспользоваться стандартным dump 76 | ROT DUP 0= IF I 4 .0R 2 SPACES THEN -ROT 77 | 2DUP I -ROT BETH 0= \ нужные данные есть в буфере? 78 | IF DROP 1+ DUP Memo@ 1- OVER + SWAP THEN \ нет - перезаполнить 79 | I OVER - rbuf + C@ 2 .0R SPACE \ напечатать байт 80 | \ проверить счетчик символов в строке 81 | ROT 1+ DUP 16 = 82 | IF DROP 83 | 2 SPACES 84 | \ текстовое изображение строки 85 | I OVER - 15 - rbuf + 16 86 | OVER + SWAP 87 | DO I C@ 88 | \ печатать только отображаемые символы 89 | \ DUP BL < IF DROP [CHAR] . THEN 90 | DUP BL [CHAR] ~ BETH 0= IF DROP [CHAR] . THEN 91 | EMIT 92 | LOOP 93 | 0 CR \ завершить текущую строку, счет=0, перейти на следующую 94 | ELSE DUP 8 = IF 2 SPACES THEN \ вертикальный интервал 95 | THEN -ROT \ убрать счётчик 96 | LOOP DROP 2DROP 97 | ]HEX 98 | ELSE DROP ." Пусто." CR 99 | THEN 100 | ; 101 | 102 | DEFER Byte! ( adr u adrW -- ) \ побайтная запись в память 103 | 104 | : Memo! ( buf sizebuf adrW -- ) \ записать содержимое буфера в память 105 | \ buf-окуда sizebuf-скока adrW-куда 106 | SizePage \ есть ли станицы? 107 | IF \ пишем по страницам 108 | BEGIN ( a u adrW ) 109 | OVER 0 > 110 | WHILE ( a u adrW ) 111 | 3DUP Page! \ a u adrW n 112 | >R 113 | ROT R@ + ROT R@ - ROT R> + \ сменить a'=a+n u'=u-n adrW'=adrW+n 114 | REPEAT DROP 2DROP 115 | ELSE \ пишем по байтам 116 | \ adr u adrW \ adr-окуда u-скока adrW-куда 117 | Byte! 118 | THEN 119 | ; 120 | : Verify ( adr u adrf -- f ) \ 0 - неравны 121 | \ сравнить участок памяти с записанным в чипе 122 | BEGIN 123 | OVER 124 | WHILE 125 | 2DUP Memo@ DUP 1 < IF DROP 2DROP 2DROP FALSE EXIT THEN 126 | MIN 127 | >R >R OVER R> SWAP rBuf R@ TUCK \ adr u adrf adr n rbuf n R: n 128 | COMPARE IF R> 2DROP 2DROP FALSE EXIT THEN 129 | ROT R@ + ROT R@ - ROT R> + 130 | REPEAT 2DROP DROP 131 | TRUE 132 | ; 133 | : WriteChip ( adr u adr1 -- ) \ записать u байт с адреса adr в adr1 Memory 134 | \ adr u adr1 135 | 3DUP Verify 0= 136 | IF 3DUP Memo! \ записать 137 | TwP PAUSE 138 | Verify \ проверить 139 | 0= IF ." Верификация не удалась." CR 1 THROW THEN 140 | ." Запись и верификация прошли успешно." CR 141 | \ IF ." Запись и верификация прошли успешно." CR ELSE S" Сбой записи." :[ THEN 142 | ELSE 2DROP DROP ." Верификация прошла успешно." CR 143 | THEN 144 | ; 145 | 146 | 147 | : Flash_ ( ) \ настройка на работу с програмной памятью 148 | TRUE TO AsWord? \ запись только по словами 149 | C" FLASHEND" FIND 150 | IF EXECUTE 2* 1+ ELSE DROP 0 THEN TO EndMemory 151 | C" PAGESIZE" FIND \ страничная память определена? 152 | IF EXECUTE 2* ELSE DROP 0 THEN TO SizePage 153 | C" TwdFlash" FIND \ таймаут определен? 154 | IF EXECUTE ELSE DROP 10 THEN TO TwP 155 | ['] ByteFlash! IS ByteM! 156 | ['] PageFlash! IS PageM! 157 | ['] FLASH_WRITE IS M_WRITE 158 | ['] FLASH_READ IS M_READ 159 | ; 160 | : EPROM_ ( ) \ настройка на работу с энергонезависимой памятью 161 | FALSE TO AsWord? \ запись возможна отдельными байтами 162 | C" E2END" FIND 163 | IF EXECUTE ELSE DROP 0 THEN TO EndMemory 164 | C" EEPAGESIZE" FIND \ страничная память определена? 165 | IF EXECUTE ELSE DROP 0 THEN TO SizePage 166 | C" TwdEEPROM" FIND \ таймаут определен? 167 | IF EXECUTE ELSE DROP 10 THEN TO TwP 168 | ['] ByteEPROM! IS ByteM! 169 | ['] PageEPROM! IS PageM! 170 | ['] EEPROM_WRITE IS M_WRITE 171 | ['] EEPROM_READ IS M_READ 172 | ; 173 | 174 | 175 | 176 | : N-byte ( -- n ) \ узнать число байт для записи 177 | 0 labels 178 | BEGIN @ ?DUP WHILE DUP label-value @ ROT MAX SWAP REPEAT 1+ \ -- число_бит=максимальный_номер+1 179 | 8 /MOD SWAP IF 1+ THEN \ число байт 180 | ; 181 | : Fuses! ( ) \ записать фузы в чип 182 | FUSE[ 183 | N-byte 184 | 0 ?DO seg @ I + C@ I #Fuse! LOOP 185 | ]FUSE 186 | ; 187 | : Locks! ( ) \ записать локи в чип 188 | LOCK[ 189 | N-byte 190 | 0 ?DO seg @ I + C@ I LockBits! LOOP 191 | ]LOCK 192 | ; 193 | 194 | : CheckPreProg ( adr u adr1 -- ) \ 195 | \ для начала проверим размер памяти 196 | 2DUP + EndMemory 1+ > IF ." Дамп слишком велик для данного чипа." :[ THEN 197 | AsWord? 198 | IF \ проверка чётности, если запись идёт по словам 199 | 2DUP 1 AND IF ." Адрес записи должен быть чётным." :[ THEN 200 | 1 AND IF ." Количество записываемых байт должено быть чётным." :[ THEN 201 | THEN 202 | ; 203 | 204 | : Flash! ( -- ) \ записать кодофайл в ROM 205 | ROM[ 206 | Flash_ 207 | FlashNumWrite 0= IF FlashFullWrite THEN \ заполнение по умолчанию 208 | HEX[ 209 | ." FLASH [" FlashStartAddr 4 .0R ." .." FlashStartAddr FlashNumWrite + 4 .0R ." ] " 210 | ]HEX 211 | FlashSRCAddr FlashNumWrite FlashStartAddr 212 | CheckPreProg WriteChip 213 | ]ROM 214 | ; 215 | 216 | : EPROM! ( ) \ записать кодофайл в EEPROM 217 | EPROM[ EPROM_ 218 | E2SRCAddr 0= IF E2FullWrite THEN \ заполнение по умолчанию 219 | E2NumWrite 220 | IF \ есть данные 221 | HEX[ 222 | ." EPROM [" E2StartAddr 4 .0R ." .." E2StartAddr E2NumWrite + 4 .0R ." ] " 223 | ]HEX 224 | E2SRCAddr E2NumWrite E2StartAddr 225 | CheckPreProg WriteChip 226 | THEN 227 | ]EPROM 228 | ; 229 | 230 | 231 | : #Calibr@ ( # -- byte ) \ чтение калибровочного байта "на лету" 232 | ProgEn CalibrationByte@ powerdown ; 233 | : #Calibr@. ( # -- byte ) \ чтение калибровочного байта "на лету" с печатью 234 | #Calibr@ dup CR ." Калибровочный байт RC-генератора =0x" .hex ; 235 | 236 | : ResetChip ( ) \ сброс чипа 237 | ProgEn 20 PAUSE PowerDown 238 | ; 239 | 240 | #def :> ( --) CR powerdown closeUsbDev CR TRUE THROW \ завершить работу с программатором 241 | 242 | 243 | : TheProg ( --) 244 | ['] Flash! CATCH 245 | DUP 1 = 246 | IF DROP \ верификация не прошла 247 | EraseChip 248 | Flash! 249 | ELSE THROW \ выход по ошибке 250 | THEN 251 | EPROM! Fuses! Locks! \ запись всего и с руганью на ошибки 252 | ; 253 | 254 | : Chip!! ( ) 255 | ['] ProgEn CATCH 256 | IF ." Неподключено." CR 257 | ELSE 258 | device Signature@ <> IF ." Не тот чип." :> THEN \ проверить сигнатуру 259 | CR 260 | PreProg 261 | TheProg 262 | PostProg 263 | THEN PowerDown 264 | ; 265 | 266 | 267 | -------------------------------------------------------------------------------- /programmers.f: -------------------------------------------------------------------------------- 1 | \ Сборник программаторов 2 | \ пробежаться по всем известным программаторам, 3 | \ найти подключенные, 4 | \ а среди них, тех что с чипом 5 | \ и если сигнатура чипа совпадает с целевой - прошить его 6 | WARNING OFF 7 | [WITHOUT?] MARKER S" lib/include/core-ext.f" INCLUDED [THEN] 8 | WARNING ON 9 | 10 | \ переменные для кусковой записи 11 | \ если они не определны (=0), то пишется все что есть 12 | 0 VALUE FlashSRCAddr \ начальный адрес источника для записи 13 | 0 VALUE FlashStartAddr \ начальный адрес записи 14 | 0 VALUE FlashNumWrite \ количество байт для записи 15 | 0 VALUE E2SRCAddr \ начальный адрес источника для записи 16 | 0 VALUE E2StartAddr \ начальный адрес записи 17 | 0 VALUE E2NumWrite \ количество байт для записи 18 | 19 | : FlashFullWrite \ полная запись 20 | ROM[ SEG @ wender 0 ]ROM TO FlashStartAddr TO FlashNumWrite TO FlashSRCAddr 21 | ; 22 | : E2FullWrite \ полная запись 23 | EPROM[ SEG @ wender 0 ]EPROM TO E2StartAddr TO E2NumWrite TO E2SRCAddr 24 | ; 25 | 26 | 0 VALUE USBdevs \ общее количество USBустройств 27 | 28 | : addUSB1 ( ) \ подключение библиотеки 29 | C" LIBUSB_LOG_LEVEL_NONE" FIND NIP 0= IF S" ~iva/AVR/USB1.f" INCLUDED THEN 30 | ; 31 | 32 | : USB1 ( -- f ) \ активизировать библиотеку USB, 33 | \ f=FALSE в случае неуспеха 34 | \ f= общее количество USBустройств 35 | ['] addUSB1 CATCH 0= 36 | IF C" initUSB" FIND DROP EXECUTE \ инциализировать и получить список устройств 37 | ELSE FALSE 38 | THEN 39 | ; 40 | 41 | DEFER PreProg \ действия перед программированием чипа 42 | DEFER PostProg \ действия после программирования чипа 43 | :NONAME ; \ пустое действие 44 | DUP IS PreProg IS PostProg 45 | 46 | : chip! ( --) \ записать в чип 47 | S" ~iva/AVR/prog.f" INCLUDED 48 | USB1 ?DUP 49 | IF TO USBdevs 50 | \ попытка через UsbTiny 51 | S" ~iva/AVR/USBtiny1.f" INCLUDED 52 | \ попытка через AVRISP_mk2 53 | S" ~iva/AVR/AVRISP_mk2.f" INCLUDED 54 | THEN 55 | ; 56 | 57 | 58 | 59 | #def {QUIT} .( Прошу пана:) CR EndedLoop THROW 60 | 61 | : chip: ( ) \ войти в режим программирования, но не программировать 62 | ['] {QUIT} IS PreProg 63 | chip! 64 | ; 65 | 66 | : chip!: ( ) \ запрограммировать и остаться в чипе 67 | ['] {QUIT} IS PostProg 68 | chip! 69 | ; 70 | 71 | \EOF 72 | \ ======== интерактивная работа с чипом до записи ========================= 73 | \ срабатывает 1 раз на первом подходящем чипе 74 | chip: \ ключевое слово 75 | \ пример что делать 76 | flash_ 0 wender dumpchip cr \ посмотреть 77 | EPROM[ 0x123 w>seg ]Eprom \ изменить 78 | theprog cr \ зашить 79 | 80 | chip: eprom_ 0 E2END 1+ dumpchip cr 81 | \ ======== автозапись ================================================== 82 | \ срабатывает на каждом подходящем чипе 83 | \ если используются известные слова можно использовать конструкцию :NONAME IS 84 | :NONAME EPROM[ 0x5523 w>seg ]Eprom ; IS PreProg 85 | \ если используются слова специфические для режима программирования чипа 86 | \ и известные только в этом режиме - используется запись #def и привязка IS 87 | #def {post} eprom_ 0 16 dumpchip 88 | ' {post} IS PostProg 89 | chip! \ ключевое слово 90 | \ ======== интерактивная работа с чипом после записи ========================= 91 | \ срабатывает 1 раз на первом подходящем чипе 92 | chip!: \ ключевое слово 93 | flash_ 0 wender dumpchip \ пример что делать 94 | 95 | 96 | -------------------------------------------------------------------------------- /sborAVR.f: -------------------------------------------------------------------------------- 1 | DECIMAL 2 | \ слова для унификации кода и удобства написания программ 3 | : (IF) POSTPONE IF ; IMMEDIATE 4 | : (THEN) POSTPONE THEN ; IMMEDIATE 5 | ALSO DASSM 6 | : VECTOR> ( adr <"name"> -- ) \ приписывает вектор к name 7 | 8 | BL WORD COUNT EVALUATE 9 | finger >R 10 | (SWAP) finger! 11 | \ RJMP 0 coder 12 | GOTO 0 coder 13 | R> finger! 14 | ; 15 | : -- ) \ приписывает вектор с name к текущему адресу (finger) 16 | finger >R 0 coder \ R: adr слова на которое укажет вектор 17 | finger \ следующий адрес компиляции 18 | BL WORD COUNT EVALUATE finger! \ переход на вектор 19 | GOTO R> \ компиляция перехода 20 | 0 coder 21 | finger! \ востановить адрес компиляции 22 | ; 23 | PREVIOUS 24 | : NOADR ( ) 25 | TRUE ABORT" Неверный адрес." ; 26 | \ ===================================== 27 | SAVE-VOCS ALSO DASSM DEFINITIONS 28 | \ нижеследующие слова будут работать только в режиме ассемблирования 29 | \ 16-ти битные операции: 30 | \ Младший байт по младшему адресу; 31 | \ Старший байт в порт пишется первым, читается последним; 32 | \ Пара представляется младшим адресом. 33 | 34 | : DUPLET ( a b -- a b a+1 b+1 ) 35 | OVER 1+ OVER 1+ \ продублировать и модифицировать операнды (старший сверху) 36 | ; 37 | 38 | : LDIW ( j*x <"Rd,k"> -- i*x) \ загрузка пары регистров константой 39 | DOAFTER> ( Rd k --) 40 | OVER >R \ скопировать Rd в R-стек 41 | BYTE-SPLIT \ разчленить K на байты 42 | R> 1+ (SWAP) 43 | LDI LDI \ дважды выполнить загрузку по байту 44 | ; 45 | : CLRW ( <"Rd"> --) \ очистит регистровую пару 46 | DOAFTER> ( Rd -- ) 47 | DUP CLR 1+ CLR 48 | ; 49 | : ORW ( <"Rd Rr"> -- ) \ логическое ИЛИ регистровых пар 50 | DOAFTER> ( Rd Rr -- ) 51 | DUPLET OR OR 52 | ; 53 | : ANDW ( <"Rd Rr"> -- ) \ логическое И регистровых пар 54 | DOAFTER> ( Rd Rr -- ) 55 | DUPLET AND AND 56 | ; 57 | : COMW ( <"Rd"> --) \ инвертирование пары регистров 58 | DOAFTER> ( Rd -- ) 59 | DUP 1+ COM COM 60 | ; 61 | : ADDI ( <"Rd k"> --) 62 | DOAFTER> ( Rd k -- ) 63 | DUP 255 > ABORT" Операнд больше байта" 64 | NEGATE (LB) ( Rd lowByte[-k] --) 65 | SUBI 66 | ; 67 | : SUBIW ( <"Rd k"> -- ) 68 | DOAFTER> ( Rd k -- ) 69 | DUP 65535 > ABORT" Операнд больше двух байт" 70 | >R 71 | DUP 1+ (SWAP) ( Rd+1 Rd --) 72 | R@ (HB) (SWAP) R> (LB) ( Rd+1 highByte[k] Rd lowByte[k] --) 73 | SUBI SBCI 74 | ; 75 | : ADDIW ( <"Rd k"> -- ) 76 | DOAFTER> ( Rd k -- ) 77 | DUP 65535 > ABORT" Операнд больше двух байт" 78 | NEGATE 0xFFFF (AND) 79 | SUBIW 80 | ; 81 | [WITH?] ADIW 82 | : NEGW ( <"Rd"> --) \ смена знака пары регистров 83 | DOAFTER> ( Rd -- ) 84 | 1 OVER COMW ADIW 85 | ; 86 | [THEN] 87 | : ADDW ( <"Rd Rr"> -- ) 88 | DOAFTER> ( Rd Rr -- ) 89 | DUPLET 2SWAP ADD ADC 90 | ; 91 | : SUBW ( <"Rd Rr"> -- ) 92 | DOAFTER> ( Rd Rr -- ) 93 | DUPLET 2SWAP SUB SBC 94 | ; 95 | : ASRW ( <"Rd"> --) \ арифметический сдвиг пары регистров 96 | DOAFTER> ( Rd -- ) 97 | DUP 1+ ASR ROR 98 | ; 99 | : LSRW ( <"Rd"> --) \ логический сдвиг пары регистров вправо 100 | DOAFTER> ( Rd -- ) 101 | DUP 1+ LSR ROR 102 | ; 103 | : LSLW ( <"Rd"> --) \ логический сдвиг пары регистров влево 104 | DOAFTER> ( Rd -- ) 105 | DUP 1+ (SWAP) LSL ROL 106 | ; 107 | : RORW ( <"Rd"> --) \ циклический сдвиг пары регистров вправо 108 | DOAFTER> ( Rd -- ) 109 | DUP 1+ ROR ROR 110 | ; 111 | : ROLW ( <"Rd"> --) \ циклический сдвиг пары регистров влево 112 | DOAFTER> ( Rd -- ) 113 | DUP 1+ (SWAP) ROL ROL 114 | ; 115 | 116 | WARNING OFF 117 | [WITH?] LDS \ вариант при наличии LDS и STS 118 | : IN ( <"Rd Port"> --) \ в зависимости от адреса порта скомпилировать 119 | \ команду IN, MOV или LDS 120 | DOAFTER> ( Rd Port --) 121 | DUP IFREG MOV EXIF; 122 | DUP IFnear IN EXIF; 123 | DUP IFfar LDS EXIF; 124 | NOADR ; 125 | : OUT ( <"Port Rr"> --) \ в зависимости от адреса порта скомпилировать 126 | \ команду OUT или STS 127 | DOAFTER> ( Port Rr --) 128 | OVER IFREG MOV EXIF; 129 | OVER IFnear OUT EXIF; 130 | OVER IFfar STS EXIF; 131 | NOADR ; 132 | 133 | : LDSW ( j*x <"Rd,k"> -- i*x) \ загрузить Rd и Rd+1 данными из адреса k и k+1 134 | DOAFTER> ( Rd k -- ) 135 | DUPLET 2SWAP LDS LDS ( младший читается первым) 136 | ; 137 | : STSW ( j*x <"k,Rd"> -- i*x) \ сохранить Rd и Rd+1 по адресу k и k+1 138 | DOAFTER> ( k Rd -- ) 139 | DUPLET 140 | LowFirstRW (IF) 2SWAP (THEN) ( младший пишется первым, иначе старший пишется первым) 141 | STS STS 142 | ; 143 | 144 | \ : LDW ??? 145 | \ : STW ??? 146 | \ : LDDW ??? 147 | \ : STDW ??? 148 | 149 | [ELSE] \ вариант при отсутствии LDS и STS 150 | : IN ( <"Rd Port"> --) \ в зависимости от адреса порта скомпилировать 151 | \ команду IN или MOV 152 | DOAFTER> ( Rd Port --) 153 | DUP IFREG MOV EXIF; 154 | DUP IFnear IN EXIF; 155 | NOADR ; 156 | : OUT ( <"Port Rr"> --) \ в зависимости от адреса порта скомпилировать 157 | \ команду OUT или STS 158 | DOAFTER> ( Port Rr --) 159 | OVER IFREG MOV EXIF; 160 | OVER IFnear OUT EXIF; 161 | NOADR ; 162 | 163 | [THEN] 164 | [WITH?] MOVW 165 | \ вариант при наличии MOVW в системе команд 166 | : 2evenReg? ( adr adr --f) \ проверить принадлежат ли эти адреса четным регистрам 167 | OVER Reg? OVER Reg? (AND) \ true - оба регистры 168 | ROT 1 (AND) ROT 1 (AND) (OR) 0= \ true - оба четные 169 | (AND) 170 | ; 171 | : 2IN ( j*x <"Rd Port"> -- i*x) \ загрузка пары 172 | DOAFTER> 173 | 2DUP 2evenReg? (IF) MOVW EXIF; \ если оба чётные регистры 174 | DUPLET 2SWAP IN IN \ выполнить 2 раза IN ( младший читается первым) 175 | ; 176 | : 2OUT ( j*x <"Port Rr"> -- i*x) \ выгрузка пары 177 | DOAFTER> ( Port Rr --) 178 | 2DUP 2evenReg? (IF) MOVW EXIF; \ если оба чётные регистры 179 | DUPLET 180 | LowFirstRW (IF) 2SWAP (THEN) ( младший пишется первым, иначе старший пишется первым) 181 | OUT OUT \ выполнить 2 раза OUT 182 | ; 183 | [ELSE] 184 | \ вариант при отсутствии MOVW в системе команд 185 | : 2IN ( j*x <"Rd Port"> -- i*x) \ загрузка пары 186 | DOAFTER> 187 | DUPLET 2SWAP IN IN \ выполнить 2 раза IN ( младший читается первым) 188 | ; 189 | : 2OUT ( j*x <"Port Rr"> -- i*x) \ выгрузка пары 190 | DOAFTER> ( Port Rr --) 191 | DUPLET 192 | OUT OUT \ выполнить 2 раза OUT (старший пишется первым) 193 | ; 194 | [THEN] 195 | : OUTW 2OUT ; \ псевдоим 196 | : INW 2IN ; \ псевдоим 197 | 198 | : MOV ( <"addr1 addr2"> --) \ в зависимости от адресов операндов скоммпилировать 199 | \ mov in out sts lds 200 | DOAFTER> 201 | DUP IFREG OUT EXIF; 202 | OVER IFREG IN EXIF; 203 | ABORT" MOV -- один из операндов должен быть регистром." 204 | ; 205 | : 2MOV ( <"addr1 addr2"> --) \ в зависимости от адресов операндов скоммпилировать 206 | \ пары mov in out sts lds для 207 | DOAFTER> ( Port Rr --) 208 | DUP IFREG 2OUT EXIF; 209 | OVER IFREG 2IN EXIF; 210 | ABORT" MOV -- один из операндов должен быть регистром." 211 | ; 212 | 213 | : MOVW 2MOV ; 214 | 215 | WARNING ON 216 | 217 | [WITH?] PUSH \ если есть PUSH и POP 218 | : PUSHW ( <"RegL"> ---) \ сохранить на стеке пару регистров 219 | DOAFTER> ( Rr --) 220 | DUP 1+ (SWAP) PUSH PUSH ; 221 | : POPW ( <"RegL"> ---) \ востановить из стека пару регистров 222 | DOAFTER> ( Rr --) 223 | DUP 1+ POP POP ; 224 | [THEN] 225 | : CPW ( <"Rd Rr"> -- ) \ сравнить пары регистров 226 | DOAFTER> ( Rd Rr --) 227 | DUPLET 2SWAP CP CPC ; ( начинать с младшего) 228 | : FOR ( ) \ начало цикла со счётчиком 229 | BEGIN ; 230 | : NEXT ( <"reg"> --) \ конец цикла со счётчиком 231 | DOAFTER> ( reg --) 232 | DEC BRNE 1V> ; 233 | 234 | : XCHG ( <"Rd Rr"> --) \ обменять содержимое регистров за 3 такта 235 | DOAFTER> ( Rd Rr --) 236 | 2DUP (SWAP) 2DUP (SWAP) EOR EOR EOR 237 | ; 238 | 239 | : XCHGW ( <"Rd,Rr"> --) \ обменять регистровые пары 240 | DOAFTER> ( Rd Rr -- ) 241 | DUPLET XCHG XCHG 242 | ; 243 | 244 | RESTORE-VOCS 245 | 246 | -------------------------------------------------------------------------------- /selectAVR.f: -------------------------------------------------------------------------------- 1 | DECIMAL 2 | CR 3 | \ ======== система команд микропроцессора ====================================== 4 | [FOUND?] WARNING [IF] WARNING OFF [THEN] 5 | FALSE VALUE LowFirstRW \ младший байт читается И записывается первым 6 | \ этот флаг TRUE для xMega 7 | 0 CONSTANT ISPprog 8 | 1 CONSTANT PDIprog 9 | 2 CONSTANT TPIprog 10 | ISPprog VALUE ProgInterface \ интерфейс программирования 11 | 12 | : ProgInterfaceS ( -- addr u) \ выдать строку с именем интерфейса программирования 13 | ProgInterface ISPprog = IF S" ISP" ELSE 14 | ProgInterface PDIprog = IF S" PDI" ELSE 15 | ProgInterface TPIprog = IF S" TPI" ELSE 16 | TRUE ABORT" Неизвестный интерфейс программирования." 17 | THEN THEN THEN 18 | ; 19 | 20 | [FOUND?] device 21 | S" ~iva/AVR/chips/" >S \ где искать файлы описания микроконтроллеров, ниже добавим нужный файл 22 | S [THEN] 27 | device 0x 9307 = [IF] .( Процессор ATmega8 ) S" m8.ff" +>S [THEN] 28 | device 0x 9109 = [IF] .( Процессор ATtiny26 ) S" tn26.ff" +>S [THEN] 29 | device 0x 910C = [IF] .( Процессор ATtiny261 ) S" tn261.ff" +>S [THEN] 30 | \ device 0x 910A = [IF] .( Процессор ATtiny2313) S" tn2313.ff" +>S [THEN] 31 | device 0x 910A = [IF] .( Процессор ATtiny2313A) S" tn2313A.ff" +>S [THEN] 32 | device 0x 920D = [IF] .( Процессор ATtiny4313) S" tn4313.ff" +>S [THEN] 33 | device 0x 9205 = [IF] .( Процессор ATmega48) S" m48.ff" +>S [THEN] 34 | device 0x 920A = [IF] .( Процессор ATmega48P) S" m48pa.ff" +>S [THEN] 35 | device 0x 930F = [IF] .( Процессор ATmega88P) S" m88pa.ff" +>S [THEN] 36 | device 0x 940B = [IF] .( Процессор ATmega168PA) S" m168pa.ff" +>S [THEN] 37 | device 0x 9406 = [IF] .( Процессор ATmega168A) S" m168a.ff" +>S [THEN] 38 | device 0x 9514 = [IF] .( Процессор ATmega328) S" m328.ff" +>S [THEN] 39 | device 0x 9108 = [IF] .( Процессор ATtiny25) S" tn25.ff" +>S [THEN] 40 | device 0x 910B = [IF] .( Процессор ATtiny24) S" tn24.ff" +>S [THEN] 41 | device 0x 9206 = [IF] .( Процессор ATtiny45) S" tn45.ff" +>S [THEN] 42 | device 0x 9207 = [IF] .( Процессор ATtiny44) S" tn44.ff" +>S [THEN] 43 | device 0x 9215 = [IF] .( Процессор ATtiny441) S" tn441.ff" +>S [THEN] 44 | device 0x 930B = [IF] .( Процессор ATtiny85) S" tn85.ff" +>S [THEN] 45 | device 0x 930C = [IF] .( Процессор ATtiny84) S" tn84.ff" +>S [THEN] 46 | device 0x 9315 = [IF] .( Процессор ATtiny841) S" tn841.ff" +>S [THEN] 47 | device 0x 9007 = [IF] .( Процессор ATtiny13 ) S" tn13.ff" +>S [THEN] 48 | device 0x 9843 = [IF] .( Процессор ATxMega256A3BU ) S" x256A3BU.ff" +>S PDIprog TO ProgInterface [THEN] 49 | device 0x 9541 = [IF] .( Процессор ATxMega32A4U ) S" x32A4U.ff" +>S PDIprog TO ProgInterface [THEN] 50 | device 0x 9441 = [IF] .( Процессор ATxMega16A4U ) S" x16A4U.ff" +>S PDIprog TO ProgInterface [THEN] 51 | [ELSE] .( Процессор AVR не определён.) CR 52 | S" ../AVR_instructions.set" +>S 53 | [THEN] 54 | 55 | 0 EMIT>S S@ INCLUDED S>DROP \ добавляем ноль в конец, загрузим файл 56 | LABELS> CR 57 | 58 | [FOUND?] WARNING [IF] WARNING ON [THEN] 59 | 70 | 71 | S" ~iva/AVR/bitsAVR.f" INCLUDED \ подключить битовые слова 72 | S" ~iva/AVR/fuses.f" INCLUDED \ для работы с фузами и локами 73 | S" ~iva/AVR/sborAVR.f" INCLUDED \ подключить сборные слова 74 | \ S" ~iva/AVR/USBprog.f" INCLUDED \ подключить программатор (старая ветка) 75 | S" ~iva/AVR/programmers.f" INCLUDED \ подключить программаторы 76 | 77 | \ установить указатель на начало SRAM, если оно есть 78 | RAMEND 0 > [IF] RAM[ SRAM_START ORG ]RAM [THEN] 79 | VOCABULARY PROJECT \ словарь проекта 80 | ALSO PROJECT DEFINITIONS 81 | 82 | -------------------------------------------------------------------------------- /spf.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivanivanovo/AVR/58ee10856bcf813c3895b71387ff21304bc7ddea/spf.log -------------------------------------------------------------------------------- /spforth.lang: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | text/x-forth 26 | *.f;*.ff;*.g; 27 | \ 28 | (* 29 | *) 30 | 31 | 32 | 33 |