Uboot Serial Port Initialization

Source: Internet
Author: User
Tags stdin volatile

The serial port initialization under Uboot is completed in several steps, and there are three serial port-related initialization functions in the Uboot initialization sequence init_sequence[]. Init_baudrate is used to set the baud rate of the serial port, it will first go to the UBOOT environment variable inside to find the baud rate definition, if found on the assignment to the global variable baudrate, if not defined in the environment variable, then use a default configuration value. Serial_init is related to a specific platform, and in the case of the Marvell platform, the function is defined in MV_SERIAL.C. The function first calculates the value of the clock_divisor based on the baud rate, and then calls Mvuartinit () to initialize the serial hardware. In Mvuartinit, the initial parameters are directly written to the register of the serial port, which completes the initialization of the hardware. Console_init_f is the first stage of console initialization, which is to set the Have_console variable in the global variable.

init_fnc_t *init_sequence[] = {
<span style= "White-space:pre" >	</span>
	Init_baudrate,/		* Initialze baudrate Settings */
	serial_init,/		* serial Communications Setup *
	/ Console_init_f,/		* Stage 1 init of console */
<span style= "White-space:pre" >	</span> ...
};
static int init_baudrate (void) {declare_global_data_ptr;	Uchar tmp[64];
	/* Long enough for environment variables */INT i = Getenv_r ("baudrate", TMP, sizeof (TMP)); Gd->bd->bi_baudrate = Gd->baudrate = (i > 0)?

	(int) Simple_strtoul (tmp, NULL, ten): Config_baudrate;
return (0); }
Mv_void Mvuartinit (mv_u32 port, mv_u32 bauddivisor, mv_uart_port* Base)
{
	volatile mv_uart_port *puartport;

#if defined (MV_UART_OVER_PEX_WA) | | Defined (MV_UART_OVER_PCI_WA)
	Uartbase[port] = Puartport = (volatile Mv_uart_port *) (base);
	return;
#else
	Uartbase[port] = Puartport = (volatile mv_uart_port *) base;

	Puartport->ier = 0x00;
	PUARTPORT->LCR = lcr_divl_en;           /* Access baud rate */
	Puartport->dll = bauddivisor & 0xFF;    /* 9600 baud *
	/PUARTPORT->DLM = (bauddivisor >> 8) & 0xFF;
	PUARTPORT->LCR = lcr_8n1;               /* 8 data, 1 stop, no parity */

	* Clear & Enable FIFOs */
	PUARTPORT->FCR = Fcr_fifo_en | FCR_RXSR | FCR_TXSR;
	return;
#endif
}

int console_init_f (void)
{
	declare_global_data_ptr;

	Gd->have_console = 1;

#ifdef config_silent_console
	if (getenv ("SILENT")! = NULL)
		gd->flags |= gd_flg_silent;
#endif

	return (0);
}

The fourth initialization phase in Devices_init (), Devices_init () is equivalent to the UBOOT device management mechanism, the various types of equipment in a specific format added to a device chain list devlist. The initialization of the serial device is done in Drv_system_init (), which first sets the device name to serial and sets the device's FLAGS to Dev_flags_output | Dev_flags_input | Dev_flags_system, and then for the corresponding operation function in the devict_t operation, the main implementation of input and output functions, the specific implementation function is also related to the platform. For example, DEV.PUTC is defined as SERIAL_PUTC (), and in Marvell's platform the function is defined in MV_SERIAL.C, which calls MVUARTPUTC () directly for output operation, in MVUARTPUTC () The value to be output is assigned directly to the output register. After initializing the device descriptor, call Device_register () to add the device to the global device list.

static void Drv_system_init (void)
{
	device_t dev;

	memset (&dev, 0, sizeof (dev));

	strcpy (Dev.name, "serial");
	Dev.flags = Dev_flags_output | Dev_flags_input | Dev_flags_system;
#ifdef config_serial_software_fifo
	dev.putc = SERIAL_BUFFERED_PUTC;
	Dev.puts = serial_buffered_puts;
	Dev.getc = serial_buffered_getc;
	DEV.TSTC = SERIAL_BUFFERED_TSTC;
#else
	DEV.PUTC = SERIAL_PUTC;
	Dev.puts = serial_puts;
	Dev.getc = serial_getc;
	DEV.TSTC = SERIAL_TSTC;
#endif

	Device_register (&dev);

#ifdef Cfg_device_nulldev
	memset (&dev, 0, sizeof (dev));

	strcpy (Dev.name, "Nulldev");
	Dev.flags = Dev_flags_output | Dev_flags_input | Dev_flags_system;
	DEV.PUTC = NULLDEV_PUTC;
	Dev.puts = nulldev_puts;
	Dev.getc = Nulldev_input;
	DEV.TSTC = Nulldev_input;

	Device_register (&dev);
#endif
}

SERIAL_PUTC (const char c)
{
#if defined (CONFIG_MV_SMP) | | (Defined (mv78xx0) && defined (MV78200))
        if (c = = ' \ n ')
                MVUARTPUTC ((WhoAmI ())%2, ' \ R ');

        MVUARTPUTC ((WhoAmI ())%2, c);
#else
	if (c = = ' \ n ')
		MVUARTPUTC (Cfg_duart_chan, ' \ R ');

	MVUARTPUTC (Cfg_duart_chan, c);
#endif
}

Mv_void	MVUARTPUTC (mv_u32 port, mv_u8 c)
{
	volatile mv_uart_port *puartport = Uartbase[port];
	while ((PUARTPORT->LSR & lsr_thre) = = 0);
	Puartport->thr = C;
	return;
}

