ucosii_demo.c

来自「Sharp LH7A400 BSP平台无关部分的代码,有很高的参考价值,尤其是系」· C语言 代码 · 共 474 行

C
474
字号
/***********************************************************************
 * $Workfile:   ucosii_demo.c  $
 * $Revision:   1.2  $
 * $Author:   WellsK  $
 * $Date:   Oct 28 2003 15:41:16  $
 *
 * Project: SDK7A400 simple uCos-II startup example
 *
 * Description:
 *     This file contains a simple uCos-II demo that will initialize
 *     the SDK7A400 board and then jump to c_entry(), which will
 *     initialize uCos-II and start the uCos-II tasks.
 *
 * Revision History:
 * $Log:   //smaicnt2/pvcs/VM/sharpmcu/archives/sharpmcu/software/csps/lh7a400/bsps/sdk7a400/startup/examples/ucosii/ucosii_demo.c-arc  $
 * 
 *    Rev 1.2   Oct 28 2003 15:41:16   WellsK
 * Updated LCD code to use common LCD parameters.
 * 
 *    Rev 1.1   Oct 02 2003 09:28:54   WellsK
 * Updated interrupt and MMU support. Added support for different
 * displays. Added automatic sizing on windows based on
 * display.
 * 
 *    Rev 1.0   Jun 30 2003 15:27:16   WellsK
 * Initial revision.
 * 
 *
 ***********************************************************************
 * SHARP MICROELECTRONICS OF THE AMERICAS MAKES NO REPRESENTATION
 * OR WARRANTIES WITH RESPECT TO THE PERFORMANCE OF THIS SOFTWARE,
 * AND SPECIFICALLY DISCLAIMS ANY RESPONSIBILITY FOR ANY DAMAGES, 
 * SPECIAL OR CONSEQUENTIAL, CONNECTED WITH THE USE OF THIS SOFTWARE.
 *
 * SHARP MICROELECTRONICS OF THE AMERICAS PROVIDES THIS SOFTWARE SOLELY 
 * FOR THE PURPOSE OF SOFTWARE DEVELOPMENT INCORPORATING THE USE OF A 
 * SHARP MICROCONTROLLER OR SYSTEM-ON-CHIP PRODUCT. USE OF THIS SOURCE
 * FILE IMPLIES ACCEPTANCE OF THESE CONDITIONS.
 *
 * COPYRIGHT (C) 2001 SHARP MICROELECTRONICS OF THE AMERICAS, INC.
 *     CAMAS, WA
 **********************************************************************/

#include "lh7a400_clcdc_driver.h"
#include "lh7a400_gpio_driver.h"
#include "lh7a400_timer_driver.h"
#include "lh7a400_uart_driver.h"
#include "lh7a400_int_driver.h"
#include "abl_arm922t_cp15_driver.h"
#include "sdk7a400_cpld_driver.h"
#include "abl_swim.h"
#include "abl_swim_font.h"
#include "abl_api.h"
#include "ucos_ii.h"

/* Pick only 1 panel from the following list of defines */
#define LCDPANEL sharp_lq035
//#define LCDPANEL sharp_lq039
//#define LCDPANEL sharp_lq057
//#define LCDPANEL sharp_lq064
//#define LCDPANEL sharp_lq104
//#define LCDPANEL sharp_lq121

/* Device handle for LCD driver */
static INT_32 lcddev;
/* Device handle for timer driver */
static INT_32 timer1dev;

/* Frame buffer physical and logic addresses - be careful that the
   uCos-II byte pool doesn't get too big, as it will collide with
   the uCos-II stacks and other important data */
#define FBPHY 0xCC000000   /* Physical address */

/* The MicroCos-II interrupt and tick handler and router */
extern PFV ucos_irq_handler;

#define TASK_STK_SIZE 512 /* Size of each task's stack (WORDs) */
#define N_TASKS       4   /* Number of tasks */

/* Task stacks */
static OS_STK TaskStk[N_TASKS][TASK_STK_SIZE];

/* Display sections for the 2 windows */
INT_32 xmin[3], xmax[3], ymin[3], ymax[3], xsz, ysz;

/* Pointer to logical frame buffer address */
COLOR_T *fblog;

