ARM bare metal article--serial UART experiment

Publisher:乘风翻浪Latest update time:2020-01-31 Source: eefocus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

You should all be familiar with the serial port. I won’t go into the specific communication principles as there are many discussions on Baidu. Then just look at the functions directly.

void Uart_SendByte(int data) //This function sends integer data, the parameter is data
{
    if(whichUart==0) //This is the selected serial port 0
    {
        if(data=='n')//Then determine if the data is not empty
        {
      /*Original macro definition of register,
      #define rUTRSTAT0 (*(volatile unsigned *)0x50000010) //UART 0 Tx/Rx status*/
            while(!(rUTRSTAT0 & 0x2));/*This is to query the status register of serial port 0. The first bit is whether the transmit buffer is empty.
            The second is Transmit buffer empty
            0 = The buffer register is not empty
            1 = Empty If the check value is 0, it means that the transmission has not been completed. When it is set to 1, it means that the transmission has been completed and the program continues to execute*/
            Delay(10); //because the slow response of hyper_terminal
            WrUTXH0('r');
        }
        while(!(rUTRSTAT0 & 0x2)); //Wait until THR is empty.
        Delay(10);
        WrUTXH0(data);
    }
    else if(whichUart==1)
    {
        if(data=='n')
        {
            while(!(rUTRSTAT1 & 0x2));
            Delay(10); //because the slow response of hyper_terminal
            rUTXH1 = 'r';
        }
        while(!(rUTRSTAT1 & 0x2)); //Wait until THR is empty.
        Delay(10);
        rUTXH1 = data;
    }  
    else if(whichUart==2)
    {
        if(data=='n')
        {
            while(!(rUTRSTAT2 & 0x2));
            Delay(10); //because the slow response of hyper_terminal
            rUTXH2 = 'r';
        }
        while(!(rUTRSTAT2 & 0x2)); //Wait until THR is empty.
        Delay(10);
        rUTXH2 = data;
    }      
}

 

After all this time, I still don't know how to determine whether ARM is big-endian or little-endian. This is set in the startup code. I haven't looked at it yet. The serial port code of mini2440 is the same as the serial port sending code of Huaheng 2410. Notes are as above.

The key code in the main function:

/***********************************************************************************************
* Function Name : Main()
* Create Date : 2011/12/10
* Author/Corporation : Taoxingtianxia
*
* Description : Find a proper thread in thread array
*
* Param : ThreadNo : someParam description
                                    ThreadStaus : someParam description
*
*
* Global Variable : DISP_wuiSegmentAppID
* File Static Variable : naucThreadNo
* Function Static Variable : None
*  
*----------------------------------------------------
* Revision History
* No. Date Revised by Item Description
* V0.0 2011/12/10 Taoxing Tianxia ... ....
*******************************************************************************************/
void Main(void)
{
    U8 count_num = 0;
    char *mode;
    int i;
    U8 key;
    U32 mpll_val = 0 ;
    //U32 divn_upll = 0;
     
    #if ADS10  
// __rt_lib_init(); //for ADS 1.0
    #endif
 
    Port_Init(); //Port initialization
     
    Isr_Init(); //Interrupt initialization
     
    i = 2 ; //don't use 100M!
        //boot_params.cpu_clk.val = 3;
    //Determine the frequency
    switch ( i )
    {
        case 0: //200
            key = 12;
            mpll_val = (92<<12)|(4<<4)|(1);
            break;
        case 1: //300
            key = 13;
            mpll_val = (67<<12)|(1<<4)|(1);
            break;
        case 2: //400
            key = 14;
            mpll_val = (92<<12)|(1<<4)|(1);
            break;
        case 3: //440!!!
            key = 14;
            mpll_val = (102<<12)|(1<<4)|(1);
            break;
        default:
            key = 14;
            mpll_val = (92<<12)|(1<<4)|(1);
            break;
    }
     
    //init FCLK=400M, so change MPLL first
    ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);
    ChangeClockDivider(key, 12);
    cal_cpu_bus_clk();
     
    consoleNum = 0; // Uart 1 select for debug. Select the serial port number
    Uart_Init( 0,115200 ); //Initialize serial port parameters and clock source
    Uart_Select(consoleNum); //Select the serial port number
     
    Beep(2000, 100); //Buzzer
     
    Uart_SendByte('n');//print information
    Uart_SendByte('H');
    while(1)
    {
        Uart_SendByte(count_num);
        Uart_SendByte(' ');
        count_num++;
        Delay(500);
    }

 

