Professional Documents
Culture Documents
Version 1.1
Contents
1 2 3 Introduction.......................................................................................... 4 Glossary .............................................................................................. 4 Clocks.................................................................................................. 5
3.1 3.2 Clock Sources ........................................................................................... 5 DUSART Clock.......................................................................................... 5 Overview............................................................................................. 5 Clock Selection................................................................................... 5
3.2.1 3.2.2
DUSART Configuration........................................................................ 6
4.1 4.2 Overview.................................................................................................... 6 Registers ................................................................................................... 6 Configuration ...................................................................................... 6 Sample Clock ..................................................................................... 6 Symbol Clock...................................................................................... 6 Baud Rates ......................................................................................... 7 Receive Timeout and Guard Time...................................................... 7 UART Configuration ........................................................................... 8 UART Control ..................................................................................... 8 Interrupt control .................................................................................. 8
4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.8 4.3 4.4
Appendix A
26 May 2006
AN014
Version 1.6
26 May 2006
Page 2 of 26
AN014
Version 1.6
Revision History
Version V1.1 V1.2 V1.3 V1.4 V1.5 V1.6 Date 19/07/2004 23/09/2004 02/11/2004 28/02/2005 12/09/2005 26/05/2006 Notes Initial revision. Updated list of trademarks. Changed font sizes. Updated for new release of CyanIDE. Updated serial buffer indexing code. Corrected error in example code in section 4.2.3.
26 May 2006
Page 3 of 26
AN014
Version 1.6
1 Introduction
This application note describes how to set up the DUSART peripheral for the standard UART protocol. The example software demonstrates the use of interrupt-driven buffering for both transmitted and received characters. The application is a simple loop which echoes received characters and also shows them on the development board LCD. The example code is available as a project for the CyanIDE development environment and runs on the eCOG1 development board.
2 Glossary
CPU DUSART eCOG1 PLL SSM UART Central Processor Unit Dual Universal Synchronous/Asynchronous Receiver/Transmitter Cyan Technology target micro controller Phase Locked Loop System Support Module Universal Asynchronous Receiver/Transmitter
The on-chip I/O registers may be accessed as complete registers, or as named bit fields within the registers. The include file ecog1.h contains structure definitions for all on-chip registers and bit fields. To access any register, use the structure prefix rg. To access a bit field within a register, use the structure prefix fd. For example: // Write to flash program data register rg.flash_prg_data = 0xA55A; // Write to period bit field in configuration register fd.flash_prg_cfg.period = 0x01F1;
26 May 2006
Page 4 of 26
AN014
Version 1.6
3 Clocks
3.1
Clock Sources
LOW_REF HIGH_REF LOW_PLL HIGH_PLL 32.768 kHz crystal oscillator input 5 MHz crystal oscillator input 4.9152 MHz clock, synthesized from LOW_REF 100 MHz clock, synthesized from HIGH_REF
Registers in the System Support Module (SSM) control the selection of the clock source for the processor and for each peripheral module.
3.2
3.2.1
DUSART Clock
Overview
The DUSART module clock is derived from one of the main clock sources via a ripple counter with 16 outputs. This allows the DUSART clock frequency to be set to the selected main clock frequency divided by between 22 and 217.
3.2.2
Clock Selection
Two bits in register ssm.div_sel are used to select the DUSART modules clock source, bit 11 and bit 1. Bit 11 = 0 and bit 1 = 0 selects HIGH_REF Bit 11 = 0 and bit 1 = 1 selects HIGH_PLL Bit 11 = 1 and bit 1 = 0 selects LOW_REF Bit 11 = 1 and bit 1 = 1 selects LOW_PLL
Bits 11:8 in register ssm.tap_sel1 select the ripple counter tap and thus the division ratio for the DUSART module clock. B0000 selects the least significant tap of the counter and divides by 4. (If the HIGH_PLL clock source is selected, values of 0 and 1 both set the division ratio to 23 = 8.) B0001 selects the next tap of the counter and divides by 8. . B1111 selects the most significant tap of the counter and divides by 217.
Setting bit 5 in register ssm.clk_en enables the module clock for the DUSART. In the example, the clock initialisation for the DUSART is performed by the supplied library function ssm_dusart_clk(). // Set dusart clock to 100MHz / 8 = 12.5 MHz ssm_dusart_clk(SSM_HIGH_PLL, 1);
26 May 2006
Page 5 of 26
AN014
Version 1.6
4 DUSART Configuration
4.1 Overview
The DUSART peripheral block provides a general purpose dual serial port. A number of different protocols are supported by hardware controllers, and any two different protocols may be assigned to the two channels of the DUSART. One of the available protocols provides a standard UART function. Note that the configuration tool within the CyanIDE package does not yet fully support all the DUSART options, and the application must configure the DUSART registers as required. For simplicity, the descriptions in this document refer only to channel A of the DUSART. Channel B operates in the same way and has a similar set of control registers.
4.2
4.2.1
Registers
Configuration
The configuration register dusart.a_cfg controls the DUSART protocol configuration for channel A, with the following options: Protocol: I2C, SPI, IFR, SCI, UART or user-defined Endianness: lsb first or msb first (user-defined protocol only) Parity: none, even or odd
In the example code, the configuration register is set for the UART protocol with no parity. // Configure dusart A for uart rg.dusart.a_cfg = 4;
4.2.2
Sample Clock
The register dusart.a_smpl_cfg defines the oversampling clock period for the selected protocol, and controls what filtering is applied to the three available input signals. The example code sets a period value of 35, giving the required clock frequency for 18x oversampling at 9600 baud. // Set oversampling clock for 9600 baud rg.dusart.a_smpl_cfg = 35;
4.2.3
Symbol Clock
Register dusart.a_sym_cfg defines the bit clock high and low times and thus the bit clock period (and duty cycle for synchronous protocols). The example code sets the high and low times of the serial data bit clock to 9 sample clock periods each. // Serial clock 9 ticks high, 9 ticks low rg.dusart.a_sym_cfg = 0x0808;
26 May 2006
Page 6 of 26
AN014
Version 1.6
4.2.4
Baud Rates
The following tables give suggested values for the sample clock period and symbol clock times for various baud rates, minimising the error in the actual baud rate. Other combinations of values are equally valid. Clock source set to HIGH_PLL, tap select set to 1 => divide by 23 = 8 => DUSART input clock = 12.5MHz. Baud rate 1200 2400 3600 4800 7200 9600 19200 38400 57600 115200 a_smpl_cfg 161 161 101 80 50 35 17 8 5 2 a_sym_cfg 0x0f0f 0x0707 0x0807 0x0707 0x0807 0x0808 0x0808 0x0808 0x0808 0x0808 Actual Baud rate 1205.6 2411.3 3604.4 4822.5 7208.8 9645.1 19290 38580 57870 115740 % error 0.5% 0.5% 0.1% 0.5% 0.1% 0.5% 0.5% 0.5% 0.5% 0.5%
Clock source set to LOW_PLL, tap select set to 0 => divide by 22 = 4 => DUSART input clock = 1.2288MHz. Baud rate 1200 2400 3600 4800 7200 9600 19200 38400 a_smpl_cfg 31 15 9 7 4 3 1 1 a_sym_cfg 0x0707 0x0707 0x0807 0x0707 0x0807 0x0707 0x0707 0x0303 Actual Baud rate 1200 2400 3614.1 4800 7228.2 9600 19200 38400 % error 0.0% 0.0% 0.4% 0.0% 0.4% 0.0% 0.0% 0.0%
4.2.5
Register dusart.a_tim_cfg defines the receive timeout and guard times for protocols which require them. In this example both are set to zero. // Receive timeout and guard time set to zero rg.dusart.a_tim_cfg = 0;
26 May 2006
Page 7 of 26
AN014
Version 1.6
4.2.6
UART Configuration
Register dusart.uart_cfg defines options specific to the UART protocol. Character size: 5, 6, 7 or 8 bits Stop bits: 1, 1.5 or 2 stop bits Receive input polarity Transmit output polarity
The example is written to use the RS-232 transceiver on the development board and requires the transmit and receive polarities set to active-high. // 8 data bits, 1 stop bit, normal polarity rg.dusart.uart_cfg = 0xc0;
4.2.7
UART Control
Register dusart.uart_ctrl controls the UART transmit, receive and break functions. Enable the transmitter and receiver by setting the appropriate bit fields. fd.dusart.uart_ctrl.tx_en = 1; fd.dusart.uart_ctrl.rx_en = 1; // Enable tx // Enable rx
4.2.8
Interrupt control
The interrupt control registers dusart.a_int_en, dusart.a_int_dis and dusart.a_int_clr are used to control interrupts from the DUSART. Register dusart.a_int_sts allows the interrupt status to be read. In this example application only two bits in these registers are used. Bit 2 rx0_1b_rdy. Register dusart.a0_rx8 contains one byte of data. The interrupt is cleared by reading from dusart.a0_rx8. An 8 bit value is returned. Bit 0 tx0_rdy. The transmit buffer is empty. The interrupt is cleared by writing to dusart.a0_tx8.
4.3
Port Assignment
The external interface for the UART function of the DUSART module can be assigned to port A, B or C. Normally this is set up using the configuration editor in the CyanIDE environment, but the register settings are described here for completeness. Register port.sel1 controls the configuration of I/O ports A to F. For this example, writing B011 to bits [6:4] configures port B for the UART signals on pins B.6 and B.7. Bit 1 of register port.en is set to enable the port output drivers for port B.
26 May 2006
Page 8 of 26
AN014
Version 1.6
4.4
The following example code shows how to configure the DUSART for the UART function. Note that the CyanIDE configuration editor now supports this function, and most of this code is not required in the application. The last line of code which enables the DUSART receive data ready interrupt is required in the application code, and should be included at a point when the application is ready to handle interrupts. // Set dusart clock to 100MHz / 8 = 12.5 MHz ssm_dusart_clk(SSM_HIGH_PLL, 1); // Configure dusart A for uart rg.dusart.a_cfg = 4; // Set oversampling clock divisor and bit clock times for 9600 baud rg.dusart.a_smpl_cfg = 35; rg.dusart.a_sym_cfg = 0x0808; rg.dusart.a_tim_cfg = 0; // Configure uart rg.dusart.uart_cfg = 0xc0; fd.dusart.uart_ctrl.tx_en = 1; fd.dusart.uart_ctrl.rx_en = 1; // Enable receive interrupt fd.dusart.a_int_en.rx0_1b_rdy = 1; // No timeouts // Normal polarity // Enable tx // Enable rx
26 May 2006
Page 9 of 26
AN014
Version 1.6
With these links fitted, the DUSART serial port is connected to the 9 way D-type plug J15 instead of DUART B.
26 May 2006
Page 10 of 26
AN014
Version 1.6
/****************************************************************************** Declaration of static functions. ******************************************************************************/ int putchar(int c); int _getchar(void); int txcount(void); int rxcount(void); // Read number of characters in transmit buffer // Read number of characters in receive buffer
// Called from irq service routines int __irq_code itxcount(void); // Read number of characters in transmit buffer int __irq_code irxcount(void); // Read number of characters in receive buffer /****************************************************************************** Global variables. ******************************************************************************/ char txbuf[TXBUFSIZE]; char rxbuf[RXBUFSIZE]; // Buffer index values int txeptr = 0; int txfptr = 0; int rxeptr = 0; int rxfptr = 0; // Transmit buffer // Receive buffer // // // // Transmit buffer empty index Transmit buffer fill index Receive buffer empty index Receive buffer fill index
26 May 2006
Page 11 of 26
AN014
Version 1.6
/****************************************************************************** Module global variables. ******************************************************************************/ /****************************************************************************** Definition of API functions. ******************************************************************************/ /****************************************************************************** NAME main SYNOPSIS int main(int argc, char *argv[]) FUNCTION When a character is received, display it on LCD, and echo it on both sw uart and normal uart RETURNS Exit code. ******************************************************************************/ int main(int argc, char *argv[]) { int count = 0; int c; lcd_rst(); lcd_puts("Example: uart"); lcd_xy(1, 2); // Dusart is now set up in configurator /* // Set dusart clock to 100MHz / 8 = 12.5 MHz ssm_dusart_clk(SSM_HIGH_PLL, 1); // Configure dusart A for uart rg.dusart.a_cfg = 4; // Set 18x oversampling clock (divide by 36) for 9600 baud rg.dusart.a_smpl_cfg = 35; rg.dusart.a_sym_cfg = 0x0808; // Serial clock 9 ticks high, 9 ticks low rg.dusart.a_tim_cfg = 0; // No timeouts // *** This code works for 9600 baud // Configure uart rg.dusart.uart_cfg = 0xc0; fd.dusart.uart_ctrl.tx_en = 1; fd.dusart.uart_ctrl.rx_en = 1; */ // Normal polarity // Enable tx // Enable rx
// Enable receive interrupt fd.dusart.a_int_en.rx0_1b_rdy = 1; // Main loop - read any received characters and echo them while (1) { if (rxcount() > 0) // Any characters received? { c = getchar(); // Yes, read character putchar(c); // Echo it count++; count %= 16; if (count == 0) { lcd_xy(1, 2); } lcd_putc(c); duart_a_tx(c); // Count character (for lcd) // Wrap at 16 chars, lcd is 16 columns wide // Reposition cursor at start of 2nd display line // Send character to lcd // Also send character to std serial port A
// Check for a carriage return and send line feed if ('\r' == c) { putchar('\n');
26 May 2006
Page 12 of 26
AN014
Version 1.6
count = 0; // Reset lcd counter lcd_xy(1, 2); // Reposition cursor duart_a_tx('\n'); } } } return 0; } // Put character in transmit buffer int putchar(int c) { while (txcount() >= (TXBUFSIZE - 1)) // Wait for space in transmit buffer ; if (txcount() < (TXBUFSIZE - 1)) { txbuf[txfptr] = (char)c; if (++txfptr >= TXBUFSIZE) txfptr = 0; } fd.dusart.a_int_en.tx0_rdy = 1; return (c); } // Read character from receive buffer int _getchar(void) { int c = 0; if (rxcount() > 0) { c = (int)rxbuf[rxeptr]; if (++rxeptr >= RXBUFSIZE) rxeptr = 0; } return (c); } // Returns number of characters in transmit buffer int txcount(void) { int chars_pending = txfptr - txeptr; if (chars_pending < 0) chars_pending += TXBUFSIZE; return (chars_pending); } // Returns number of characters in receive buffer int rxcount(void) { int chars_received = rxfptr - rxeptr; if (chars_received < 0) chars_received += RXBUFSIZE; return (chars_received); } /****************************************************************************** NAME usr_tx_handler SYNOPSIS void __irq_entry usr_tx_handler(void) // Any characters received? // Yes, read character from buffer // Check for index pointer wraparound // Is there space in transmit buffer? // Yes, put character into buffer // Check for index pointer wraparound
26 May 2006
Page 13 of 26
AN014
Version 1.6
FUNCTION Interrupt handler for usr transmit ready RETURNS Nothing. ******************************************************************************/ void __irq_entry usr_tx_handler(void) { // Read tx interrupt status register int test = fd.dusart.a_int_sts.tx0_rdy; // Transmitter ready? if (1 == test) { // Yes, any characters to send? if (itxcount() > 0) { // Yes, get character from buffer rg.dusart.a0_tx8 = txbuf[txeptr]; if (++txeptr >= TXBUFSIZE) // Check for index pointer wraparound txeptr = 0; } else // No characters left in transmit buffer { // Disable transmitter ready interrupt fd.dusart.a_int_dis.tx0_rdy = 1; } } } /****************************************************************************** NAME usr_rx_handler SYNOPSIS void __irq_entry usr_rx_handler(void) FUNCTION Interrupt handler for usr receive ready RETURNS Nothing. ******************************************************************************/ void __irq_entry usr_rx_handler(void) { // Read rx interrupt status register int test = fd.dusart.a_int_sts.rx0_1b_rdy; // Received character ready? if (1 == test) { // Yes, read receive register char c = rg.dusart.a0_rx8; // Is there space in receive buffer? if (irxcount() < (RXBUFSIZE - 1)) { // Yes, put character into input buffer rxbuf[rxfptr] = c; if (++rxfptr >= RXBUFSIZE) // Check for index pointer wraparound rxfptr = 0; } } } // Duplicate buffer count routines for use by interrupt service routines // Return number of characters in transmit buffer int __irq_code itxcount(void) { int chars_pending = txfptr - txeptr;
26 May 2006
Page 14 of 26
AN014
Version 1.6
if (chars_pending < 0) chars_pending += TXBUFSIZE; return (chars_pending); } // Return number of characters in receive buffer int __irq_code irxcount(void) { int chars_received = rxfptr - rxeptr; if (chars_received < 0) chars_received += RXBUFSIZE; return (chars_received); } /****************************************************************************** NAME usr_ex_handler SYNOPSIS void __irq_entry usr_ex_handler(void) FUNCTION Interrupt handler for usr exceptions RETURNS Nothing. ******************************************************************************/ void __irq_entry usr_ex_handler(void) { // Clear any interrupt rg.dusart.a_ex_clr = 0xfff; // Disable any interrupt rg.dusart.a_ex_dis = 0xfff; }
26 May 2006
Page 15 of 26
AN014
Version 1.6
A.2
cstartup.asm
;============================================================================== ; Cyan Technology Ltd ; ; FILE ; cstartup.asm - Assembler startup for C programs. ; ; DESCRIPTION ; Defines C segments. Contains initial code called before C is started ;============================================================================== MODULE .ALL ; ; ; ; ; ; cstartup
C reserves DATA address 0 for the NULL pointer. The value H'DEAD is put in here so that it is easier to spot the effect of a NULL pointer during debugging. User memory for constants grows upwards from H'0001. The first address is given the equate symbol $??LO_ADDR. .SEG ORG dc EQU C_RESERVED1 0 H'DEAD $
$??LO_ADDR ; ; ; ; ; ; ; ; ; ; ;
DATA addresses H'EFE0-H'EFFF are used for scratchpad RAM in interrupt mode. DATA addresses H'EFC0-H'EFDF are used for scratchpad RAM in user mode. DATA addresses H'EFB8-H'EFBF are used for register storage in interrupt mode. Then follows the interrupt stack, user stack and user heap. User memory for variables grows downwards from the end of the user stack. This version of cstartup only contains one area of scratchpad RAM which constrains users not to write re-entrant re-interruptable code. The interrupt stack must start at IY-38 to be compatible with the C compiler. .SEG ORG C_RESERVED2 H'EFB8 $ 8 32 $ $ 32 ; Interrupt register storage ; User Scratchpad
$??HI_ADDR
DEQU ds ds DEQU
IY_SCRATCH
$?irq_scratchpad? DEQU ds ; ; ; ; ; ;
; Interrupt Scratchpad
The registers that control the functional blocks of the eCOG1 are located at addresses H'FEA0 to H'FFCF. The C header file <ecog1.h> declares an external structure that descibes the registers. This variable is defined below. .SEG ORG REGISTERS H'FEA0 304
$fd: $rg
ds
; ; C requires the following segments: ; CONST - Constants in ROM. For example: ; const char c = 'c' ; ; printf( "Hello World!" ) ; ; VAR - Variables in RAM. These are set to zero by the cstartup code. ; For example: ; int i ; (in file scope) ; static int i ; (in function scope) ; INIT - Initialisd variables in RAM. For example: ; int i = 9 ; (in file scope) ; static int i = 9 ; (in function scope) ; INITC - Initialisation data for the INIT segment ; HEAP - The heap. Required if malloc() etc. are used. ; STACK - The stack. Always required.
26 May 2006
Page 16 of 26
AN014
Version 1.6
; ; The memory allocated to each segment is defined by the value of ; $??<segment_name>_SIZE as set below. These sizes can be set manually or, if ; the appropriate line is tagged with !PACK and the -pack option is specified ; to ECOGCL, ECOGCL will write in the size actually required for the segment. ; The sizes of the STACK and HEAP segments must be set by the user. ; $??ISTACK_SIZE = H'0040 $??STACK_SIZE = H'0100 $??HEAP_SIZE = H'0080 ; ROM segments $??INITC_SIZE $??CONST_SIZE ; RAM segments $??INIT_SIZE $??VAR_SIZE = = = = h'0005 h'0009 h'0005 h'0058 ; !PACK ; !PACK ; !PACK ; !PACK
; -- Locate DATA segments in memory -; ; Segments are allocated sequentially by the ??ALLOCATE macro. They may be ; set at fixed addresses by setting ADDR prior to calling ??ALLOCATE. ; ??ALLOCATE MACRO seg .SEG &seg ORG ADDR $??&seg!_LO = ADDR ADDR = ADDR + $??&seg!_SIZE $??&seg!_HI = ADDR-1 ENDMAC ; Allocate DATA ROM ADDR = $??LO_ADDR ??ALLOCATE INITC ??ALLOCATE CONST ; Allocate DATA RAM ADDR = $??HI_ADDR - $??VAR_SIZE - $??INIT_SIZE ADDR = ADDR - $??ISTACK_SIZE - $??STACK_SIZE - $??HEAP_SIZE ??ALLOCATE INIT ??ALLOCATE VAR ??ALLOCATE HEAP ??ALLOCATE STACK ??ALLOCATE ISTACK ; -- Memory initialisation macros -; ; Segments may be initialised by filling with a constant value using the ; ??SEGFILL macro. Two symbols are passed, the segment name and the value to ; fill with. A third symbol (the size) is assumed. ; ??SEGFILL MACRO seg, value LOCAL fill_loop IF $??&seg!_SIZE ld x, #$??&seg ld al, #$??&seg!_SIZE ld ah, &value &fill_loop: st ah, @(0,x) add x, #1 sub al, #1 bne &fill_loop ENDIF ENDMAC ; ; Segments may be initialised by copying an initialisation segment with ; the ??SEGCOPY macro. Two symbols are passed, the source and destination ; segment names. ; ??SEGCOPY MACRO src, dest IF $??&src!_SIZE NE $??&dest!_SIZE .ERR "Copy segments different sizes" ENDIF IF $??&src!_SIZE
26 May 2006
Page 17 of 26
AN014
Version 1.6
ld ld ld bc ENDIF ENDMAC
; ; Fills a block of memory with a value. Three values are passed, the start ; address for the block, the number of addresses to write to and the value ; to be written. ; ??MEMFILL MACRO start, length, value LOCAL fill_loop ld x, &start ld al, &length ld ah, &value &fill_loop: st ah, @(0,x) add x, #1 sub al, #1 bne &fill_loop ENDMAC ; ; Input argument for main(). ; .SEG CONST argv dc 0,0 ; ; Start of Code. ; .CODE ORG $?cstart_code: bra $ecog1ConfigMMU ; configure MMU and Cache Banks $ecog1ConfigContinue: ; ; Initialise segments. The HEAP and STACK are filled with H'9999 and H'aaaa ; respectively so that their maximum runtime extents can be checked. The ; INIT segment is set from the ROM initialisers in the INITC segment. The non ; initialised RAM segment VAR is set to zero (compiler puts 0 initialised ; variables in these segments as well as uninitialised ones,x). ; ??SEGFILL HEAP, #h'9999 ??SEGFILL STACK, #h'AAAA ??SEGFILL ISTACK, #h'BBBB ??SEGCOPY INITC, INIT ??SEGFILL VAR, #h'0 ; Set interrupt stack pointer. ld y, #IY_SCRATCH ; Set user mode flag st ld or st ld to allow interupts. flags, @(-1,y) al, @(-1,y) al, #h'10 al, @(-1,y) flags, @(-1,y) H'40
; Set usermode stack pointer ld y, #$??STACK_HI ; Call ecog1Config to setup eCOG1 peripherals ; Defined in module produced by configuration compiler bsr $ecog1Config ; Call main, setting argc and argv[0] to 0. ld ah, #argv ld al, #0 bsr $main
26 May 2006
Page 18 of 26
AN014
Version 1.6
; ; Main may exit by returning or by explicitly calling $exit. In either case ; exit code will be in AL. ; $exit: brk ; Alert the user if in debug mode bra 0 ; Restart ; ; This is the minimal interrupt routine. The contents of FLAGS is restored ; as the program counter is restored using rti. ; $minimal_handler: st flags,@(-33,y) ; Store Flags st al, @(-34,y) ; Store AL ld al, @(-33,y) or al, #h'0010 st al, @(-33,y) brk ld al, @(-34,y) rti @(-33,y) ; Put Flags into AL ; Set usermode ; Store the value to be restored to Flags ; Alert the user if in debug mode ; Restore AL ; Restore PC and Flags
; ; The address exception can happen often during development. A handler ; is put here to catch the exception. ; $address_error: st flags,@(-33,y) ; Store Flags st al, @(-34,y) ; Store AL ld al, @(-33,y) or al, #h'0010 st al, @(-33,y) brk ld al, #h'a st al, @h'ff69 ld al, #h'200 st al, @h'ff7a ld al, @(-34,y) rti @(-33,y) ; End of startup code $??CSTARTUP_END EQU $ ENDMOD ; Put Flags into AL ; Set usermode ; Store the value to be restored to Flags ; Alert the user if in debug mode ; Clear status in mmu.address_exception ; Clear status in emi.ctrl_sts ; Restore AL ; Restore PC and Flags
26 May 2006
Page 19 of 26
AN014
Version 1.6
A.3
irq.asm
;============================================================================== ; Cyan Technology Ltd ; Example application software for eCOG ; ; FILE - irq.asm ; Contains the interrupt vectors and the initial branch to the main code. ;============================================================================== MODULE irq .ALL ; Interrupt vectors are sign-extended 24 bit absolute branch addresses. For ; example a vector containing H'1234 will start executing at H'1234 and a ; vector containing H'8765 will start executing at H'ff8765. ; ORG H'0 bra $?cstart_code ORG ex_debug ex_tim_wdog_ufl ex_adr_err reserved ex_tim ex_intact ex_usart_a ex_usart_b ex_uart_a ex_uart_b int_tim_tmr_ufl int_tim_cnt1_ufl int_tim_cnt2_ufl int_tim_cnt1_match int_tim_cnt2_match int_tim_pwm1_ufl int_tim_pwm2_ufl int_tim_pwm1_match int_tim_pwm2_match int_tim_cap_ofl int_tim_cap1 int_tim_cap2 int_tim_cap3 int_tim_cap4 int_tim_cap5 int_tim_cap6 int_tim_ltmr_ufl int_intact_cpu_rx_rdy int_intact_cpu_tx_rdy int_intact_dma_rdy int_intact_dma_done int_intact_up_clk_inact int_intact_up_rx_purge int_intact_down_clk_inact int_intact_down_rx_purge int_usart_a_rx int_usart_a_tx int_usart_b_rx int_usart_b_tx int_sci_tx_done int_sci_tx_err int_sci int_ifr_tx_done int_ifr_rx_done int_ifr_rx_err int_ifr_frame_done int_uart_a_tx_rdy int_uart_a_rx_rdy int_uart_b_tx_rdy int_uart_b_rx_rdy int_ehi int_gpio int_adc ENDMOD H'4 DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC DC $minimal_handler $minimal_handler $address_error $minimal_handler $minimal_handler $minimal_handler $usr_ex_handler?? $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $usr_rx_handler?? $usr_tx_handler?? $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler $minimal_handler
26 May 2006
Page 20 of 26
AN014
Version 1.6
A.4
; ; ; ; ; ; ; ; ; ; ; ;
devboard.asm
============================================================================= CREATED by eCOG1 Configuration Compiler Version 1.00.0001 DATE 28/02/2005 14:22:41 INPUT : devboard.cfg WARNING! Any changes made to this file will be lost when it is regenerated by the eCOG1 Configuration Compiler ============================================================================= MODULE devboard .CODE .LARGE ORG $??CSTARTUP_END
; Define symbols used in mmu initialisation ; Internal flash code area addresses $??code_log = 0 $??code_phy = 0 $??code_siz = H'8000 $ecog1ConfigMMU: ; ; ; ; ; ; ; -----------------------; Configure MMU (part 1) -----------------------Setup MMU to enable cache configuration Get address of mmu registers ld x, #h'ff43 Disable all (flash code ld al, st al, ; &mmu.translate_en
unwanted mmu translations initially and sram data areas are always enabled) #0 @(0,x) ; mmu.translate_en
; ;
Initialise mmu for flash code area 1. CODE H'0000-H'7FFF IROM H'0000-H'7FFF 32Kwords ld al, #($??code_log SHR 8) st al, @(1,x) ; mmu.flash_code_log ld al, #($??code_phy SHR 8) st al, @(2,x) ; mmu.flash_code_phy ld al, #(($??code_siz - 1) SHR 8) st al, @(3,x) ; mmu.flash_code_size ------------------Cache Configuration -------------------
; ; ;
; macro used for initialisation of cache banks ??MEMFILL MACRO start, length, value LOCAL fill_loop ld x, &start ld al, &length ld ah, &value &fill_loop: st ah, @(0,x) add x, #1 sub al, #1 bne &fill_loop ENDMAC ld st ; AH,#H'0 AH,@H'ff42 ; Enable both Cache banks for data access
Set physical mappings of cache banks ld al, #h'10 ; map cache bank 0 at 0x1000 - 0x11ff st al, @h'ff59 ; mmu.cache0_data_log ld al, #h'12 ; map cache bank 1 at 0x1200 - 0x13ff
26 May 2006
Page 21 of 26
AN014
Version 1.6
st ;
al, @h'ff5a
; mmu.cache1_data_log
Map both cache banks in data space ld al, @h'ff43 ; read mmu.translate_en or al, #h'180 ; map both cache banks to data space st al, @h'ff43 ; set mmu.translate_en Invalidate cache contents ??MEMFILL #h'1000, #h'100, ??MEMFILL #h'1100, #h'100, ??MEMFILL #h'1200, #h'100, ??MEMFILL #h'1300, #h'100, #h'0 #h'8000 #h'0 #h'8000
Unmap both cache banks from data space ld al, @h'ff43 ; read mmu.translate_en and al, #h'fe7f ; unmap both cache banks from data space st al, @h'ff43 ; set mmu.translate_en Enable cache memory Mode is 'One Way 512 Words' ld AH,#H'10 st AH,@H'ff41 ; ld st AH,#H'3 AH,@H'ff42 ;
; ;
; Configure Cache ; Enable Cache ; Three NOPs are required following ; the enable
Wait for HW nop nop nop Clock Setup Notes 32kHz and 5 MHz xtal fitted
; ; ; ; ; ; ; ; ; ; ; ; ; ;
Possible peripheral clock sources are: Low Ref Low PLL High Ref High PLL --------------------------------Configuring CPU and memory clocks --------------------------------Enabling in_clk source - High PLL ld AH,#H'8001 st AH,@H'ff6c ; ssm.clk_en CPU frequency > 10 MHz - inserting flash wait state ld AH,#H'2 st AH,@H'ff67 ; mmu.flash_ctrl Setting prescalar and divider ld AH,#H'37 st AH,@H'ff72 ; ssm.cpu
; Setting in_clk source ?LOOP1: ld AH,#H'20 st AH,@H'ff74 ; ssm.cfg ld asr and cmp bne ; ; AL,@H'ff72 #8 AL,#15 AL,#2 ?LOOP1 ; ssm.cpu
------------------Port configuration: ; A 11 ; B 3 ; C 7 ; D 1 ; E 0
26 May 2006
Page 22 of 26
AN014
Version 1.6
; F 0 ; G 0 ; H 0 ; I 0 ; J 3 ; K 99 ; L 2 ------------------ld st ld st ld st ld st AH,#H'7bb AH,@H'ff9c AH,#H'bc0 AH,@H'ff9d AH,#H'fff AH,@H'ff9e AH,#H'0 AH,@H'ff9f ; port.sel1 ; port.sel2 ; port.en ; port.dis
; ; ;
------------------;GPIO Configuration ------------------st st st st st st st st ld st ld st ld st st ld st ld st st ld st AH,@H'ffa5 AH,@H'ffa6 AH,@H'ffa7 AH,@H'ffa8 AH,@H'ffa9 AH,@H'ffaa AH,@H'ffab AH,@H'ffac AH,#H'5555 AH,@H'ffad AH,#H'a5aa AH,@H'ffae AH,#H'aaaa AH,@H'ffaf AH,@H'ffb0 AH,#H'aaa5 AH,@H'ffb1 AH,#H'aaaa AH,@H'ffb2 AH,@H'ffb3 AH,#H'a AH,@H'ffb4 ; io.gp0_3_cfg ; io.gp4_7_cfg ; io.gp8_11_cfg ; io.gp12_15_cfg ; io.gp16_19_cfg ; io.gp20_23_cfg ; io.gp24_27_cfg ; io.gp28_cfg ; io.gp0_3_out ; io.gp4_7_out ; io.gp8_11_out ; io.gp12_15_out ; io.gp16_19_out ; io.gp20_23_out ; io.gp24_27_out ; io.gp28_out
; ; ;
----------------EMI Configuration ----------------ld st ld st ld st AH,#H'37 AH,@H'ff7b AH,#H'3000 AH,@H'ff7c AH,#H'940d AH,@H'ff7d ; emi.bus_cfg1 ; emi.bus_cfg2 ; emi.sdram_cfg
26 May 2006
Page 23 of 26
AN014
Version 1.6
ld st ld st ld st ld st st ld st ; ; ;
AH,#H'330c AH,@H'ff80 AH,#H'10 AH,@H'ff81 AH,#H'8a4 AH,@H'ff7a AH,#H'4000 AH,@H'ff6b AH,@H'ff6c AH,#H'200 AH,@H'ff7a
Map CodeFlash Physical 0 - 7fff to Logical Code 0 - 7fff ld al, #h'0 st al, @(1,x) ; mmu.xxx_log h'ff44 st al, @(2,x) ; mmu.xxx_phys h'ff45 ld al, #h'7f st al, @(3,x) ; mmu.xxx_size h'ff46 Map DataFlash Physical 7800 - 7fff to Logical Data 0 - 7ff ld al, #h'0 st al, @(13,x) ; mmu.xxx_log h'ff50 ld al, #h'78 st al, @(14,x) ; mmu.xxx_phys h'ff51 ld al, #h'7 st al, @(15,x) ; mmu.xxx_size h'ff52 Map DataRam0 Physical 0 - 7ff to Logical Data e800 - efff ld al, #h'e8 st al, @(16,x) ; mmu.xxx_log h'ff53 ld al, #h'0 st al, @(17,x) ; mmu.xxx_phys h'ff54 ld al, #h'7 st al, @(18,x) ; mmu.xxx_size h'ff55 Enable translations ld al, #h'10 st al, @(0,x)
; mmu.translate_enable
; ;
Clear the address exception. These can be active when the software has done a self reset using the if_reset and cpu_reset bits. ld al,#h'a st al,@h'ff69 ; Clear status in mmu.address_exception bra $ecog1ConfigContinue
; ; ;
$ecog1Config: ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;UART on USART Configuration ;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Setting up UART on DUSART Channel A ld AH,#H'4 st AH,@H'feb4 ; dusart.a_cfg ld st ; AH,#H'0 AH,@H'feb7 ; dusart.a_tim_cfg
26 May 2006
Page 24 of 26
AN014
Version 1.6
st ld st ld st ld st ; ; ;
Enable DUSART clock source Enable divider chain for DUSART Using High PLL ld AH,#H'4 st AH,@H'ff6b ; ssm.rst_clr Select ld and or st Select ld and or st DUSART clock source AH,@H'ff75 ; ssm.div_sel AH,#B'1111011111111101 ; clear DUSART selections AH,#H'2 AH,@H'ff75 DUSART Divider tap AH,@H'ff76 AH,#H'f0ff AH,#H'100 AH,@H'ff76 ; ssm.tap_sel1
; ssm.rst_clr ; ssm.clk_en
; ; ;
-----------------------UART A & B Configuration -----------------------ld st st st AH,#H'0 AH,@H'fea1 AH,@H'fea2 AH,@H'feab ; duart.frame_cfg ; duart.a_tmr_cfg ; duart.b_tmr_cfg
; ; ;
Configure DUART clock source Enable divider chain for DUART Using High PLL ld AH,#H'4 st AH,@H'ff6b ; ssm.rst_clr Select ld and or st Select ld and st DUART clock source AH,@H'ff75 ; ssm.div_sel AH,#B'1111101111111110 ; clear DUART selections AH,#H'1 AH,@H'ff75 DUART Divider tap AH,@H'ff76 AH,#H'ff0f AH,@H'ff76 ; ssm.tap_sel1
Setting UARTA baud rate to 9600 (actual = 9645.06, divider = 80) ld AH,#H'50 st AH,@H'fea3 ; duart.a_baud Setting UARTB baud rate to 9600 (actual = 9645.06, divider = 80) st AH,@H'feac ; duart.b_baud Enabling duart clocks ld AH,#H'10 st AH,@H'ff6b ; ssm.rst_clr
; ;
26 May 2006
Page 25 of 26
AN014
Version 1.6
ld st ;
AH,#H'18 AH,@H'ff6c
; ssm.clk_en
Enabling duart tx/rx ld AH,#H'145 st AH,@H'fea0 ------------------Sleep Configuration ------------------Select ld and st ld and st rts ENDMOD
; duart.ctrl
; ; ; ;
Sleep Timeout clock source AH,@H'ff75 ; ssm.div_sel AH,#B'1101111111111111 ; clear Sleep timeout selections AH,@H'ff75 AH,@H'ff76 AH,#H'fff0 AH,@H'ff76 ; ssm.tap_sel1
; ; ;
26 May 2006
Page 26 of 26