提交 99922cdf 编写于 作者: B bernard.xiong

import lm3s, lpc2148/lpc2478, x86/qemu, AT91SAM7S/7X, s3c44b0, STM32F103ZE bsp

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@4 bbd45198-f89e-11dd-88c7-29a3b14d5316
上级 1d742733
/*
* File : at91sam7s.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Develop Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://openlab.rt-thread.com/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2006-08-23 Bernard first version
*/
#ifndef __AT91SAM7S_H__
#define __AT91SAM7S_H__
#ifdef __cplusplus
extern "C" {
#endif
#define AT91_REG *(volatile unsigned int *) /* Hardware register definition */
/* ========== Register definition for TC0 peripheral ========== */
#define AT91C_TC0_SR (AT91_REG(0xFFFA0020)) /* TC0 Status Register */
#define AT91C_TC0_RC (AT91_REG(0xFFFA001C)) /* TC0 Register C */
#define AT91C_TC0_RB (AT91_REG(0xFFFA0018)) /* TC0 Register B */
#define AT91C_TC0_CCR (AT91_REG(0xFFFA0000)) /* TC0 Channel Control Register */
#define AT91C_TC0_CMR (AT91_REG(0xFFFA0004)) /* TC0 Channel Mode Register (Capture Mode / Waveform Mode) */
#define AT91C_TC0_IER (AT91_REG(0xFFFA0024)) /* TC0 Interrupt Enable Register */
#define AT91C_TC0_RA (AT91_REG(0xFFFA0014)) /* TC0 Register A */
#define AT91C_TC0_IDR (AT91_REG(0xFFFA0028)) /* TC0 Interrupt Disable Register */
#define AT91C_TC0_CV (AT91_REG(0xFFFA0010)) /* TC0 Counter Value */
#define AT91C_TC0_IMR (AT91_REG(0xFFFA002C)) /* TC0 Interrupt Mask Register */
/* ========== Register definition for TC1 peripheral ========== */
#define AT91C_TC1_RB (AT91_REG(0xFFFA0058)) /* TC1 Register B */
#define AT91C_TC1_CCR (AT91_REG(0xFFFA0040)) /* TC1 Channel Control Register */
#define AT91C_TC1_IER (AT91_REG(0xFFFA0064)) /* TC1 Interrupt Enable Register */
#define AT91C_TC1_IDR (AT91_REG(0xFFFA0068)) /* TC1 Interrupt Disable Register */
#define AT91C_TC1_SR (AT91_REG(0xFFFA0060)) /* TC1 Status Register */
#define AT91C_TC1_CMR (AT91_REG(0xFFFA0044)) /* TC1 Channel Mode Register (Capture Mode / Waveform Mode) */
#define AT91C_TC1_RA (AT91_REG(0xFFFA0054)) /* TC1 Register A */
#define AT91C_TC1_RC (AT91_REG(0xFFFA005C)) /* TC1 Register C */
#define AT91C_TC1_IMR (AT91_REG(0xFFFA006C)) /* TC1 Interrupt Mask Register */
#define AT91C_TC1_CV (AT91_REG(0xFFFA0050)) /* TC1 Counter Value */
/* ========== Register definition for TC2 peripheral ========== */
#define AT91C_TC2_CMR (AT91_REG(0xFFFA0084)) /* TC2 Channel Mode Register (Capture Mode / Waveform Mode) */
#define AT91C_TC2_CCR (AT91_REG(0xFFFA0080)) /* TC2 Channel Control Register */
#define AT91C_TC2_CV (AT91_REG(0xFFFA0090)) /* TC2 Counter Value */
#define AT91C_TC2_RA (AT91_REG(0xFFFA0094)) /* TC2 Register A */
#define AT91C_TC2_RB (AT91_REG(0xFFFA0098)) /* TC2 Register B */
#define AT91C_TC2_IDR (AT91_REG(0xFFFA00A8)) /* TC2 Interrupt Disable Register */
#define AT91C_TC2_IMR (AT91_REG(0xFFFA00AC)) /* TC2 Interrupt Mask Register */
#define AT91C_TC2_RC (AT91_REG(0xFFFA009C)) /* TC2 Register C */
#define AT91C_TC2_IER (AT91_REG(0xFFFA00A4)) /* TC2 Interrupt Enable Register */
#define AT91C_TC2_SR (AT91_REG(0xFFFA00A0)) /* TC2 Status Register */
/* ========== Register definition for PITC peripheral ========== */
#define AT91C_PITC_PIVR (AT91_REG(0xFFFFFD38)) /* PITC Period Interval Value Register */
#define AT91C_PITC_PISR (AT91_REG(0xFFFFFD34)) /* PITC Period Interval Status Register */
#define AT91C_PITC_PIIR (AT91_REG(0xFFFFFD3C)) /* PITC Period Interval Image Register */
#define AT91C_PITC_PIMR (AT91_REG(0xFFFFFD30)) /* PITC Period Interval Mode Register */
/* ========== Register definition for UDP peripheral ========== */
#define AT91C_UDP_NUM (AT91_REG(0xFFFB0000)) /* UDP Frame Number Register */
#define AT91C_UDP_STAT (AT91_REG(0xFFFB0004)) /* UDP Global State Register */
#define AT91C_UDP_FADDR (AT91_REG(0xFFFB0008)) /* UDP Function Address Register */
#define AT91C_UDP_IER (AT91_REG(0xFFFB0010)) /* UDP Interrupt Enable Register */
#define AT91C_UDP_IDR (AT91_REG(0xFFFB0014)) /* UDP Interrupt Disable Register */
#define AT91C_UDP_IMR (AT91_REG(0xFFFB0018)) /* UDP Interrupt Mask Register */
#define AT91C_UDP_ISR (AT91_REG(0xFFFB001C)) /* UDP Interrupt Status Register */
#define AT91C_UDP_ICR (AT91_REG(0xFFFB0020)) /* UDP Interrupt Clear Register */
#define AT91C_UDP_RSTEP (AT91_REG(0xFFFB0028)) /* UDP Reset Endpoint Register */
#define AT91C_UDP_CSR0 (AT91_REG(0xFFFB0030)) /* UDP Endpoint Control and Status Register */
#define AT91C_UDP_CSR(n) (*(&AT91C_UDP_CSR0 + n))
#define AT91C_UDP_FDR0 (AT91_REG(0xFFFB0050)) /* UDP Endpoint FIFO Data Register */
#define AT91C_UDP_FDR(n) (*(&AT91C_UDP_FDR0 + n))
#define AT91C_UDP_TXVC (AT91_REG(0xFFFB0074)) /* UDP Transceiver Control Register */
/* ========== Register definition for US0 peripheral ========== */
#define AT91C_US0_CR (AT91_REG(0xFFFC0000)) /* US0 Control Register */
#define AT91C_US0_MR (AT91_REG(0xFFFC0004)) /* US0 Mode Register */
#define AT91C_US0_IER (AT91_REG(0xFFFC0008)) /* US0 Interrupt Enable Register */
#define AT91C_US0_IDR (AT91_REG(0xFFFC000C)) /* US0 Interrupt Disable Register */
#define AT91C_US0_IMR (AT91_REG(0xFFFC0010)) /* US0 Interrupt Mask Register */
#define AT91C_US0_CSR (AT91_REG(0xFFFC0014)) /* US0 Channel Status Register */
#define AT91C_US0_RHR (AT91_REG(0xFFFC0018)) /* US0 Receiver Holding Register */
#define AT91C_US0_THR (AT91_REG(0xFFFC001C)) /* US0 Transmitter Holding Register */
#define AT91C_US0_BRGR (AT91_REG(0xFFFC0020)) /* US0 Baud Rate Generator Register */
#define AT91C_US0_RTOR (AT91_REG(0xFFFC0024)) /* US0 Receiver Time-out Register */
#define AT91C_US0_TTGR (AT91_REG(0xFFFC0028)) /* US0 Transmitter Time-guard Register */
#define AT91C_US0_NER (AT91_REG(0xFFFC0044)) /* US0 Nb Errors Register */
#define AT91C_US0_FIDI (AT91_REG(0xFFFC0040)) /* US0 FI_DI_Ratio Register */
#define AT91C_US0_IF (AT91_REG(0xFFFC004C)) /* US0 IRDA_FILTER Register */
/* ========== Register definition for AIC peripheral ========== */
#define AT91C_AIC_SMR0 (AT91_REG(0xFFFFF000)) /* AIC Source Mode Register */
#define AT91C_AIC_SMR(n) (*(&AT91C_AIC_SMR0 + n))
#define AT91C_AIC_SVR0 (AT91_REG(0xFFFFF080)) /* AIC Source Vector Register */
#define AT91C_AIC_SVR(n) (*(&AT91C_AIC_SVR0 + n))
#define AT91C_AIC_IVR (AT91_REG(0xFFFFF100)) /* AIC Interrupt Vector Register */
#define AT91C_AIC_FVR (AT91_REG(0xFFFFF104)) /* AIC FIQ Vector Register */
#define AT91C_AIC_ISR (AT91_REG(0xFFFFF108)) /* AIC Interrupt Status Register */
#define AT91C_AIC_IPR (AT91_REG(0xFFFFF10C)) /* AIC Interrupt Pending Register */
#define AT91C_AIC_IMR (AT91_REG(0xFFFFF110)) /* AIC Interrupt Mask Register */
#define AT91C_AIC_CISR (AT91_REG(0xFFFFF114)) /* AIC Core Interrupt Status Register */
#define AT91C_AIC_IECR (AT91_REG(0xFFFFF120)) /* AIC Interrupt Enable Command Register */
#define AT91C_AIC_IDCR (AT91_REG(0xFFFFF124)) /* AIC Interrupt Disable Command Register */
#define AT91C_AIC_ICCR (AT91_REG(0xFFFFF128)) /* AIC Interrupt Clear Command Register */
#define AT91C_AIC_ISCR (AT91_REG(0xFFFFF12C)) /* AIC Interrupt Set Command Register */
#define AT91C_AIC_EOICR (AT91_REG(0xFFFFF130)) /* AIC End of Interrupt Command Register */
#define AT91C_AIC_SPU (AT91_REG(0xFFFFF134)) /* AIC Spurious Vector Register */
#define AT91C_AIC_DCR (AT91_REG(0xFFFFF138)) /* AIC Debug Control Register (Protect) */
#define AT91C_AIC_FFER (AT91_REG(0xFFFFF140)) /* AIC Fast Forcing Enable Register */
#define AT91C_AIC_FFDR (AT91_REG(0xFFFFF144)) /* AIC Fast Forcing Disable Register */
#define AT91C_AIC_FFSR (AT91_REG(0xFFFFF148)) /* AIC Fast Forcing Status Register */
/* ========== Register definition for DBGU peripheral ========== */
#define AT91C_DBGU_EXID (AT91_REG(0xFFFFF244)) /* DBGU Chip ID Extension Register */
#define AT91C_DBGU_BRGR (AT91_REG(0xFFFFF220)) /* DBGU Baud Rate Generator Register */
#define AT91C_DBGU_IDR (AT91_REG(0xFFFFF20C)) /* DBGU Interrupt Disable Register */
#define AT91C_DBGU_CSR (AT91_REG(0xFFFFF214)) /* DBGU Channel Status Register */
#define AT91C_DBGU_CIDR (AT91_REG(0xFFFFF240)) /* DBGU Chip ID Register */
#define AT91C_DBGU_MR (AT91_REG(0xFFFFF204)) /* DBGU Mode Register */
#define AT91C_DBGU_IMR (AT91_REG(0xFFFFF210)) /* DBGU Interrupt Mask Register */
#define AT91C_DBGU_CR (AT91_REG(0xFFFFF200)) /* DBGU Control Register */
#define AT91C_DBGU_FNTR (AT91_REG(0xFFFFF248)) /* DBGU Force NTRST Register */
#define AT91C_DBGU_THR (AT91_REG(0xFFFFF21C)) /* DBGU Transmitter Holding Register */
#define AT91C_DBGU_RHR (AT91_REG(0xFFFFF218)) /* DBGU Receiver Holding Register */
#define AT91C_DBGU_IER (AT91_REG(0xFFFFF208)) /* DBGU Interrupt Enable Register */
/* ========== Register definition for PIO peripheral ========== */
#define AT91C_PIO_ODR (AT91_REG(0xFFFFF414)) /* PIOA Output Disable Registerr */
#define AT91C_PIO_SODR (AT91_REG(0xFFFFF430)) /* PIOA Set Output Data Register */
#define AT91C_PIO_ISR (AT91_REG(0xFFFFF44C)) /* PIOA Interrupt Status Register */
#define AT91C_PIO_ABSR (AT91_REG(0xFFFFF478)) /* PIOA AB Select Status Register */
#define AT91C_PIO_IER (AT91_REG(0xFFFFF440)) /* PIOA Interrupt Enable Register */
#define AT91C_PIO_PPUDR (AT91_REG(0xFFFFF460)) /* PIOA Pull-up Disable Register */
#define AT91C_PIO_IMR (AT91_REG(0xFFFFF448)) /* PIOA Interrupt Mask Register */
#define AT91C_PIO_PER (AT91_REG(0xFFFFF400)) /* PIOA PIO Enable Register */
#define AT91C_PIO_IFDR (AT91_REG(0xFFFFF424)) /* PIOA Input Filter Disable Register */
#define AT91C_PIO_OWDR (AT91_REG(0xFFFFF4A4)) /* PIOA Output Write Disable Register */
#define AT91C_PIO_MDSR (AT91_REG(0xFFFFF458)) /* PIOA Multi-driver Status Register */
#define AT91C_PIO_IDR (AT91_REG(0xFFFFF444)) /* PIOA Interrupt Disable Register */
#define AT91C_PIO_ODSR (AT91_REG(0xFFFFF438)) /* PIOA Output Data Status Register */
#define AT91C_PIO_PPUSR (AT91_REG(0xFFFFF468)) /* PIOA Pull-up Status Register */
#define AT91C_PIO_OWSR (AT91_REG(0xFFFFF4A8)) /* PIOA Output Write Status Register */
#define AT91C_PIO_BSR (AT91_REG(0xFFFFF474)) /* PIOA Select B Register */
#define AT91C_PIO_OWER (AT91_REG(0xFFFFF4A0)) /* PIOA Output Write Enable Register */
#define AT91C_PIO_IFER (AT91_REG(0xFFFFF420)) /* PIOA Input Filter Enable Register */
#define AT91C_PIO_PDSR (AT91_REG(0xFFFFF43C)) /* PIOA Pin Data Status Register */
#define AT91C_PIO_PPUER (AT91_REG(0xFFFFF464)) /* PIOA Pull-up Enable Register */
#define AT91C_PIO_OSR (AT91_REG(0xFFFFF418)) /* PIOA Output Status Register */
#define AT91C_PIO_ASR (AT91_REG(0xFFFFF470)) /* PIOA Select A Register */
#define AT91C_PIO_MDDR (AT91_REG(0xFFFFF454)) /* PIOA Multi-driver Disable Register */
#define AT91C_PIO_CODR (AT91_REG(0xFFFFF434)) /* PIOA Clear Output Data Register */
#define AT91C_PIO_MDER (AT91_REG(0xFFFFF450)) /* PIOA Multi-driver Enable Register */
#define AT91C_PIO_PDR (AT91_REG(0xFFFFF404)) /* PIOA PIO Disable Register */
#define AT91C_PIO_IFSR (AT91_REG(0xFFFFF428)) /* PIOA Input Filter Status Register */
#define AT91C_PIO_OER (AT91_REG(0xFFFFF410)) /* PIOA Output Enable Register */
#define AT91C_PIO_PSR (AT91_REG(0xFFFFF408)) /* PIOA PIO Status Register */
// ========== Register definition for PIOA peripheral ==========
#define AT91C_PIOA_IMR (AT91_REG(0xFFFFF448)) // (PIOA) Interrupt Mask Register
#define AT91C_PIOA_IER (AT91_REG(0xFFFFF440)) // (PIOA) Interrupt Enable Register
#define AT91C_PIOA_OWDR (AT91_REG(0xFFFFF4A4)) // (PIOA) Output Write Disable Register
#define AT91C_PIOA_ISR (AT91_REG(0xFFFFF44C)) // (PIOA) Interrupt Status Register
#define AT91C_PIOA_PPUDR (AT91_REG(0xFFFFF460)) // (PIOA) Pull-up Disable Register
#define AT91C_PIOA_MDSR (AT91_REG(0xFFFFF458)) // (PIOA) Multi-driver Status Register
#define AT91C_PIOA_MDER (AT91_REG(0xFFFFF450)) // (PIOA) Multi-driver Enable Register
#define AT91C_PIOA_PER (AT91_REG(0xFFFFF400)) // (PIOA) PIO Enable Register
#define AT91C_PIOA_PSR (AT91_REG(0xFFFFF408)) // (PIOA) PIO Status Register
#define AT91C_PIOA_OER (AT91_REG(0xFFFFF410)) // (PIOA) Output Enable Register
#define AT91C_PIOA_BSR (AT91_REG(0xFFFFF474)) // (PIOA) Select B Register
#define AT91C_PIOA_PPUER (AT91_REG(0xFFFFF464)) // (PIOA) Pull-up Enable Register
#define AT91C_PIOA_MDDR (AT91_REG(0xFFFFF454)) // (PIOA) Multi-driver Disable Register
#define AT91C_PIOA_PDR (AT91_REG(0xFFFFF404)) // (PIOA) PIO Disable Register
#define AT91C_PIOA_ODR (AT91_REG(0xFFFFF414)) // (PIOA) Output Disable Registerr
#define AT91C_PIOA_IFDR (AT91_REG(0xFFFFF424)) // (PIOA) Input Filter Disable Register
#define AT91C_PIOA_ABSR (AT91_REG(0xFFFFF478)) // (PIOA) AB Select Status Register
#define AT91C_PIOA_ASR (AT91_REG(0xFFFFF470)) // (PIOA) Select A Register
#define AT91C_PIOA_PPUSR (AT91_REG(0xFFFFF468)) // (PIOA) Pull-up Status Register
#define AT91C_PIOA_ODSR (AT91_REG(0xFFFFF438)) // (PIOA) Output Data Status Register
#define AT91C_PIOA_SODR (AT91_REG(0xFFFFF430)) // (PIOA) Set Output Data Register
#define AT91C_PIOA_IFSR (AT91_REG(0xFFFFF428)) // (PIOA) Input Filter Status Register
#define AT91C_PIOA_IFER (AT91_REG(0xFFFFF420)) // (PIOA) Input Filter Enable Register
#define AT91C_PIOA_OSR (AT91_REG(0xFFFFF418)) // (PIOA) Output Status Register
#define AT91C_PIOA_IDR (AT91_REG(0xFFFFF444)) // (PIOA) Interrupt Disable Register
#define AT91C_PIOA_PDSR (AT91_REG(0xFFFFF43C)) // (PIOA) Pin Data Status Register
#define AT91C_PIOA_CODR (AT91_REG(0xFFFFF434)) // (PIOA) Clear Output Data Register
#define AT91C_PIOA_OWSR (AT91_REG(0xFFFFF4A8)) // (PIOA) Output Write Status Register
#define AT91C_PIOA_OWER (AT91_REG(0xFFFFF4A0)) // (PIOA) Output Write Enable Register
// ========== Register definition for PIOB peripheral ==========
#define AT91C_PIOB_OWSR (AT91_REG(0xFFFFF6A8)) // (PIOB) Output Write Status Register
#define AT91C_PIOB_PPUSR (AT91_REG(0xFFFFF668)) // (PIOB) Pull-up Status Register
#define AT91C_PIOB_PPUDR (AT91_REG(0xFFFFF660)) // (PIOB) Pull-up Disable Register
#define AT91C_PIOB_MDSR (AT91_REG(0xFFFFF658)) // (PIOB) Multi-driver Status Register
#define AT91C_PIOB_MDER (AT91_REG(0xFFFFF650)) // (PIOB) Multi-driver Enable Register
#define AT91C_PIOB_IMR (AT91_REG(0xFFFFF648)) // (PIOB) Interrupt Mask Register
#define AT91C_PIOB_OSR (AT91_REG(0xFFFFF618)) // (PIOB) Output Status Register
#define AT91C_PIOB_OER (AT91_REG(0xFFFFF610)) // (PIOB) Output Enable Register
#define AT91C_PIOB_PSR (AT91_REG(0xFFFFF608)) // (PIOB) PIO Status Register
#define AT91C_PIOB_PER (AT91_REG(0xFFFFF600)) // (PIOB) PIO Enable Register
#define AT91C_PIOB_BSR (AT91_REG(0xFFFFF674)) // (PIOB) Select B Register
#define AT91C_PIOB_PPUER (AT91_REG(0xFFFFF664)) // (PIOB) Pull-up Enable Register
#define AT91C_PIOB_IFDR (AT91_REG(0xFFFFF624)) // (PIOB) Input Filter Disable Register
#define AT91C_PIOB_ODR (AT91_REG(0xFFFFF614)) // (PIOB) Output Disable Registerr
#define AT91C_PIOB_ABSR (AT91_REG(0xFFFFF678)) // (PIOB) AB Select Status Register
#define AT91C_PIOB_ASR (AT91_REG(0xFFFFF670)) // (PIOB) Select A Register
#define AT91C_PIOB_IFER (AT91_REG(0xFFFFF620)) // (PIOB) Input Filter Enable Register
#define AT91C_PIOB_IFSR (AT91_REG(0xFFFFF628)) // (PIOB) Input Filter Status Register
#define AT91C_PIOB_SODR (AT91_REG(0xFFFFF630)) // (PIOB) Set Output Data Register
#define AT91C_PIOB_ODSR (AT91_REG(0xFFFFF638)) // (PIOB) Output Data Status Register
#define AT91C_PIOB_CODR (AT91_REG(0xFFFFF634)) // (PIOB) Clear Output Data Register
#define AT91C_PIOB_PDSR (AT91_REG(0xFFFFF63C)) // (PIOB) Pin Data Status Register
#define AT91C_PIOB_OWER (AT91_REG(0xFFFFF6A0)) // (PIOB) Output Write Enable Register
#define AT91C_PIOB_IER (AT91_REG(0xFFFFF640)) // (PIOB) Interrupt Enable Register
#define AT91C_PIOB_OWDR (AT91_REG(0xFFFFF6A4)) // (PIOB) Output Write Disable Register
#define AT91C_PIOB_MDDR (AT91_REG(0xFFFFF654)) // (PIOB) Multi-driver Disable Register
#define AT91C_PIOB_ISR (AT91_REG(0xFFFFF64C)) // (PIOB) Interrupt Status Register
#define AT91C_PIOB_IDR (AT91_REG(0xFFFFF644)) // (PIOB) Interrupt Disable Register
#define AT91C_PIOB_PDR (AT91_REG(0xFFFFF604)) // (PIOB) PIO Disable Register
/* ========== Register definition for PMC peripheral ========== */
#define AT91C_PMC_SCER (AT91_REG(0xFFFFFC00)) /* PMC System Clock Enable Register */
#define AT91C_PMC_SCDR (AT91_REG(0xFFFFFC04)) /* PMC System Clock Disable Register */
#define AT91C_PMC_SCSR (AT91_REG(0xFFFFFC08)) /* PMC System Clock Status Register */
#define AT91C_PMC_PCER (AT91_REG(0xFFFFFC10)) /* PMC Peripheral Clock Enable Register */
#define AT91C_PMC_PCDR (AT91_REG(0xFFFFFC14)) /* PMC Peripheral Clock Disable Register */
#define AT91C_PMC_PCSR (AT91_REG(0xFFFFFC18)) /* PMC Peripheral Clock Status Register */
#define AT91C_PMC_MOR (AT91_REG(0xFFFFFC20)) /* PMC Main Oscillator Register */
#define AT91C_PMC_MCFR (AT91_REG(0xFFFFFC24)) /* PMC Main Clock Frequency Register */
#define AT91C_PMC_PLLR (AT91_REG(0xFFFFFC2C)) /* PMC PLL Register */
#define AT91C_PMC_MCKR (AT91_REG(0xFFFFFC30)) /* PMC Master Clock Register */
#define AT91C_PMC_PCKR (AT91_REG(0xFFFFFC40)) /* PMC Programmable Clock Register */
#define AT91C_PMC_IER (AT91_REG(0xFFFFFC60)) /* PMC Interrupt Enable Register */
#define AT91C_PMC_IDR (AT91_REG(0xFFFFFC64)) /* PMC Interrupt Disable Register */
#define AT91C_PMC_SR (AT91_REG(0xFFFFFC68)) /* PMC Status Register */
#define AT91C_PMC_IMR (AT91_REG(0xFFFFFC6C)) /* PMC Interrupt Mask Register */
/******************************************************************************/
/* PERIPHERAL ID DEFINITIONS FOR AT91SAM7S64 */
/******************************************************************************/
#define AT91C_ID_FIQ 0 /* Advanced Interrupt Controller (FIQ) */
#define AT91C_ID_SYS 1 /* System Peripheral */
#define AT91C_ID_PIOA 2 /* Parallel IO Controller A */
#define AT91C_ID_PIOB 3 /* Parallel IO Controller B */
#define AT91C_ID_ADC 4 /* Analog-to-Digital Converter */
#define AT91C_ID_SPI 5 /* Serial Peripheral Interface */
#define AT91C_ID_US0 6 /* USART 0 */
#define AT91C_ID_US1 7 /* USART 1 */
#define AT91C_ID_SSC 8 /* Serial Synchronous Controller */
#define AT91C_ID_TWI 9 /* Two-Wire Interface */
#define AT91C_ID_PWMC 10 /* PWM Controller */
#define AT91C_ID_UDP 11 /* USB Device Port */
#define AT91C_ID_TC0 12 /* Timer Counter 0 */
#define AT91C_ID_TC1 13 /* Timer Counter 1 */
#define AT91C_ID_TC2 14 /* Timer Counter 2 */
#define AT91C_ID_15 15 /* Reserved */
#define AT91C_ID_16 16 /* Reserved */
#define AT91C_ID_17 17 /* Reserved */
#define AT91C_ID_18 18 /* Reserved */
#define AT91C_ID_19 19 /* Reserved */
#define AT91C_ID_20 20 /* Reserved */
#define AT91C_ID_21 21 /* Reserved */
#define AT91C_ID_22 22 /* Reserved */
#define AT91C_ID_23 23 /* Reserved */
#define AT91C_ID_24 24 /* Reserved */
#define AT91C_ID_25 25 /* Reserved */
#define AT91C_ID_26 26 /* Reserved */
#define AT91C_ID_27 27 /* Reserved */
#define AT91C_ID_28 28 /* Reserved */
#define AT91C_ID_29 29 /* Reserved */
#define AT91C_ID_IRQ0 30 /* Advanced Interrupt Controller (IRQ0) */
#define AT91C_ID_IRQ1 31 /* Advanced Interrupt Controller (IRQ1) */
#define AT91C_ALL_INT 0xC0007FF7 /* ALL VALID INTERRUPTS */
/*****************************/
/* CPU Mode */
/*****************************/
#define USERMODE 0x10
#define FIQMODE 0x11
#define IRQMODE 0x12
#define SVCMODE 0x13
#define ABORTMODE 0x17
#define UNDEFMODE 0x1b
#define MODEMASK 0x1f
#define NOINT 0xc0
#ifdef __cplusplus
}
#endif
#endif
/*
* File : context.S
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2006-03-13 Bernard first version
*/
#define NOINT 0xc0
/*
* rt_base_t rt_hw_interrupt_disable()/*
*/
.globl rt_hw_interrupt_disable
rt_hw_interrupt_disable:
mrs r0, cpsr
orr r1, r0, #NOINT
msr cpsr_c, r1
mov pc, lr
/*
* void rt_hw_interrupt_enable(rt_base_t level)/*
*/
.globl rt_hw_interrupt_enable
rt_hw_interrupt_enable:
msr cpsr, r0
mov pc, lr
/*
* void rt_hw_context_switch(rt_uint32 from, rt_uint32 to)/*
* r0 --> from
* r1 --> to
*/
.globl rt_hw_context_switch
rt_hw_context_switch:
stmfd sp!, {lr} /* push pc (lr should be pushed in place of PC) */
stmfd sp!, {r0-r12, lr} /* push lr & register file */
mrs r4, cpsr
stmfd sp!, {r4} /* push cpsr */
mrs r4, spsr
stmfd sp!, {r4} /* push spsr */
str sp, [r0] /* store sp in preempted tasks TCB */
ldr sp, [r1] /* get new task stack pointer */
ldmfd sp!, {r4} /* pop new task spsr */
msr spsr_cxsf, r4
ldmfd sp!, {r4} /* pop new task cpsr */
msr cpsr_cxsf, r4
ldmfd sp!, {r0-r12, lr, pc} /* pop new task r0-r12, lr & pc */
/*
* void rt_hw_context_switch_to(rt_uint32 to)/*
* r0 --> to
*/
.globl rt_hw_context_switch_to
rt_hw_context_switch_to:
ldr sp, [r0] /* get new task stack pointer */
ldmfd sp!, {r4} /* pop new task spsr */
msr spsr_cxsf, r4
ldmfd sp!, {r4} /* pop new task cpsr */
msr cpsr_cxsf, r4
ldmfd sp!, {r0-r12, lr, pc} /* pop new task r0-r12, lr & pc */
/*
* void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)/*
*/
.globl rt_thread_switch_interrput_flag
.globl rt_interrupt_from_thread
.globl rt_interrupt_to_thread
.globl rt_hw_context_switch_interrupt
rt_hw_context_switch_interrupt:
ldr r2, =rt_thread_switch_interrput_flag
ldr r3, [r2]
cmp r3, #1
beq _reswitch
mov r3, #1 /* set rt_thread_switch_interrput_flag to 1 */
str r3, [r2]
ldr r2, =rt_interrupt_from_thread /* set rt_interrupt_from_thread */
str r0, [r2]
_reswitch:
ldr r2, =rt_interrupt_to_thread /* set rt_interrupt_to_thread */
str r1, [r2]
mov pc, lr
;/*
; * File : context_rvds.S
; * This file is part of RT-Thread RTOS
; * COPYRIGHT (C) 2006, RT-Thread Development Team
; *
; * The license and distribution terms for this file may be
; * found in the file LICENSE in this distribution or at
; * http://www.rt-thread.org/license/LICENSE
; *
; * Change Logs:
; * Date Author Notes
; * 2009-01-20 Bernard first version
; */
NOINT EQU 0xc0 ; disable interrupt in psr
AREA |.text|, CODE, READONLY, ALIGN=2
ARM
REQUIRE8
PRESERVE8
;/*
; * rt_base_t rt_hw_interrupt_disable();
; */
rt_hw_interrupt_disable PROC
EXPORT rt_hw_interrupt_disable
MRS r0, cpsr
ORR r1, r0, #NOINT
MSR cpsr_c, r1
BX lr
ENDP
;/*
; * void rt_hw_interrupt_enable(rt_base_t level);
; */
rt_hw_interrupt_enable PROC
EXPORT rt_hw_interrupt_enable
MSR cpsr_c, r0
BX lr
ENDP
;/*
; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
; * r0 --> from
; * r1 --> to
; */
rt_hw_context_switch PROC
EXPORT rt_hw_context_switch
STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC)
STMFD sp!, {r0-r12, lr} ; push lr & register file
MRS r4, cpsr
STMFD sp!, {r4} ; push cpsr
MRS r4, spsr
STMFD sp!, {r4} ; push spsr
STR sp, [r0] ; store sp in preempted tasks TCB
LDR sp, [r1] ; get new task stack pointer
LDMFD sp!, {r4} ; pop new task spsr
MSR spsr_cxsf, r4
LDMFD sp!, {r4} ; pop new task cpsr
MSR cpsr_cxsf, r4
LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc
ENDP
;/*
; * void rt_hw_context_switch_to(rt_uint32 to);
; * r0 --> to
; */
rt_hw_context_switch_to PROC
EXPORT rt_hw_context_switch_to
LDR sp, [r0] ; get new task stack pointer
LDMFD sp!, {r4} ; pop new task spsr
MSR spsr_cxsf, r4
LDMFD sp!, {r4} ; pop new task cpsr
MSR cpsr_cxsf, r4
LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc
ENDP
;/*
; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
; */
IMPORT rt_thread_switch_interrput_flag
IMPORT rt_interrupt_from_thread
IMPORT rt_interrupt_to_thread
rt_hw_context_switch_interrupt PROC
EXPORT rt_hw_context_switch_interrupt
LDR r2, =rt_thread_switch_interrput_flag
LDR r3, [r2]
CMP r3, #1
BEQ _reswitch
MOV r3, #1 ; set rt_thread_switch_interrput_flag to 1
STR r3, [r2]
LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread
STR r0, [r2]
_reswitch
LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread
STR r1, [r2]
BX lr
ENDP
END
\ No newline at end of file
/*
* File : cpu.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Develop Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2006-08-23 Bernard first version
*/
#include <rtthread.h>
#include "AT91SAM7S.h"
/**
* @addtogroup AT91SAM7
*/
/*@{*/
/**
* this function will reset CPU
*
*/
void rt_hw_cpu_reset()
{
}
/**
* this function will shutdown CPU
*
*/
void rt_hw_cpu_shutdown()
{
rt_kprintf("shutdown...\n");
while (1);
}
/*@}*/
/*
* File : trap.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://openlab.rt-thread.com/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2006-08-23 Bernard first version
*/
#include <rtthread.h>
#include "AT91SAM7S.h"
#define MAX_HANDLERS 32
extern rt_uint32_t rt_interrupt_nest;
rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
rt_uint32_t rt_thread_switch_interrput_flag;
/**
* @addtogroup AT91SAM7
*/
/*@{*/
void rt_hw_interrupt_handler(int vector)
{
rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
}
/**
* This function will initialize hardware interrupt
*/
void rt_hw_interrupt_init()
{
rt_base_t index;
for (index = 0; index < MAX_HANDLERS; index ++)
{
AT91C_AIC_SVR(index) = (rt_uint32_t)rt_hw_interrupt_handler;
}
/* init interrupt nest, and context in thread sp */
rt_interrupt_nest = 0;
rt_interrupt_from_thread = 0;
rt_interrupt_to_thread = 0;
rt_thread_switch_interrput_flag = 0;
}
/**
* This function will mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_mask(int vector)
{
/* disable interrupt */
AT91C_AIC_IDCR = 1 << vector;
/* clear interrupt */
AT91C_AIC_ICCR = 1 << vector;
}
/**
* This function will un-mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_umask(int vector)
{
AT91C_AIC_IECR = 1 << vector;
}
/**
* This function will install a interrupt service routine to a interrupt.
* @param vector the interrupt number
* @param new_handler the interrupt service routine to be installed
* @param old_handler the old interrupt service routine
*/
void rt_hw_interrupt_install(int vector, rt_isr_handler_t new_handler, rt_isr_handler_t *old_handler)
{
if(vector >= 0 && vector < MAX_HANDLERS)
{
if (*old_handler != RT_NULL) *old_handler = (rt_isr_handler_t)AT91C_AIC_SVR(vector);
if (new_handler != RT_NULL) AT91C_AIC_SVR(vector) = (rt_uint32_t)new_handler;
}
}
/*@}*/
/*
* File : serial.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://openlab.rt-thread.com/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2006-08-23 Bernard first version
* 2009-05-14 Bernard add RT-THread device interface
*/
#include <rthw.h>
#include <rtthread.h>
#include "AT91SAM7S.h"
#include "serial.h"
/**
* @addtogroup AT91SAM7
*/
/*@{*/
typedef volatile rt_uint32_t REG32;
struct rt_at91serial_hw
{
REG32 US_CR; // Control Register
REG32 US_MR; // Mode Register
REG32 US_IER; // Interrupt Enable Register
REG32 US_IDR; // Interrupt Disable Register
REG32 US_IMR; // Interrupt Mask Register
REG32 US_CSR; // Channel Status Register
REG32 US_RHR; // Receiver Holding Register
REG32 US_THR; // Transmitter Holding Register
REG32 US_BRGR; // Baud Rate Generator Register
REG32 US_RTOR; // Receiver Time-out Register
REG32 US_TTGR; // Transmitter Time-guard Register
REG32 Reserved0[5]; //
REG32 US_FIDI; // FI_DI_Ratio Register
REG32 US_NER; // Nb Errors Register
REG32 Reserved1[1]; //
REG32 US_IF; // IRDA_FILTER Register
REG32 Reserved2[44]; //
REG32 US_RPR; // Receive Pointer Register
REG32 US_RCR; // Receive Counter Register
REG32 US_TPR; // Transmit Pointer Register
REG32 US_TCR; // Transmit Counter Register
REG32 US_RNPR; // Receive Next Pointer Register
REG32 US_RNCR; // Receive Next Counter Register
REG32 US_TNPR; // Transmit Next Pointer Register
REG32 US_TNCR; // Transmit Next Counter Register
REG32 US_PTCR; // PDC Transfer Control Register
REG32 US_PTSR; // PDC Transfer Status Register
};
struct rt_at91serial
{
struct rt_device parent;
struct rt_at91serial_hw* hw_base;
rt_uint16_t peripheral_id;
rt_uint32_t baudrate;
/* reception field */
rt_uint16_t save_index, read_index;
rt_uint8_t rx_buffer[RT_UART_RX_BUFFER_SIZE];
};
#ifdef RT_USING_UART1
struct rt_at91serial serial1;
#endif
#ifdef RT_USING_UART2
struct rt_at91serial serial2;
#endif
static void rt_hw_serial_isr(int irqno)
{
rt_base_t level;
struct rt_device* device;
struct rt_at91serial* serial = RT_NULL;
if (irqno == AT91C_ID_US0)
{
#ifdef RT_USING_UART1
/* serial 1 */
serial = &serial1;
#endif
}
else if (irqno == AT91C_ID_US1)
{
#ifdef RT_USING_UART2
/* serial 2 */
serial = &serial2;
#endif
}
RT_ASSERT(serial != RT_NULL);
/* get generic device object */
device = (rt_device_t)serial;
/* disable interrupt */
level = rt_hw_interrupt_disable();
/* get received character */
serial->rx_buffer[serial->save_index] = serial->hw_base->US_RHR;
/* move to next position */
serial->save_index ++;
if (serial->save_index >= RT_UART_RX_BUFFER_SIZE)
serial->save_index = 0;
/* if the next position is read index, discard this 'read char' */
if (serial->save_index == serial->read_index)
{
serial->read_index ++;
if (serial->read_index >= RT_UART_RX_BUFFER_SIZE)
serial->read_index = 0;
}
/* enable interrupt */
rt_hw_interrupt_enable(level);
/* indicate to upper layer application */
if (device->rx_indicate != RT_NULL)
device->rx_indicate(device, 1);
/* ack interrupt */
AT91C_AIC_EOICR = 1;
}
static rt_err_t rt_serial_init (rt_device_t dev)
{
rt_uint32_t bd;
struct rt_at91serial* serial = (struct rt_at91serial*) dev;
RT_ASSERT(serial != RT_NULL);
/* must be US0 or US1 */
RT_ASSERT((serial->peripheral_id != AT91C_ID_US0) &&
(serial->peripheral_id != AT91C_ID_US1));
/* Enable Clock for USART */
AT91C_PMC_PCER = 1 << serial->peripheral_id;
/* Enable RxD0 and TxDO Pin */
if (serial->peripheral_id == AT91C_ID_US0)
{
/* set pinmux */
AT91C_PIO_PDR = (1 << 5) | (1 << 6);
}
else if (serial->peripheral_id == AT91C_ID_US1)
{
/* set pinmux */
AT91C_PIO_PDR = (1 << 21) | (1 << 22);
}
serial->hw_base->US_CR = AT91C_US_RSTRX | /* Reset Receiver */
AT91C_US_RSTTX | /* Reset Transmitter */
AT91C_US_RXDIS | /* Receiver Disable */
AT91C_US_TXDIS; /* Transmitter Disable */
serial->hw_base->US_MR = AT91C_US_USMODE_NORMAL | /* Normal Mode */
AT91C_US_CLKS_CLOCK | /* Clock = MCK */
AT91C_US_CHRL_8_BITS | /* 8-bit Data */
AT91C_US_PAR_NONE | /* No Parity */
AT91C_US_NBSTOP_1_BIT; /* 1 Stop Bit */
/* set baud rate divisor */
bd = ((MCK*10)/(serial->baudrate * 16));
if ((bd % 10) >= 5) bd = (bd / 10) + 1;
else bd /= 10;
serial->hw_base->US_BRGR = bd;
serial->hw_base->US_CR = AT91C_US_RXEN | /* Receiver Enable */
AT91C_US_TXEN; /* Transmitter Enable */
/* reset rx index */
serial->save_index = 0;
serial->read_index = 0;
/* reset rx buffer */
rt_memset(serial->rx_buffer, 0, RT_UART_RX_BUFFER_SIZE);
return RT_EOK;
}
static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag)
{
struct rt_at91serial *serial = (struct rt_at91serial*)dev;
RT_ASSERT(serial != RT_NULL);
if (dev->flag & RT_DEVICE_FLAG_INT_RX)
{
/* enable UART rx interrupt */
serial->hw_base->US_IER = 1 << 0; /* RxReady interrupt */
serial->hw_base->US_IMR |= 1 << 0; /* umask RxReady interrupt */
/* install UART handler */
rt_hw_interrupt_install(serial->peripheral_id, rt_hw_serial_isr, RT_NULL);
AT91C_AIC_SMR(serial->peripheral_id) = 5 | (0x01 << 5);
rt_hw_interrupt_umask(serial->peripheral_id);
}
return RT_EOK;
}
static rt_err_t rt_serial_close(rt_device_t dev)
{
struct rt_at91serial *serial = (struct rt_at91serial*)dev;
RT_ASSERT(serial != RT_NULL);
if (dev->flag & RT_DEVICE_FLAG_INT_RX)
{
/* disable interrupt */
serial->hw_base->US_IDR = 1 << 0; /* RxReady interrupt */
serial->hw_base->US_IMR &= ~(1 << 0); /* mask RxReady interrupt */
}
return RT_EOK;
}
static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
rt_uint8_t* ptr;
struct rt_at91serial *serial = (struct rt_at91serial*)dev;
RT_ASSERT(serial != RT_NULL);
/* point to buffer */
ptr = (rt_uint8_t*) buffer;
if (dev->flag & RT_DEVICE_FLAG_INT_RX)
{
while (size)
{
/* interrupt receive */
rt_base_t level;
/* disable interrupt */
level = rt_hw_interrupt_disable();
if (serial->read_index != serial->save_index)
{
*ptr = serial->rx_buffer[serial->read_index];
serial->read_index ++;
if (serial->read_index >= RT_UART_RX_BUFFER_SIZE)
serial->read_index = 0;
}
else
{
/* no data in rx buffer */
/* enable interrupt */
rt_hw_interrupt_enable(level);
break;
}
/* enable interrupt */
rt_hw_interrupt_enable(level);
ptr ++; size --;
}
return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
}
else if (dev->flag & RT_DEVICE_FLAG_DMA_RX)
{
/* not support right now */
RT_ASSERT(0);
}
else
{
/* poll mode */
while (size)
{
/* Wait for Full Rx Buffer */
while (!(serial->hw_base->US_CSR & AT91C_US_RXRDY));
/* Read Character */
*ptr = serial->hw_base->US_RHR;
ptr ++;
size --;
}
return (rt_size_t)ptr - (rt_size_t)buffer;
}
return 0;
}
static rt_size_t rt_serial_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
rt_uint8_t* ptr;
struct rt_at91serial *serial = (struct rt_at91serial*)dev;
RT_ASSERT(serial != RT_NULL);
ptr = (rt_uint8_t*) buffer;
if (dev->open_flag & RT_DEVICE_OFLAG_WRONLY)
{
if (dev->flag & RT_DEVICE_FLAG_STREAM)
{
/* it's a stream mode device */
while (size)
{
/* stream mode */
if (*ptr == '\n')
{
while (!(serial->hw_base->US_CSR & AT91C_US_TXRDY));
serial->hw_base->US_THR = '\r';
}
/* Wait for Empty Tx Buffer */
while (!(serial->hw_base->US_CSR & AT91C_US_TXRDY));
/* Transmit Character */
serial->hw_base->US_THR = *ptr;
ptr ++; size --;
}
}
else
{
while (size)
{
/* Wait for Empty Tx Buffer */
while (!(serial->hw_base->US_CSR & AT91C_US_TXRDY));
/* Transmit Character */
serial->hw_base->US_THR = *ptr;
ptr ++; size --;
}
}
}
return (rt_size_t)ptr - (rt_size_t)buffer;
}
static rt_err_t rt_serial_control (rt_device_t dev, rt_uint8_t cmd, void *args)
{
return RT_EOK;
}
rt_err_t rt_hw_serial_init()
{
rt_device_t device;
#ifdef RT_USING_UART1
device = (rt_device_t) &serial1;
/* init serial device private data */
serial1.hw_base = (struct rt_at91serial_hw*)AT91C_BASE_US0;
serial1.peripheral_id = AT91C_ID_US0;
serial1.baudrate = 115200;
/* set device virtual interface */
device->init = rt_serial_init;
device->open = rt_serial_open;
device->close = rt_serial_close;
device->read = rt_serial_read;
device->write = rt_serial_write;
device->control = rt_serial_control;
/* register uart1 on device subsystem */
rt_device_register(device, "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
#endif
#ifdef RT_USING_UART2
device = (rt_device_t) &serial2;
serial2.hw_base = (struct rt_at91serial_hw*)AT91C_BASE_US1;
serial2.peripheral_id = AT91C_ID_US1;
serial2.baudrate = 115200;
/* set device virtual interface */
device->init = rt_serial_init;
device->open = rt_serial_open;
device->close = rt_serial_close;
device->read = rt_serial_read;
device->write = rt_serial_write;
device->control = rt_serial_control;
/* register uart2 on device subsystem */
rt_device_register(device, "uart2", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
#endif
return RT_EOK;
}
/*@}*/
#ifndef __RT_SERIAL_H__
#define __RT_SERIAL_H__
#ifndef AT91C_BASE_US0
#define AT91C_BASE_US0 (0xFFFC0000) // (US0) Base Address
#endif
#ifndef AT91C_BASE_US1
#define AT91C_BASE_US1 (0xFFFC4000) // (US1) Base Address
#endif
#define AT91C_US_RXRDY ((unsigned int) 0x1 << 0) /* US RXRDY Interrupt */
#define AT91C_US_TXRDY ((unsigned int) 0x1 << 1) /* US TXRDY Interrupt */
#define AT91C_US_RSTRX ((unsigned int) 0x1 << 2) /* US Reset Receiver */
#define AT91C_US_RSTTX ((unsigned int) 0x1 << 3) /* US Reset Transmitter */
#define AT91C_US_RXEN ((unsigned int) 0x1 << 4) /* US Receiver Enable */
#define AT91C_US_RXDIS ((unsigned int) 0x1 << 5) /* US Receiver Disable */
#define AT91C_US_TXEN ((unsigned int) 0x1 << 6) /* US Transmitter Enable */
#define AT91C_US_TXDIS ((unsigned int) 0x1 << 7) /* US Transmitter Disable */
#define AT91C_US_RSTSTA ((unsigned int) 0x1 << 8) /* US Reset Status Bits */
#define AT91C_US_USMODE_NORMAL ((unsigned int) 0x0) /* USAR) Normal */
#define AT91C_US_USMODE_RS485 ((unsigned int) 0x1) /* USAR) RS485 */
#define AT91C_US_USMODE_HWHSH ((unsigned int) 0x2) /* USAR) Hardware Handshaking */
#define AT91C_US_USMODE_MODEM ((unsigned int) 0x3) /* USAR) Modem */
#define AT91C_US_USMODE_ISO7816_0 ((unsigned int) 0x4) /* USAR) ISO7816 protocol: T = 0 */
#define AT91C_US_USMODE_ISO7816_1 ((unsigned int) 0x6) /* USAR) ISO7816 protocol: T = 1 */
#define AT91C_US_USMODE_IRDA ((unsigned int) 0x8) /* USAR) IrDA */
#define AT91C_US_USMODE_SWHSH ((unsigned int) 0xC) /* USAR) Software Handshaking */
#define AT91C_US_CLKS_CLOCK ((unsigned int) 0x0 << 4) /* USAR) Clock */
#define AT91C_US_CLKS_FDIV1 ((unsigned int) 0x1 << 4) /* USAR) fdiv1 */
#define AT91C_US_CLKS_SLOW ((unsigned int) 0x2 << 4) /* USAR) slow_clock (ARM) */
#define AT91C_US_CLKS_EXT ((unsigned int) 0x3 << 4) /* USAR) External (SCK) */
#define AT91C_US_CHRL_5_BITS ((unsigned int) 0x0 << 6) /* USAR) Character Length: 5 bits */
#define AT91C_US_CHRL_6_BITS ((unsigned int) 0x1 << 6) /* USAR) Character Length: 6 bits */
#define AT91C_US_CHRL_7_BITS ((unsigned int) 0x2 << 6) /* USAR) Character Length: 7 bits */
#define AT91C_US_CHRL_8_BITS ((unsigned int) 0x3 << 6) /* USAR) Character Length: 8 bits */
#define AT91C_US_PAR_EVEN ((unsigned int) 0x0 << 9) /* DBGU Even Parity */
#define AT91C_US_PAR_ODD ((unsigned int) 0x1 << 9) /* DBGU Odd Parity */
#define AT91C_US_PAR_SPACE ((unsigned int) 0x2 << 9) /* DBGU Parity forced to 0 (Space) */
#define AT91C_US_PAR_MARK ((unsigned int) 0x3 << 9) /* DBGU Parity forced to 1 (Mark) */
#define AT91C_US_PAR_NONE ((unsigned int) 0x4 << 9) /* DBGU No Parity */
#define AT91C_US_PAR_MULTI_DROP ((unsigned int) 0x6 << 9) /* DBGU Multi-drop mode */
#define AT91C_US_NBSTOP_1_BIT ((unsigned int) 0x0 << 12) /* USART 1 stop bit */
#define AT91C_US_NBSTOP_15_BIT ((unsigned int) 0x1 << 12) /* USART Asynchronous (SYNC=0) 2 stop bits Synchronous (SYNC=1) 2 stop bits */
#define AT91C_US_NBSTOP_2_BIT ((unsigned int) 0x2 << 12) /* USART 2 stop bits */
#define MCK 48054857
#define BR 115200 /* Baud Rate */
#define BRD (MCK/16/BR) /* Baud Rate Divisor */
#endif
/*
* File : stack.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://openlab.rt-thread.com/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2006-08-23 Bernard the first version
*/
#include <rtthread.h>
#include "AT91SAM7S.h"
/**
* @addtogroup AT91SAM7
*/
/*@{*/
/**
* This function will initialize thread stack
*
* @param tentry the entry of thread
* @param parameter the parameter of entry
* @param stack_addr the beginning stack address
* @param texit the function will be called when thread exit
*
* @return stack address
*/
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
rt_uint8_t *stack_addr, void *texit)
{
unsigned long *stk;
stk = (unsigned long *)stack_addr;
*(stk) = (unsigned long)tentry; /* entry point */
*(--stk) = (unsigned long)texit; /* lr */
*(--stk) = 0; /* r12 */
*(--stk) = 0; /* r11 */
*(--stk) = 0; /* r10 */
*(--stk) = 0; /* r9 */
*(--stk) = 0; /* r8 */
*(--stk) = 0; /* r7 */
*(--stk) = 0; /* r6 */
*(--stk) = 0; /* r5 */
*(--stk) = 0; /* r4 */
*(--stk) = 0; /* r3 */
*(--stk) = 0; /* r2 */
*(--stk) = 0; /* r1 */
*(--stk) = (unsigned long)parameter; /* r0 : argument */
*(--stk) = SVCMODE; /* cpsr */
*(--stk) = SVCMODE; /* spsr */
/* return task's current stack address */
return (rt_uint8_t *)stk;
}
/*@}*/
/*
* File : start_gcc.S
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2006-08-31 Bernard first version
*/
/* Internal Memory Base Addresses */
.equ FLASH_BASE, 0x00100000
.equ RAM_BASE, 0x00200000
/* Stack Configuration */
.equ TOP_STACK, 0x00204000
.equ UND_STACK_SIZE, 0x00000100
.equ SVC_STACK_SIZE, 0x00000400
.equ ABT_STACK_SIZE, 0x00000100
.equ FIQ_STACK_SIZE, 0x00000100
.equ IRQ_STACK_SIZE, 0x00000100
.equ USR_STACK_SIZE, 0x00000004
/* ARM architecture definitions */
.equ MODE_USR, 0x10
.equ MODE_FIQ, 0x11
.equ MODE_IRQ, 0x12
.equ MODE_SVC, 0x13
.equ MODE_ABT, 0x17
.equ MODE_UND, 0x1B
.equ MODE_SYS, 0x1F
.equ I_BIT, 0x80 /* when this bit is set, IRQ is disabled */
.equ F_BIT, 0x40 /* when this bit is set, FIQ is disabled */
.section .init, "ax"
.code 32
.align 0
.globl _start
_start:
b reset
ldr pc, _vector_undef
ldr pc, _vector_swi
ldr pc, _vector_pabt
ldr pc, _vector_dabt
nop /* reserved vector */
ldr pc, _vector_irq
ldr pc, _vector_fiq
_vector_undef: .word vector_undef
_vector_swi: .word vector_swi
_vector_pabt: .word vector_pabt
_vector_dabt: .word vector_dabt
_vector_resv: .word vector_resv
_vector_irq: .word vector_irq
_vector_fiq: .word vector_fiq
/*
* rtthread bss start and end
* which are defined in linker script
*/
.globl _bss_start
_bss_start: .word __bss_start
.globl _bss_end
_bss_end: .word __bss_end
/* the system entry */
reset:
/* disable watchdog */
ldr r0, =0xFFFFFD40
ldr r1, =0x00008000
str r1, [r0, #0x04]
/* enable the main oscillator */
ldr r0, =0xFFFFFC00
ldr r1, =0x00000601
str r1, [r0, #0x20]
/* wait for main oscillator to stabilize */
moscs_loop:
ldr r2, [r0, #0x68]
ands r2, r2, #1
beq moscs_loop
/* set up the PLL */
ldr r1, =0x00191C05
str r1, [r0, #0x2C]
/* wait for PLL to lock */
pll_loop:
ldr r2, [r0, #0x68]
ands r2, r2, #0x04
beq pll_loop
/* select clock */
ldr r1, =0x00000007
str r1, [r0, #0x30]
/* setup stack for each mode */
ldr r0, =TOP_STACK
/* set stack */
/* undefined instruction mode */
msr cpsr_c, #MODE_UND|I_BIT|F_BIT
mov sp, r0
sub r0, r0, #UND_STACK_SIZE
/* abort mode */
msr cpsr_c, #MODE_ABT|I_BIT|F_BIT
mov sp, r0
sub r0, r0, #ABT_STACK_SIZE
/* FIQ mode */
msr cpsr_c, #MODE_FIQ|I_BIT|F_BIT
mov sp, r0
sub r0, r0, #FIQ_STACK_SIZE
/* IRQ mode */
msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT
mov sp, r0
sub r0, r0, #IRQ_STACK_SIZE
/* supervisor mode */
msr cpsr_c, #MODE_SVC
mov sp, r0
#ifdef __FLASH_BUILD__
/* Relocate .data section (Copy from ROM to RAM) */
ldr r1, =_etext
ldr r2, =_data
ldr r3, =_edata
data_loop:
cmp r2, r3
ldrlo r0, [r1], #4
strlo r0, [r2], #4
blo data_loop
#else
/* remap SRAM to 0x0000 */
ldr r0, =0xFFFFFF00
mov r1, #0x01
str r1, [r0]
#endif
/* mask all IRQs */
ldr r1, =0xFFFFF124
ldr r0, =0XFFFFFFFF
str r0, [r1]
/* start RT-Thread Kernel */
ldr pc, _rtthread_startup
_rtthread_startup: .word rtthread_startup
/* exception handlers */
vector_undef: b vector_undef
vector_swi : b vector_swi
vector_pabt : b vector_pabt
vector_dabt : b vector_dabt
vector_resv : b vector_resv
.globl rt_interrupt_enter
.globl rt_interrupt_leave
.globl rt_thread_switch_interrput_flag
.globl rt_interrupt_from_thread
.globl rt_interrupt_to_thread
vector_irq:
stmfd sp!, {r0-r12,lr}
bl rt_interrupt_enter
bl rt_hw_trap_irq
bl rt_interrupt_leave
/*
* if rt_thread_switch_interrput_flag set, jump to
* rt_hw_context_switch_interrupt_do and don't return
*/
ldr r0, =rt_thread_switch_interrput_flag
ldr r1, [r0]
cmp r1, #1
beq rt_hw_context_switch_interrupt_do
ldmfd sp!, {r0-r12,lr}
subs pc, lr, #4
vector_fiq:
stmfd sp!,{r0-r7,lr}
bl rt_hw_trap_fiq
ldmfd sp!,{r0-r7,lr}
subs pc,lr,#4
/*
* void rt_hw_context_switch_interrupt_do(rt_base_t flag)
*/
rt_hw_context_switch_interrupt_do:
mov r1, #0 /* clear flag */
str r1, [r0]
ldmfd sp!, {r0-r12,lr} /* reload saved registers */
stmfd sp!, {r0-r3} /* save r0-r3 */
mov r1, sp
add sp, sp, #16 /* restore sp */
sub r2, lr, #4 /* save old task's pc to r2 */
mrs r3, spsr /* disable interrupt */
orr r0, r3, #I_BIT|F_BIT
msr spsr_c, r0
ldr r0, =.+8 /* switch to interrupted task's stack */
movs pc, r0
stmfd sp!, {r2} /* push old task's pc */
stmfd sp!, {r4-r12,lr} /* push old task's lr,r12-r4 */
mov r4, r1 /* Special optimised code below */
mov r5, r3
ldmfd r4!, {r0-r3}
stmfd sp!, {r0-r3} /* push old task's r3-r0 */
stmfd sp!, {r5} /* push old task's psr */
mrs r4, spsr
stmfd sp!, {r4} /* push old task's spsr */
ldr r4, =rt_interrupt_from_thread
ldr r5, [r4]
str sp, [r5] /* store sp in preempted tasks's TCB */
ldr r6, =rt_interrupt_to_thread
ldr r6, [r6]
ldr sp, [r6] /* get new task's stack pointer */
ldmfd sp!, {r4} /* pop new task's spsr */
msr SPSR_cxsf, r4
ldmfd sp!, {r4} /* pop new task's psr */
msr CPSR_cxsf, r4
ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */
;/*****************************************************************************/
;/* SAM7.S: Startup file for Atmel AT91SAM7 device series */
;/*****************************************************************************/
;/* <<< Use Configuration Wizard in Context Menu >>> */
;/*****************************************************************************/
;/* This file is part of the uVision/ARM development tools. */
;/* Copyright (c) 2005-2006 Keil Software. All rights reserved. */
;/* This software may only be used under the terms of a valid, current, */
;/* end user licence from KEIL for a compatible version of KEIL software */
;/* development tools. Nothing else gives you the right to use this software. */
;/*****************************************************************************/
;/*
; * The SAM7.S code is executed after CPU Reset. This file may be
; * translated with the following SET symbols. In uVision these SET
; * symbols are entered under Options - ASM - Define.
; *
; * REMAP: when set the startup code remaps exception vectors from
; * on-chip RAM to address 0.
; *
; * RAM_INTVEC: when set the startup code copies exception vectors
; * from on-chip Flash to on-chip RAM.
; */
; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
Mode_USR EQU 0x10
Mode_FIQ EQU 0x11
Mode_IRQ EQU 0x12
Mode_SVC EQU 0x13
Mode_ABT EQU 0x17
Mode_UND EQU 0x1B
Mode_SYS EQU 0x1F
I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled
F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled
; Internal Memory Base Addresses
FLASH_BASE EQU 0x00100000
RAM_BASE EQU 0x00200000
;// <h> Stack Configuration (Stack Sizes in Bytes)
;// <o0> Undefined Mode <0x0-0xFFFFFFFF:8>
;// <o1> Supervisor Mode <0x0-0xFFFFFFFF:8>
;// <o2> Abort Mode <0x0-0xFFFFFFFF:8>
;// <o3> Fast Interrupt Mode <0x0-0xFFFFFFFF:8>
;// <o4> Interrupt Mode <0x0-0xFFFFFFFF:8>
;// <o5> User/System Mode <0x0-0xFFFFFFFF:8>
;// </h>
UND_Stack_Size EQU 0x00000000
SVC_Stack_Size EQU 0x00000100
ABT_Stack_Size EQU 0x00000000
FIQ_Stack_Size EQU 0x00000000
IRQ_Stack_Size EQU 0x00000100
USR_Stack_Size EQU 0x00000100
ISR_Stack_Size EQU (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
FIQ_Stack_Size + IRQ_Stack_Size)
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE USR_Stack_Size
__initial_sp SPACE ISR_Stack_Size
Stack_Top
;// <h> Heap Configuration
;// <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF>
;// </h>
Heap_Size EQU 0x00000000
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
; Reset Controller (RSTC) definitions
RSTC_BASE EQU 0xFFFFFD00 ; RSTC Base Address
RSTC_MR EQU 0x08 ; RSTC_MR Offset
;/*
;// <e> Reset Controller (RSTC)
;// <o1.0> URSTEN: User Reset Enable
;// <i> Enables NRST Pin to generate Reset
;// <o1.8..11> ERSTL: External Reset Length <0-15>
;// <i> External Reset Time in 2^(ERSTL+1) Slow Clock Cycles
;// </e>
;*/
RSTC_SETUP EQU 1
RSTC_MR_Val EQU 0xA5000401
; Embedded Flash Controller (EFC) definitions
EFC_BASE EQU 0xFFFFFF00 ; EFC Base Address
EFC0_FMR EQU 0x60 ; EFC0_FMR Offset
EFC1_FMR EQU 0x70 ; EFC1_FMR Offset
;// <e> Embedded Flash Controller 0 (EFC0)
;// <o1.16..23> FMCN: Flash Microsecond Cycle Number <0-255>
;// <i> Number of Master Clock Cycles in 1us
;// <o1.8..9> FWS: Flash Wait State
;// <0=> Read: 1 cycle / Write: 2 cycles
;// <1=> Read: 2 cycle / Write: 3 cycles
;// <2=> Read: 3 cycle / Write: 4 cycles
;// <3=> Read: 4 cycle / Write: 4 cycles
;// </e>
EFC0_SETUP EQU 1
EFC0_FMR_Val EQU 0x00320100
;// <e> Embedded Flash Controller 1 (EFC1)
;// <o1.16..23> FMCN: Flash Microsecond Cycle Number <0-255>
;// <i> Number of Master Clock Cycles in 1us
;// <o1.8..9> FWS: Flash Wait State
;// <0=> Read: 1 cycle / Write: 2 cycles
;// <1=> Read: 2 cycle / Write: 3 cycles
;// <2=> Read: 3 cycle / Write: 4 cycles
;// <3=> Read: 4 cycle / Write: 4 cycles
;// </e>
EFC1_SETUP EQU 0
EFC1_FMR_Val EQU 0x00320100
; Watchdog Timer (WDT) definitions
WDT_BASE EQU 0xFFFFFD40 ; WDT Base Address
WDT_MR EQU 0x04 ; WDT_MR Offset
;// <e> Watchdog Timer (WDT)
;// <o1.0..11> WDV: Watchdog Counter Value <0-4095>
;// <o1.16..27> WDD: Watchdog Delta Value <0-4095>
;// <o1.12> WDFIEN: Watchdog Fault Interrupt Enable
;// <o1.13> WDRSTEN: Watchdog Reset Enable
;// <o1.14> WDRPROC: Watchdog Reset Processor
;// <o1.28> WDDBGHLT: Watchdog Debug Halt
;// <o1.29> WDIDLEHLT: Watchdog Idle Halt
;// <o1.15> WDDIS: Watchdog Disable
;// </e>
WDT_SETUP EQU 1
WDT_MR_Val EQU 0x00008000
; Power Mangement Controller (PMC) definitions
PMC_BASE EQU 0xFFFFFC00 ; PMC Base Address
PMC_MOR EQU 0x20 ; PMC_MOR Offset
PMC_MCFR EQU 0x24 ; PMC_MCFR Offset
PMC_PLLR EQU 0x2C ; PMC_PLLR Offset
PMC_MCKR EQU 0x30 ; PMC_MCKR Offset
PMC_SR EQU 0x68 ; PMC_SR Offset
PMC_MOSCEN EQU (1<<0) ; Main Oscillator Enable
PMC_OSCBYPASS EQU (1<<1) ; Main Oscillator Bypass
PMC_OSCOUNT EQU (0xFF<<8) ; Main OScillator Start-up Time
PMC_DIV EQU (0xFF<<0) ; PLL Divider
PMC_PLLCOUNT EQU (0x3F<<8) ; PLL Lock Counter
PMC_OUT EQU (0x03<<14) ; PLL Clock Frequency Range
PMC_MUL EQU (0x7FF<<16) ; PLL Multiplier
PMC_USBDIV EQU (0x03<<28) ; USB Clock Divider
PMC_CSS EQU (3<<0) ; Clock Source Selection
PMC_PRES EQU (7<<2) ; Prescaler Selection
PMC_MOSCS EQU (1<<0) ; Main Oscillator Stable
PMC_LOCK EQU (1<<2) ; PLL Lock Status
PMC_MCKRDY EQU (1<<3) ; Master Clock Status
;// <e> Power Mangement Controller (PMC)
;// <h> Main Oscillator
;// <o1.0> MOSCEN: Main Oscillator Enable
;// <o1.1> OSCBYPASS: Oscillator Bypass
;// <o1.8..15> OSCCOUNT: Main Oscillator Startup Time <0-255>
;// </h>
;// <h> Phase Locked Loop (PLL)
;// <o2.0..7> DIV: PLL Divider <0-255>
;// <o2.16..26> MUL: PLL Multiplier <0-2047>
;// <i> PLL Output is multiplied by MUL+1
;// <o2.14..15> OUT: PLL Clock Frequency Range
;// <0=> 80..160MHz <1=> Reserved
;// <2=> 150..220MHz <3=> Reserved
;// <o2.8..13> PLLCOUNT: PLL Lock Counter <0-63>
;// <o2.28..29> USBDIV: USB Clock Divider
;// <0=> None <1=> 2 <2=> 4 <3=> Reserved
;// </h>
;// <o3.0..1> CSS: Clock Source Selection
;// <0=> Slow Clock
;// <1=> Main Clock
;// <2=> Reserved
;// <3=> PLL Clock
;// <o3.2..4> PRES: Prescaler
;// <0=> None
;// <1=> Clock / 2 <2=> Clock / 4
;// <3=> Clock / 8 <4=> Clock / 16
;// <5=> Clock / 32 <6=> Clock / 64
;// <7=> Reserved
;// </e>
PMC_SETUP EQU 1
PMC_MOR_Val EQU 0x00000601
PMC_PLLR_Val EQU 0x00191C05
PMC_MCKR_Val EQU 0x00000007
PRESERVE8
; Area Definition and Entry Point
; Startup Code must be linked first at Address at which it expects to run.
AREA RESET, CODE, READONLY
ARM
; Exception Vectors
; Mapped to Address 0.
; Absolute addressing mode must be used.
; Dummy Handlers are implemented as infinite loops which can be modified.
Vectors LDR PC,Reset_Addr
LDR PC,Undef_Addr
LDR PC,SWI_Addr
LDR PC,PAbt_Addr
LDR PC,DAbt_Addr
NOP ; Reserved Vector
LDR PC,IRQ_Addr
LDR PC,FIQ_Addr
Reset_Addr DCD Reset_Handler
Undef_Addr DCD Undef_Handler
SWI_Addr DCD SWI_Handler
PAbt_Addr DCD PAbt_Handler
DAbt_Addr DCD DAbt_Handler
DCD 0 ; Reserved Address
IRQ_Addr DCD IRQ_Handler
FIQ_Addr DCD FIQ_Handler
Undef_Handler B Undef_Handler
SWI_Handler B SWI_Handler
PAbt_Handler B PAbt_Handler
DAbt_Handler B DAbt_Handler
FIQ_Handler B FIQ_Handler
; Reset Handler
EXPORT Reset_Handler
Reset_Handler
; Setup RSTC
IF RSTC_SETUP != 0
LDR R0, =RSTC_BASE
LDR R1, =RSTC_MR_Val
STR R1, [R0, #RSTC_MR]
ENDIF
; Setup EFC0
IF EFC0_SETUP != 0
LDR R0, =EFC_BASE
LDR R1, =EFC0_FMR_Val
STR R1, [R0, #EFC0_FMR]
ENDIF
; Setup EFC1
IF EFC1_SETUP != 0
LDR R0, =EFC_BASE
LDR R1, =EFC1_FMR_Val
STR R1, [R0, #EFC1_FMR]
ENDIF
; Setup WDT
IF WDT_SETUP != 0
LDR R0, =WDT_BASE
LDR R1, =WDT_MR_Val
STR R1, [R0, #WDT_MR]
ENDIF
; Setup PMC
IF PMC_SETUP != 0
LDR R0, =PMC_BASE
; Setup Main Oscillator
LDR R1, =PMC_MOR_Val
STR R1, [R0, #PMC_MOR]
; Wait until Main Oscillator is stablilized
IF (PMC_MOR_Val:AND:PMC_MOSCEN) != 0
MOSCS_Loop LDR R2, [R0, #PMC_SR]
ANDS R2, R2, #PMC_MOSCS
BEQ MOSCS_Loop
ENDIF
; Setup the PLL
IF (PMC_PLLR_Val:AND:PMC_MUL) != 0
LDR R1, =PMC_PLLR_Val
STR R1, [R0, #PMC_PLLR]
; Wait until PLL is stabilized
PLL_Loop LDR R2, [R0, #PMC_SR]
ANDS R2, R2, #PMC_LOCK
BEQ PLL_Loop
ENDIF
; Select Clock
IF (PMC_MCKR_Val:AND:PMC_CSS) == 1 ; Main Clock Selected
LDR R1, =PMC_MCKR_Val
AND R1, #PMC_CSS
STR R1, [R0, #PMC_MCKR]
WAIT_Rdy1 LDR R2, [R0, #PMC_SR]
ANDS R2, R2, #PMC_MCKRDY
BEQ WAIT_Rdy1
LDR R1, =PMC_MCKR_Val
STR R1, [R0, #PMC_MCKR]
WAIT_Rdy2 LDR R2, [R0, #PMC_SR]
ANDS R2, R2, #PMC_MCKRDY
BEQ WAIT_Rdy2
ELIF (PMC_MCKR_Val:AND:PMC_CSS) == 3 ; PLL Clock Selected
LDR R1, =PMC_MCKR_Val
AND R1, #PMC_PRES
STR R1, [R0, #PMC_MCKR]
WAIT_Rdy1 LDR R2, [R0, #PMC_SR]
ANDS R2, R2, #PMC_MCKRDY
BEQ WAIT_Rdy1
LDR R1, =PMC_MCKR_Val
STR R1, [R0, #PMC_MCKR]
WAIT_Rdy2 LDR R2, [R0, #PMC_SR]
ANDS R2, R2, #PMC_MCKRDY
BEQ WAIT_Rdy2
ENDIF ; Select Clock
ENDIF ; PMC_SETUP
; Copy Exception Vectors to Internal RAM
IF :DEF:RAM_INTVEC
ADR R8, Vectors ; Source
LDR R9, =RAM_BASE ; Destination
LDMIA R8!, {R0-R7} ; Load Vectors
STMIA R9!, {R0-R7} ; Store Vectors
LDMIA R8!, {R0-R7} ; Load Handler Addresses
STMIA R9!, {R0-R7} ; Store Handler Addresses
ENDIF
; Remap on-chip RAM to address 0
MC_BASE EQU 0xFFFFFF00 ; MC Base Address
MC_RCR EQU 0x00 ; MC_RCR Offset
IF :DEF:REMAP
LDR R0, =MC_BASE
MOV R1, #1
STR R1, [R0, #MC_RCR] ; Remap
ENDIF
; Setup Stack for each mode
LDR R0, =Stack_Top
; Enter Undefined Instruction Mode and set its Stack Pointer
MSR CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #UND_Stack_Size
; Enter Abort Mode and set its Stack Pointer
MSR CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #ABT_Stack_Size
; Enter FIQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #FIQ_Stack_Size
; Enter IRQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #IRQ_Stack_Size
; Enter Supervisor Mode and set its Stack Pointer
MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #SVC_Stack_Size
; Enter User Mode and set its Stack Pointer
; MSR CPSR_c, #Mode_USR
IF :DEF:__MICROLIB
EXPORT __initial_sp
ELSE
MOV SP, R0
SUB SL, SP, #USR_Stack_Size
ENDIF
; Enter the C code
IMPORT __main
LDR R0, =__main
BX R0
IMPORT rt_interrupt_enter
IMPORT rt_interrupt_leave
IMPORT rt_thread_switch_interrput_flag
IMPORT rt_interrupt_from_thread
IMPORT rt_interrupt_to_thread
IMPORT rt_hw_trap_irq
IRQ_Handler PROC
EXPORT IRQ_Handler
STMFD sp!, {r0-r12,lr}
BL rt_interrupt_enter
BL rt_hw_trap_irq
BL rt_interrupt_leave
; if rt_thread_switch_interrput_flag set, jump to
; rt_hw_context_switch_interrupt_do and don't return
LDR r0, =rt_thread_switch_interrput_flag
LDR r1, [r0]
CMP r1, #1
BEQ rt_hw_context_switch_interrupt_do
LDMFD sp!, {r0-r12,lr}
SUBS pc, lr, #4
ENDP
; /*
; * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
; */
rt_hw_context_switch_interrupt_do PROC
EXPORT rt_hw_context_switch_interrupt_do
MOV r1, #0 ; clear flag
STR r1, [r0]
LDMFD sp!, {r0-r12,lr}; reload saved registers
STMFD sp!, {r0-r3} ; save r0-r3
MOV r1, sp
ADD sp, sp, #16 ; restore sp
SUB r2, lr, #4 ; save old task's pc to r2
MRS r3, spsr ; get cpsr of interrupt thread
; switch to SVC mode and no interrupt
MSR cpsr_c, #I_Bit|F_Bit|Mode_SVC
STMFD sp!, {r2} ; push old task's pc
STMFD sp!, {r4-r12,lr}; push old task's lr,r12-r4
MOV r4, r1 ; Special optimised code below
MOV r5, r3
LDMFD r4!, {r0-r3}
STMFD sp!, {r0-r3} ; push old task's r3-r0
STMFD sp!, {r5} ; push old task's cpsr
MRS r4, spsr
STMFD sp!, {r4} ; push old task's spsr
LDR r4, =rt_interrupt_from_thread
LDR r5, [r4]
STR sp, [r5] ; store sp in preempted tasks's TCB
LDR r6, =rt_interrupt_to_thread
LDR r6, [r6]
LDR sp, [r6] ; get new task's stack pointer
LDMFD sp!, {r4} ; pop new task's spsr
MSR spsr_cxsf, r4
LDMFD sp!, {r4} ; pop new task's psr
MSR cpsr_cxsf, r4
LDMFD sp!, {r0-r12,lr,pc} ; pop new task's r0-r12,lr & pc
ENDP
IF :DEF:__MICROLIB
EXPORT __heap_base
EXPORT __heap_limit
ELSE
; User Initial Stack & Heap
AREA |.text|, CODE, READONLY
IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap
LDR R0, = Heap_Mem
LDR R1, =(Stack_Mem + USR_Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR
ENDIF
END
/*
* File : trap.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://openlab.rt-thread.com/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2006-08-25 Bernard first version
*/
#include <rtthread.h>
#include <rthw.h>
#include "AT91SAM7S.h"
/**
* @addtogroup AT91SAM7
*/
/*@{*/
void rt_hw_trap_irq()
{
rt_isr_handler_t hander = (rt_isr_handler_t)AT91C_AIC_IVR;
hander(AT91C_AIC_ISR);
/* end of interrupt */
AT91C_AIC_EOICR = 0;
}
void rt_hw_trap_fiq()
{
rt_kprintf("fast interrupt request\n");
}
/*@}*/
此差异已折叠。
/*
* File : context.S
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://openlab.rt-thread.com/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2006-03-13 Bernard first version
*/
/*!
* \addtogroup xgs3c4510
*/
/*@{*/
#define NOINT 0xc0
/*
* rt_base_t rt_hw_interrupt_disable();
*/
.globl rt_hw_interrupt_disable
rt_hw_interrupt_disable:
mrs r0, cpsr
orr r1, r0, #NOINT
msr cpsr_c, r1
mov pc, lr
/*
* void rt_hw_interrupt_enable(rt_base_t level);
*/
.globl rt_hw_interrupt_enable
rt_hw_interrupt_enable:
msr cpsr, r0
mov pc, lr
/*
* void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
* r0 --> from
* r1 --> to
*/
.globl rt_hw_context_switch
rt_hw_context_switch:
stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC)
stmfd sp!, {r0-r12, lr} @ push lr & register file
mrs r4, cpsr
stmfd sp!, {r4} @ push cpsr
mrs r4, spsr
stmfd sp!, {r4} @ push spsr
str sp, [r0] @ store sp in preempted tasks TCB
ldr sp, [r1] @ get new task stack pointer
ldmfd sp!, {r4} @ pop new task spsr
msr spsr_cxsf, r4
ldmfd sp!, {r4} @ pop new task cpsr
msr cpsr_cxsf, r4
ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc
/*
* void rt_hw_context_switch_to(rt_uint32 to);
* r0 --> to
*/
.globl rt_hw_context_switch_to
rt_hw_context_switch_to:
ldr sp, [r0] @ get new task stack pointer
ldmfd sp!, {r4} @ pop new task spsr
msr spsr_cxsf, r4
ldmfd sp!, {r4} @ pop new task cpsr
msr cpsr_cxsf, r4
ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc
/*
* void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
*/
.globl rt_thread_switch_interrput_flag
.globl rt_interrupt_from_thread
.globl rt_interrupt_to_thread
.globl rt_hw_context_switch_interrupt
rt_hw_context_switch_interrupt:
ldr r2, =rt_thread_switch_interrput_flag
ldr r3, [r2]
cmp r3, #1
beq _reswitch
mov r3, #1 @ set rt_thread_switch_interrput_flag to 1
str r3, [r2]
ldr r2, =rt_interrupt_from_thread @ set rt_interrupt_from_thread
str r0, [r2]
_reswitch:
ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread
str r1, [r2]
mov pc, lr
;/*
; * File : context_rvds.S
; * This file is part of RT-Thread RTOS
; * COPYRIGHT (C) 2006, RT-Thread Development Team
; *
; * The license and distribution terms for this file may be
; * found in the file LICENSE in this distribution or at
; * http://www.rt-thread.org/license/LICENSE
; *
; * Change Logs:
; * Date Author Notes
; * 2009-01-20 Bernard first version
; */
NOINT EQU 0xc0 ; disable interrupt in psr
AREA |.text|, CODE, READONLY, ALIGN=2
ARM
REQUIRE8
PRESERVE8
;/*
; * rt_base_t rt_hw_interrupt_disable();
; */
rt_hw_interrupt_disable PROC
EXPORT rt_hw_interrupt_disable
MRS r0, cpsr
ORR r1, r0, #NOINT
MSR cpsr_c, r1
BX lr
ENDP
;/*
; * void rt_hw_interrupt_enable(rt_base_t level);
; */
rt_hw_interrupt_enable PROC
EXPORT rt_hw_interrupt_enable
MSR cpsr_c, r0
BX lr
ENDP
;/*
; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
; * r0 --> from
; * r1 --> to
; */
rt_hw_context_switch PROC
EXPORT rt_hw_context_switch
STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC)
STMFD sp!, {r0-r12, lr} ; push lr & register file
MRS r4, cpsr
STMFD sp!, {r4} ; push cpsr
MRS r4, spsr
STMFD sp!, {r4} ; push spsr
STR sp, [r0] ; store sp in preempted tasks TCB
LDR sp, [r1] ; get new task stack pointer
LDMFD sp!, {r4} ; pop new task spsr
MSR spsr_cxsf, r4
LDMFD sp!, {r4} ; pop new task cpsr
MSR cpsr_cxsf, r4
LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc
ENDP
;/*
; * void rt_hw_context_switch_to(rt_uint32 to);
; * r0 --> to
; */
rt_hw_context_switch_to PROC
EXPORT rt_hw_context_switch_to
LDR sp, [r0] ; get new task stack pointer
LDMFD sp!, {r4} ; pop new task spsr
MSR spsr_cxsf, r4
LDMFD sp!, {r4} ; pop new task cpsr
MSR cpsr_cxsf, r4
LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc
ENDP
;/*
; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
; */
IMPORT rt_thread_switch_interrput_flag
IMPORT rt_interrupt_from_thread
IMPORT rt_interrupt_to_thread
rt_hw_context_switch_interrupt PROC
EXPORT rt_hw_context_switch_interrupt
LDR r2, =rt_thread_switch_interrput_flag
LDR r3, [r2]
CMP r3, #1
BEQ _reswitch
MOV r3, #1 ; set rt_thread_switch_interrput_flag to 1
STR r3, [r2]
LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread
STR r0, [r2]
_reswitch
LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread
STR r1, [r2]
BX lr
ENDP
END
\ No newline at end of file
/*
* File : cpu.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Develop Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2006-08-23 Bernard first version
*/
#include <rtthread.h>
#include "AT91SAM7X.h"
/**
* @addtogroup AT91SAM7X
*/
/*@{*/
/**
* this function will reset CPU
*
*/
void rt_hw_cpu_reset()
{
}
/**
* this function will shutdown CPU
*
*/
void rt_hw_cpu_shutdown()
{
rt_kprintf("shutdown...\n");
while (1);
}
/*@}*/
/*
* File : trap.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://openlab.rt-thread.com/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2006-08-23 Bernard first version
*/
#include <rtthread.h>
#include "AT91SAM7X.h"
#define MAX_HANDLERS 32
extern rt_uint32_t rt_interrupt_nest;
rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
rt_uint32_t rt_thread_switch_interrput_flag;
/**
* @addtogroup AT91SAM7
*/
/*@{*/
void rt_hw_interrupt_handler(int vector)
{
rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
}
/**
* This function will initialize hardware interrupt
*/
void rt_hw_interrupt_init()
{
rt_base_t index;
for (index = 0; index < MAX_HANDLERS; index ++)
{
AT91C_AIC_SVR(index) = (rt_uint32_t)rt_hw_interrupt_handler;
}
/* init interrupt nest, and context in thread sp */
rt_interrupt_nest = 0;
rt_interrupt_from_thread = 0;
rt_interrupt_to_thread = 0;
rt_thread_switch_interrput_flag = 0;
}
/**
* This function will mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_mask(int vector)
{
/* disable interrupt */
AT91C_AIC_IDCR = 1 << vector;
/* clear interrupt */
AT91C_AIC_ICCR = 1 << vector;
}
/**
* This function will un-mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_umask(int vector)
{
AT91C_AIC_IECR = 1 << vector;
}
/**
* This function will install a interrupt service routine to a interrupt.
* @param vector the interrupt number
* @param new_handler the interrupt service routine to be installed
* @param old_handler the old interrupt service routine
*/
void rt_hw_interrupt_install(int vector, rt_isr_handler_t new_handler, rt_isr_handler_t *old_handler)
{
if(vector >= 0 && vector < MAX_HANDLERS)
{
if (*old_handler != RT_NULL) *old_handler = (rt_isr_handler_t)AT91C_AIC_SVR(vector);
if (new_handler != RT_NULL) AT91C_AIC_SVR(vector) = (rt_uint32_t)new_handler;
}
}
/*@}*/
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT 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 3 of the License, or
(at your option) any later version.
ChibiOS/RT 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Parts of this file are borrowed by the Linux include file linux/mii.h:
* Copyright (C) 1996, 1999, 2001 David S. Miller (davem@redhat.com)
*/
#ifndef _MII_H_
#define _MII_H_
/* Generic MII registers. */
#define MII_BMCR 0x00 /* Basic mode control register */
#define MII_BMSR 0x01 /* Basic mode status register */
#define MII_PHYSID1 0x02 /* PHYS ID 1 */
#define MII_PHYSID2 0x03 /* PHYS ID 2 */
#define MII_ADVERTISE 0x04 /* Advertisement control reg */
#define MII_LPA 0x05 /* Link partner ability reg */
#define MII_EXPANSION 0x06 /* Expansion register */
#define MII_CTRL1000 0x09 /* 1000BASE-T control */
#define MII_STAT1000 0x0a /* 1000BASE-T status */
#define MII_ESTATUS 0x0f /* Extended Status */
#define MII_DCOUNTER 0x12 /* Disconnect counter */
#define MII_FCSCOUNTER 0x13 /* False carrier counter */
#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
#define MII_RERRCOUNTER 0x15 /* Receive error counter */
#define MII_SREVISION 0x16 /* Silicon revision */
#define MII_RESV1 0x17 /* Reserved... */
#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
#define MII_PHYADDR 0x19 /* PHY address */
#define MII_RESV2 0x1a /* Reserved... */
#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
#define MII_NCONFIG 0x1c /* Network interface config */
/* Basic mode control register. */
#define BMCR_RESV 0x003f /* Unused... */
#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */
#define BMCR_CTST 0x0080 /* Collision test */
#define BMCR_FULLDPLX 0x0100 /* Full duplex */
#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
#define BMCR_RESET 0x8000 /* Reset the DP83840 */
/* Basic mode status register. */
#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
#define BMSR_JCD 0x0002 /* Jabber detected */
#define BMSR_LSTATUS 0x0004 /* Link status */
#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
#define BMSR_RFAULT 0x0010 /* Remote fault detected */
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
#define BMSR_RESV 0x00c0 /* Unused... */
#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */
#define BMSR_100HALF2 0x0200 /* Can do 100BASE-T2 HDX */
#define BMSR_100FULL2 0x0400 /* Can do 100BASE-T2 FDX */
#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
/* Advertisement control register. */
#define ADVERTISE_SLCT 0x001f /* Selector bits */
#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */
#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */
#define ADVERTISE_RESV 0x1000 /* Unused... */
#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
ADVERTISE_CSMA)
#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
ADVERTISE_100HALF | ADVERTISE_100FULL)
/* Link partner ability register. */
#define LPA_SLCT 0x001f /* Same as advertise selector */
#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
#define LPA_1000XFULL 0x0020 /* Can do 1000BASE-X full-duplex */
#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
#define LPA_1000XHALF 0x0040 /* Can do 1000BASE-X half-duplex */
#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
#define LPA_1000XPAUSE 0x0080 /* Can do 1000BASE-X pause */
#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
#define LPA_1000XPAUSE_ASYM 0x0100 /* Can do 1000BASE-X pause asym*/
#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */
#define LPA_PAUSE_CAP 0x0400 /* Can pause */
#define LPA_PAUSE_ASYM 0x0800 /* Can pause asymetrically */
#define LPA_RESV 0x1000 /* Unused... */
#define LPA_RFAULT 0x2000 /* Link partner faulted */
#define LPA_LPACK 0x4000 /* Link partner acked us */
#define LPA_NPAGE 0x8000 /* Next page bit */
#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL)
#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
/* Expansion register for auto-negotiation. */
#define EXPANSION_NWAY 0x0001 /* Can do N-way auto-nego */
#define EXPANSION_LCWP 0x0002 /* Got new RX page code word */
#define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */
#define EXPANSION_NPCAPABLE 0x0008 /* Link partner supports npage */
#define EXPANSION_MFAULTS 0x0010 /* Multiple faults detected */
#define EXPANSION_RESV 0xffe0 /* Unused... */
#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */
#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */
/* N-way test register. */
#define NWAYTEST_RESV1 0x00ff /* Unused... */
#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */
#define NWAYTEST_RESV2 0xfe00 /* Unused... */
/* 1000BASE-T Control register */
#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */
#define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */
/* 1000BASE-T Status register */
#define LPA_1000LOCALRXOK 0x2000 /* Link partner local receiver status */
#define LPA_1000REMRXOK 0x1000 /* Link partner remote receiver status */
#define LPA_1000FULL 0x0800 /* Link partner 1000BASE-T full duplex */
#define LPA_1000HALF 0x0400 /* Link partner 1000BASE-T half duplex */
#define MII_DM9161_ID 0x0181b8a0
#define MII_AM79C875_ID 0x00225540
#define MII_MICREL_ID 0x00221610
#endif /* _MII_H_ */
#include <rthw.h>
#include <rtthread.h>
#include <netif/ethernetif.h>
#include "sam7x_emac.h"
#include "AT91SAM7X256.h"
#include "lwipopts.h"
#define MAX_ADDR_LEN 6
#define EMAC_PIO_CFG (AT91C_PB0_ETXCK_EREFCK | \
AT91C_PB1_ETXEN | \
AT91C_PB2_ETX0 | \
AT91C_PB3_ETX1 | \
AT91C_PB4_ECRS | \
AT91C_PB5_ERX0 | \
AT91C_PB6_ERX1 | \
AT91C_PB7_ERXER | \
AT91C_PB8_EMDC | \
AT91C_PB9_EMDIO | \
AT91C_PB10_ETX2 | \
AT91C_PB11_ETX3 | \
AT91C_PB10_ETX2 | \
AT91C_PB13_ERX2 | \
AT91C_PB14_ERX3 | \
AT91C_PB15_ERXDV_ECRSDV| \
AT91C_PB16_ECOL | \
AT91C_PB17_ERXCK)
#define RB_BUFFER_SIZE 8 /* max number of receive buffers */
#define ETH_RX_BUF_SIZE 128
#define TB_BUFFER_SIZE 4
#define ETH_TX_BUF_SIZE (PBUF_POOL_BUFSIZE)
struct rbf_t
{
rt_uint32_t addr;
rt_uint32_t status;
};
static rt_uint32_t current_rb_index; /* current receive buffer index */
static volatile struct rbf_t rb_descriptors[RB_BUFFER_SIZE];
static volatile struct rbf_t tb_descriptors[TB_BUFFER_SIZE];
static rt_uint8_t rx_buf[RB_BUFFER_SIZE][ETH_RX_BUF_SIZE] __attribute__ ((aligned (8)));
static rt_uint8_t tx_buf[TB_BUFFER_SIZE][ETH_TX_BUF_SIZE] __attribute__ ((aligned (8)));
static struct rt_semaphore tx_sem;
struct net_device
{
/* inherit from ethernet device */
struct eth_device parent;
/* interface address info. */
rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
};
static struct net_device sam7x_dev_entry;
static struct net_device *sam7x_dev =&sam7x_dev_entry;
AT91PS_EMAC pEmac = AT91C_BASE_EMAC;
rt_inline void write_phy(rt_uint8_t addr, rt_uint32_t value)
{
AT91C_BASE_EMAC->EMAC_MAN = ((0x01<<30) | (2 << 16) | (1 << 28) |
(AT91C_PHY_ADDR << 23) | (addr << 18)) | value;
/* Wait until IDLE bit in Network Status register is cleared */
while (!(AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE));
}
rt_inline rt_uint32_t read_phy(rt_uint8_t addr)
{
AT91C_BASE_EMAC->EMAC_MAN = (0x01<<30) | (0x02 << 16) | (0x02 << 28) |
(AT91C_PHY_ADDR << 23) | (addr << 18);
/* Wait until IDLE bit in Network Status register is cleared */
while (!(AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE));
return (AT91C_BASE_EMAC->EMAC_MAN & 0x0000ffff);
}
rt_inline void sam7xether_reset_tx_desc(void)
{
static rt_uint32_t index = 0;
if(tb_descriptors[index].status & TxDESC_STATUS_USED)
{
while(!tb_descriptors[index].status & TxDESC_STATUS_LAST_BUF)
{
index ++;
if(index >= TB_BUFFER_SIZE)index = 0;
tb_descriptors[index].status |= TxDESC_STATUS_USED;
}
index ++;
if(index >= TB_BUFFER_SIZE)index = 0;
}
}
/* interrupt service routing */
static void sam7xether_isr(int irq)
{
/* Variable definitions can be made now. */
volatile rt_uint32_t isr, rsr;
/* get status */
isr = AT91C_BASE_EMAC->EMAC_ISR;
rsr = AT91C_BASE_EMAC->EMAC_RSR;
if( ( isr & AT91C_EMAC_RCOMP ) || ( rsr & AT91C_EMAC_REC ) )
{
rt_err_t result;
/* a frame has been received */
result = eth_device_ready((struct eth_device*)&(sam7x_dev->parent));
RT_ASSERT(result == RT_EOK);
AT91C_BASE_EMAC->EMAC_RSR = AT91C_EMAC_REC;
}
if( isr & AT91C_EMAC_TCOMP )
{
/* A frame has been transmitted. Mark all the buffers as free */
sam7xether_reset_tx_desc();
AT91C_BASE_EMAC->EMAC_TSR = AT91C_EMAC_COMP;
}
}
rt_inline void linksetup(void)
{
rt_uint32_t value;
/* Check if this is a RTL8201 PHY. */
rt_uint16_t id1 = read_phy(PHY_REG_PHYID1);
rt_uint16_t id2 = read_phy(PHY_REG_PHYID2);
if (((id2 << 16) | (id1 & 0xfff0)) == MII_RTL8201_ID)
{
rt_uint32_t tout;
/* Configure the PHY device */
/* Use autonegotiation about the link speed. */
write_phy (PHY_REG_BMCR, PHY_AUTO_NEG);
/* Wait to complete Auto_Negotiation. */
for (tout = 0; tout < 0x100000; tout++)
{
value = read_phy (PHY_REG_BMSR);
if (value & BMSR_ANEGCOMPLETE) break; /* autonegotiation finished. */
}
/* Check the link status. */
for (tout = 0; tout < 0x10000; tout++)
{
value = read_phy (PHY_REG_BMSR);
if (value & BMSR_LINKST) break; /* Link is on. */
}
}
value = read_phy (PHY_REG_ANLPAR);
/* Update the MAC register NCFGR. */
AT91C_BASE_EMAC->EMAC_NCFGR &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
/* set full duplex . */
if (value & 0xA000) AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_FD;
/* set speed */
if (value & 0xC000) AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_SPD;
}
/*
* Set the MAC address.
*/
rt_inline void update_mac_address(struct net_device* device)
{
AT91C_BASE_EMAC->EMAC_SA1L = (device->dev_addr[3] << 24) |
(device->dev_addr[2] << 16) |
(device->dev_addr[1] << 8) |
device->dev_addr[0];
AT91C_BASE_EMAC->EMAC_SA1H = (device->dev_addr[5] << 8) |
device->dev_addr[4];
}
rt_inline void sam7xether_desc_init()
{
rt_uint32_t i;
/* Rx Buffer Descriptor initialization */
current_rb_index = 0;
for (i = 0; i < RB_BUFFER_SIZE; i++)
{
rb_descriptors[i].addr = (rt_uint32_t)&(rx_buf[i][0]);
rb_descriptors[i].status = 0;
}
/* Set the WRAP bit at the end of the list descriptor. */
rb_descriptors[RB_BUFFER_SIZE-1].addr |= 0x02;
/* Set Rx Queue pointer to descriptor list. */
AT91C_BASE_EMAC->EMAC_RBQP = (unsigned int)&(rb_descriptors[0]);
/* Tx Buffer Descriptor initialization */
for (i = 0; i < TB_BUFFER_SIZE; i++)
{
tb_descriptors[i].addr = (rt_uint32_t)&(tx_buf[i][0]);
tb_descriptors[i].status = TxDESC_STATUS_USED;
}
/* Set the WRAP bit at the end of the list descriptor. */
tb_descriptors[TB_BUFFER_SIZE-1].status |= TxDESC_STATUS_WRAP;
/* Set Tx Queue pointer to descriptor list. */
AT91C_BASE_EMAC->EMAC_TBQP = (unsigned int)&(tb_descriptors[0]);
}
/* RT-Thread Device Interface */
/* initialize the interface */
rt_err_t sam7xether_init(rt_device_t dev)
{
/* enable peripheral clock for EMAC and PIO B */
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOB | 1 << AT91C_ID_EMAC;
/* Disable pull up on RXDV => PHY normal mode (not in test mode), */
/* and set MII mode. PHY has internal pull down. */
AT91C_BASE_PIOB->PIO_PPUDR = (1<<16) | (1 << 15);
/* Clear PB18 <=> PHY powerdown */
AT91C_BASE_PIOB->PIO_PER = 1<<18;
AT91C_BASE_PIOB->PIO_OER = 1<<18;
AT91C_BASE_PIOB->PIO_CODR = 1<<18;
/* EMAC IO init for EMAC-PHY communication. */
AT91C_BASE_PIOB->PIO_ASR = EMAC_PIO_CFG;
AT91C_BASE_PIOB->PIO_PDR = EMAC_PIO_CFG; // Set in Periph mode
/* Enable communication between EMAC-PHY. */
AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_MPE;
/* MDC = MCK/32 */
AT91C_BASE_EMAC->EMAC_NCFGR |= 2<<10;
/* Reset PHY */
AT91C_BASE_PIOB->PIO_PPUDR = AT91C_PB7_ERXER;
AT91C_BASE_RSTC->RSTC_RMR = 0xA5000000 | (0x08 << 8) ;
AT91C_BASE_RSTC->RSTC_RCR = 0xA5000000 | AT91C_RSTC_EXTRST;
while(!(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_NRSTL));
linksetup();
/* Disable management port in MAC control register. */
AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE;
/* Enable EMAC in MII mode, enable clock ERXCK and ETXCK */
AT91C_BASE_EMAC->EMAC_USRIO= AT91C_EMAC_CLKEN;
/* Transmit and Receive disable. */
AT91C_BASE_EMAC->EMAC_NCR &= ~(AT91C_EMAC_RE | AT91C_EMAC_TE);
/* init descriptor */
sam7xether_desc_init();
/* Clear receive and transmit status registers. */
AT91C_BASE_EMAC->EMAC_RSR = (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
AT91C_BASE_EMAC->EMAC_TSR = (AT91C_EMAC_UND | AT91C_EMAC_COMP| AT91C_EMAC_BEX |
AT91C_EMAC_RLES| AT91C_EMAC_COL | AT91C_EMAC_UBR);
/* Configure EMAC operation mode. */
AT91C_BASE_EMAC->EMAC_NCFGR |= (AT91C_EMAC_BIG | AT91C_EMAC_DRFCS);
AT91C_BASE_EMAC->EMAC_NCR |= (AT91C_EMAC_TE | AT91C_EMAC_RE | AT91C_EMAC_WESTAT);
/* update MAC address */
update_mac_address(sam7x_dev);
/* enable interrupt */
AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RCOMP | AT91C_EMAC_TCOMP;
/* setup interrupt */
rt_hw_interrupt_install(AT91C_ID_EMAC, sam7xether_isr, RT_NULL);
*(volatile unsigned int*)(0xFFFFF000 + AT91C_ID_EMAC * 4) = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 5;
// AT91C_AIC_SMR(AT91C_ID_EMAC) = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 5;
rt_hw_interrupt_umask(AT91C_ID_EMAC);
return RT_EOK;
}
/* control the interface */
rt_err_t sam7xether_control(rt_device_t dev, rt_uint8_t cmd, void *args)
{
switch(cmd)
{
case NIOCTL_GADDR:
/* get mac address */
if(args) rt_memcpy(args, sam7x_dev_entry.dev_addr, 6);
else return -RT_ERROR;
break;
default :
break;
}
return RT_EOK;
}
/* Open the ethernet interface */
rt_err_t sam7xether_open(rt_device_t dev, rt_uint16_t oflags)
{
return RT_EOK;
}
/* Close the interface */
rt_err_t sam7xether_close(rt_device_t dev)
{
return RT_EOK;
}
/* Read */
rt_size_t sam7xether_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
rt_set_errno(-RT_ENOSYS);
return 0;
}
/* Write */
rt_size_t sam7xether_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
rt_set_errno(-RT_ENOSYS);
return 0;
}
/* See the header file for descriptions of public functions. */
void sam7xether_write_frame(rt_uint8_t *ptr, rt_uint32_t length, rt_bool_t eof)
{
rt_uint8_t *buf_ptr;
static rt_uint32_t current_tb_index = 0;
rt_uint32_t is_last, tx_offset = 0, remain, pdu_length;
while(tx_offset < length)
{
/* check whether buffer is available */
while(!(tb_descriptors[current_tb_index].status & TxDESC_STATUS_USED))
{
/* no buffer */
rt_thread_delay(5);
}
/* Get the address of the buffer from the descriptor, then copy
the data into the buffer. */
buf_ptr = (rt_uint8_t *)tb_descriptors[current_tb_index].addr;
/* How much can we write to the buffer? */
remain = length - tx_offset;
pdu_length = (remain <= ETH_TX_BUF_SIZE)? remain : ETH_TX_BUF_SIZE;
/* Copy the data into the buffer. */
rt_memcpy(buf_ptr, &ptr[tx_offset], pdu_length );
tx_offset += pdu_length;
/* Is this the last data for the frame? */
if((eof == RT_TRUE) && ( tx_offset >= length )) is_last = TxDESC_STATUS_LAST_BUF;
else is_last = 0;
/* Fill out the necessary in the descriptor to get the data sent,
then move to the next descriptor, wrapping if necessary. */
if(current_tb_index >= (TB_BUFFER_SIZE - 1))
{
tb_descriptors[current_tb_index].status = ( pdu_length & TxDESC_STATUS_BUF_SIZE )
| is_last
| TxDESC_STATUS_WRAP;
current_tb_index = 0;
}
else
{
tb_descriptors[current_tb_index].status = ( pdu_length & TxDESC_STATUS_BUF_SIZE )
| is_last;
current_tb_index++;
}
/* If this is the last buffer to be sent for this frame we can
start the transmission. */
if(is_last)
{
AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TSTART;
}
}
}
/* ethernet device interface */
/*
* Transmit packet.
*/
rt_err_t sam7xether_tx( rt_device_t dev, struct pbuf* p)
{
struct pbuf* q;
/* lock tx operation */
rt_sem_take(&tx_sem, RT_WAITING_FOREVER);
for (q = p; q != NULL; q = q->next)
{
if (q->next == RT_NULL) sam7xether_write_frame(q->payload, q->len, RT_TRUE);
else sam7xether_write_frame(q->payload, q->len, RT_FALSE);
}
rt_sem_release(&tx_sem);
return 0;
}
void sam7xether_read_frame(rt_uint8_t* ptr, rt_uint32_t section_length, rt_uint32_t total)
{
static rt_uint8_t* src_ptr;
register rt_uint32_t buf_remain, section_remain;
static rt_uint32_t section_read = 0, buf_offset = 0, frame_read = 0;
if(ptr == RT_NULL)
{
/* Reset our state variables ready for the next read from this buffer. */
src_ptr = (rt_uint8_t *)(rb_descriptors[current_rb_index].addr & RxDESC_FLAG_ADDR_MASK);
frame_read = (rt_uint32_t)0;
buf_offset = (rt_uint32_t)0;
}
else
{
/* Loop until we have obtained the required amount of data. */
section_read = 0;
while( section_read < section_length )
{
buf_remain = (ETH_RX_BUF_SIZE - buf_offset);
section_remain = section_length - section_read;
if( section_remain > buf_remain )
{
/* more data on section than buffer size */
rt_memcpy(&ptr[ section_read ], &src_ptr[buf_offset], buf_remain);
section_read += buf_remain;
frame_read += buf_remain;
/* free buffer */
rb_descriptors[current_rb_index].addr &= ~RxDESC_FLAG_OWNSHIP;
/* move to the next frame. */
current_rb_index++;
if(current_rb_index >= RB_BUFFER_SIZE) current_rb_index = 0;
/* Reset the variables for the new buffer. */
src_ptr = (rt_uint8_t *)(rb_descriptors[current_rb_index].addr & RxDESC_FLAG_ADDR_MASK);
buf_offset = 0;
}
else
{
/* more data on buffer than section size */
rt_memcpy(&ptr[section_read], &src_ptr[buf_offset], section_remain);
buf_offset += section_remain;
section_read += section_remain;
frame_read += section_remain;
/* finish this read */
if((buf_offset >= ETH_RX_BUF_SIZE) || (frame_read >= total))
{
/* free buffer */
rb_descriptors[current_rb_index].addr &= ~(RxDESC_FLAG_OWNSHIP);
/* move to the next frame. */
current_rb_index++;
if( current_rb_index >= RB_BUFFER_SIZE ) current_rb_index = 0;
src_ptr = (rt_uint8_t*)(rb_descriptors[current_rb_index].addr & RxDESC_FLAG_ADDR_MASK);
buf_offset = 0;
}
}
}
}
}
struct pbuf *sam7xether_rx(rt_device_t dev)
{
struct pbuf *p = RT_NULL;
/* skip fragment frame */
while((rb_descriptors[current_rb_index].addr & RxDESC_FLAG_OWNSHIP)
&& !(rb_descriptors[current_rb_index].status & RxDESC_STATUS_FRAME_START))
{
rb_descriptors[current_rb_index].addr &= (~RxDESC_FLAG_OWNSHIP);
current_rb_index++;
if(current_rb_index >= RB_BUFFER_SIZE) current_rb_index = 0;
}
if ((rb_descriptors[current_rb_index].addr & RxDESC_FLAG_OWNSHIP))
{
struct pbuf* q;
rt_uint32_t index, pkt_len = 0;
/* first of all, find the frame length */
index = current_rb_index;
while (rb_descriptors[index].addr & RxDESC_FLAG_OWNSHIP)
{
pkt_len = rb_descriptors[index].status & RxDESC_STATUS_BUF_SIZE;
if (pkt_len > 0) break;
index ++;
if (index > RB_BUFFER_SIZE) index = 0;
}
if (pkt_len)
{
p = pbuf_alloc(PBUF_LINK, pkt_len, PBUF_RAM);
if(p != RT_NULL)
{
sam7xether_read_frame(RT_NULL, 0, pkt_len);
for(q = p; q != RT_NULL; q= q->next)
sam7xether_read_frame(q->payload, q->len, pkt_len);
}
else
{
rt_kprintf("no memory in pbuf\n");
}
}
}
/* enable interrupt */
AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RCOMP;
return p;
}
int sam7xether_register(char *name)
{
rt_err_t result;
/* init rt-thread device interface */
sam7x_dev_entry.parent.parent.init = sam7xether_init;
sam7x_dev_entry.parent.parent.open = sam7xether_open;
sam7x_dev_entry.parent.parent.close = sam7xether_close;
sam7x_dev_entry.parent.parent.read = sam7xether_read;
sam7x_dev_entry.parent.parent.write = sam7xether_write;
sam7x_dev_entry.parent.parent.control = sam7xether_control;
sam7x_dev_entry.parent.eth_rx = sam7xether_rx;
sam7x_dev_entry.parent.eth_tx = sam7xether_tx;
/* Update MAC address */
sam7x_dev_entry.dev_addr[0] = 0x1e;
sam7x_dev_entry.dev_addr[1] = 0x30;
sam7x_dev_entry.dev_addr[2] = 0x6c;
sam7x_dev_entry.dev_addr[3] = 0xa2;
sam7x_dev_entry.dev_addr[4] = 0x45;
sam7x_dev_entry.dev_addr[5] = 0x5e;
/* update mac address */
update_mac_address(sam7x_dev);
rt_sem_init(&tx_sem, "emac", 1, RT_IPC_FLAG_FIFO);
result = eth_device_init(&(sam7x_dev->parent), (char*)name);
RT_ASSERT(result == RT_EOK);
return RT_EOK;
}
#ifndef __SAM7X_EMAC_H__
#define __SAM7X_EMAC_H__
#define AT91C_PHY_ADDR 0x01
#define MII_RTL8201_ID 0x82010000
/* RTL8201 PHY registers. */
#define PHY_REG_BMCR 0x00 /* Basic mode control register */
#define PHY_REG_BMSR 0x01 /* Basic mode status register */
#define PHY_REG_PHYID1 0x02 /* PHY ID identifier #1 */
#define PHY_REG_PHYID2 0x03 /* PHY ID identifier #2 */
#define PHY_REG_ANAR 0x04 /* AutoNegotiation Advertisement reg.*/
#define PHY_REG_ANLPAR 0x05 /* AutoNeg.Link partner ability reg */
#define PHY_REG_ANER 0x06 /* AutoNeg. Expansion register */
#define PHY_REG_DSCR 0x10 /* DAVICOM Specified Config. reg */
#define PHY_REG_DSCSR 0x11 /* DAVICOM Spec. Config/Status reg */
#define PHY_REG_10BTCSR 0x12 /* 10BASET Configuration/Status reg */
#define PHY_REG_PWDOR 0x13 /* Power Down Control Register */
#define PHY_REG_SCR 0x14 /* Specified Config register */
#define PHY_REG_INTR 0x15 /* Interrupt register */
#define PHY_REG_RECR 0x16 /* Receive Error Counter register */
#define PHY_REG_DISCR 0x17 /* Disconnect Counter register */
#define PHY_REG_RLSR 0x18 /* Hardware Reset Latch State reg. */
#define PHY_FULLD_100M 0x2100 /* Full Duplex 100Mbit */
#define PHY_HALFD_100M 0x2000 /* Half Duplex 100Mbit */
#define PHY_FULLD_10M 0x0100 /* Full Duplex 10Mbit */
#define PHY_HALFD_10M 0x0000 /* Half Duplex 10MBit */
#define PHY_AUTO_NEG 0x3000 /* Select Auto Negotiation */
/* Basic mode status register. */
#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
#define BMSR_JCD 0x0002 /* Jabber detected */
#define BMSR_LINKST 0x0004 /* Link status */
#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
#define BMSR_RFAULT 0x0010 /* Remote fault detected */
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
#define BMSR_MIIPRESUP 0x0040 /* MII Frame Preamble Suppression */
#define BMSR_RESV 0x0780 /* Unused... */
#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
#define RxDESC_FLAG_ADDR_MASK 0xfffffffc
#define RxDESC_FLAG_WARP 0x00000002
#define RxDESC_FLAG_OWNSHIP 0x00000001
#define RxDESC_STATUS_BUF_SIZE (0x00000FFF)
#define RxDESC_STATUS_FRAME_START (1U << 14)
#define RxDESC_STATUS_FRAME_END (1U << 15)
#define TxDESC_STATUS_BUF_SIZE (0x000007FF)
#define TxDESC_STATUS_LAST_BUF (1U << 15)
#define TxDESC_STATUS_NO_CRC (1U << 16)
#define TxDESC_STATUS_BUF_EXHAUSTED (1U << 27)
#define TxDESC_STATUS_Tx_UNDERRUN (1U << 28)
#define TxDESC_STATUS_Tx_ERROR (1U << 29)
#define TxDESC_STATUS_WRAP (1U << 30)
#define TxDESC_STATUS_USED (1U << 31)
int sam7xether_register(char *name);
#endif
/*
* File : serial.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://openlab.rt-thread.com/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2006-08-23 Bernard first version
* 2009-05-14 Bernard add RT-THread device interface
*/
#include <rthw.h>
#include <rtthread.h>
#include "AT91SAM7X.h"
#include "serial.h"
/**
* @addtogroup AT91SAM7X256
*/
/*@{*/
typedef volatile rt_uint32_t REG32;
struct rt_at91serial_hw
{
REG32 US_CR; // Control Register
REG32 US_MR; // Mode Register
REG32 US_IER; // Interrupt Enable Register
REG32 US_IDR; // Interrupt Disable Register
REG32 US_IMR; // Interrupt Mask Register
REG32 US_CSR; // Channel Status Register
REG32 US_RHR; // Receiver Holding Register
REG32 US_THR; // Transmitter Holding Register
REG32 US_BRGR; // Baud Rate Generator Register
REG32 US_RTOR; // Receiver Time-out Register
REG32 US_TTGR; // Transmitter Time-guard Register
REG32 Reserved0[5]; //
REG32 US_FIDI; // FI_DI_Ratio Register
REG32 US_NER; // Nb Errors Register
REG32 Reserved1[1]; //
REG32 US_IF; // IRDA_FILTER Register
REG32 Reserved2[44]; //
REG32 US_RPR; // Receive Pointer Register
REG32 US_RCR; // Receive Counter Register
REG32 US_TPR; // Transmit Pointer Register
REG32 US_TCR; // Transmit Counter Register
REG32 US_RNPR; // Receive Next Pointer Register
REG32 US_RNCR; // Receive Next Counter Register
REG32 US_TNPR; // Transmit Next Pointer Register
REG32 US_TNCR; // Transmit Next Counter Register
REG32 US_PTCR; // PDC Transfer Control Register
REG32 US_PTSR; // PDC Transfer Status Register
};
struct rt_at91serial
{
struct rt_device parent;
struct rt_at91serial_hw* hw_base;
rt_uint16_t peripheral_id;
rt_uint32_t baudrate;
/* reception field */
rt_uint16_t save_index, read_index;
rt_uint8_t rx_buffer[RT_UART_RX_BUFFER_SIZE];
};
#ifdef RT_USING_UART1
struct rt_at91serial serial1;
#endif
#ifdef RT_USING_UART2
struct rt_at91serial serial2;
#endif
static void rt_hw_serial_isr(int irqno)
{
rt_base_t level;
struct rt_device* device;
struct rt_at91serial* serial = RT_NULL;
#ifdef RT_USING_UART1
if (irqno == AT91C_ID_US0)
{
/* serial 1 */
serial = &serial1;
}
#endif
#ifdef RT_USING_UART2
if (irqno == AT91C_ID_US1)
{
/* serial 2 */
serial = &serial2;
}
#endif
RT_ASSERT(serial != RT_NULL);
/* get generic device object */
device = (rt_device_t)serial;
/* disable interrupt */
level = rt_hw_interrupt_disable();
/* get received character */
serial->rx_buffer[serial->save_index] = serial->hw_base->US_RHR;
/* move to next position */
serial->save_index ++;
if (serial->save_index >= RT_UART_RX_BUFFER_SIZE)
serial->save_index = 0;
/* if the next position is read index, discard this 'read char' */
if (serial->save_index == serial->read_index)
{
serial->read_index ++;
if (serial->read_index >= RT_UART_RX_BUFFER_SIZE)
serial->read_index = 0;
}
/* enable interrupt */
rt_hw_interrupt_enable(level);
/* indicate to upper layer application */
if (device->rx_indicate != RT_NULL)
device->rx_indicate(device, 1);
/* ack interrupt */
AT91C_AIC_EOICR = 1;
}
static rt_err_t rt_serial_init (rt_device_t dev)
{
rt_uint32_t bd;
struct rt_at91serial* serial = (struct rt_at91serial*) dev;
RT_ASSERT(serial != RT_NULL);
/* must be US0 or US1 */
RT_ASSERT((serial->peripheral_id != AT91C_ID_US0) &&
(serial->peripheral_id != AT91C_ID_US1));
/* Enable Clock for USART */
AT91C_PMC_PCER = 1 << serial->peripheral_id;
/* Enable RxD0 and TxDO Pin */
if (serial->peripheral_id == AT91C_ID_US0)
{
/* set pinmux */
AT91C_PIO_PDR = (1 << 5) | (1 << 6);
}
else if (serial->peripheral_id == AT91C_ID_US1)
{
/* set pinmux */
AT91C_PIO_PDR = (1 << 21) | (1 << 22);
}
serial->hw_base->US_CR = AT91C_US_RSTRX | /* Reset Receiver */
AT91C_US_RSTTX | /* Reset Transmitter */
AT91C_US_RXDIS | /* Receiver Disable */
AT91C_US_TXDIS; /* Transmitter Disable */
serial->hw_base->US_MR = AT91C_US_USMODE_NORMAL | /* Normal Mode */
AT91C_US_CLKS_CLOCK | /* Clock = MCK */
AT91C_US_CHRL_8_BITS | /* 8-bit Data */
AT91C_US_PAR_NONE | /* No Parity */
AT91C_US_NBSTOP_1_BIT; /* 1 Stop Bit */
/* set baud rate divisor */
bd = ((MCK*10)/(serial->baudrate * 16));
if ((bd % 10) >= 5) bd = (bd / 10) + 1;
else bd /= 10;
serial->hw_base->US_BRGR = bd;
serial->hw_base->US_CR = AT91C_US_RXEN | /* Receiver Enable */
AT91C_US_TXEN; /* Transmitter Enable */
/* reset rx index */
serial->save_index = 0;
serial->read_index = 0;
/* reset rx buffer */
rt_memset(serial->rx_buffer, 0, RT_UART_RX_BUFFER_SIZE);
return RT_EOK;
}
static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag)
{
struct rt_at91serial *serial = (struct rt_at91serial*)dev;
RT_ASSERT(serial != RT_NULL);
if (dev->flag & RT_DEVICE_FLAG_INT_RX)
{
/* enable UART rx interrupt */
serial->hw_base->US_IER = 1 << 0; /* RxReady interrupt */
serial->hw_base->US_IMR |= 1 << 0; /* umask RxReady interrupt */
/* install UART handler */
rt_hw_interrupt_install(serial->peripheral_id, rt_hw_serial_isr, RT_NULL);
AT91C_AIC_SMR(serial->peripheral_id) = 5 | (0x01 << 5);
rt_hw_interrupt_umask(serial->peripheral_id);
}
return RT_EOK;
}
static rt_err_t rt_serial_close(rt_device_t dev)
{
struct rt_at91serial *serial = (struct rt_at91serial*)dev;
RT_ASSERT(serial != RT_NULL);
if (dev->flag & RT_DEVICE_FLAG_INT_RX)
{
/* disable interrupt */
serial->hw_base->US_IDR = 1 << 0; /* RxReady interrupt */
serial->hw_base->US_IMR &= ~(1 << 0); /* mask RxReady interrupt */
}
serial->hw_base->US_CR = AT91C_US_RSTRX | /* Reset Receiver */
AT91C_US_RSTTX | /* Reset Transmitter */
AT91C_US_RXDIS | /* Receiver Disable */
AT91C_US_TXDIS; /* Transmitter Disable */
return RT_EOK;
}
static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
rt_uint8_t* ptr;
struct rt_at91serial *serial = (struct rt_at91serial*)dev;
RT_ASSERT(serial != RT_NULL);
/* point to buffer */
ptr = (rt_uint8_t*) buffer;
if (dev->flag & RT_DEVICE_FLAG_INT_RX)
{
while (size)
{
/* interrupt receive */
rt_base_t level;
/* disable interrupt */
level = rt_hw_interrupt_disable();
if (serial->read_index != serial->save_index)
{
*ptr = serial->rx_buffer[serial->read_index];
serial->read_index ++;
if (serial->read_index >= RT_UART_RX_BUFFER_SIZE)
serial->read_index = 0;
}
else
{
/* no data in rx buffer */
/* enable interrupt */
rt_hw_interrupt_enable(level);
break;
}
/* enable interrupt */
rt_hw_interrupt_enable(level);
ptr ++;
size --;
}
return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
}
else if (dev->flag & RT_DEVICE_FLAG_DMA_RX)
{
/* not support right now */
RT_ASSERT(0);
}
else
{
/* poll mode */
while (size)
{
/* Wait for Full Rx Buffer */
while (!(serial->hw_base->US_CSR & AT91C_US_RXRDY));
/* Read Character */
*ptr = serial->hw_base->US_RHR;
ptr ++;
size --;
}
return (rt_size_t)ptr - (rt_size_t)buffer;
}
return 0;
}
static rt_size_t rt_serial_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
rt_uint8_t* ptr;
struct rt_at91serial *serial = (struct rt_at91serial*)dev;
RT_ASSERT(serial != RT_NULL);
ptr = (rt_uint8_t*) buffer;
if (dev->open_flag & RT_DEVICE_OFLAG_WRONLY)
{
if (dev->flag & RT_DEVICE_FLAG_STREAM)
{
/* it's a stream mode device */
while (size)
{
/* stream mode */
if (*ptr == '\n')
{
while (!(serial->hw_base->US_CSR & AT91C_US_TXRDY));
serial->hw_base->US_THR = '\r';
}
/* Wait for Empty Tx Buffer */
while (!(serial->hw_base->US_CSR & AT91C_US_TXRDY));
/* Transmit Character */
serial->hw_base->US_THR = *ptr;
ptr ++;
size --;
}
}
else
{
while (size)
{
/* Wait for Empty Tx Buffer */
while (!(serial->hw_base->US_CSR & AT91C_US_TXRDY));
/* Transmit Character */
serial->hw_base->US_THR = *ptr;
ptr ++;
size --;
}
}
}
return (rt_size_t)ptr - (rt_size_t)buffer;
}
static rt_err_t rt_serial_control (rt_device_t dev, rt_uint8_t cmd, void *args)
{
return RT_EOK;
}
rt_err_t rt_hw_serial_init()
{
rt_device_t device;
#ifdef RT_USING_UART1
device = (rt_device_t) &serial1;
/* init serial device private data */
serial1.hw_base = (struct rt_at91serial_hw*)AT91C_BASE_US0;
serial1.peripheral_id = AT91C_ID_US0;
serial1.baudrate = 115200;
/* set device virtual interface */
device->init = rt_serial_init;
device->open = rt_serial_open;
device->close = rt_serial_close;
device->read = rt_serial_read;
device->write = rt_serial_write;
device->control = rt_serial_control;
/* register uart1 on device subsystem */
rt_device_register(device, "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
#endif
#ifdef RT_USING_UART2
device = (rt_device_t) &serial2;
serial2.hw_base = (struct rt_at91serial_hw*)AT91C_BASE_US1;
serial2.peripheral_id = AT91C_ID_US1;
serial2.baudrate = 115200;
/* set device virtual interface */
device->init = rt_serial_init;
device->open = rt_serial_open;
device->close = rt_serial_close;
device->read = rt_serial_read;
device->write = rt_serial_write;
device->control = rt_serial_control;
/* register uart2 on device subsystem */
rt_device_register(device, "uart2", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
#endif
return RT_EOK;
}
/*@}*/
#ifndef __RT_SERIAL_H__
#define __RT_SERIAL_H__
#ifndef AT91C_BASE_US0
#define AT91C_BASE_US0 (0xFFFC0000) // (US0) Base Address
#endif
#ifndef AT91C_BASE_US1
#define AT91C_BASE_US1 (0xFFFC4000) // (US1) Base Address
#endif
#define AT91C_US_RXRDY ((unsigned int) 0x1 << 0) /* US RXRDY Interrupt */
#define AT91C_US_TXRDY ((unsigned int) 0x1 << 1) /* US TXRDY Interrupt */
#define AT91C_US_RSTRX ((unsigned int) 0x1 << 2) /* US Reset Receiver */
#define AT91C_US_RSTTX ((unsigned int) 0x1 << 3) /* US Reset Transmitter */
#define AT91C_US_RXEN ((unsigned int) 0x1 << 4) /* US Receiver Enable */
#define AT91C_US_RXDIS ((unsigned int) 0x1 << 5) /* US Receiver Disable */
#define AT91C_US_TXEN ((unsigned int) 0x1 << 6) /* US Transmitter Enable */
#define AT91C_US_TXDIS ((unsigned int) 0x1 << 7) /* US Transmitter Disable */
#define AT91C_US_RSTSTA ((unsigned int) 0x1 << 8) /* US Reset Status Bits */
#define AT91C_US_USMODE_NORMAL ((unsigned int) 0x0) /* USAR) Normal */
#define AT91C_US_USMODE_RS485 ((unsigned int) 0x1) /* USAR) RS485 */
#define AT91C_US_USMODE_HWHSH ((unsigned int) 0x2) /* USAR) Hardware Handshaking */
#define AT91C_US_USMODE_MODEM ((unsigned int) 0x3) /* USAR) Modem */
#define AT91C_US_USMODE_ISO7816_0 ((unsigned int) 0x4) /* USAR) ISO7816 protocol: T = 0 */
#define AT91C_US_USMODE_ISO7816_1 ((unsigned int) 0x6) /* USAR) ISO7816 protocol: T = 1 */
#define AT91C_US_USMODE_IRDA ((unsigned int) 0x8) /* USAR) IrDA */
#define AT91C_US_USMODE_SWHSH ((unsigned int) 0xC) /* USAR) Software Handshaking */
#define AT91C_US_CLKS_CLOCK ((unsigned int) 0x0 << 4) /* USAR) Clock */
#define AT91C_US_CLKS_FDIV1 ((unsigned int) 0x1 << 4) /* USAR) fdiv1 */
#define AT91C_US_CLKS_SLOW ((unsigned int) 0x2 << 4) /* USAR) slow_clock (ARM) */
#define AT91C_US_CLKS_EXT ((unsigned int) 0x3 << 4) /* USAR) External (SCK) */
#define AT91C_US_CHRL_5_BITS ((unsigned int) 0x0 << 6) /* USAR) Character Length: 5 bits */
#define AT91C_US_CHRL_6_BITS ((unsigned int) 0x1 << 6) /* USAR) Character Length: 6 bits */
#define AT91C_US_CHRL_7_BITS ((unsigned int) 0x2 << 6) /* USAR) Character Length: 7 bits */
#define AT91C_US_CHRL_8_BITS ((unsigned int) 0x3 << 6) /* USAR) Character Length: 8 bits */
#define AT91C_US_PAR_EVEN ((unsigned int) 0x0 << 9) /* DBGU Even Parity */
#define AT91C_US_PAR_ODD ((unsigned int) 0x1 << 9) /* DBGU Odd Parity */
#define AT91C_US_PAR_SPACE ((unsigned int) 0x2 << 9) /* DBGU Parity forced to 0 (Space) */
#define AT91C_US_PAR_MARK ((unsigned int) 0x3 << 9) /* DBGU Parity forced to 1 (Mark) */
#define AT91C_US_PAR_NONE ((unsigned int) 0x4 << 9) /* DBGU No Parity */
#define AT91C_US_PAR_MULTI_DROP ((unsigned int) 0x6 << 9) /* DBGU Multi-drop mode */
#define AT91C_US_NBSTOP_1_BIT ((unsigned int) 0x0 << 12) /* USART 1 stop bit */
#define AT91C_US_NBSTOP_15_BIT ((unsigned int) 0x1 << 12) /* USART Asynchronous (SYNC=0) 2 stop bits Synchronous (SYNC=1) 2 stop bits */
#define AT91C_US_NBSTOP_2_BIT ((unsigned int) 0x2 << 12) /* USART 2 stop bits */
#define MCK 48054857
#define BR 115200 /* Baud Rate */
#define BRD (MCK/16/BR) /* Baud Rate Divisor */
#endif
/*
* File : stack.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://openlab.rt-thread.com/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2006-08-23 Bernard the first version
*/
#include <rtthread.h>
#include "AT91SAM7X.h"
/**
* @addtogroup AT91SAM7
*/
/*@{*/
/**
* This function will initialize thread stack
*
* @param tentry the entry of thread
* @param parameter the parameter of entry
* @param stack_addr the beginning stack address
* @param texit the function will be called when thread exit
*
* @return stack address
*/
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
rt_uint8_t *stack_addr, void *texit)
{
unsigned long *stk;
stk = (unsigned long *)stack_addr;
*(stk) = (unsigned long)tentry; /* entry point */
*(--stk) = (unsigned long)texit; /* lr */
*(--stk) = 0; /* r12 */
*(--stk) = 0; /* r11 */
*(--stk) = 0; /* r10 */
*(--stk) = 0; /* r9 */
*(--stk) = 0; /* r8 */
*(--stk) = 0; /* r7 */
*(--stk) = 0; /* r6 */
*(--stk) = 0; /* r5 */
*(--stk) = 0; /* r4 */
*(--stk) = 0; /* r3 */
*(--stk) = 0; /* r2 */
*(--stk) = 0; /* r1 */
*(--stk) = (unsigned long)parameter; /* r0 : argument */
*(--stk) = SVCMODE; /* cpsr */
*(--stk) = SVCMODE; /* spsr */
/* return task's current stack address */
return (rt_uint8_t *)stk;
}
/*@}*/
/*
* File : start.S
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://openlab.rt-thread.com/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2006-08-31 Bernard first version
*/
/* Internal Memory Base Addresses */
.equ FLASH_BASE, 0x00100000
.equ RAM_BASE, 0x00200000
/* Stack Configuration */
.equ TOP_STACK, 0x00204000
.equ UND_STACK_SIZE, 0x00000100
.equ SVC_STACK_SIZE, 0x00000400
.equ ABT_STACK_SIZE, 0x00000100
.equ FIQ_STACK_SIZE, 0x00000100
.equ IRQ_STACK_SIZE, 0x00000100
.equ USR_STACK_SIZE, 0x00000004
/* ARM architecture definitions */
.equ MODE_USR, 0x10
.equ MODE_FIQ, 0x11
.equ MODE_IRQ, 0x12
.equ MODE_SVC, 0x13
.equ MODE_ABT, 0x17
.equ MODE_UND, 0x1B
.equ MODE_SYS, 0x1F
.equ I_BIT, 0x80 /* when this bit is set, IRQ is disabled */
.equ F_BIT, 0x40 /* when this bit is set, FIQ is disabled */
.section .init, "ax"
.code 32
.align 0
.globl _start
_start:
b reset
ldr pc, _vector_undef
ldr pc, _vector_swi
ldr pc, _vector_pabt
ldr pc, _vector_dabt
nop /* reserved vector */
ldr pc, _vector_irq
ldr pc, _vector_fiq
_vector_undef: .word vector_undef
_vector_swi: .word vector_swi
_vector_pabt: .word vector_pabt
_vector_dabt: .word vector_dabt
_vector_resv: .word vector_resv
_vector_irq: .word vector_irq
_vector_fiq: .word vector_fiq
/*
* rtthread bss start and end
* which are defined in linker script
*/
.globl _bss_start
_bss_start: .word __bss_start
.globl _bss_end
_bss_end: .word __bss_end
/* the system entry */
reset:
/* disable watchdog */
ldr r0, =0xFFFFFD40
ldr r1, =0x00008000
str r1, [r0, #0x04]
/* enable the main oscillator */
ldr r0, =0xFFFFFC00
ldr r1, =0x00000601
str r1, [r0, #0x20]
/* wait for main oscillator to stabilize */
moscs_loop:
ldr r2, [r0, #0x68]
ands r2, r2, #1
beq moscs_loop
/* set up the PLL */
ldr r1, =0x00191C05
str r1, [r0, #0x2C]
/* wait for PLL to lock */
pll_loop:
ldr r2, [r0, #0x68]
ands r2, r2, #0x04
beq pll_loop
/* select clock */
ldr r1, =0x00000007
str r1, [r0, #0x30]
#ifdef __FLASH_BUILD__
/* copy exception vectors into internal sram */
mov r8, #RAM_BASE
ldr r9, =_start
ldmia r9!, {r0-r7}
stmia r8!, {r0-r7}
ldmia r9!, {r0-r6}
stmia r8!, {r0-r6}
#endif
/* setup stack for each mode */
ldr r0, =TOP_STACK
/* set stack */
/* undefined instruction mode */
msr cpsr_c, #MODE_UND|I_BIT|F_BIT
mov sp, r0
sub r0, r0, #UND_STACK_SIZE
/* abort mode */
msr cpsr_c, #MODE_ABT|I_BIT|F_BIT
mov sp, r0
sub r0, r0, #ABT_STACK_SIZE
/* FIQ mode */
msr cpsr_c, #MODE_FIQ|I_BIT|F_BIT
mov sp, r0
sub r0, r0, #FIQ_STACK_SIZE
/* IRQ mode */
msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT
mov sp, r0
sub r0, r0, #IRQ_STACK_SIZE
/* supervisor mode */
msr cpsr_c, #MODE_SVC
mov sp, r0
/* remap SRAM to 0x0000 */
ldr r0, =0xFFFFFF00
mov r1, #0x01
str r1, [r0]
/* mask all IRQs */
ldr r1, =0xFFFFF124
ldr r0, =0XFFFFFFFF
str r0, [r1]
/* start RT-Thread Kernel */
ldr pc, _rtthread_startup
_rtthread_startup: .word rtthread_startup
/* exception handlers */
vector_undef: b vector_undef
vector_swi : b vector_swi
vector_pabt : b vector_pabt
vector_dabt : b vector_dabt
vector_resv : b vector_resv
.globl rt_interrupt_enter
.globl rt_interrupt_leave
.globl rt_thread_switch_interrput_flag
.globl rt_interrupt_from_thread
.globl rt_interrupt_to_thread
vector_irq:
stmfd sp!, {r0-r12,lr}
bl rt_interrupt_enter
bl rt_hw_trap_irq
bl rt_interrupt_leave
/*
* if rt_thread_switch_interrput_flag set, jump to
* rt_hw_context_switch_interrupt_do and don't return
*/
ldr r0, =rt_thread_switch_interrput_flag
ldr r1, [r0]
cmp r1, #1
beq rt_hw_context_switch_interrupt_do
ldmfd sp!, {r0-r12,lr}
subs pc, lr, #4
vector_fiq:
stmfd sp!,{r0-r7,lr}
bl rt_hw_trap_fiq
ldmfd sp!,{r0-r7,lr}
subs pc,lr,#4
/*
* void rt_hw_context_switch_interrupt_do(rt_base_t flag)
*/
rt_hw_context_switch_interrupt_do:
mov r1, #0 @ clear flag
str r1, [r0]
ldmfd sp!, {r0-r12,lr}@ reload saved registers
stmfd sp!, {r0-r3} @ save r0-r3
mov r1, sp
add sp, sp, #16 @ restore sp
sub r2, lr, #4 @ save old task's pc to r2
mrs r3, spsr @ disable interrupt
orr r0, r3, #I_BIT|F_BIT
msr spsr_c, r0
ldr r0, =.+8 @ switch to interrupted task's stack
movs pc, r0
stmfd sp!, {r2} @ push old task's pc
stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4
mov r4, r1 @ Special optimised code below
mov r5, r3
ldmfd r4!, {r0-r3}
stmfd sp!, {r0-r3} @ push old task's r3-r0
stmfd sp!, {r5} @ push old task's psr
mrs r4, spsr
stmfd sp!, {r4} @ push old task's spsr
ldr r4, =rt_interrupt_from_thread
ldr r5, [r4]
str sp, [r5] @ store sp in preempted tasks's TCB
ldr r6, =rt_interrupt_to_thread
ldr r6, [r6]
ldr sp, [r6] @ get new task's stack pointer
ldmfd sp!, {r4} @ pop new task's spsr
msr SPSR_cxsf, r4
ldmfd sp!, {r4} @ pop new task's psr
msr CPSR_cxsf, r4
ldmfd sp!, {r0-r12,lr,pc} @ pop new task's r0-r12,lr & pc
;/*****************************************************************************/
;/* SAM7.S: Startup file for Atmel AT91SAM7 device series */
;/*****************************************************************************/
;/* <<< Use Configuration Wizard in Context Menu >>> */
;/*****************************************************************************/
;/* This file is part of the uVision/ARM development tools. */
;/* Copyright (c) 2005-2006 Keil Software. All rights reserved. */
;/* This software may only be used under the terms of a valid, current, */
;/* end user licence from KEIL for a compatible version of KEIL software */
;/* development tools. Nothing else gives you the right to use this software. */
;/*****************************************************************************/
;/*
; * The SAM7.S code is executed after CPU Reset. This file may be
; * translated with the following SET symbols. In uVision these SET
; * symbols are entered under Options - ASM - Define.
; *
; * REMAP: when set the startup code remaps exception vectors from
; * on-chip RAM to address 0.
; *
; * RAM_INTVEC: when set the startup code copies exception vectors
; * from on-chip Flash to on-chip RAM.
; */
; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
Mode_USR EQU 0x10
Mode_FIQ EQU 0x11
Mode_IRQ EQU 0x12
Mode_SVC EQU 0x13
Mode_ABT EQU 0x17
Mode_UND EQU 0x1B
Mode_SYS EQU 0x1F
I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled
F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled
; Internal Memory Base Addresses
FLASH_BASE EQU 0x00100000
RAM_BASE EQU 0x00200000
;// <h> Stack Configuration (Stack Sizes in Bytes)
;// <o0> Undefined Mode <0x0-0xFFFFFFFF:8>
;// <o1> Supervisor Mode <0x0-0xFFFFFFFF:8>
;// <o2> Abort Mode <0x0-0xFFFFFFFF:8>
;// <o3> Fast Interrupt Mode <0x0-0xFFFFFFFF:8>
;// <o4> Interrupt Mode <0x0-0xFFFFFFFF:8>
;// <o5> User/System Mode <0x0-0xFFFFFFFF:8>
;// </h>
UND_Stack_Size EQU 0x00000000
SVC_Stack_Size EQU 0x00000100
ABT_Stack_Size EQU 0x00000000
FIQ_Stack_Size EQU 0x00000000
IRQ_Stack_Size EQU 0x00000100
USR_Stack_Size EQU 0x00000100
ISR_Stack_Size EQU (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
FIQ_Stack_Size + IRQ_Stack_Size)
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE USR_Stack_Size
__initial_sp SPACE ISR_Stack_Size
Stack_Top
;// <h> Heap Configuration
;// <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF>
;// </h>
Heap_Size EQU 0x00000000
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
; Reset Controller (RSTC) definitions
RSTC_BASE EQU 0xFFFFFD00 ; RSTC Base Address
RSTC_MR EQU 0x08 ; RSTC_MR Offset
;/*
;// <e> Reset Controller (RSTC)
;// <o1.0> URSTEN: User Reset Enable
;// <i> Enables NRST Pin to generate Reset
;// <o1.8..11> ERSTL: External Reset Length <0-15>
;// <i> External Reset Time in 2^(ERSTL+1) Slow Clock Cycles
;// </e>
;*/
RSTC_SETUP EQU 1
RSTC_MR_Val EQU 0xA5000401
; Embedded Flash Controller (EFC) definitions
EFC_BASE EQU 0xFFFFFF00 ; EFC Base Address
EFC0_FMR EQU 0x60 ; EFC0_FMR Offset
EFC1_FMR EQU 0x70 ; EFC1_FMR Offset
;// <e> Embedded Flash Controller 0 (EFC0)
;// <o1.16..23> FMCN: Flash Microsecond Cycle Number <0-255>
;// <i> Number of Master Clock Cycles in 1us
;// <o1.8..9> FWS: Flash Wait State
;// <0=> Read: 1 cycle / Write: 2 cycles
;// <1=> Read: 2 cycle / Write: 3 cycles
;// <2=> Read: 3 cycle / Write: 4 cycles
;// <3=> Read: 4 cycle / Write: 4 cycles
;// </e>
EFC0_SETUP EQU 1
EFC0_FMR_Val EQU 0x00320100
;// <e> Embedded Flash Controller 1 (EFC1)
;// <o1.16..23> FMCN: Flash Microsecond Cycle Number <0-255>
;// <i> Number of Master Clock Cycles in 1us
;// <o1.8..9> FWS: Flash Wait State
;// <0=> Read: 1 cycle / Write: 2 cycles
;// <1=> Read: 2 cycle / Write: 3 cycles
;// <2=> Read: 3 cycle / Write: 4 cycles
;// <3=> Read: 4 cycle / Write: 4 cycles
;// </e>
EFC1_SETUP EQU 0
EFC1_FMR_Val EQU 0x00320100
; Watchdog Timer (WDT) definitions
WDT_BASE EQU 0xFFFFFD40 ; WDT Base Address
WDT_MR EQU 0x04 ; WDT_MR Offset
;// <e> Watchdog Timer (WDT)
;// <o1.0..11> WDV: Watchdog Counter Value <0-4095>
;// <o1.16..27> WDD: Watchdog Delta Value <0-4095>
;// <o1.12> WDFIEN: Watchdog Fault Interrupt Enable
;// <o1.13> WDRSTEN: Watchdog Reset Enable
;// <o1.14> WDRPROC: Watchdog Reset Processor
;// <o1.28> WDDBGHLT: Watchdog Debug Halt
;// <o1.29> WDIDLEHLT: Watchdog Idle Halt
;// <o1.15> WDDIS: Watchdog Disable
;// </e>
WDT_SETUP EQU 1
WDT_MR_Val EQU 0x00008000
; Power Mangement Controller (PMC) definitions
PMC_BASE EQU 0xFFFFFC00 ; PMC Base Address
PMC_MOR EQU 0x20 ; PMC_MOR Offset
PMC_MCFR EQU 0x24 ; PMC_MCFR Offset
PMC_PLLR EQU 0x2C ; PMC_PLLR Offset
PMC_MCKR EQU 0x30 ; PMC_MCKR Offset
PMC_SR EQU 0x68 ; PMC_SR Offset
PMC_MOSCEN EQU (1<<0) ; Main Oscillator Enable
PMC_OSCBYPASS EQU (1<<1) ; Main Oscillator Bypass
PMC_OSCOUNT EQU (0xFF<<8) ; Main OScillator Start-up Time
PMC_DIV EQU (0xFF<<0) ; PLL Divider
PMC_PLLCOUNT EQU (0x3F<<8) ; PLL Lock Counter
PMC_OUT EQU (0x03<<14) ; PLL Clock Frequency Range
PMC_MUL EQU (0x7FF<<16) ; PLL Multiplier
PMC_USBDIV EQU (0x03<<28) ; USB Clock Divider
PMC_CSS EQU (3<<0) ; Clock Source Selection
PMC_PRES EQU (7<<2) ; Prescaler Selection
PMC_MOSCS EQU (1<<0) ; Main Oscillator Stable
PMC_LOCK EQU (1<<2) ; PLL Lock Status
PMC_MCKRDY EQU (1<<3) ; Master Clock Status
;// <e> Power Mangement Controller (PMC)
;// <h> Main Oscillator
;// <o1.0> MOSCEN: Main Oscillator Enable
;// <o1.1> OSCBYPASS: Oscillator Bypass
;// <o1.8..15> OSCCOUNT: Main Oscillator Startup Time <0-255>
;// </h>
;// <h> Phase Locked Loop (PLL)
;// <o2.0..7> DIV: PLL Divider <0-255>
;// <o2.16..26> MUL: PLL Multiplier <0-2047>
;// <i> PLL Output is multiplied by MUL+1
;// <o2.14..15> OUT: PLL Clock Frequency Range
;// <0=> 80..160MHz <1=> Reserved
;// <2=> 150..220MHz <3=> Reserved
;// <o2.8..13> PLLCOUNT: PLL Lock Counter <0-63>
;// <o2.28..29> USBDIV: USB Clock Divider
;// <0=> None <1=> 2 <2=> 4 <3=> Reserved
;// </h>
;// <o3.0..1> CSS: Clock Source Selection
;// <0=> Slow Clock
;// <1=> Main Clock
;// <2=> Reserved
;// <3=> PLL Clock
;// <o3.2..4> PRES: Prescaler
;// <0=> None
;// <1=> Clock / 2 <2=> Clock / 4
;// <3=> Clock / 8 <4=> Clock / 16
;// <5=> Clock / 32 <6=> Clock / 64
;// <7=> Reserved
;// </e>
PMC_SETUP EQU 1
PMC_MOR_Val EQU 0x00000601
PMC_PLLR_Val EQU 0x00191C05
PMC_MCKR_Val EQU 0x00000007
PRESERVE8
; Area Definition and Entry Point
; Startup Code must be linked first at Address at which it expects to run.
AREA RESET, CODE, READONLY
ARM
; Exception Vectors
; Mapped to Address 0.
; Absolute addressing mode must be used.
; Dummy Handlers are implemented as infinite loops which can be modified.
Vectors LDR PC,Reset_Addr
LDR PC,Undef_Addr
LDR PC,SWI_Addr
LDR PC,PAbt_Addr
LDR PC,DAbt_Addr
NOP ; Reserved Vector
LDR PC,IRQ_Addr
LDR PC,FIQ_Addr
Reset_Addr DCD Reset_Handler
Undef_Addr DCD Undef_Handler
SWI_Addr DCD SWI_Handler
PAbt_Addr DCD PAbt_Handler
DAbt_Addr DCD DAbt_Handler
DCD 0 ; Reserved Address
IRQ_Addr DCD IRQ_Handler
FIQ_Addr DCD FIQ_Handler
Undef_Handler B Undef_Handler
SWI_Handler B SWI_Handler
PAbt_Handler B PAbt_Handler
DAbt_Handler B DAbt_Handler
FIQ_Handler B FIQ_Handler
; Reset Handler
EXPORT Reset_Handler
Reset_Handler
; Setup RSTC
IF RSTC_SETUP != 0
LDR R0, =RSTC_BASE
LDR R1, =RSTC_MR_Val
STR R1, [R0, #RSTC_MR]
ENDIF
; Setup EFC0
IF EFC0_SETUP != 0
LDR R0, =EFC_BASE
LDR R1, =EFC0_FMR_Val
STR R1, [R0, #EFC0_FMR]
ENDIF
; Setup EFC1
IF EFC1_SETUP != 0
LDR R0, =EFC_BASE
LDR R1, =EFC1_FMR_Val
STR R1, [R0, #EFC1_FMR]
ENDIF
; Setup WDT
IF WDT_SETUP != 0
LDR R0, =WDT_BASE
LDR R1, =WDT_MR_Val
STR R1, [R0, #WDT_MR]
ENDIF
; Setup PMC
IF PMC_SETUP != 0
LDR R0, =PMC_BASE
; Setup Main Oscillator
LDR R1, =PMC_MOR_Val
STR R1, [R0, #PMC_MOR]
; Wait until Main Oscillator is stablilized
IF (PMC_MOR_Val:AND:PMC_MOSCEN) != 0
MOSCS_Loop LDR R2, [R0, #PMC_SR]
ANDS R2, R2, #PMC_MOSCS
BEQ MOSCS_Loop
ENDIF
; Setup the PLL
IF (PMC_PLLR_Val:AND:PMC_MUL) != 0
LDR R1, =PMC_PLLR_Val
STR R1, [R0, #PMC_PLLR]
; Wait until PLL is stabilized
PLL_Loop LDR R2, [R0, #PMC_SR]
ANDS R2, R2, #PMC_LOCK
BEQ PLL_Loop
ENDIF
; Select Clock
IF (PMC_MCKR_Val:AND:PMC_CSS) == 1 ; Main Clock Selected
LDR R1, =PMC_MCKR_Val
AND R1, #PMC_CSS
STR R1, [R0, #PMC_MCKR]
WAIT_Rdy1 LDR R2, [R0, #PMC_SR]
ANDS R2, R2, #PMC_MCKRDY
BEQ WAIT_Rdy1
LDR R1, =PMC_MCKR_Val
STR R1, [R0, #PMC_MCKR]
WAIT_Rdy2 LDR R2, [R0, #PMC_SR]
ANDS R2, R2, #PMC_MCKRDY
BEQ WAIT_Rdy2
ELIF (PMC_MCKR_Val:AND:PMC_CSS) == 3 ; PLL Clock Selected
LDR R1, =PMC_MCKR_Val
AND R1, #PMC_PRES
STR R1, [R0, #PMC_MCKR]
WAIT_Rdy1 LDR R2, [R0, #PMC_SR]
ANDS R2, R2, #PMC_MCKRDY
BEQ WAIT_Rdy1
LDR R1, =PMC_MCKR_Val
STR R1, [R0, #PMC_MCKR]
WAIT_Rdy2 LDR R2, [R0, #PMC_SR]
ANDS R2, R2, #PMC_MCKRDY
BEQ WAIT_Rdy2
ENDIF ; Select Clock
ENDIF ; PMC_SETUP
; Copy Exception Vectors to Internal RAM
IF :DEF:RAM_INTVEC
ADR R8, Vectors ; Source
LDR R9, =RAM_BASE ; Destination
LDMIA R8!, {R0-R7} ; Load Vectors
STMIA R9!, {R0-R7} ; Store Vectors
LDMIA R8!, {R0-R7} ; Load Handler Addresses
STMIA R9!, {R0-R7} ; Store Handler Addresses
ENDIF
; Remap on-chip RAM to address 0
MC_BASE EQU 0xFFFFFF00 ; MC Base Address
MC_RCR EQU 0x00 ; MC_RCR Offset
IF :DEF:REMAP
LDR R0, =MC_BASE
MOV R1, #1
STR R1, [R0, #MC_RCR] ; Remap
ENDIF
; Setup Stack for each mode
LDR R0, =Stack_Top
; Enter Undefined Instruction Mode and set its Stack Pointer
MSR CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #UND_Stack_Size
; Enter Abort Mode and set its Stack Pointer
MSR CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #ABT_Stack_Size
; Enter FIQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #FIQ_Stack_Size
; Enter IRQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #IRQ_Stack_Size
; Enter Supervisor Mode and set its Stack Pointer
MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #SVC_Stack_Size
; Enter User Mode and set its Stack Pointer
; MSR CPSR_c, #Mode_USR
IF :DEF:__MICROLIB
EXPORT __initial_sp
ELSE
MOV SP, R0
SUB SL, SP, #USR_Stack_Size
ENDIF
; Enter the C code
IMPORT __main
LDR R0, =__main
BX R0
IMPORT rt_interrupt_enter
IMPORT rt_interrupt_leave
IMPORT rt_thread_switch_interrput_flag
IMPORT rt_interrupt_from_thread
IMPORT rt_interrupt_to_thread
IMPORT rt_hw_trap_irq
IRQ_Handler PROC
EXPORT IRQ_Handler
STMFD sp!, {r0-r12,lr}
BL rt_interrupt_enter
BL rt_hw_trap_irq
BL rt_interrupt_leave
; if rt_thread_switch_interrput_flag set, jump to
; rt_hw_context_switch_interrupt_do and don't return
LDR r0, =rt_thread_switch_interrput_flag
LDR r1, [r0]
CMP r1, #1
BEQ rt_hw_context_switch_interrupt_do
LDMFD sp!, {r0-r12,lr}
SUBS pc, lr, #4
ENDP
; /*
; * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
; */
rt_hw_context_switch_interrupt_do PROC
EXPORT rt_hw_context_switch_interrupt_do
MOV r1, #0 ; clear flag
STR r1, [r0]
LDMFD sp!, {r0-r12,lr}; reload saved registers
STMFD sp!, {r0-r3} ; save r0-r3
MOV r1, sp
ADD sp, sp, #16 ; restore sp
SUB r2, lr, #4 ; save old task's pc to r2
MRS r3, spsr ; get cpsr of interrupt thread
; switch to SVC mode and no interrupt
MSR cpsr_c, #I_Bit|F_Bit|Mode_SVC
STMFD sp!, {r2} ; push old task's pc
STMFD sp!, {r4-r12,lr}; push old task's lr,r12-r4
MOV r4, r1 ; Special optimised code below
MOV r5, r3
LDMFD r4!, {r0-r3}
STMFD sp!, {r0-r3} ; push old task's r3-r0
STMFD sp!, {r5} ; push old task's cpsr
MRS r4, spsr
STMFD sp!, {r4} ; push old task's spsr
LDR r4, =rt_interrupt_from_thread
LDR r5, [r4]
STR sp, [r5] ; store sp in preempted tasks's TCB
LDR r6, =rt_interrupt_to_thread
LDR r6, [r6]
LDR sp, [r6] ; get new task's stack pointer
LDMFD sp!, {r4} ; pop new task's spsr
MSR spsr_cxsf, r4
LDMFD sp!, {r4} ; pop new task's psr
MSR cpsr_cxsf, r4
LDMFD sp!, {r0-r12,lr,pc} ; pop new task's r0-r12,lr & pc
ENDP
IF :DEF:__MICROLIB
EXPORT __heap_base
EXPORT __heap_limit
ELSE
; User Initial Stack & Heap
AREA |.text|, CODE, READONLY
IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap
LDR R0, = Heap_Mem
LDR R1, =(Stack_Mem + USR_Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR
ENDIF
END
/*
* File : trap.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://openlab.rt-thread.com/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2006-08-25 Bernard first version
*/
#include <rtthread.h>
#include <rthw.h>
#include "AT91SAM7X.h"
/**
* @addtogroup AT91SAM7
*/
/*@{*/
void rt_hw_trap_irq()
{
rt_isr_handler_t hander = (rt_isr_handler_t)AT91C_AIC_IVR;
hander(AT91C_AIC_ISR);
/* end of interrupt */
AT91C_AIC_EOICR = 0;
}
void rt_hw_trap_fiq()
{
rt_kprintf("fast interrupt request\n");
}
/*@}*/
/*
* File : backtrace.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, 2008 RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://openlab.rt-thread.com/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2008-07-29 Bernard first version from QiuYi implementation
*/
#include <rtthread.h>
#ifdef __GNUC__
/*
-->High Address,Stack Top
PC<-----|
LR |
IP |
FP |
...... |
PC<-| |
LR | |
IP | |
FP---|-- |
...... |
PC |
LR |
IP |
FP---
-->Low Address,Stack Bottom
*/
void rt_hw_backtrace(rt_uint32_t *fp, rt_uint32_t thread_entry)
{
rt_uint32_t i, pc, func_entry;
pc = *fp;
rt_kprintf("[0x%x]\n", pc-0xC);
for(i=0; i<10; i++)
{
fp = *(fp - 3);
pc = *fp ;
func_entry = pc - 0xC;
if(func_entry <= 0x30000000) break;
if((func_entry == thread_entry))
{
rt_kprintf("EntryPoint:0x%x\n", func_entry);
break;
}
rt_kprintf("[0x%x]\n", func_entry);
}
}
#else
void rt_hw_backtrace(rt_uint32_t *fp, rt_uint32_t thread_entry)
{
/* old compiler implementation */
}
#endif
void __div0 (void)
{
while (1) ;
}
此差异已折叠。
/*
* File : showmem.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, 2008 RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://openlab.rt-thread.com/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2008-07-29 Bernard first version from QiuYi implementation
*/
#include <rtthread.h>
void rt_hw_show_memory(rt_uint32_t addr, rt_uint32_t size)
{
int i = 0, j =0;
RT_ASSERT(addr);
addr = addr & ~0xF;
size = 4*((size + 3)/4);
while(i < size)
{
rt_kprintf("0x%08x: ", addr );
for(j=0; j<4; j++)
{
rt_kprintf("0x%08x ", *(rt_uint32_t *)addr);
addr += 4;
i++;
}
rt_kprintf("\n");
}
return;
}
;/*
; * File : context.S
; * This file is part of RT-Thread RTOS
; * COPYRIGHT (C) 2006, RT-Thread Development Team
; *
; * The license and distribution terms for this file may be
; * found in the file LICENSE in this distribution or at
; * http://www.rt-thread.org/license/LICENSE
; *
; * Change Logs:
; * Date Author Notes
; * 2009-01-17 Bernard first version
; */
;/**
; * @addtogroup STM32
; */
;/*@{*/
NVIC_INT_CTRL EQU 0xE000ED04 ; interrupt control state register
NVIC_SYSPRI2 EQU 0xE000ED20 ; system priority register (2)
NVIC_PENDSV_PRI EQU 0x00000000 ; PendSV priority value (lowest)
NVIC_PENDSVSET EQU 0x10000000 ; value to trigger PendSV exception
AREA |.text|, CODE, READONLY, ALIGN=2
THUMB
REQUIRE8
PRESERVE8
IMPORT rt_thread_switch_interrput_flag
IMPORT rt_interrupt_from_thread
IMPORT rt_interrupt_to_thread
;/*
; * rt_base_t rt_hw_interrupt_disable();
; */
rt_hw_interrupt_disable PROC
EXPORT rt_hw_interrupt_disable
MRS r0, PRIMASK
CPSID I
BX LR
ENDP
;/*
; * void rt_hw_interrupt_enable(rt_base_t level);
; */
rt_hw_interrupt_enable PROC
EXPORT rt_hw_interrupt_enable
MSR PRIMASK, r0
BX LR
ENDP
;/*
; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
; * r0 --> from
; * r1 --> to
; */
rt_hw_context_switch PROC
EXPORT rt_hw_context_switch
LDR r2, =rt_interrupt_from_thread
STR r0, [r2]
LDR r2, =rt_interrupt_to_thread
STR r1, [r2]
LDR r0, =NVIC_INT_CTRL ; trigger the PendSV exception (causes context switch)
LDR r1, =NVIC_PENDSVSET
STR r1, [r0]
CPSIE I ; enable interrupts at processor level
BX LR
ENDP
; r0 --> swith from thread stack
; r1 --> swith to thread stack
; psr, pc, lr, r12, r3, r2, r1, r0 are pushed into [from] stack
rt_hw_pend_sv PROC
EXPORT rt_hw_pend_sv
LDR r0, =rt_interrupt_from_thread
LDR r1, [r0]
CBZ r1, swtich_to_thread ; skip register save at the first time
MRS r1, psp ; get from thread stack pointer
STMFD r1!, {r4 - r11} ; push r4 - r11 register
LDR r0, [r0]
STR r1, [r0] ; update from thread stack pointer
swtich_to_thread
LDR r1, =rt_interrupt_to_thread
LDR r1, [r1]
LDR r1, [r1] ; load thread stack pointer
LDMFD r1!, {r4 - r11} ; pop r4 - r11 register
MSR psp, r1 ; update stack pointer
ORR lr, lr, #0x04
BX lr
ENDP
;/*
; * void rt_hw_context_switch_to(rt_uint32 to);
; * r0 --> to
; */
rt_hw_context_switch_to PROC
EXPORT rt_hw_context_switch_to
LDR r1, =rt_interrupt_to_thread
STR r0, [r1]
; set from thread to 0
LDR r1, =rt_interrupt_from_thread
MOV r0, #0x0
STR r0, [r1]
; set the PendSV exception priority
LDR r0, =NVIC_SYSPRI2
LDR r1, =NVIC_PENDSV_PRI
STR r1, [r0]
LDR r0, =NVIC_INT_CTRL ; trigger the PendSV exception (causes context switch)
LDR r1, =NVIC_PENDSVSET
STR r1, [r0]
CPSIE I ; enable interrupts at processor level
; never reach here!
ENDP
;/*
; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)
; * {
; * if (rt_thread_switch_interrput_flag == 1)
; * {
; * rt_interrupt_to_thread = to;
; * }
; * else
; * {
; * rt_thread_switch_interrput_flag = 1;
; * rt_interrupt_from_thread = from;
; * rt_interrupt_to_thread = to;
; * }
; * }
; */
rt_hw_context_switch_interrupt PROC
EXPORT rt_hw_context_switch_interrupt
LDR r2, =rt_thread_switch_interrput_flag
LDR r3, [r2]
CMP r3, #1
BEQ _reswitch
MOV r3, #1 ; set rt_thread_switch_interrput_flag to 1
STR r3, [r2]
LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread
STR r0, [r2]
_reswitch
LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread
STR r1, [r2]
BX lr
ENDP
rt_hw_interrupt_thread_switch PROC
EXPORT rt_hw_interrupt_thread_switch
LDR r0, =rt_thread_switch_interrput_flag
LDR r1, [r0]
CBZ r1, _no_switch
; clear rt_thread_switch_interrput_flag to 0
MOV r1, #0x00
STR r1, [r0]
; trigger context switch
LDR r0, =NVIC_INT_CTRL ; trigger the PendSV exception (causes context switch)
LDR r1, =NVIC_PENDSVSET
STR r1, [r0]
_no_switch
BX lr
ENDP
END
\ No newline at end of file
/*
* File : cpu.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Develop Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://openlab.rt-thread.com/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2006-03-13 Bernard first version
*/
#include <rtthread.h>
/**
* @addtogroup S3C2410
*/
/*@{*/
/**
* reset cpu by dog's time-out
*
*/
void rt_hw_cpu_reset()
{
/*NOTREACHED*/
}
/**
* shutdown CPU
*
*/
void rt_hw_cpu_shutdown()
{
rt_kprintf("shutdown...\n");
RT_ASSERT(0);
}
/*@}*/
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册