How to simulate Real Time Interrupt in 68HC11 THRSim11 simulator - microcontroller

how do you simulate the RTI (Real Time Interrupt) in the 68HC11 THRSim11 simulator (see http://www.hc11.demon.nl/thrsim11/thrsim11.htm)? the following program works at the 68HC11 module but not in THRSim11. It's a test program to read from Analog to Digital Converter and display results to serial port using RTI. I tried the RTI interrupt vector 00EB and FFF0. My chip is the 68H711E9 with the following memory map.
I expected the THRSim11 to simulate the interrupt vector. When running the "again BRA again" just before CLI (enable Interrupt). It must be running the subroutine that reads from ADC and display to serial. It works perfectly in my 68HC711E9 Evaluation board with buffalo
REGBS EQU $1000 ;start of registers
BAUD EQU REGBS+$2B ;sci baud reg
SCCR1 EQU REGBS+$2C ;sci control1 reg
SCCR2 EQU REGBS+$2D ;sci control2 reg
SCSR EQU REGBS+$2E ;sci status reg
SCDR EQU REGBS+$2F ;sci data reg
TMSK2 EQU REGBS+$24 ;Timer Interrupt Mask Register 2
TFLG2 EQU REGBS+$25 ;Timer Interrupt Flag Register 2
ADR3 EQU $1033 ;ADC address 3
OPTION EQU $1039 ;ADC enable
SCS EQU $2E ;SCSR low bit
ADCTL EQU $1030 ;ADC setting
ADCT EQU $30 ;ADC setting low bit
PACTL EQU $1026 ;Pulse Accumulator control
***************************************************************
* Main program starts here *
***************************************************************
ORG $0110
* ORG $E000
start LDS #$01FF ;set stack pointer
JSR ONSCI ;initialize serial port
JSR t_init ;initialize timer
CLI ;enable interrupts
again BRA again
************************************************************
* t_init - Initialize the RTI timer
************************************************************
t_init LDAA #$01 ; set PTR1 and PTR0 to 0 and 1
STAA PACTL ;which leads to an RTI rate of 8.19 ms
LDAA #$40
STAA TFLG2 ;clears RTIF flag (write 1 in it!)
STAA TMSK2 ;sets RTII to allow interruptssec
RTS
************************************************************
* ADC_SERIAL - timer overflow interrupt service routine
************************************************************
ADC_SERIAL
LDX #REGBS
LDAA #%00010010
STAA ADCTL
LDAB #6
ADF00 DECB
BNE ADF00
ldaa ADR3 ; read ADC value
ldab SCSR ; read first Status
staa SCDR ; save in TX Register
BUFFS BRCLR SCS,X #$80 BUFFS
CLRFLG LDAA #$40
STAA TFLG2 ;clear RTIF
RTI ;return from ISR
************************************************************
* ONSCI() - Initialize the SCI for 9600
* baud at 8 MHz
************************************************************
ONSCI LDAA #$30
STAA BAUD baud register
LDAA #$00
STAA SCCR1
LDAA #$0C
STAA SCCR2 enable
LDAA #%10011010 ; enable the ADC
STAA OPTION
RTS
* Interrupt Vectors for BUFALO monitor
* ORG $FFF0 ;RTI vector for microcontroller
*
ORG $00EB ;Real Time Interrupt under Buffalo monitor
JMP ADC_SERIAL ;this instruction is executed every
* time there is a timer overflow

Presumably you mixed up "vector table" and "jump table". The HC11 expects an address at $FFF0, not an instruction.
In contrast, the Buffalo monitor expects an instruction at $00EB.
ORG $FFF0 ;RTI vector for microcontroller
FDB ADC_SERIAL
ORG $FFFE ;Reset vector for microcontroller
FDB start
As you will note, the same holds true for the reset vector at $FFFE.
With these changes it works for me. Be aware that the simulation is really slow*, depending on the number and kind of views opened.
Another side note: You send the single byte of conversion result without further processing. The serial receiver view of the simulator will try to interpret this byte as an ASCII character, and only if it fails, show a decimal number in angles. You might want to consider to convert the conversion result into a human readable value. The most simple solution may be a hex representation.
EDIT:
*) A simulator needs to be factors faster than the original machine, depending on the specific implementation of the simulation. In this case, they seem to have used a quite slow way. The documentation has some words on this. To gain some speed, close any view you don't need, and use the fastest PC you can get. To gain some understanding, think about how slow a simulation would be if it will simulate the analog electronics with each semiconductor of the chip. And even that is just a model, the "real" world currently starts at quantum mechanics.
Without further measure, you cannot use Buffalo's jump table entries, because the Buffalo monitor is not included in the simulator.
If you want to use an unmodified version of your firmware, you will need to add at least the used parts of the Buffalo monitor. If you have the monitor as a file loadable by the simulator, you might want to load it before loading your application.
The least you could do is to provide the jump table yourself, placing the appropriate address of the jump in the vector:
ORG $FFF0 ;RTI vector for microcontroller
FDB $00EB
The "problem" with the ASCII interpretation becomes visible, if values of printable characters are sent. Put the slider in the first third, and you will see some letter or digit or punctuation. Slide it minimally up and down for other characters. Yes, terminals can be dumb, and this one is no exception. Actually it is a little bit smart and shows the printable characters instead of their ASCII value. Additionally it knows at least CR (carriage return, $0D, decimal 13) and LF (line feed, $0A, decimal 10). You might want to write a little test program that sends "Hello, world", CR, LF. Or another experiment that sends all values from $00 to $FF.
The meaning of a value always depends on its interpretation. This terminal interprets values as ASCII characters, if possible.

