[PATCH 4/6] add fb support for rpi bsp

YANG QIAO yangqiao0505 at me.com
Wed Aug 12 22:08:03 UTC 2015


From: YANG Qiao <yangqiao0505 at me.com>

---
 c/src/lib/libbsp/arm/raspberrypi/Makefile.am       |   5 +-
 c/src/lib/libbsp/arm/raspberrypi/console/fb.c      | 331 +++++++++++++++++++++
 c/src/lib/libbsp/arm/raspberrypi/include/bsp.h     |   2 +
 .../arm/raspberrypi/startup/bspgetworkarea.c       |  61 ++++
 c/src/lib/libbsp/arm/raspberrypi/startup/linkcmds  |   5 +-
 c/src/lib/libbsp/arm/raspberrypi/startup/mminit.c  |  42 +++
 6 files changed, 442 insertions(+), 4 deletions(-)
 create mode 100644 c/src/lib/libbsp/arm/raspberrypi/console/fb.c
 create mode 100644 c/src/lib/libbsp/arm/raspberrypi/startup/bspgetworkarea.c
 create mode 100644 c/src/lib/libbsp/arm/raspberrypi/startup/mminit.c

diff --git a/c/src/lib/libbsp/arm/raspberrypi/Makefile.am b/c/src/lib/libbsp/arm/raspberrypi/Makefile.am
index e0b4806..b4853a6 100644
--- a/c/src/lib/libbsp/arm/raspberrypi/Makefile.am
+++ b/c/src/lib/libbsp/arm/raspberrypi/Makefile.am
@@ -79,7 +79,6 @@ libbsp_a_LIBADD =
 # Shared
 libbsp_a_SOURCES += ../../shared/bootcard.c
 libbsp_a_SOURCES += ../../shared/bspclean.c
-libbsp_a_SOURCES += ../../shared/bspgetworkarea.c
 libbsp_a_SOURCES += ../../shared/bsplibc.c
 libbsp_a_SOURCES += ../../shared/bsppost.c
 libbsp_a_SOURCES += ../../shared/bsppredriverhook.c
@@ -97,6 +96,7 @@ libbsp_a_SOURCES += ../shared/arm-cp15-set-ttb-entries.c
 libbsp_a_SOURCES += ../../shared/bspreset_loop.c
 libbsp_a_SOURCES += startup/bspstart.c
 libbsp_a_SOURCES += startup/cmdline.c
+libbsp_a_SOURCES += startup/bspgetworkarea.c
 
 # IRQ
 libbsp_a_SOURCES += ../shared/arm-cp15-set-exception-handler.c
@@ -115,6 +115,7 @@ libbsp_a_SOURCES += ../../shared/console_select.c
 libbsp_a_SOURCES += ../../shared/console_write.c
 libbsp_a_SOURCES += console/console-config.c
 libbsp_a_SOURCES += console/usart.c
+libbsp_a_SOURCES += console/fb.c
 
 # clock
 libbsp_a_SOURCES += clock/clockdrv.c ../../../shared/clockdrv_shell.h
@@ -147,7 +148,7 @@ libbsp_a_SOURCES += startup/bspstarthooks.c
 
 # LIBMM
 libbsp_a_SOURCES += startup/mm_config_table.c
-libbsp_a_SOURCES += ../shared/mminit.c
+libbsp_a_SOURCES += startup/mminit.c
 
 ###############################################################################
 # Network                                                    #
