Atom Pro IDE 8.0.1.8 bug list

Hi Nathan,

I have been having fun using the assembly level programming and working on the PS2 controller code. As you mentioned in another post, if I get this to work reasonably well you might convert it into a command. To make this easier I was wondering if you have some defined coding standards. In particular do you have a standard way you pass paramters between subroutines and registers you save and destroy and a standard way to setup a call frame.

Looking at what the C compiler generates, it looks like it passes the first three parameters in registers R0-R2. Any additional registers are stored on the stack and the caller is responsible for cleaning up the stack after the call. I know that ER7 is the stack pointer. It appears like the C compiler sets up ER6 as a stack frame pointer. They generally appear to setup the stack with code something like:

Mysub:
    push     er6
    mov.l    er7, er6
    sub.l     #<Local Size?, er7
    ...

    ; end of the function
    add.l    #<the size>,er7
    pop.l    er6
    rts

The reason I am looking at this is the current function I am updating uses temporary localized in scope variables. Probably the better way would be for me to define these on the stack local to the function, but so far I have done it the lazy way of defining the variables in basic and simply using them… Suggestions?

Kurt

I was trying to write a detailed description of how the stacks are used(ther eare two, basic code and asm code stacks) but I stepped away from my computer for a while and when I got back and finished the reply and hit submit everything disappeared. Joy.

So I’ll have to rewrite that reply eventually. For now I’ll try to give you a simple answer.

In your asm code you can do whatever you want to the asm stack(eg push and pop values). R7 will always point to the asm stack when entering user asm code. Don’t mess with E7 though because I use that to store the address of the basic stack. if you use normal push and pop asm commands you won’t mess with E7 but if you do a mov into ER7 you will trash my basic stack pointer.

I always hate when that happens. What usually nails me is my mice have two buttons on the side, one which is to go back to the previoius web site. More than once I have typed a lot, bumped my mouse which caused it to go back and I lost everything I typed! :angry:

Currently I do modify the stack to try to make room for temporary variables. For example, the beginning of one function looks lik:

[code].equ PS2IOC_BRETRYCNT, -12; er6-12
.equ PS2IOC_CBINT, -11 ; er6-11
.equ PS2IOC_CBOUTT, -10 ; er6-10
.equ PS2IOC_CBIN, -9 ; er6 - 9
.equ PS2IOC_PSZOUT, -8 ; er6 -8
.equ PS2IOC_PSZIN, -4 ; er6-4
; er6
; er6+4
; Registers changed:

PS2_INPUT_OUTPUT_CMD:
push.l er6 ; save away for use as stack frame pointer
mov.l er7, er6 ; Ok now ER6 will work as our stack frame.
sub.l #12, er7 ; leave room for our temporary variables.
push.l er4 ; save away a couple of registers we use
push.l er5
…[/code]
The ending looks like:

[code] ; cleanup the stack frame

pop.l	er5					; restore er5
pop.l	er4
add.l	#12, er7			; get back beyond or stack junk
pop		er6					; restore it back 

rts				

[/code]

To access one of the locals looks something like:

	mov.b	@(PS2IOC_CBINT, er6), r1l	; lets get our input counter

Would you suggest that I should shy away from using something like stack frame based variables and instead simply define globals?

Thanks
Kurt

P.S. - I tried using the assmbly level debugging. I moved all of the macro definitions into a secondary file that I did an include on and did not end up with a bunch of duplicate definition errors. However I then found it would be real nice if I could actually see what the content of the registers ER0-ER7 were.

Yes, I’ll have to add a register display window for asm level debugging, eventually.

I try to use only the regsiters and basic stack and I try to limit using the basic stack for anything but grabbing the basic arguments. Some time that may not be possible. In that case use a global variable but pass the global variable as an argument to the command(eg see the button command). This is only in cases where non-volatile data is needed. In very rare case(eg hardware commands like hservo and hserial) I define a buffer in the compiler specifically for those commands. If that becomes necessary I can add the capability to the ps2 command as well. I’d only do that if you were working on an interrupt driven version that ran in the back ground though.