Related

PWM output always 0 on proteus (using atmega328p and assembly on microchip studio to write the code)

i am currently trying to setup a servo motor on a proteus circuit using a PWM signal (TCR0) on the atmega328p , i went through several manual books to setup the bits in the TCCR0A and TCCR0B registers and the duty cycle value on OCR0A and expect an output on the OCR0A port.
.INCLUDE "M328PDEF.INC"
.ORG 0x00
SBI DDRD , 6 // port D6 output for PWM
LOOP:
CALL TESTN
CALL delay
JMP LOOP
TESTN:
LDI R20 , 127 //duty cycle value (50%)
STS OCR0A , R20 // duty cycle on OCR0A
LDI R17 , 0b10000011
STS TCCR0A , R17 //Non-Inverting Fast PWM mode 3 using OCRA
LDI R18 , 0b00000001
STS TCCR0B , R18 //No-Prescalar
//LDS R20 , OCR0A // trying to output on port D6 but maybe doesnt matter
//OUT PORTD , R20
delay:
LDI R16 , 1
L0: LDI R17 , 1
L1: LDI R18 , 20
L2: DEC R18
BRNE L2
DEC R17
BRNE L1
DEC R16
BRNE L0
RET
proteus circuit results
Can anyone tell me what i am missing ?
Any help is appreciated ,thanks in advance
I expected to receive a signal on portD,6 which will result in a movement of the servo but the output is always 0 on that port (not sure why other ports have output values without actually defining anything regarding them)
Edit : if anyone knows a good compiler from C to avr assembly it would be appreciated.
It would be much simpler if you write the code in C and then look at the disassembly.
Note: Timer0 registers (TCCR0A, TCCR0B, OCR0A etc) are in the lower range of I/O-registers and can be accessed both by memory access operations (like STS, LDS) using their memory address, and also can be accessed by IN and OUT operations, using their I/O-register number.
How your constant are declared? For example, if TCCR0A equals to 0x44, then it is a memory address, and STS should be used. But if it equals to 0x24 then it is IO-register number and OUT should be used instead.
Also, there is no ret at the end of TESTN in your code
Turns out i needed prescaling since the atmega32p has 18MHz processor speed which wont provide the 20ms duration signal needed by a servo motor. I used 8 prescaling (TCCR0B = 0b00000100) and adjust the angle through the OCR0A values.

Ada for I2C on the BBC Micro:Bit with the MCP23017

