diff --git a/programs/Makefile b/programs/Makefile new file mode 100644 index 0000000..fee8dbd --- /dev/null +++ b/programs/Makefile @@ -0,0 +1,26 @@ +# Define directories +SRC_DIR = ../src +PROGRAMS_DIR = ../programs +PROGRAMS_LIB_DIR = $(PROGRAMS_DIR)/lib +ASSEMBLE = $(SRC_DIR)/assemble +SOURCE = $(PROGRAMS_DIR)/led_blink.s +OUTPUT = $(PROGRAMS_DIR)/kernel8.img + +# Default target +default: + $(MAKE) -C $(SRC_DIR) + cd $(SRC_DIR) && $(ASSEMBLE) $(SOURCE) $(OUTPUT) + cd $(PROGRAMS_DIR) + $(MAKE) -C $(SRC_DIR) clean + +commented: remove_comments default + +remove_comments: + python $(PROGRAMS_LIB_DIR)/remove_comments.py $(PROGRAMS_LIB_DIR)/led_blink_commented.s $(SOURCE) + + +# Clean +clean: + $(MAKE) -C $(SRC_DIR) clean + rm -f $(OUTPUT) + \ No newline at end of file diff --git a/programs/README.md b/programs/README.md new file mode 100644 index 0000000..9eaefdf --- /dev/null +++ b/programs/README.md @@ -0,0 +1,38 @@ +# LED Blink Program + +This is an example program to test the assembler. It blinks an LED in a Raspberry Pi 3B model. +You can find the source code in the file `led_blink.s`. + +## How to run + +Run the following commands in the terminal: + +```bash +$ make +``` + +You should then find the compiled binary file `kernel8.img` in this folder. Copy this file +along with [start.elf](https://github.com/raspberrypi/firmware/blob/master/boot/start.elf) and [bootcode.bin](https://github.com/raspberrypi/firmware/blob/master/boot/bootcode.bin) to an SD card and insert it into the Raspberry Pi 3B model. + +Connect an LED to the GPIO Pin 4 (physical pin 7) and the ground pin (physical pin 6) of the Raspberry Pi. Connect the longer leg of the LED to a 220 ohm resistor and then to the GPIO Pin 4. Connect the shorter leg of the LED to the ground pin. The following picture shows the connections: + +![LED Blink Circuit](lib/images/led_blink_circuit.jpeg) + +(The yellow wire is ground and the cyan wire is GPIO Pin 4) + +Power on the Raspberry Pi and you should see the LED blinking, as shown in the following image: + +![LED Blink](lib/images/led_blink.gif) + + +## How it works + +A commented version of the source code can be found in the file `lib/led_blink_commented.s`. + +If you want to make any changes to the program, such as changing the GPIO pin or the blinking frequency, you might find it easier to edit the commented version of the source code. Once you are done, you can run the following command: + +```bash +$ make commented +``` + +This will generate the file `led_blink.s` with the changes you made. The program then is compiled and the file `kernel8.img` is generated in this folder. You can then follow the steps above to run the program in the Raspberry Pi. diff --git a/programs/led_blink.s b/programs/led_blink.s new file mode 100644 index 0000000..f010ea0 --- /dev/null +++ b/programs/led_blink.s @@ -0,0 +1,16 @@ +movz w1, #0x10 +movz w2, #0x1000 +movz x3, #0x3f20, lsl #16 +str w2, [x3] +loop: +str w1, [x3, #0x1c] +movz w4, #0x30, lsl #16 +sleep1: +subs w4, w4, #1 +b.ne sleep1 +str w1, [x3, #0x28] +movz w4, #0x30, lsl #16 +sleep2: +subs w4, w4, #1 +b.ne sleep2 +b loop diff --git a/programs/lib/images/led_blink.gif b/programs/lib/images/led_blink.gif new file mode 100644 index 0000000..26f63b1 Binary files /dev/null and b/programs/lib/images/led_blink.gif differ diff --git a/programs/lib/images/led_blink_circuit.jpeg b/programs/lib/images/led_blink_circuit.jpeg new file mode 100644 index 0000000..031642c Binary files /dev/null and b/programs/lib/images/led_blink_circuit.jpeg differ diff --git a/programs/lib/led_blink_commented.s b/programs/lib/led_blink_commented.s new file mode 100644 index 0000000..df2cd68 --- /dev/null +++ b/programs/lib/led_blink_commented.s @@ -0,0 +1,54 @@ +--------------- LED BLINK PROGRAM --------------- +------------------------------------------------- +--- Do NOT use this file as the source assembly, as this format of comments are +--- not allowed in either assemblers (ours, or the official ARM assembler). +--- Please read README.md before reading this file +------------------------------------------------- + +--- How it works --- +-- In psuedocode, the overall idea: +-- +-- setup() +-- while (true): +-- turn_on() +-- sleep() +-- turn_off() +-- sleep() +-- +-- Now, there is no sleep function obviously. So, we will use a loop to simulate +-- to simulate the sleep function. The loop will run for about 3 million times. +-- this was experimentally determined to be a good value for a sleep of about half a second. +-- In other words: +-- +-- sleep(): for i=0 to 3,145,728: continue +-- +-- We now start with the actual code. +-- +-- +-- The setup() part: +-- +movz w1, #0x10 -- w1 contains the binary value 1 0000, this is to set the GPSET0 and GPCLR0 registers, to set/clear GPIO 4. +movz w2, #0x1000 -- value to set the FSEL4 to output (001 followed by 000 four times). This is to set the GPIO 4 to output mode. +movz x3, #0x3f20, lsl #16 -- x3 contains the address of the GPIO registers. +str w2, [x3] -- sets GPIO 2 to output mode (FSEL = 1). + +-- This is the main while loop that will run forever. +loop: +str w1, [x3, #0x1c] -- sets GPIO 2 on. GPSET0 address is [x3] + 0x1c. This writes 1 to the 4th bit of the GPSET0 register. +movz w4, #0x30, lsl #16 -- let i = 3,145,728. Used for the sleep function. + +-- sleep() function: +sleep1: +subs w4, w4, #1 -- i--; +b.ne sleep1 -- repeat until i = 0. + +-- turn off the LED. +str w1, [x3, #0x28] -- sets GPIO 2 off. GPCLR0 address is [x3] + 0x28. This writes 1 to the 4th bit of the GPCLR0 register. +movz w4, #0x30, lsl #16 -- let i = 3,145,728. Used for the sleep function. + +-- sleep() function: +sleep2: +subs w4, w4, #1 -- i--; +b.ne sleep2 -- repeat off. + +b loop -- repeat the main loop diff --git a/programs/lib/remove_comments.py b/programs/lib/remove_comments.py new file mode 100644 index 0000000..b9c14f0 --- /dev/null +++ b/programs/lib/remove_comments.py @@ -0,0 +1,16 @@ +def remove_comments(input_file, output_file): + with open(input_file, 'r') as infile, open(output_file, 'w') as outfile: + for line in infile: + cleaned_line = line.split('--')[0].rstrip() # Remove comment and trailing whitespace + if cleaned_line: # Check if the line is not empty + outfile.write(cleaned_line + '\n') + +if __name__ == "__main__": + import sys + if len(sys.argv) != 3: + print("Usage: python remove_comments.py ") + sys.exit(1) + + input_file = sys.argv[1] + output_file = sys.argv[2] + remove_comments(input_file, output_file)