forked from Imagelibrary/rtems
bsps: Move console drivers to bsps
This patch is a part of the BSP source reorganization. Update #3285.
This commit is contained in:
68
bsps/arm/raspberrypi/console/console-config.c
Normal file
68
bsps/arm/raspberrypi/console/console-config.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup raspberrypi_usart
|
||||
*
|
||||
* @brief Console Configuration.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Yang Qiao
|
||||
* based on work by:
|
||||
* Copyright (c) 2013 Alan Cudmore
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
*
|
||||
* http://www.rtems.org/license/LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include <rtems/bspIo.h>
|
||||
|
||||
#include <libchip/serial.h>
|
||||
|
||||
#include <bspopts.h>
|
||||
#include <bsp/irq.h>
|
||||
#include <bsp/usart.h>
|
||||
#include <bsp/raspberrypi.h>
|
||||
#include <bsp/fbcons.h>
|
||||
|
||||
console_tbl Console_Configuration_Ports [] = {
|
||||
{
|
||||
.sDeviceName = "/dev/ttyS0",
|
||||
.deviceType = SERIAL_CUSTOM,
|
||||
.pDeviceFns = &bcm2835_usart_fns,
|
||||
.deviceProbe = NULL,
|
||||
.pDeviceFlow = NULL,
|
||||
.ulCtrlPort1 = BCM2835_UART0_BASE,
|
||||
.ulCtrlPort2 = 0,
|
||||
.ulClock = USART0_DEFAULT_BAUD,
|
||||
.ulIntVector = BCM2835_IRQ_ID_UART
|
||||
},
|
||||
{
|
||||
.sDeviceName ="/dev/fbcons",
|
||||
.deviceType = SERIAL_CUSTOM,
|
||||
.pDeviceFns = &fbcons_fns,
|
||||
.deviceProbe = fbcons_probe,
|
||||
.pDeviceFlow = NULL,
|
||||
},
|
||||
};
|
||||
|
||||
#define PORT_COUNT \
|
||||
(sizeof(Console_Configuration_Ports) \
|
||||
/ sizeof(Console_Configuration_Ports [0]))
|
||||
|
||||
unsigned long Console_Configuration_Count = PORT_COUNT;
|
||||
|
||||
static void output_char(char c)
|
||||
{
|
||||
const console_fns *con =
|
||||
Console_Configuration_Ports [Console_Port_Minor].pDeviceFns;
|
||||
|
||||
con->deviceWritePolled((int) Console_Port_Minor, c);
|
||||
}
|
||||
|
||||
BSP_output_char_function_type BSP_output_char = output_char;
|
||||
|
||||
BSP_polling_getchar_function_type BSP_poll_char = NULL;
|
||||
114
bsps/arm/raspberrypi/console/console_select.c
Normal file
114
bsps/arm/raspberrypi/console/console_select.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup raspberrypi_console
|
||||
*
|
||||
* @brief console select
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Yang Qiao
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
*
|
||||
* http://www.rtems.org/license/LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include <bsp.h>
|
||||
#include <bsp/fatal.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <rtems/termiostypes.h>
|
||||
#include <libchip/serial.h>
|
||||
#include "../../shared/dev/serial/legacy-console.h"
|
||||
#include <bsp/rpi-fb.h>
|
||||
|
||||
rtems_device_minor_number BSPPrintkPort = 0;
|
||||
|
||||
/*
|
||||
* Method to return true if the device associated with the
|
||||
* minor number probs available.
|
||||
*/
|
||||
static bool bsp_Is_Available( rtems_device_minor_number minor )
|
||||
{
|
||||
console_tbl *cptr = Console_Port_Tbl[ minor ];
|
||||
|
||||
/*
|
||||
* First perform the configuration dependent probe, then the
|
||||
* device dependent probe
|
||||
*/
|
||||
if ( ( !cptr->deviceProbe || cptr->deviceProbe( minor ) ) &&
|
||||
cptr->pDeviceFns->deviceProbe( minor ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Method to return the first available device.
|
||||
*/
|
||||
static rtems_device_minor_number bsp_First_Available_Device( void )
|
||||
{
|
||||
rtems_device_minor_number minor;
|
||||
|
||||
for ( minor = 0; minor < Console_Port_Count; minor++ ) {
|
||||
console_tbl *cptr = Console_Port_Tbl[ minor ];
|
||||
|
||||
/*
|
||||
* First perform the configuration dependent probe, then the
|
||||
* device dependent probe
|
||||
*/
|
||||
|
||||
if ( ( !cptr->deviceProbe || cptr->deviceProbe( minor ) ) &&
|
||||
cptr->pDeviceFns->deviceProbe( minor ) ) {
|
||||
return minor;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Error No devices were found. We will want to bail here.
|
||||
*/
|
||||
bsp_fatal( BSP_FATAL_CONSOLE_NO_DEV );
|
||||
}
|
||||
|
||||
void bsp_console_select( void )
|
||||
{
|
||||
/*
|
||||
* Reset Console_Port_Minor and
|
||||
* BSPPrintkPort here if desired.
|
||||
*
|
||||
* This default version allows the bsp to set these
|
||||
* values at creation and will not touch them again
|
||||
* unless the selected port number is not available.
|
||||
*/
|
||||
const char *opt;
|
||||
|
||||
Console_Port_Minor = BSP_CONSOLE_UART0;
|
||||
BSPPrintkPort = BSP_CONSOLE_UART0;
|
||||
|
||||
opt = rpi_cmdline_get_arg( "--console=" );
|
||||
|
||||
if ( opt ) {
|
||||
if ( strncmp( opt, "fbcons", sizeof( "fbcons" ) - 1 ) == 0 ) {
|
||||
if ( rpi_video_is_initialized() > 0 ) {
|
||||
Console_Port_Minor = BSP_CONSOLE_FB;
|
||||
BSPPrintkPort = BSP_CONSOLE_FB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the device that was selected isn't available then
|
||||
* let the user know and select the first available device.
|
||||
*/
|
||||
if ( !bsp_Is_Available( Console_Port_Minor ) ) {
|
||||
Console_Port_Minor = bsp_First_Available_Device();
|
||||
}
|
||||
}
|
||||
437
bsps/arm/raspberrypi/console/fb.c
Normal file
437
bsps/arm/raspberrypi/console/fb.c
Normal file
@@ -0,0 +1,437 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup raspberrypi
|
||||
*
|
||||
* @brief framebuffer support.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Yang Qiao
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
*
|
||||
* http://www.rtems.org/license/LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <bsp.h>
|
||||
#include <bsp/raspberrypi.h>
|
||||
#include <bsp/mailbox.h>
|
||||
#include <bsp/vc.h>
|
||||
#include <bsp/rpi-fb.h>
|
||||
|
||||
#include <libcpu/arm-cp15.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <rtems/fb.h>
|
||||
#include <rtems/framebuffer.h>
|
||||
#include <rtems/score/atomic.h>
|
||||
#include <rtems/bspIo.h>
|
||||
|
||||
#define SCREEN_WIDTH 1024
|
||||
#define SCREEN_HEIGHT 768
|
||||
#define BPP 32
|
||||
|
||||
/* flag to limit driver to protect against multiple opens */
|
||||
static Atomic_Flag driver_mutex;
|
||||
|
||||
/*
|
||||
* screen information for the driver (fb0).
|
||||
*/
|
||||
|
||||
static struct fb_var_screeninfo fb_var_info = {
|
||||
.xres = SCREEN_WIDTH,
|
||||
.yres = SCREEN_HEIGHT,
|
||||
.bits_per_pixel = BPP
|
||||
};
|
||||
|
||||
static struct fb_fix_screeninfo fb_fix_info = {
|
||||
.smem_start = (void *) NULL,
|
||||
.smem_len = 0,
|
||||
.type = FB_TYPE_PACKED_PIXELS,
|
||||
.visual = FB_VISUAL_TRUECOLOR,
|
||||
.line_length = 0
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NO_SUITABLE_MODE = -1,
|
||||
BAD_FORMAT = -2,
|
||||
AUTO_SELECT = -3,
|
||||
DONT_INIT = -4,
|
||||
NO_MODE_REQ = -5,
|
||||
} mode_err_ret_val;
|
||||
|
||||
int rpi_get_fix_screen_info( struct fb_fix_screeninfo *info )
|
||||
{
|
||||
*info = fb_fix_info;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rpi_get_var_screen_info( struct fb_var_screeninfo *info )
|
||||
{
|
||||
*info = fb_var_info;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find mode given in string format.
|
||||
*
|
||||
* expected format
|
||||
* <resX>x<resY>[-<bpp>]
|
||||
* numbers <resX>, <resY> and <bpp> are decadic
|
||||
*
|
||||
* @param[out] fb_var_ptr pointer to variable mode part filled by function
|
||||
* @param[in] video_string string to be parsed
|
||||
* @retval video mode number to be set
|
||||
* @retval -1 no suitable mode found
|
||||
* @retval -2 bad format of the video_string
|
||||
* @retval -3 automatic mode selection requested
|
||||
* @retval -4 request to not initialize graphics
|
||||
* @retval -5 no mode requested/empty video string
|
||||
*/
|
||||
|
||||
static int parse_mode_from_string(
|
||||
struct fb_var_screeninfo *fb_var_ptr,
|
||||
const char *video_string
|
||||
)
|
||||
{
|
||||
const char *opt;
|
||||
char *endptr;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t bpp = 0;
|
||||
|
||||
opt = video_string;
|
||||
|
||||
if ( opt == NULL )
|
||||
return NO_MODE_REQ;
|
||||
|
||||
if ( strncmp( opt, "auto", 4 ) == 0 )
|
||||
return AUTO_SELECT;
|
||||
|
||||
if ( strncmp( opt, "none", 4 ) == 0 ||
|
||||
strncmp( opt, "off", 3 ) == 0 )
|
||||
return DONT_INIT;
|
||||
|
||||
width = strtol( opt, &endptr, 10 );
|
||||
|
||||
if ( *endptr != 'x' ) {
|
||||
return BAD_FORMAT;
|
||||
}
|
||||
|
||||
opt = endptr + 1;
|
||||
height = strtol( opt, &endptr, 10 );
|
||||
|
||||
switch ( *endptr ) {
|
||||
case '-':
|
||||
opt = endptr + 1;
|
||||
endptr = NULL;
|
||||
bpp = strtol( opt, &endptr, 10 );
|
||||
|
||||
if ( ( endptr == opt ) || ( endptr == NULL ) )
|
||||
return BAD_FORMAT;
|
||||
|
||||
if ( *endptr && ( *endptr != ' ' ) )
|
||||
return BAD_FORMAT;
|
||||
|
||||
break;
|
||||
case ' ':
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
return BAD_FORMAT;
|
||||
}
|
||||
|
||||
fb_var_ptr->xres = width;
|
||||
fb_var_ptr->yres = height;
|
||||
|
||||
if ( bpp != 0 )
|
||||
fb_var_ptr->bits_per_pixel = bpp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int find_mode_from_vc( void )
|
||||
{
|
||||
int res;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
bcm2835_get_display_size_entries entries;
|
||||
|
||||
res = bcm2835_mailbox_get_display_size( &entries );
|
||||
|
||||
width = entries.width;
|
||||
height = entries.height;
|
||||
|
||||
if ( width == 0 || height == 0 ) {
|
||||
fb_var_info.xres = SCREEN_WIDTH;
|
||||
fb_var_info.yres = SCREEN_HEIGHT;
|
||||
} else {
|
||||
fb_var_info.xres = width;
|
||||
fb_var_info.yres = height;
|
||||
}
|
||||
printk("find_mode_from_vc %u x %u, res %d\n", width, height, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool rpi_fb_hdmi_is_present( void )
|
||||
{
|
||||
bcm2835_get_display_size_entries entries;
|
||||
|
||||
memset( &entries, 0, sizeof( entries ) );
|
||||
bcm2835_mailbox_get_display_size( &entries );
|
||||
|
||||
/* Impossible display dimension */
|
||||
if ( ( entries.width < 10 ) || ( entries.height < 10 ) )
|
||||
return false;
|
||||
|
||||
/* Know default values reported when monitor is not present */
|
||||
if ( ( entries.width == 0x290 ) && ( entries.height == 0x1A0 ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int rpi_fb_init( void )
|
||||
{
|
||||
int res;
|
||||
int mode_from_cmdline;
|
||||
bcm2835_init_frame_buffer_entries init_frame_buffer_entries;
|
||||
|
||||
if ( fb_fix_info.smem_start != NULL ) {
|
||||
return RPI_FB_INIT_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
if ( rpi_fb_hdmi_is_present() == false ) {
|
||||
return RPI_FB_INIT_NO_DISPLAY;
|
||||
}
|
||||
|
||||
mode_from_cmdline = parse_mode_from_string( &fb_var_info,
|
||||
rpi_cmdline_get_arg( "--video=" ) );
|
||||
|
||||
switch ( mode_from_cmdline ) {
|
||||
case BAD_FORMAT:
|
||||
return RPI_FB_INIT_CMDLINE_BAD_FORMAT;
|
||||
case AUTO_SELECT:
|
||||
break;
|
||||
case DONT_INIT:
|
||||
return RPI_FB_INIT_CMDLINE_DONT_INIT;
|
||||
case NO_MODE_REQ:
|
||||
return RPI_FB_INIT_CMDLINE_NO_MODE_REQ;
|
||||
}
|
||||
|
||||
if ( mode_from_cmdline ) {
|
||||
if ( find_mode_from_vc() )
|
||||
return RPI_FB_INIT_MODE_PROBE_ERROR;
|
||||
}
|
||||
|
||||
memset( &init_frame_buffer_entries, 0, sizeof( init_frame_buffer_entries ) );
|
||||
init_frame_buffer_entries.xres = fb_var_info.xres;
|
||||
init_frame_buffer_entries.yres = fb_var_info.yres;
|
||||
init_frame_buffer_entries.xvirt = fb_var_info.xres;
|
||||
init_frame_buffer_entries.yvirt = fb_var_info.yres;
|
||||
init_frame_buffer_entries.depth = fb_var_info.bits_per_pixel;
|
||||
init_frame_buffer_entries.pixel_order = bcm2835_mailbox_pixel_order_rgb;
|
||||
init_frame_buffer_entries.alpha_mode = bcm2835_mailbox_alpha_mode_0_opaque;
|
||||
init_frame_buffer_entries.voffset_x = 0;
|
||||
init_frame_buffer_entries.voffset_y = 0;
|
||||
init_frame_buffer_entries.overscan_left = 0;
|
||||
init_frame_buffer_entries.overscan_right = 0;
|
||||
init_frame_buffer_entries.overscan_top = 0;
|
||||
init_frame_buffer_entries.overscan_bottom = 0;
|
||||
printk("bcm2835_mailbox_init_frame_buffer ...\n");
|
||||
res = bcm2835_mailbox_init_frame_buffer( &init_frame_buffer_entries );
|
||||
printk("bcm2835_mailbox_init_frame_buffer returned %d\n", res);
|
||||
if (res != 0) {
|
||||
printk("bcm2835_mailbox_init_frame_buffer retry ...\n");
|
||||
res = bcm2835_mailbox_init_frame_buffer( &init_frame_buffer_entries );
|
||||
printk("bcm2835_mailbox_init_frame_buffer returned %d\n", res);
|
||||
if (res != 0)
|
||||
return RPI_FB_INIT_SETUP_FAILED;
|
||||
}
|
||||
|
||||
bcm2835_get_pitch_entries get_pitch_entries;
|
||||
bcm2835_mailbox_get_pitch( &get_pitch_entries );
|
||||
|
||||
fb_var_info.xres = init_frame_buffer_entries.xres;
|
||||
fb_var_info.yres = init_frame_buffer_entries.yres;
|
||||
fb_var_info.bits_per_pixel = init_frame_buffer_entries.depth;
|
||||
fb_fix_info.smem_start = (void *) init_frame_buffer_entries.base;
|
||||
fb_fix_info.smem_len = init_frame_buffer_entries.size;
|
||||
fb_fix_info.line_length = get_pitch_entries.pitch;
|
||||
|
||||
if ( fb_fix_info.smem_start == NULL )
|
||||
return RPI_FB_INIT_START_ADDR_UNKNOWN;
|
||||
|
||||
printk("fb_fix_info.smem_start %p\n", fb_fix_info.smem_start);
|
||||
|
||||
arm_cp15_set_translation_table_entries( (void *) fb_fix_info.smem_start,
|
||||
(void *) fb_fix_info.smem_start +
|
||||
fb_fix_info.smem_len,
|
||||
ARMV7_MMU_DATA_READ_WRITE_CACHED );
|
||||
|
||||
return RPI_FB_INIT_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* fbds device driver initialize entry point.
|
||||
*/
|
||||
|
||||
rtems_device_driver frame_buffer_initialize(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
rtems_status_code status;
|
||||
|
||||
/* register the devices */
|
||||
status = rtems_io_register_name( FRAMEBUFFER_DEVICE_0_NAME, major, 0 );
|
||||
|
||||
if ( status != RTEMS_SUCCESSFUL ) {
|
||||
printk( "[!] error registering framebuffer\n" );
|
||||
rtems_fatal_error_occurred( status );
|
||||
}
|
||||
|
||||
_Atomic_Flag_clear( &driver_mutex, ATOMIC_ORDER_RELEASE );
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
* fbds device driver open operation.
|
||||
*/
|
||||
|
||||
rtems_device_driver frame_buffer_open(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
if ( _Atomic_Flag_test_and_set( &driver_mutex,
|
||||
ATOMIC_ORDER_ACQUIRE ) != 0 ) {
|
||||
printk( "RaspberryPi framebuffer could not lock driver_mutex\n" );
|
||||
return RTEMS_UNSATISFIED;
|
||||
}
|
||||
|
||||
if ( fb_fix_info.smem_start == NULL ) {
|
||||
int res;
|
||||
res = rpi_fb_init();
|
||||
if ( (res < RPI_FB_INIT_OK) || (fb_fix_info.smem_start == NULL) ) {
|
||||
_Atomic_Flag_clear( &driver_mutex, ATOMIC_ORDER_RELEASE );
|
||||
printk( "RaspberryPi framebuffer initialization failed\n" );
|
||||
return RTEMS_UNSATISFIED;
|
||||
}
|
||||
}
|
||||
|
||||
memset( (void *) fb_fix_info.smem_start, 0, fb_fix_info.smem_len );
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
* fbds device driver close operation.
|
||||
*/
|
||||
|
||||
rtems_device_driver frame_buffer_close(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
/* restore previous state. for VGA this means return to text mode.
|
||||
* leave out if graphics hardware has been initialized in
|
||||
* frame_buffer_initialize() */
|
||||
memset( (void *) fb_fix_info.smem_start, 0, fb_fix_info.smem_len );
|
||||
_Atomic_Flag_clear( &driver_mutex, ATOMIC_ORDER_RELEASE );
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
* fbds device driver read operation.
|
||||
*/
|
||||
|
||||
rtems_device_driver frame_buffer_read(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) arg;
|
||||
|
||||
rw_args->bytes_moved =
|
||||
( ( rw_args->offset + rw_args->count ) > fb_fix_info.smem_len ) ?
|
||||
( fb_fix_info.smem_len - rw_args->offset ) : rw_args->count;
|
||||
memcpy( rw_args->buffer,
|
||||
(const void *) ( fb_fix_info.smem_start + rw_args->offset ),
|
||||
rw_args->bytes_moved );
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
* fbds device driver write operation.
|
||||
*/
|
||||
|
||||
rtems_device_driver frame_buffer_write(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) arg;
|
||||
|
||||
rw_args->bytes_moved =
|
||||
( ( rw_args->offset + rw_args->count ) > fb_fix_info.smem_len ) ?
|
||||
( fb_fix_info.smem_len - rw_args->offset ) : rw_args->count;
|
||||
memcpy( (void *) ( fb_fix_info.smem_start + rw_args->offset ),
|
||||
rw_args->buffer,
|
||||
rw_args->bytes_moved );
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
* ioctl entry point.
|
||||
*/
|
||||
|
||||
rtems_device_driver frame_buffer_control(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
rtems_libio_ioctl_args_t *args = arg;
|
||||
|
||||
/* XXX check minor */
|
||||
|
||||
switch ( args->command ) {
|
||||
case FBIOGET_VSCREENINFO:
|
||||
memcpy( args->buffer, &fb_var_info, sizeof( fb_var_info ) );
|
||||
args->ioctl_return = 0;
|
||||
break;
|
||||
case FBIOGET_FSCREENINFO:
|
||||
memcpy( args->buffer, &fb_fix_info, sizeof( fb_fix_info ) );
|
||||
args->ioctl_return = 0;
|
||||
break;
|
||||
case FBIOGETCMAP:
|
||||
/* no palette - truecolor mode */
|
||||
args->ioctl_return = -1;
|
||||
return RTEMS_UNSATISFIED;
|
||||
case FBIOPUTCMAP:
|
||||
/* no palette - truecolor mode */
|
||||
args->ioctl_return = -1;
|
||||
return RTEMS_UNSATISFIED;
|
||||
default:
|
||||
args->ioctl_return = -1;
|
||||
return RTEMS_UNSATISFIED;
|
||||
}
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
177
bsps/arm/raspberrypi/console/fbcons.c
Normal file
177
bsps/arm/raspberrypi/console/fbcons.c
Normal file
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup raspberrypi_console
|
||||
*
|
||||
* @brief framebuffer graphic console support.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Yang Qiao
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
*
|
||||
* http://www.rtems.org/license/LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <libchip/serial.h>
|
||||
#include <libchip/sersupp.h>
|
||||
|
||||
#include <bsp.h>
|
||||
#include <bsp/fbcons.h>
|
||||
#include <bsp/vc.h>
|
||||
#include <bsp/rpi-fb.h>
|
||||
|
||||
/*
|
||||
* fbcons_init
|
||||
*
|
||||
* This function initializes the fb console to a quiecsent state.
|
||||
*/
|
||||
static void fbcons_init( int minor )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* fbcons_open
|
||||
*
|
||||
* This function opens a port for communication.
|
||||
*
|
||||
* Default state is 9600 baud, 8 bits, No parity, and 1 stop bit.
|
||||
*/
|
||||
static int fbcons_open(
|
||||
int major,
|
||||
int minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
* fbcons_close
|
||||
*
|
||||
* This function shuts down the requested port.
|
||||
*/
|
||||
static int fbcons_close(
|
||||
int major,
|
||||
int minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
return ( RTEMS_SUCCESSFUL );
|
||||
}
|
||||
|
||||
/*
|
||||
* fbcons_write_polled
|
||||
*
|
||||
* This routine polls out the requested character.
|
||||
*/
|
||||
static void fbcons_write_polled(
|
||||
int minor,
|
||||
char c
|
||||
)
|
||||
{
|
||||
rpi_fb_outch( c );
|
||||
|
||||
if ( c == '\n' )
|
||||
rpi_fb_outch( '\r' ); /* LF = LF + CR */
|
||||
}
|
||||
|
||||
/*
|
||||
* fbcons_write_support_polled
|
||||
*
|
||||
* Console Termios output entry point when using polled output.
|
||||
*
|
||||
*/
|
||||
static ssize_t fbcons_write_support_polled(
|
||||
int minor,
|
||||
const char *buf,
|
||||
size_t len
|
||||
)
|
||||
{
|
||||
int nwrite = 0;
|
||||
|
||||
/*
|
||||
* poll each byte in the string out of the port.
|
||||
*/
|
||||
while ( nwrite < len ) {
|
||||
fbcons_write_polled( minor, *buf++ );
|
||||
nwrite++;
|
||||
}
|
||||
|
||||
/*
|
||||
* return the number of bytes written.
|
||||
*/
|
||||
return nwrite;
|
||||
}
|
||||
|
||||
/*
|
||||
* fbcons_inbyte_nonblocking_polled
|
||||
*
|
||||
* Console Termios polling input entry point.
|
||||
*/
|
||||
static int fbcons_inbyte_nonblocking_polled( int minor )
|
||||
{
|
||||
// if( rtems_kbpoll() ) {
|
||||
// int c = getch();
|
||||
// return c;
|
||||
// }
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* fbcons_set_attributes
|
||||
*
|
||||
* This function sets the UART channel to reflect the requested termios
|
||||
* port settings.
|
||||
*/
|
||||
static int fbcons_set_attributes(
|
||||
int minor,
|
||||
const struct termios *t
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool fbcons_probe( int minor )
|
||||
{
|
||||
// rtems_status_code status;
|
||||
static bool firstTime = true;
|
||||
static bool ret = false;
|
||||
|
||||
/*
|
||||
* keyboard interrupt should be registered when the keyboard is available
|
||||
*/
|
||||
if ( firstTime ) {
|
||||
if ( !rpi_fb_hdmi_is_present() ) {
|
||||
ret = false;
|
||||
} else {
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
firstTime = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const console_fns fbcons_fns =
|
||||
{
|
||||
.deviceProbe = libchip_serial_default_probe, /* deviceProbe */
|
||||
.deviceFirstOpen = fbcons_open, /* deviceFirstOpen */
|
||||
.deviceLastClose = fbcons_close, /* deviceLastClose */
|
||||
.deviceRead = fbcons_inbyte_nonblocking_polled, /* deviceRead */
|
||||
.deviceWrite = fbcons_write_support_polled, /* deviceWrite */
|
||||
.deviceInitialize = fbcons_init, /* deviceInitialize */
|
||||
.deviceWritePolled = fbcons_write_polled, /* deviceWritePolled */
|
||||
.deviceSetAttributes = fbcons_set_attributes, /* deviceSetAttributes */
|
||||
.deviceOutputUsesInterrupts = FALSE, /* deviceOutputUsesInterrupts*/
|
||||
};
|
||||
4639
bsps/arm/raspberrypi/console/font_data.h
Normal file
4639
bsps/arm/raspberrypi/console/font_data.h
Normal file
File diff suppressed because it is too large
Load Diff
463
bsps/arm/raspberrypi/console/outch.c
Normal file
463
bsps/arm/raspberrypi/console/outch.c
Normal file
@@ -0,0 +1,463 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup raspberrypi
|
||||
*
|
||||
* @brief displaying characters on the console
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* Copyright (c) 2015 Yang Qiao
|
||||
* based on work by:
|
||||
* Copyright (C) 1998 Eric Valette (valette@crf.canon.fr)
|
||||
* Canon Centre Recherche France.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*
|
||||
* Till Straumann <strauman@slac.stanford.edu>, 2003/9:
|
||||
* - added handling of basic escape sequences (cursor movement
|
||||
* and erasing; just enough for the line editor 'libtecla' to
|
||||
* work...)
|
||||
*
|
||||
*/
|
||||
|
||||
#include <bsp.h>
|
||||
#include <bsp/vc.h>
|
||||
#include <bsp/rpi-fb.h>
|
||||
#include <rtems/fb.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "font_data.h"
|
||||
|
||||
static void wr_cursor(
|
||||
int r,
|
||||
int c
|
||||
)
|
||||
{
|
||||
/* dummy function for now */
|
||||
}
|
||||
|
||||
#define TAB_SPACE 4
|
||||
#define CONSOLE_BG_COL 0x00
|
||||
#define CONSOLE_FG_COL 0xa0
|
||||
|
||||
static void *fb_mem = NULL;
|
||||
static unsigned short maxCol;
|
||||
static unsigned short maxRow;
|
||||
static unsigned short bytes_per_pixel;
|
||||
static unsigned int bytes_per_line;
|
||||
static unsigned int bytes_per_char_line;
|
||||
static unsigned char row;
|
||||
static unsigned char column;
|
||||
static unsigned int nLines;
|
||||
static uint32_t fgx, bgx, eorx;
|
||||
static int rpi_video_initialized;
|
||||
|
||||
static const int video_font_draw_table32[ 16 ][ 4 ] = {
|
||||
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x00000000, 0x00000000, 0x00000000, 0x00ffffff },
|
||||
{ 0x00000000, 0x00000000, 0x00ffffff, 0x00000000 },
|
||||
{ 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff },
|
||||
{ 0x00000000, 0x00ffffff, 0x00000000, 0x00000000 },
|
||||
{ 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff },
|
||||
{ 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000 },
|
||||
{ 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff },
|
||||
{ 0x00ffffff, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff },
|
||||
{ 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000 },
|
||||
{ 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff },
|
||||
{ 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000 },
|
||||
{ 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff },
|
||||
{ 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000 },
|
||||
{ 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff }
|
||||
};
|
||||
|
||||
static void scroll( void )
|
||||
{
|
||||
int i, j; /* Counters */
|
||||
uint8_t *pt_scroll, *pt_bitmap; /* Pointers on the bit-map */
|
||||
|
||||
pt_bitmap = fb_mem;
|
||||
j = 0;
|
||||
pt_bitmap = pt_bitmap + j;
|
||||
pt_scroll = pt_bitmap + bytes_per_char_line;
|
||||
|
||||
for ( i = j; i < maxRow - 1; i++ ) {
|
||||
memcpy( pt_bitmap, pt_scroll, bytes_per_char_line );
|
||||
pt_bitmap = pt_bitmap + bytes_per_char_line;
|
||||
pt_scroll = pt_bitmap + bytes_per_char_line;
|
||||
}
|
||||
|
||||
/*
|
||||
* Blank characters are displayed on the last line.
|
||||
*/
|
||||
memset( pt_bitmap, 0, bytes_per_char_line );
|
||||
}
|
||||
|
||||
static void doCRNL(
|
||||
int cr,
|
||||
int nl
|
||||
)
|
||||
{
|
||||
if ( nl ) {
|
||||
if ( ++row == maxRow ) {
|
||||
scroll(); /* Scroll the screen now */
|
||||
row = maxRow - 1;
|
||||
}
|
||||
|
||||
nLines++;
|
||||
}
|
||||
|
||||
if ( cr )
|
||||
column = 0;
|
||||
|
||||
/* Move cursor on the next location */
|
||||
if ( cr || nl ) {
|
||||
wr_cursor( row, column );
|
||||
}
|
||||
}
|
||||
|
||||
static void advanceCursor( void )
|
||||
{
|
||||
if ( ++column == maxCol )
|
||||
doCRNL( 1, 1 );
|
||||
else
|
||||
wr_cursor( row, column );
|
||||
}
|
||||
|
||||
static void gotorc(
|
||||
int r,
|
||||
int c
|
||||
)
|
||||
{
|
||||
column = c;
|
||||
row = r;
|
||||
wr_cursor( row, column );
|
||||
}
|
||||
|
||||
static void video_drawchars(
|
||||
int r,
|
||||
int c,
|
||||
unsigned char ch
|
||||
)
|
||||
{
|
||||
if ( fb_mem == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *cdat, *dest, *dest0;
|
||||
int rows, offset;
|
||||
|
||||
offset = r * bytes_per_char_line + c * bytes_per_pixel * RPI_FONT_WIDTH;
|
||||
dest0 = fb_mem + offset;
|
||||
|
||||
/*
|
||||
* only 32-bit per pixel format is supported for now
|
||||
*/
|
||||
cdat = rpi_font + ch * RPI_FONT_HEIGHT;
|
||||
|
||||
for ( rows = RPI_FONT_HEIGHT, dest = dest0;
|
||||
rows--; dest += bytes_per_line ) {
|
||||
uint8_t bits = *cdat++;
|
||||
|
||||
( (uint32_t *) dest )[ 0 ] =
|
||||
( video_font_draw_table32
|
||||
[ bits >> 4 ][ 0 ] & eorx ) ^ bgx;
|
||||
( (uint32_t *) dest )[ 1 ] =
|
||||
( video_font_draw_table32
|
||||
[ bits >> 4 ][ 1 ] & eorx ) ^ bgx;
|
||||
( (uint32_t *) dest )[ 2 ] =
|
||||
( video_font_draw_table32
|
||||
[ bits >> 4 ][ 2 ] & eorx ) ^ bgx;
|
||||
( (uint32_t *) dest )[ 3 ] =
|
||||
( video_font_draw_table32
|
||||
[ bits >> 4 ][ 3 ] & eorx ) ^ bgx;
|
||||
|
||||
( (uint32_t *) dest )[ 4 ] =
|
||||
( video_font_draw_table32
|
||||
[ bits & 15 ][ 0 ] & eorx ) ^ bgx;
|
||||
( (uint32_t *) dest )[ 5 ] =
|
||||
( video_font_draw_table32
|
||||
[ bits & 15 ][ 1 ] & eorx ) ^ bgx;
|
||||
( (uint32_t *) dest )[ 6 ] =
|
||||
( video_font_draw_table32
|
||||
[ bits & 15 ][ 2 ] & eorx ) ^ bgx;
|
||||
( (uint32_t *) dest )[ 7 ] =
|
||||
( video_font_draw_table32
|
||||
[ bits & 15 ][ 3 ] & eorx ) ^ bgx;
|
||||
}
|
||||
}
|
||||
|
||||
#define ESC ( (char) 27 )
|
||||
/* erase current location without moving the cursor */
|
||||
#define BLANK ( (char) 0x7f )
|
||||
|
||||
static void videoPutChar( char ch )
|
||||
{
|
||||
switch ( ch ) {
|
||||
case '\b': {
|
||||
if ( column )
|
||||
column--;
|
||||
|
||||
/* Move cursor on the previous location */
|
||||
wr_cursor( row, column );
|
||||
return;
|
||||
}
|
||||
case '\t': {
|
||||
int i;
|
||||
|
||||
i = TAB_SPACE - ( column & ( TAB_SPACE - 1 ) );
|
||||
|
||||
while ( i-- ) {
|
||||
|
||||
video_drawchars( row, column, ' ' );
|
||||
column += 1;
|
||||
|
||||
if ( column >= maxCol ) {
|
||||
doCRNL( 1, 1 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wr_cursor( row, column );
|
||||
|
||||
return;
|
||||
}
|
||||
case '\n': {
|
||||
doCRNL( 0, 1 );
|
||||
return;
|
||||
}
|
||||
case 7: { /* Bell code must be inserted here */
|
||||
return;
|
||||
}
|
||||
case '\r': {
|
||||
doCRNL( 1, 0 );
|
||||
return;
|
||||
}
|
||||
case BLANK: {
|
||||
video_drawchars( row, column, ' ' );
|
||||
|
||||
wr_cursor( row, column );
|
||||
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
// *pt_bitmap = (unsigned char)ch | attribute;
|
||||
video_drawchars( row, column, ch );
|
||||
advanceCursor();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* trivial state machine to handle escape sequences:
|
||||
*
|
||||
* ---------------------------------
|
||||
* | |
|
||||
* | |
|
||||
* KEY: esc V [ DCABHKJ esc |
|
||||
* STATE: 0 -----> 27 -----> '[' ----------> -1 -----
|
||||
* ^\ \ \ \
|
||||
* KEY: | \other \ other \ other \ other
|
||||
* <-------------------------------------
|
||||
*
|
||||
* in state '-1', the DCABHKJ cases are handled
|
||||
*
|
||||
* (cursor motion and screen clearing)
|
||||
*/
|
||||
|
||||
#define DONE ( -1 )
|
||||
|
||||
static int handleEscape(
|
||||
int oldState,
|
||||
char ch
|
||||
)
|
||||
{
|
||||
int rval = 0;
|
||||
int ro, co;
|
||||
|
||||
switch ( oldState ) {
|
||||
case DONE: /* means the previous char terminated an ESC sequence... */
|
||||
case 0:
|
||||
|
||||
if ( 27 == ch ) {
|
||||
rval = 27; /* START of an ESC sequence */
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 27:
|
||||
|
||||
if ( '[' == ch ) {
|
||||
rval = ch; /* received ESC '[', so far */
|
||||
} else {
|
||||
/* dump suppressed 'ESC'; outch will append the char */
|
||||
videoPutChar( ESC );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '[':
|
||||
/* handle 'ESC' '[' sequences here */
|
||||
ro = row;
|
||||
co = column;
|
||||
rval = DONE; /* done */
|
||||
|
||||
switch ( ch ) {
|
||||
case 'D': /* left */
|
||||
|
||||
if ( co > 0 )
|
||||
co--;
|
||||
|
||||
break;
|
||||
case 'C': /* right */
|
||||
|
||||
if ( co < maxCol )
|
||||
co++;
|
||||
|
||||
break;
|
||||
case 'A': /* up */
|
||||
|
||||
if ( ro > 0 )
|
||||
ro--;
|
||||
|
||||
break;
|
||||
case 'B': /* down */
|
||||
|
||||
if ( ro < maxRow )
|
||||
ro++;
|
||||
|
||||
break;
|
||||
case 'H': /* home */
|
||||
ro = co = 0;
|
||||
break;
|
||||
case 'K': /* clear to end of line */
|
||||
|
||||
while ( column < maxCol - 1 )
|
||||
videoPutChar( ' ' );
|
||||
|
||||
videoPutChar( BLANK );
|
||||
break;
|
||||
case 'J': /* clear to end of screen */
|
||||
|
||||
while ( ( ( row < maxRow - 1 ) || ( column < maxCol - 1 ) ) )
|
||||
videoPutChar( ' ' );
|
||||
|
||||
videoPutChar( BLANK );
|
||||
break;
|
||||
default:
|
||||
videoPutChar( ESC );
|
||||
videoPutChar( '[' );
|
||||
/* DONT move the cursor */
|
||||
ro = -1;
|
||||
rval = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// /* reset cursor */
|
||||
if ( ro >= 0 )
|
||||
gotorc( ro, co );
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static void clear_screen( void )
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for ( j = 0; j < maxRow; j++ ) {
|
||||
for ( i = 0; i < maxCol; i++ ) {
|
||||
videoPutChar( ' ' );
|
||||
}
|
||||
}
|
||||
|
||||
column = 0;
|
||||
row = 0;
|
||||
}
|
||||
|
||||
void rpi_fb_outch( char c )
|
||||
{
|
||||
static int escaped = 0;
|
||||
|
||||
if ( !( escaped = handleEscape( escaped, c ) ) ) {
|
||||
if ( '\n' == c )
|
||||
videoPutChar( '\r' );
|
||||
|
||||
videoPutChar( c );
|
||||
}
|
||||
}
|
||||
|
||||
void rpi_video_init( void )
|
||||
{
|
||||
int ret = rpi_fb_init();
|
||||
|
||||
if ( ( ret != RPI_FB_INIT_OK ) &&
|
||||
( ret != RPI_FB_INIT_ALREADY_INITIALIZED ) ) {
|
||||
rpi_video_initialized = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
struct fb_var_screeninfo fb_var_info;
|
||||
struct fb_fix_screeninfo fb_fix_info;
|
||||
rpi_get_var_screen_info( &fb_var_info );
|
||||
rpi_get_fix_screen_info( &fb_fix_info );
|
||||
maxCol = fb_var_info.xres / RPI_FONT_WIDTH;
|
||||
maxRow = fb_var_info.yres / RPI_FONT_HEIGHT;
|
||||
bytes_per_pixel = fb_var_info.bits_per_pixel / 8;
|
||||
bytes_per_line = bytes_per_pixel * fb_var_info.xres;
|
||||
bytes_per_char_line = RPI_FONT_HEIGHT * bytes_per_line;
|
||||
fb_mem = RTEMS_DEVOLATILE( void *, fb_fix_info.smem_start );
|
||||
column = 0;
|
||||
row = 0;
|
||||
nLines = 0;
|
||||
fgx = ( CONSOLE_FG_COL << 24 ) |
|
||||
( CONSOLE_FG_COL << 16 ) |
|
||||
( CONSOLE_FG_COL << 8 ) |
|
||||
CONSOLE_FG_COL;
|
||||
bgx = ( CONSOLE_BG_COL << 24 ) |
|
||||
( CONSOLE_BG_COL << 16 ) |
|
||||
( CONSOLE_BG_COL << 8 ) |
|
||||
CONSOLE_BG_COL;
|
||||
eorx = fgx ^ bgx;
|
||||
clear_screen();
|
||||
rpi_video_initialized = 1;
|
||||
}
|
||||
|
||||
int rpi_video_is_initialized( void )
|
||||
{
|
||||
return rpi_video_initialized;
|
||||
}
|
||||
|
||||
/* for old DOS compatibility n-curses type of applications */
|
||||
void gotoxy(
|
||||
int x,
|
||||
int y
|
||||
);
|
||||
int whereX( void );
|
||||
int whereY( void );
|
||||
|
||||
void gotoxy(
|
||||
int x,
|
||||
int y
|
||||
)
|
||||
{
|
||||
gotorc( y, x );
|
||||
}
|
||||
|
||||
int whereX( void )
|
||||
{
|
||||
return row;
|
||||
}
|
||||
|
||||
int whereY( void )
|
||||
{
|
||||
return column;
|
||||
}
|
||||
167
bsps/arm/raspberrypi/console/usart.c
Normal file
167
bsps/arm/raspberrypi/console/usart.c
Normal file
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup raspberrypi_usart
|
||||
*
|
||||
* @brief USART support.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 Alan Cudmore
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
*
|
||||
* http://www.rtems.org/license/LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include <libchip/sersupp.h>
|
||||
|
||||
#include <bsp.h>
|
||||
#include <bsp/irq.h>
|
||||
#include <bsp/usart.h>
|
||||
#include <bsp/raspberrypi.h>
|
||||
#include <rtems/bspIo.h>
|
||||
|
||||
static void usart_delay(uint32_t n)
|
||||
{
|
||||
volatile uint32_t i = 0;
|
||||
|
||||
for(i = 0; i < n; i++)
|
||||
;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* These will be useful when the driver supports interrupt driven IO.
|
||||
*/
|
||||
static rtems_vector_number usart_get_irq_number(const console_tbl *ct)
|
||||
{
|
||||
return ct->ulIntVector;
|
||||
}
|
||||
|
||||
static uint32_t usart_get_baud(const console_tbl *ct)
|
||||
{
|
||||
return ct->ulClock;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void usart_set_baud(int minor, int baud)
|
||||
{
|
||||
/*
|
||||
* Nothing for now
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
static void usart_initialize(int minor)
|
||||
{
|
||||
unsigned int gpio_reg;
|
||||
|
||||
/*
|
||||
** Program GPIO pins for UART 0
|
||||
*/
|
||||
gpio_reg = BCM2835_REG(BCM2835_GPIO_GPFSEL1);
|
||||
gpio_reg &= ~(7<<12); /* gpio14 */
|
||||
gpio_reg |= (4<<12); /* alt0 */
|
||||
gpio_reg &= ~(7<<15); /* gpio15 */
|
||||
gpio_reg |= (4<<15); /* alt0 */
|
||||
BCM2835_REG(BCM2835_GPIO_GPFSEL1) = gpio_reg;
|
||||
|
||||
BCM2835_REG(BCM2835_GPIO_GPPUD) = 0;
|
||||
usart_delay(150);
|
||||
BCM2835_REG(BCM2835_GPIO_GPPUDCLK0) = (1<<14)|(1<<15);
|
||||
usart_delay(150);
|
||||
BCM2835_REG(BCM2835_GPIO_GPPUDCLK0) = 0;
|
||||
|
||||
/*
|
||||
** Init the PL011 UART
|
||||
*/
|
||||
BCM2835_REG(BCM2835_UART0_CR) = 0;
|
||||
BCM2835_REG(BCM2835_UART0_ICR) = 0x7FF;
|
||||
BCM2835_REG(BCM2835_UART0_IMSC) = 0;
|
||||
BCM2835_REG(BCM2835_UART0_IBRD) = 1;
|
||||
BCM2835_REG(BCM2835_UART0_FBRD) = 40;
|
||||
BCM2835_REG(BCM2835_UART0_LCRH) = 0x70;
|
||||
BCM2835_REG(BCM2835_UART0_RSRECR) = 0;
|
||||
|
||||
BCM2835_REG(BCM2835_UART0_CR) = 0x301;
|
||||
|
||||
BCM2835_REG(BCM2835_UART0_IMSC) = BCM2835_UART0_IMSC_RX;
|
||||
|
||||
usart_set_baud(minor, 115000);
|
||||
}
|
||||
|
||||
static int usart_first_open(int major, int minor, void *arg)
|
||||
{
|
||||
rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg;
|
||||
struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1;
|
||||
const console_tbl *ct = Console_Port_Tbl [minor];
|
||||
console_data *cd = &Console_Port_Data [minor];
|
||||
|
||||
cd->termios_data = tty;
|
||||
rtems_termios_set_initial_baud(tty, ct->ulClock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usart_last_close(int major, int minor, void *arg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usart_read_polled(int minor)
|
||||
{
|
||||
if (minor == 0) {
|
||||
if (((BCM2835_REG(BCM2835_UART0_FR)) & BCM2835_UART0_FR_RXFE) == 0) {
|
||||
return((BCM2835_REG(BCM2835_UART0_DR)) & 0xFF );
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
printk("Unknown console minor number: %d\n", minor);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void usart_write_polled(int minor, char c)
|
||||
{
|
||||
while (1) {
|
||||
if ((BCM2835_REG(BCM2835_UART0_FR) & BCM2835_UART0_FR_TXFF) == 0)
|
||||
break;
|
||||
}
|
||||
BCM2835_REG(BCM2835_UART0_DR) = c;
|
||||
}
|
||||
|
||||
static ssize_t usart_write_support_polled(
|
||||
int minor,
|
||||
const char *s,
|
||||
size_t n
|
||||
)
|
||||
{
|
||||
ssize_t i = 0;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
usart_write_polled(minor, s [i]);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static int usart_set_attributes(int minor, const struct termios *term)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
const console_fns bcm2835_usart_fns = {
|
||||
.deviceProbe = libchip_serial_default_probe,
|
||||
.deviceFirstOpen = usart_first_open,
|
||||
.deviceLastClose = usart_last_close,
|
||||
.deviceRead = usart_read_polled,
|
||||
.deviceWrite = usart_write_support_polled,
|
||||
.deviceInitialize = usart_initialize,
|
||||
.deviceWritePolled = usart_write_polled,
|
||||
.deviceSetAttributes = usart_set_attributes,
|
||||
.deviceOutputUsesInterrupts = false
|
||||
};
|
||||
Reference in New Issue
Block a user