When I get the chance to make that detailed write up I’ll explain how to define a basic command and how to access the basic stack values. there are several macros specifically designed for that but I don’t think I gave you those yet.

Note that ER0 to ER5 are free whenever you enter inline asm code. Trash them however you want. Just a reminder this is not the case with asm interrupts.

The compiler specifically requires you not mess with ER6 or ER7 other than using the push and pop commands and the basic stack macros I’ll give you latter. Otherwise as long as you pop everything off the stack you pushed on you don’t need to store a frame pointer for the stack, but it isn’t going to hurt if you continue you using it the way you have been, it’s just a waste of code is all. I hve never needed to use the asm stack as local variable storage in all the commands in the compiler. You have 24 bytes of local storage in the registers so it should be very rare that you need more.

Basic interrupts need ER6 to point to the token list and both interrupt types need ER7 to be pointing to the asm stack so don’t touch.

Hello. I am using the Basic Atom Pro 28. What a great device!

I use it to control a BlinkM, CMPS03, DS1631, IRCM, ISD5216, LC32A, LCD03, MD22, PCF8574, PCF8583, RLY08, SD21, SP03, SRF04, SRF08, uMP3 (and others designed and built by me) all in the same project! What a chip! I am using I2C “bit banging” code for all of these with clock-stretching support. If anyone wants any sample code, I’d be glad to send it to you. Just ask. I’m not sure where to post code…

I am a NOOB on this forum and this is my first post. If this subject has already been discussed, please point me that way and accept my apologies.

I am trying to switch to the new IDE 8.0.1.8. I am currently using IDE 8.0.1.7.

I am getting a linker error whenever I use the “read” command.
This command works fine with 8.0.1.7 even though the manual states that the Atom Pro 28 does not have EEPROM. It certainly does.

In my projects using 8.0.1.7, I am using the internal 4K EEPROM and it works fine, so I know the memory exists.

Here is the “read” command example from the manual:

Main
contents var byte
read 100,contents
End

Here is the linker error:

;ld.exe : Unsupported .stab relocation
;readtest.o(.text+0x30a): undefined reference to I2COUTFUNCCMD' ;ld.exe : Unsupported .stab relocation ;readtest.o(.text+0x310): undefined reference to I2COUTFUNCCMD’

If you comment out the “read” command it compiles, and links, fine.
This sample also compiles and links fine using 8.0.1.7.

Many thanks for any information.

-Bob

Looks liek a typo in my library file. All library functions should begin with an ‘_’, ie _I2COUTFUNCCMD. I’ll take a look at it and make sure it gets fixed in the next release which should be pretty soon. So fare I don’t have any other reports of major issues like this. You may want to try the readdm command instead to see if that works(eg readdm address,[data,data2,data3…etc]).

Thanks for the quick reply Nathan.

I tried using the readdm command, but it has the same linker error.

I am in no rush for the next version of the IDE, but I am willing to help test it when it is ready. I’ll watch the forum for any updates and try my projects again at that time.

Thanks for the great controller! (Basic Atom Pro 28)

-Bob

You should be able to use the i2cin and i2cout commands though. I used them a couple days ago on another project without any trouble. The onboard eeprom is connected to P33 and P34 but I can’t remember right now if the SCL is p33 or p34. If you can wait I’ll fix them this weekend. If not you should be able to try the i2c commands with both combinations of pins to find the right ones.

Happy New Year!

Hi Nathan.

I am only trying the IDE 8.0.1.8 because it’s there :slight_smile: 8.0.1.7 is working fine for my needs, so don’t rush anything on my account.

Thanks for the I2C EEPROM hint. In this case I need the speed of the internal EEPROM.

I use internal (fast) EEPROM for fast lookups of text constants to save code space. these text constants are in tight loops and need the speed.

I also use external (slow) I2C EEPROM for slow lookups for the same reason for text like banner screens, and other constant text, etc where speed is not an issue.

This is a great way to save code space as you only need a small lookup function to fetch the text, and the text can be loaded “offline” using a separate program so that it frees up that function in the main runtime app.

I pass the lookup function the access type (fast/slow) and an integer id and it loads the text into a common buffer. works great. I use this for text-driven speech, banner screens, status msgs, you name it.