I am trying to set up a very simple example using the ada I2C library with the MCP23017 IO expander on the micro:bit (V1.5) but I can't figure it out. For now, all I want to do is turn on an LED that is connected to a GPIOA pin. I have it working in python with the following:
from microbit import i2c
while True:
# set pins to output
# 0x20 is the address of the MCP23017
# the first 0x00 is the IODIRA address for setting pin direction (input/output)
# the second 0x00 sets all the pins to be outputs
i2c.write(0x20, bytes([0x00, 0x00]))
# set outputs to true to turn on led
# 0x14 is the OLATA address for outputs
# 0xFF sets all outputs to true
i2c.write(0x20, bytes([0x14, 0xFF]))
and here is my attempt in ada:
with MicroBit.Display; use MicroBit.Display;
with MicroBit.I2C;
with HAL.I2C; use HAL.I2C;
procedure Main is
I2C_Controller : constant HAL.I2C.Any_I2C_Port := MicroBit.I2C.Controller;
I2C_Slave_Address : constant HAL.I2C.I2C_Address := 32;
Pins_Out : constant I2C_Data (0 .. 1) := (0, 0);
Outputs_On : constant I2C_Data (0 .. 1) := (20, 255);
Status : HAL.I2C.I2C_Status;
begin
MicroBit.I2C.Initialize;
Display ('I');
loop
I2C_Controller.Master_Transmit (Addr => I2C_Slave_Address,
Data => Pins_Out,
Status => Status);
I2C_Controller.Master_Transmit (Addr => I2C_Slave_Address,
Data => Outputs_On,
Status => Status);
end loop;
end Main;
I tried to translate the inputs from hex in the python example to the decimal that the ada library needs. So 0x20 in the python corresponds to 32 decimal for the ada. Similarly, 0x00 -> 0, 0x14 -> 20 and 0xFF -> 255. I must be missing something because this isn't working. I display the 'I' to make sure that it flashes successfully, but nothing happens other than that. Any help would be greatly appreciated,
Thanks!
I had an MCP23017 in 2012; can’t find it, so hard to help other than by suggesting lines of approach.
Have you tied the three settable address lines in the datasheet Fig 3.6 (pins 15, 16, 17 in the diagram on the first page) to ground?
You don’t check that the returned Status from the Master_Transmit calls is HAL.I2C.Ok.
Looking at line 135 of nrf-twi.adb
This.Periph.ADDRESS.ADDRESS := UInt7 (Addr / 2);
and comparing it to Fig 3.6 again, I strongly suspect that the chip address you pass to the Ada Drivers Library should be 16#40#. There’s controversy as to whether the address you specify to your support library is bits 1..7 or 0..6, i.e. whether the library expects to divide or multiply it by 2 before sending to the hardware. To confuse the picture further, Table 272 in the nRF51 RM suggests that only the 7 bits of the address are written to the ADDRESS register, with the read/write bit sent after the address bits by the nRF51 hardware; while for the STM32 range, it’s up to our software to put the address bits in the right place (bits 1 .. 7), and the library software twiddles the read/write bit (0).
Guessing here, but it looks as though the Python library writes the value you give it straight into the ADDRESS register.
See this Ada Drivers Library issue.

I noticed something in the optiboot bootloader hex file for Arduino. Why so?

When I look at the bootloader hex file, the starting address from the word type of the program is 7E00 according to intel-hex format. This is the 3F00. The interesting part starts right now. According to the Atmega328p datasheet, the BOOTS1 and BOOTS2 registers must be set for this to start from 3F00. But when I look at the Arduino Uno fuse settings,
lfuse = 0xff
hfuse = 0xde
efuse = 0x05
is defined as such. In this case . The BOOTS1 and BOOTS2 parameters in the High fuse settings parameter are set as not set.
Is there something I'm missing?
Here is the optibootbootloader.hex file
:107E0000112484B714BE81FFF0D085E080938100F7
:107E100082E08093C00088E18093C10086E0809377
:107E2000C20080E18093C4008EE0C9D0259A86E02C
:107E300020E33CEF91E0309385002093840096BBD3
:107E4000B09BFECF1D9AA8958150A9F7CC24DD24C4
:107E500088248394B5E0AB2EA1E19A2EF3E0BF2EE7
:107E6000A2D0813461F49FD0082FAFD0023811F036
:107E7000013811F484E001C083E08DD089C08234E0
:107E800011F484E103C0853419F485E0A6D080C0E4
:107E9000853579F488D0E82EFF2485D0082F10E0AE
:107EA000102F00270E291F29000F111F8ED06801E7
:107EB0006FC0863521F484E090D080E0DECF843638
:107EC00009F040C070D06FD0082F6DD080E0C81688
:107ED00080E7D80618F4F601B7BEE895C0E0D1E017
:107EE00062D089930C17E1F7F0E0CF16F0E7DF06D8
:107EF00018F0F601B7BEE89568D007B600FCFDCFD4
:107F0000A601A0E0B1E02C9130E011968C91119780
:107F100090E0982F8827822B932B1296FA010C0160
:107F200087BEE89511244E5F5F4FF1E0A038BF0790
:107F300051F7F601A7BEE89507B600FCFDCF97BE46
:107F4000E89526C08437B1F42ED02DD0F82E2BD052
:107F50003CD0F601EF2C8F010F5F1F4F84911BD097
:107F6000EA94F801C1F70894C11CD11CFA94CF0C13
:107F7000D11C0EC0853739F428D08EE10CD085E9AC
:107F80000AD08FE07ACF813511F488E018D01DD067
:107F900080E101D065CF982F8091C00085FFFCCF94
:107FA0009093C60008958091C00087FFFCCF809118
:107FB000C00084FD01C0A8958091C6000895E0E648
:107FC000F0E098E1908380830895EDDF803219F02E
:107FD00088E0F5DFFFCF84E1DECF1F93182FE3DFCA
:107FE0001150E9F7F2DF1F91089580E0E8DFEE27F6
:047FF000FF270994CA
:027FFE00040479
:0400000300007E007B
:00000001FF
You are correct that this high fuse byte of the Arduino Uno is 0xDE; I confirmed that by checking boards.txt.
That means that BOOTSZ is set to 11, which means the bootloader size is 256 words and starts at word 0x3F00 (byte address 0x7E00), as documented in the ATmega328P datasheet (Table 26-7). There is no contradiction.

