diff options
author | Camil Staps | 2019-12-30 22:44:25 +0100 |
---|---|---|
committer | Camil Staps | 2019-12-30 22:44:25 +0100 |
commit | 6b2f4a6f0e87147a46de16066ff756aa4f9d9274 (patch) | |
tree | 9a40a64d22a13b5c264c93430ca28d3e07176861 |
Initial committests
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Makefile | 20 | ||||
-rw-r--r-- | README.md | 52 | ||||
-rw-r--r-- | main.s | 159 |
4 files changed, 234 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2135d58 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.elf +*.hex +*.o diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2d60cfa --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +XC32_PATH=/opt/microchip/xc32/v2.30/bin + +NAME:=main +PROCESSOR:=32MZ2048ECG064 + +ASM:=$(NAME).s +OBJ:=$(NAME).o +ELF:=$(NAME).elf +HEX:=$(NAME).hex + +default: $(HEX) + +$(OBJ): %.o: %.s + $(XC32_PATH)/xc32-as -o $@ $< + +$(ELF): $(OBJ) + $(XC32_PATH)/xc32-gcc -mprocessor=$(PROCESSOR) -o $@ $^ + +$(HEX): $(ELF) + $(XC32_PATH)/xc32-bin2hex $< diff --git a/README.md b/README.md new file mode 100644 index 0000000..ceba168 --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +# Readme + +This is a test to get a PIC32MZ2048ECG064 running without the MPLAB IDE. There +is an Assembly file and a Makefile. The generated HEX can be uploaded using the +MPLAB IPE. Generating C code is fairly similar, but uses `gcc` instead of `as`. + +### Links + +About the chip: https://www.microchip.com/wwwproducts/en/PIC32MZ2048ECG064 +About the architecture: https://www.cs.cornell.edu/courses/cs3410/2008fa/MIPS_Vol1.pdf +About the instruction set: https://www.cs.cornell.edu/courses/cs3410/2008fa/MIPS_Vol2.pdf + +## Notes to self + +### Instruction set + +This chip has a somewhat larger instruction set than MIPS32; it is a MIPS32 +microAptiv. For this extension, see ยง50 of the PIC32 reference manual (to be +found on the chip information page linked above). It is not clear to me how +widespread this instructions set is (i.e. whether it would make sense to rely +on it being available for code generation or so). + +### Branch delay slots + +Watch out for the branch/jump instructions. The following instruction is always +executed, regardless of whether the branch is taken or not. This instruction is +said to be in the 'branch delay slot'. For example, this does not loop +endlessly even though the body of `main_loop_delay` seems empty: + +``` + lui $2,0xf + ori $5,0xffff +main_loop_delay: + bne $2,$0,main_loop_delay + addiu $2,-1 +``` + +Also note that when the file ends with a branch/jump, a `nop` *must* follow to +avoid unpredictable behaviour (the following instruction could be anything +otherwise). + +### `lw` and `lui` + +One needs `lui` to load an address, e.g. to clear `TRISB`: + +``` + lui $2,%hi(TRISB) + sw $0,%lo(TRISB)($2) +``` + +Using `lw` instead of `lui` is an easy mistake, assembles fine, but you usually +end up reading out of memory leading to a reset. @@ -0,0 +1,159 @@ + # SEQ0 + .section .config_BFC0FFFC, code, keep, address(0xBFC0FFFC) + .type __config_BFC0FFFC, @object + .size __config_BFC0FFFC, 4 +__config_BFC0FFFC: + .word 0xFFFFFFFF + # DEVCP0 + .section .config_BFC0FFDC, code, keep, address(0xBFC0FFDC) + .type __config_BFC0FFDC, @object + .size __config_BFC0FFDC, 4 +__config_BFC0FFDC: + .word 0xFFFFFFFF + # DEVCFG0 + .section .config_BFC0FFCC, code, keep, address(0xBFC0FFCC) + .type __config_BFC0FFCC, @object + .size __config_BFC0FFCC, 4 +__config_BFC0FFCC: + .word 0xFFFFFFDB + # DEVCFG1 + .section .config_BFC0FFC8, code, keep, address(0xBFC0FFC8) + .type __config_BFC0FFC8, @object + .size __config_BFC0FFC8, 4 +__config_BFC0FFC8: + .word 0x5F74FF39 + # DEVCFG2 + .section .config_BFC0FFC4, code, keep, address(0xBFC0FFC4) + .type __config_BFC0FFC4, @object + .size __config_BFC0FFC4, 4 +__config_BFC0FFC4: + .word 0x7FF9B198 # SPLL is 8MHz (FRC) / 1 * 50 / 2 = 200MHz + # DEVCFG3 + .section .config_BFC0FFC0, code, keep, address(0xBFC0FFC0) + .type __config_BFC0FFC0, @object + .size __config_BFC0FFC0, 4 +__config_BFC0FFC0: + .word 0xBFFFFFFF + + .section .sdata,data + .type string, @object +string: + .ascii "Hello, world!\0" + .size string, .-string + + .section .text,code + .align 2 + + .set nomips16 + .set nomicromips + .set noreorder + .set nomacro + + .globl main + .ent main + .type main, @function +main: + # Unlock + di $2 + ehb + lui $2,%hi(SYSKEY) + sw $0,%lo(SYSKEY)($2) + lui $3,0xaa99 + ori $3,0x6655 + sw $3,%lo(SYSKEY)($2) + lui $3,0x5566 + ori $3,0x99aa + sw $3,%lo(SYSKEY)($2) + # PB7DIV := 0x00008800 (CPU clock: enable; SPLL / 1 = 200MHz) + lui $2,%hi(PB7DIV) + xor $3,$3 + ori $3,0x8800 + sw $3,%lo(PB7DIV)($2) + # PB2DIV := 0x00008818 (UART clock: enable; SPLL / 25 = 8MHz) + lui $2,%hi(PB2DIV) + xor $3,$3 + ori $3,0x8818 + sw $3,%lo(PB2DIV)($2) + # Lock + lui $2,%hi(SYSKEY) + sw $0,%lo(SYSKEY)($2) + ei $2 + ehb + + # TRISB := 0 + lui $2,%hi(TRISB) + sw $0,%lo(TRISB)($2) + + # Remappable pins + # RPG7 is U1TX + xor $3,$3 + ori $3,1 + lui $2,%hi(RPG7R) + sw $3,%lo(RPG7R)($2) + # RPG8 is U1RX + lui $2,%hi(U1RXR) + sw $3,%lo(U1RXR)($2) + # TRISG + xor $3,$3 + ori $3,0xfff7 + lui $2,%hi(TRISG) + sw $3,%lo(TRISG)($2) + + # UART + xor $3,$3 + ori $3,0x1400 + lui $2,%hi(U1STA) + sw $3,%lo(U1STA)($2) + # BRG := 0; with 8MHz peripheral clock gives baud rate 500000 + xor $3,$3 + lui $2,%hi(U1BRG) + sw $3,%lo(U1BRG)($2) + xor $3,$3 + ori $3,0x8000 + lui $2,%hi(U1MODE) + sw $3,%lo(U1MODE)($2) + + # Prepare main loop + lui $10,%hi(LATB) + lui $11,%hi(U1STA) + lui $12,%hi(U1TXREG) + lui $13,%hi(string) + ori $13,%lo(string) + # Main loop +main_loop: + # Toggle LED at LATB.B15 + lw $4,%lo(LATB)($10) + andi $6,$4,0x8000 + andi $4,$4,0x7fff + xori $6,0x8000 + or $4,$4,$6 + sh $4,%lo(LATB)($10) + + # Wait for UART buffer to empty + lw $4,%lo(U1STA)($11) +main_loop_tx_buffer_full: + andi $4,$4,0x200 # UTXBF + bne $4,$0,main_loop_tx_buffer_full + lw $4,%lo(U1STA)($11) + + # Write one character of the string to U1TXREG + lb $4,($13) + bne $4,$0,main_loop_no_end_of_string + addi $13,1 + lui $13,%hi(string) + ori $13,%lo(string) + li $4,10 # \n +main_loop_no_end_of_string: + sw $4,%lo(U1TXREG)($12) + + # Busy wait delay loop + lui $2,0xff + ori $5,0xffff +main_loop_delay: + bne $2,$0,main_loop_delay + addiu $2,-1 + j main_loop + nop + + .end main + .size main, .-main |