I know this reply is wordy, but I figure letting the designer know how you use their product is usually a good plan :slight_smile:

-Bob

Well, using the read/write commands shouldn’t be any significantly faster than using the i2cin and i2cout commands. Read and write use the i2cin and i2cout functions internally to the hardcoded pins that the onboard 4kbyte eeprom is on.

If you came from the BasicAtom family(eg the PICmicro based modules) there the 256bytes of eeprom was faster than any i2c eeprom could be(a read could be done in about 10 machine level instructions).

However using tables(which are stored in flash program memory) would be siginificantly faster than any of the eeprom options on any of the modules but can’t be changed on the fly on the AtomPro modules) like eeprom can.

Fixed the define error. This fix will be in the next update.

Also the onboard eeprom on the modules uses P34 for SCL and P35 for SDA. So if you want to access the eeprom without using the read and write commands just use P34 and P35 in the i2c commands.

Also for thos eusing the AtomPro24 which doesn’t have an onboard eeprom you can use the read and write commands if you wire an external eeprom on P10 to SCL on the eeprom and P11 to SDA on the eeprom.

Looks like hservo is broken in this release. If you need hservo then un-install 1.8 and then re-install 1.7 until it can be resolved.

I am not using the i2cin/i2cout commands because they do not work with all of my devices, so I just bit bang it. I think it was related to slave clock-stretching it something. I will try all my devices again using the 8.0.1.8 i2c commands and provide feedback if you want.

Is there a way to access the pins P34 & P35 without using the i2c commands?
There seems to be no IN34 or IN35 commands, so my I2C routines have no way to access these pins. any ideas?

on a similar note, is there a way to pass the IN command a pin number from a variable? something like:

bPinSDA var byte
bPinSCL var byte
bPinSDA = P0
bPinSCL = P1
IN bPinSDA
IN bPinSCL

I use multiple I2C busses in my project and this would clean up some code.

thanks!
-Bob

The IN OUT and DIR are all variables already. They are aliases for the pin direction and state registers. I only derfine IN,OUT and DIR upto 31(0 to 31).