/***********************************************************************
 *
 * Function: make_number_str
 *
 * Purpose: Convert a number to a positive decimal string
 *
 * Processing:
 *     Using successive division, compute the base10 value of a number
 *     into a string and return the string value to the caller.
 *
 * Parameters:
 *     str      : Where to place the generated strinjg
 *     iteration: Number to generate a string from
 *
 * Outputs: None
 *
 * Returns: Nothing
 *
 * Notes: None
 *
 **********************************************************************/
void make_number_str(CHAR *str,
                     INT_32 iteration)
{
    UNS_8 tmp[32];
    INT_32 dvv1, dvv2;
    INT_32 cnt = 0;

    /* Number 0 in string */
    str[cnt] = '0';

    /* Main loop */
    while (iteration > 0)
    {
        dvv1 = iteration / 10;
        dvv2 = dvv1 * 10;
        dvv1 = iteration - dvv2;

        tmp[cnt] = dvv1;
        iteration = iteration / 10;
        cnt++;
    }

    if (cnt > 0)
    {
        for (dvv1 = 0; dvv1 < cnt; dvv1++)
        {
            str[dvv1] = (CHAR) ('0' + tmp[cnt - (dvv1 + 1)]);
        }
    }
    
    str[cnt + 1] = '\0';
}

/***********************************************************************
 *
 * Function: Task1
 *
 * Purpose: Task #1
 *
 * Processing:
 *     Initialize UART2 for 115K-8-N-1 and create a window on the
 *     LCD. Periodically wakeup and check for data in the UART2 ring
 *     buffer. If data exists, output it to the window and go back to
 *     sleep until the next wakeup period.
 *
 * Parameters:
 *     data: Task input data value, not used
 *
 * Outputs: None
 *
 * Returns: Nothing
 *
 * Notes: None
 *
 **********************************************************************/
static void Task1(void *data)
{
    INT_32 uartdev;
    SWIM_WINDOW_T win;
    CHAR str[32];
    INT_32 bytes, idx;

    /* Enable UART2 at 115K-N-8-1 */
    uartdev = abl_open((INT_32) UART2, 0);
    abl_ioctl(uartdev, UART_SET_BAUD_RATE, BPS_115200);
    abl_ioctl(uartdev, UART_SET_PARITY, UART_PARITY_NONE);
    abl_ioctl(uartdev, UART_SET_DATA_BITS, 8);
    abl_ioctl(uartdev, UART_SET_STOP_BITS, 1);

    /* Enable the UART2 receive interrupts in the UART peripheral */
    abl_ioctl(uartdev, UART_ENABLE_INTS,
        (UART_INTR_RI | UART_INTR_RTI));

    /* Place address of UART2 interrupt handler in IRQ router, but use
       as a vectored interrupt (for best performance) */
    int_install_irq_handler(INT_UART2INTR, uart2_isr);

    /* Enable the UART2 interrupt in the interrupt controller */
    int_enable(INT_UART2INTR);

    /* Open a window on the left side of the display */
    swim_window_open(&win, xsz, ysz, fblog, xmin[1], ymin[1],
       xmax[1], ymax[1], 1, WHITE, BLACK, DARKGRAY);

    /* Add a title bar */
    swim_set_title(&win, "Window #1", GREEN);

    while(1)
    {
        /* Sleep for a 10th of a second */
        OSTimeDly(OS_TICKS_PER_SEC / 10);

        /* Try to read some data from the UART ring buffer */
        idx = 0;
        bytes = abl_read(uartdev, str, sizeof(str));
        while (idx < bytes)
        {
            swim_put_char(&win, str[idx]);
            idx++;
        }
    }
}

/***********************************************************************
 *
 * Function: Task2
 *
 * Purpose: Task #2
 *
 * Processing:
 *     Open a SWIM window in the right bottom side of the window. Add a
 *     title bar to the window. Enter the task loop and loop forever.
 *     Approximately every 100 ticks, wakeup and print the 1 second
 *     tick value to the window.
 *
 * Parameters:
 *     data: Task input data value, not used
 *
 * Outputs: None
 *
 * Returns: Nothing
 *
 * Notes: None
 *
 **********************************************************************/
