[PDF] H8 Microcontroller Series Application Notes Collection
Có thể bạn quan tâm
Search
- Categories
- Top Downloads
- Login
- Register Search
- Home
- Oct 1996 Lit. No A. H8 Microcontroller Series Application Notes Collection
Short Description
1 Oct 1996 Lit. No A H8 Microcontroller Series Application Notes Collection2 H8 Microcontroller Series Application Notes...Description
Oct 1996 Lit. No. 21-098A H8 Microcontroller Series Application Notes Collection H8 Microcontroller Series Application Notes Content App.Note Number CPU, Title APPS/001/1.0 APPS/003/1.0 APPS/004/1.0 H8/300, Physical and Logical Address Space H8/325, Configuring the 8-bit timer to create PWM waveforms H8/300, Development and Debugging Code using the Banked Memory models for the H8/300 H8 Series, Using the S-Record file splitting utility ‘splitter’ H8/300, Serial communications interface H8/300, Analogue to digital converter 4 APPS/010/1.0 H8/300, Digital to analogue converter H8, EPROM security on the H8/300 and H8/500 Families H8/300H, DMA request and transfer time for H8/300H H8/300H, Interfacing various bit-size DRAM to the 300H H8/3003, Adding the damping resistor to the oscillator H8/300H, Enabling DMA end-of-transfer interrupts H8/304X, Multiplexed I/O functions on the 3003 and 304X H8/300, ‘C’ code framework example program H8, Memory checking and initialisation program H8/325, Interfacing to LCD character modules H8/300H, Software UART implementation using 2 timer and 2 DMA channels APPS/005/1.0 APPS/008/1.0 APPS/009/1.0 APPS/011/1.0 APPS/012/1.0 APPS/013/1.0 APPS/014/1.0 APPS/015/1.0 APPS/016/1.0 APPS/019/1.0 APPS/022/1.0 APPS/026/1.0 APPS/036/1.0 APPS/002/1.0 APPS/006/1.0 APPS/007/1.0 APPS/029/1.1 APPS/032/1.1 APPS/037/1.1 APPS/043/1.0 APPS/044/1.0 APPS/045/1.0 APPS/048/1.1 APPS/049/1.1 APPS/050/1.2 APPS/051/1.0 A Mechanism for Banking Data on the H8/300 Example Assembler Fuzzy Driver Routine, which can be called from C Writing Downloadable C code using the IAR C Compiler H8/300 C Code Demonstration Program H8-3042 Framework Program H8/300H Software UART implementation using 2 Timer and 2 DMA channels Flat Panel Displays - EMI Considerations H8/300H Direct Memory Access Channel (DMAC) example H8/300H Direct Memory Access Channel (DMAC) - Serial communication example LCD character module control using H8_300H Producing Optimised C for 300/300H Controllers Memory Access Speed on the H8/300H Real time low power sheduler for the 300L series. Pages 5 3 4 4 6 2 3 2 5 1 2 4 9 7 4 13 6 6 13 4 9 12 4 4 5 10 12 2 7 Hitachi Europe Ltd. ISSUE : APPLICATION NOTE D ATE : 23/11/93 APPS/001/1.0 ________________________________________________________ H8/300 Physical and Logical Address Space The H8/300 C compiler can be used to produce code which is greater in size than the total address space of the microcontroller. The banked (b) and mini-banked (m) memory models make use of an I/O port to extend the address bus by up to 8 bits for code only. Each time a given function is called a bank switch may have to be undertaken to access the memory device / area containing it, thus a table of addresses must be available to be able to perform the bank switch, this is created for you by the compiler in the segment FLIST. Each vector in FLIST has the following structure: Figure 1: Structure of FLIST vector in banked models 31 24 23 16 15 bank number 0 16-bit offset address The default I/O port used is Port 4, but this can be changed by modifying the CSTARTUP and L07 assembler source files. The start address, size, separation and type of banked segments is defined at link time using the following format: -b()=,, where: is ≅# for physical addressing or blank for logical addressing is ≅CODE to define the correct segment type is the comma separated list of segment names to be included in the banks is the start address in hexadecimal is the bank size in hexadecimal is the logical offset between the start addresses of successive banks There are two ways to allocate memory to banked segments at link time - either Logically or Physically the difference is defined below, using the example of a three code bank system, where the banks are of size H 4000. Hitachi Europe Ltd. ISSUE : APPS/003/1.0 APPLICATION NOTE D ATE : 10/12/93 ________________________________________________________ Configuring the 8 - bit timer on the H8-325 to create PWM waveforms The H8/325 series have one 16 bit free-running timer and two multifunctional 8bit timers on board. Each of the two 8 bit timers have two registers; TCORA and TCORB associated with it. The values contained in these registers are compared with the timer register -TCNT. If a match occurs then an interrupt will be requested. An interrupt request will also occur if the timer overflow (FFH > 00H) occurs. If enabled, the interrupt requests will cause the program to vector to the appropriate interrupt service routine. TCORA and TCORB are both set to FFH after reset, whilst the timer control and status registers are depicted below. Figure 1 - 8-bit Timer Control/Status Registers TCR - REGISTER CMIEB CMIEA OVIE CCLR1 CCLR0 CKS2 CKS1 bi t7 bi t 0 Compa re ma tch Ena bl es/Di sa bl es Sel ect th e wa y i n Interrupt ena ble for Overflow Interrupt- wh i ch th e counter registers A or B (OVI) i f OVF i s set. i s reset. TCSR - REGISTER CMFB CMFA OVF ----- OS3 Determines th e source from wh i ch th e counter i ncrements i e. Interna l /Externa l OS2 bi t7 Compa re ma tch fl a gs A a nd B . CKS0 OS1 OS0 bi t 0 Overfl ow Fl a gMust be clea red by software. Sel ect th e a cti on performed by th e rel eva nt output pi n for compa re/ma tch wi th regi ster B . Sel ect th e acti on performed by th e rel evant output pi n for compa re/ma tch wi th regi ster A. Creating a PWM waveform By using the compare/match facility to toggle an output pin, PWM can be achieved using the 8-bit timers. The following code example demonstrates this effect and creates a waveform of 50% duty cycle, see figure2, below. Software intervention is not required, hence no interrupt service routines are used. NB. By changing the initial values of TMR0_TCORA and TMR0_TCORB, the 1 of 3 duty cycle can be altered. Program #include void init_timer (void) { TMR0_TCORA = 0xE0; TMR0_TCORB = 0x70; TMR0_TCSR = 0x06; /* include I/O header files */ /* sets pulse rate /* sets pulse width /* o/p '0' on compare B /* o/p '1' on compare A */ */ */ */ } int main (void) { init_timer(); /* initialise the 8-bit timer ctrl registers */ TMR0_TCR |= 0x0B; /* start timer with phi/1024 internal clock /* timer reset on comp/match with TCORA */ while(1); /* main code sequence ... repeat ≅forever } Figure 2 - Output Waveform 0xFF 0xE0 TCNT 0x70 0x00 TM0 1 Output Pin 0 2 of 3 */ */ Hitachi Europe Ltd. ISSUE : APPS/004/1.0 APPLICATION NOTE D ATE : 7/2/94 ________________________________________________________ Developing and Debugging Code using the Banked memory models for the H8/300 The H8/300 series of microcontrollers have a linear 64KByte address range. The C compiler does directly support an extended ≅banked address range for code. The banked memory model used by the compiler extends the effective address bus by utilising a number of I/O pins to switch between banked external memory (see the H8/300 C tools tutorial for more information). The linker provided with the C compiler produces a single output file in the format specified by the user (usually Motorola S-Record format). The S-Record file contains the following: 1, Constant ROM segments (vectors, constants and initialisers) 2, Startup code ROM segments. 3, Library code ROM segments. 4, Non-banked user code ROM segments. 5, Banked user code ROM segments. 6, Various data RAM segments. Having generated the S-Record files the user then may decide to debug the code using an evaluation board, or an in-circuit emulator, or to program an H8 device and try to run the code directly. In Circuit Emulators: The Hitachi in circuit emulators PCE83XX do not directly support the banked memory models as the I/O lines used to switch banks are user defined and may be changed dynamically in some systems. Thus the full S-Record file cannot be loaded into the device as the banked segments contained in the object code will be outside the addressing range of the PCE83XX. One approach is to separate the banked segments from the object code, and then load them into external memory on the target board (i.e. not emulator memory). There are two hurdles to overcome in doing this, firstly the object code needs to be dissected , and secondly the target memory needs to be programmed. 1 of 4 i, Dissecting the S-Record Object file: The user may dissect a S-Record file by hand using an EPROM programmer to load in the whole file, then selectively save blocks to separate files. This however can take some time to do, and will have to be repeated each time the user has a new revision of code to debug. The process as a whole is prone to errors and will increase the development time unnecessarily. ii, Moving the S-Record addresses: Given that the banks of code exist in separate files, the base file may be loaded into an In-Circuit Emulator (ICE) for debugging. The memory on the target board which is to contain the banked code segments must then be programmed. Usually the finished product will use EPROM devices to store the banks. Typically many banks will typically exist in one EPROM, thus the EPROM will need to have the banks contiguously loaded from address 0. To move logically spaced S-Records into one contiguous range suitable for loading into a single EPROM the user will need to cut and paste all of the banks using an EPROM programmer. Once again the process will take some time and is fraught with possible errors. iii, Choosing the storage medium: Once the user has generated separate files which contain the code / data to exist on the H8 microcontroller and one or more banked code segment files, the data needs to be programmed into the target memory. Usually this has been achieved using EPROMs, as this matches the final production run for the target hardware, however this will be a slow process as the EPROMs will have to be erased and then reprogrammed. A quicker solution is to use SRAM on the target and program it directly from the ICE. This can be achieved using the following method: 1, Compile and link the banked code using the IAR tools using logical addressing. 2, Use the Hitachi ≅splitter routine to segment the file in the following manner: a, Place all H8 files into a single output file without moving them. b, Place bank 0 code into another file without moving the bank base address. c, Place all successive banks in separate files and move the base address of each to the start address of bank 0. 3, Use the ICE to set up a series of macros to perform the following: a, Set the I/O lines responsible for addressing bank 0 b, load in the S-record file for bank 0 ...and repeat for banks 1..N 2 of 4 The ICE will effectively switch the address decoding on the target hardware to point to the correct SRAM bank start address, and then the bank will be loaded into area using the ICE to load the S-Record file (which has the correct lower 16-bit addresses). In short the ≅splitter utility is used to separate all banks into separate files and then move all banks so that they occupy the same address range (the lower 16-bits of the actual bank address). The full bank address is reconstructed by the ICE just before loading of the bank from the file using the I/O ports as defined by the bank switching routine L07. The Hitachi utility ≅splitter is available on request from Hitachi, and is supplemented by applications note APPS/005. 3 of 4 Hitachi Europe Ltd. ISSUE : APPS/005/1.0 APPLICATION NOTE D ATE : 19/1/94 ________________________________________________________ Using the S-Record file splitting utility ≅splitter Hitachi has produced a utility to enable code developers to reformat the object code produced by the IAR C compiler / linker. The ≅splitter utility has been written for customers who wish to develop and debug code which is to reside in target system memory (i.e. not on an in-circuit emulator). The decoding logic used to define the target memory map may require that the logical addresses put out by the H8 processor do not correspond to the actual addresses the code resides in. Splitter Specification The splitter utility allows the user to take a single S-Record object file and split it into a number of separate files, the features are: 1, The splitter utility uses a textual format file to define the input file (i.e. linker produced S-Record file), the names of all of the output files, and the addresses and ranges of the segments to move. 2, Each output file may have a number of segment areas associated with it. 3, Each segment area may have its base address moved to any address. 4, Segments which need to be ≅shadowed can be copied to any number of output files. 5, Each shadow segment may have its base address moved. 6, In performing the split, it may be necessary to change the base address for many S-Records, and in addition certain S1 records may need to be translated into S 2 records to handle a wider address range. This is all done automatically by splitter with the appropriate recalculation of checksums where necessary. 6, ≅splitter checks the given format file for segment clashes and invalid ranges. In addition if an S-Record exists in the input file which has no defined output destination the user is informed of the error and the splitting process stops. 7, On completion ≅splitter informs the user of the total number of S-Records processed. Format File Specification A line in the format file may take one of the following forms: 1 of 4 1, Input file name specification line contains ≅-I, whitespace, then the filename in double quotes: e.g. -I ∋input.obj 2, Output file specification for a segment ≅-O plus filename, the segment range (in hexadecimal or decimal) plus an optional new base address: e.g. -O ∋out1.obj 0x1000 0x1FFF e.g. -O ∋out2.obj 0x1000 0x1FFF BASE 0x20000 If no BASE value is specified the S-Records are copied to the new file directly, without modification. 3, Copied segment specification ≅-C ,the output filename, the range of addresses defining the segment and an optional new base address for the segment. e.g. -C ∋out3.obj 0x0000 0x0100 4, Any line not containing one of ≅-I, ≅-O or ≅-C is treated as a comment. Example address Mapping and format file: The user has a program for the H8/300, compiled using the banked memory model. The system can be described in logical addresses as: 0000 to 7FFF 8000 to BFFF C000 to FFFF 18000 to 1BFFF 28000 to 2BFFF 38000 to 3BFFF Vectors, constants, startup code and libraries. Bank 0 user code User data. Bank 1 user code Bank 2 user code Bank 3 user code The banked code will actually reside in a single EPROM on the target, with each bank segment being contiguous in memory. Thus the actual S-Record addresses need to be: 0000 to 7FFF 0000 to 3FFF C000 to FFFF 4000 to 7FFF 8000 to BFFF C000 to FFFF Vectors, constants, startup code and libraries. (H8) Bank 0 user code (EPROM) User data. (H8) Bank 1 user code (EPROM) Bank 2 user code (EPROM) Bank 3 user code (EPROM) Thus we need two output files, one for the H8 and the other for the EPROM. The format file is then: define input file -I ∋aout.a21 H8 output file segments -O ∋h8.a21 0x0000 0x7FFF 2 of 4 -O ∋h8.a21 EPROM output file -O ∋eprom.a21 -O ∋eprom.a21 -O ∋eprom.a21 -O ∋eprom.a21 0xC000 segments 0x8000 0x18000 0x28000 0x38000 0xFFFF 0xBFFF 0x1BFFF 0x2BFFF 0x3BFFF BASE BASE BASE BASE 0x0000 0x4000 0x8000 0xC000 To invoke the splitter utility, enter ≅splitter with the filename of your format file (if no extension is specified the default extension ≅.fmt is used). e.g. c:\> splitter example.fmt Two output files will then be created, with the desired S-Record configuration. 3 of 4 Hitachi Europe Ltd. ISSUE : APPS/008/1.0 APPLICATION NOTE D ATE : 21/3/94 ________________________________________________________ THE H8/300 SERIAL COMMUNICATIONS INTERFACE The serial communications interface (SCI) can perform either synchronous or asynchronous communications, and data rates of up to 2.5Mbit/sec are possible. Each channel of SCI has its own baud rate generation, so the use of serial communications does not impact the number of timers available in the microcontroller. By programming a control register and loading the baud rate register, a wide range of data rates can be achieved from one source of microcontroller clock. In asynchronous mode, several data formats are catered for, including the provision of odd or even parity. To indicate various conditions occurring within the SCI, a status register is provided which contains flags for receive buffer full, transmit buffer empty or receive error. Each of these flags has an interrupt associated with it to indicate the occurrence of such a condition. Each of the SCI data registers (TDR and RDR) is double buffered so it is possible to transmit and receive data in a "Back-to-back" manner. The following three code examples show how to initialise and use both the transmit and receive interrupts. Two types of transmission are provided, synchronous and asynchronous. MODULE TO TRANSMIT A MESSAGE USING SYNCHRONOUS COMMUNICATIONS #pragma language=extended /* ALLOW NON ANSI SPECIFIC EXTENSIONS */ #include #include #define BRR_SETUP 0x0C #define SMR_SETUP 0x80 #define SCR_SETUP 0xCF #define CLR_TDRF 0x7F #define SRR_SETUP 0xC8 #define SET_TE 0x20 #define TEND_SET 0x40 #define CLR_TE 0xDF char message[5] = "HELLO"; /* TRANSMISSION MESSAGE */ int index = 0; /* INDEX VARIABLE FOR MESSAGE TRANSMISSION */ 1 of 6 interrupt [SCI_TXI0] void tx_isr (void) { SCI0_TDR = message[index++]; /* TRANSMIT NEXT CHARACTER */ SCI0_SSR &= CLR_TDRE; /* CLEAR THE TDRE BIT TO '0' */ if (index > 4) /* ENSURE ALL BITS HAVE BEEN TRANSMITTED */ { while (SCI0_SSR &= TEND_SET != TEND_SET); /* WAIT FOR TEND BIT IN SSR TO BE SET (TO '1') */ SCI0_SCR &= CLR_TE; /* CLEAR TE BIT IN THE SCR */ } } /* DELAY OF 105 us */ void wait_for_1_bit (void) { int a; for (a=0;a6; An2 = ADDRC>>6; An3 = ADDRD>>6; // shift down to botton of short, '0's moved in /* Scale in tenths of a volt */ An0 = (An0*50)/1024; An1 = (An1*50)/1024; An2 = (An2*50)/1024; An3 = (An3*50)/1024; /* Use An0 to vary the PWM ratio on ITU Ch 0 */ ITU_GRA1 = (An0*640)/50; } } void Init_Interrupts(void) { /* Configue SYSCR and CCR first */ SYSCR = 0x03; // set UI bit in CCR as an interrupt mask bit and_ccr(0x3F); // enable interrupts, set UI bit to 0 - inline function /* or alternatively this could be used to enable interrupts */ set_interrupt_mask(0); // enable all interrupts /* Set priorities, Refresh controller and DMAC interrupt have priority. */ Hitachi Europe Ltd. IPRA = 0x08; IPRB = 0x20; IER = 0; ISCR = 0x3F; ISSUE : APPS/032/1.1 // Priority for refresh controller // Priority for DMAC interrupts // all external ints disabled as default // all external ints triggered by falling edge input } void Init_ITU(void) { /* Ch 0 - 5ms timebase interrupt for scheduler */ ITU_TCR0 = 0x21; ITU_TIOR0 = 0; ITU_TIER0 = 0x01; ITU_GRA0 = 0x9c3F; // clear comp' match GRA, internal clock/2 // no output at compare match // interrupt on compare match GRA // 40000 - to give 5ms compare match /* Ch 1 - 25Khz PWM with 75% on duty cycle */ // Commented out for TPC operation /*ITU_TCR1 = 0x40; ITU_TIOR1 = 0; ITU_TIER1 = 0; ITU_GRA1 = 160; ITU_GRB1 = 640; // clear comp' match GRB, internal clock // ignored PWM mode set in TMDR register // no interrupts // Go high // Go low*/ /* Ch 2 - Input capture */ ITU_TCR2 = 0x40; ITU_TIOR2 = 0x45; ITU_TIER2 = 0; // clear on i/p cap on GRB // i/p capture GRB +ve edge, GRA -ve edge // no interrupts /* Ch 3 - 2mS interrupt to trigger DMA */ ITU_TCR3 = 0xC3; ITU_TIOR3 = 0; ITU_TIER3 = 0x01; ITU_GRA3 = 400; ITU_GRB3 = 4000; // counter clear compare match GRB, clk/8 // set GRA & GRB to output compares /* interrupt on compare match A, triggers DMA & TPC, interrupt flag, automatically cleared by DMAC */ // set non-overlap margin (10uS @ 16Mhz) // set period (2mS @ 16Mhz) /* set registers common to all ITU channels */ ITU_TSNC = 0; // channels operate independently - not synch'd // Commented out for TPC operation /*ITU_TMDR = 0x02; // Ch 1 set for PWM mode*/ ITU_TFCR = 0; // Ch 4 not used ITU_TOER = 0; // Ch 4 not used, pins used for normal i/o ITU_TOCR = 0xFF; // not used as default ITU_TSTR = 0x0D; // start channels 0, 2 and 3 - 1 stopped for TPC } Hitachi Europe Ltd. ISSUE : APPS/032/1.1 void Init_DMAC(void) { /* configure DMAC for short addressing mode. Channel 0A set for I/O mode with a cpu interrupt generated after 8 transfers */ unsigned char temp; DMAC_MAR0A = (unsigned long)step_out; // address of look up table DMAC_IOAR0A = 0xA5; // NDRA same output trigger for TPC groups 0 & 1 DMAC_ETCR0AH = 0; // high byte DMAC_ETCR0AL = 8; // Low byte, transfer count of 8 temp = DMAC_DTCR0A; /* dummy read to allow DTE bit to be set to 1 */ DMAC_DTCR0A = 0x8B; /* enable transfers, byte size, increment MAR, I/O mode, enable CPU interrupt at end of transfer count, trigger compare match A ITU 3 - DTCRB only used for full address mode */ } void Init_TPC(void) { /* configure for non overlap with byte output on TPC groups 0 & 1. Groups are triggered by same timer, ITU Ch3. */ TPC_TPCR = 0xFF; TPC_TPMR = 0x03; TPC_NDERA = 0xFF; } // groups 0 & 1 triggered by ITU Ch3 compare match // non overlap mode for groups 0 & 1 // enable transfer of NDERA data to PADR void Init_AD(void) { /* Configure for scan mode on channels 0 to 3 */ ADCSR = 0x3B; // Scan mode, ch's 0 to 3, start, no interrupt } void Init_Serial(void) { /* configure serial port for 9600baud, 1 stop, 8 data, no parity, interrupt on receive */ // Serial Port 1 not used SCI0_SMR = 0; SCI0_SCR = 0x70; SCI0_BRR = 51; } // multiprocessor bit not used // interrupt on receive , start tx and rx // set for 9600 baud Hitachi Europe Ltd. ISSUE : APPS/032/1.1 void Init_Ports(void) { /* Ports set for following:PortB = Output. */ PADDR = 0xFF; PBDDR = 0xFF; // output // output } void interrupt [DMAC_DEND0A] DMAC0A_Tfr_End(void) { /* interrupt generated by DMAC0A at end of transfer count */ unsigned char temp; DMAC_ETCR0AH = 0; // re-write transfer count - high byte DMAC_ETCR0AL = 8; // Low byte, transfer count of 8 DMAC_MAR0A = (unsigned long)step_out; // reset MAR to point to start of table temp = DMAC_DTCR0A; // dummy read DMAC_DTCR0A |= 0x80; // re-enable DTC transfers } void interrupt [ITU_IMIA0] ccr_mask[0x02FF] Scheduler(void) /* Interrupt Service routine for compare match on ITU Ch 0. Note ccr_mask shown for example only as mask operation and value is set to have no effect on ccr. */ { static unsigned char t50ms=9, t100ms=1, t250ms=4, t500ms=1, index=0; ITU0_TSR0.0 = 0; // reset GRA compare match interrupt flag // read modify write required ie a bit operation /* This interrupt is called every 5ms */ /* Toggle port pin for square wave output at 100Hz (10mS) */ PB_DR.5 = (!PB_DR.5) ? 1 : 0; /* toggle pin */ schedule_count++; if (schedule_count >= 5000) schedule_count=0; /* transmit message from buffer */ if (msg_sending_flag) Hitachi Europe Ltd. ISSUE { while (!SCI0_SSR0.7); /* wait until tx buffer free */ SCI0_TDR = tx_msg_buf1[msg_ptr++]; SCI0_SSR0.7 = 0; /* reset TDRE flag */ } if (!tx_msg_buf1[msg_ptr]) { msg_ptr=0; msg_sending_flag = 0; // message sent } /* user functions to be called every 5ms - note combined run time of these functions must be < 5ms */ /* User_5ms_Func1(); User_5ms_Func2(); User_5ms_Func3(); */ if (!t50ms) { /* user functions to be called every 50ms - note combined run time of these functions must be < 50ms */ /* 50ms tick */ /* User_50ms_Func1(); User_50ms_Func2(); User_50ms_Func3(); */ /* reload 50ms tick */ t50ms = 9; /* user functions to be called every 100ms - note combined run time of these functions must be < 100ms */ /* 100ms tick */ if (!t100ms) { /* Toggle port pin for square wave output at 5Hz (200mS) */ PB_DR.6 = (!PB_DR.6) ? 1 : 0; /* /* toggle pin */ User_100ms_Func1(); User_100ms_Func2(); User_100ms_Func3();*/ /* reload 100ms tick */ t100ms = 1; /* user functions to be called every 500ms - note combined run time of these functions must be < 500ms */ : APPS/032/1.1 Hitachi Europe Ltd. ISSUE /* 500ms tick */ /* if (!t500ms) { User_500ms_Func1(); User_500ms_Func2(); User_500ms_Func3();*/ /* reload 500ms tick */ t500ms = 4; } else t500ms--; } else t100ms--; /* user functions to be called every 250ms - note combined run time of these functions must be < 250ms */ /* 250ms tick */ if (!t250ms) { /* User_250ms_Func1(); User_250ms_Func2(); User_250ms_Func3();*/ /* reload 250ms tick */ t250ms = 4; } else t250ms--; } else t50ms--; } void Init_Refresh(void) { RFSHCR = 0; RTCOR = 78; RTMCSR = 0x7F; } // set for interval timer mode // set for a compare match every 20mS // interrupt, clk/4096 void interrupt [CMI] Refresh_Int(void) /* Interrupt handler for refresh controller when in interval mode */ { RTM_CSR.7 = 0; // reset compare match flag PB_DR.7 = (!PB_DR.7) ? 1 : 0; /* toggle pin */ : APPS/032/1.1 Hitachi Europe Ltd. ISSUE : APPS/032/1.1 /* reset watchdog timer to prevent overflow */ WDT_TCNT = 0x5A00; // '5A' password - reset timer to zero } void Init_WDog(void) { /* configure for watchdog mode - will reset MCU at overflow */ WDT_TCSR = 0xA57F; // 'A5' password, watchdog mode, clk/4096, started // will overflow every 65mS if not reset } When using this document, keep the following in mind, 1, This document may, wholly or partially, be subject to change without notice. 2, All rights are reserved: No one is permitted to reproduce or duplicate, in any form, the whole or part of this document without Hitachi’s permission. 3, Hitachi will not be held responsible for any damage to the user that may result from accidents or any other reasons during the operation of the user’s unit according to this document. 4, Circuitry and other examples described herein are meant only to indicate the characteristics and performance of Hitachi’s semiconductor products. Hitachi assumes no responsibility for any intellectual property claims or other problems that may result from applications based on the examples therein. 5, No license is granted by implication or otherwise under any patents or other rights of any third party or Hitachi, Ltd. 6, MEDICAL APPLICATIONS: Hitachi’s products are not authorised for use in MEDICAL APPLICATIONS without the written consent of the appropriate officer of Hitachi’s sales company. Such use includes, but is not limited to, use in life support systems. Buyers of Hitachi’s products are requested to notify the relevant sales office when planning to use the products in MEDICAL APPLICATIONS. Copyright Hitachi, Ltd.,1995. All rights reserved Hitachi Europe Ltd. ISSUE : APPS/037/1.1 APPLICATION NOTE DATE : 8/5/96 H8/300H Software UART implementation using 2 Timer and 2 DMA channels Most variants of the H8/300H family of micro-controllers support two hardware UARTS as standard. However in a lot of detailed embedded applications today there is an increasing requirement for more than two. Detailed here is a method where a further full duplex UART channel can be implemented using two on board timers and two of the DMA channels. For the transmission side there is some overhead required to set up the transmission table and pattern and on the receive side there are two CPU interrupts, one at reception of the first start pulse edge (approximately 8 µs) and one when the packet has been received (approximately 64 µs). The outer layer of the application code has been written in C but the bit bashing routines are shown here in assembler for speed purposes, but there is no reason why these cannot be converted to Ansi C. Asynchronous Communications: An asynchronous data packet will be of one of the following formats: The data content may be, typically, between five and eight bits. Parity may be even, odd or disabled. There may be one or two stop bits. In standard use the user selects the format required for the communications protocol in use, and the UART remains set at a standard format. This example assumes that the user has only one protocol required, and that this is known at compile time, thus the code may be written specifically for the format required, and may therefore have any generalisations removed to increase execution speed and reduce code overhead. The selected packet format is: 9600 bps, 8 data bits, no parity, 1 stop bit. To implement a Uart two separate operations must be catered for: • • The UART must be able to create data packets on an I/O line which conform to the required bit rate and packet format. The UART must be able to detect transitions on a separate I/O line and disassemble the transitions into a valid data value. Both the above operations require the UART simulation software to be able to time I/O control at a rate which is proportional to the bit rate of the asynchronous interface. In addition data must be transferred to/from the I/O lines in synchronisation with the time steps. It is feasible to implement such timing and data transfer operations in a number of ways: • • • CPU performs a timing loop and transfers data. Timers generate time-out interrupts, the CPU then transfers data on interrupts occurring. Timers generate time-out interrupts, data is transferred by DMA on time-out events. Hitachi Europe Ltd. ISSUE : APPS/037/1.1 The above three options represent a decreasing requirement on the CPU, with the timer/DMA option requiring CPU intervention only to set up and start transmission, or to disassemble the received data. It is this option which has been selected for this example, as it represents the best use of the H8/300H peripherals to minimise the CPU overhead in implementing a UART. Transmitter Implementation: The algorithm used to implement the transmission par of the software UART reduces the number of DMA transfers to the absolute minimum required, with the slight CPU overhead of creating a timer set up table before invoking the timer/DMA transmission system. The algorithm uses the following basic principle: • If a bit pattern is exclusive-ORed with itself divided by 2, the resulting pattern represents the 0 to 1, or 1 to 0 transitions in the original bit pattern. For example: Original Pattern: 01110100 Pattern / 2 00111010 XOR 01001110 i.e. a bit transition occurs at (reading from left to right) bits 1,4,5 and 6. This transition data may then be used to determine the exact time at which the transmit line must be toggled, which will not usually be on every bit of the packet. Thus worst case, the transition method of forming data packets will tend to that of transferring bit data at the bit rate, while usually the number of transfers will be significantly reduced ((four transitions in the above example). The set up procedure for transmission is described below: • • • • Calculate the transition pattern. Form a table of transition times based upon the bit rate. The table should contain multiples of the bit rate count for the frequency of the timer channel used. Set the timer channel to compare-match on the first transition time-out and to toggle an I/O line on each compare-match event. The timer channel should also trigger a DMA transfer on each compare-match event. Set a DMA channel to transfer successive data from the transition data channel, to the compare-match register on each successive compare-match event, until all transitions have occurred. Thus once the transition table has been created and the timer and DMA initialised, then the timer will control the I/O line using a compare-match event, and the DMA will reload the compare-match register automatically with the next compare-match value. When the required number of transitions have occurred the DMA can be used generate a CPU interrupt, which may then stop any further timer and DMA operations. This represents a completely self-contained system which will only interrupt the CPU on completion of transmission Receiver Implementation The receiver needs to detect the start of a data packet (denoted by the low start bit), it then must sample the receive data line at a minimum of the bit rate to determine the incoming data bits. It is recommended that the received data line is sampled at a frequency greater than the bit rate, so that more than one sample is available for each data bit. This will then enable the receiver to remove any spurious readings from the incoming bit stream, by taking the majority of the readings for each bit. Hitachi Europe Ltd. ISSUE : APPS/037/1.1 The implementation described below uses a sampling rate which is four times the bit rate. The start bit is detected by a timer channel using the input capture function. This may then be used to interrupt the CPU, which may then start the sampling process. A timer channel may then be used to set a sampling interrupt which may be used to trigger a DMA transfer from the receiver I/O line to a receive data buffer. Having finished the sampling process the CPU may then examine the sampled data to determine the received value. This is accomplished by taking the majority level of each four samples as the received bit level. Once the data value has been determined any parity checking may be performed, if required. To summarise the operations Set-up - Timer & DMA • • • • • • Set the sample rate in to a compare-match register Enable input-capture interrupts for the timer channel Start the timer channel Set the source and destination DMA transfer addresses Set the DMA transfer count Set the DMA operation mode On Input-capture Interrupt: • • • • • Stop timer channel Disable input capture interrupt & clear flag Enable compare match-interrupts Enable DMA transfers on compare-match interrupt and enable DMA Start timer channel On DMA completion interrupt: • • • • Stop the timer channel & clear flags Disable DMA transfers Disassemble receive buffer using majority samples to determine data bits. Set receiver flag and store data. The above process may then be used to receive multiple data bytes at the desired bit rate. Please note that this method uses two DMA channels to perform the data transfer, as normal address mode is required. If these are not available, the sample transfer could be implemented as a compare-match CPU interrupt. However, this would have more impact on CPU bandwidth. Hitachi Europe Ltd. ISSUE : APPS/037/1.1 UART design notes: The UART uses the following hardware: Transmitter Receiver - One channel of the ITU One channel of the DMA One channel of the ITU Two channels of the DMA However if the UART is not required to transmit at the same time as data may be received, then the total requirement for the UART will be one channel of the ITU and two channel of the DMA. In this example the UART has been set up assuming that reception and transmission will not occur simultaneously. UART Benchmark Timings: The code was timed on an E7000PC emulator for the H8/3042 device in advanced single chip mode (mode 6) operating at 16Mhz system clock. The functions/interrupt handlers are listed below with execution times. In addition timings were taken from the invocation of the transmit function, until the last data bit was transferred, and the handler returned. This will give an indication of the toal transmit time which the CPU requires - please note that the CPU will not be performing this code exclusively during this period. Function: Time Taken ( µsec): Receiver 64 µsec Transmit 21 to 25 µsec Initialise UART 21 µ sec ITU Capture Interrupt 8 µsec DMA Isr 2 µsec Hitachi Europe Ltd. ISSUE : APPS/037/1.1 UART.C - Software UART implementation for H8/3042. #include “ioh83042.h” #include “inh83042.h” #include // // I/O register definitions Interrupt vector addresses // In-line functions #pragma language=extended //System Constants #define GRA0 #define DRA 0x6A 0xD3 //Union for C access to DMAC MAR registers union u_tag { unsigned long full; struct w_tag { unsigned short hw; unsigned short lw; } word; struct b_tag { unsigned char rb; unsigned char eb; unsigned char hb; unsigned char lb; } byte } MAR //Global data and transmit/receive buffers unsigned short dma_buff[20] unsigned short period; unsigned short dma_count unsigned char rx_buff[40]; //Assembler based fast comms routine void Transmit (unsigned char); //Globals used for Flags unsigned char SCI2_SMR; unsigned char SCI2_SSR; unsigned char SCI2_SCR; unsigned char SCI2_RDR; Function to set the ITU and DMAC channels to their initial settings, the ITU is run for a short time to allow a compare match to occur so that the output line may be set to a logic high. The transmitter uses ITU channel 0 (CMA) and DMA channel OA (in I/O mode). The receiver uses ITU channel 1 (ICA then OCA) and DMA channels 1A and 1B (in block transfer full address mode) void Initialise UART (void) Hitachi Europe Ltd. ISSUE : APPS/037/1.1 { period = 417; //sys/4 @16MHz -> 9600 bps //set up for Transmit, initialise the timer output to high... ITU_TCNT0 = 0x0000; ITU_TCR0 = 0xA2; //CCLRA, sys/4 ITU_TIOR = 0x8A; //output 1 on CMA ITU_GRA0 = 10; //compare match value ITU_TSRO &= 0xF8; //clear flags ITU_TSTR | = 0x01; //start the timer channel while ((ITU_TSRO & 0x01) ! = 0x01); //wait on compare match ITU_TSTR & OxFE; //stop channel 0 with output = 1 ITU-TSRO & = 0xF8; //clear flags //now set up the timer and DMA channels to perform the transmission ITU_TIOR0 = 0x8B; //toggle O/P on CMA ITU_TIER0 = 0xF9; //enable interrupts on CMA DMAC_IOAR0A = GRAO //enable interrupts on CMA DMACIOAR0A = GRA0; //set I/O destination to GRA0 register DMAC_DTCR0A= 0x40; //word, inc MAR, I/O CMA //set up ITU for receive ITU_TCNT1 =0x0000; //reset counter ITU_TCR1 =0xA0; //CCLRA, sys ITU_TIOR1 = 0x8E; //ICA falling edge ITU_TSR1 & = 0xF8; //clear flags ITU_ TIER1 = 0x01; //enable interrupt on ICA //set up DMA for receive DMAC_DTCR1A = 0x07; //byte, fixed source, block mode DMAC_DTCR1B = 0x19; //inc dest, source is block, trigger on CMA 1 DMAC_ETCR1AH = 0x01; //1 byte per block DMAC_ETCR1AL = 0x01; DMAC_ETCR1BH = 0x00; //36 transfers to complete DMAC_ ETCR1BL = 0x24; DMAC_MAR1AE = 0x00; //port A is the source address DMAC_MAR1AH = 0xFF; DMAC_MAR1AL = DRA; MAR.word.lw = (unsigned short) &rx_buff; //set destination DMAC_MAR1BE = MAR.byte.eb; DMAC_MAR1BH = MAR.byte.hb; DMAC_MAR1BL = MAR.byte.lb; } Interrupt service routine to fire off the sampling process for a packet of data, given that the low edge of a start bit has been detected by the input capture logic of the timer channel. interrupt [ITU_IMIA1] void ITUCaptureInterrupt (void) Hitachi Europe Ltd. ISSUE : APPS/037/1.1 { ITU_TSTR & = 0xFD; ITU_TCNT1 = 0x0000; ITU_TIOR1 = 0x88; ITU_GRA1 = 417; DMAC_DTCR1A | = 0x80; DMAC_DTCR1B | = 0x80; DMAC_DTCR1A | = 0x08 ITU_TSR1 &= 0xF8; ITU-TSTR |= 0x02; //stop channel 1 //reset counter //CMA, no output //sys @ 16Mhz -> 4 * 9600 samples/sec //enable DMA //DMA master enable //enable DMA interrupts //Clear flags //start channel 1 } Main function to test that the transmit and receive operations work - here the transmit line may be fed back to the receive line to allow simultaneous transmission and receipt. int main (void) { int i; set_interrupt_mask (0); InitialiseUART(); while (1) { Transmit (0x74); for (i=0;i 1usecs The manner in which the 300H will, address and control the LCD module is to use the address and chip select lines to decode the enable line to the LCD module, data will be sent on the high lines of the data bus under direct control of the RD pin. The wait pin signal will again be generated by the decode logic to sufficiently stall the 300H for the period of 610nsecs after the initial access. The address of the LCD display shall be designated to be within byte wide memory area 7 with A1 (lowest address line for byte wide memory) used to select between the instruction and data registers. For completeness the watchdog timer has been used to ensure that the LCD display is not accessed, either read or write, within 1µsecond. The manner by which this is done is to stall the software until the watchdog counts up to 1µsecond. Note this could easily be done by using a simple a simple wait or NOP loop. Hitachi Europe Ltd. ISSUE : APPS/048/1.1 Hardware Specification The schematic below shows the hardware involved in the control of the LCD. However, it should be noted that the choice of low level control is up to the final design although the logic architecture must provide registers to enable the construction of a counter and state machine, as shown later. Figure 2 : Hardware schematics LCD MODULE DB0-7 R/W RS E DATA(high) RD A1 300H ~wait CS7 AS LOW LEVEL CONTROL The low level control requirements are simply to provide the enable and wait signal pulses to the LCD module and 300H respectively. The operation of the logic can be simply defined using the state diagram overleaf. Figure 3 : Low level control operation ../.. CS7,.AS/WAIT Enable WAIT pin IDLE stall 150nsecs CS7,.AS/WAIT,ENABLE ../.. CS7,.AS/ .. wait on 300H CS7,.AS/.. Send ENABLE pulse stall 450nsecs To provide the timing requirements from the initial application of RS and R/W (A1 and RD) to the ENABLE signal at the LCM a simple counter mechanism can be used. For example the counter can be enabled when the address strobe signal is asserted, thereby indicating A1 is valid along with RD, from which the states can be counted until the necessary time Hitachi Europe Ltd. ISSUE : APPS/048/1.1 Software Specification The software requirements for the interface to the LCD screen are shown in the following sections which describe not only the functionality of the code but the generation of it. Generation of code The tools that are used for the code generation are that of the IAR compiler/linker system as shown in the figure overleaf. Figure 4 : IAR code system. LCD driver software (*.C) Assembler AH8300 Compiler ICCH83 Library manager XLIB Linker link file *.xcl XLINK IAR suite LCD driver object code (*.obj) For the purposes of the control of the LCD driver software the program was built using the following options. It should be noted that when choosing development options they should be replicated right across the IAR system build. Since failure to do so could cause errors at the linker stage. 1. 2. 3. 4. 5. 6. 7. Processor options : v3 > H8_300H with a 16Mbyte address space Memory model : ml > far function calls with default data type of huge, stack size is unlimited Floating point precision : -1id > ints are 2 bytes long and doubles are used as floats(4 bytes long) De-bugging level : NA > High level de-bugging not required (C-spy or CIDE not used) Memory configuration : • INTVEC - 0-FF > Interrupt vector table • RCODE, CODE - 100 - FFFF > Vector handling code and normal code in area0 of device • Data, IData : FFFD10 - FFFE00 > Initialised and non-initialised data kept in ON-chip Ram. Stack size : Stack set as 120 bytes Code optimisation : Using standard speed and size optimisation s3 and z4 Consequently, the following commands were used to firstly build the library , compile the code and then linking together. BUILDLIB -v3 -ml -1id -s3 -z4 ------> Outputs library file CLHSF3.r20 Hitachi Europe Ltd. ISSUE : APPS/048/1.1 ICCH83 -v3 -ml -1id -s3 -z4 -P Lcd_Drv.c -l Lcd_Drv.lst -----> Outputs Lcd_Drv list and r20 files XLINK -f linkfile.xcl ------> Outputs executable Lcd_Drv object file It should be noted that the format of linkfile.xcl is as shown below : lcd_drv -ch8300h -o lcd_drv.obj -l lcd_drv.lst clh83sf3 -FPENTICA-BM -xsme -Z(CODE)INTVEC,IFLIST,FLIST=0-ff -Z(CODE)RCODE,CODE,CDATA0,CDATA1,CDATA2,CDATA3,ZVECT,CONST,CSTR,CCSTR=100 -! Then the writeable segments which must be mapped to a RAM area C000 was here supposed to be start of RAM -! -Z(huge)DATA3,IDATA3,UDATA3,ECSTR,WCSTR,TEMP=fffd10 -Z(huge)CSTACK+120=Fffde0 -Z(FAR)DATA2,IDATA2,UDATA2=fffd10 -Z(FAR)DATA1,IDATA1,UDATA1=fffd10 -Z(FAR)DATA0,IDATA0,UDATA0,SHORTAD,DATA=fffd10 Software functionality The algorithm below shows the progression of control from reset or power-on, through initialisation to the writing of an ASCII string to the display. 1. Initialise On-chip registers • Set-up bus control registers for area 7 - 8-bit, 3 accesses with wait controller enabled • Set-up wait state controller - Pin wait mode 1 with 1 wait state automatically included • Enable CS7 on port C • Set-up watchdog timer to count 1µsecond 2. Initialise LCD display to correct mode • Delay for 15msecs after power-on (minimum) • Set function interface - 8bits • Delay for 4.1msecs to next write to LCD display • Set function interface to 8bits • Delay for 100usecs • Set function to 8-bits (Busy flag now valid to check) • Set LCD function/type to 8-bits, 2 lines with char. format of 5x7. • Set LCD display,cursor and blink to off. • Clear LCD display and return cursor to home position. • Set entry mode to increment cursor with accompanied shift left 3. Set pointer to ASCII text string to display 4. Clear LCD display 5. Return cursor to home 6. while not(end of string) do 7. check not end of current LCD row 8. write ASCII character to LCD screen 9. increment pointer to LCD screen 10. increment count for cursor 11. endwhile It should be noted that for each access to the LCD screen whether reading or writing to either the instruction or data register the following procedure is followed to ensure that the LCD screens operating procedure is not violated (i.e. writing to screen when still busy and making an access to screen within 1µsecond of last access). 1. 2. 3. 4. while (LCD flag still busy) wait for watchdog to count down 1µsecond read busy flag from LCD module endwhile Hitachi Europe Ltd. ISSUE : APPS/048/1.1 To access the busy flag is simply a matter or reading the instruction register and checking bit 7 which indicates the busy flag status. As can be seen from the above algorithm the functionality of the code should be very simple once the LCD module and 300H controller has been properly initialised, thus requiring minimal CPU control. Also note that the watchdog timer should be turned off when in a period of inactivity in accessing the LCD screen as the watchdog timer can use a great deal of processing cycles, since it is interrupt driven. Register set-up As shown in the previous section care must be taken in setting up the 300H microcontroller to ensure the LCD module is correctly and effectively interfaced to. [1] Bus controller set-up As noted earlier the LCD module has been addressed in area 7 of the 300H memory map consequently a number of registers must be set-up to enable the module to be accessed in 8-bit mode using CS7 and enabling the use of A0 to differentiate between the instruction and data registers respectively. The above requirements are provided through the following register set-up ABWCR - Bus width control register ABW7 0 ABW6 X ABW5 X ABW4 X ABW3 X ABW2 X ABW1 X ABW0 1 AST4 0 AST3 0 AST2 0 AST1 0 AST0 1 PCDDR4 0 PCDDR3 0 PCDDR2 0 PCDDR1 0 PCDDR0 0 ASTCR - Area access state control register AST7 1 AST6 0 AST5 0 PCDDR - Port C data direction register PCDDR7 0 PCDDR6 0 PCDDR5 1 [2] Wait state controller The wait state controller has been enabled in area 7 to provide wait mode 1 which automatically inserts 1 wait state and then thereafter depends if the input wait signal is low at the next low to high transition of the clock. This mechanism should enable the LCD module to stall the microcontroller by the required amount (around 500nsecs), through the low level hardware control. WCR - Wait control register X X X X X X X X WMS1 1 WMS2 0 WC1 0 WWC0 1 WCE4 0 WCE3 0 WCE2 0 WCE1 0 WCE0 0 WCER - Wait control enable register WCE7 1 WCE6 0 WCE5 0 Hitachi Europe Ltd. ISSUE : APPS/048/1.1 [3] Watchdog timer set-up The following watchdog timer setup should enable the microcontroller to ensure accesses to the LCD module are no more frequent that 1µsecond access cycle. (Clock ticks at 0.125usecs thus count for 8 at least before enabling access) It should be noted that in the 300H microcontrollers the watchdog registers are password protected and cannot be written to normally. If using a microcontroller without a watchdog simply stall within the loop with NOP commands. TCSR - Timer control/status register OVF 0 WT/IT 0 TME 1 X X X X CKS2 1 CKS1 1 CKS0 1 bit4 1 bit3 0 bit2 1 bit1 1 bit0 1 TCNT - Timer counter register bit7 1 bit6 1 bit5 1 LCD driver code The attached C-code shows example code that can control the LCD display as specified throughout this document. The code shows example text which can be replaced by any ASCII or a sub-set of KANJI codes to send to the screen. /*********************************************************************** LCD MODULE DRIVER SOFTWARE. Purpose : Software designed to integrate 300H processor to a typical Hitachi LCD module. Applicable units are all the ones listed in the character display catalog. Input text can be derived from serials ports or constant strings, text shown here gives an example of ASCII and KANJI text. **********************************************************************/ #pragma language = extended #include #include /*300h port defines*/ /*300h interrupt vector table*/ Hitachi Europe Ltd. #define #define #define #define END_ROW1 NEW_LINE NULL CR 20 0x40 0x00 0x0d ISSUE : APPS/048/1.1 /*Define of length of LCD row*/ /*Define of the cursor position of the 2nd row*/ /*ASCII null char. which terminates string*/ /*ASCII equivalent of carriage return*/ unsigned char *LCMIR = 0 ; /*Pointer to the LCD module instruction register*/ unsigned char *LCMDR = 0 ; /*Pointer to the LCD module data register*/ unsigned char Access_Made = 0 ; /*Global flag that signifys if it is okay to access LCD display*/ unsigned char *text_string ; /*Pointer to string to output to LCD display*/ interrupt [WDT_WOVI] void LCD_count(void) /* Purpose is to count from last LCD access and enable a flag if more than 1µsecond*/ { unsigned char temp=0; Access_Made = 0 ; /*Clear flag to indicate that it is okay to re-access LCD*/ /*Setup TCNT register again to count 1µsecond*/ /*10 ticks of a 8Mhz clock is sufficient for 1µsecond */ temp = (char)WDT_TCNT & 0xF5 ; WDT_TCNT = 0x5A|temp ; /*Write value to TCNT register*/ } void reg_setup() /* Purpose : Procedure to set-up internal 300H registers*/ { unsigned char temp =0 ; /*Temp var used to write values to watchdog register*/ /*Wait state enable register*/ WCER=0x80 ; /*Wait control only enabled in area 7 accesses*/ /*Wait state control register*/ WCR=0xf9 ; /*Wait mode 1 with 1 wait state automatically inserted*/ /*Bus width control register*/ ABWCR=0x80 ; /*Area 7 accessed as an 8-bit area - only high data bus*/ /*Access state control register*/ ASTCR=0xff ; /*Area 7 (and all the rest) accessed in a 3 state access*/ /*Port C data direction control register*/ PCDDR=0x20 ; /*CS7 (PC5) enabled as an output - all the rest as generic inputs*/ /*Set-up watchdog timer - register locked by password*/ /*10 ticks of a 8Mhz clock is sufficient for 1µsecond */ temp = (char)WDT_TCNT & 0xF5 ; WDT_TCNT = 0x5A|temp ; /*Write value to TCNT register*/ /*temp = (char)WDT_TCSR & 0x38 ; /*Enable timer operation using 8Mhz increment clock*/ WDT_TCSR = 0xA500|temp ; /*Use password to write value*/ */ } void delay(long *delay_val) /* Purpose : Delay loop for waiting on LCD display - passed value indicates length of delay*/ { long times ; times = 0 ; Hitachi Europe Ltd. ISSUE : APPS/048/1.1 while (times < *delay_val) { times = times + 1 ; } } void poll_lcd_busy() /* Purpose : Function to determine if the LCD module is ready for another access*/ { while(( *LCMIR & 0x80 )== 0x80 ) /* Check bit 7 of Instruction register*/ { /*Wait for LCD busy flag to go low*/ Access_Made = 0 ; /*Included for test */ while (Access_Made) { /*Wait for 1µsecond from last access to LCD display*/ } Access_Made = 1 ; /*Clear flag to show an access will be made*/ } } void lcdinit() /* Routine to initialse LCD display into the required setup - dependant on type */ { long delay_val=0; /*Delay variable for initial initialisation*/ delay_val=200000; /*Delay for 15msecs after powerup - 16Mhz clock*/ delay(&delay_val); *LCMIR = 0x30; /* Funciton Set - 8bit interface*/ delay_val=65000; /* Delay for 4.1msecs*/ delay(&delay_val); *LCMIR = 0x30; /* Funciton Set - 8bit interface */ delay_val=2000; /* Delay for 100usecs*/ delay(&delay_val); *LCMIR = 0x30; /* Funciton Set - 8bit interface*/ poll_lcd_busy(); /*Wait for LCD module*/ *LCMIR = 0x30; /* Function Set */ /* BUSY FLAG CAN NOW BE CHECKED FROM THE LCD MODULE */ poll_lcd_busy(); *LCMIR = 0x08; /* Function set to 8bits, 2lines and 5x7character form*/ poll_lcd_busy(); *LCMIR = 0x08; /* Display on/off control enable */ poll_lcd_busy(); *LCMIR = 0x01; /* Clear display and return cursor to home */ poll_lcd_busy(); *LCMIR = 0x06; /* Entry Mode Set as increment with accompanying shift */ poll_lcd_busy(); *LCMIR = 0x0C; /* Display set to on, cursor and blink off*/ Access_Made = 0 ; /*Access to display enabled*/ /*LCD MODULE NOW READY TO ACCEPT DATA FOR DISPLAYING*/ } Hitachi Europe Ltd. ISSUE : APPS/048/1.1 void text_out() /*Purpose : Sub-routine to handle passing of char to module - checks line over run*/ { unsigned char char_cnt = 0; /*Count of characters sent to LCD screen*/ char_cnt = 0 ; while (*text_string != NULL) { /*While text_string pointing to ASCII char*/ poll_lcd_busy() ; /*Proceed no further if display busy*/ if ((char_cnt == END_ROW1)||(*text_string==CR)) { /*If new line required from line overrun or carriage return*/ *LCMIR = NEW_LINE; /*Set cursor position to new line position*/ char_cnt = 0 ; if(*text_string != CR) { /*If actual character to show on display*/ *LCMDR=*text_string ; } } else { /*Simply display next char in next position*/ *LCMDR =*text_string; char_cnt++; } text_string++ ; /*Next character to display*/ } } void display_txt() /*Purpose : Routine to set-up display ready for a new text string*/ { *LCMIR = 0x01; poll_lcd_busy(); *LCMIR = 0x0C; poll_lcd_busy(); text_out(); /*Clear display and return cursor to home position*/ /*Display is set on */ /*Output text string to LCD module*/ } main() { /*Set-up the 300H control by initialising registers*/ reg_setup(); /*Setup the pointers to the LCD display*/ LCMIR = ( unsigned char *)0xE04000; /*Instruction register address*/ LCMDR = ( unsigned char *)0xE04002; /*Data register address*/ /*Initialise the display*/ Hitachi Europe Ltd. ISSUE : APPS/048/1.1 lcdinit(); /*Write text strings to the LCD display*/ text_string = "HITACHI EUROPE LTD. LCD MODULE TEXT" ; /*Display string over two lines of LCD module*/ display_txt() ; } When using this document, keep the following in mind, 1, This document may, wholly or partially, be subject to change without notice. 2, All rights are reserved: No one is permitted to reproduce or duplicate, in any form, the whole or part of this document without Hitachi’s permission. 3, Hitachi will not be held responsible for any damage to the user that may result from accidents or any other reasons during the operation of the user’s unit according to this document. 4, Circuitry and other examples described herein are meant only to indicate the characteristics and performance of Hitachi’s semiconductor products. Hitachi assumes no responsibility for any intellectual property claims or other problems that may result from applications based on the examples therein. 5, No license is granted by implication or otherwise under any patents or other rights of any third party or Hitachi, Ltd. 6, MEDICAL APPLICATIONS: Hitachi’s products are not authorised for use in MEDICAL APPLICATIONS without the written consent of the appropriate officer of Hitachi’s sales company. Such use includes, but is not limited to, use in life support systems. Buyers of Hitachi’s products are requested to notify the relevant sales office when planning to use the products in MEDICAL APPLICATIONS. Copyright Hitachi, Ltd.,1995. All rights reserved Hitachi Europe Ltd. ISSUE : APPS/049/1.1 APPLICATION NOTE DATE : 8/5/96 Producing Optimised C for 300/300H Controllers The following application note has been produced to demonstrate features of the IAR toolsuite to enable efficient C coding for all of the 300 and 300H microcontrollers. The notes in this document will apply to all versions of the compiler and are applicable to all of the microcontrollers in the 3 something range. Assumptions have been made that a certain degree of competence has been obtained in the IAR toolsuite. Although appendix A details a list of contacts and references for the IAR toolset for any teething troubles, the 300 compiler tutorial is recommended as a quick reference. The following aspects will be covered : 1.0 General C coding practice 1.1 Use of modula coding 1.2 Globals vs Local variables 1.4 General C-guidelines 2.0 Memory Models and Processor options 3.0 Data and Code segment location. 4.0 Processor Bit Representations 5.0 Processor dependent code 5.1 Memory indirect addressing 5.2 Inline functions 6.0 Compiler Optimisation switches 6.1 Size and speed optimisations 6.2 Register Utilisation As an introduction to the comments on C-coding it is worth refreshing the CPU architectures of the 300 and 300H and their respective instruction sets. The reasoning behind this is that it should make it clear why certain programming techniques should be avoided to obtain maximum performance from the microcontroller. Hitachi Europe Ltd. ISSUE : APPS/049/1.1 300 / 300H CPU architecture In general both of these architectures are based upon a Load/Store type utilising compact instruction sets based around mostly register operations. A further point to note that the architecture addresses in linear fashion 1.0 General C-Coding Practices 1.1 Modula coding principles When programming to any C-environment it is recommended that a modular approach is used. The reasons for this are : • Ease of Refining complex problem to code solution • Maintainability can be obtained by enabling distinct modules to be easily swapped out or changed when necessary. • Readability for new engineers joining the project • Enabling portability to other micontrollers. • Makes possible more refined and localised testing mechanisms. A further point to note about this is that if code is grouped into similar execution code (code that runs at similar times) it may be possible to reduce the jumps to simple local ones and thus reduce the amount of full address reads required to run the code and thus reduce execution time. 1.2 Global Vs Local variables In general it is much better programming style and practice to make use of local variables wherever possible. The reason for this is quite simply to reduce the amount of RAM required for DATA structures. The more local a variable is the more feasible it will be to store the value on STACK or in General Purpose Registers. Thus avoiding the need to obtain variable address, read from address and write back value to address, which could possibly be stored as a long pointer requiring 32-bits of data. For further proof of this it can be seen that by examining the CPU instruction table in the HW manuals operations are about twice as efficient when using registered or immediate addressing modes rather than indirect addressing modes. Therefore where possible local variables should be used and always passed by reference through functions, thus ensuring that is only one copy of the respective variable. As an example of this code has been included below and then compiled using the IAR compiler with the achieved data densities as shown below : Version 1 : Automatic variables utilised char demo(void); void main(void) { char x; x=demo(); } char demo(void) Code size = 20 bytes Hitachi Europe Ltd. ISSUE : APPS/049/1.1 { char a=5, b=78, c; return(c=a*b+5); } Version 2 : Global static variables utilised char demo(void); char a=5, b=78, c; void main(void) { demo(); } Code size = 32bytes char demo(void) { c=a*b+5; } Thus, as illustrated above careful choice of programming style, such as using localised automatics, can have a dramatic effect on the code density produced for the 300 or 300H. Later on example benchmark code will be timed to show how effect of programming style can effect the speed of execution. 1.3 General programming style comments The following list although by no means definitive gives some final points on programming style that made aid in obtaining Robust, Readable and Correct code for an embedded application which can quite often be critical enough without allowing possible compiler/code bugs to be entered : • Group all externs required for C file in an include *.h file • Use static to give a variable file scope rather than making it global to the file • Create fewer special purpose functions to stop thrashing between code areas. • Always uses reference names that are meaningful to the system purpose • Always name any constants that maybe required. • Never use GOTO unless in a critical error situation. Repeatedly used code should be grouped into a function to avoid redundancy. Hitachi Europe Ltd. ISSUE : APPS/049/1.1 2.0 Memory and Processor options This section will deal with choosing the correct processor and memory models for a particular application. Careful choice of both these options is essential to achieve the optimum usage of the processor data and code areas. Also enabling the IAR compiler to generate the most efficient code by choosing the most appropriate addressing modes. Processor options are the simplest to choose, effectively only two factors to determine. Firstly, actual processor of choice (H8_300/300L/300H) and secondly the maximum address range (H8_300H only). The choice of processor option is simplified even more by the fact that the H8_300 and H8_300L have identical CPU cores with both having a maximum address range of 64K bytes. Consequently the only choice for 300 or 300L users is : v0. However, for the 300H there is a choice of 3 address ranges that can be chosen : 64K, 1M and 16M; The choice of range depends not only depends on the suitability for the software program but most certainly on the choice regarding the hardware design. For instance it may be a requirement for the hardware to have the full address range of 0 to FFFFFF where in terms of the software it would make much better sense to compile for a 1M address range (0 to FFFFF). However, what ever choice is made the software and hardware modes must be compliant with each other. Careful choice will be required between modes as this effects the size and location of pointers and function calling mechanisms. For instance a 16M address range requires pointers of a default size range of 32 bits to enable each address in the range to be accessed. Where a 64K address range would not require such a large pointer and could make do with a word pointer. • • • • v0 v1 v2 v3 - H8_300 OR H8_300L - ADDRESS RANGE = 64K H8_300H - ADDRESS RANGE = 64K H8_300H - ADDRESS RANGE = 1M H8_300H - ADDRESS RANGE = 16M Memory model options are much more vast and give the user further control of code generation process. For ease of choice included below is a flowchart which should enable the most efficient choice for a particular application. When examining the flowchart it should be remembered that the choice of memory model is effected by the choice of processor option. The reason for this being that the processor options specifies the maximum address range and thus the default of the calling mechanisms, details of this is shown in the flowchart. Further to the above choice variations is that it is possible to specify whether intrinsic library modules are addressed by the tiny_func mechanism or by the default mechanism of the memory model of choice. The case of the memory model specifies whether the space saving mechanism is employed or not. (lower case tiny_func calling mechanism will be employed). A discussion of the tiny_func calling mechanism is made later in this document. However, in general by using the tiny_func mechanism allows the compiler to generate a jsr rather than a bsr and thus save 2 bytes of code size. Hitachi Europe Ltd. ISSUE : APPS/049/1.1 Figure 1 : Memory model choice plan START 300H option only 300/300L or 300H single chip 64k Address Range outwith address range ? Banked maximum stack req. mb/B Non-Banked minimum stack req. mm/M me/E default code calling 16-bit ms/S Banked RAM reduction mb/B Default Stack reduce code by using tiny calling mt/T default code calling 16-bit ml/L Non-Banked minimum stack req. maximum stack req. Minimise Stack reduce code by using tiny calling 1M/16M Addr. Range outwith address range ? mm/M Minimise Stack reduce code by using tiny calling also with 256 byte stack me/E RAM reduction Default stack of 16M or 64K max. Default Stack reduce code default by using tiny code calling calling but with 64K stack ms/S mt/T default code calling 32/24-bit ml/L Consequently, although there is a positive wealth of choices they can be quickly tailored down to a choice of around 2 or 3 for each application if the flowchart is followed correctly. Note that although the choice of maximum stack size will effect directly the amount of RAM required for an application it will also have a considerable effect on the code requirements as well. The reason for this being that if the stack is specified as a maximum of 256 bytes then it can always be accessed as byte, R7L and similarly 64K would be word operations, R7 and 16M would be long operations, ER7. Thus,the code size requirements reduce as the size of maximum stack reduces. The final choice of model is usually down to the requirements of data addressing, function calling mechanism and stack requirements. The points below give a summary on how the models effect the compiler generation of code. • LARGE MODEL - Default option using standard calling mechanism and the stack calling mechanism represents that the stack can be a size up to the complete address range. No real code and data calling optimisations implemented • SMALL MODEL - Code calling mechanism reflects maximum address range. However, stack size is reduced by a factor that enables the stack to be addressed as a word instead of a long or a byte instead of a word. • TINY MODEL - Stack size is the default of a maximum as large as complete addressing range, word or long addressing. Code addressing is reduced by using tiny_func calling mechanism, as long as the function calling fits into the first 256 addresses of the memory map, where the interrupt vectors reside. • EXTRA SMALL - Code optimisations as tiny model, along with further RAM savings by reducing the stack size to a minimum of 256 bytes. Thus all stack operations are byte wide. Therefore, although the processor options defines the maximum range it is possible to still configure the software in a manner that makes use of ROM and RAM most efficiently. Hitachi Europe Ltd. ISSUE : APPS/049/1.1 3.0 Data and Code Segment direction Although generally conceived as a linker procedure it is possible to control the final generation of placing code and data at the compiler routine. When referring to placing code and data what is really meant is the assigning of addresses to constant code areas and the addresses of data locations. Consequently, it is very important to achieve the most efficient mapping since it can generally mean the difference between addressing something using a word value or a long value. Not only will the mechanism of addressing data be examined but also procedures in calling functions. As described in the previous section final address mapping of code can be altered depending on the choice of memory model. The choice of memory model will in general provide the default mechanism to be used by the compiler and linker to produce the object code. However, it is not the sole instrument in storage class description. it is in general possible to use overrides of memory directives where a programmer can determine a particularly time critical part of code that requires to run at optimum speed. Consequently, it may be possible to override the standard memory model with a more suitable one that may translate into assembly and thus machine code that will take less CPU cycles to run. To enable this the IAR toolset enables non-ANSI functions or #pragmas to directly alter the memory usage. Simply what can be done is to specify memory to be tiny, near, far, huge and back to default as the user may seem fit. Further to this the programmer has available 3 further #pragmas. Firstly there are two pragmas to enable direct naming of code or constant areas and data areas. The reason for doing this is such that it enables complete control at the linker stage where the actual code or data has to be placed, simply be specify the segment name and specify an actual address (-Z(DATA)DIFF_POSITION=0x900000). Secondly, the programmer can override the data initialisation mechanism by specifing certain variables as no_init. Consequently, this means that no extra ROM area is required for initialising values for data, also as a by product the CSTARTUP routine will obviously run quicker although this is usually not a concern in most systems. In general the most popular pragmas will be to control what functions can be addresses in a tiny_func mechanism. This is true as often programs are too large to be completely compiled as a tiny model so instead a default mechanism such as large or small can be used and then selectively choose critical modules to be compiled using the tiny_func mechanism i.e. #pragma tiny_func. The final technique available to the programmer to effect code generation is the use function attribute pragmas. Function attributes enable each individual module to be specified into a particular addressing scheme and also how it is called itself. The availble function attributes fall into two distinct variations =, firstly the ones that detail Hitachi Europe Ltd. ISSUE : APPS/049/1.1 4.0 Processor Bit Representation In many applications the effective representation of bit variables are essential. Either for use in pin manipulation, register set-up or simply as an efficient mechanism of holding status flags. To provide bit storage and manipulation there are two techniques of representation available to the programmer. Firstly, there is the standard keyword bit that can be used to access any variable in any area of memory as a bit variable and thus used the bit manipulation instructions. Secondly, we can define variables using the no-ANSI standard sfr and sfrp routines. Using these extended language features enables the actual bit to placed in the memory address area specifically set out for bit manipulations, 0xFFFF00 to 0xFFFFFF. The difference between both these mechanisms although both syntactically correct is the efficiency of representation in terms of both speed of operation and size of object code created. For instance all bit operations must be within the address range 0xFFFF00 to 0xFFFFFF since the addressing range of all of them are tiny, i.e. 0 to FF. Consequently, if data is specified to be of bit type and is not within the tiny addressing range then before the bit operations is completed the data must be transferred to a general purpose register. Example code is shown below detailing the size of object code produced and the number of CPU cycles to complete : Example Code Using SFRs #pragma language=extended NAME bitr(31) RSEG CODE(1) PUBLICmain EXTERN ?CL83LD3000_3_22_L00 RSEG CODE sfr right_way = 0xFFFF00 ; main () { } main: /*Do some bit manipulations */ right_way.1 = 1 ; right_way.2 = 0 ; right_way.3 = right_way.2 & right_way.1 ; if (right_way.0 == 1) { right_way.4 = 1 ; } ?0000: BSET.B BCLR.B BLD.B BAND.B BST.B BLD.B BCC #1,@0:8 #2,@0:8 #1,@0:8 #2,@0:8 #3,@0:8 #0,@0:8 ?0001 BSET.B #4,@0:8 ?0001: Speed of Execution = 7useconds Code Size = 948 Bytes Example code using Unsigned chars and Bits /* Bit Testing routine using unsigned chars*/ #pragma extended=language struct { unsigned char Flag1 : 1 ; unsigned char Flag2 : 1 ; unsigned char Flag3 : 1 ; unsigned char Flag4 : 1 ; unsigned char Flag5 : 1 ; } Byte_of_Bits; RTS END BSET.B BCLR.B MOV.L MOV.L BLD.B BAND.B BST.B MOV.B BTST.B BNE #0,@ER6 #1,@ER6 ER6,ER5 ER6,ER4 #1,@ER4 #0,@ER5 #2,@ER6 @Byte_of_Bits,R6L #3,R6L ?0001 ?0000: MOV.L BCLR.B ?0001: RTS RSEG DATA3 Byte_of_Bits: DC.B 0,0 END #Byte_of_Bits,ER6 #4,@ER6 Hitachi Europe Ltd. main() { Byte_of_Bits.Flag1 = 1 ; Byte_of_Bits.Flag2 = 0 ; Byte_of_Bits.Flag3 = Byte_of_Bits.Flag1 & Byte_of_Bits.Flag2 ; if (Byte_of_Bits.Flag4 == 0) { Byte_of_Bits.Flag5 = 0 ; } } ISSUE : APPS/049/1.1 NAME bitw(31) RSEG CODE(1) RSEG DATA3(1) PUBLICByte_of_Bits PUBLICmain EXTERN ?CL83LD3000_3_22_L00 RSEG CODE main: MOV.L #Byte_of_Bits,ER6 Speed of Execution = 14useconds Code size = 1030 bytes Thus from the code comparisons it can be seen that both speed and size efficiency is gained through using the provided extended compiler functions of SFRs. Not only efficiency is gained but also the ease of use in programming. 5.0 Processor Dependant Code The following sections now deal with more architecture dependant features that will directly effect the efficiency of representation of the C code. 5.1 Memory Indirect Addressing The memory indirect addressing mode is an effective way of reducing the overall code implementation of software. The reason for this is by using memory indirect addressing it is possible to use the JSR command rather than a BSR which in turn uses 2 less bytes. However, the only constraint of this is that the function that is being called is within the tiny addressing range. To demonstrate the procedure in making effective use of memory indirect addressing the following code has been included. Hitachi Europe Ltd. /* Addressing Test Program */ #pragma language=extended #pragma function=tiny_func void func_tiny() { static unsigned char i; i ++; } #pragma function=default void norm_func() { static unsigned char j; j++; } main () { /*Call normal Function*/ norm_func(); /*Call tiny Function*/ func_tiny(); } ISSUE : APPS/049/1.1 NAME ftest(31) RSEG CODE(1) RSEG FLIST(1) RSEG DATA3(1) PUBLIC?Flist_func_tiny PUBLICfunc_tiny PUBLICmain PUBLICnorm_func EXTERN ?CL83LD3000_3_22_L00 RSEG CODE func_tiny: PUSH.W R6 MOV.B @?0000,R6L INC.B R6L MOV.B R6L,@?0000 POP.W R6 RTS norm_func: PUSH.W R6 MOV.B @?0001,R6L INC.B R6L MOV.B R6L,@?0001 POP.W R6 RTS main: BSR norm_func JSR @@?Flist_func_tiny RTS Thus, it can be seen that by using the pragma directive to set-up a function as a tiny rather than the default (Huge in this case) then the JSR command can be used. Which as already discussed uses 2 less bytes in implementation. than a BSR with addressing mode @(d,PC). Further, to this point it is worth comparing the size of object code created. If tiny_func is used the size of code is , where if no tiny_func mode was used the size of code is 5.2 Inline Functions Intrinsic functions have been provided as extensions to the ANSI library functions to provide more device specific utilities. For a full list it will be necessary to examine the IAR C manual although detailed in the included code below shows specifics of some of the routines. In general the routines allow control of registers that would only be made possible by jumping to an assembly level module, such as altering the interrupt mask level on the CCR. The code below not only shows the action of some of the routines it shows that the intrinsic functions are actually Inline. This meaning that it is not necessary to jump to a distinct routine to complete the action, but simply include the necessary assembly instructions. This will give a saving on code size and code execution. The feature of making the functions Inline is even more useful when examination shows how little code is required to complete the operation. more code would be involved in jumping to/from a function rather than executing it. main () 8 9 { Hitachi Europe Ltd. ISSUE \ 00000000 main: 10 11 /*Set interrupt mask in ccr to level 2*/ 12 set_interrupt_mask(2) ; \ 00000000 0480 ORC.B #128,CCR \ 00000002 06BF ANDC.B #191,CCR 13 14 /* XOR CCR to value shown*/ 15 xor_ccr(8) ; \ 00000004 0508 XORC.B #8,CCR 16 17 18 /* Execute sleep command*/ 19 sleep() ; \ 00000006 0180 SLEEP 20 21 /* Execute a no-operation*/ 22 no_operation() ; \ 00000008 0000 NOP 23 24 /*etc.. */ 25 26 } \ 0000000A 5470 RTS \ 0000000C END : APPS/049/1.1 Assembly functions included within created object code. No call or jump to a function. Thus, the main point to consider is that wherever possible use a supplied Inline function, rather than creating your own function to complete the operation. Since, this will result in a much better implementation in terms of code density and speed. Also note that setting a function as Inline is non-ANSI standard and the IAR compiler only enables the already defined intrinsic functions to be Inline. The reason for this is that complete corruption of code can occur if registers are altered within Inline code without saving the previous value used within the normal code. 6.0 Optimisation Switches at Compile Time The following section detail switches that can be used when the compiler ICCH83 is invoked to make use of certain compilation algorithms to maximise the efficiency of the code. 6.1 Size and Speed Optimisation The size and speed optimisation algorithm can be implemented at a number of levels to produce optimised code and data usage. The levels of optimisation will determine the correspondence between the C-code and the generated assembly code. It should be noted that the algorithms are incompatible and thus cannot be used in the same execution of the compiler. Levels of optimisation range from 0 (min) to 8/9 (max.) with the following effects : • • • • • Level 0-2 - No optimisation and thus can be used for debug processes Level 3 - debuggable optimisations only Level 4-7 - Medium complex optimisations and thus may not be fully debuggable Level 8 - Complex optimisations Level 9 - New optimisations for a particular version and thus maynot be fully tested and thus can improve in later versions The method to choose the optimisation level should be based on a trial basis by re-compiling the code a number of times with different options. Typical results obtained are as follows, although the level of optimisation in general will improve code density to different degrees depending on the code structures. Note that in this case optimising for speed not only achieves the quickest execution speed it also obtains the smallest code size. Although, speed optimisation will not always produce the most compact code. Hitachi Europe Ltd. ISSUE : APPS/049/1.1 6.2 Register Utilisation The final run-time compiler technique that can be used is the register utilisation switches, -u and -W. They give the programmer further control on how the generated code uses registers to clean up and trash. Using these mechanisms can have a dramatic effect on the code density required for a procedure Stack Clean Up The stack clean up option -W directs the compiler in how often it should clean up temporary variables from the stack. Temporary variables are used in complex operations to store intermediary results. The -W option plus a number up to 50 specifies how much of the stack can be used by garbage before resetting the SP back again. With a high -W value less cleans up will occur and thus the code will execute quicker, although to offset this more stack will be required, specifically if the program has a high degree of function nesting. i.e. Complex Instruction A B C D E Bytes of Stack required 4 6 8 2 6 Clean ups : -W0 Clean ups : -W18 4->0 6->0 8->0 2->0 6->0 4 10 18->0 2 8 Register trashing conventions The -u option effects the manner in which registers are used to store parameters and which registers need not be saved by a function and thus can be trashed. For instance the general procedure is to store the first function parameter in R6 and the rest in the stack with all registers exempt from trashing. This can be extended to store parameters in ER4, ER5 and ER6 with register trashing enabled on ER4, ER5 and ER6. This is the highest level and will provide the most code compact solution. Hitachi Europe Ltd. ISSUE : APPS/049/1.1 The option is used as follows : -urxuy where x chooses the level of register parameter storing and y the level of register trashing. • • • • • • • • • • • r0 - Normal procedure R6 stores first parameter r1 - ER6 used to store parameter r2 - ER5, ER6 used to store parameters r3 - ER4 ER5 and ER6 used to store parameters u0 - No registers trashed in function call u1 - R6 trashed u2 - ER6 trashed u3 - R5 and ER6 trashed u4 - ER5 and ER6 trashed u5 - R4, ER5 and ER6 trashed u6 - ER4, ER5 and ER6 trashed Thus, after proving the functionality of the code further levels of optimization can be introduced to reduce code size. Please remember the library routines must be built with the same optimizations levels or it will not link! When using this document, keep the following in mind, 1, This document may, wholly or partially, be subject to change without notice. 2, All rights are reserved: No one is permitted to reproduce or duplicate, in any form, the whole or part of this document without Hitachi’s permission. 3, Hitachi will not be held responsible for any damage to the user that may result from accidents or any other reasons during the operation of the user’s unit according to this document. 4, Circuitry and other examples described herein are meant only to indicate the characteristics and performance of Hitachi’s semiconductor products. Hitachi assumes no responsibility for any intellectual property claims or other problems that may result from applications based on the examples therein. 5, No license is granted by implication or otherwise under any patents or other rights of any third party or Hitachi, Ltd. 6, MEDICAL APPLICATIONS: Hitachi’s products are not authorised for use in MEDICAL APPLICATIONS without the written consent of the appropriate officer of Hitachi’s sales company. Such use includes, but is not limited to, use in life support systems. Buyers of Hitachi’s products are requested to notify the relevant sales office when planning to use the products in MEDICAL APPLICATIONS. Copyright Hitachi, Ltd.,1995. All rights reserved Hitachi Europe Ltd. ISSUE : APPS/050/1.2 APPLICATION NOTE DATE : 17/4/96 Access Speed on the H8/300H Minimum access times for external memory of H8/300H series are given in table 1. These minimum times are for two-, three-, and four-state accesses. Note that H8/3048 Series have different minimum access times and these times are presented in table 2. System clock Min Clock Cycle Time Min 2-State Access Time Min 3-State Access Time Min 4-State Access Time 8MHz 125.0 110 230 355 10MHz 100.0 100 200 300 12MHz 83.3 80 160 245 16MHz 62.5 55 115 180 Table 1. Minimum access times for external memory of H8/300H Series. Times are in ns. Note that H8/3048 times differ from these (Table 2.). System clock Min Clock Cycle Time Min 2-State Access Time Min 3-State Access Time Min 4-State Access Time 8MHz 125.0 120 240 365 13MHz 76.9 60 140 220 16MHz 62.5 60 120 185 18MHz 55.5 50 105 160 Table 2. Minimum access times for external memory of H8/3048 Series. Times are in ns. Simple example how 8-/16-bit bus width and 2-/3-state access affects performance is shown in Table 3, where a word from external memory address h’6FFFFF is loaded to register R0, incremented by 1 and stored back to external memory address h’6FFFFF. Table 3 presents the amount of states required and table 4 the time in ns required to execute these instructions. Instruction On-Chip 8-Bit Memory Bus, 2State Access 8-Bit Bus, 3State Access 16-Bit Bus, 2State Access 16-Bit Bus, 3State Access mov.w @aa,R0 inc.w #1,R0 mov.w R0,@aa 8 2 8 16 4 16 24 6 24 8 2 8 12 3 12 States Total 18 36 54 18 27 Hitachi Europe Ltd. ISSUE : APPS/050/1.2 Table 3. Number of states required for instruction execution with different bus width and different state accesses. Advanced mode. Instruction On-Chip 8-Bit Memory Bus, 2State Access 8-Bit Bus, 3State Access 16-Bit Bus, 2State Access 16-Bit Bus, 3State Access mov.w @aa,R0 inc.w #1,R0 mov.w R0,@aa 444 111 444 888 222 888 1332 333 1332 444 111 444 666 167 666 Time Total 999 1998 2997 999 1499 Table 4. Time in ns required for instruction execution with different bus width and different state accesses. Advanced mode, 16MHz clock speed. When using this document, keep the following in mind, 1, This document may, wholly or partially, be subject to change without notice. 2, All rights are reserved: No one is permitted to reproduce or duplicate, in any form, the whole or part of this document without Hitachi’s permission. 3, Hitachi will not be held responsible for any damage to the user that may result from accidents or any other reasons during the operation of the user’s unit according to this document. 4, Circuitry and other examples described herein are meant only to indicate the characteristics and performance of Hitachi’s semiconductor products. Hitachi assumes no responsibility for any intellectual property claims or other problems that may result from applications based on the examples therein. 5, No license is granted by implication or otherwise under any patents or other rights of any third party or Hitachi, Ltd. 6, MEDICAL APPLICATIONS: Hitachi’s products are not authorised for use in MEDICAL APPLICATIONS without the written consent of the appropriate officer of Hitachi’s sales company. Such use includes, but is not limited to, use in life support systems. Buyers of Hitachi’s products are requested to notify the relevant sales office when planning to use the products in MEDICAL APPLICATIONS. Copyright Hitachi, Ltd.,1995. All rights reserved Hitachi Europe Ltd. ISSUE : APPS/051/1.0 APPLICATION NOTE DATE : 17/4/96 Real time low power sheduler for the 300L series. INTRODUCTION The following example is a framework for a real-time sheduler which makes use of the very low power capabilities of the 300L family. The 300L family of microcontrollers feature a dual crystal solution; one main oscillator between 0.2 and 10Mhz (0.1-5Mhz internal) and a subclock which uses a standard 32Khz watch crystal. This example uses full speed mode running off the main oscillator and watch mode using the 32Khz sub clock. Watch mode is a software triggered standby mode where the main clock is shut down and a few key peripherals are kept running. All other registers and the on board RAM is retained. The members of the 300L family which feature LCD drive can also keep the display active during watch mode. The key to watch mode is Timer A which functions as the time base timer, again running off the 32Khz subclock. When this timer overflows (Period selectable between 1/ 32 ,1/8 1/4 or 1 second overflow) an interrupt is generated which will wake the 300L up into active mode. The scheduler can then execute the real time tasks at full speed and instantly switch back to watch mode on completion. The power consumption reduction by switching modes can be as much as from 10mA down to 15µA, which is particularly applicable to battery operation. The example considered here uses a quarter second overflow period, and by using two software counters a simple scheduler providing 1/4 , one second and ten second schedule periods although these could be adjusted to any value within reason. To demonstrate the operation of the code each sheduler period function toggles a port (port 2) which can be connected to an L.E.D. via a buffer. FUNCTIONS OVERVIEW main() This contains only the watch mode call which always happens as soon as the real time scheduler has finished its current tasks. interrupt [TIMER_A] void schedule (void) This is the interrupt service routine for timer A. Its purpose is to reset the interrupt request (to disable continual looping of the routine) and then call the scheduled functions. void initialisation (void) Here the ports controlling the LED’s are initialised to outputs and timer A is set up as the timebase. Also timer A interrupt is enabled to allow it to wake the CPU up form watch mode on and overflow. The final and important initialisation is using the in-line function set_interrupt_mask(0) which clears the I bit in the CCR. This globally enables interrupts by reseting the mask from the default (1). 1 of 7 Hitachi Europe Ltd. ISSUE : APPS/051/1.0 TMA- Timer A control register set to HEX ba = 1011 1010 TMA7 TMA6 TMA5 - Clock output pin prescaler TMA3 TMA2 unused TMA1 TMA0 Prescaler/overflow peri od timebase on/off void watch(void) The watch function sets the system control registers to tell the CPU to enter watch mode when the sleep instruction is called. SLEEP is another in-line extension to ANSI C provided by the IAR C compiler. SYSCR1 SSBY System control Register 1 - set to HEX b0 = 1011 0000 STS2 STS1 STS0 clock settling time selection standby/watch mode SYSCR2 - LSON - - low speed flag (32Khz) - reserved System control register 2 - set to HEX 00 - 0000 0000 - Reservered - NESEL DTON MSON SA1 SA2 Noise elimination Medium speed Direct transfer Subactive clock select. void quarter_second_tasks(void) void one_second_tasks(void) void ten_second_tasks(void) These functions are where the user should place or call the scheduled tasks. The only two restrictions to be considered are:1) The worst case when all 3 task calls are entered (once every ten seconds), the total execution time should be less than the schedule period. 2) Other interrupts will not be serviced as the schedule calls are themselves called from the interrupt service routine. This means the I bit will be set, preventing any further interrupts until it has finished. One way to avoid this is to use a global flag to request a schedule task, with the schedule call only setting the flag. 2 of 7 Hitachi Europe Ltd. ISSUE 3 of 7 : APPS/051/1.0 Hitachi Europe Ltd. ISSUE : APPS/051/1.0 300LRTC.C /******************************************************************** This program is an a simple example of a low power, real time scheduler.It can wake up and execute tasks on a periodic basis. The 300L initially sit in WATCH mode (see main) until timer A overflows and causes it to wake up into full speed execution mode. Three schedule time periods are shown here, 1/4 second, 1 second and 10 seconds. Each schedule function flashes an led to prove the operation of the program. ********************************************************************/ #include "c:\h8\inc\ioh83834.h" #include "c:\h8\inc\inh83834.h" #include /* H8/3834 IO labels */ /*and the interrupts */ /*include interrupt std functions*/ /* ********** */ /* Variables */ /* ********** */ unsigned char one_second,ten_seconds; /* /* /* /* ********** */ Functions */ Declaration*/ ********** */ interrupt [TIMER_A] void schedule(void); void initialisation(void); void watch(void); void quarter_second_tasks(void); void one_second_tasks(void); void ten_seconds_tasks(void); void main(void) { initialisation(); /*set up timer A overflow interrupt*/ /*and the port registers */ for (;;) { /*The processor return to this section of the code as soon as the scheduler has finished its tasks. When an interrupt occurs the 300L will wake up and jump the relevant interrupt service routine.*/ watch(); } } 4 of 7 to Hitachi Europe Ltd. ISSUE : APPS/051/1.0 interrupt [TIMER_A] void schedule(void) { IRR1 &= 0x7f; /*reset the interrupt request. */ /*this lot must be View more...Comments
Report "Oct 1996 Lit. No A. H8 Microcontroller Series Application Notes Collection"Please fill this form, we will try to respond as soon as possible.
Your name Email Reason -Select Reason- Pornographic Defamatory Illegal/Unlawful Spam Other Terms Of Service Violation File a copyright complaint Description Close Submit Share & Embed "Oct 1996 Lit. No A. H8 Microcontroller Series Application Notes Collection"Please copy and paste this embed script to where you want to embed
Embed Script Size (px) 750x600 750x500 600x500 600x400 URL Close Copyright � 2017 SILO Inc.Từ khóa » Hitachi H8/3003
-
H8/3003 - 16-bit Microcontrollers With Embedded 512KB ... - Renesas
-
[PDF] H8/3003 Hardware Manual - Octopart
-
H8 Family - Wikipedia
-
HD6413003 Datasheet - H8/3003 Microcontroller - DigChip
-
HITACHI IC Chip HD6413003F10 6K1 R H8/3003 - EBay
-
H8/3003 Datasheet & Applicatoin Notes
-
Keysight Technologies 64784A Emulator For Hitachi H8/3003 ...
-
[PDF] H8s And H8/300H
-
[PDF] H8/3003 - PICList
-
[PDF] H8/300H Series Programming Manual
-
H8® H8/300H - Renesas Electronics America Inc | Online Catalog
-
[PDF] Hitachi Microcomputer H8/3032 Series Hardware Manual
-
[PDF] Hitachi Microcomputer H8/300H Series Application Notes For CPU