In the last initialization phase in Console_init_r (), in this function, first define two variables Inputdev and Outputdev, and initialize to NULL, and then go through the global device list if there is a device with the FLAGS of Dev_flags_ INPUT, the device is assigned to Inputdev, similarly, if there is a device with the FLAGS of Dev_flags_output, it is assigned to Outputdev. If such inputdev and Outputdev are found, call Console_setfile () to set the file descriptor for standard input, standard input, and error output. In Console_setfile (), the assignment operation is primarily for the stdio_devices[] array, which has three elements, corresponding inputs, outputs, and error file descriptors, so it binds the specific device to the three file descriptions.

int Console_init_r (void) {declare_global_data_ptr;
	device_t *inputdev = null, *outputdev = NULL;

int i, items = Listnumitems (devlist);                                            #ifdef Config_splash_screen/* Suppress all output if SPLASH-enabled and we have a BMP to display */if (getenv ("splashimage") = NULL) Outputdev = Search_device (Dev_flags_output, "n
Ulldev "); #endif #ifdef config_silent_console/* Suppress all output if "SILENT" mode requested */if (Gd->flags & GD_FLG
_silent) Outputdev = Search_device (Dev_flags_output, "Nulldev");
	     #endif/* Scan devices looking for input and output devices */for (i = 1; (I <= items) && ((Inputdev = = NULL) | |
	     (Outputdev = = NULL));

		i++) {device_t *dev = Listgetptrtoitem (devlist, i);
		if ((Dev->flags & Dev_flags_input) && (Inputdev = = NULL)) {inputdev = dev; } if ((Dev->flags & Dev_flags_output) && (Outputdev = = NULL)) {OUTPUTdev = dev;
		}}/* Initializes output console first */if (Outputdev! = NULL) {console_setfile (stdout, Outputdev);
	Console_setfile (stderr, Outputdev);
	}/* Initializes input console */if (Inputdev! = NULL) {console_setfile (stdin, Inputdev);	} gd->flags |= Gd_flg_devinit;
	/* Device Initialization completed */#ifndef cfg_console_info_quiet/* Print information */puts ("in:");
	if (Stdio_devices[stdin] = = NULL) {puts ("No Input Devices available!\n");
	} else {printf ("%s\n", stdio_devices[stdin]->name);
	} puts ("Out:");
	if (stdio_devices[stdout] = = NULL) {puts ("No output Devices available!\n");
	} else {printf ("%s\n", stdio_devices[stdout]->name);
	} puts ("ERR:");
	if (stdio_devices[stderr] = = NULL) {puts ("No Error Devices available!\n");
	} else {printf ("%s\n", stdio_devices[stderr]->name); } #endif/* Cfg_console_info_quiet *///Setting environment variables */for (i = 0; i < 3; i++) {setenv (StDio_names[i], stdio_devices[i]->name); } #if 0/* If nothing usable installed, use only the initial console */if ((stdio_devices[stdin] = = NULL) && (
Stdio_devices[stdout] = = NULL)) return (0);
#endif return (0); }

static int console_setfile (int file, device_t * dev)
{
	declare_global_data_ptr;
	int error = 0;

	if (dev = = NULL)
		return-1;

	Switch (file) {case
	stdin: Case
	stdout: Case
	stderr:/
		* Start New device *
		/if (Dev->start) {
  error = Dev->start ();
			/* If it ' s not started dont use it *
			/if (Error < 0) break
				;
		}

		/* Assign The new device (leaving the existing one started) */
		stdio_devices[file] = dev;
		 /* Update monitor functions
		 * (to use the console stuff by other applications) */
		switch (file) {
  case stdin:
			gd->jt[xf_getc] = dev->getc;
			GD->JT[XF_TSTC] = dev->tstc;
			break;
		Case stdout:
			GD->JT[XF_PUTC] = dev->putc;
			Gd->jt[xf_puts] = dev->puts;
			GD->JT[XF_PRINTF] = printf;
			break;
		}
		break;

	Default:/		* Invalid file ID *
		/error =-1;
	}
	return error;
}

The first three stages are mainly the initialization of the hardware, the following two stages are mainly to realize the initialization of the serial port operation function, because after setting the standard input and output, we can see the loading and debugging information of Uboot from the serial port. Take a look at the printf () function under Uboot, which first calls vsprintf () to format the output and then calls the puts () output. In puts (), different processing is performed according to the gd_flg_devinit tag, which is set in Console_init_r (), so the fputs () function is called, and fputs () is called directly stdio_devices[] The standard output device in the array to output the content, which is bound in Console_init_r ().

void printf (const char *fmt, ...)
{
	va_list args;
	UINT I;
	Char printbuffer[cfg_pbsize];

	Va_start (args, fmt);

	/* For the work, Printbuffer must is larger than
	 * anything we ever want to print.
	 *
	/i = vsprintf (Printbuffer, FMT, args);
	Va_end (args); 

	/* Print The String *
	/puts (printbuffer);
}
void puts (const char *s)
{
	declare_global_data_ptr;

#ifdef config_silent_console
	if (gd->flags & gd_flg_silent)
		return;
#endif

	if (Gd->flags & Gd_flg_devinit) {/
		* Send to the standard output *
		/fputs (stdout, s);
	} els e {
		/* Send directly to the handler *
		/serial_puts (s);
	}
}

void fputs (int file, const char *s)
{
	if (file < max_files)
		stdio_devices[file]->puts (s);
}





Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.