To access the higher pins you can do it directly through the PDR registers associated with those pins(see the hitachi hardware manual for details. For the I2C eeprom pins they are PDR7.bit5(p34) and PDR7.bit6(p35). You can read and write to these like variables(eg PDR7.bit5 = 0. If PDR7.bit5=0 then…) of course you need to set the direction of the pin.

To set the direction of a pin I recommand using the input and output commands because accessing the PCR register directly has a big gotcha. All PCR registers are write only so you have to remember the state of all pins. I use a shadow register(which you can’t access) internally to keep track of this but if you manual change any of the PCR registers my internal state will no longer be valid and you may have interesting problems.

great info! I’ll be sure to continue to use the input command to be safe.
I don’t think I’m explaining very well what I’m really looking to do. here is my working code:

cPIN_SCL_1 con P0 ; I2C bus #1 Serial CLock
cPIN_SDA_1 con P1 ; I2C bus #1 Serial DAta
cPIN_SCL_2 con P2 ; I2C bus #2 Serial CLock
cPIN_SDA_2 con P3 ; I2C bus #2 Serial DAta
cPIN_SCL_3 con P4 ; I2C bus #3 Serial CLock
cPIN_SDA_3 con P5 ; I2C bus #3 Serial DAta

cPIN_SCL_CMPS03 con P4 ; I2C bus Serial CLock
cPIN_SDA_CMPS03 con P5 ; I2C bus Serial DAta
cI2C_CMPS03 con 0xC0 ; CMPS03 digital compass
cCMPS03_REG_REVISION con 0x00

CMPS03GetVersion
gosub I2CRead [cPIN_SDA_CMPS03, cPIN_SCL_CMPS03, cI2C_CMPS03, cCMPS03_REG_REVISION, 1]
sMessage = "CMPS03 version: ", dec sBuffer (0), 0
gosub DisplayMessage [cTRUE]
return

bI2CPinSCL var byte ; I2C Serial CLock
bI2CPinSDA var byte ; I2C Serial DAta
bI2CControl var byte
wI2CAddress var word
wI2CReadCount var word
I2CRead [bI2CPinSDA, bI2CPinSCL, bI2CControl, wI2CAddress, wI2CReadCount]
bI2CReadAck var byte
; blah blah blah

input bI2CPinSCL
if (bI2CPinSCL = cPIN_SCL_1) then
    bI2CReadAck = IN0
elseif (bI2CPinSCL = cPIN_SCL_2)
    bI2CReadAck = IN2
elseif (bI2CPinSCL = cPIN_SCL_3)
    bI2CReadAck = IN4
endif

; blah blah blah
return

what I would really prefer:

I2CRead [bI2CPinSDA, bI2CPinSCL, bI2CControl, wI2CAddress, wI2CReadCount]
; blah blah blah

input bI2CPinSCL
bI2CReadAck = IN bI2CPinSCL

; blah blah blah
return

but I can find no way to pass a variable to the IN command and no other way to get the pin state other than using IN.
so I have to repeat this block of code
if (bI2CPinSCL = cPIN_SCL_1) then
bI2CReadAck = IN0
elseif (bI2CPinSCL = cPIN_SCL_2)
bI2CReadAck = IN2
elseif (bI2CPinSCL = cPIN_SCL_3)
bI2CReadAck = IN4
endif
every time I read the pins. costly in terms of code space (which I have 516 bytes left, so it’s tight).

thanks for any pointers you can provide.

-Bob

I can see maybe a couple ways of doing this. One might be to set a Mask and do a multiple pin input and then see if that is zero or not…

Example:
bI2CReadAck = ((INS & (1 << bI2CPinSCL)) <> 0)

You probably don’t need to compare for 0, you can can precompute the mask, you can use some of the other INx ones if your pin numbers are more limited. Note: I have not tried this…

You could do some of thie using the underlying H8 IO registers. For example to get the current state of BAP io pin 0, you find out by looking at the atom pro manual (Page 187) that this is on the underlying H8 IO pin P50. Assuming you have done an INPUT P0 earlier you can get the IO state of P50 from the IO Port 5. Which looking at the H83694 manual you will see that this has 3 IO registers of interest (PMR5, PCR5 and PDR5). We will assume that PMR5 is set properly to say that pin 0 is a general purpose IO pin. Likewise PCR5 is set properly to say that pin 0 is an INPUT pin. So then we know bit 0 of PDR5 will contain the current input state for the H8 IO pin P50 which is the BAPs IO pin P0.

There are many ways to capture this state. For example you could use inline assembly language. Note: I am typing this off the top of my head and have not compiled it or checked for errors. But something like:

mov.b @BI2CPINSCL, r1l ; get the SCL pin number xor.b r0l, r0l ; set r0l to zero bset r1l, r0l ; will set the r1l bit to 1 in r0l we have mask mov.b @PDR5, r1l ; R1l now has input for P50-P57 and.b r0l, r1l ; we issolated off our one bit xor.b r0l, r0l ; zero out r0l again add.b 0xff,r1l ; If our input bit is set carry will be set rotxr.b r0l ; if carry is set r0l will now be 1 mov.b r0l, @BI2CREADACK ; your variable is set.

This code could be simplified if you did not necessary want the bReadAck to be zero or one. you could remove the xor, add, rotxr and change the final mov.b to store r1l instead of r0l. Note: this code would only work for BAP IO pins 0-7. To do IO pins 8-15, you would need to use the underlying IO port 8 for those pins…

I am not sure if this helped or not, but good luck
Kurt

Send me a PM on this and I’ll try to come up with something. What you want is the ability to send a variable address(a pointer) as an argument in a gosub. I’ll have to try somethings and make sure it actually works before I give you anything. There is a pointer system in our language but it is under tested(very little testing) and completely undocumented.

Hi,

Is it possible that the #include doesn’t work in version 8.0.1.8?

I’ve got 2 separate files that I want to “joinâ€

Nevermind…

I found the problem. The build button saves the main file for me but NOT the separate file. So safe the separate file first silly! :blush:

Xan

Also if you create a project out of your disperate files when you click build it will save all the project file changes automatically.