This allows ARM to send data from 0 to 255 to the PC, and the results displayed on the PC are as follows:

Serial Port Screenshot

This can't see the hexadecimal number, I made a serial port assistant to display it:

Serial assistant displays hexadecimal

The one above is implemented with mini2440, which can burn the program directly through UBOOT, but I don't know why it doesn't work on Huaheng's board. This has been bothering me for a long time. Today, I used the erase command to erase the linux system in PPCBOOT, and then entered the ppcboot command line form to enable jtag debugging. I don't know why, but this time I finally got the debugging result.

Here is a counting graph. Feel the sense of accomplishment, even though the underlying functions are not fully understood yet!

 Now to summarize these steps, at the beginning, do not start the system immediately when the power is turned on. First enter the PPCBOOT mode command line, and then start the AXD debugger.

Through the H-JATG software, we can see that it is in little-endian format, but the specific setting is not clear yet.

#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)

 WrUTXH0 means write UTXH0, UTXH0 is the send buffer register of the first serial port!

 December 13, 2011

Anan's program is really good. The program that comes with Huaheng board is useless.

December 21, 2011

I feel like time flies by so fast! But I haven't made any progress. Let's start with the program:

; //Call the main application
    b UART
UART
    ldr r0, =GPHCON ; //Set RxD0, TxD0 pins
    ldr r1, =0x2afaaa
    str r1, [r0]
     
    ldr r0, =GPHUP
    ldr r1, =0x7ff
    str r1, [r0] ; // The pull up function is disabled GPH[10:0]
 
 
    ldr r0, =UFCON0 ; //disable FIFO
    ldr r1, =0x0
    str r1, [r0]
    
    ldr r0, =UMCON0 ; //Disable AFC
    ldr r1, =0x0
    str r1, [r0]
     
    ldr r0, =ULCON0 ; //Set line register
    ldr r1, =0x3 ; //UART LINE CONFIG normal mode, no parity check, one stop bit, 8 data bits
    str r1, [r0]
     
    ldr r0, =UCON0 ; //Set Uart0 controller
    ldr r1, =0x245; //RX edge trigger, TX level trigger, disable delay interrupt, use RX error interrupt, normal operation mode, interrupt request or voting mode
    str r1, [r0]
     
    ldr r0, =UBRDIV0 ; //Set the baud rate to 115200
    ldr r1, =0x1a ;//int(50700000 / 16 / 115200) - 1 = 26
    str r1, [r0]
     
    mov r1, #100
Delay
    sub r1, r1, #0x1
    bne Delay
     
    ;//Open interrupt
    ldr r0, =INTMSK
    ldr r1, [r0]
    and r1, r1, #0xefffffff
    str r1, [r0]
     
    MOV R5 , #127 ; //Set the number of characters to be printed
    MOV R1 , #0x0 ; //Set the character to be printed
LOOP 
   LDR R3 , =UTRSTAT0
   LDR R2 , [R3]
   TST R2 ,#0x04 ;//Judge whether the send buffer is empty
   BEQ LOOP ;//If it is empty, execute the following statement, if it is not empty, jump to LOOP
   LDR R0 , =UTXH0
    
   STR R1, [R0]; //Place the data to be sent into the data buffer
   ADD R1, R1, #1
   SUB R5 ,R5, #0x01 ; //Counter decrement
   CMP R5 ,#0x0
   BNE LOOP
   
LOOP2 B LOOP2

The part following the startup code is a serial port sending program compiled in assembly language, which sets the relevant registers and then sends data to the PC.

 


Reference address:ARM bare metal article--serial UART experiment

Previous article:Clock mechanism of ARM Linux system
Next article:apache+sqlite+php for Arm Linux

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号