bsps: Move console drivers to bsps

This patch is a part of the BSP source reorganization.

Update #3285.
This commit is contained in:
Sebastian Huber
2018-04-19 06:28:01 +02:00
parent 58adad484e
commit d7d66d7d45
236 changed files with 204 additions and 204 deletions

View 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;

View 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();
}
}

View 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;
}

View 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*/
};

File diff suppressed because it is too large Load Diff

View 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;
}

View 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
};