MSP430 MEMORY ADDRESS IN CCS6

I've wrote my very first MSP-EXP430F5529LP LED on/off program.
and I wanted to analyze my program. but I had problem at my first step.
I extracted my LED program from board and I've got unclear data. (3)
that's my first question. what is that file format? I mean I want to know file format for my memory dump file. (3)
my second question is that why CCS 6 doesn't indicate memory address properly?
I know that MSP430 is 16 bit MCU. so every memory address should be 16 bit-width. but my assembly code(2) which is copied from CCS6 Disassembly View show me address just like 01XXXX format.
relative data dereference and execution flow branches work well. but why CSS6 make me confused? I mean I want to know that why CCS6 display memory addresse 24 bit-width??
anyone who know where is TI document which explain what I want to know, please let me know. please just don't mention MSP430xxxx User's Guide.
sorry for my english :(
1.c code
#include <msp430f5529.h>
volatile unsigned int i;
void main(void) {
WDTCTL = WDTPW | WDTHOLD;
P1DIR |= 0x01;
while(1){
P1OUT ^= 0x01;
for(i = 20000;i > 0; i--);
}
}
2.assembly code
0100c2: 40B2 5A80 015C MOV.W #0x5a80,&Watchdog_Timer_WDTCTL
0100c8: D3D2 0204 BIS.B #1,&Port_A_PADIR
0100cc: E3D2 0202 XOR.B #1,&Port_A_PAOUT
0100d0: 40B2 4E20 2400 MOV.W #0x4e20,&i
0100d6: 3C02 JMP (0x00dc)
0100d8: 8392 2400 DEC.W &i
0100dc: 9382 2400 TST.W &i
0100e0: 27F5 JEQ (0x00cc)
0100e2: 3FFA JMP (0x00d8)
0100e4: 4303 NOP
0100e6: D032 0010 BIS.W #0x0010,SR
0100ea: 3FFD JMP (0x00e6)
0100ec: 431C MOV.W #1,R12
0100ee: 0110 RETA
0100f0: 4303 NOP
0100f2: 3FFF JMP (0x00f2)
3.memory dump (MAIN)
:1044000031400044b113ec000c930224b1130000be
:104410000c43b113c200b113f00000000200000011
:10442000840001001a44000000240000ffffffff89
:10443000ffffffffffffffffffffffffffffffff8c
:10444000ffffffffffffffffffffffffffffffff7c
...
...
If one reads the User Guide (which is why they exist) then one is informed that the Program Counter is 20-bit. So, now you know why you see an address in the 20-bit range.
Link to the MSP430 User Guide: http://www.ti.com/lit/ug/slau208n/slau208n.pdf
The 20-bit PC (PC/R0) points to the next instruction to be executed.
Each instruction uses an even number of bytes (2, 4, 6, or 8 bytes),
and the PC is incremented accordingly. Instruction accesses are
performed on word boundaries, and the PC is aligned to even addresses.
Figure 6-3 shows the PC.
The above is an excerpt from the User Guide. I cannot emphasis this enough - but you really need to read the User Guide. Not doing so and attempting to program microcontrollers is perlious to your mental health.
The memory dump seems to be in the Intel hex file format https://en.wikipedia.org/wiki/Intel_HEX

MSP540F5438A Clock Bringup

I'm new to the MSP430 and I am trying to better understand the clock bring-up process. For my current purpose I'm going to take PMMCOREV out of the equation by using a 4 MHz MCLK which is within the 0-8 MHz range for PMMCOREV = 0.
Will someone knowledgable about these parts please check my logic and assumptions:
When the part boots XT1 is selected as the FLL reference and DCOCLKDIV is selected as the MCLK input. DIVM is 0 so the MCLK source is not divided.
When the system boots the crystal is not yet stable so I'm assuming the UCS moves in to fail-safe mode and uses REFO (internal trimmed 32K) as the FLL reference.
Already I'm a bit confused. If the divided DCO is used for MCLK how are we assured that the FLL is stable? So how is the core functioning at all?
It seems to me that MCLK should be either VLO or REFO until you can bring things up gracefully.
Can someone clarify these details and steer me in the right direction to properly initialize these clocks?
Thanks!
Per your comment, yes.
At startup DCO will be the clock - so you just need to modify the UCSCTL registers and wait for the oscillators to settle and you are good to go.
Here are the steps in general:
Change the vcore level in steps (if necessary - in your case its not)
Enable XT1
Configure the drive strength
Select your clock sources for MCLK, SMCLK, and ACLK and do any source division that you need to do
Allow XT1, XT2 and DCO to stablize by checking for fault flags.
Your external crystal is 4Mhz - Are you wanting to use it as MCLK directly? Or is your angle to use it as a reference to the FLL for DCO, and use DCO for MCLK (to achieve a higher MCLK frequency)? The core volatage that you will need depends on whatever your MCLK frequency is, not your external crystal's frequency. So if you are wanting to use a MCLK rate of higher than 8Mhz you will need to consider stepping up PMMCOREV to 01.
For convenience, here is a reference for UCS registers from SLAU208M.
http://www.ti.com/lit/ug/slau208m/slau208m.pdf#page=172
Based on your OP, I think you should do the following if you want to use XT1 are your MCLK:
//1) Enable XT1 - XT1 will be off by default. You may not need to explicitly
// perform this step. According to pg. 162 in SLAU208M, XT1 will be
// enabled when you select it as the source for one of the clocks. But I
// like being explicit!
UCSCTL6 &= ~XT1OFF //XT1OFF= 0x0001u
//2) Clear the XT1DRIVE bits - it may not be necessary to clear these bits
// explicitly, but XT1's drive strength can be reduced to 0 w/ a 4MHz
// crystal. By default, this will be b11, full scale, which will consume
// more power, but result in a quicker settling time.
UCSCTL6 &= ~XT1DRIVE0; //XT1DRIVE0 = 0x0040u
UCSCTL6 &= ~XT1DRIVE1; //XT1DRIVE1 = 0x0080u
//3) Select XT1 as the clock source for XT1. UCSCTL4 defaults to 0x44 at
// power on - DCOCLKDIV (b100). SELM_XT1CLK = b000.
UCSCTL4 &= SELM__XT1CLK; //SELM__XT1CLK = 0x0000u
//4) Wait for XT1 to stabilize
do
{
//Explicitly clear the XT1 low and high frequency fault flasg, XT2 fault flag,
//and DCO fault flag. 0X0008u, 0x0002, 0x0004, 0x0001 respectively.
UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);
//Clear the oscillator fault interrupt flag in the special function interrupt
//flags register.
SFRIFG1 &= ~OFIFG; //0X0002U
} while (SFRIFG1&OFIFG); //Test to see if any oscillator fault flags are asserted.
I am using IAR systems, not sure if you are using CCS if those definitions will be named differently. I went ahead and typed out the hex for each of the operands.
On the msp4305438A you do not have to do anything with bypass.
Does that answer your question?
Also, in your OP you mention wanting to use XT1 as a reference for an FLL. That is accomplished using UCSCTL3. SELFREF is the field you want to set to b000 to use XT1,
Here's the definitions for the MSP4305438A header in IAR:
#define SELREF0 (0x0010u) /* FLL Reference Clock Select Bit : 0 */
#define SELREF1 (0x0020u) /* FLL Reference Clock Select Bit : 1 */
#define SELREF2 (0x0040u) /* FLL Reference Clock Select Bit : 2 */

Resources