static void Task2(void *data)
{
    SWIM_WINDOW_T win;
    CHAR str[32];
    INT_32 ticks = 0;

    swim_window_open(&win, xsz, ysz, fblog, xmin[2], ymin[2],
       xmax[2], ymax[2], 1, WHITE, BLUE, DARKGRAY);

    /* Add a title bar */
    swim_set_title(&win, "Window #2", MAGENTA);

    while(1)
    {
        /* Sleep for about 1 second */
        OSTimeDly(OS_TICKS_PER_SEC);

        swim_put_text(&win, "Tick #");
        make_number_str(str, ticks);
        swim_put_text(&win, str);
        swim_put_text(&win, "\n");
        ticks++;
    }
}

/***********************************************************************
 *
 * Function: TaskFirst
 *
 * Purpose: First uCos-II task
 *
 * Processing:
 *     Set the uCos time to 0. Enable timer to start timer interrupts.
 *     Call the OSStatInit() to start uCos statistics. Call the
 *     OSTaskCreate() function to start tassk 1 and 2. Open a SWIM
 *     window in the left side of the window. Add a title bar to the
 *     window. Enter the task loop and loop forever. In the task loop,
 *     increment iteration and clr. Set the new window pen color based
 *     on clr. Output a string to the window with the iteration counter
 *     value.
 *
 * Parameters:
 *     data: Task input data value, not used
 *
 * Outputs: None
 *
 * Returns: Nothing
 *
 * Notes: None
 *
 **********************************************************************/
static void TaskFirst(void *data)
{
    SWIM_WINDOW_T win;
    CHAR str[32];
    const CHAR it_str[] = "Iteration #";
    COLOR_T clr = BLACK;
    INT_32 iteration = 0;
#if OS_CRITICAL_METHOD == 3 /* Storage for CPU status register */
    OS_CPU_SR  cpu_sr;
#endif

    OSTimeSet(0);

    OS_ENTER_CRITICAL();
    /* Start timer 1 */
    abl_ioctl(timer1dev, TIMER_ENABLE, 1);
    OS_EXIT_CRITICAL();

    OSStatInit();

    /* Create task #1 with priority 0 */
    OSTaskCreate(Task1, (void *) 0, &TaskStk[1][TASK_STK_SIZE - 1], 0);

    /* Create task #2 with priority 1 */
    OSTaskCreate(Task2, (void *) 0, &TaskStk[2][TASK_STK_SIZE - 1], 1);

    /* Open a window on the left side of the display */
    swim_window_open(&win, xsz, ysz, fblog, xmin[0], ymin[0],
       xmax[0], ymax[0], 1, WHITE, DARKGRAY, BLACK);

    /* Add a title bar on the window */
    swim_set_title(&win, "Thread #1 - Iteration list", LIGHTGRAY);

    /* Thread task loop */
    while(1)
    {
        /* Increment iteration counter */
        iteration++;

        /* Use a new pen color for the next iteration message */
        clr = clr + 0x2;
        swim_set_pen_color(&win, clr);

        /* Output the next iteration message in the window */
        swim_put_text(&win, it_str);
        make_number_str(str, iteration);
        swim_put_text(&win, str);
        swim_put_text(&win, "\n");
    }
}

/***********************************************************************
 *
 * Function: c_entry
 *
 * Purpose: Main entry point for image - transfers from startup code
 *
 * Processing:
 *     See function.
 *
 * Parameters: None
 *
 * Outputs: None
 *
 * Returns: Nothing
 *
 * Notes: None
 *
 **********************************************************************/