diff --git a/c/src/lib/libbsp/arm/raspberrypi/console/fb.c b/c/src/lib/libbsp/arm/raspberrypi/console/fb.c
new file mode 100644
index 0000000..a83d560
--- /dev/null
+++ b/c/src/lib/libbsp/arm/raspberrypi/console/fb.c
@@ -0,0 +1,331 @@
+/**
+ * @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 <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 <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/fb.h>
+#include <rtems/framebuffer.h>
+#include <rtems/score/atomic.h>
+
+#define SCREEN_WIDTH 1024
+#define SCREEN_HEIGHT 768
+#define BPP 32
+#define BUFFER_SIZE (SCREEN_WIDTH*SCREEN_HEIGHT*BPP/8)
+
+/* 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
+};
+
+int raspberrypi_get_fix_screen_info( struct fb_fix_screeninfo *info )
+{
+  *info = fb_fix_info;
+  return 0;
+}
+
+int raspberrypi_get_var_screen_info( struct fb_var_screeninfo *info )
+{
+  *info = fb_var_info;
+  return 0;
+}
+
+static int
+find_mode_from_cmdline(void)
+{
+  const char* opt;
+  char* endptr;
+  uint32_t width;
+  uint32_t height;
+  uint32_t bpp;
+  opt = rpi_cmdline_arg("--video=");
+  if (opt)
+  {
+      opt += sizeof("--video=")-1;
+      width = strtol(opt, &endptr, 10);
+      if (*endptr != 'x')
+      {
+          return -2;
+      }
+      opt = endptr+1;
+      height = strtol(opt, &endptr, 10);
+      switch (*endptr)
+      {
+          case '-':
+              opt = endptr+1;
+              if (strlen(opt) <= 2)
+                  bpp = strtol(opt, &endptr, 10);
+              else
+              {
+                  bpp = strtol(opt, &endptr, 10);
+                  if (*endptr != ' ')
+                  {
+                      return -4;
+                  }
+              }
+          case ' ':
+          case 0:
+              break;
+          default:
+              return -3;
+      }
+  }
+  else
+    return -1;
+
+  fb_var_info.xres    = width;
+  fb_var_info.yres    = height;
+
+  return 0;
+}
+
+static int
+find_mode_from_vc(void)
+{
+  bcm2835_get_display_size_entries entries;
+  bcm2835_mailbox_get_display_size(&entries);
+  unsigned int width = entries.width;
+  unsigned int 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;
+  }
+
+  return 0;
+}
+
+static bool
+hdmi_is_present(void)
+{
+  bcm2835_get_display_size_entries entries;
+  bcm2835_mailbox_get_display_size(&entries);
+  if(entries.width == 0x290 && entries.height ==0x1A0 )
+  {
+    return false;
+  }
+  else
+  {
+    return true;
+  }
+}
+
+int
+fb_init(void)
+{
+  if (fb_fix_info.smem_start != NULL)
+  {
+    return -2;
+  }
+
+  if (hdmi_is_present() == false)
+  {
+    return -3;
+  }
+
+  if (find_mode_from_cmdline())
+  {
+    if(find_mode_from_vc())
+      return -1;
+  }
+
+  bcm2835_init_frame_buffer_entries  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;
+  bcm2835_mailbox_init_frame_buffer(&init_frame_buffer_entries);
+
+  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 = init_frame_buffer_entries.base;
+  fb_fix_info.smem_len = init_frame_buffer_entries.size;
+  fb_fix_info.line_length = get_pitch_entries.pitch;
+
+  return 0;
+}
+
+
+/*
+ * 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( "FB_CIRRUS could not lock driver_mutex\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() */
+  _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE);
+  memset ((void *)fb_fix_info.smem_start, 0, fb_fix_info.smem_len);
+  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:
+    args->ioctl_return = 0;
+    break;
+  case FBIOPUTCMAP:
+    args->ioctl_return = 0;
+    break;
+
+  default:
+    args->ioctl_return = 0;
+    break;
+
+  }
+  return RTEMS_SUCCESSFUL;
+}
diff --git a/c/src/lib/libbsp/arm/raspberrypi/include/bsp.h b/c/src/lib/libbsp/arm/raspberrypi/include/bsp.h
index 7cb9e70..0bc5f99 100644
--- a/c/src/lib/libbsp/arm/raspberrypi/include/bsp.h
+++ b/c/src/lib/libbsp/arm/raspberrypi/include/bsp.h
@@ -34,6 +34,8 @@ extern "C" {
 
 #define BSP_FEATURE_IRQ_EXTENSION
 
+#define RPI_L2_CACHE_ENABLE 1
+
 #define BSP_GPIO_PIN_COUNT 32
 #define BSP_GPIO_PINS_PER_BANK 32
 #define BSP_GPIO_PINS_PER_SELECT_BANK 10
diff --git a/c/src/lib/libbsp/arm/raspberrypi/startup/bspgetworkarea.c b/c/src/lib/libbsp/arm/raspberrypi/startup/bspgetworkarea.c
new file mode 100644
index 0000000..07a38e9
--- /dev/null
+++ b/c/src/lib/libbsp/arm/raspberrypi/startup/bspgetworkarea.c
@@ -0,0 +1,61 @@
+/**
+ * @file
+ *
+ * @ingroup arm_start
+ *
+ * @brief Raspberry pi workarea initialization.
+ *
+ *  COPYRIGHT (c) 1989-2008.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ *  Copyright (c) 2011-2012 embedded brains GmbH.
+ *
+ *  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.
+ *
+ *  Copyright (c) 2015 YANG Qiao
+ */
+
+#include <bsp.h>
+#include <bsp/bootcard.h>
+#include <bsp/vc.h>
+#ifdef BSP_INTERRUPT_STACK_AT_WORK_AREA_BEGIN
+  #include <rtems/config.h>
+#endif
+
+#if defined(HAS_UBOOT) && !defined(BSP_DISABLE_UBOOT_WORK_AREA_CONFIG)
+  #define USE_UBOOT
+#endif
+
+extern char WorkAreaBase[];
+
+#ifdef USE_UBOOT
+  #include <bsp/u-boot.h>
+#else
+  extern char RamBase[];
+  extern char RamSize[];
+#endif
+
+void bsp_work_area_initialize(void)
+{
+  uintptr_t work_base = (uintptr_t) WorkAreaBase;
+  uintptr_t ram_end;
+  bcm2835_get_arm_memory_entries arm_entry;
+  bcm2835_get_vc_memory_entries vc_entry;
+
+  #ifdef USE_UBOOT
+    ram_end = (uintptr_t) bsp_uboot_board_info.bi_memstart +
+                          bsp_uboot_board_info.bi_memsize;
+  #else
+    ram_end = (uintptr_t)RamBase + (uintptr_t)RamSize;
+  #endif
+
+  #ifdef BSP_INTERRUPT_STACK_AT_WORK_AREA_BEGIN
+    work_base += rtems_configuration_get_interrupt_stack_size();
+  #endif
+
+  bcm2835_mailbox_get_vc_memory(&vc_entry);
+  ram_end = ram_end>vc_entry.base? vc_entry.base: ram_end;
+  bsp_work_area_initialize_default( (void *) work_base, ram_end - work_base );
+}
diff --git a/c/src/lib/libbsp/arm/raspberrypi/startup/linkcmds b/c/src/lib/libbsp/arm/raspberrypi/startup/linkcmds
index f1ad11c..81d4f8d 100644
--- a/c/src/lib/libbsp/arm/raspberrypi/startup/linkcmds
+++ b/c/src/lib/libbsp/arm/raspberrypi/startup/linkcmds
@@ -37,8 +37,9 @@
 
 MEMORY {
         VECTOR_RAM     (AIW) : ORIGIN = 0x0       , LENGTH = 0x8000
-        RAM            (AIW) : ORIGIN = 0x00008000, LENGTH = 128M - 48K
-	RAM_MMU        (AIW) : ORIGIN = 128M - 16k, LENGTH = 16k
+        GPU_RAM        (AIW) : ORIGIN = 256M - 64M, LENGTH = 64M
+        RAM            (AIW) : ORIGIN = 0x00008000, LENGTH = 256M - 64M - 48K
+	RAM_MMU        (AIW) : ORIGIN = 256M - 64M - 16k, LENGTH = 16k
 }
 
 REGION_ALIAS ("REGION_START", RAM);
diff --git a/c/src/lib/libbsp/arm/raspberrypi/startup/mminit.c b/c/src/lib/libbsp/arm/raspberrypi/startup/mminit.c
new file mode 100644
index 0000000..e012060
--- /dev/null
+++ b/c/src/lib/libbsp/arm/raspberrypi/startup/mminit.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015 Yang Qiao
+ * based on work by:
+ * Copyright (c) 2013 Hesham AL-Matary.
+ *
+ * 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.
+ */
+
+#define ARM_CP15_TEXT_SECTION BSP_START_TEXT_SECTION
+
+#include <bsp/start.h>
+#include <bsp/arm-cp15-start.h>
+#include <bsp/linker-symbols.h>
+#include <bsp/mm.h>
+#include <rtems/fb.h>
+
+extern int raspberrypi_get_var_screen_info( struct fb_var_screeninfo *info );
+
+BSP_START_TEXT_SECTION void bsp_memory_management_initialize(void)
+{
+  uint32_t ctrl = arm_cp15_get_control();
+
+  ctrl |= ARM_CP15_CTRL_AFE | ARM_CP15_CTRL_S | ARM_CP15_CTRL_XP;
+
+  struct fb_fix_screeninfo fb_fix_info;
+  raspberrypi_get_fix_screen_info(&fb_fix_info);
+
+  arm_cp15_start_setup_translation_table_and_enable_mmu_and_cache(
+    ctrl,
+    (uint32_t *) bsp_translation_table_base,
+    ARM_MMU_DEFAULT_CLIENT_DOMAIN,
+    &arm_cp15_start_mmu_config_table[0],
+    arm_cp15_start_mmu_config_table_size
+  );
+
+  arm_cp15_set_translation_table_entries(fb_fix_info.smem_start,
+                                        fb_fix_info.smem_start +
+                                        fb_fix_info.smem_len,
+                                        ARMV7_MMU_DATA_READ_WRITE_CACHED);
+}
-- 
2.1.0




More information about the devel mailing list