代写辅导接单-# Lab 3 C language

欢迎使用51辅导,51作业君孵化低价透明的学长辅导平台,服务保持优质,平均费用压低50%以上! 51fudao.top

# Lab 3

 

This lab introduces the basic I/O capabilities of the DE1-SoC computer, more specifically, the slider switches, pushbuttons, LEDs, and 7-Segment (HEX) displays. After writing assembly drivers that interface with the I/O components, we will use the higher level I/O capabilities of the

<a href="./docs/DE1-SoC_Computer_ARM.pdf">DE1-SOC Computer Manual</a>

to

 

1.  display pixels and characters using the VGA controller, and

2.  accept keyboard input via the PS/2 port.

 

For each of these topics, we will create a driver. We will test the drivers both individually and in tandem by means of test applications.

 

## Getting started

This lab requires students to use <a href="https://gcc.gnu.org/onlinedocs/gcc/extensions-to-the-c-language-family/how-to-use-inline-assembly-language-in-c-code.html">inline assembly</a> to finish the tasks below.

Inline assembly allows users to combine C language with assembly.

To get started, please make sure the language setup is configured as C rather than ARMv7.

 

![simulator](./images/simulator_c.jpg)

 

Also please ensure that you are using the `HTTPS` protocol when accessing the simulator otherwise you will receive a server error when compiling.

Here is the `HTTPS` url: [https://ecse324.ece.mcgill.ca/simulator/?sys=arm-de1soc](https://ecse324.ece.mcgill.ca/simulator/?sys=arm-de1soc)

 

This is an example of using ARM assembly with C.

``` c

int foo(int x){

int y = 0;

__asm__ __volatile__(

"add %0, %1, %2\n\t" // %0, %1, and %2 are linked to output and input operands. y = x + 10.

       :"=r"(y)             // Output operands: %0

       :"r"(x), "r"(10)     // Input operands: %1, %2

:"r1"                // Clobbers

);

return y;

}

 

int main() {

int x = 0;

printf("Before inline assembly: x = %d\n", x);

__asm__ __volatile__(

"mov r0, %0\n\t"    // \n\t is newline in assembly and required for each line.

"bl foo\n\t"// Call function foo. Note that it automatically uses r0 as the argument registers.

"mov %0, r0\n\t"// r0 is used as the result registers.

       :"+r"(x)            // output operands: %0 ('+' instead of '=' here means it can be also used as input.)

);

printf("Final result: x = %d\n", x);

return x;

}

```

 

 

## Task 1- Basic I/O

 

For this task, it is necessary to refer to sections 2.9.1 - 2.9.4 (pp.

7 - 9) and 3.4.1 (p. 14) in the

<a href="./docs/DE1-SoC_Computer_ARM.pdf">DE1-SOC Computer Manual</a>.

 

### Brief overview

 

The hardware setup of the DE1-SoC’s I/O components is fairly straightforward. The system has designated addresses in memory that are connected to hardware circuits on the FPGA through parallel ports, and these hardware circuits, in turn, interface with the physical I/O components. In most cases, the FPGA hardware simply maps the I/O terminals to the memory address designated to it. There are several parallel ports implemented in the FPGA that support input, output, and bidirectional transfers of data between the ARM A9 processor and I/O peripherals. For instance, the state of the slider switches is available to the FPGA on a bus of 10 wires which carry either a logical `’0’` or `’1’`. The state of the slider switches is then stored in the memory address reserved for the slider switches (`0xFF200040` in this case).

 

It is useful to have slightly more sophisticated FPGA hardware in some cases. For instance, in the case of the push-buttons, in addition to knowing the state of the button, it is also helpful to know whether a falling edge is detected, signaling a keypress. This can be achieved with a simple edge detection circuit in the FPGA.

 

### Getting Started: Drivers for slider switches and LEDs

 

Access to the memory addresses designated for I/O interfaces is best facilitated by what are called **device drivers**. Drivers are subroutines (drivers) that ease the process of reading from and writing to I/O interface addresses, thereby manipulating the state of and data associated with a given peripheral. When writing drivers, it is critical that you follow the subroutine calling conventions presented in this course.

 

1. **Slider Switches:** Create a new subroutine labeled **read_slider_switches_ASM**, which reads the value from the memory location designated for the slider switches data (SW_MEMORY) and stores it R0, and then returns. Remember to use the subroutine calling convention, and save processor state (by pushing and popping registers) if needed! If there are fewer than four 32-bit arguments or return values, use registers, rather than the stack, for communication between caller and callee.

 

2.  **LEDs:** Create a new subroutine labelled **write_LEDs_ASM**. The

   write_LEDs_ASM subroutine writes the value in `R0` to the LEDs

   memory location (LED_MEMORY), and then branches to the address

   contained in the `LR`.

 

To help you get started, the codes for the slider switches and LEDs drivers have been provided below.

These can also be found in the started code template provided in the `src/` folder.

Please make sure to use these files when starting the different tasks.

 

``` c

// Initializing the drivers registers

/* The EQU directive gives a symbolic name to a numeric constant,

a register-relative value or a PC-relative value. */

void init() {

__asm__(

".equ SW_MEMORY, 0xFF200040\n\t"

".equ LED_MEMORY, 0xFF200000\n\t"

 

// TODO

);

}

```

 

``` c

// Sider Switches Driver

// returns the state of slider switches in R0

int read_slider_switches_ASM() {

int readVal = 0;

__asm__  __volatile__(

"LDR R1, =SW_MEMORY\n\t"

   "LDR R0, [R1]\n\t"

"MOV %0, R0\n\t"

       :"=r"(readVal) // output operand %0

);

return readVal;

}

```

 

``` c

// LEDs Driver

// writes the state of LEDs (On/Off state) in R0 to the LEDs memory location

void write_LEDs_ASM(int val) {

__asm__  __volatile__(

"MOV R0, %0\n\t"

"LDR R1, =LED_MEMORY\n\t"

   "STR R0, [R1]\n\t"

       :    

       :"r"(val)  // input operand %0

);

}

```

 

To acquaint yourself with using memory-mapped I/O, write an application (inside a main function) that makes use of your read_slider_switches_ASM and the write_LEDs_ASM subroutines to turn on/off the LEDs. Write an infinite loop that calls read_slider_switches_ASM and write_LEDs_ASM in order. Compile and Run your project, and then change the state of the switches in the online simulator to turn on/off the corresponding LEDs. Note that

both the Switches and the LEDs panels are located on the top corner of your screen.

The figure below demonstrates the result of activating slider switches 0, 4, 5 and 9.       

 

 


51作业君

Email:51zuoyejun

@gmail.com

添加客服微信: abby12468