void c_entry()
{
    INT_32 regionsize;

    /* Set virtual address of MMU table (needed for interrupt driver
       functions) */
    cp15_set_vmmu_addr((UNS_32 *)
        (0xC1C00000 + (0xCD3E0000- 0xCD000000)));

    /* Initialize the IO system */
    abl_api_init((UNS_32 *) NULL);

    /* Register LCD, timer, and UART drivers in API - instead of
       registering, the direct driver functions can also be called
       directly. */
    abl_api_register((INT_32) CLCDC, (void *) lcd_open,
        (void *) lcd_close, (void *) lcd_read,
        (void *) lcd_write, (void *) lcd_ioctl);
    abl_api_register((INT_32) TIMER1, (void *) timer_open,
        (void *) timer_close, (void *) timer_read,
        (void *) timer_write, (void *) timer_ioctl);
    abl_api_register((INT_32) UART2, (void *) uart_open,
        (void *) uart_close, (void *) uart_read_ring,
        (void *) uart_write_ring, (void *) uart_ioctl);

    /* Initialize the CPLD interface driver */
    cpld_init();

    /* Initialize the interrupt system */
    int_initialize(0xFFFFFFFF);

    /* Attach the uCos-II interrupt handler to the IRQ vector */
    int_install_handler(IRQ_VEC, (PFV) &ucos_irq_handler);

    /* Enable GPIO signals PE4..7 and PD0..7 as LCD signals */
    gpio_lcd_signal_select(GPIO_LCDV_0_15);

    /* Open LCD with lh7a404_lq035q7db02 display */
    lcddev = abl_open((INT_32) CLCDC, (INT_32) &LCDPANEL);

    /* Make sure shared JTAG signal on PA2 is not active */
    gpio_set_data_dir(GPIO_PORT_A, 0x04, GPIO_OUTPUT);
    gpio_data_write(GPIO_PORT_A, 0x04);

    /* Turn on the LCD backlight */
    cpld_enable_lcd_veeen(TRUE);

    /* Set color depth to 16 bits per pixel */
    abl_ioctl(lcddev, LCD_SET_BPP, 16);
 
    /* For displays that require more bandwidth, set DMA to request
       a transfer on 4 words empty instead of the default 8. This may
       help prevent 'display tearing' due to a starved LCD controller */
    regionsize = abl_ioctl(lcddev, LCD_GET_STATUS, LCD_XSIZE) *
        abl_ioctl(lcddev, LCD_GET_STATUS, LCD_YSIZE) *
        sizeof (COLOR_T);
    if (regionsize >= (800 * 600 * 2))
    {
        /* Displays of 800x600 pixels and 16-bits of color (or larger)
           will use faster DMA requests */
        abl_ioctl(lcddev, LCD_DMA_ON_4MT, 1);
    }

    /* Set frame buffer and enable display */
    abl_ioctl(lcddev, LCD_SET_UP_FB, (INT_32) FBPHY);
    abl_ioctl(lcddev, LCD_PWENABLE, 1);

    /* Get display size */
    xsz = abl_ioctl(lcddev, LCD_GET_STATUS, LCD_XSIZE);
    ysz = abl_ioctl(lcddev, LCD_GET_STATUS, LCD_YSIZE);
    
    /* Break the display into 3 sections for SWIM windows */
    /* First section is left half of the display */
    xmin[0] = ymin[0] = 0;
    xmax[0] = (xsz / 2) - 1;
    ymax[0] = ysz - 1;

    /* Next window sizes */
    xmin[1] = xmin[2] = xmax[0] + 1;
    xmax[1] = xmax[2] = xsz - 1;
    ymin[1] = 0;
    ymax[1] = (ysz / 2) - 1;
    ymin[2] = ymax[1] + 1;
    ymax[2] = ysz - 1;

    /* Save logical address of frame buffer */
    fblog = cp15_map_physical_to_virtual(FBPHY);
    
    /* Setup timer 1 */
    timer1dev = abl_open((INT_32) TIMER1, 0);

    /* Compute the timer tick time based on the uCos OS_TICKS_PER_SEC
       define */
    abl_ioctl(timer1dev, TIMER_SET_USECS,
        ((1000 / OS_TICKS_PER_SEC) * 1000));

    /* Normally, we would put the address of the timer interrupt in
       the IRQ dispatcher, but the uCos-II interrupt handler in the
       os_cpu_a.s file directly handles the timer 1 interrupt so the
       following statement is not needed */
    /*
    int_install_handler(INT_TC1UINTR, **some_timer_isr**);
    */

    /* Enable timer interrupt in the interrupt controller - note we do
       not actually start the timer clock yet - it will start in the
       first uCos-II task */
    int_enable(INT_TC1UINTR);

    /* Initialize uC/OS-II */
    OSInit(); 

    /* Start the first task as the (almost) background task */ 
    OSTaskCreate(TaskFirst, (void *) 0,
        &TaskStk[0][TASK_STK_SIZE - 1], 4);

    /* Start uC/OS-II */ 
    OSStart();
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?