var_misc.c

来自「eCos操作系统源码」· C语言 代码 · 共 362 行

C
362
字号
//==========================================================================////      var_misc.c////      HAL implementation miscellaneous functions////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2002, 2003 Gary Thomas//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):    jskov// Contributors: jskov, gthomas// Date:         2000-02-04// Purpose:      HAL miscellaneous functions// Description:  This file contains miscellaneous functions provided by the//               HAL.////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/hal.h>#define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS#include <cyg/hal/ppc_regs.h>#include <cyg/infra/cyg_type.h>#include <cyg/hal/hal_io.h>             // I/O macros#include <cyg/hal/hal_if.h>             // Support (virtual vector)#include <cyg/hal/hal_mem.h>#include <cyg/infra/diag.h>#ifdef CYGPKG_IO_PCIexternC void hal_ppc405_pci_init(void);#endifexternC void hal_ppc40x_clock_initialize(cyg_uint32 period);static  void hal_ppc405_i2c_init(void);//--------------------------------------------------------------------------void hal_variant_init(void){    // Initialize I/O interfaces    hal_if_init();#if defined(CYGHWR_HAL_POWERPC_PPC4XX_405) || defined(CYGHWR_HAL_POWERPC_PPC4XX_405GP)    // Initialize I2C controller    hal_ppc405_i2c_init();#endif    // Initialize real-time clock (for delays, etc, even if kernel doesn't use it)    hal_ppc40x_clock_initialize(CYGNUM_HAL_RTC_PERIOD);#ifdef CYGPKG_IO_PCI    hal_ppc405_pci_init();#endif}//--------------------------------------------------------------------------// Variant specific idle thread action.boolhal_variant_idle_thread_action( cyg_uint32 count ){    // Let architecture idle thread action run    return true;}//---------------------------------------------------------------------------// Use MMU resources to map memory regions.  // Takes and returns an int used to ID the MMU resource to use. This ID// is increased as resources are used and should be used for subsequent// invocations.//// The PPC4xx CPUs do not have BATs. Fortunately we don't currently// use the MMU, so we can simulate BATs by using the TLBs.intcyg_hal_map_memory (int id, CYG_ADDRESS virt, CYG_ADDRESS phys,                     cyg_int32 size, cyg_uint8 flags){    cyg_uint32 epn, rpn;    int sv, lv, max_tlbs;    // There are 64 TLBs.    max_tlbs = 64;    // May need to use more than one slot since the TLB can only    // map 16MB max.    while (size > 0) {        // Use the smallest "size" value which is big enough (round up)        for (sv = 0, lv = 0x400;  sv < 7;  sv++, lv <<= 2) {            if (lv >= size) break;                }        // Note: the process ID comes from the PID register (always 0)        epn = (virt & M_EPN_EPNMASK) | M_EPN_EV | M_EPN_SIZE(sv);        rpn = (phys & M_RPN_RPNMASK) | M_RPN_EX | M_RPN_WR;        if (flags & CYGARC_MEMDESC_CI) {            rpn |= M_RPN_I;        }#ifdef CYGSEM_HAL_DCACHE_STARTUP_MODE_WRITETHRU        // Only for cache-enabled regions        else {            rpn |= M_RPN_W;        }#endif        if (flags & CYGARC_MEMDESC_GUARDED)             rpn |= M_RPN_G;        CYGARC_TLBWE(id, epn, rpn);        id++;        size -= lv;        virt += lv;        phys += lv;    }    return id;}// Initialize MMU to a sane (NOP) state.//// Initialize TLBs with 0, Valid bits unset.voidcyg_hal_clear_MMU (void){    cyg_uint32 tlbhi = 0;    cyg_uint32 tlblo = 0;    int id, max_tlbs;    // There are 64 TLBs.    max_tlbs = 64;    CYGARC_MTSPR (SPR_PID, 0);    for (id = 0; id < max_tlbs; id++) {        CYGARC_TLBWE(id, tlbhi, tlblo);    }}//--------------------------------------------------------------------------// Clock control - use the programmable (variable period) timerstatic cyg_uint32 _period;extern cyg_uint32 _hold_tcr;  // Shadow of TCR register which can't be readvoid hal_ppc40x_clock_initialize(cyg_uint32 period){    cyg_uint32 tcr;        // Enable auto-reload    CYGARC_MFSPR(SPR_TCR, tcr);    tcr = _hold_tcr;    tcr |= TCR_ARE;    CYGARC_MTSPR(SPR_TCR, tcr);    _hold_tcr = tcr;    // Set up the counter register    _period = period;    CYGARC_MTSPR(SPR_PIT, period);}// Returns the number of clocks since the last interruptexternC void hal_ppc40x_clock_read(cyg_uint32 *val){    cyg_uint32 cur_val;    CYGARC_MFSPR(SPR_PIT, cur_val);    *val = _period - cur_val;}externC void hal_ppc40x_clock_reset(cyg_uint32 vector, cyg_uint32 period){    hal_ppc40x_clock_initialize(period);}//// Delay for the specified number of microseconds.// Assumption: _period has been set already and corresponds to the// system clock frequency, normally 10ms.//externC void hal_ppc40x_delay_us(int us){    cyg_uint32 delay_period, delay, diff;    cyg_uint32 pit_val1, pit_val2;    delay_period = (_period * us) / 10000;    delay_period = ((_period / 10000) * us);    delay = 0;    CYGARC_MFSPR(SPR_PIT, pit_val1);    while (delay < delay_period) {        // Wait for clock to "tick"        while (true) {            CYGARC_MFSPR(SPR_PIT, pit_val2);            if (pit_val1 != pit_val2) break;        }        // The counter ticks down        if (pit_val2 < pit_val1) {            diff = pit_val1 - pit_val2;        } else {            diff = (_period - pit_val2) + pit_val1;        }        delay += diff;                pit_val1 = pit_val2;    }}#if defined(CYGHWR_HAL_POWERPC_PPC4XX_405) || defined(CYGHWR_HAL_POWERPC_PPC4XX_405GP)//----------------------------------------------------------------------// I2C Supportstatic voidhal_ppc405_i2c_init(void){    HAL_WRITE_UINT8(IIC0_CLKDIV, 6);  // 66MHz    HAL_WRITE_UINT8(IIC0_STS, (IIC0_STS_SCMP|IIC0_STS_IRQA));    HAL_WRITE_UINT8(IIC0_LMADR, 0);  // Clear interface    HAL_WRITE_UINT8(IIC0_HMADR, 0);    HAL_WRITE_UINT8(IIC0_LSADR, 0);    HAL_WRITE_UINT8(IIC0_HSADR, 0);    HAL_WRITE_UINT8(IIC0_EXTSTS, (IIC0_EXTSTS_IRQP|IIC0_EXTSTS_IRQD));    HAL_WRITE_UINT8(IIC0_MDCNTL, (IIC0_MDCNTL_FSDB|IIC0_MDCNTL_FMDB|IIC0_MDCNTL_EUBS));}externC boolhal_ppc405_i2c_put_bytes(int addr, cyg_uint8 *val, int len){    cyg_uint8 stat, extstat, xfrcnt, cmd, size;    int i, j;    // The hardware can only move up to 4 bytes in a single operation    // This code breaks the request down into chunks of up to 4 bytes    // and checks the status after each chunk.    // Note: the actual device may impose additional size restrictions,    // e.g. some EEPROM devices may limit a single write to 32 bytes.    for (i = 0;  i < len;  i += size) {        HAL_WRITE_UINT8(IIC0_STS, (IIC0_STS_SCMP|IIC0_STS_IRQA));        HAL_WRITE_UINT8(IIC0_EXTSTS, (IIC0_EXTSTS_IRQP|IIC0_EXTSTS_IRQD));        HAL_WRITE_UINT8(IIC0_MDCNTL, (IIC0_MDCNTL_FSDB|IIC0_MDCNTL_FMDB));        cmd = IIC0_CNTL_RW_WRITE|IIC0_CNTL_PT;        size = (len - i);        if (size > 4) {            size = 4;            cmd |= IIC0_CNTL_CHT;        }        cmd |= ((size-1)<<IIC0_CNTL_TCT_SHIFT);        for (j = 0;  j < size;  j++) {            HAL_WRITE_UINT8(IIC0_MDBUF, val[i+j]);        }        HAL_WRITE_UINT8(IIC0_LMADR, addr);        HAL_WRITE_UINT8(IIC0_CNTL, cmd);        while (true) {            CYGACC_CALL_IF_DELAY_US(10);   // 10us            HAL_READ_UINT8(IIC0_STS, stat);            if ((stat & IIC0_STS_PT) == 0) {                if ((stat & IIC0_STS_ERR) != 0) {                    // Some sort of error                    HAL_READ_UINT8(IIC0_EXTSTS, extstat);                                    HAL_READ_UINT8(IIC0_XFRCNT, xfrcnt);                                    HAL_WRITE_UINT8(IIC0_EXTSTS, extstat);                                    HAL_WRITE_UINT8(IIC0_MDCNTL, (IIC0_MDCNTL_FSDB|IIC0_MDCNTL_FMDB));                    HAL_WRITE_UINT8(IIC0_STS, (IIC0_STS_SCMP|IIC0_STS_IRQA));                    diag_printf("%s addr: %x, len: %d, err: %x/%x, count: %d, cmd: %x\n",                                 __FUNCTION__, addr, len, stat, extstat, xfrcnt, cmd);                    diag_printf("buf: ");                    for (j = 0;  j < size;  j++) {                        diag_printf("0x%02x ", val[i+j]);                    }                    diag_printf("\n");                    return false;                }                break;            }        }    }    return true;}externC boolhal_ppc405_i2c_get_bytes(int addr, cyg_uint8 *val, int len){    cyg_uint8 stat, extstat, _val, cmd;    int i, j, size;    for (i = 0;  i < len;  i += size) {        cmd = IIC0_CNTL_RW_READ|IIC0_CNTL_PT;        size = (len - i);        if (size > 4) {            size = 4;            cmd |= IIC0_CNTL_CHT;        }        cmd |= ((size-1)<<IIC0_CNTL_TCT_SHIFT);        HAL_WRITE_UINT8(IIC0_LMADR, addr);        HAL_WRITE_UINT8(IIC0_CNTL, cmd);        while (true) {            CYGACC_CALL_IF_DELAY_US(10);   // 10us            HAL_READ_UINT8(IIC0_STS, stat);            if ((stat & IIC0_STS_PT) == 0) {                if ((stat & IIC0_STS_ERR) != 0) {                    // Some sort of error                    HAL_READ_UINT8(IIC0_EXTSTS, extstat);                                    HAL_WRITE_UINT8(IIC0_EXTSTS, extstat);                                    HAL_WRITE_UINT8(IIC0_MDCNTL, (IIC0_MDCNTL_FSDB|IIC0_MDCNTL_FMDB));                    HAL_WRITE_UINT8(IIC0_STS, (IIC0_STS_SCMP|IIC0_STS_IRQA));                    diag_printf("%s addr: %x, len: %d, err: %x/%x\n",                                 __FUNCTION__, addr, len, stat, extstat);                    return false;                }                break;            }        }        for (j = 0;  j < size;  j++) {            HAL_READ_UINT8(IIC0_MDBUF, _val);            val[i+j] = _val;        }    }    return true;}#endif // 405//--------------------------------------------------------------------------// End of var_misc.c

⌨️ 快捷键说明

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