UART program:
1. The writing function of head.S file is to start the code
@******************************************************************************
@ File:head.S
@ Function: Initialization, system mode stack
@******************************************************************************
.extern main
.text
.global _start
_start:
b Reset
Reset:
ldr sp, =4096 @ Set the stack pointer. The following are all C functions. You need to set the stack before calling them.
bl disable_watch_dog @ Disable WATCHDOG, otherwise the CPU will restart continuously
bl clock_init @ Set up MPLL, change FCLK, HCLK, PCLK
bl memsetup @ Set up the memory controller to use SDRAM
bl inituart@ written inituart() serial port initialization function in init.c
bl copy_steppingstone_to_sdram @ Copy code to SDRAM
ldr pc, =on_sdram @ Jump to SDRAM and continue execution
on_sdram:
msr cpsr_c, #0xdf @ Enter system mode
ldr sp, =0x34000000 @ Set the system mode stack pointer,
ldr lr, =halt_loop @ Set the return address
ldr pc, =Main @ Call the main function
halt_loop:
b halt_loop
2. init.c file, which declares some functions and implementations that need to be used
#include "2440addr.h"
void disable_watch_dog(void);
void clock_init(void);
void memsetup(void);
void copy_steppingstone_to_sdram(void);
void inituart(void);
void disable_watch_dog(void)
{
rWTCON = 0; // Turning off WATCHDOG is very simple, just write 0 to this register
}
#define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00))
#define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))
void clock_init(void)
{
// LOCKTIME = 0x00ffffff; // Use the default value
rCLKDIVN = 0x03; // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
__asm__(
"mrc p15, 0, r1, c1, c0, 0\n"
"orr r1, r1, #0xc0000000\n"
"mcr p15, 0, r1, c1, c0, 0\n"
);
if ((rGSTATUS1 == 0x32410000) || (rGSTATUS1 == 0x32410002))
{
rMPLLCON = S3C2410_MPLL_200MHZ;
}
else
{
rMPLLCON = S3C2440_MPLL_200MHZ;
}
}
void memsetup(void)
{
volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;
p[0] = 0x22011110; //BWSCON
p[1] = 0x00000700; //BANKCON0
p[2] = 0x00000700; //BANKCON1
p[3] = 0x00000700; //BANKCON2
p[4] = 0x00000700; //BANKCON3
p[5] = 0x00000700; //BANKCON4
p[6] = 0x00000700; //BANKCON5
p[7] = 0x00018005; //BANKCON6
p[8] = 0x00018005; //BANKCON7
p[9] = 0x008C04F4;
p[10] = 0x000000B1; //BANKSIZE
p[11] = 0x00000030; //MRSRB6
p[12] = 0x00000030; //MRSRB7
}
void copy_steppingstone_to_sdram(void)
{
unsigned int *pdwSrc = (unsigned int *)0;
unsigned int *pdwDest = (unsigned int *)0x30000000;
while (pdwSrc < (unsigned int *)4096)
{
*pdwDest = *pdwSrc;
pdwDest++;
pdwSrc++;
}
}
void inituart(void)
{
rGPBCON = 0x015551;
rGPBUP = 0x7ff;
rGPBDAT = 0x1e0;
rGPHCON = 0x00faaa; //Use UART0 function
rGPHUP = 0x7ff;
rULCON0 = 0x3; //Set UART0 to no parity, one stop bit, 8 data bits
rUCON0 = 0x245; //PCLK is the clock source, receiving and sending data is in query or interrupt mode
rUFCON0 = 0; //
rUMCON0 = 0; //
rUBRDIV0 = 26;
}
3. uart.c This program uses the query method to implement serial communication
#include"2440addr.h"
void Main(void)
{
char ch;
//Set the baud rate, PCLK is 50MHz, and the baud rate is 115.2kHz
while(!(rUTRSTAT0 & 0x2)); //Wait and determine whether the send buffer is empty
rUTXH0 = 0xaa; //If it is empty, send 0xAA byte
while(1)
{
while(!(rUTRSTAT0 & 0x1)); //Wait and determine whether the receive buffer is ready
ch = rURXH0; //Receive one byte of data
while(!(rUTRSTAT0 & 0x2)); //Wait and determine whether the send buffer is empty
rUTXH0 = ch; //Send one byte of data
switch(ch) //Execute different programs according to the received data
{
case 0x11: // Turn off LED
rGPBDAT |= 0x1e0;
break;
case 0x22: //light up the LED
rGPBDAT &= 0x1f;
break;
case 0x33: //Buzzer does not sound
rGPBDAT &= 0x1e0;
break;
case 0x44: //Buzzer sounds
rGPBDAT |= 0x1;
break;
default: //LED off, buzzer off
rGPBDAT = 0x1e0;
break;
}
}
}
4. The specific function of the uart.lds file is not very clear. I personally feel that it should be used for segment declarations and entry addresses.
SECTIONS {
. = 0x30000000;
.text : { *(.text) }
.rodata ALIGN(4) : {*(.rodata)}
.data ALIGN(4) : { *(.data) }
.bss ALIGN(4) : { *(.bss) *(COMMON) }
}
5. Makefile
objs := head.o uart.o init.o
uart.bin: $(objs)
arm-linux-ld -Tuart.lds -o uart_elf $^
arm-linux-objcopy -O binary -S uart_elf $@
arm-linux-objdump -D -m arm uart_elf > uart.dis
%.o:%.c
arm-linux-gcc -Wall -O2 -c -o $@ $<
%.o:%.S
arm-linux-gcc -Wall -O2 -c -o $@ $<
clean:
rm -f uart.bin uart_elf uart.dis *.o
With the above five files, you can directly use the command to generate the uart.bin file under Linux, burn it into NAND FLASH, and then start it from NAND FLASH to run. Use the serial port debugging tool to perform data communication.
Previous article:ARM Notes: Application of timer interrupts
Next article:ARM Notes: UART Learning Notes
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Please share the basic routines of STM32F0 series microcontroller
- PD fast charging technology has been significantly updated, USB PD3.1 has been released, supporting 48V and 240W output
- Recording a newbie's understanding of RISC-V
- [GD32L233C-START Review] Driver for serial dot matrix display module
- Huawei Hongmeng was released yesterday, are you ready to upgrade???
- Cadence User Manual Classic
- The name of the SOLDER layer means soldering. Who translated it into solder mask?
- PYPL Programming Language Rankings for November 2022
- How can esp32 get the file information in the file system of the micropython task in another task?
- zstack protocol stack serial port problem